ruby2js 3.1.1 → 3.3.2

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.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +52 -11
  3. data/lib/ruby2js.rb +14 -2
  4. data/lib/ruby2js/converter.rb +11 -3
  5. data/lib/ruby2js/converter/args.rb +1 -1
  6. data/lib/ruby2js/converter/block.rb +2 -2
  7. data/lib/ruby2js/converter/class.rb +4 -3
  8. data/lib/ruby2js/converter/class2.rb +38 -9
  9. data/lib/ruby2js/converter/cvar.rb +1 -1
  10. data/lib/ruby2js/converter/cvasgn.rb +1 -1
  11. data/lib/ruby2js/converter/def.rb +2 -2
  12. data/lib/ruby2js/converter/for.rb +7 -0
  13. data/lib/ruby2js/converter/hash.rb +3 -3
  14. data/lib/ruby2js/converter/if.rb +13 -2
  15. data/lib/ruby2js/converter/import.rb +38 -0
  16. data/lib/ruby2js/converter/logical.rb +46 -1
  17. data/lib/ruby2js/converter/opasgn.rb +5 -2
  18. data/lib/ruby2js/converter/regexp.rb +27 -2
  19. data/lib/ruby2js/converter/return.rb +1 -1
  20. data/lib/ruby2js/converter/send.rb +53 -27
  21. data/lib/ruby2js/converter/super.rb +15 -9
  22. data/lib/ruby2js/converter/xnode.rb +89 -0
  23. data/lib/ruby2js/es2021.rb +5 -0
  24. data/lib/ruby2js/es2021/strict.rb +3 -0
  25. data/lib/ruby2js/filter/cjs.rb +2 -2
  26. data/lib/ruby2js/filter/esm.rb +72 -0
  27. data/lib/ruby2js/filter/functions.rb +191 -41
  28. data/lib/ruby2js/filter/matchAll.rb +49 -0
  29. data/lib/ruby2js/filter/node.rb +18 -10
  30. data/lib/ruby2js/filter/nokogiri.rb +13 -13
  31. data/lib/ruby2js/filter/react.rb +190 -30
  32. data/lib/ruby2js/filter/require.rb +1 -4
  33. data/lib/ruby2js/filter/rubyjs.rb +4 -4
  34. data/lib/ruby2js/filter/vue.rb +40 -15
  35. data/lib/ruby2js/filter/wunderbar.rb +63 -0
  36. data/lib/ruby2js/serializer.rb +25 -11
  37. data/lib/ruby2js/version.rb +2 -2
  38. data/ruby2js.gemspec +2 -11
  39. metadata +24 -4
@@ -0,0 +1,49 @@
1
+ require 'ruby2js'
2
+
3
+ module Ruby2JS
4
+ module Filter
5
+ module MatchAll
6
+ include SEXP
7
+
8
+ # ensure matchAll is before Functions in the filter list
9
+ def self.reorder(filters)
10
+ if \
11
+ defined? Ruby2JS::Filter::Functions and
12
+ filters.include? Ruby2JS::Filter::Functions
13
+ then
14
+ filters = filters.dup
15
+ matchAll = filters.delete(Ruby2JS::Filter::MatchAll)
16
+ filters.insert filters.index(Ruby2JS::Filter::Functions), matchAll
17
+ else
18
+ filters
19
+ end
20
+ end
21
+
22
+ def on_block(node)
23
+ return super if es2020
24
+
25
+ # only process each/forEach blocks
26
+ call = node.children.first
27
+ return super unless
28
+ [:each, :forEach].include? call.children[1] and
29
+ call.children.first.type == :send and
30
+ node.children[1].children.length == 1
31
+
32
+ # only process matchAll requests with simple expressions
33
+ call = call.children.first
34
+ return super unless
35
+ call.children[1] == :matchAll and
36
+ call.children[2].type == :send and
37
+ call.children[2].children.first == nil and
38
+ call.children[2].children.length == 2
39
+
40
+ process s(:while,
41
+ s(:lvasgn, node.children[1].children[0].children[0],
42
+ s(:send, call.children[2], :exec, call.children.first)),
43
+ node.children[2])
44
+ end
45
+ end
46
+
47
+ DEFAULTS.push MatchAll
48
+ end
49
+ end
@@ -56,7 +56,7 @@ module Ruby2JS
56
56
  s(:hash, s(:pair, s(:sym, :stdio), s(:str, 'inherit'))))
