ES Levels
By default, Ruby2JS targets ES2020, which is the minimum supported version. ES2020 includes let/const, arrow functions, template literals, classes, spread syntax, optional chaining (?.), and nullish coalescing (??).
By passing an eslevel option to the convert method, you can target a newer ECMAScript version. Every newer level enables older levels, so for example 2021 will enable ES2020 features plus ES2021-specific features.
Baseline Features (ES2015-ES2019)
The following features are always available since ES2020 is the minimum supported version:
"#{a}"`${a}`a = 1let a = 1A = 1const A = 1a, b = b, a[a, b] = [b, a]a, (foo, *bar) = xlet [a, [foo, ...bar]] = xdef f(a, (foo, *bar))function f(a, [foo, ...bar])def a(b=1)function a(b=1)def a(*b)function a(...b).each_valuefor (i of ...) {}a(*b)a(...b)"#{a}"\`${a}\`lambda {|x| x}(x) => {return x}proc {|x| x}(x) => {x}a {|x|}a((x) => {})class Person; endclass Person {}Class.new do; endclass {}(0...a).to_a[...Array(a).keys()](0..a).to_a[...Array(a+1).keys()](b..a).to_aArray.from({length: (a-b+1)}, (_, idx) => idx+b)hash => {a:, b:}let { a, b } = hash
Class support includes constructors, super, methods, class methods, instance methods, instance variables, class variables, getters, setters, attr_accessor, attr_reader, attr_writer, etc.
Additionally, the functions filter provides the following conversions:
Array(x)Array.from(x).inject(n) {}.reduce(() => {}, n)a[0..2] = va.splice(0, 3, ...v)a ** ba ** b.include?.includes.values()Object.values().entries()Object.entries().each_pair {}for (let [key, value] of Object.entries()) {}include MObject.defineProperties(..., Object.getOwnPropertyDescriptors(M)).merge{...a, ...b}.flatten.flat(Infinity).lstrip.trimEnd.rstrip.trimStarta.to_hObject.fromEntries(a)Hash[a]Object.fromEntries(a)a&.ba?.b.scanArray.from(str.matchAll(/.../g), s => s.slice(1))a.nil? ? b : aa ?? b
Async support:
async defasync functionasync lambdaasync =>async procasync =>async ->async =>foo bar, async do...endfoo(bar, async () => {})
Keyword arguments and optional keyword arguments are mapped to parameter destructuring.
Rest arguments can be used with keyword arguments and optional keyword arguments.
rescue without a variable maps to catch without a variable.
Classes defined with a method_missing method will emit a Proxy object
for each instance that will forward calls. Note that in order to forward
arguments, this proxy will return a function that will need to be called,
making it impossible to proxy attributes/getters. As a special accommodation,
if the method_missing method is defined to only accept a single parameter
it will be called with only the method name, and it is free to return
either values or functions.
ES2021 support
When option eslevel: 2021 is provided, the following additional
conversions are made:
x ||= 1x ||= 1x &&= 1x &&= 1x = y if x.nil?x ??= y1000000.0000011_000_000.000_001.gsub.replaceAll
The x = y if x.nil? pattern provides an idiomatic Ruby way to express
nullish assignment. This is useful when you want nullish semantics (only
assign if nil) rather than the falsy semantics of ||= (which also
triggers on false).
ES2022 support
@xthis.#x(unless theunderscored_privateoption is set totrue)@@xClassName.#xself.a = []static a = [](within a class)privatemethods after privateuse#prefix (e.g.,#helper())
Private method support allows you to use Ruby’s private keyword to mark methods as private:
class Calculator
def calculate(x)
helper(x) # Calls this.#helper(x)
end
private
def helper(x) # Becomes #helper(x)
x * 2
end
end
Both implicit and explicit self calls to private methods are correctly prefixed:
helper(x) # => this.#helper(x)
self.helper(x) # => this.#helper(x)
When underscored_private: true is set, private methods use _ prefix instead of #.
When the functions filter is enabled, the following additional conversions are
made:
x[-2]x.at(-2)x.lastx.at(-1)
ES2023 support
When option eslevel: 2023 is provided, the following additional
conversion is made by the functions filter:
.sort_by {}.toSorted()
Ruby’s sort_by method uses ES2023’s non-mutating toSorted():
# Ruby
people.sort_by { |p| p.age }
# JavaScript (ES2023)
people.toSorted((p_a, p_b) => p_a.age < p_b.age ? -1 : p_a.age > p_b.age ? 1 : 0)
For older ES levels, sort_by uses slice().sort() to avoid mutating the original array.
ES2024 support
When option eslevel: 2024 is provided, the following additional
conversion is made by the functions filter:
.group_by {}Object.groupBy()
Ruby’s group_by method maps directly to ES2024’s Object.groupBy():
# Ruby
people.group_by { |p| p.age }
# JavaScript (ES2024)
Object.groupBy(people, p => p.age)
For older ES levels, group_by uses a reduce() fallback to build the grouped object.
ES2025 support
When option eslevel: 2025 is provided, the following additional
conversion is made by the functions filter:
Regexp.escape()RegExp.escape()
Ruby’s Regexp.escape method maps directly to ES2025’s RegExp.escape():
# Ruby
Regexp.escape("hello.world")
# JavaScript (ES2025)
RegExp.escape("hello.world")