Skip to content

Commit afa4add

Browse files
committed
es2018 support
1 parent 11fb0ee commit afa4add

File tree

10 files changed

+90
-6
lines changed

10 files changed

+90
-6
lines changed

README.md

+9
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@ the script.
236236
* `.last` becomes `[*.length-1]`
237237
* `.last(n)` becomes `.slice(*.length-1, *.length)`
238238
* `.max` becomes `Math.max.apply(Math)`
239+
* `.merge` becomes `Object.assign({}, ...)`
239240
* `.merge!` becomes `Object.assign()`
240241
* `.min` becomes `Math.min.apply(Math)`
241242
* `.nil?` becomes `== null`
@@ -566,6 +567,14 @@ conversion is made by the `functions` filter:
566567

567568
* `.each_entry` becomes `Object.entries().forEach`
568569

570+
ES2018 support
571+
---
572+
573+
When option `eslevel: 2018` is provided, the following additional
574+
conversion is made by the `functions` filter:
575+
576+
* `.merge` becomes `{...a, ...b}`
577+
569578
Picking a Ruby to JS mapping tool
570579
---
571580

demo/ruby2js.rb

+4-3
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
# --es2015
1818
# --es2016
1919
# --es2017
20+
# --es2018
2021
# --strict
2122
# ---filter filter
2223
# -f filter
@@ -95,15 +96,15 @@
9596
_input type: 'checkbox', name: 'ast', id: 'ast', checked: !!@ast
9697
_label 'Show AST', for: 'ast'
9798

98-
_input type: 'checkbox', name: 'es2017', id: 'es2017', checked: !!@es2017
99-
_label 'ES2017', for: 'es2017'
99+
_input type: 'checkbox', name: 'es2018', id: 'es2018', checked: !!@es2018
100+
_label 'ES2018', for: 'es2018'
100101
end
101102

102103
if @ruby
103104
_div_? do
104105
raise $load_error if $load_error
105106

106-
options[:eslevel] = 2017 if @es2017
107+
options[:eslevel] = 2018 if @es2018
107108

108109
ruby = Ruby2JS.convert(@ruby, options)
109110

lib/ruby2js.rb

+4
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,10 @@ def es2017
8181
@options[:eslevel] >= 2017
8282
end
8383

84+
def es2018
85+
@options[:eslevel] >= 2018
86+
end
87+
8488
def process(node)
8589
ast, @ast = @ast, node
8690
replacement = super

lib/ruby2js/converter.rb

+4
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,10 @@ def es2017
138138
@eslevel >= 2017
139139
end
140140

141+
def es2018
142+
@eslevel >= 2018
143+
end
144+
141145
@@handlers = []
142146
def self.handle(*types, &block)
143147
types.each do |type|

lib/ruby2js/converter/hash.rb

+19-3
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,26 @@ class Converter
1212

1313
(singleton ? put('{') : puts('{'))
1414

15-
pairs.each_with_index do |node, index|
16-
raise Error.new("kwsplat", @ast) if node.type == :kwsplat
17-
15+
index = 0
16+
while pairs.length > 0
17+
node = pairs.shift
1818
(singleton ? put(', ') : put(",#@ws")) unless index == 0
19+
index += 1
20+
21+
if node.type == :kwsplat
22+
if es2018
23+
if node.children.first.type == :hash
24+
pairs.unshift *node.children.first.children
25+
index = 0
26+
else
27+
puts '...'; parse node.children.first
28+
end
29+
30+
next
31+
else
32+
raise Error.new("kwsplat", @ast)
33+
end
34+
end
1935

2036
if not @comments[node].empty?
2137
(puts ''; singleton = false) if singleton

lib/ruby2js/es2018.rb

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
require 'ruby2js'
2+
3+
if Ruby2JS.eslevel_default < 2018
4+
Ruby2JS.eslevel_default = 2018
5+
end

lib/ruby2js/es2018/strict.rb

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
require 'ruby2js/es2018'
2+
3+
Ruby2JS.strict_default = true

lib/ruby2js/filter/functions.rb

+21
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,27 @@ def on_send(node)
3535
elsif method == :keys and args.length == 0 and node.is_method?
3636
process S(:send, s(:const, nil, :Object), :keys, target)
3737

38+
elsif method == :merge
39+
args.unshift target
40+
41+
if es2015
42+
if es2018
43+
process S(:hash, *args.map {|arg| s(:kwsplat, arg)})
44+
else
45+
process S(:send, s(:const, nil, :Object), :assign, s(:hash),
46+
*args)
47+
end
48+
else
49+
copy = [s(:gvasgn, :$$, s(:hash))]
50+
51+
s(:send, s(:block, s(:send, nil, :lambda), s(:args),
52+
s(:begin, *copy, *args.map {|modname|
53+
s(:for, s(:lvasgn, :$_), modname,
54+
s(:send, s(:gvar, :$$), :[]=,
55+
s(:lvar, :$_), s(:send, modname, :[], s(:lvar, :$_))))
56+
}, s(:return, s(:gvar, :$$)))), :[])
57+
end
58+
3859
elsif method == :merge!
3960
if es2015
4061
process S(:send, s(:const, nil, :Object), :assign, target, *args)

spec/es2015_spec.rb

+4
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,10 @@ def to_js_fn(string)
179179
to_js( 'a=1; {a:a}' ).must_equal 'let a = 1; {a}'
180180
end
181181

182+
it "should handle merge" do
183+
to_js_fn( 'a.merge(b)' ).must_equal 'Object.assign({}, a, b)'
184+
end
185+
182186
it "should handle merge!" do
183187
to_js_fn( 'a.merge!(b)' ).must_equal 'Object.assign(a, b)'
184188
end

spec/es2018_spec.rb

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
gem 'minitest'
2+
require 'minitest/autorun'
3+
4+
describe "ES2018 support" do
5+
6+
def to_js_fn(string)
7+
Ruby2JS.convert(string, eslevel: 2018,
8+
filters: [Ruby2JS::Filter::Functions]).to_s
9+
end
10+
11+
describe :Hash_Spread do
12+
it "should convert merge to Object spread" do
13+
to_js_fn( 'a.merge(b)' ).must_equal '{...a, ...b}'
14+
to_js_fn( 'a.merge(b: 1)' ).must_equal '{...a, b: 1}'
15+
end
16+
end
17+
end

0 commit comments

Comments
 (0)