57
57
  end
58
58
 
59
- elsif
59
+ elsif \
60
60
  method == :require and args.length == 1 and
61
61
  args.first.type == :str and
62
62
  %w(fileutils tmpdir).include? args.first.children.first
@@ -67,7 +67,7 @@ module Ruby2JS
67
67
  super
68
68
  end
69
69
 
70
- elsif
70
+ elsif \
71
71
  [:File, :IO].include? target.children.last and
72
72
  target.type == :const and target.children.first == nil
73
73
  then
@@ -99,7 +99,7 @@ module Ruby2JS
99
99
  @node_setup << :fs
100
100
  S(:send, s(:attr, nil, :fs), :renameSync, *process_all(args))
101
101
 
102
- elsif
102
+ elsif \
103
103
  [:chmod, :lchmod].include? method and
104
104
  args.length > 1 and args.first.type == :int
105
105
  then
@@ -110,7 +110,7 @@ module Ruby2JS
110
110
  s(:octal, *args.first.children))
111
111
  })
112
112
 
113
- elsif
113
+ elsif \
114
114
  [:chown, :lchown].include? method and args.length > 2 and
115
115
  args[0].type == :int and args[1].type == :int
116
116
  then
@@ -148,7 +148,7 @@ module Ruby2JS
148
148
  super
149
149
  end
150
150
 
151
- elsif
151
+ elsif \
152
152
  target.children.last == :FileUtils and
153
153
  target.type == :const and target.children.first == nil
154
154
  then
@@ -201,7 +201,7 @@ module Ruby2JS
201
201
  s(:send, s(:attr, nil, :fs), :unlinkSync, process(file))
202
202
  })
203
203
 
204
- elsif
204
+ elsif \
205
205
  method == :chmod and args.length == 2 and args.first.type == :int
206
206
  then
207
207
  @node_setup << :fs
@@ -211,7 +211,7 @@ module Ruby2JS
211
211
  s(:octal, *args.first.children))
212
212
  })
213
213
 
214
- elsif
214
+ elsif \
215
215
  method == :chown and args.length == 3 and
216
216
  args[0].type == :int and args[1].type == :int
217
217
  then
@@ -233,7 +233,7 @@ module Ruby2JS
233
233
  super
234
234
  end
235
235
 
236
- elsif
236
+ elsif \
237
237
  target.type == :const and target.children.first == nil and
238
238
  target.children.last == :Dir
239
239
  then
@@ -274,7 +274,7 @@ module Ruby2JS
274
274
  call = node.children.first
275
275
  target, method, *args = call.children
276
276
 
277
- if
277
+ if \
278
278
  method == :chdir and args.length == 1 and
279
279
  target.children.last == :Dir and
280
280
  target.type == :const and target.children.first == nil
@@ -324,7 +324,15 @@ module Ruby2JS
324
324
  children = node.children.dup
325
325
  command = children.shift
326
326
  while children.length > 0
327
- command = s(:send, accumulator, :+, children.shift)
327
+ child = children.shift
328
+ if \
329
+ child.type == :begin and child.children.length == 1 and
330
+ child.children.first.type == :send and
331
+ child.children.first.children.first == nil
332
+ then
333
+ child = child.children.first
334
+ end
335
+ command = s(:send, command, :+, child)
328
336
  end
329
337
 
