ruby2js 2.1.24 → 3.0.0

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 (40) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +91 -50
  3. data/lib/ruby2js/converter/args.rb +10 -0
  4. data/lib/ruby2js/converter/block.rb +1 -1
  5. data/lib/ruby2js/converter/case.rb +1 -1
  6. data/lib/ruby2js/converter/casgn.rb +6 -1
  7. data/lib/ruby2js/converter/class.rb +7 -2
  8. data/lib/ruby2js/converter/class2.rb +167 -0
  9. data/lib/ruby2js/converter/def.rb +54 -6
  10. data/lib/ruby2js/converter/defs.rb +11 -5
  11. data/lib/ruby2js/converter/dstr.rb +26 -0
  12. data/lib/ruby2js/converter/for.rb +3 -3
  13. data/lib/ruby2js/converter/hash.rb +31 -6
  14. data/lib/ruby2js/converter/if.rb +1 -1
  15. data/lib/ruby2js/converter/ivasgn.rb +5 -2
  16. data/lib/ruby2js/converter/masgn.rb +41 -4
  17. data/lib/ruby2js/converter/send.rb +71 -10
  18. data/lib/ruby2js/converter/super.rb +21 -8
  19. data/lib/ruby2js/converter/vasgn.rb +5 -1
  20. data/lib/ruby2js/converter/while.rb +13 -0
  21. data/lib/ruby2js/converter.rb +32 -5
  22. data/lib/ruby2js/es2015/strict.rb +3 -0
  23. data/lib/ruby2js/es2015.rb +5 -0
  24. data/lib/ruby2js/es2016/strict.rb +3 -0
  25. data/lib/ruby2js/es2016.rb +5 -0
  26. data/lib/ruby2js/es2017/strict.rb +3 -0
  27. data/lib/ruby2js/es2017.rb +5 -0
  28. data/lib/ruby2js/execjs.rb +1 -1
  29. data/lib/ruby2js/filter/camelCase.rb +1 -1
  30. data/lib/ruby2js/filter/functions.rb +49 -2
  31. data/lib/ruby2js/filter/vue.rb +66 -45
  32. data/lib/ruby2js/strict.rb +3 -0
  33. data/lib/ruby2js/version.rb +3 -3
  34. data/lib/ruby2js.rb +41 -0
  35. data/ruby2js.gemspec +3 -1
  36. metadata +10 -6
  37. data/lib/ruby2js/filter/angular-resource.rb +0 -25
  38. data/lib/ruby2js/filter/angular-route.rb +0 -44
  39. data/lib/ruby2js/filter/angularrb.rb +0 -604
  40. data/lib/ruby2js/filter/strict.rb +0 -20
