ruby2js 4.0.0 → 4.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 064d9dc5d65f6e2456e91d951e2f4311b776221422a77d59a8cfd466ceb5056d
4
- data.tar.gz: ffc274a55ceb9a1280f776c00da8c296dc10672150174135931547cd056a3520
3
+ metadata.gz: b77ba98b59e2dd3f500c4fa6c4974d6a082757becd31eb47efa841b51513ec28
4
+ data.tar.gz: 3a868aa5a10b6562ad156c47bec44aed4060338f6aa747e90298dd890ae3095f
5
5
  SHA512:
6
- metadata.gz: 8fe9775803716fce25697adaf59a8afb57f4de499052a66847f18dfdd59c1f73b52d77be473adf762a57693a0896a6c90ed275a2b9152b5b6b548ca454e6d9ae
7
- data.tar.gz: aa901eab47bba051a69a0ee132b69e7754aa5da49ff2e7e22560303a4c0fd02cdb727d4297c13098f3a6f82cf20788f4657c7ec21d145e66533875933d1a5154
6
+ metadata.gz: 2837170756fe4b6ca1f369d1dfe10c2ee6613f0572d54104354fb10df0b2f57dbe38c1dc4a44fa53f093af26bc6b826897144fbd5c5f0f6029885898878ff581
7
+ data.tar.gz: 97b02c3f49d12c7eb6f84e5a504e6b5210f04bf4450f8923ee38927714aa749968839b67ac2ad04f508f7a4cc34010eab06ad4b3cc408415390107bc1a04d623
data/lib/ruby2js.rb CHANGED
@@ -182,10 +182,12 @@ module Ruby2JS
182
182
  return on_block s(:block, s(:send, *node.children[0..-2]),
183
183
  s(:args, s(:arg, :a), s(:arg, :b)), s(:return,
184
184
  process(s(:send, s(:lvar, :a), method, s(:lvar, :b)))))
185
- else
185
+ elsif node.children.last.children.first.type == :sym
186
186
  return on_block s(:block, s(:send, *node.children[0..-2]),
187
187
  s(:args, s(:arg, :item)), s(:return,
188
188
  process(s(:attr, s(:lvar, :item), method))))
189
+ else
190
+ super
189
191
  end
190
192
  end
191
193
  super
@@ -30,13 +30,18 @@ module Ruby2JS
30
30
  if kw.type == :kwarg
31
31
  put kw.children.first
32
32
  elsif kw.type == :kwoptarg
33
- put kw.children.first; put ' = '; parse kw.children.last
33
+ put kw.children.first
34
+ unless kw.children.last == s(:send, nil, :undefined)
35
+ put ' = '; parse kw.children.last
36
+ end
34
37
  elsif kw.type == :kwrestarg
35
38
  raise 'Rest arg requires ES2018' unless es2018
36
39
  put '...'; put kw.children.first
37
40
  end
38
41
  end
39
42
  put ' }'
43
+
44
+ put ' = {}' unless kwargs.any? {|kw| kw.type == :kwarg}
40
45
  end
41
46
  end
42
47
 
@@ -114,6 +114,7 @@ module Ruby2JS
114
114
  if m.children[1] == :attr_accessor
115
115
  m.children[2..-1].map do |child_sym|
116
116
  var = child_sym.children.first