330
338
  s(:send, s(:attr, nil, :child_process), :execSync, command,
@@ -36,7 +36,7 @@ module Ruby2JS
36
36
  return super if excluded?(method)
37
37
 
38
38
  if target == nil
39
- if
39
+ if \
40
40
  method == :require and args.length == 1 and
41
41
  args.first.type == :str and
42
42
  %w(nokogiri nokogumbo).include? args.first.children.first
@@ -47,7 +47,7 @@ module Ruby2JS
47
47
  super
48
48
  end
49
49
 
50
- elsif
50
+ elsif \
51
51
  [:HTML, :HTML5].include? method and
52
52
  target == s(:const, nil, :Nokogiri)
53
53
  then
@@ -55,7 +55,7 @@ module Ruby2JS
55
55
  S(:attr, s(:attr, s(:send, s(:const, nil, :JSDOM), :new,
56
56
  *process_all(args)), :window), :document)
57
57
 
58
- elsif
58
+ elsif \
59
59
  method == :parse and
60
60
  target.type == :const and
61
61
  target.children.first == s(:const, nil, :Nokogiri) and
@@ -65,13 +65,13 @@ module Ruby2JS
65
65
  S(:attr, s(:attr, s(:send, s(:const, nil, :JSDOM), :new,
66
66
  *process_all(args)), :window), :document)
67
67
 
68
- elsif
68
+ elsif \
69
69
  method == :at and
70
70
  args.length == 1 and args.first.type == :str
71
71
  then
72
72
  S(:send, target, :querySelector, process(args.first))
73
73
 
74
- elsif
74
+ elsif \
75
75
  method == :search and
76
76
  args.length == 1 and args.first.type == :str
77
77
  then
@@ -98,25 +98,25 @@ module Ruby2JS
98
98
  elsif method === :to_html and args.length == 0
99
99
  S(:attr, target, :outerHTML)
100
100
 
101
- elsif
101
+ elsif \
102
102
  [:attr, :get_attribute].include? method and
103
103
  args.length == 1 and args.first.type == :str
104
104
  then
105
105
  S(:send, target, :getAttribute, process(args.first))
106
106
 
107
- elsif
107
+ elsif \
108
108
  [:key?, :has_attribute].include? method and
109
109
  args.length == 1 and args.first.type == :str
110
110
  then
111
111
  S(:send, target, :hasAttribute, process(args.first))
112
112
 
113
- elsif
113
+ elsif \
114
114
  method == :set_attribute and
115
115
  args.length == 2 and args.first.type == :str
116
116
  then
117
117
  S(:send, target, :setAttribute, *process_all(args))
118
118
 
119
- elsif
119
+ elsif \
120
120
  method == :attribute and
121
121
  args.length == 1 and args.first.type == :str
122
122
  then
@@ -128,7 +128,7 @@ module Ruby2JS
128
128
  elsif method == :attribute_nodes and args.length == 0
129
129
  S(:attr, target, :attributes)
130
130
 
131
- elsif
131
+ elsif \
132
132
  method == :new and args.length == 2 and
133
133
  target == s(:const, s(:const, s(:const, nil, :Nokogiri), :XML), :Node)
134
134
  then
@@ -172,14 +172,14 @@ module Ruby2JS
172
172
  elsif method == :add_child and args.length == 1
173
173
  S(:send, target, :appendChild, process(args.first))
174
174
 
175
- elsif
175
+ elsif \
176
176
  [:add_next_sibling, :next=, :after].include? method and
177
177
  args.length == 1
178
178
  then
179
179
  S(:send, s(:attr, target, :parentNode), :insertBefore,
180
180
  process(args.first), s(:attr, target, :nextSibling))
181
181
 
182
- elsif
182
+ elsif \
183
183
  [:add_previous_sibling, :previous=, :before].include? method and
184
184
  args.length == 1
185
185
  then
@@ -199,7 +199,7 @@ module Ruby2JS
199
199
  elsif method == :previous_element and args.length == 0
200
200
  S(:attr, target, :previousElement)
201
201
 
202
- elsif
202
+ elsif \
203
203
  [:previous, :previous_sibling].include? method and args.length == 0
204
204
  then
205
205
  S(:attr, target, :previousSibling)
@@ -68,12 +68,31 @@ module Ruby2JS
68
68
  @reactApply = nil
69
69
  @reactBlock = nil
70
70
  @reactClass = nil
71
+ @react_props = []
72
+ @react_methods = []
73
+ @react_filter_functions = false
74
+ @jsx = false
71
75
  super
72
76
  end
73
77
 
74
78
  def options=(options)
75
79
  super
76
80
  @react = true if options[:react]
81
+ filters = options[:filters] || Filter::DEFAULTS
82
+
83
+ if \
84
+ defined? Ruby2JS::Filter::Functions and
85
+ filters.include? Ruby2JS::Filter::Functions
86
+ then
87
+ @react_filter_functions = true
88
+ end
89
+
90
+ if \
91
+ defined? Ruby2JS::Filter::Wunderbar and
92
+ filters.include? Ruby2JS::Filter::Wunderbar
93
+ then
94
+ @jsx = true
95
+ end
77
96
  end
78
97
 
79
98
  # Example conversion
@@ -85,7 +104,9 @@ module Ruby2JS
85
104
  def on_class(node)
86
105
  cname, inheritance, *body = node.children
87
106
  return super unless cname.children.first == nil
88
- return super unless inheritance == s(:const, nil, :React)
107
+ return super unless inheritance == s(:const, nil, :React) or
108
+ inheritance == s(:const, nil, :Vue) or
109
+ inheritance == s(:send, s(:const, nil, :React), :Component)
89
110
 
90
111
  # traverse down to actual list of class statements
91
112
  if body.length == 1
@@ -106,18 +127,25 @@ module Ruby2JS
106
127
  react, @react = @react, true
107
128
  reactClass, @reactClass = @reactClass, true
108
129
 
109
- # automatically capture the displayName for the class
110
- pairs = [s(:pair, s(:sym, :displayName),
111
- s(:str, cname.children.last.to_s))]
130
+ pairs = []
131
+
132
+ unless es2015
133
+ # automatically capture the displayName for the class
134
+ pairs << s(:pair, s(:sym, :displayName),
135
+ s(:str, cname.children.last.to_s))
136
+ end
112
137
 
113
138
  # collect static properties/functions
114
139
  statics = []
115
140
  body.select {|child| child.type == :defs}.each do |child|
116
141
  _parent, mname, args, *block = child.children
117
- if child.is_method?
142
+ if es2015
143
+ block = [s(:autoreturn, *block)] unless child.is_method?
144
+ pairs << s(:defs, s(:self), mname, args, *block)
145
+ elsif child.is_method?
118
146
  statics << s(:pair, s(:sym, mname), process(child.updated(:block,
119
147
  [s(:send, nil, :proc), args, s(:autoreturn, *block)])))
120
- elsif
148
+ elsif \
121
149
  block.length == 1 and
122
150
  Converter::EXPRESSIONS.include? block.first.type
123
151
  then
@@ -128,6 +156,25 @@ module Ruby2JS
128
156
  end
129
157
  end
130
158
 
159
+ # collect instance methods (including getters and setters)
160
+ @react_props = []
161
+ @react_methods = []
162
+ body.each do |statement|
163
+ if statement.type == :def
164
+ method = statement.children.first
165
+ unless method == :initialize
166
+ if method.to_s.end_with? '='
167
+ method = method.to_s[0..-2].to_sym
168
+ @react_props << method unless @react_props.include? method
169
+ elsif statement.is_method?
170
+ @react_methods << method unless @react_methods.include? method
171
+ else
172
+ @react_props << method unless @react_props.include? method
173
+ end
174
+ end
175
+ end
176
+ end
177
+
131
178
  # append statics (if any)
132
179
  unless statics.empty?
133
180
  pairs << s(:pair, s(:sym, :statics), s(:hash, *statics))
@@ -135,7 +182,8 @@ module Ruby2JS
135
182
 
136
183
  # create a default getInitialState method if there is no such method
137
184
  # and there are references to instance variables.
138
- if
185
+ if \
186
+ not es2015 and
139
187
  not body.any? do |child|
140
188
  child.type == :def and
141
189
  [:getInitialState, :initialize].include? child.children.first
@@ -162,7 +210,7 @@ module Ruby2JS
162
210
  (@reactIvars[:pre] + @reactIvars[:post]).uniq
163
211
 
164
212
  if mname == :initialize
165
- mname = :getInitialState
213
+ mname = es2015 ? :initialize : :getInitialState
166
214
 
167
215
  # extract real list of statements
168
216
  if block.length == 1
@@ -193,7 +241,9 @@ module Ruby2JS
193
241
  anode.children.first.to_s[1..-1]), anode.children.last)})