@@ -1,604 +0,0 @@
1
- require 'ruby2js'
2
-
3
- module Ruby2JS
4
- module Filter
5
- module AngularRB
6
- include SEXP
7
-
8
- def self.s(type, *args)
9
- Parser::AST::Node.new type, args
10
- end
11
-
12
- Angular = s(:const, nil, :Angular)
13
-
14
- # convert simple assignments, simple method calls, and simple method
15
- # definitions into a hash when possible; return false otherwise
16
- def self.hash(pairs)
17
- if pairs.length == 1 and pairs.first.type == :begin
18
- pairs = pairs.first.children
19
- end
20
-
21
- s(:hash, *pairs.map {|pair|
22
- if pair.type == :send and pair.children[0] == nil
23
- s(:pair, s(:sym, pair.children[1]), pair.children[2])
24
- elsif pair.type == :lvasgn
25
- s(:pair, s(:sym, pair.children[0]), pair.children[1])
26
- elsif pair.type == :def
27
- s(:pair, s(:sym, pair.children[0]), s(:block, s(:send, nil, :proc),
28
- *pair.children[1..-1]))
29
- else
30
- return false
31
- end
32
- })
33
- end
34
-
35
- def initialize(*args)
36
- @ngApp = nil
37
- @ngContext = nil
38
- @ngAppUses = []
39
- @ngClassUses = []
40
- @ngClassOmit = []
41
- @ngScope = nil
42
- super
43
- end
44
-
45
- # input:
46
- # module Angular::AppName
47
- # use :Dependency
48
- # ...
49
- # end
50
- #
51
- # output:
52
- # AppName = angular.module("AppName", ["Dependency"])
53
- # ...
54
-
55
- def on_module(node)
56
- ngContext, @ngContext = @ngContext, :module
57
- @ngModule = node.children
58
- if @ngModule.last and @ngModule.last.type == :begin
59
- @ngModule = @ngModule.last.children
60
- end
61
- module_name = node.children[0]
62
- parent_name = module_name.children[0]
63
-
64
- return super unless parent_name == Angular
65
-
66
- @ngApp = s(:lvar, module_name.children[1])
67
- @ngChildren = node.children[1..-1]
68
- while @ngChildren.length == 1 and @ngChildren.first and @ngChildren.first.type == :begin
69
- @ngChildren = @ngChildren.first.children.dup
70
- end
71
- @ngAppUses = []
72
-
73
- block = process_all(node.children[1..-1])
74
-
75
- # convert use calls into dependencies
76
- depends = @ngAppUses.map {|sym| s(:sym, sym)} + extract_uses(block)
77
- depends = depends.map {|dnode| dnode.children.first.to_s}.uniq.sort.
78
- map {|sym| s(:str, sym)}
79
-
80
- ngApp, @ngApp, @ngChildren = @ngApp, nil, nil
81
- name = module_name.children[1].to_s
82
-
83
- # construct app
84
- app = s(:send, s(:lvar, :angular), :module,
85
- s(:str, name), s(:array, *depends.uniq))
86
-
87
- # return a single chained statement when there is only one call
88
- block.compact!
89
- if block.length == 0
90
- return app
91
- elsif block.length == 1
92
- call = block.first.children.first
93
- if block.first.type == :send and call == ngApp
94
- return block.first.updated nil, [app, *block.first.children[1..-1]]
95
- elsif block.first.type == :block and call.children.first == ngApp
96
- call = call.updated nil, [app, *call.children[1..-1]]
97
- return block.first.updated nil, [call, *block.first.children[1..-1]]
98
- end
99
- end
100
-
101
- # replace module with a constant assign followed by the module
102
- # contents all wrapped in an anonymous function
103
- s(:send, s(:block, s(:send, nil, :proc), s(:args),
104
- s(:begin, s(:casgn, nil, name, app), *block)), :[])
105
- ensure
106
- @ngContext = ngContext
107
- end
108
-
109
- # input:
110
- # class name {...}
111
- #
112
- # output:
113
- # app.factory(uses) do
114
- # ...
115
- # end
116
- def on_class(node)
117
- ngContext, @ngContext = @ngContext, :class
118
- return super unless @ngApp and @ngChildren.include? node
119
-
120
- name = node.children.first
121
- if name.children.first == nil
122
- @ngClassUses, @ngClassOmit = [], []
123
- @ngClassUses << node.children[1].children[1] if node.children[1]
124
-
125
- block = [node.children.last]
126
- uses = extract_uses(block)
127
- node = s(:class, name, node.children[1],
128
- s(:begin, *process_all(block)))
129
-
130
- @ngClassUses -= @ngClassOmit + [name.children.last]
131
- args = @ngClassUses.map {|sym| s(:arg, sym)} + uses
132
- args = args.map {|anode| anode.children.first.to_sym}.uniq.sort.
133
- map {|sym| s(:arg, sym)}
134
- @ngClassUses, @ngClassOmit = [], []
135
-
136
- s(:block, s(:send, @ngApp, :factory,
137
- s(:sym, name.children.last)), s(:args, *args),
138
- s(:begin, node, s(:return, s(:const, nil, name.children.last))))
139
- else
140
- super
141
- end
142
- ensure
143
- @ngClassUses, @ngClassOmit = [], []
144
- @ngContext = ngContext
145
- end
146
-
147
- # input:
148
- # filter :name { ... }
149
- # controller :name { ... }
150
- # factory :name { ... }
151
- # directive :name { ... }
152
-
153
- def on_block(node)
154
- ngApp = @ngApp
155
- call = node.children.first
156
- target = call.children.first
157
- if target and target.type == :const and target.children.first == Angular
158
- @ngApp = s(:send, s(:lvar, :angular), :module, s(:str,
159
- target.children.last.to_s))
160
- else
161
- return super if target
162
- return super unless @ngApp
163
- end
164
-
165
- begin
166
- case call.children[1]
167
- when :controller
168
- ng_controller(node, :controller)
169
- when :factory
170
- ng_factory(node)
171
- when :filter
172
- ng_filter(node)
173
- when :config
174
- ng_config(node)
175
- when :directive
176
- hash = AngularRB.hash(node.children[2..-1])
177
- if hash
178
- node = node.updated nil, [*node.children[0..1], s(:return, hash)]
179
- end
180
- ng_controller(node, :directive)
181
- when :watch
182
- ng_watch(node, :$watch)
183
- when :on
184
- ng_watch(node, :$on)
185
- when :observe
186
- ng_observe(node)
187
- when :timeout, :interval
188
- method = (call.children[1] == :timeout ? :$timeout : :$interval)
189
- process s(:gvar, method) # for dependency injection purposes
190
- process s(:send, nil, method, s(:block, s(:send, nil, :proc),
191
- *node.children[1..-1]), *call.children[2..-1])
192
- else
193
- super
194
- end
195
- ensure
196
- @ngApp = ngApp
197
- end
198
- end
199
-
200
- # input:
201
- # config :service do
202
- # name = value
203
- # end
204
- #
205
- # output:
206
- # AppName.config("service") do |service|
207
- # service.name = value
208
- # end
209
- def ng_config(node)
210
- call = node.children.first
211
- services = call.children[2..-1].map {|sym| sym.children[0]}
212
- list = node.children[2..-1]
213
-
214
- if services.length == 1
215
- hash = AngularRB.hash(node.children[2..-1])
216
- if hash
217
- service = call.children[2].children[0]
218
- list = hash.children.map do |pair|
219
- s(:send, s(:gvar, service), "#{pair.children[0].children[0]}=",
220
- pair.children[1])
221
- end
222
- end
223
- end
224
-
225
- s(:send, @ngApp, :config,
226
- s(:array, *services.map {|sym| s(:str, sym.to_s)},
227
- s(:block, s(:send, nil, :proc),
228
- s(:args, *services.map {|sym| s(:arg, sym)}), s(:begin, *list))))
229
- end
230
-
231
- # input:
232
- # controller :name do
233
- # ...
234
- # end
235
- #
236
- # output:
237
- # AppName.controller("name") do |uses|
238
- # ...
239
- # end
240
- def ng_controller(node, scope)
241
- ngContext, @ngContext = @ngContext, scope
242
- @ngClassUses, @ngClassOmit = [], []
243
- target = node.children.first
244
- target = target.updated(nil, [@ngApp, *target.children[1..-1]])
245
-
246
- block = process_all(node.children[2..-1])
247
-
248
- # convert use calls into args
249
- @ngClassUses -= @ngClassOmit
250
- args = node.children[1].children
251
- args += @ngClassUses.map {|sym| s(:arg, sym)} + extract_uses(block)
252
- args = args.map {|anode| anode.children.first.to_sym}.uniq.sort.
253
- map {|sym| s(:arg, sym)}
254
-
255
- node.updated :block, [target, s(:args, *args), s(:begin, *block)]
256
- ensure
257
- @ngClassUses, @ngClassOmit = [], []
258
- @ngContext = ngContext
259
- end
260
-
261
- # input:
262
- # filter :name do |input|
263
- # ...
264
- # end
265
- #
266
- # output:
267
- # AppName.filter :name do
268
- # return proc {|input| return ... }
269
- # end
270
- EXPRESSION = [ :and, :array, :attr, :const, :cvar, :defined?, :dstr,
271
- :dsym, :false, :float, :gvar, :hash, :int, :ivar, :lvar, :nil, :not,
272
- :or, :regexp, :self, :send, :str, :sym, :true, :undefined?, :xstr ]
273
-
274
- def ng_filter(node)
275
- ngContext, @ngContext = @ngContext, :filter
276
- @ngClassUses, @ngClassOmit = [], []
277
- call = node.children.first
278
-
279
- # insert return
280
- args = process_all(node.children[1].children)
281
- block = process_all(node.children[2..-1])
282
- uses = (@ngClassUses - @ngClassOmit).uniq.sort.map {|sym| s(:arg, sym)}
283
- tail = [block.pop || s(:nil)]
284
- while tail.length == 1 and tail.first.type == :begin
285
- tail = tail.first.children.dup
286
- end
287
- tail.push s(:return, tail.pop) if EXPRESSION.include? tail.last.type
288
- block.push (tail.length == 1 ? tail.first : s(:begin, *tail))
289
-
290
- # construct a function returning a function
291
- inner = s(:block, s(:send, nil, :proc), s(:args, *args), *block)
292
- outer = s(:send, @ngApp, :filter, *call.children[2..-1])
293
-
294
- node.updated nil, [outer, s(:args, *uses), s(:return, inner)]
295
- ensure
296
- @ngClassUses, @ngClassOmit = [], []
297
- @ngContext = ngContext
298
- end
299
-
300
- # input:
301
- # factory :name do |uses|
302
- # ...
303
- # end
304
- #
305
- # output:
306
- # AppName.factory :name, [uses, proc {|uses| ...}]
307
- def ng_factory(node)
308
- ngContext, @ngContext = @ngContext, :factory
309
- call = node.children.first
310
- call = call.updated(nil, [@ngApp, *call.children[1..-1]])
311
-
312
- # insert return
313
- block = process_all(node.children[2..-1])
314
- tail = [block.pop || s(:nil)]
315
- while tail.length == 1 and tail.first.type == :begin
316
- tail = tail.first.children.dup
317
- end
318
- tail.push s(:return, tail.pop) unless tail.last.type == :return
319
- block.push (tail.length == 1 ? tail.first : s(:begin, *tail))
320
-
321
- # extract dependencies
322
- @ngClassUses.delete call.children[2].children[0]
323
- args = process_all(node.children[1].children)
324
- args += @ngClassUses.map {|sym| s(:arg, sym)} + extract_uses(block)
325
- args = args.map {|anode| anode.children.first.to_sym}.uniq.sort.
326
- map {|sym| s(:arg, sym)}
327
-
328
- # construct a function
329
- function = s(:block, s(:send, nil, :proc), s(:args, *args), *block)
330
- array = args.map {|arg| s(:str, arg.children.first.to_s)}
331
-
332
- s(:send, *call.children, s(:array, *array, function))
333
- ensure
334
- @ngClassUses, @ngClassOmit = [], []
335
- @ngContext = ngContext
336
- end
337
-
338
- # input:
339
- # Constant = ...
340
- #
341
- # output:
342
- # AppName.factory :name, [uses, proc {|uses| ...}]
343
- def on_casgn(node)
344
- return super if node.children[0]
345
- @ngClassOmit << node.children[1]
346
- return super unless @ngApp and @ngChildren.include? node
347
- ng_factory s(:block, s(:send, nil, :factory, s(:sym, node.children[1])),
348
- s(:args), process(node.children[2]))
349
- end
350
-
351
- # convert ivar referencess in controllers to $scope
352
- def on_ivar(node)
353
- if @ngContext == :controller
354
- process s(:attr, s(:gvar, :$scope), node.children.first.to_s[1..-1])
355
- else
356
- super
357
- end
358
- end
359
-
360
- # convert cvar referencess in controllers to self
361
- def on_cvar(node)
362
- if @ngContext == :controller
363
- process s(:attr, s(:self), node.children.first.to_s[2..-1])
364
- else
365
- super
366
- end
367
- end
368
-
369
- # input:
370
- # watch 'expression' do |oldvalue, newvalue|
371
- # ...
372
- # end
373
- #
374
- # output:
375
- # $scope.$watch 'expression' do |oldvalue, newvalue|
376
- # ...
377
- # end
378
- #
379
- # also handles 'on'
380
- #
381
- def ng_watch(node, method)
382
- call = node.children.first
383
- if @ngContext == :controller and call.children.first == nil
384
- target = s(:gvar, :$scope)
385
- expression = call.children[2]
386
- if not [:str, :dstr, :sym, :dsym].include? expression.type
387
- expression = s(:block, s(:send, nil, :proc), s(:args),
388
- s(:return, expression))
389
- end
390
- else
391
- target = nil
392
- method = call.children[1]
393
- expression = call.children[2]
394
- end
395
- call = s(:send, process(target), method, process(expression),
396
- *process_all(call.children[3..-1]))
397
- node.updated nil, [call, *process_all(node.children[1..-1])]
398
- end
399
-
400
- # input:
401
- # observe attr.name do |value|
402
- # ...
403
- # end
404
- #
405
- # output:
406
- # attr.$observe('name') do |value|
407
- # ...
408
- # end
409
- def ng_observe(node)
410
- if @ngContext == :controller and @ngScope
411
- call = node.children[0]
412
- expression = call.children[2]
413
- call = s(:send, expression.children[0], :$observe,
414
- s(:sym, expression.children[1]))
415
- process node.updated nil, [call, *node.children[1..-1]]
416
- else
417
- node.updated nil, process_all(node.children)
418
- end
419
- end
420
-
421
- # convert ivar assignments in controllers to $scope
422
- def on_ivasgn(node)
423
- if @ngContext == :controller
424
- if node.children.length == 1
425
- process s(:attr, s(:gvar, :$scope),
426
- "#{node.children.first.to_s[1..-1]}")
427
- else
428
- process s(:send, s(:gvar, :$scope),
429
- "#{node.children.first.to_s[1..-1]}=", node.children.last)
430
- end
431
- else
432
- super
433
- end
434
- end
435
-
436
- # convert cvar assignments in controllers to self
437
- def on_cvasgn(node)
438
- if @ngContext == :controller
439
- if node.children.length == 1
440
- process s(:attr, s(:self), "#{node.children.first.to_s[2..-1]}")
441
- else
442
- process s(:send, s(:self), "#{node.children.first.to_s[2..-1]}=",
443
- node.children.last)
444
- end
445
- else
446
- super
447
- end
448
- end
449
-
450
- NG_METHOD_MAP = {
451
- :apply! => [:$rootScope, :$apply],
452
- :apply => [:$scope, :$apply],
453
- :broadcast! => [:$rootScope, :$broadcast],
454
- :broadcast => [:$scope, :$broadcast],
455
- :digest! => [:$rootScope, :$digest],
456
- :digest => [:$scope, :$digest],
457
- :emit => [:$scope, :$emit],
458
- :evalAsync! => [:$rootScope, :$evalAsync],
459
- :evalAsync => [:$scope, :$evalAsync],
460
- :eval! => [:$rootScope, :$eval],
461
- :eval => [:$scope, :$eval],
462
- :filter => [nil, :$filter],
463
- :parent => [:$scope, :$parent],
464
- }
465
-
466
- def on_send(node)
467
- if @ngContext == :controller
468
- if node.children[0..1] == [nil, :interpolate] and @ngScope
469
- @ngClassUses << :$interpolate
470
- if node.children.length > 3 and node.children[3].type == :nil
471
- return process node.updated nil, [nil, :$interpolate,
472
- node.children[2]]
473
- else
474
- return process s(:send, s(:send, nil, :$interpolate,
475
- *node.children[2..-1]), nil, @ngScope)
476
- end
477
-
478
- elsif node.children[0..1] == [nil, :compile] and @ngScope
479
-
480
- @ngClassUses << :$compile
481
- if node.children.length > 3 and node.children.last.type == :nil
482
- return process node.updated nil, [nil, :$compile,
483
- *node.children[2..-2]]
484
- else
485
- return process s(:send, s(:send, nil, :$compile,
486
- *node.children[2..-1]), nil, @ngScope)
487
- end
488
- end
489
-
490
- # map well known method names to the appropriate service
491
- scope, method = NG_METHOD_MAP[node.children[1]]
492
-
493
- return super unless node.children.first == nil and method
494
-
495
- scope = s(:gvar, scope) if scope
496
- process s(:gvar, method) unless scope
497
-
498
- process node.updated nil, [scope, method, *node.children[2..-1]]
499
-
500
- elsif @ngContext == :module and node.children[0]
501
- return super unless @ngModule.include? node
502
- child = node
503
- while child and child.type == :send
504
- child = child.children[0]
505
- end
506
-
507
- # singleton configuration syntax
508
- return super unless child and (child.type == :gvar or
509
- (child.type == :const and child.children[0] == nil))
510
-
511
- service = child.children.last
512
- s(:send, @ngApp, :config, s(:array, s(:str, service.to_s), s(:block,
513
- s(:send, nil, :proc), s(:args, s(:arg, service)), node)))
514
-
515
- else
516
- super
517
- end
518
- end
519
-
520
- # convert instance method definitions in controllers to $scope
521
- def on_pair(node)
522
- if @ngContext == :directive and node.children[0] == s(:sym, :link)
523
- begin
524
- ngScope = @ngScope
525
- if node.children[1].type == :block
526
- args = node.children[1].children[1]
527
- if args.children.length > 0
528
- @ngScope = s(:lvar, args.children[0].children[0])
529
- @ngContext = :controller
530
- end
531
- end
532
- super
533
- ensure
534
- @ngScope = ngScope
535
- @ngContext = :directive
536
- end
537
- else
538
- super
539
- end
540
- end
541
-
542
- # convert instance method definitions in controllers to $scope
543
- def on_def(node)
544
- if @ngContext == :controller
545
- if node.is_method?
546
- process s(:defs, s(:gvar, :$scope), *node.children)
547
- else
548
- process s(:defp, s(:gvar, :$scope), *node.children)
549
- end
550
- else
551
- super
552
- end
553
- end
554
-
555
- def on_gvar(node)
556
- return @ngScope if node.children.first == :$scope and @ngScope
557
-
558
- if @ngClassUses
559
- @ngClassUses << node.children.first
560
- end
561
-
562
- super
563
- end
564
-
565
- BUILTINS = [ :Array, :Boolean, :Date, :Error, :Function, :Infinity, :JSON,
566
- :Math, :NaN, :Number, :Object, :RegExp, :Regexp, :String ]
567
-
568
- def on_const(node)
569
- if @ngClassUses and not node.children.first
570
- unless BUILTINS.include? node.children.last
571
- @ngClassUses << node.children.last
572
- end
573
- end
574
-
575
- super
576
- end
577
-
578
- def extract_uses(block)
579
- # find the block
580
- while block.length == 1 and block.first and block.first.type == :begin
581
- block.push(*block.shift.children)
582
- end
583
-
584
- # find use class method calls
585
- uses = block.find_all do |node|
586
- node and node.type == :send and node.children[0..1] == [nil, :use]
587
- end
588
-
589
- # convert use calls into dependencies
590
- depends = []
591
- uses.each do |use|
592
- use.children[2..-1].each do |node|
593
- depends << node if [:str, :sym].include? node.type
594
- end
595
- block.delete use
596
- end
597
-
598
- depends
599
- end
600
- end
601
-
602
- DEFAULTS.push AngularRB
603
- end
604
- end
@@ -1,20 +0,0 @@
1
- require 'ruby2js'
2
-
3
- module Ruby2JS
4
- module Filter
5
- module Strict
6
- include SEXP
7
-
8
- def process(node)
9
- if @strict
10
- super
11
- else
12
- @strict = true
13
- s(:begin, s(:str, 'use strict'), super(node))
14
- end
15
- end
16
- end
17
-
18
- DEFAULTS.push Strict
19
- end
20
- end