opal 1.1.1 → 1.2.0.beta1
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 +4 -4
- data/.codeclimate.yml +3 -2
- data/.github/ISSUE_TEMPLATE/bug-report.md +47 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
- data/.github/workflows/build.yml +11 -5
- data/.gitignore +1 -0
- data/.jshintrc +1 -1
- data/Gemfile +0 -4
- data/HACKING.md +1 -1
- data/README.md +19 -15
- data/UNRELEASED.md +41 -0
- data/benchmark-ips/bm_array_unshift.rb +7 -0
- data/bin/opal-mspec +2 -0
- data/docs/compiler.md +1 -1
- data/examples/rack/Gemfile +0 -1
- data/examples/rack/Gemfile.lock +0 -4
- data/lib/opal/cli.rb +1 -0
- data/lib/opal/cli_options.rb +4 -0
- data/lib/opal/cli_runners/nodejs.rb +4 -0
- data/lib/opal/cli_runners/source-map-support-browser.js +3 -1
- data/lib/opal/cli_runners/source-map-support-node.js +3 -1
- data/lib/opal/cli_runners/source-map-support.js +3 -1
- data/lib/opal/compiler.rb +2 -2
- data/lib/opal/nodes/args/arity_check.rb +1 -0
- data/lib/opal/nodes/args/parameters.rb +6 -0
- data/lib/opal/nodes/class.rb +1 -13
- data/lib/opal/nodes/literal.rb +14 -7
- data/lib/opal/nodes/module.rb +13 -9
- data/lib/opal/nodes/variables.rb +13 -4
- data/lib/opal/nodes/while.rb +54 -17
- data/lib/opal/parser.rb +1 -5
- data/lib/opal/parser/patch.rb +34 -0
- data/lib/opal/repl.rb +7 -0
- data/lib/opal/rewriter.rb +2 -0
- data/lib/opal/rewriters/arguments.rb +4 -1
- data/lib/opal/rewriters/forward_args.rb +54 -0
- data/lib/opal/rewriters/logical_operator_assignment.rb +5 -2
- data/lib/opal/rewriters/opal_engine_check.rb +5 -7
- data/lib/opal/version.rb +1 -1
- data/opal/corelib/array.rb +42 -20
- data/opal/corelib/array/pack.rb +6 -1
- data/opal/corelib/complex.rb +2 -0
- data/opal/corelib/constants.rb +3 -3
- data/opal/corelib/hash.rb +36 -38
- data/opal/corelib/module.rb +2 -7
- data/opal/corelib/number.rb +2 -180
- data/opal/corelib/numeric.rb +156 -0
- data/opal/corelib/object_space.rb +102 -0
- data/opal/corelib/random.rb +31 -66
- data/opal/corelib/random/formatter.rb +122 -0
- data/opal/corelib/range.rb +50 -19
- data/opal/corelib/runtime.js +82 -21
- data/opal/corelib/string.rb +86 -52
- data/opal/corelib/string/encoding.rb +140 -25
- data/opal/corelib/string/unpack.rb +26 -40
- data/opal/opal.rb +1 -0
- data/opal/opal/full.rb +1 -0
- data/spec/filters/bugs/array.rb +0 -22
- data/spec/filters/bugs/basicobject.rb +3 -0
- data/spec/filters/bugs/encoding.rb +0 -2
- data/spec/filters/bugs/exception.rb +1 -0
- data/spec/filters/bugs/float.rb +0 -2
- data/spec/filters/bugs/hash.rb +2 -7
- data/spec/filters/bugs/integer.rb +0 -2
- data/spec/filters/bugs/kernel.rb +16 -3
- data/spec/filters/bugs/language.rb +6 -14
- data/spec/filters/bugs/marshal.rb +1 -3
- data/spec/filters/bugs/module.rb +16 -1
- data/spec/filters/bugs/numeric.rb +4 -12
- data/spec/filters/bugs/objectspace.rb +67 -0
- data/spec/filters/bugs/pack_unpack.rb +0 -9
- data/spec/filters/bugs/pathname.rb +1 -0
- data/spec/filters/bugs/proc.rb +8 -0
- data/spec/filters/bugs/random.rb +3 -6
- data/spec/filters/bugs/range.rb +83 -113
- data/spec/filters/bugs/set.rb +2 -0
- data/spec/filters/bugs/string.rb +31 -70
- data/spec/filters/bugs/struct.rb +2 -0
- data/spec/filters/bugs/time.rb +8 -2
- data/spec/filters/unsupported/float.rb +3 -0
- data/spec/filters/unsupported/freeze.rb +1 -0
- data/spec/filters/unsupported/integer.rb +3 -0
- data/spec/filters/unsupported/refinements.rb +5 -0
- data/spec/filters/unsupported/string.rb +100 -95
- data/spec/filters/unsupported/time.rb +4 -0
- data/spec/lib/compiler_spec.rb +16 -0
- data/spec/lib/rewriters/forward_args_spec.rb +61 -0
- data/spec/lib/rewriters/logical_operator_assignment_spec.rb +1 -1
- data/spec/lib/rewriters/numblocks_spec.rb +44 -0
- data/spec/lib/rewriters/opal_engine_check_spec.rb +49 -4
- data/spec/opal/core/language/forward_args_spec.rb +53 -0
- data/spec/opal/core/language/infinite_range_spec.rb +13 -0
- data/spec/opal/core/language/memoization_spec.rb +16 -0
- data/spec/opal/core/module_spec.rb +38 -2
- data/spec/opal/core/number/to_i_spec.rb +28 -0
- data/spec/opal/core/runtime/bridged_classes_spec.rb +16 -0
- data/spec/opal/core/runtime/constants_spec.rb +20 -1
- data/spec/opal/core/string/subclassing_spec.rb +16 -0
- data/spec/opal/core/string/unpack_spec.rb +22 -0
- data/spec/opal/core/string_spec.rb +4 -4
- data/spec/ruby_specs +4 -1
- data/stdlib/json.rb +3 -1
- data/stdlib/securerandom.rb +55 -35
- data/tasks/testing.rake +6 -3
- data/test/nodejs/test_string.rb +25 -0
- data/vendored-minitest/minitest/assertions.rb +2 -0
- metadata +31 -10
- data/lib/opal/parser/with_c_lexer.rb +0 -15
data/lib/opal/compiler.rb
CHANGED
|
@@ -151,7 +151,7 @@ module Opal
|
|
|
151
151
|
|
|
152
152
|
# @!method use_strict?
|
|
153
153
|
#
|
|
154
|
-
#
|
|
154
|
+
# Enables JavaScript's strict mode (i.e., adds 'use strict'; statement)
|
|
155
155
|
compiler_option :use_strict, default: false, as: :use_strict?, magic_comment: true
|
|
156
156
|
|
|
157
157
|
# @!method parse_comments?
|
|
@@ -358,7 +358,7 @@ module Opal
|
|
|
358
358
|
def in_while
|
|
359
359
|
return unless block_given?
|
|
360
360
|
@while_loop = @scope.push_while
|
|
361
|
-
result =
|
|
361
|
+
result = yield
|
|
362
362
|
@scope.pop_while
|
|
363
363
|
result
|
|
364
364
|
end
|
|
@@ -30,6 +30,7 @@ module Opal
|
|
|
30
30
|
|
|
31
31
|
def on_restarg(arg_name = nil)
|
|
32
32
|
if arg_name
|
|
33
|
+
arg_name = :* if arg_name == :fwd_rest_arg
|
|
33
34
|
%{['rest', '#{arg_name}']}
|
|
34
35
|
else
|
|
35
36
|
%{['rest']}
|
|
@@ -53,9 +54,14 @@ module Opal
|
|
|
53
54
|
end
|
|
54
55
|
|
|
55
56
|
def on_blockarg(arg_name)
|
|
57
|
+
arg_name = :& if arg_name == :fwd_block_arg
|
|
56
58
|
%{['block', '#{arg_name}']}
|
|
57
59
|
end
|
|
58
60
|
|
|
61
|
+
def on_kwnilarg
|
|
62
|
+
%{['nokey']}
|
|
63
|
+
end
|
|
64
|
+
|
|
59
65
|
def on_shadowarg(_arg_name); end
|
|
60
66
|
end
|
|
61
67
|
end
|
data/lib/opal/nodes/class.rb
CHANGED
|
@@ -15,28 +15,16 @@ module Opal
|
|
|
15
15
|
|
|
16
16
|
push '(function($base, $super, $parent_nesting) {'
|
|
17
17
|
line " var self = $klass($base, $super, '#{name}');"
|
|
18
|
-
|
|
19
18
|
in_scope do
|
|
20
19
|
scope.name = name
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
body_code = self.body_code
|
|
24
|
-
empty_line
|
|
25
|
-
|
|
26
|
-
line scope.to_vars
|
|
27
|
-
line body_code
|
|
20
|
+
compile_body
|
|
28
21
|
end
|
|
29
|
-
|
|
30
22
|
line '})(', base, ', ', super_code, ', $nesting)'
|
|
31
23
|
end
|
|
32
24
|
|
|
33
25
|
def super_code
|
|
34
26
|
sup ? expr(sup) : 'null'
|
|
35
27
|
end
|
|
36
|
-
|
|
37
|
-
def body_code
|
|
38
|
-
stmt(compiler.returns(body || s(:nil)))
|
|
39
|
-
end
|
|
40
28
|
end
|
|
41
29
|
end
|
|
42
30
|
end
|
data/lib/opal/nodes/literal.rb
CHANGED
|
@@ -70,6 +70,11 @@ module Opal
|
|
|
70
70
|
wrap "$enc(", ", \"#{encoding.name}\")"
|
|
71
71
|
end
|
|
72
72
|
end
|
|
73
|
+
|
|
74
|
+
unless value.valid_encoding?
|
|
75
|
+
helper :binary
|
|
76
|
+
wrap "$binary(", ")"
|
|
77
|
+
end
|
|
73
78
|
end
|
|
74
79
|
|
|
75
80
|
# http://www.2ality.com/2013/09/javascript-unicode.html
|
|
@@ -253,9 +258,11 @@ module Opal
|
|
|
253
258
|
end
|
|
254
259
|
|
|
255
260
|
def compile_inline?
|
|
256
|
-
|
|
257
|
-
SIMPLE_CHILDREN_TYPES.include?(start.type)
|
|
258
|
-
|
|
261
|
+
(
|
|
262
|
+
!start || (start.type && SIMPLE_CHILDREN_TYPES.include?(start.type))
|
|
263
|
+
) && (
|
|
264
|
+
!finish || (finish.type && SIMPLE_CHILDREN_TYPES.include?(finish.type))
|
|
265
|
+
)
|
|
259
266
|
end
|
|
260
267
|
|
|
261
268
|
def compile_inline
|
|
@@ -271,11 +278,11 @@ module Opal
|
|
|
271
278
|
handle :irange
|
|
272
279
|
|
|
273
280
|
def compile_inline
|
|
274
|
-
push '$range(',
|
|
281
|
+
push '$range(', expr_or_nil(start), ', ', expr_or_nil(finish), ', false)'
|
|
275
282
|
end
|
|
276
283
|
|
|
277
284
|
def compile_range_initialize
|
|
278
|
-
push 'Opal.Range.$new(',
|
|
285
|
+
push 'Opal.Range.$new(', expr_or_nil(start), ', ', expr_or_nil(finish), ', false)'
|
|
279
286
|
end
|
|
280
287
|
end
|
|
281
288
|
|
|
@@ -283,11 +290,11 @@ module Opal
|
|
|
283
290
|
handle :erange
|
|
284
291
|
|
|
285
292
|
def compile_inline
|
|
286
|
-
push '$range(',
|
|
293
|
+
push '$range(', expr_or_nil(start), ', ', expr_or_nil(finish), ', true)'
|
|
287
294
|
end
|
|
288
295
|
|
|
289
296
|
def compile_range_initialize
|
|
290
|
-
push 'Opal.Range.$new(',
|
|
297
|
+
push 'Opal.Range.$new(', expr_or_nil(start), ',', expr_or_nil(finish), ', true)'
|
|
291
298
|
end
|
|
292
299
|
end
|
|
293
300
|
|
data/lib/opal/nodes/module.rb
CHANGED
|
@@ -15,21 +15,15 @@ module Opal
|
|
|
15
15
|
|
|
16
16
|
push '(function($base, $parent_nesting) {'
|
|
17
17
|
line " var self = $module($base, '#{name}');"
|
|
18
|
-
|
|
19
18
|
in_scope do
|
|
20
19
|
scope.name = name
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
body_code = stmt(body || s(:nil))
|
|
24
|
-
empty_line
|
|
25
|
-
|
|
26
|
-
line scope.to_vars
|
|
27
|
-
line body_code
|
|
20
|
+
compile_body
|
|
28
21
|
end
|
|
29
|
-
|
|
30
22
|
line '})(', base, ', $nesting)'
|
|
31
23
|
end
|
|
32
24
|
|
|
25
|
+
private
|
|
26
|
+
|
|
33
27
|
# cid is always s(:const, scope_sexp_or_nil, :ConstName)
|
|
34
28
|
def name_and_base
|
|
35
29
|
base, name = cid.children
|
|
@@ -40,6 +34,16 @@ module Opal
|
|
|
40
34
|
[name, expr(base)]
|
|
41
35
|
end
|
|
42
36
|
end
|
|
37
|
+
|
|
38
|
+
def compile_body
|
|
39
|
+
add_temp '$nesting = [self].concat($parent_nesting)'
|
|
40
|
+
|
|
41
|
+
body_code = stmt(compiler.returns(body || s(:nil)))
|
|
42
|
+
empty_line
|
|
43
|
+
|
|
44
|
+
line scope.to_vars
|
|
45
|
+
line body_code
|
|
46
|
+
end
|
|
43
47
|
end
|
|
44
48
|
end
|
|
45
49
|
end
|
data/lib/opal/nodes/variables.rb
CHANGED
|
@@ -194,9 +194,16 @@ module Opal
|
|
|
194
194
|
children :name
|
|
195
195
|
|
|
196
196
|
def compile
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
197
|
+
helper :class_variable_get
|
|
198
|
+
|
|
199
|
+
tolerant = false
|
|
200
|
+
# We should be tolerant of expressions like: def x; @@notexist; 0; end
|
|
201
|
+
# (NB: Shouldn't we actually optimize them out?)
|
|
202
|
+
tolerant = true if stmt?
|
|
203
|
+
# We should be tolerant of expressions like: @@notexist ||= 6
|
|
204
|
+
# (those are handled with logical_operator_assignment)
|
|
205
|
+
|
|
206
|
+
push "$class_variable_get(#{class_variable_owner}, '#{name}', #{tolerant.inspect})"
|
|
200
207
|
end
|
|
201
208
|
end
|
|
202
209
|
|
|
@@ -206,7 +213,9 @@ module Opal
|
|
|
206
213
|
children :name, :value
|
|
207
214
|
|
|
208
215
|
def compile
|
|
209
|
-
|
|
216
|
+
helper :class_variable_set
|
|
217
|
+
|
|
218
|
+
push "$class_variable_set(#{class_variable_owner}, '#{name}', ", expr(value), ')'
|
|
210
219
|
end
|
|
211
220
|
end
|
|
212
221
|
end
|
data/lib/opal/nodes/while.rb
CHANGED
|
@@ -10,32 +10,45 @@ module Opal
|
|
|
10
10
|
children :test, :body
|
|
11
11
|
|
|
12
12
|
def compile
|
|
13
|
-
|
|
14
|
-
test_code = js_truthy(test)
|
|
13
|
+
test_code = js_truthy(test)
|
|
15
14
|
|
|
15
|
+
with_temp do |redo_var|
|
|
16
16
|
compiler.in_while do
|
|
17
17
|
while_loop[:closure] = true if wrap_in_closure?
|
|
18
18
|
while_loop[:redo_var] = redo_var
|
|
19
19
|
|
|
20
|
-
body_code = stmt(body)
|
|
21
|
-
|
|
20
|
+
body_code = indent { stmt(body) }
|
|
22
21
|
if uses_redo?
|
|
23
|
-
|
|
24
|
-
push test_code
|
|
25
|
-
push while_close
|
|
22
|
+
compile_with_redo(test_code, body_code, redo_var)
|
|
26
23
|
else
|
|
27
|
-
|
|
24
|
+
compile_without_redo(test_code, body_code)
|
|
28
25
|
end
|
|
29
|
-
|
|
30
|
-
push "#{redo_var} = false;" if uses_redo?
|
|
31
|
-
line body_code
|
|
32
26
|
end
|
|
33
|
-
line '}'
|
|
34
27
|
end
|
|
35
28
|
|
|
36
29
|
wrap '(function() {', '; return nil; })()' if wrap_in_closure?
|
|
37
30
|
end
|
|
38
31
|
|
|
32
|
+
private
|
|
33
|
+
|
|
34
|
+
def compile_with_redo(test_code, body_code, redo_var)
|
|
35
|
+
push "#{redo_var} = false; "
|
|
36
|
+
compile_while(
|
|
37
|
+
[redo_var, " || ", test_code],
|
|
38
|
+
["#{redo_var} = false;", body_code]
|
|
39
|
+
)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def compile_without_redo(test_code, body_code)
|
|
43
|
+
compile_while([test_code], [body_code])
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def compile_while(test_code, body_code)
|
|
47
|
+
push while_open, *test_code, while_close
|
|
48
|
+
indent { line(*body_code) }
|
|
49
|
+
line '}'
|
|
50
|
+
end
|
|
51
|
+
|
|
39
52
|
def while_open
|
|
40
53
|
'while ('
|
|
41
54
|
end
|
|
@@ -53,13 +66,11 @@ module Opal
|
|
|
53
66
|
end
|
|
54
67
|
end
|
|
55
68
|
|
|
56
|
-
class WhilePostNode < WhileNode
|
|
57
|
-
handle :while_post
|
|
58
|
-
end
|
|
59
|
-
|
|
60
69
|
class UntilNode < WhileNode
|
|
61
70
|
handle :until
|
|
62
71
|
|
|
72
|
+
private
|
|
73
|
+
|
|
63
74
|
def while_open
|
|
64
75
|
'while (!('
|
|
65
76
|
end
|
|
@@ -69,8 +80,34 @@ module Opal
|
|
|
69
80
|
end
|
|
70
81
|
end
|
|
71
82
|
|
|
72
|
-
class
|
|
83
|
+
class WhilePostNode < WhileNode
|
|
84
|
+
handle :while_post
|
|
85
|
+
|
|
86
|
+
private
|
|
87
|
+
|
|
88
|
+
def compile_while(test_code, body_code)
|
|
89
|
+
push "do {"
|
|
90
|
+
indent { line(*body_code) }
|
|
91
|
+
line "} ", while_open, *test_code, while_close
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def while_close
|
|
95
|
+
');'
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
class UntilPostNode < WhilePostNode
|
|
73
100
|
handle :until_post
|
|
101
|
+
|
|
102
|
+
private
|
|
103
|
+
|
|
104
|
+
def while_open
|
|
105
|
+
'while(!('
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def while_close
|
|
109
|
+
'));'
|
|
110
|
+
end
|
|
74
111
|
end
|
|
75
112
|
end
|
|
76
113
|
end
|
data/lib/opal/parser.rb
CHANGED
data/lib/opal/parser/patch.rb
CHANGED
|
@@ -39,3 +39,37 @@ if RUBY_ENGINE == 'opal'
|
|
|
39
39
|
end
|
|
40
40
|
end
|
|
41
41
|
end
|
|
42
|
+
|
|
43
|
+
module AST::Processor::Mixin
|
|
44
|
+
undef process
|
|
45
|
+
# This patch to #process removes a bit of dynamic abilities (removed
|
|
46
|
+
# call to node.to_ast) and it tries to optimize away the string
|
|
47
|
+
# operations and method existence check by caching them inside a
|
|
48
|
+
# processor.
|
|
49
|
+
#
|
|
50
|
+
# This is the second most inefficient call in the compilation phase
|
|
51
|
+
# so an optimization may be warranted.
|
|
52
|
+
def process(node)
|
|
53
|
+
return if node.nil?
|
|
54
|
+
|
|
55
|
+
@_on_handler_cache ||= {}
|
|
56
|
+
type = node.type
|
|
57
|
+
|
|
58
|
+
on_handler = @_on_handler_cache[type] ||= begin
|
|
59
|
+
handler = :"on_#{type}"
|
|
60
|
+
handler = :handler_missing unless respond_to?(handler)
|
|
61
|
+
handler
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
send(on_handler, node) || node
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
class Parser::Builders::Default
|
|
69
|
+
# string_value raises on invalid UTF-8 strings, like "\x80",
|
|
70
|
+
# otherwise it's the same as value.
|
|
71
|
+
undef string_value
|
|
72
|
+
def string_value(token)
|
|
73
|
+
value(token)
|
|
74
|
+
end
|
|
75
|
+
end
|
data/lib/opal/repl.rb
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'opal'
|
|
4
|
+
require 'securerandom'
|
|
4
5
|
|
|
5
6
|
module Opal
|
|
6
7
|
class REPL
|
|
@@ -38,9 +39,15 @@ module Opal
|
|
|
38
39
|
eval_ruby File.read(filename)
|
|
39
40
|
end
|
|
40
41
|
|
|
42
|
+
# A polyfill so that SecureRandom works in repl correctly.
|
|
43
|
+
def random_bytes(bytes)
|
|
44
|
+
::SecureRandom.bytes(bytes).split('').map(&:ord)
|
|
45
|
+
end
|
|
46
|
+
|
|
41
47
|
def load_opal
|
|
42
48
|
v8.attach('console.log', method(:puts).to_proc)
|
|
43
49
|
v8.attach('console.warn', method(:warn).to_proc)
|
|
50
|
+
v8.attach('crypto.randomBytes', method(:random_bytes).to_proc)
|
|
44
51
|
v8.eval Opal::Builder.new.build('opal').to_s
|
|
45
52
|
v8.attach('Opal.exit', method(:exit).to_proc)
|
|
46
53
|
end
|
data/lib/opal/rewriter.rb
CHANGED
|
@@ -14,6 +14,7 @@ require 'opal/rewriters/mlhs_args'
|
|
|
14
14
|
require 'opal/rewriters/inline_args'
|
|
15
15
|
require 'opal/rewriters/numblocks'
|
|
16
16
|
require 'opal/rewriters/returnable_logic'
|
|
17
|
+
require 'opal/rewriters/forward_args'
|
|
17
18
|
|
|
18
19
|
module Opal
|
|
19
20
|
class Rewriter
|
|
@@ -45,6 +46,7 @@ module Opal
|
|
|
45
46
|
use Rewriters::OpalEngineCheck
|
|
46
47
|
use Rewriters::ForRewriter
|
|
47
48
|
use Rewriters::Numblocks
|
|
49
|
+
use Rewriters::ForwardArgs
|
|
48
50
|
use Rewriters::BlockToIter
|
|
49
51
|
use Rewriters::DotJsSyntax
|
|
50
52
|
use Rewriters::JsReservedWords
|
|
@@ -4,7 +4,7 @@ module Opal
|
|
|
4
4
|
module Rewriters
|
|
5
5
|
class Arguments
|
|
6
6
|
attr_reader :args, :optargs, :restarg, :postargs,
|
|
7
|
-
:kwargs, :kwoptargs, :kwrestarg,
|
|
7
|
+
:kwargs, :kwoptargs, :kwrestarg, :kwnilarg,
|
|
8
8
|
:shadowargs, :blockarg
|
|
9
9
|
|
|
10
10
|
def initialize(args)
|
|
@@ -15,6 +15,7 @@ module Opal
|
|
|
15
15
|
@kwargs = []
|
|
16
16
|
@kwoptargs = []
|
|
17
17
|
@kwrestarg = nil
|
|
18
|
+
@kwnilarg = false
|
|
18
19
|
@shadowargs = []
|
|
19
20
|
@blockarg = nil
|
|
20
21
|
|
|
@@ -30,6 +31,8 @@ module Opal
|
|
|
30
31
|
@kwargs << arg
|
|
31
32
|
when :kwoptarg
|
|
32
33
|
@kwoptargs << arg
|
|
34
|
+
when :kwnilarg
|
|
35
|
+
@kwnilarg = true
|
|
33
36
|
when :kwrestarg
|
|
34
37
|
@kwrestarg = arg
|
|
35
38
|
when :shadowarg
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'opal/rewriters/base'
|
|
4
|
+
|
|
5
|
+
module Opal
|
|
6
|
+
module Rewriters
|
|
7
|
+
class ForwardArgs < Base
|
|
8
|
+
def on_forward_args(_node)
|
|
9
|
+
process(
|
|
10
|
+
s(:args, s(:forward_arg, :"$"))
|
|
11
|
+
)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def on_args(node)
|
|
15
|
+
if node.children.last && node.children.last.type == :forward_arg
|
|
16
|
+
prev_children = node.children[0..-2]
|
|
17
|
+
|
|
18
|
+
node.updated(nil,
|
|
19
|
+
[
|
|
20
|
+
*prev_children,
|
|
21
|
+
s(:restarg, '$fwd_rest'),
|
|
22
|
+
s(:blockarg, '$fwd_block')
|
|
23
|
+
]
|
|
24
|
+
)
|
|
25
|
+
else
|
|
26
|
+
super
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def on_send(node)
|
|
31
|
+
if node.children.last &&
|
|
32
|
+
node.children.last.class != Symbol &&
|
|
33
|
+
node.children.last.type == :forwarded_args
|
|
34
|
+
|
|
35
|
+
prev_children = node.children[0..-2]
|
|
36
|
+
|
|
37
|
+
node.updated(nil,
|
|
38
|
+
[
|
|
39
|
+
*prev_children,
|
|
40
|
+
s(:splat,
|
|
41
|
+
s(:lvar, '$fwd_rest')
|
|
42
|
+
),
|
|
43
|
+
s(:block_pass,
|
|
44
|
+
s(:lvar, '$fwd_block')
|
|
45
|
+
)
|
|
46
|
+
]
|
|
47
|
+
)
|
|
48
|
+
else
|
|
49
|
+
super
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|