ruby2js 3.5.2 → 4.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +5 -665
- data/lib/ruby2js.rb +47 -13
- data/lib/ruby2js/converter.rb +9 -3
- data/lib/ruby2js/converter/args.rb +6 -1
- data/lib/ruby2js/converter/assign.rb +159 -0
- data/lib/ruby2js/converter/begin.rb +7 -2
- data/lib/ruby2js/converter/case.rb +7 -2
- data/lib/ruby2js/converter/class.rb +80 -21
- data/lib/ruby2js/converter/class2.rb +107 -33
- data/lib/ruby2js/converter/def.rb +7 -3
- data/lib/ruby2js/converter/dstr.rb +8 -3
- data/lib/ruby2js/converter/hash.rb +28 -6
- data/lib/ruby2js/converter/hide.rb +13 -0
- data/lib/ruby2js/converter/if.rb +10 -2
- data/lib/ruby2js/converter/import.rb +19 -4
- data/lib/ruby2js/converter/kwbegin.rb +9 -2
- data/lib/ruby2js/converter/literal.rb +14 -2
- data/lib/ruby2js/converter/logical.rb +1 -1
- data/lib/ruby2js/converter/module.rb +41 -4
- data/lib/ruby2js/converter/opasgn.rb +8 -0
- data/lib/ruby2js/converter/return.rb +2 -1
- data/lib/ruby2js/converter/send.rb +73 -8
- data/lib/ruby2js/converter/vasgn.rb +5 -0
- data/lib/ruby2js/converter/xstr.rb +2 -3
- data/lib/ruby2js/demo.rb +53 -0
- data/lib/ruby2js/es2022.rb +5 -0
- data/lib/ruby2js/es2022/strict.rb +3 -0
- data/lib/ruby2js/filter.rb +9 -1
- data/lib/ruby2js/filter/active_functions.rb +44 -0
- data/lib/ruby2js/filter/camelCase.rb +6 -3
- data/lib/ruby2js/filter/cjs.rb +2 -0
- data/lib/ruby2js/filter/esm.rb +118 -26
- data/lib/ruby2js/filter/functions.rb +104 -106
- data/lib/ruby2js/filter/{wunderbar.rb → jsx.rb} +29 -7
- data/lib/ruby2js/filter/node.rb +58 -14
- data/lib/ruby2js/filter/nokogiri.rb +12 -12
- data/lib/ruby2js/filter/react.rb +192 -57
- data/lib/ruby2js/filter/require.rb +102 -11
- data/lib/ruby2js/filter/return.rb +13 -1
- data/lib/ruby2js/filter/stimulus.rb +185 -0
- data/lib/ruby2js/jsx.rb +309 -0
- data/lib/ruby2js/namespace.rb +75 -0
- data/lib/ruby2js/rails.rb +15 -9
- data/lib/ruby2js/serializer.rb +3 -1
- data/lib/ruby2js/version.rb +3 -3
- data/ruby2js.gemspec +2 -2
- metadata +17 -9
- data/lib/ruby2js/filter/esm_migration.rb +0 -72
- data/lib/ruby2js/filter/fast-deep-equal.rb +0 -23
@@ -11,13 +11,27 @@ module Ruby2JS
|
|
11
11
|
# NOTE: class_extend is not generated by the parser, but instead produced
|
12
12
|
# when ++class is encountered; it signals that this construct is
|
13
13
|
# meant to extend an already existing JavaScrpt class.
|
14
|
+
#
|
15
|
+
# class_hash is an anonymous class as a value in a hash; the
|
16
|
+
# name has already been output so should be ignored other than
|
17
|
+
# in determining the namespace.
|
18
|
+
#
|
19
|
+
# class_module is a module that to be re-processed by this handler
|
20
|
+
# given the similarity between the two structures.
|
14
21
|
|
15
|
-
handle :class, :class_extend, :class_module do |name, inheritance, *body|
|
16
|
-
|
22
|
+
handle :class, :class_hash, :class_extend, :class_module do |name, inheritance, *body|
|
23
|
+
extend = @namespace.enter(name) unless @ast.type == :class_module
|
24
|
+
|
25
|
+
if !%i(class class_hash).include?(@ast.type) or extend
|
17
26
|
init = nil
|
18
27
|
else
|
19
|
-
if es2015
|
20
|
-
|
28
|
+
if es2015 and not extend
|
29
|
+
if @ast.type == :class_hash
|
30
|
+
parse @ast.updated(:class2, [nil, *@ast.children[1..-1]])
|
31
|
+
else
|
32
|
+
parse @ast.updated(:class2)
|
33
|
+
end
|
34
|
+
@namespace.leave unless @ast.type == :class_module
|
21
35
|
return
|
22
36
|
end
|
23
37
|
|
@@ -35,7 +49,7 @@ module Ruby2JS
|
|
35
49
|
end
|
36
50
|
|
37
51
|
body.compact!
|
38
|
-
visible =
|
52
|
+
visible = @namespace.getOwnProps
|
39
53
|
body.map! do |m|
|
40
54
|
if \
|
41
55
|
@ast.type == :class_module and m.type == :defs and
|
@@ -45,7 +59,7 @@ module Ruby2JS
|
|
45
59
|
end
|
46
60
|
|
47
61
|
node = if m.type == :def
|
48
|
-
if m.children.first == :initialize
|
62
|
+
if m.children.first == :initialize and !visible[:initialize]
|
49
63
|
# constructor: remove from body and overwrite init function
|
50
64
|
init = m
|
51
65
|
nil
|
@@ -54,17 +68,20 @@ module Ruby2JS
|
|
54
68
|
sym = :"#{m.children.first.to_s[0..-2]}"
|
55
69
|
s(:prop, s(:attr, name, :prototype), sym =>
|
56
70
|
{enumerable: s(:true), configurable: s(:true),
|
57
|
-
set: s(:
|
71
|
+
set: s(:defm, nil, *m.children[1..-1])})
|
58
72
|
else
|
59
|
-
visible[m.children[0]] = s(:self)
|
60
73
|
|
61
74
|
if not m.is_method?
|
75
|
+
visible[m.children[0]] = s(:self)
|
76
|
+
|
62
77
|
# property getter
|
63
78
|
s(:prop, s(:attr, name, :prototype), m.children.first =>
|
64
79
|
{enumerable: s(:true), configurable: s(:true),
|
65
|
-
get: s(:
|
80
|
+
get: s(:defm, nil, m.children[1],
|
66
81
|
m.updated(:autoreturn, m.children[2..-1]))})
|
67
82
|
else
|
83
|
+
visible[m.children[0]] = s(:autobind, s(:self))
|
84
|
+
|
68
85
|
# method: add to prototype
|
69
86
|
s(:method, s(:attr, name, :prototype),
|
70
87
|
:"#{m.children[0].to_s.chomp('!')}=",
|
@@ -90,13 +107,14 @@ module Ruby2JS
|
|
90
107
|
else
|
91
108
|
# class method definition: add to prototype
|
92
109
|
s(:prototype, s(:send, name, "#{m.children[1]}=",
|
93
|
-
s(:
|
110
|
+
s(:defm, nil, *m.children[2..-1])))
|
94
111
|
end
|
95
112
|
|
96
113
|
elsif m.type == :send and m.children.first == nil
|
97
114
|
if m.children[1] == :attr_accessor
|
98
115
|
m.children[2..-1].map do |child_sym|
|
99
116
|
var = child_sym.children.first
|
117
|
+
visible[var] = s(:self)
|
100
118
|
s(:prop, s(:attr, name, :prototype), var =>
|
101
119
|
{enumerable: s(:true), configurable: s(:true),
|
102
120
|
get: s(:block, s(:send, nil, :proc), s(:args),
|
@@ -107,6 +125,7 @@ module Ruby2JS
|
|
107
125
|
elsif m.children[1] == :attr_reader
|
108
126
|
m.children[2..-1].map do |child_sym|
|
109
127
|
var = child_sym.children.first
|
128
|
+
visible[var] = s(:self)
|
110
129
|
s(:prop, s(:attr, name, :prototype), var =>
|
111
130
|
{get: s(:block, s(:send, nil, :proc), s(:args),
|
112
131
|
s(:return, s(:ivar, :"@#{var}"))),
|
@@ -116,6 +135,7 @@ module Ruby2JS
|
|
116
135
|
elsif m.children[1] == :attr_writer
|
117
136
|
m.children[2..-1].map do |child_sym|
|
118
137
|
var = child_sym.children.first
|
138
|
+
visible[var] = s(:self)
|
119
139
|
s(:prop, s(:attr, name, :prototype), var =>
|
120
140
|
{set: s(:block, s(:send, nil, :proc), s(:args, s(:arg, var)),
|
121
141
|
s(:ivasgn, :"@#{var}", s(:lvar, var))),
|
@@ -125,9 +145,10 @@ module Ruby2JS
|
|
125
145
|
elsif m.children[1] == :include
|
126
146
|
s(:send, s(:block, s(:send, nil, :lambda), s(:args),
|
127
147
|
s(:begin, *m.children[2..-1].map {|modname|
|
128
|
-
|
129
|
-
|
130
|
-
|
148
|
+
@namespace.defineProps @namespace.find(modname)
|
149
|
+
s(:for, s(:lvasgn, :$_), modname,
|
150
|
+
s(:send, s(:attr, name, :prototype), :[]=,
|
151
|
+
s(:lvar, :$_), s(:send, modname, :[], s(:lvar, :$_))))
|
131
152
|
})), :[])
|
132
153
|
elsif [:private, :protected, :public].include? m.children[1]
|
133
154
|
raise Error.new("class #{m.children[1]} is not supported", @ast)
|
@@ -160,17 +181,23 @@ module Ruby2JS
|
|
160
181
|
s(:send, s(:attr, name, :prototype),
|
161
182
|
"#{m.children[0].children.first}=",
|
162
183
|
s(:attr, s(:attr, name, :prototype), m.children[1].children.first))
|
163
|
-
elsif m.type == :class
|
184
|
+
elsif m.type == :class or m.type == :module
|
164
185
|
innerclass_name = m.children.first
|
165
186
|
if innerclass_name.children.first
|
166
187
|
innerclass_name = innerclass_name.updated(nil,
|
167
|
-
[s(:attr, innerclass_name.children[0]
|
188
|
+
[s(:attr, name, innerclass_name.children[0].children.last),
|
168
189
|
innerclass_name.children[1]])
|
169
190
|
else
|
170
191
|
innerclass_name = innerclass_name.updated(nil,
|
171
192
|
[name, innerclass_name.children[1]])
|
172
193
|
end
|
173
194
|
m.updated(nil, [innerclass_name, *m.children[1..-1]])
|
195
|
+
elsif @ast.type == :class_module
|
196
|
+
m
|
197
|
+
elsif m.type == :defineProps
|
198
|
+
@namespace.defineProps m.children.first
|
199
|
+
visible.merge! m.children.first
|
200
|
+
nil
|
174
201
|
else
|
175
202
|
raise Error.new("class #{ m.type } not supported", @ast)
|
176
203
|
end
|
@@ -194,7 +221,7 @@ module Ruby2JS
|
|
194
221
|
# merge property definitions
|
195
222
|
combine_properties(body)
|
196
223
|
|
197
|
-
if inheritance
|
224
|
+
if inheritance and (@ast.type != :class_extend and !extend)
|
198
225
|
body.unshift s(:send, name, :prototype=,
|
199
226
|
s(:send, s(:const, nil, :Object), :create,
|
200
227
|
s(:attr, inheritance, :prototype))),
|
@@ -206,10 +233,14 @@ module Ruby2JS
|
|
206
233
|
methods = 0
|
207
234
|
start = 0
|
208
235
|
body.each do |node|
|
209
|
-
if
|
236
|
+
if (node.type == :method or (node.type == :prop and es2015)) and
|
210
237
|
node.children[0].type == :attr and
|
211
238
|
node.children[0].children[1] == :prototype
|
212
239
|
methods += 1
|
240
|
+
elsif node.type == :class and @ast.type == :class_module and es2015
|
241
|
+
methods += 1 if node.children.first.children.first == name
|
242
|
+
elsif node.type == :module and @ast.type == :class_module
|
243
|
+
methods += 1 if node.children.first.children.first == name
|
213
244
|
elsif methods == 0
|
214
245
|
start += 1
|
215
246
|
else
|
@@ -219,14 +250,22 @@ module Ruby2JS
|
|
219
250
|
|
220
251
|
# collapse sequence to a single assignment
|
221
252
|
if \
|
222
|
-
@ast.type
|
223
|
-
|
253
|
+
@ast.type == :class_module or methods > 1 or
|
254
|
+
body[start]&.type == :prop
|
224
255
|
then
|
225
256
|
pairs = body[start...start+methods].map do |node|
|
226
257
|
if node.type == :method
|
227
258
|
replacement = node.updated(:pair, [
|
228
259
|
s(:str, node.children[1].to_s.chomp('=')),
|
229
260
|
node.children[2]])
|
261
|
+
elsif node.type == :class and node.children.first.children.first == name
|
262
|
+
sym = node.children.first.children.last
|
263
|
+
replacement = s(:pair, s(:sym, sym),
|
264
|
+
s(:class_hash, s(:const, nil, sym), nil, node.children.last))
|
265
|
+
elsif node.type == :module and node.children.first.children.first == name
|
266
|
+
sym = node.children.first.children.last
|
267
|
+
replacement = s(:pair, s(:sym, sym),
|
268
|
+
s(:module_hash, s(:const, nil, sym), node.children.last))
|
230
269
|
else
|
231
270
|
replacement = node.children[1].map do |prop, descriptor|
|
232
271
|
node.updated(:pair, [s(:prop, prop), descriptor])
|
@@ -244,12 +283,30 @@ module Ruby2JS
|
|
244
283
|
end
|
245
284
|
|
246
285
|
if @ast.type == :class_module
|
286
|
+
start = 0 if methods == 0
|
287
|
+
if name
|
288
|
+
body[start...start+methods] =
|
289
|
+
s(:casgn, *name.children, s(:hash, *pairs.flatten))
|
290
|
+
else
|
291
|
+
body[start...start+methods] = s(:hash, *pairs.flatten)
|
292
|
+
end
|
293
|
+
elsif @ast.type == :class_extend or extend
|
247
294
|
body[start...start+methods] =
|
248
|
-
s(:
|
295
|
+
s(:assign, body[start].children.first, s(:hash, *pairs.flatten))
|
249
296
|
else
|
250
297
|
body[start...start+methods] =
|
251
298
|
s(:send, name, :prototype=, s(:hash, *pairs.flatten))
|
252
299
|
end
|
300
|
+
|
301
|
+
elsif (@ast.type == :class_extend or extend) and methods > 1
|
302
|
+
|
303
|
+
pairs = body[start...start+methods].map do |node|
|
304
|
+
node.updated(:pair, [
|
305
|
+
s(:sym, node.children[1].to_s[0..-2]), node.children[2]])
|
306
|
+
end
|
307
|
+
|
308
|
+
body[start...start+methods] =
|
309
|
+
s(:assign, body[start].children.first, s(:hash, *pairs))
|
253
310
|
end
|
254
311
|
end
|
255
312
|
|
@@ -258,7 +315,7 @@ module Ruby2JS
|
|
258
315
|
constructor = init.updated(:constructor, [name, *init.children[1..-1]])
|
259
316
|
@comments[constructor] = @comments[init] unless @comments[init].empty?
|
260
317
|
|
261
|
-
if @ast.type == :class_extend
|
318
|
+
if @ast.type == :class_extend or extend
|
262
319
|
if es2015
|
263
320
|
constructor = s(:masgn, s(:mlhs,
|
264
321
|
s(:attr, s(:casgn, *name.children, constructor), :prototype)),
|
@@ -285,6 +342,7 @@ module Ruby2JS
|
|
285
342
|
|
286
343
|
# add locally visible interfaces to rbstack. See send.rb, const.rb
|
287
344
|
@rbstack.push visible
|
345
|
+
@rbstack.last.merge!(@namespace.find(inheritance)) if inheritance
|
288
346
|
|
289
347
|
parse s(:begin, *body.compact), :statement
|
290
348
|
ensure
|
@@ -292,6 +350,7 @@ module Ruby2JS
|
|
292
350
|
@class_name = class_name
|
293
351
|
@class_parent = class_parent
|
294
352
|
@rbstack.pop
|
353
|
+
@namespace.leave unless @ast.type == :class_module
|
295
354
|
end
|
296
355
|
end
|
297
356
|
|
@@ -9,11 +9,24 @@ module Ruby2JS
|
|
9
9
|
# NOTE: this is the es2015 version of class
|
10
10
|
|
11
11
|
handle :class2 do |name, inheritance, *body|
|
12
|
-
|
12
|
+
body.compact!
|
13
|
+
while body.length == 1 and body.first.type == :begin
|
14
|
+
body = body.first.children
|
15
|
+
end
|
16
|
+
|
17
|
+
proxied = body.find do |node|
|
18
|
+
node.type == :def and node.children.first == :method_missing
|
19
|
+
end
|
20
|
+
|
21
|
+
if not name
|
22
|
+
put 'class'
|
23
|
+
elsif name.type == :const and name.children.first == nil
|
13
24
|
put 'class '
|
14
25
|
parse name
|
26
|
+
put '$' if proxied
|
15
27
|
else
|
16
28
|
parse name
|
29
|
+
put '$' if proxied
|
17
30
|
put ' = class'
|
18
31
|
end
|
19
32
|
|
@@ -24,15 +37,11 @@ module Ruby2JS
|
|
24
37
|
|
25
38
|
put " {"
|
26
39
|
|
27
|
-
body.compact!
|
28
|
-
while body.length == 1 and body.first.type == :begin
|
29
|
-
body = body.first.children
|
30
|
-
end
|
31
|
-
|
32
40
|
begin
|
33
41
|
class_name, @class_name = @class_name, name
|
34
42
|
class_parent, @class_parent = @class_parent, inheritance
|
35
|
-
@rbstack.push(
|
43
|
+
@rbstack.push(@namespace.getOwnProps)
|
44
|
+
@rbstack.last.merge!(@namespace.find(inheritance)) if inheritance
|
36
45
|
constructor = []
|
37
46
|
index = 0
|
38
47
|
|
@@ -40,10 +49,17 @@ module Ruby2JS
|
|
40
49
|
body.each do |m|
|
41
50
|
if m.type == :def
|
42
51
|
prop = m.children.first
|
43
|
-
if prop == :initialize
|
52
|
+
if prop == :initialize and !@rbstack.last[:initialize]
|
44
53
|
constructor = m.children[2..-1]
|
45
|
-
elsif
|
46
|
-
@rbstack.last[prop] = s(:self)
|
54
|
+
elsif prop.to_s.end_with? '='
|
55
|
+
@rbstack.last[prop.to_s[0..-2].to_sym] = s(:autobind, s(:self))
|
56
|
+
else
|
57
|
+
@rbstack.last[prop] = m.is_method? ? s(:autobind, s(:self)) : s(:self)
|
58
|
+
end
|
59
|
+
elsif m.type == :send and m.children[0..1] == [nil, :async]
|
60
|
+
if m.children[2].type == :def
|
61
|
+
prop = m.children[2].children.first
|
62
|
+
@rbstack.last[prop] = s(:autobind, s(:self))
|
47
63
|
end
|
48
64
|
end
|
49
65
|
end
|
@@ -64,21 +80,21 @@ module Ruby2JS
|
|
64
80
|
walk[child] if child.is_a? Parser::AST::Node
|
65
81
|
end
|
66
82
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
83
|
+
if ast.type == :send and ast.children.first == nil
|
84
|
+
if ast.children[1] == :attr_accessor
|
85
|
+
ast.children[2..-1].each_with_index do |child_sym, index2|
|
86
|
+
ivars << :"@#{child_sym.children.first}"
|
87
|
+
end
|
88
|
+
elsif ast.children[1] == :attr_reader
|
89
|
+
ast.children[2..-1].each_with_index do |child_sym, index2|
|
90
|
+
ivars << :"@#{child_sym.children.first}"
|
91
|
+
end
|
92
|
+
elsif ast.children[1] == :attr_writer
|
93
|
+
ast.children[2..-1].each_with_index do |child_sym, index2|
|
94
|
+
ivars << :"@#{child_sym.children.first}"
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
82
98
|
|
83
99
|
end
|
84
100
|
walk[@ast]
|
@@ -140,10 +156,10 @@ module Ruby2JS
|
|
140
156
|
end
|
141
157
|
end
|
142
158
|
|
143
|
-
if m.type == :def || m.type == :async
|
159
|
+
if m.type == :def || m.type == :defm || m.type == :async
|
144
160
|
@prop = m.children.first
|
145
161
|
|
146
|
-
if @prop == :initialize
|
162
|
+
if @prop == :initialize and !@rbstack.last[:initialize]
|
147
163
|
@prop = :constructor
|
148
164
|
|
149
165
|
if constructor == [] or constructor == [(:super)]
|
@@ -190,7 +206,7 @@ module Ruby2JS
|
|
190
206
|
@prop = "static #{m.children[1]}"
|
191
207
|
end
|
192
208
|
|
193
|
-
@prop.sub
|
209
|
+
@prop = @prop.sub('static', 'static async') if m.type == :asyncs
|
194
210
|
|
195
211
|
m = m.updated(:def, m.children[1..3])
|
196
212
|
begin
|
@@ -208,6 +224,7 @@ module Ruby2JS
|
|
208
224
|
m.children[2..-1].each_with_index do |child_sym, index2|
|
209
225
|
put @sep unless index2 == 0
|
210
226
|
var = child_sym.children.first
|
227
|
+
@rbstack.last[var] = s(:self)
|
211
228
|
put "get #{var}() {#{@nl}return this.#{p}#{var}#@nl}#@sep"
|
212
229
|
put "set #{var}(#{var}) {#{@nl}this.#{p}#{var} = #{var}#@nl}"
|
213
230
|
end
|
@@ -215,12 +232,14 @@ module Ruby2JS
|
|
215
232
|
m.children[2..-1].each_with_index do |child_sym, index2|
|
216
233
|
put @sep unless index2 == 0
|
217
234
|
var = child_sym.children.first
|
235
|
+
@rbstack.last[var] = s(:self)
|
218
236
|
put "get #{var}() {#{@nl}return this.#{p}#{var}#@nl}"
|
219
237
|
end
|
220
238
|
elsif m.children[1] == :attr_writer
|
221
239
|
m.children[2..-1].each_with_index do |child_sym, index2|
|
222
240
|
put @sep unless index2 == 0
|
223
241
|
var = child_sym.children.first
|
242
|
+
@rbstack.last[var] = s(:self)
|
224
243
|
put "set #{var}(#{var}) {#{@nl}this.#{p}#{var} = #{var}#@nl}"
|
225
244
|
end
|
226
245
|
elsif [:private, :protected, :public].include? m.children[1]
|
@@ -228,13 +247,27 @@ module Ruby2JS
|
|
228
247
|
else
|
229
248
|
if m.children[1] == :include
|
230
249
|
m = m.updated(:begin, m.children[2..-1].map {|mname|
|
231
|
-
|
232
|
-
s(:attr, name, :prototype), mname)
|
250
|
+
@namespace.defineProps @namespace.find(mname)
|
251
|
+
s(:assign, s(:attr, name, :prototype), mname)
|
252
|
+
})
|
233
253
|
end
|
234
254
|
|
235
255
|
skipped = true
|
236
256
|
end
|
237
257
|
|
258
|
+
elsif es2022 and \
|
259
|
+
m.type == :send and m.children.first.type == :self and \
|
260
|
+
m.children[1].to_s.end_with? '='
|
261
|
+
|
262
|
+
put 'static '
|
263
|
+
parse m.updated(:lvasgn, [m.children[1].to_s.sub('=', ''),
|
264
|
+
m.children[2]])
|
265
|
+
|
266
|
+
elsif m.type == :defineProps
|
267
|
+
skipped = true
|
268
|
+
@namespace.defineProps m.children.first
|
269
|
+
@rbstack.last.merge! m.children.first
|
270
|
+
|
238
271
|
else
|
239
272
|
if m.type == :cvasgn and !underscored_private
|
240
273
|
put 'static #$'; put m.children[0].to_s[2..-1]; put ' = '
|
@@ -246,7 +279,7 @@ module Ruby2JS
|
|
246
279
|
if m.type == :casgn and m.children[0] == nil
|
247
280
|
@rbstack.last[m.children[1]] = name
|
248
281
|
|
249
|
-
if
|
282
|
+
if es2022
|
250
283
|
put 'static '; put m.children[1].to_s; put ' = '
|
251
284
|
parse m.children[2]
|
252
285
|
skipped = false
|
@@ -257,7 +290,7 @@ module Ruby2JS
|
|
257
290
|
end
|
258
291
|
|
259
292
|
if skipped
|
260
|
-
post << [m, comments]
|
293
|
+
post << [m, comments] unless m.type == :defineProps
|
261
294
|
else
|
262
295
|
comments.reverse.each {|comment| insert location, comment}
|
263
296
|
end
|
@@ -294,15 +327,56 @@ module Ruby2JS
|
|
294
327
|
else
|
295
328
|
parse m.updated(:send, [@class_name, *m.children[1..-1]])
|
296
329
|
end
|
330
|
+
elsif m.type == :block and m.children.first.children.first == nil
|
331
|
+
# class method calls passing a block
|
332
|
+
parse s(:block, s(:send, name, *m.children.first.children[1..-1]),
|
333
|
+
*m.children[1..-1])
|
297
334
|
else
|
298
335
|
parse m, :statement
|
299
336
|
end
|
300
337
|
end
|
301
338
|
|
339
|
+
if proxied
|
340
|
+
put @sep
|
341
|
+
|
342
|
+
rename = name.updated(nil, [name.children.first, name.children.last.to_s + '$'])
|
343
|
+
|
344
|
+
if proxied.children[1].children.length == 1
|
345
|
+
# special case: if method_missing only has on argument, call it
|
346
|
+
# directly (i.e., don't pass arguments). This enables
|
347
|
+
# method_missing to return instance attributes (getters) as well
|
348
|
+
# as bound functions (methods).
|
349
|
+
forward = s(:send, s(:lvar, :obj), :method_missing, s(:lvar, :prop))
|
350
|
+
else
|
351
|
+
# normal case: return a function which, when called, will call
|
352
|
+
# method_missing with method name and arguments.
|
353
|
+
forward = s(:block, s(:send, nil, :proc), s(:args, s(:restarg, :args)),
|
354
|
+
s(:send, s(:lvar, :obj), :method_missing, s(:lvar, :prop),
|
355
|
+
s(:splat, s(:lvar, :args))))
|
356
|
+
end
|
357
|
+
|
358
|
+
proxy = s(:return, s(:send, s(:const, nil, :Proxy), :new,
|
359
|
+
s(:send, rename, :new, s(:splat, s(:lvar, :args))),
|
360
|
+
s(:hash, s(:pair, s(:sym, :get), s(:block, s(:send, nil, :proc),
|
361
|
+
s(:args, s(:arg, :obj), s(:arg, :prop)),
|
362
|
+
s(:if, s(:in?, s(:lvar, :prop), s(:lvar, :obj)),
|
363
|
+
s(:return, s(:send, s(:lvar, :obj), :[], s(:lvar, :prop))),
|
364
|
+
s(:return, forward))))))
|
365
|
+
)
|
366
|
+
|
367
|
+
if name.children.first == nil
|
368
|
+
proxy = s(:def, name.children.last, s(:args, s(:restarg, :args)), proxy)
|
369
|
+
else
|
370
|
+
proxy = s(:defs, *name.children, s(:args, s(:restarg, :args)), proxy)
|
371
|
+
end
|
372
|
+
|
373
|
+
parse proxy
|
374
|
+
end
|
375
|
+
|
302
376
|
ensure
|
303
377
|
@class_name = class_name
|
304
378
|
@class_parent = class_parent
|
305
|
-
@rbstack.pop
|
379
|
+
@namespace.defineProps @rbstack.pop
|
306
380
|
end
|
307
381
|
end
|
308
382
|
end
|