194
242
 
195
243
  # modify block to build and/or return state
196
- if block.empty?
244
+ if mname == :initialize
245
+ block.unshift(s(:send, s(:self), :state=, state))
246
+ elsif block.empty?
197
247
  block = [s(:return, state)]
198
248
  else
199
249
  block.unshift(s(:send, s(:self), :state=, state))
@@ -201,13 +251,30 @@ module Ruby2JS
201
251
  end
202
252
 
203
253
  elsif mname == :render
204
- if
205
- block.length != 1 or not block.last or
254
+ if \
255
+ block.length != 1 or not block.last or
206
256
  not [:send, :block].include? block.last.type
207
257
  then
208
- # wrap multi-line blocks with a 'span' element
209
- block = [s(:return,
210
- s(:block, s(:send, nil, :_span), s(:args), *block))]
258
+ if @jsx
259
+ while block.length == 1 and block.first.type == :begin
260
+ block = block.first.children.dup
261
+ end
262
+
263
+ # gather non-element emitting statements in the front
264
+ prolog = []
265
+ while not block.empty? and
266
+ react_wunderbar_free([block.first]) do
267
+ prolog << process(block.shift)
268
+ end
269
+
270
+ # wrap multi-line blocks with an empty element
271
+ block = [*prolog, s(:return,
272
+ s(:xnode, '', *process_all(block)))]
273
+ else
274
+ # wrap multi-line blocks with a 'span' element
275
+ block = [s(:return,
276
+ s(:block, s(:send, nil, :_span), s(:args), *block))]
277
+ end
211
278
  end
