ruby2js 4.1.5 → 4.2.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.
@@ -69,5 +69,19 @@ module Ruby2JS
69
69
  parse s(@ast.children[0].type, *call.children, function), @state
70
70
  end
71
71
  end
72
+
73
+ # (numblock
74
+ # (send nil :x)
75
+ # 1
76
+ # (lvar :_1))
77
+
78
+ handle :numblock do |call, count, block|
79
+ parse s(:block,
80
+ call,
81
+ s(:args, *((1..count).map {|i| s(:arg, "_#{i}")})),
82
+ block
83
+ )
84
+ end
85
+
72
86
  end
73
87
  end
@@ -73,12 +73,12 @@ module Ruby2JS
73
73
  s(:and, left, right)
74
74
  elsif conditionally_equals(left, right.children.first)
75
75
  # a && a.b => a&.b
76
- right.updated(:csend, [left, right.children.last])
76
+ right.updated(:csend, [left, *right.children[1..-1]])
77
77
  elsif conditionally_equals(left.children.last, right.children.first)
78
78
  # a && b && b.c => a && b&.c
79
79
  left.updated(:and, [left.children.first,
80
80
  left.children.last.updated(:csend,
81
- [left.children.last, right.children.last])])
81
+ [left.children.last, *right.children[1..-1]])])
82
82
  else
83
83
  s(:and, left, right)
84
84
  end
@@ -15,7 +15,7 @@ module Ruby2JS
15
15
  EXPRESSIONS = [ :array, :float, :hash, :int, :lvar, :nil, :send, :attr,
16
16
  :str, :sym, :dstr, :dsym, :cvar, :ivar, :zsuper, :super, :or, :and,
17
17
  :block, :const, :true, :false, :xnode, :taglit, :self,
18
- :op_asgn, :and_asgn, :or_asgn, :taglit, :gvar ]
18
+ :op_asgn, :and_asgn, :or_asgn, :taglit, :gvar, :csend ]
19
19
 
20
20
  handle :autoreturn do |*statements|
21
21
  return if statements == [nil]
@@ -17,8 +17,8 @@ module Ruby2JS
17
17
 
18
18
  LOGICAL = :and, :not, :or
19
19
  OPERATORS = [:[], :[]=], [:not, :!], [:**], [:*, :/, :%], [:+, :-],
20
- [:>>, :<<], [:&], [:^, :|], [:<=, :<, :>, :>=], [:==, :!=, :===, :"!=="],
21
- [:and, :or]
20
+ [:>>, :<<], [:&], [:^, :|], [:<=, :<, :>, :>=],
21
+ [:==, :!=, :===, :"!==", :=~, :!~], [:and, :or]
22
22
 