117
+ visible[var] = s(:self)
117
118
  s(:prop, s(:attr, name, :prototype), var =>
118
119
  {enumerable: s(:true), configurable: s(:true),
119
120
  get: s(:block, s(:send, nil, :proc), s(:args),
@@ -124,6 +125,7 @@ module Ruby2JS
124
125
  elsif m.children[1] == :attr_reader
125
126
  m.children[2..-1].map do |child_sym|
126
127
  var = child_sym.children.first
128
+ visible[var] = s(:self)
127
129
  s(:prop, s(:attr, name, :prototype), var =>
128
130
  {get: s(:block, s(:send, nil, :proc), s(:args),
129
131
  s(:return, s(:ivar, :"@#{var}"))),
@@ -133,6 +135,7 @@ module Ruby2JS
133
135
  elsif m.children[1] == :attr_writer
134
136
  m.children[2..-1].map do |child_sym|
135
137
  var = child_sym.children.first
138
+ visible[var] = s(:self)
136
139
  s(:prop, s(:attr, name, :prototype), var =>
137
140
  {set: s(:block, s(:send, nil, :proc), s(:args, s(:arg, var)),
138
141
  s(:ivasgn, :"@#{var}", s(:lvar, var))),
@@ -206,7 +206,7 @@ module Ruby2JS
206
206
  @prop = "static #{m.children[1]}"
207
207
  end
208
208
 
209
- @prop.sub! 'static', 'static async' if m.type == :asyncs
209
+ @prop = @prop.sub('static', 'static async') if m.type == :asyncs
210
210
 
211
211
  m = m.updated(:def, m.children[1..3])
212
212
  begin
@@ -224,6 +224,7 @@ module Ruby2JS
224
224
  m.children[2..-1].each_with_index do |child_sym, index2|
225
225
  put @sep unless index2 == 0
226
226
  var = child_sym.children.first
227
+ @rbstack.last[var] = s(:self)
227
228
  put "get #{var}() {#{@nl}return this.#{p}#{var}#@nl}#@sep"
228
229
  put "set #{var}(#{var}) {#{@nl}this.#{p}#{var} = #{var}#@nl}"
229
230
  end
@@ -231,12 +232,14 @@ module Ruby2JS
231
232
  m.children[2..-1].each_with_index do |child_sym, index2|
232
233
  put @sep unless index2 == 0
233
234
  var = child_sym.children.first
235
+ @rbstack.last[var] = s(:self)
234
236
  put "get #{var}() {#{@nl}return this.#{p}#{var}#@nl}"
235
237
  end
236
238
  elsif m.children[1] == :attr_writer
237
239
  m.children[2..-1].each_with_index do |child_sym, index2|
238
240
  put @sep unless index2 == 0
239
241
  var = child_sym.children.first
242
+ @rbstack.last[var] = s(:self)
240
243
  put "set #{var}(#{var}) {#{@nl}this.#{p}#{var} = #{var}#@nl}"
241
244
  end
242
245
  elsif [:private, :protected, :public].include? m.children[1]
@@ -276,7 +279,7 @@ module Ruby2JS
276
279
  if m.type == :casgn and m.children[0] == nil
277
280
  @rbstack.last[m.children[1]] = name
278
281
 
279
- if es2020
282
+ if es2022
280
283
  put 'static '; put m.children[1].to_s; put ' = '
281
284
  parse m.children[2]
282
285
  skipped = false
@@ -135,7 +135,7 @@ module Ruby2JS
135
135
  style = :statement
136
136
  end
137
137
 
138
- if args.children.length == 1 and args.children.first.type != :restarg and style == :expression
138
+ if args.children.length == 1 and args.children.first.type == :arg and style == :expression
139
139
  parse args; put ' => '
140
140
  else
141
141
  put '('; parse args; put ') => '
@@ -7,6 +7,24 @@ module Ruby2JS
7
7
  # (str "value")))
8
8
 
9
9
  handle :hash do |*pairs|
10
+ if not es2018 and pairs.any? {|pair| pair.type == :kwsplat}
11
+ groups = []
12
+ pending = []
13
+ while not pairs.empty?
14
+ pair = pairs.shift
15
+ if pair.type != :kwsplat
16
+ pending << pair
17
+ else
18
+ groups << s(:hash, *pending) unless pending.empty?
19
+ groups << pair.children.first
20
+ pending = []
21
+ end
22
+ end
23
+ groups << s(:hash, *pending) unless pending.empty?
24
+ parse s(:assign, s(:hash), *groups)
25
+ return
26
+ end
27
+
10
28
  compact do
11
29
  singleton = pairs.length <= 1
12
30
 
@@ -24,7 +42,7 @@ module Ruby2JS
24
42
  pairs.unshift(*node.children.first.children)
25
43
  index = 0
26
44
  else
27
- puts '...'; parse node.children.first
45
+ put '...'; parse node.children.first
28
46
  end
29
47
 
30
48
  next
@@ -57,7 +57,7 @@ module Ruby2JS
57
57
  else
58
58
  group = LOGICAL.include?( expr.type ) &&
59
59
  operator_index( :not ) < operator_index( expr.type )
60
- group = true if expr and expr.type == :begin
60
+ group = true if expr and %i[begin in?].include? expr.type
61
61
 
62
62
  put '!'; put '(' if group; parse expr; put ')' if group
63
63
  end
@@ -14,7 +14,8 @@ module Ruby2JS
14
14
 
15
15
  EXPRESSIONS = [ :array, :float, :hash, :int, :lvar, :nil, :send, :attr,
16
16
  :str, :sym, :dstr, :dsym, :cvar, :ivar, :zsuper, :super, :or, :and,
17
- :block, :const, :true, :false, :xnode, :taglit, :self ]
17
+ :block, :const, :true, :false, :xnode, :taglit, :self,
18
+ :op_asgn, :and_asgn, :or_asgn ]
18
19
 
19
20
  handle :autoreturn do |*statements|
20
21
  return if statements == [nil]
@@ -60,7 +60,7 @@ module Ruby2JS
60
60
  return parse args.first, @state
61
61
 
62
62
  elsif not receiver and [:lambda, :proc].include? method
63
- if method == :lambda
63
+ if method == :lambda and @state != :statement
64
64
  return parse s(args.first.type, *args.first.children[0..-2],
65
65
  s(:autoreturn, args.first.children[-1])), @state
66
66
  else
@@ -75,10 +75,17 @@ module Ruby2JS
75
75
  (es2015 || @state == :statement ? group(receiver) : parse(receiver))
76
76
  put '('; parse_all(*args, join: ', '); put ')'
77
77
  return
78
+ elsif not t2 and m2 == :async and args2.length == 0
79
+ put '('; parse receiver; put ')()'
80
+ return
78
81
  end
79
82
  end
80
83
 
81
84
  # async/await support
85
+ # map "await x do...end" to "await x {...}" due to precedence rules
86
+ if method == :await and es2017 and receiver == nil and args.length == 2 and args[1].type == :def
87
+ args = [s(:block, args.first, *args.last.children[1..-1])]
88
+ end
82
89
  if es2017 and receiver == nil and args.length == 1
83
90
  if method == :async
84
91
  if args.first.type == :def
@@ -89,6 +96,15 @@ module Ruby2JS
89
96
  # async def o.m(x) {...}
90
97
  return parse args.first.updated :asyncs
91
98
 
99
+ elsif args.first.type == :send and
100
+ args.first.children.first.type == :block and
101
+ args.first.children.last == :[]
102
+
103
+ put '(async '
104
+ parse args.first.children.first, :statement
105
+ put ')()'
106
+ return
107
+
92
108
  elsif args.first.type == :block
93
109
  block = args.first
94
110
 
@@ -157,6 +173,8 @@ module Ruby2JS
157
173
  group_target ||= GROUP_OPERATORS.include? target.type
158
174
  end
159
175
 
176
+ put 'await ' if @ast.type == :await
177
+
160
178
  if method == :!
161
179
  parse s(:not, receiver)
162
180
 
@@ -172,7 +190,7 @@ module Ruby2JS
172
190
  end
173
191
 
174
192
  elsif method == :[]=
175
- parse receiver
193
+ (group_receiver ? group(receiver) : parse(receiver))
176
194
  if \
177
195
  args.length == 2 and [:str, :sym].include? args.first.type and
178
196
  args.first.children.first.to_s =~ /^[a-zA-Z]\w*$/
@@ -303,9 +321,16 @@ module Ruby2JS
303
321
  elsif method == :typeof and receiver == nil
304
322
  put 'typeof '; parse args.first
305
323
 
306
- else
307
- put 'await ' if @ast.type == :await
324
+ elsif ast.children[1] == :is_a? and receiver and args.length == 1
325
+ parse receiver; put ' instanceof '; parse args.first
326
+
327
+ elsif ast.children[1] == :kind_of? and receiver and args.length == 1
328
+ parse receiver; put ' instanceof '; parse args.first
308
329
 
330
+ elsif ast.children[1] == :instance_of? and receiver and args.length == 1
331
+ parse s(:send, s(:attr, receiver, :constructor), :==, args.first)
332
+
333
+ else
309
334
  if method == :bind and receiver&.type == :send
310
335
  if receiver.children.length == 2 and receiver.children.first == nil
311
336
  receiver = receiver.updated(:attr) # prevent autobind
@@ -5,9 +5,8 @@ module Ruby2JS
5
5
  # (str 'a'))
6
6
 
7
7
  handle :xstr do |*children|
8
- str = eval capture { parse_all(*children) }
9
-
10
8
  if @binding
9
+ str = eval capture { parse_all(*children) }
11
10
  puts @binding.eval(str).to_s
12
11
  else
13
12
  raise SecurityError.new('Insecure operation, eval without binding option')
@@ -11,6 +11,8 @@ module Ruby2JS
11
11
 
12
12
  ALLOWLIST = %w{
13
13
  attr_accessor
14
+ attr_reader
15
+ attr_writer
14
16
  method_missing
15
17
  }
16
18
 
@@ -1,4 +1,5 @@
1
1
  require 'ruby2js'
2
+
2
3
  require 'regexp_parser/scanner'
3
4
 
4
5
  module Ruby2JS
@@ -7,7 +8,7 @@ module Ruby2JS
7
8
  include SEXP
8
9
 
9
10
  # require explicit opt-in to to class => constructor mapping
10
- Filter.exclude :class
11
+ Filter.exclude :class, :call
11
12
 
12
13
  VAR_TO_ASSIGN = {
13
14
  lvar: :lvasgn,
@@ -23,7 +24,7 @@ module Ruby2JS
23
24
 
24
25
  def on_send(node)
25
26
  target, method, *args = node.children
26
- return super if excluded?(method)
27
+ return super if excluded?(method) and method != :call
27
28
 
28
29
  if [:max, :min].include? method and args.length == 0
29
30
  if target.type == :array
@@ -36,13 +37,10 @@ module Ruby2JS
36
37
  return super
37
38
  end
38
39
 
39
- elsif method == :call and target and target.type == :ivar
40
- process S(:send, s(:self), "_#{target.children.first.to_s[1..-1]}",
41
- *args)
40
+ elsif method == :call and target and
41
+ (%i[ivar cvar].include?(target.type) or not excluded?(:call))
42
42
 
43
- elsif method == :call and target and target.type == :cvar
44
- process S(:send, s(:attr, s(:self), :constructor),
45
- "_#{target.children.first.to_s[2..-1]}", *args)
43
+ S(:call, process(target), nil, *process_all(args))
46
44
 
47
45
  elsif method == :keys and args.length == 0 and node.is_method?
48
46
  process S(:send, s(:const, nil, :Object), :keys, target)
@@ -222,7 +222,7 @@ module Ruby2JS
222
222
  scan_events[node.children]
223
223
  end
224
224
  end
225
- scan_events[body]
225
+ scan_events[body] unless es2015
226
226
 
227
227
  # append statics (if any)
228
228
  unless statics.empty?
@@ -323,7 +323,7 @@ module Ruby2JS
323
323
  elsif mname == :render and not react_wunderbar_free(block, true)
324
324
  if \
325
325
  block.length != 1 or not block.last or
326
- not [:send, :block].include? block.last.type
326
+ not %i[send block xstr].include? block.last.type
327
327
  then
328
328
  if @jsx
329
329
  while block.length == 1 and block.first.type == :begin
@@ -111,6 +111,7 @@ module Ruby2JS
111
111
 
112
112
  importname = Pathname.new(filename).relative_path_from(Pathname.new(dirname)).to_s
113
113
  importname = Pathname.new(@require_relative).join(importname).to_s
114
+ importname = "./#{importname}" unless importname.start_with? '.'
114
115
 
115
116
  prepend_list << s(:import, importname, *imports)
116
117
 
@@ -152,12 +153,7 @@ module Ruby2JS
152
153
  end
153
154
  end
154
155
  else
155
- begin
156
- require_expr, @require_expr = @require_expr, true
157
- super
158
- ensure
159
- @require_expr = require_expr
160
- end
156
+ super
161
157
  end
162
158
  end
163
159
 
data/lib/ruby2js/jsx.rb CHANGED
@@ -11,7 +11,7 @@ module Ruby2JS
11
11
 
12
12
  class JsxParser
13
13
  def initialize(stream)
14
- @stream = stream
14
+ @stream = stream.respond_to?(:next) ? stream : OpalEnumerator.new(stream)
15
15
  @state = :text
16
16
  @text = ''
17
17
  @result = []
@@ -288,4 +288,22 @@ module Ruby2JS
288
288
  self.class.new(@stream).parse(:element)
289
289
  end
290
290
  end
291
+
292
+ # Opal's enumerator doesn't currently support next and peek methods.
293
+ # Build a wrapper that adds those methods.
294
+ class OpalEnumerator
295
+ def initialize(stream)
296
+ @stream = stream.to_a
297
+ end
298
+
299
+ def next
300
+ raise StopIteration.new if @stream.empty?
301
+ @stream.shift
302
+ end
303
+
304
+ def peek
305
+ raise StopIteration.new if @stream.empty?
306
+ @stream.first
307
+ end
308
+ end
291
309
  end
@@ -2,7 +2,7 @@ module Ruby2JS
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 4
4
4
  MINOR = 0
5
- TINY = 0
5
+ TINY = 1
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
data/ruby2js.gemspec CHANGED
@@ -19,5 +19,5 @@ Gem::Specification.new do |s|
19
19
  s.summary = "Minimal yet extensible Ruby to JavaScript conversion.".freeze
20
20
 
21
21
  s.add_dependency('parser')
22
- s.add_dependency('regexp_parser')
22
+ s.add_dependency('regexp_parser', '~> 2.0.3')
23
23
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby2js
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.0
4
+ version: 4.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Ruby
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2021-02-10 00:00:00.000000000 Z
12
+ date: 2021-02-23 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: parser
@@ -29,16 +29,16 @@ dependencies:
29
29
  name: regexp_parser
30
30
  requirement: !ruby/object:Gem::Requirement
31
31
  requirements:
32
- - - ">="
32
+ - - "~>"
33
33
  - !ruby/object:Gem::Version
34
- version: '0'
34
+ version: 2.0.3
35
35
  type: :runtime
36
36
  prerelease: false
37
37
  version_requirements: !ruby/object:Gem::Requirement
38
38
  requirements:
39
- - - ">="
39
+ - - "~>"
40
40
  - !ruby/object:Gem::Version
41
- version: '0'
41
+ version: 2.0.3
42
42
  description: |2
43
43
  The base package maps Ruby syntax to JavaScript semantics.
44
44
  Filters may be provided to add Ruby-specific or framework specific