212
279
 
213
280
  elsif mname == :componentWillReceiveProps
@@ -227,12 +294,17 @@ module Ruby2JS
227
294
 
228
295
  # add method to class
229
296
  type = (child.is_method? ? :begin : :autoreturn)
297
+ type = :begin if mname == :initialize
230
298
  if block.length == 1 and Parser::AST::Node === block.first
231
299
  type = :begin if block.first.type == :return
232
300
  end
233
301
 
234
- pairs << s(:pair, s(:sym, mname), child.updated(:block,
235
- [s(:send, nil, :proc), args, process(s(type, *block))]))
302
+ if es2015
303
+ pairs << s(:def, mname, args, process(s(type, *block)))
304
+ else
305
+ pairs << s(:pair, s(:sym, mname), child.updated(:block,
306
+ [s(:send, nil, :proc), args, process(s(type, *block))]))
307
+ end
236
308
 
237
309
  # retain comment
238
310
  unless @comments[child].empty?
@@ -245,18 +317,61 @@ module Ruby2JS
245
317
  @reactMethod = nil
246
318
  end
247
319
 
248
- # emit a createClass statement
249
- node.updated(:casgn, [nil, cname.children.last,
250
- s(:send, inheritance, :createClass, s(:hash, *pairs))])
320
+ if es2015
321
+ # emit a class that extends React.Component
322
+ node.updated(:class, [s(:const, nil, cname.children.last),
323
+ s(:attr, s(:const, nil, :React), :Component), *pairs])
324
+ else
325
+ # emit a createClass statement
326
+ node.updated(:casgn, [nil, cname.children.last,
327
+ s(:send, s(:const, nil, :React), :createClass, s(:hash, *pairs))])
328
+ end
251
329
  end
