ruby2js 4.0.0 → 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 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