opal 1.3.2 → 1.4.0.alpha1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.eslintrc.js +1 -0
- data/.github/workflows/build.yml +0 -3
- data/.rubocop.yml +5 -1
- data/UNRELEASED.md +66 -2
- data/benchmark-ips/bm_truthy.rb +30 -0
- data/bin/opal-mspec +1 -3
- data/bin/opal-repl +1 -2
- data/bin/remove-filters +1 -4
- data/docs/compiled_ruby.md +10 -6
- data/exe/opal-repl +1 -3
- data/lib/opal/ast/builder.rb +1 -1
- data/lib/opal/cli.rb +2 -2
- data/lib/opal/cli_runners/nodejs.rb +9 -2
- data/lib/opal/cli_runners/source-map-support-browser.js +80 -216
- data/lib/opal/cli_runners/source-map-support-node.js +80 -216
- data/lib/opal/cli_runners/source-map-support.js +5 -1
- data/lib/opal/cli_runners/system_runner.rb +10 -4
- data/lib/opal/compiler.rb +3 -5
- data/lib/opal/fragment.rb +5 -1
- data/lib/opal/nodes/args/extract_block_arg.rb +1 -8
- data/lib/opal/nodes/args/extract_kwoptarg.rb +1 -3
- data/lib/opal/nodes/args/extract_optarg.rb +1 -3
- data/lib/opal/nodes/args/extract_post_arg.rb +2 -5
- data/lib/opal/nodes/args/extract_post_optarg.rb +2 -7
- data/lib/opal/nodes/args/initialize_iterarg.rb +1 -3
- data/lib/opal/nodes/args/prepare_post_args.rb +5 -1
- data/lib/opal/nodes/base.rb +3 -2
- data/lib/opal/nodes/call.rb +20 -9
- data/lib/opal/nodes/call_special.rb +50 -0
- data/lib/opal/nodes/class.rb +24 -15
- data/lib/opal/nodes/constants.rb +23 -5
- data/lib/opal/nodes/def.rb +20 -23
- data/lib/opal/nodes/defined.rb +5 -5
- data/lib/opal/nodes/definitions.rb +2 -2
- data/lib/opal/nodes/defs.rb +2 -5
- data/lib/opal/nodes/helpers.rb +48 -18
- data/lib/opal/nodes/if.rb +109 -8
- data/lib/opal/nodes/iter.rb +23 -16
- data/lib/opal/nodes/literal.rb +18 -4
- data/lib/opal/nodes/logic.rb +2 -1
- data/lib/opal/nodes/masgn.rb +4 -9
- data/lib/opal/nodes/module.rb +29 -19
- data/lib/opal/nodes/node_with_args.rb +1 -7
- data/lib/opal/nodes/scope.rb +54 -15
- data/lib/opal/nodes/singleton_class.rb +5 -3
- data/lib/opal/nodes/super.rb +3 -3
- data/lib/opal/nodes/top.rb +34 -31
- data/lib/opal/nodes/variables.rb +2 -2
- data/lib/opal/nodes/x_string.rb +3 -0
- data/lib/opal/nodes.rb +0 -1
- data/lib/opal/parser/patch.rb +75 -0
- data/lib/opal/parser/with_ruby_lexer.rb +1 -1
- data/lib/opal/regexp_anchors.rb +7 -7
- data/lib/opal/requires.rb +19 -0
- data/lib/opal/rewriters/pattern_matching.rb +1 -1
- data/lib/opal/rewriters/returnable_logic.rb +102 -4
- data/lib/opal/util.rb +2 -2
- data/lib/opal/version.rb +1 -1
- data/lib/opal.rb +1 -17
- data/opal/corelib/array/pack.rb +11 -11
- data/opal/corelib/array.rb +193 -152
- data/opal/corelib/basic_object.rb +14 -14
- data/opal/corelib/binding.rb +7 -7
- data/opal/corelib/boolean.rb +12 -15
- data/opal/corelib/class.rb +23 -1
- data/opal/corelib/comparable.rb +8 -8
- data/opal/corelib/complex/base.rb +2 -2
- data/opal/corelib/complex.rb +79 -88
- data/opal/corelib/constants.rb +9 -9
- data/opal/corelib/dir.rb +4 -3
- data/opal/corelib/enumerable.rb +140 -127
- data/opal/corelib/enumerator/arithmetic_sequence.rb +177 -0
- data/opal/corelib/enumerator/chain.rb +42 -0
- data/opal/corelib/enumerator/generator.rb +35 -0
- data/opal/corelib/enumerator/lazy.rb +243 -0
- data/opal/corelib/enumerator/yielder.rb +36 -0
- data/opal/corelib/enumerator.rb +45 -300
- data/opal/corelib/error/errno.rb +47 -0
- data/opal/corelib/error.rb +62 -60
- data/opal/corelib/file.rb +26 -12
- data/opal/corelib/hash.rb +98 -107
- data/opal/corelib/helpers.rb +62 -13
- data/opal/corelib/io.rb +47 -34
- data/opal/corelib/kernel/format.rb +29 -29
- data/opal/corelib/kernel.rb +86 -83
- data/opal/corelib/main.rb +14 -12
- data/opal/corelib/marshal/read_buffer.rb +15 -15
- data/opal/corelib/marshal/write_buffer.rb +45 -44
- data/opal/corelib/marshal.rb +3 -3
- data/opal/corelib/math.rb +50 -50
- data/opal/corelib/method.rb +12 -8
- data/opal/corelib/module.rb +96 -79
- data/opal/corelib/nil.rb +9 -11
- data/opal/corelib/number.rb +113 -118
- data/opal/corelib/numeric.rb +37 -33
- data/opal/corelib/object_space.rb +11 -10
- data/opal/corelib/pack_unpack/format_string_parser.rb +3 -3
- data/opal/corelib/pattern_matching/base.rb +7 -7
- data/opal/corelib/pattern_matching.rb +1 -1
- data/opal/corelib/proc.rb +15 -16
- data/opal/corelib/process/base.rb +2 -2
- data/opal/corelib/process/status.rb +21 -0
- data/opal/corelib/process.rb +5 -5
- data/opal/corelib/random/formatter.rb +11 -11
- data/opal/corelib/random/math_random.js.rb +1 -1
- data/opal/corelib/random/mersenne_twister.rb +3 -3
- data/opal/corelib/random/seedrandom.js.rb +3 -3
- data/opal/corelib/random.rb +17 -17
- data/opal/corelib/range.rb +51 -35
- data/opal/corelib/rational/base.rb +4 -4
- data/opal/corelib/rational.rb +61 -62
- data/opal/corelib/regexp.rb +47 -38
- data/opal/corelib/runtime.js +245 -139
- data/opal/corelib/string/encoding.rb +21 -21
- data/opal/corelib/string/unpack.rb +19 -14
- data/opal/corelib/string.rb +135 -128
- data/opal/corelib/struct.rb +59 -46
- data/opal/corelib/time.rb +47 -57
- data/opal/corelib/trace_point.rb +2 -2
- data/opal/corelib/unsupported.rb +31 -120
- data/opal/corelib/variables.rb +3 -3
- data/opal/opal/base.rb +9 -8
- data/opal/opal/full.rb +8 -8
- data/opal/opal/mini.rb +17 -17
- data/opal/opal.rb +17 -18
- data/opal.gemspec +1 -1
- data/spec/filters/bugs/array.rb +4 -24
- data/spec/filters/bugs/bigdecimal.rb +0 -23
- data/spec/filters/bugs/binding.rb +0 -1
- data/spec/filters/bugs/boolean.rb +3 -0
- data/spec/filters/bugs/class.rb +2 -0
- data/spec/filters/bugs/date.rb +0 -5
- data/spec/filters/bugs/encoding.rb +8 -50
- data/spec/filters/bugs/enumerable.rb +4 -1
- data/spec/filters/bugs/enumerator.rb +3 -36
- data/spec/filters/bugs/exception.rb +0 -2
- data/spec/filters/bugs/file.rb +0 -2
- data/spec/filters/bugs/float.rb +0 -3
- data/spec/filters/bugs/hash.rb +5 -3
- data/spec/filters/bugs/integer.rb +2 -3
- data/spec/filters/bugs/kernel.rb +2 -31
- data/spec/filters/bugs/language.rb +29 -49
- data/spec/filters/bugs/main.rb +0 -2
- data/spec/filters/bugs/marshal.rb +2 -3
- data/spec/filters/bugs/matrix.rb +0 -36
- data/spec/filters/bugs/module.rb +7 -61
- data/spec/filters/bugs/numeric.rb +0 -7
- data/spec/filters/bugs/objectspace.rb +1 -1
- data/spec/filters/bugs/pack_unpack.rb +0 -4
- data/spec/filters/bugs/proc.rb +0 -9
- data/spec/filters/bugs/random.rb +0 -5
- data/spec/filters/bugs/range.rb +1 -6
- data/spec/filters/bugs/regexp.rb +0 -3
- data/spec/filters/bugs/set.rb +8 -1
- data/spec/filters/bugs/string.rb +9 -34
- data/spec/filters/bugs/stringscanner.rb +8 -7
- data/spec/filters/bugs/struct.rb +2 -3
- data/spec/filters/bugs/symbol.rb +0 -1
- data/spec/filters/bugs/time.rb +0 -8
- data/spec/filters/bugs/unboundmethod.rb +0 -8
- data/spec/filters/bugs/warnings.rb +1 -7
- data/spec/filters/unsupported/freeze.rb +24 -0
- data/spec/filters/unsupported/integer.rb +1 -0
- data/spec/filters/unsupported/kernel.rb +12 -0
- data/spec/filters/unsupported/privacy.rb +3 -0
- data/spec/filters/unsupported/string.rb +2 -0
- data/spec/lib/builder_spec.rb +2 -2
- data/spec/lib/cli_spec.rb +1 -1
- data/spec/lib/compiler_spec.rb +37 -37
- data/spec/lib/simple_server_spec.rb +2 -2
- data/spec/lib/source_map/file_spec.rb +1 -1
- data/spec/opal/compiler/irb_spec.rb +2 -2
- data/spec/opal/core/kernel/puts_spec.rb +90 -0
- data/spec/opal/core/language/super_spec.rb +24 -0
- data/spec/ruby_specs +4 -2
- data/spec/support/rewriters_helper.rb +1 -1
- data/stdlib/bigdecimal.rb +7 -11
- data/stdlib/buffer/view.rb +2 -2
- data/stdlib/buffer.rb +2 -2
- data/stdlib/date.rb +5 -6
- data/stdlib/erb.rb +1 -0
- data/stdlib/js.rb +2 -1
- data/stdlib/native.rb +7 -8
- data/stdlib/nodejs/argf.rb +4 -4
- data/stdlib/nodejs/base.rb +29 -0
- data/stdlib/nodejs/dir.rb +1 -1
- data/stdlib/nodejs/env.rb +6 -9
- data/stdlib/nodejs/file.rb +23 -17
- data/stdlib/nodejs/fileutils.rb +3 -3
- data/stdlib/nodejs/io.rb +2 -20
- data/stdlib/nodejs/irb.rb +0 -0
- data/stdlib/nodejs/kernel.rb +2 -37
- data/stdlib/nodejs.rb +1 -3
- data/stdlib/opal/miniracer.rb +2 -0
- data/stdlib/opal/platform.rb +6 -13
- data/stdlib/opal/replutils.rb +16 -5
- data/stdlib/opal-parser.rb +2 -2
- data/stdlib/optparse/ac.rb +54 -0
- data/stdlib/optparse/date.rb +14 -0
- data/stdlib/optparse/kwargs.rb +22 -0
- data/stdlib/optparse/shellwords.rb +7 -0
- data/stdlib/optparse/time.rb +15 -0
- data/stdlib/optparse/uri.rb +7 -0
- data/stdlib/optparse/version.rb +69 -0
- data/stdlib/optparse.rb +2279 -0
- data/stdlib/pathname.rb +5 -6
- data/stdlib/pp.rb +18 -2
- data/stdlib/promise/v2.rb +18 -22
- data/stdlib/promise.rb +15 -21
- data/stdlib/set.rb +32 -32
- data/stdlib/shellwords.rb +240 -0
- data/stdlib/stringio.rb +3 -6
- data/stdlib/strscan.rb +5 -8
- data/stdlib/template.rb +2 -2
- data/stdlib/thread.rb +7 -9
- data/tasks/performance.rake +5 -2
- data/tasks/testing/mspec_special_calls.rb +0 -12
- data/tasks/testing.rake +55 -37
- data/test/nodejs/test_file.rb +11 -0
- metadata +55 -10
- data/lib/opal/nodes/case.rb +0 -114
data/lib/opal/nodes/if.rb
CHANGED
@@ -10,10 +10,30 @@ module Opal
|
|
10
10
|
children :test, :true_body, :false_body
|
11
11
|
|
12
12
|
def compile
|
13
|
+
if should_compile_as_simple_expression?
|
14
|
+
if true_body == s(:true)
|
15
|
+
compile_with_binary_or
|
16
|
+
elsif false_body == s(:false)
|
17
|
+
compile_with_binary_and
|
18
|
+
else
|
19
|
+
compile_with_ternary
|
20
|
+
end
|
21
|
+
else
|
22
|
+
compile_with_if
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def compile_with_if
|
13
27
|
truthy = self.truthy
|
14
28
|
falsy = self.falsy
|
15
29
|
|
16
|
-
|
30
|
+
if falsy && !truthy
|
31
|
+
# Let's optimize a little bit `unless` calls.
|
32
|
+
push 'if (!', js_truthy(test), ') {'
|
33
|
+
falsy, truthy = truthy, falsy
|
34
|
+
else
|
35
|
+
push 'if (', js_truthy(test), ') {'
|
36
|
+
end
|
17
37
|
|
18
38
|
# skip if-body if no truthy sexp
|
19
39
|
indent { line stmt(truthy) } if truthy
|
@@ -30,29 +50,110 @@ module Opal
|
|
30
50
|
line '}'
|
31
51
|
end
|
32
52
|
else
|
33
|
-
|
53
|
+
line '}'
|
54
|
+
|
55
|
+
# This resolution isn't finite. Let's ensure this block
|
56
|
+
# always return something if we expect a return
|
57
|
+
line 'return nil;' if expects_expression?
|
34
58
|
end
|
35
59
|
|
36
|
-
if
|
60
|
+
if expects_expression?
|
37
61
|
if scope.await_encountered
|
38
|
-
wrap '(await (async function() {', '
|
62
|
+
wrap '(await (async function() {', '})())'
|
39
63
|
else
|
40
|
-
wrap '(function() {', '
|
64
|
+
wrap '(function() {', '})()'
|
41
65
|
end
|
42
66
|
end
|
43
67
|
end
|
44
68
|
|
45
69
|
def truthy
|
46
|
-
|
70
|
+
returnify(true_body)
|
47
71
|
end
|
48
72
|
|
49
73
|
def falsy
|
50
|
-
|
74
|
+
returnify(false_body)
|
75
|
+
end
|
76
|
+
|
77
|
+
def returnify(body)
|
78
|
+
if expects_expression? && body
|
79
|
+
compiler.returns(body)
|
80
|
+
else
|
81
|
+
body
|
82
|
+
end
|
51
83
|
end
|
52
84
|
|
53
|
-
def
|
85
|
+
def expects_expression?
|
54
86
|
expr? || recv?
|
55
87
|
end
|
88
|
+
|
89
|
+
# There was a particular case in the past, that when we
|
90
|
+
# expected an expression from if, we always had to closure
|
91
|
+
# it. This produced an ugly code that was hard to minify.
|
92
|
+
# This addition tries to make a few cases compiled with
|
93
|
+
# a ternary operator instead and possibly a binary operator
|
94
|
+
# even?
|
95
|
+
def should_compile_as_simple_expression?
|
96
|
+
expects_expression? && simple?(true_body) && simple?(false_body)
|
97
|
+
end
|
98
|
+
|
99
|
+
def compile_with_ternary
|
100
|
+
truthy = true_body
|
101
|
+
falsy = false_body
|
102
|
+
|
103
|
+
push '('
|
104
|
+
|
105
|
+
push js_truthy(test), ' ? '
|
106
|
+
|
107
|
+
push '(', expr(truthy || s(:nil)), ') : '
|
108
|
+
if !falsy || falsy.type == :if
|
109
|
+
push expr(falsy || s(:nil))
|
110
|
+
else
|
111
|
+
push '(', expr(falsy || s(:nil)), ')'
|
112
|
+
end
|
113
|
+
|
114
|
+
push ')'
|
115
|
+
end
|
116
|
+
|
117
|
+
def compile_with_binary_and
|
118
|
+
if sexp.meta[:do_js_truthy_on_true_body]
|
119
|
+
truthy = js_truthy(true_body || s(:nil))
|
120
|
+
else
|
121
|
+
truthy = expr(true_body || s(:nil))
|
122
|
+
end
|
123
|
+
|
124
|
+
push '('
|
125
|
+
push js_truthy(test), ' && '
|
126
|
+
push '(', truthy, ')'
|
127
|
+
push ')'
|
128
|
+
end
|
129
|
+
|
130
|
+
def compile_with_binary_or
|
131
|
+
if sexp.meta[:do_js_truthy_on_false_body]
|
132
|
+
falsy = js_truthy(false_body || s(:nil))
|
133
|
+
else
|
134
|
+
falsy = expr(false_body || s(:nil))
|
135
|
+
end
|
136
|
+
|
137
|
+
push '('
|
138
|
+
push js_truthy(test), ' || '
|
139
|
+
push '(', falsy, ')'
|
140
|
+
push ')'
|
141
|
+
end
|
142
|
+
|
143
|
+
# Let's ensure there are no control flow statements inside.
|
144
|
+
def simple?(body)
|
145
|
+
case body
|
146
|
+
when AST::Node
|
147
|
+
case body.type
|
148
|
+
when :return, :js_return, :break, :next, :redo, :retry
|
149
|
+
false
|
150
|
+
else
|
151
|
+
body.children.all? { |i| simple?(i) }
|
152
|
+
end
|
153
|
+
else
|
154
|
+
true
|
155
|
+
end
|
156
|
+
end
|
56
157
|
end
|
57
158
|
|
58
159
|
class IFlipFlop < Base
|
data/lib/opal/nodes/iter.rb
CHANGED
@@ -19,13 +19,15 @@ module Opal
|
|
19
19
|
|
20
20
|
in_scope do
|
21
21
|
identity = scope.identify!
|
22
|
-
add_temp "self = #{identity}.$$s == null ? this : #{identity}.$$s"
|
23
22
|
|
24
23
|
inline_params = process(inline_args)
|
25
24
|
|
26
25
|
compile_arity_check
|
27
26
|
|
28
27
|
body_code = stmt(returned_body)
|
28
|
+
|
29
|
+
add_temp "self = #{identity}.$$s == null ? this : #{identity}.$$s" if @define_self
|
30
|
+
|
29
31
|
to_vars = scope.to_vars
|
30
32
|
|
31
33
|
line body_code
|
@@ -40,16 +42,19 @@ module Opal
|
|
40
42
|
unshift to_vars
|
41
43
|
|
42
44
|
if await_encountered
|
43
|
-
unshift "
|
45
|
+
unshift "async function #{identity}(", inline_params, '){'
|
44
46
|
else
|
45
|
-
unshift "
|
47
|
+
unshift "function #{identity}(", inline_params, '){'
|
46
48
|
end
|
47
|
-
push
|
48
|
-
|
49
|
-
|
49
|
+
push '}'
|
50
|
+
|
51
|
+
blockopts = []
|
52
|
+
blockopts << "$$arity: #{arity}"
|
53
|
+
blockopts << "$$s: #{scope.self}" if @define_self
|
54
|
+
blockopts << "$$brk: $brk" if contains_break?
|
50
55
|
|
51
56
|
if compiler.arity_check?
|
52
|
-
|
57
|
+
blockopts << "$$parameters: #{parameters_code}"
|
53
58
|
end
|
54
59
|
|
55
60
|
# MRI expands a passed argument if the block:
|
@@ -61,24 +66,26 @@ module Opal
|
|
61
66
|
# This flag on the method indicates that a block has a top level mlhs argument
|
62
67
|
# which means that we have to expand passed array explicitly in runtime.
|
63
68
|
if has_top_level_mlhs_arg?
|
64
|
-
|
69
|
+
blockopts << "$$has_top_level_mlhs_arg: true"
|
65
70
|
end
|
66
71
|
|
67
72
|
if has_trailing_comma_in_args?
|
68
|
-
|
73
|
+
blockopts << "$$has_trailing_comma_in_args: true"
|
69
74
|
end
|
70
75
|
|
71
|
-
|
76
|
+
if blockopts.length == 1
|
77
|
+
push ", #{arity}"
|
78
|
+
elsif blockopts.length > 1
|
79
|
+
push ', {', blockopts.join(', '), '}'
|
80
|
+
end
|
81
|
+
|
82
|
+
scope.nesting if @define_nesting
|
83
|
+
scope.relative_access if @define_relative_access
|
72
84
|
end
|
73
85
|
|
74
86
|
def compile_block_arg
|
75
87
|
if block_arg
|
76
|
-
scope.
|
77
|
-
scope.add_temp block_arg
|
78
|
-
scope_name = scope.identify!
|
79
|
-
|
80
|
-
line "#{block_arg} = #{scope_name}.$$p || nil;"
|
81
|
-
line "if (#{block_arg}) #{scope_name}.$$p = null;"
|
88
|
+
scope.prepare_block
|
82
89
|
end
|
83
90
|
end
|
84
91
|
|
data/lib/opal/nodes/literal.rb
CHANGED
@@ -8,7 +8,11 @@ module Opal
|
|
8
8
|
handle :true, :false, :self, :nil
|
9
9
|
|
10
10
|
def compile
|
11
|
-
|
11
|
+
if type == :self
|
12
|
+
push scope.self
|
13
|
+
else
|
14
|
+
push type.to_s
|
15
|
+
end
|
12
16
|
end
|
13
17
|
|
14
18
|
def self.truthy_optimize?
|
@@ -137,7 +141,9 @@ module Opal
|
|
137
141
|
end
|
138
142
|
|
139
143
|
def compile_dynamic_regexp
|
140
|
-
|
144
|
+
helper :regexp
|
145
|
+
|
146
|
+
push '$regexp(['
|
141
147
|
value.children.each_with_index do |v, index|
|
142
148
|
push ', ' unless index.zero?
|
143
149
|
push expr(v)
|
@@ -229,10 +235,18 @@ module Opal
|
|
229
235
|
handle :dstr
|
230
236
|
|
231
237
|
def compile
|
232
|
-
|
238
|
+
if children.length > 1 && children.first.type == :str
|
239
|
+
skip_empty = true
|
240
|
+
else
|
241
|
+
push '""'
|
242
|
+
end
|
233
243
|
|
234
244
|
children.each do |part|
|
235
|
-
|
245
|
+
if skip_empty
|
246
|
+
skip_empty = false
|
247
|
+
else
|
248
|
+
push ' + '
|
249
|
+
end
|
236
250
|
|
237
251
|
if part.type == :str
|
238
252
|
push expr(part)
|
data/lib/opal/nodes/logic.rb
CHANGED
data/lib/opal/nodes/masgn.rb
CHANGED
@@ -18,17 +18,11 @@ module Opal
|
|
18
18
|
rhs_len = rhs.children.any? { |c| c.type == :splat } ? nil : rhs.children.size
|
19
19
|
compile_masgn(lhs.children, array, rhs_len)
|
20
20
|
push ", #{array}" # a mass assignment evaluates to the RHS
|
21
|
-
elsif rhs.type == :begin
|
22
|
-
retval = scope.new_temp
|
23
|
-
push "#{retval} = ", expr(rhs)
|
24
|
-
push ", #{array} = Opal.to_ary(#{retval})"
|
25
|
-
compile_masgn(lhs.children, array)
|
26
|
-
push ", #{retval}"
|
27
|
-
scope.queue_temp(retval)
|
28
21
|
else
|
22
|
+
helper :to_ary
|
29
23
|
retval = scope.new_temp
|
30
24
|
push "#{retval} = ", expr(rhs)
|
31
|
-
push ", #{array} =
|
25
|
+
push ", #{array} = $to_ary(#{retval})"
|
32
26
|
compile_masgn(lhs.children, array)
|
33
27
|
push ", #{retval}"
|
34
28
|
scope.queue_temp(retval)
|
@@ -97,9 +91,10 @@ module Opal
|
|
97
91
|
elsif child.type == :attrasgn
|
98
92
|
part.last << assign
|
99
93
|
elsif child.type == :mlhs
|
94
|
+
helper :to_ary
|
100
95
|
# nested destructuring
|
101
96
|
tmp = scope.new_temp
|
102
|
-
push ", (#{tmp} =
|
97
|
+
push ", (#{tmp} = $to_ary(#{assign.children[0]})"
|
103
98
|
compile_masgn(child.children, tmp)
|
104
99
|
push ')'
|
105
100
|
scope.queue_temp(tmp)
|
data/lib/opal/nodes/module.rb
CHANGED
@@ -13,23 +13,32 @@ module Opal
|
|
13
13
|
name, base = name_and_base
|
14
14
|
helper :module
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
await_begin = '(await '
|
24
|
-
await_end = ')'
|
25
|
-
async = 'async '
|
26
|
-
parent.await_encountered = true
|
16
|
+
if body.nil?
|
17
|
+
# Simplified compile for empty body
|
18
|
+
if stmt?
|
19
|
+
unshift '$module(', base, ", '#{name}')"
|
20
|
+
else
|
21
|
+
unshift '($module(', base, ", '#{name}'), nil)"
|
22
|
+
end
|
27
23
|
else
|
28
|
-
|
29
|
-
|
24
|
+
line " var self = $module($base, '#{name}');"
|
25
|
+
in_scope do
|
26
|
+
scope.name = name
|
27
|
+
compile_body
|
28
|
+
end
|
29
|
+
|
30
|
+
if await_encountered
|
31
|
+
await_begin = '(await '
|
32
|
+
await_end = ')'
|
33
|
+
async = 'async '
|
34
|
+
parent.await_encountered = true
|
35
|
+
else
|
36
|
+
await_begin, await_end, async = '', '', ''
|
37
|
+
end
|
30
38
|
|
31
|
-
|
32
|
-
|
39
|
+
unshift "#{await_begin}(#{async}function($base#{', $parent_nesting' if @define_nesting}) {"
|
40
|
+
line '})(', base, "#{', ' + scope.nesting if @define_nesting})#{await_end}"
|
41
|
+
end
|
33
42
|
end
|
34
43
|
|
35
44
|
private
|
@@ -39,18 +48,19 @@ module Opal
|
|
39
48
|
base, name = cid.children
|
40
49
|
|
41
50
|
if base.nil?
|
42
|
-
[name,
|
51
|
+
[name, "#{scope.nesting}[0]"]
|
43
52
|
else
|
44
53
|
[name, expr(base)]
|
45
54
|
end
|
46
55
|
end
|
47
56
|
|
48
57
|
def compile_body
|
49
|
-
|
50
|
-
|
51
|
-
body_code = stmt(compiler.returns(body || s(:nil)))
|
58
|
+
body_code = stmt(compiler.returns(body))
|
52
59
|
empty_line
|
53
60
|
|
61
|
+
add_temp "$nesting = [self].concat($parent_nesting)" if @define_nesting
|
62
|
+
add_temp '$$ = Opal.$r($nesting)' if @define_relative_access
|
63
|
+
|
54
64
|
line scope.to_vars
|
55
65
|
line body_code
|
56
66
|
end
|
@@ -29,13 +29,7 @@ module Opal
|
|
29
29
|
|
30
30
|
def compile_block_arg
|
31
31
|
if scope.uses_block?
|
32
|
-
|
33
|
-
yielder = scope.block_name || '$yield'
|
34
|
-
|
35
|
-
add_temp "$iter = #{scope_name}.$$p"
|
36
|
-
add_temp "#{yielder} = $iter || nil"
|
37
|
-
|
38
|
-
line "if ($iter) #{scope_name}.$$p = null;"
|
32
|
+
scope.prepare_block
|
39
33
|
end
|
40
34
|
end
|
41
35
|
|
data/lib/opal/nodes/scope.rb
CHANGED
@@ -88,11 +88,6 @@ module Opal
|
|
88
88
|
@type == :top
|
89
89
|
end
|
90
90
|
|
91
|
-
# Traverses to the top scope.
|
92
|
-
def top_scope
|
93
|
-
top? ? self : parent.top_scope
|
94
|
-
end
|
95
|
-
|
96
91
|
# True if a block/iter scope
|
97
92
|
def iter?
|
98
93
|
@type == :iter
|
@@ -141,19 +136,21 @@ module Opal
|
|
141
136
|
"if ($gvars#{gvar} == null) $gvars#{gvar} = nil;\n"
|
142
137
|
end
|
143
138
|
|
139
|
+
if class? && !@proto_ivars.empty?
|
140
|
+
vars << '$proto = self.$$prototype'
|
141
|
+
end
|
142
|
+
|
144
143
|
indent = @compiler.parser_indent
|
145
144
|
str = vars.empty? ? '' : "var #{vars.join ', '};\n"
|
146
145
|
str += "#{indent}#{iv.join indent}" unless ivars.empty?
|
147
146
|
str += "#{indent}#{gv.join indent}" unless gvars.empty?
|
148
147
|
|
149
148
|
if class? && !@proto_ivars.empty?
|
150
|
-
pvars = @proto_ivars.map { |i| "
|
151
|
-
|
152
|
-
else
|
153
|
-
result = str
|
149
|
+
pvars = @proto_ivars.map { |i| "$proto#{i}" }.join(' = ')
|
150
|
+
str = "#{str}\n#{indent}#{pvars} = nil;"
|
154
151
|
end
|
155
152
|
|
156
|
-
fragment(
|
153
|
+
fragment(str)
|
157
154
|
end
|
158
155
|
|
159
156
|
def add_scope_ivar(ivar)
|
@@ -190,7 +187,8 @@ module Opal
|
|
190
187
|
end
|
191
188
|
|
192
189
|
def scope_locals
|
193
|
-
@locals | @args | (@parent && @type == :iter ? @parent.scope_locals : [])
|
190
|
+
locals = @locals | @args | (@parent && @type == :iter ? @parent.scope_locals : [])
|
191
|
+
locals.reject { |i| i.to_s.start_with?('$') }
|
194
192
|
end
|
195
193
|
|
196
194
|
def add_scope_temp(tmp)
|
@@ -251,10 +249,21 @@ module Opal
|
|
251
249
|
def identify!(name = nil)
|
252
250
|
return @identity if @identity
|
253
251
|
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
252
|
+
if valid_name? mid
|
253
|
+
# There are some special utf8 chars that can be used as valid JS
|
254
|
+
# identifiers, some examples:
|
255
|
+
#
|
256
|
+
# utf8_pond = 'ⵌ'
|
257
|
+
# utf8_question = 'ʔ̣'
|
258
|
+
# utf8_exclamation 'ǃ'
|
259
|
+
#
|
260
|
+
# For now we're just using $$, to maintain compatibility with older IEs.
|
261
|
+
@identity = "$$#{mid}"
|
262
|
+
else
|
263
|
+
# Parent scope is the defining module/class
|
264
|
+
name ||= [(parent && (parent.name || parent.scope_name)), mid].compact.join('_')
|
265
|
+
@identity = @compiler.unique_temp(name)
|
266
|
+
end
|
258
267
|
|
259
268
|
@identity
|
260
269
|
end
|
@@ -371,6 +380,36 @@ module Opal
|
|
371
380
|
[prev, curr]
|
372
381
|
end
|
373
382
|
|
383
|
+
# Returns 'self', but also ensures that the self variable is set
|
384
|
+
def self
|
385
|
+
@define_self = true
|
386
|
+
'self'
|
387
|
+
end
|
388
|
+
|
389
|
+
# Returns '$nesting', but also ensures we compile the nesting chain
|
390
|
+
def nesting
|
391
|
+
@define_nesting = true
|
392
|
+
'$nesting'
|
393
|
+
end
|
394
|
+
|
395
|
+
# Returns '$$', but also ensures we compile it
|
396
|
+
def relative_access
|
397
|
+
@define_relative_access = @define_nesting = true
|
398
|
+
'$$'
|
399
|
+
end
|
400
|
+
|
401
|
+
def prepare_block(block_name = nil)
|
402
|
+
scope_name = scope.identity
|
403
|
+
self.block_name = block_name if block_name
|
404
|
+
|
405
|
+
add_temp "#{self.block_name} = #{scope_name}.$$p || nil"
|
406
|
+
|
407
|
+
unless @block_prepared
|
408
|
+
line "delete #{scope_name}.$$p;"
|
409
|
+
@block_prepared = true
|
410
|
+
end
|
411
|
+
end
|
412
|
+
|
374
413
|
attr_accessor :await_encountered
|
375
414
|
end
|
376
415
|
end
|
@@ -13,14 +13,16 @@ module Opal
|
|
13
13
|
push '(function(self, $parent_nesting) {'
|
14
14
|
|
15
15
|
in_scope do
|
16
|
-
add_temp '$nesting = [self].concat($parent_nesting)'
|
17
|
-
|
18
16
|
body_stmt = stmt(compiler.returns(body))
|
17
|
+
|
18
|
+
add_temp '$nesting = [self].concat($parent_nesting)' if @define_nesting
|
19
|
+
add_temp '$$ = Opal.$r($nesting)' if @define_relative_access
|
20
|
+
|
19
21
|
line scope.to_vars
|
20
22
|
line body_stmt
|
21
23
|
end
|
22
24
|
|
23
|
-
line '})(Opal.get_singleton_class(', recv(object),
|
25
|
+
line '})(Opal.get_singleton_class(', recv(object), "), #{scope.nesting})"
|
24
26
|
end
|
25
27
|
end
|
26
28
|
end
|
data/lib/opal/nodes/super.rb
CHANGED
@@ -70,14 +70,14 @@ module Opal
|
|
70
70
|
|
71
71
|
def super_method_invocation
|
72
72
|
helper :find_super
|
73
|
-
"$find_super(self, '#{method_id}', #{def_scope_identity}, #{defined_check_param}, #{allow_stubs})"
|
73
|
+
"$find_super(#{scope.self}, '#{method_id}', #{def_scope_identity}, #{defined_check_param}, #{allow_stubs})"
|
74
74
|
end
|
75
75
|
|
76
76
|
def super_block_invocation
|
77
77
|
helper :find_block_super
|
78
78
|
chain, cur_defn, mid = scope.super_chain
|
79
79
|
trys = chain.map { |c| "#{c}.$$def" }.join(' || ')
|
80
|
-
"$find_block_super(self, #{mid}, (#{trys} || #{cur_defn}), #{defined_check_param}, #{implicit_arguments_param})"
|
80
|
+
"$find_block_super(#{scope.self}, #{mid}, (#{trys} || #{cur_defn}), #{defined_check_param}, #{implicit_arguments_param})"
|
81
81
|
end
|
82
82
|
|
83
83
|
def compile_method_body
|
@@ -153,7 +153,7 @@ module Opal
|
|
153
153
|
unless iter.type == :iter
|
154
154
|
# Need to support passing block up even if it's not referenced in this method at all
|
155
155
|
scope.uses_block!
|
156
|
-
@iter = s(:js_tmp, '$
|
156
|
+
@iter = s(:js_tmp, scope.block_name || '$yield')
|
157
157
|
end
|
158
158
|
end
|
159
159
|
|
data/lib/opal/nodes/top.rb
CHANGED
@@ -13,33 +13,40 @@ module Opal
|
|
13
13
|
children :body
|
14
14
|
|
15
15
|
def compile
|
16
|
+
compiler.top_scope = self
|
17
|
+
|
16
18
|
push version_comment
|
17
19
|
|
18
20
|
in_scope do
|
19
|
-
|
21
|
+
if body == s(:nil)
|
22
|
+
# A shortpath for empty (stub?) modules.
|
23
|
+
line 'return Opal.nil;'
|
24
|
+
else
|
25
|
+
line '"use strict";' if compiler.use_strict?
|
20
26
|
|
21
|
-
|
22
|
-
|
27
|
+
body_code = stmt(stmts)
|
28
|
+
body_code = [body_code] unless body_code.is_a?(Array)
|
23
29
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
30
|
+
if compiler.eval?
|
31
|
+
add_temp '$nesting = self.$$is_a_module ? [self] : [self.$$class]' if @define_nesting
|
32
|
+
else
|
33
|
+
add_temp 'self = Opal.top' if @define_self
|
34
|
+
add_temp '$nesting = []' if @define_nesting
|
35
|
+
end
|
36
|
+
add_temp '$$ = Opal.$r($nesting)' if @define_relative_access
|
37
|
+
|
38
|
+
add_temp 'nil = Opal.nil'
|
39
|
+
add_temp '$$$ = Opal.$$$' if @define_absolute_const
|
33
40
|
|
34
|
-
|
35
|
-
|
36
|
-
line scope.to_vars
|
41
|
+
add_used_helpers
|
42
|
+
line scope.to_vars
|
37
43
|
|
38
|
-
|
39
|
-
|
40
|
-
|
44
|
+
compile_method_stubs
|
45
|
+
compile_irb_vars
|
46
|
+
compile_end_construct
|
41
47
|
|
42
|
-
|
48
|
+
line body_code
|
49
|
+
end
|
43
50
|
end
|
44
51
|
opening
|
45
52
|
closing
|
@@ -73,6 +80,12 @@ module Opal
|
|
73
80
|
compiler.returns(body)
|
74
81
|
end
|
75
82
|
|
83
|
+
# Returns '$$$', but also ensures that the '$$$' variable is set
|
84
|
+
def absolute_const
|
85
|
+
@define_absolute_const = true
|
86
|
+
'$$$'
|
87
|
+
end
|
88
|
+
|
76
89
|
def compile_irb_vars
|
77
90
|
if compiler.irb?
|
78
91
|
line 'if (!Opal.irb_vars) { Opal.irb_vars = {}; }'
|
@@ -83,21 +96,11 @@ module Opal
|
|
83
96
|
compiler.helpers.to_a.each { |h| add_temp "$#{h} = Opal.#{h}" }
|
84
97
|
end
|
85
98
|
|
86
|
-
def add_used_operators
|
87
|
-
operators = compiler.operator_helpers.to_a
|
88
|
-
operators.each do |op|
|
89
|
-
name = Nodes::CallNode::OPERATORS[op]
|
90
|
-
line "function $rb_#{name}(lhs, rhs) {"
|
91
|
-
line " return (typeof(lhs) === 'number' && typeof(rhs) === 'number') ? lhs #{op} rhs : lhs['$#{op}'](rhs);"
|
92
|
-
line '}'
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
99
|
def compile_method_stubs
|
97
100
|
if compiler.method_missing?
|
98
101
|
calls = compiler.method_calls
|
99
|
-
stubs = calls.to_a.map
|
100
|
-
line "Opal.add_stubs(
|
102
|
+
stubs = calls.to_a.map(&:to_s).join(',')
|
103
|
+
line "Opal.add_stubs('#{stubs}');" unless stubs.empty?
|
101
104
|
end
|
102
105
|
end
|
103
106
|
|
data/lib/opal/nodes/variables.rb
CHANGED
@@ -70,7 +70,7 @@ module Opal
|
|
70
70
|
def compile
|
71
71
|
name = property(var_name)
|
72
72
|
add_ivar name
|
73
|
-
push "self#{name}"
|
73
|
+
push "#{scope.self}#{name}"
|
74
74
|
end
|
75
75
|
end
|
76
76
|
|
@@ -85,7 +85,7 @@ module Opal
|
|
85
85
|
|
86
86
|
def compile
|
87
87
|
name = property(var_name)
|
88
|
-
push "self#{name} = "
|
88
|
+
push "#{scope.self}#{name} = "
|
89
89
|
push expr(value)
|
90
90
|
|
91
91
|
wrap '(', ')' if (recv? || expr?) && value
|