252
330
 
253
331
  def on_send(node)
332
+ # convert Vue.utile.defineReactive to class fields or assignments
333
+ if node.children.first == s(:send, s(:const, nil, :Vue), :util)
334
+ if node.children[1] == :defineReactive
335
+ if node.children[2].type == :cvar
336
+ return process s(:cvasgn, node.children[2].children.first,
337
+ node.children[3])
338
+ elsif node.children[2].type == :send
339
+ assign = node.children[2]
340
+ return assign.updated(nil, [assign.children[0],
341
+ assign.children[1].to_s + '=', node.children[3]])
342
+ end
343
+ end
344
+ end
345
+
346
+ # calls to methods (including getters) defined in this class
347
+ if node.children[0]==nil and Symbol === node.children[1]
348
+ if node.is_method?
349
+ if @react_methods.include? node.children[1]
350
+ # calls to methods defined in this class
351
+ return node.updated nil, [s(:self), node.children[1],
352
+ *process_all(node.children[2..-1])]
353
+ end
354
+ else
355
+ if @react_props.include? node.children[1]
356
+ # access to properties defined in this class
357
+ return node.updated nil, [s(:self), node.children[1],
358
+ *process_all(node.children[2..-1])]
359
+ end
360
+ end
361
+ end
362
+
363
+ if node.children.first == s(:const, nil, :Vue)
364
+ node = node.updated(nil, [s(:const, nil, :React),
365
+ *node.children[1..-1]])
366
+ end
367
+
254
368
  if not @react
255
369
  # enable React filtering within React class method calls or
256
370
  # React component calls
257
- if
371
+ if \
258
372
  node.children.first == s(:const, nil, :React)
259
373
  then
374
+
260
375
  begin
261
376
  react, @react = @react, true
262
377
  return on_send(node)
@@ -278,7 +393,7 @@ module Ruby2JS
278
393
  process(node.children[2])
279
394
  end
280
395
 
281
- elsif
396
+ elsif \
282
397
  @reactApply and node.children[1] == :createElement and
283
398
  node.children[0] == s(:const, nil, :React)
284
399
  then
@@ -286,7 +401,7 @@ module Ruby2JS
286
401
  s(:send, s(:gvar, :$_), :push, s(:send, *node.children[0..1],
287
402
  *process_all(node.children[2..-1])))
288
403
 
289
- elsif node.children[0] == nil and node.children[1] =~ /^_\w/
404
+ elsif !@jsx and node.children[0] == nil and node.children[1] =~ /^_\w/
290
405
  # map method calls starting with an underscore to React calls
291
406
  # to create an element.
292
407
  #
@@ -344,7 +459,7 @@ module Ruby2JS
344
459
  expr = expr.children.first
345
460
  end
346
461
 
347
- if
462
+ if \
348
463
  expr.type == :if and expr.children[1] and
349
464
  expr.children[1].type == :str
350
465
  then
@@ -468,6 +583,8 @@ module Ruby2JS
468
583
  # explicit call to React.createElement
469
584
  next true if arg.children[1] == :createElement and
470
585
  arg.children[0] == s(:const, nil, :React)
586
+ next true if arg.children[1] == :createElement and
587
+ arg.children[0] == s(:const, nil, :Vue)
471
588
 
472
589
  # wunderbar style call
473
590
  arg = arg.children.first if arg.type == :block
@@ -669,7 +786,7 @@ module Ruby2JS
669
786
  super
670
787
  end
671
788
 
672
- elsif
789
+ elsif \
673
790
  node.children[0] and node.children[0].type == :self and
674
791
  node.children.length == 2 and
675
792
  node.children[1] == :componentWillReceiveProps
@@ -686,7 +803,7 @@ module Ruby2JS
686
803
  if not @react