23
23
  INVERT_OP = {
24
24
  :< => :>=,
data/lib/ruby2js/demo.rb CHANGED
@@ -3,6 +3,34 @@ require 'ruby2js'
3
3
 
4
4
  module Ruby2JS
5
5
  module Demo
6
+ # convert {"[:foo, :Bar]" => "wee"} to {[:foo, :Bar] => "wee"}
7
+ def self.parse_stringified_symbol_keys(mapping_hash)
8
+ updated_mappings = {}
9
+
10
+ mapping_hash.each do |k, v|
11
+ next updated_mappings[k] = v unless k.is_a?(String) && k.start_with?("[:")
12
+
13
+ new_k = k.tr("[]", "").split(",").map! {|str| str.strip.delete_prefix(":").to_sym }.map(&:to_sym)
14
+ updated_mappings[new_k] = v
15
+ end
16
+
17
+ updated_mappings
18
+ end
19
+
20
+ # convert {"Foo" => "[:bar, :Baz]"} to {"Foo" => [:bar, :Baz]}
21
+ def self.parse_stringified_symbol_values(mapping_hash)
22
+ updated_mappings = {}
23
+
24
+ mapping_hash.each do |k, v|
25
+ next updated_mappings[k] = v unless v.is_a?(String) && v.start_with?("[:")
26
+
27
+ new_v = v.tr("[]", "").split(",").map! {|str| str.strip.delete_prefix(":").to_sym }.map(&:to_sym)
28
+ updated_mappings[k] = new_v
29
+ end
30
+
31
+ updated_mappings
32
+ end
33
+
6
34
  def self.parse_autoimports(mappings)
7
35
  autoimports = {}
8
36
 
@@ -13,16 +13,30 @@ module Ruby2JS
13
13
  @esm_autoimports = options[:autoimports]
14
14
  @esm_defs = options[:defs] || {}
15
15
  @esm_explicit_tokens = Set.new
16
+ @esm_top = nil
17
+
18
+ # don't convert requires if Require filter is included
19
+ filters = options[:filters] || Filter::DEFAULTS
20
+ if \
21
+ defined? Ruby2JS::Filter::Require and
22
+ filters.include? Ruby2JS::Filter::Require
23
+ then
24
+ @esm_top = []
25
+ end
16
26
  end
17
27
 
18
28
  def process(node)
19
- return super unless @esm_autoexports
29
+ return super if @esm_top
20
30
 
21
31
  list = [node]
22
32
  while list.length == 1 and list.first.type == :begin
23
33
  list = list.first.children.dup
24
34
  end
25
35
 
36
+ @esm_top = list
37
+
38
+ return super unless @esm_autoexports
39
+
26
40
  replaced = []
27
41
  list.map! do |child|
28
42
  replacement = child
@@ -84,7 +98,7 @@ module Ruby2JS
84
98
  target, method, *args = node.children
85
99
  return super unless target.nil?
86
100
 
87
- if method == :import
101
+ if method == :import or (method == :require and @esm_top&.include? @ast)
88
102
  # don't do the conversion if the word import is followed by a paren
89
103
  if node.loc.respond_to? :selector
90
104
  selector = node.loc.selector
@@ -98,7 +112,7 @@ module Ruby2JS
98
112
  # => import "file.css"
99
113
  s(:import, args[0].children[0])
100
114
  elsif args.length == 1 and \
101
- args[0].type == :send and \
115
+ args[0].type == :send and \
102
116
  args[0].children[0].nil? and \
103
117
  args[0].children[2].type == :send and \
104
118
  args[0].children[2].children[0].nil? and \
@@ -152,17 +166,17 @@ module Ruby2JS
152
166
 
153
167
  values = @esm_defs[node.children.last]
154
168
 
155
- if values
156
- values = values.map {|value|
157
- if value.to_s.start_with? "@"
158
- [value.to_s[1..-1].to_sym, s(:self)]
159
- else
160
- [value.to_sym, s(:autobind, s(:self))]
161
- end
162
- }.to_h
163
-
164
- @namespace.defineProps values, [node.children.last]
165
- end
169
+ if values
170
+ values = values.map {|value|
171
+ if value.to_s.start_with? "@"
172
+ [value.to_s[1..-1].to_sym, s(:self)]
173
+ else
174
+ [value.to_sym, s(:autobind, s(:self))]
175
+ end
176
+ }.to_h
177
+
178
+ @namespace.defineProps values, [node.children.last]
179
+ end
166
180
  end
167
181
 
168
182
  super
@@ -162,6 +162,9 @@ module Ruby2JS
162
162
  elsif method == :to_f
163
163
  process node.updated :send, [nil, :parseFloat, target, *args]
164
164
 
165
+ elsif method == :to_json
166
+ process node.updated :send, [s(:const, nil, :JSON), :stringify, target, *args]
167
+
165
168
  elsif method == :sub and args.length == 2
166
169
  if args[1].type == :str
167
170
  args[1] = s(:str, args[1].children.first.gsub(/\\(\d)/, "$\\1"))
@@ -503,6 +506,12 @@ module Ruby2JS
503
506
  s(:regexp, s(:str, '\A\s+') , s(:regopt)), s(:str, '')])
504
507
  end
505
508
 
509
+ elsif method == :index
510
+ process node.updated(nil, [target, :indexOf, *args])
511
+
512
+ elsif method == :rindex
513
+ process node.updated(nil, [target, :lastIndexOf, *args])
514
+
506
515
  elsif method == :class and args.length==0 and not node.is_method?
507
516
  process node.updated(:attr, [target, :constructor])
508
517
 
@@ -515,6 +524,9 @@ module Ruby2JS
515
524
  elsif method == :abs and args.length == 0
516
525
  process S(:send, s(:const, nil, :Math), :abs, target)
517
526
 
527
+ elsif method == :round and args.length == 0
528
+ process S(:send, s(:const, nil, :Math), :round, target)
529
+
518
530
  elsif method == :ceil and args.length == 0
519
531
  process S(:send, s(:const, nil, :Math), :ceil, target)
520
532
 
@@ -570,6 +582,13 @@ module Ruby2JS
570
582
  process S(:send, s(:attr, target, :prototype), :[]=, args[0],
571
583
  s(:attr, s(:attr, target, :prototype), args[1].children[0]))
572
584
 
585
+ elsif method == :new and args.length == 2 and target == s(:const, nil, :Array)
586
+ if es2015
587
+ s(:send, S(:send, target, :new, args.first), :fill, args.last)
588
+ else
589
+ super
590
+ end
591
+
573
592
  else
574
593
  super
575
594
  end
@@ -616,6 +635,11 @@ module Ruby2JS
616
635
  node.updated nil, [process(call), process(node.children[1]),
617
636
  s(:autoreturn, *process_all(node.children[2..-1]))]
618
637
 
638
+ elsif method == :index and call.children.length == 2
639
+ call = call.updated nil, [call.children.first, :findIndex]
640
+ node.updated nil, [process(call), process(node.children[1]),
641
+ s(:autoreturn, *process_all(node.children[2..-1]))]
642
+
619
643
  elsif method == :map and call.children.length == 2
620
644
  node.updated nil, [process(call), process(node.children[1]),
621
645
  s(:autoreturn, *process_all(node.children[2..-1]))]
@@ -1,218 +1,2 @@
1
- require 'ruby2js'
2
-
3
- module Ruby2JS
4
- module Filter
5
- module LitElement
6
- include SEXP
7
- extend SEXP
8
-
9
- LITELEMENT_IMPORT = s(:import,
10
- [s(:pair, s(:sym, :from), s(:str, "lit-element"))],
11
- [s(:const, nil, :LitElement), s(:attr, nil, :css), s(:attr, nil, :html)])
12
-
13
- def initialize(node)
14
- super
15
- @le_props = nil
16
- end
17
-
18
- def on_ivar(node)
19
- return super unless @le_props&.include?(node.children.first)
20
- s(:attr, s(:self), node.children.first.to_s[1..-1])
21
- end
22
-
23
- def on_ivasgn(node)
24
- return super unless @le_props&.include?(node.children.first)
25
- return super unless node.children.length > 1
26
- s(:send, s(:self), node.children.first.to_s[1..-1]+'=',
27
- process(node.children[1]))
28
- end
29
-
30
- def on_op_asgn(node)
31
- return super unless node.children.first.type == :ivasgn
32
- var = node.children.first.children.first
33
- return super unless @le_props&.include?(var)
34
- super node.updated(nil, [s(:attr, s(:attr, nil, :this),
35
- var.to_s[1..-1]), *node.children[1..-1]])
36
- end
37
-
38
- def on_class(node)
39
- _, inheritance, *body = node.children
40
- return super unless inheritance == s(:const, nil, :LitElement)
41
-
42
- @le_props = {}
43
- le_walk(node)
44
-
45
- prepend_list << LITELEMENT_IMPORT if modules_enabled?
46
-
47
- nodes = body.dup
48
- if nodes.length == 1 and nodes.first&.type == :begin
49
- nodes = nodes.first.children.dup
50
- end
51
-
52
- # insert/update static get properties() {}
53
- unless @le_props.empty?
54
- values = nodes.find_index {|child|
55
- child.type == :defs and child.children[0..1] == [s(:self), :properties]
56
- }
57
-
58
- if values == nil
59
- nodes.unshift s(:defp, s(:self), :properties, s(:args), s(:return,
60
- s(:hash, *@le_props.map {|name, type| s(:pair, s(:str, name.to_s[1..-1]),
61
- s(:hash, s(:pair, s(:sym, :type), s(:const, nil, type || :String))))})))
62
- elsif nodes[values].children[3].type == :hash
63
- le_props = @le_props.map {|name, type|
64
- [s(:sym, name.to_s[1..-1].to_sym),
65
- s(:hash, s(:pair, s(:sym, :type), s(:const, nil, type || :String)))]
66
- }.to_h.merge(
67
- nodes[values].children[3].children.map {|pair| pair.children}.to_h
68
- )
69
-
70
- nodes[values] = nodes[values].updated(nil,
71
- [*nodes[values].children[0..2], s(:hash,
72
- *le_props.map{|name, value| s(:pair, name, value)})])
73
- end
74
- end
75
-
76
- # render of a string is converted to a taglit :html
77
- render = nodes.find_index {|child|
78
- child&.type == :def and child.children.first == :render
79
- }
80
- if render and %i[str dstr].include?(nodes[render].children[2]&.type)
81
- nodes[render] = nodes[render].updated(:deff,
82
- [*nodes[render].children[0..1],
83
- s(:autoreturn, html_wrap(nodes[render].children[2]))])
84
- end
85
-
86
- # self.styles returning string is converted to a taglit :css
87
- styles = nodes.find_index {|child|
88
- child&.type == :defs and child.children[0..1] == [s(:self), :styles]
89
- }
90
- if styles and %i[str dstr].include?(nodes[styles].children[3]&.type)
91
- string = nodes[styles].children[3]
92
- string = s(:dstr, string) if string.type == :str
93
- children = string.children.dup
94
-
95
- while children.length > 1 and children.last.type == :str and
96
- children.last.children.last.strip == ''
97
- children.pop
98
- end
99
-
100
- if children.last.type == :str
101
- children << s(:str, children.pop.children.first.chomp)
102
- end
103
-
104
- nodes[styles] = nodes[styles].updated(nil,
105
- [*nodes[styles].children[0..2],
106
- s(:autoreturn, s(:taglit, s(:sym, :css),
107
- s(:dstr, *children)))])
108
- end
109
-
110
- # insert super calls into initializer
111
- initialize = nodes.find_index {|child|
112
- child&.type == :def and child.children.first == :initialize
113
- }
114
- if initialize and nodes[initialize].children.length == 3
115
- statements = nodes[initialize].children[2..-1]
116
-
117
- if statements.length == 1 and statements.first.type == :begin
118
- statements = statements.first.children
119
- end
120
-
121
- unless statements.any? {|statement| %i[super zuper].include? statement.type}
122
- nodes[initialize] = nodes[initialize].updated(nil,
123
- [*nodes[initialize].children[0..1],
124
- s(:begin, s(:zsuper), *statements)])
125
- end
126
- end
127
-
128
- props = @le_props.keys.map {|prop| [prop.to_sym, s(:self)]}.to_h
129
-
130
- nodes.unshift s(:defineProps, props)
131
-
132
- nodes.pop unless nodes.last
133
-
134
- node.updated(nil, [*node.children[0..1], s(:begin, *process_all(nodes))])
135
- ensure
136
- @le_props = nil
137
- end
138
-
139
- def html_wrap(node)
140
- if node.type == :str and node.children.first.strip.start_with? '<'
141
- s(:taglit, s(:sym, :html), s(:dstr, node))
142
- elsif node.type == :dstr
143
- prefix = ''
144
- node.children.each do |child|
145
- break unless child.type == :str
146
- prefix += child.children.first
147
- end
148
-
149
- return node unless prefix.strip.start_with? '<'
150
-
151
- children = node.children.map do |child|
152
- if child.type == :str
153
- child
154
- else
155
- html_wrap(child)
156
- end
157
- end
158
-
159
- while children.length > 1 and children.last.type == :str and
160
- children.last.children.last.strip == ''
161
- children.pop
162
- end
163
-
164
- if children.last.type == :str
165
- children << s(:str, children.pop.children.first.chomp)
166
- end
167
-
168
- s(:taglit, s(:sym, :html), node.updated(nil, children))
169
- elsif node.type == :begin
170
- node.updated(nil, node.children.map {|child| html_wrap(child)})
171
- elsif node.type == :if
172
- node.updated(nil, [node.children.first,
173
- *node.children[1..2].map {|child| html_wrap(child)}])
174
- elsif node.type == :block and
175
- node.children.first.children[1] == :map
176
- node.updated(nil, [*node.children[0..1],
177
- html_wrap(node.children[2])])
178
- else
179
- node
180
- end
181
- end
182
-
183
- # analyze ivar usage
184
- def le_walk(node)
185
- node.children.each do |child|
186
- next unless child.is_a? Parser::AST::Node
187
-
188
- if child.type == :ivar
189
- @le_props[child.children.first] ||= nil
190
- elsif child.type == :ivasgn || child.type == :op_asgn
191
- prop = child.children.first
192
- unless prop.is_a? Symbol
193
- prop = prop.children.first if prop.type == :ivasgn
194
- next unless prop.is_a? Symbol
195
- end
196
-
197
- @le_props[prop] = case child.children.last.type
198
- when :str, :dstr
199
- :String
200
- when :array
201
- :Array
202
- when :int, :float
203
- :Number
204
- when :true, :false
205
- :Boolean
206
- else
207
- @le_props[prop] || :Object
208
- end
209
- else
210
- le_walk(child)
211
- end
212
- end
213
- end
214
- end
215
-
216
- DEFAULTS.push LitElement
217
- end
218
- end
1
+ # for backwards compatibility
2
+ require_relative './lit'