687
804
  # enable React filtering within React class method calls or
688
805
  # React component calls
689
- if
806
+ if \
690
807
  node.children.first == s(:const, nil, :React)
691
808
  then
692
809
  begin
@@ -713,7 +830,7 @@ module Ruby2JS
713
830
  #
714
831
  # Base Ruby2JS processing will convert the 'splat' to 'apply'
715
832
  child = node.children.first
716
- if
833
+ if \
717
834
  child.children[1] == :createElement and
718
835
  child.children[0] == s(:const, nil, :React)
719
836
  then
@@ -743,7 +860,7 @@ module Ruby2JS
743
860
  end
744
861
 
745
862
  # wunderbar style calls
746
- if child.children[0] == nil and child.children[1] =~ /^_\w/
863
+ if !@jsx and child.children[0] == nil and child.children[1] =~ /^_\w/
747
864
  if node.children[1].children.empty?
748
865
  # append block as a standalone proc
749
866
  block = s(:block, s(:send, nil, :proc), s(:args),
@@ -875,6 +992,49 @@ module Ruby2JS
875
992
  s(:attr, @reactProps, node.children.first.to_s[2..-1])
876
993
  end
877
994
 
995
+ # is this a "wunderbar" style call or createElement?
996
+ def react_element?(node)
997
+ return false unless node
998
+
999
+ forEach = [:forEach]
1000
+ forEach << :each if @react_filter_functions
1001
+
1002
+ return true if node.type == :block and
1003
+ forEach.include? node.children.first.children.last and
1004
+ react_element?(node.children.last)
1005
+
1006
+ # explicit call to React.createElement
1007
+ return true if node.children[1] == :createElement and
1008
+ node.children[0] == s(:const, nil, :React)
1009
+
1010
+ # explicit call to Vue.createElement
1011
+ return true if node.children[1] == :createElement and
1012
+ node.children[0] == s(:const, nil, :Vue)
1013
+
1014
+ # wunderbar style call
1015
+ node = node.children.first if node.type == :block
1016
+ while node.type == :send and node.children.first != nil
1017
+ node = node.children.first
1018
+ end
1019
+ node.type == :send and node.children[1].to_s.start_with? '_'
1020
+ end
1021
+
1022
+ # ensure that there are no "wunderbar" or "createElement" calls in
1023
+ # a set of statements.
1024
+ def react_wunderbar_free(nodes)
1025
+ nodes.each do |node|
1026
+ if Parser::AST::Node === node
1027
+ return false if react_element?(node)
1028
+
1029
+ # recurse
1030
+ return false unless react_wunderbar_free(node.children)
1031
+ end
1032
+ end
1033
+
1034
+ # no problems found
1035
+ return true
1036
+ end
1037
+
878
1038
  # analyze ivar usage
879
1039
  def react_walk(node)
880
1040
  # ignore hash values which are blocks (most typically, event handlers)
@@ -920,7 +1080,7 @@ module Ruby2JS
920
1080
  end
921
1081
 
922
1082
  when :send
923
- if
1083
+ if \
924
1084
  child and child.type == :self and node.children.length == 2 and
925
1085
  node.children[1] == :componentWillReceiveProps
926
1086
  then
@@ -933,7 +1093,7 @@ module Ruby2JS
933
1093
  # Ruby 'desugars' -> to lambda, and Ruby2JS presumes that lambdas
934
1094
  # return a value.
935
1095
  def on_pair(node)
936
- if
1096
+ if \
937
1097
  node.children[1].type == :block and
938
1098
  node.children[1].children[0] == s(:send, nil, :lambda)
939
1099
  then
@@ -949,7 +1109,7 @@ module Ruby2JS
949
1109
  def on_begin(node)
950
1110
  node = super
951
1111
  (node.children.length-2).downto(0) do |i|
952
- if
1112
+ if \
953
1113
  node.children[i].type == :send and
954
1114
  node.children[i].children[0] and
955
1115
  node.children[i].children[0].type == :self and