opal 0.9.4 → 0.10.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitattributes +1 -0
- data/.gitignore +2 -3
- data/.gitmodules +5 -2
- data/.jshintrc +1 -8
- data/.rspec +1 -1
- data/.travis.yml +15 -23
- data/CHANGELOG.md +511 -326
- data/CODE_OF_CONDUCT.md +13 -15
- data/CONTRIBUTING.md +26 -216
- data/Gemfile +20 -12
- data/Guardfile +2 -2
- data/HACKING.md +230 -0
- data/README.md +6 -7
- data/bin/opal-mspec +1 -1
- data/config.ru +2 -2
- data/docs/faq.md +1 -1
- data/docs/source_maps.md +1 -1
- data/lib/opal.rb +1 -0
- data/lib/opal/builder.rb +1 -1
- data/lib/opal/cli.rb +30 -28
- data/lib/opal/cli_options.rb +3 -0
- data/lib/opal/cli_runners.rb +14 -1
- data/lib/opal/cli_runners/{apple_script.rb → applescript.rb} +3 -3
- data/lib/opal/cli_runners/nashorn.rb +2 -2
- data/lib/opal/cli_runners/nodejs.rb +2 -2
- data/lib/opal/cli_runners/phantom.js +24 -0
- data/lib/opal/cli_runners/phantomjs.rb +10 -10
- data/lib/opal/cli_runners/server.rb +3 -3
- data/lib/opal/compiler.rb +43 -4
- data/lib/opal/config.rb +3 -1
- data/lib/opal/errors.rb +13 -0
- data/lib/opal/fragment.rb +0 -13
- data/lib/opal/nodes.rb +10 -0
- data/lib/opal/nodes/args/initialize_kwargs.rb +28 -0
- data/lib/opal/nodes/args/kwarg.rb +29 -0
- data/lib/opal/nodes/args/kwoptarg.rb +29 -0
- data/lib/opal/nodes/args/kwrestarg.rb +39 -0
- data/lib/opal/nodes/args/mlhsarg.rb +79 -0
- data/lib/opal/nodes/args/normarg.rb +26 -0
- data/lib/opal/nodes/args/optarg.rb +27 -0
- data/lib/opal/nodes/args/post_args.rb +200 -0
- data/lib/opal/nodes/args/post_kwargs.rb +31 -0
- data/lib/opal/nodes/args/restarg.rb +33 -0
- data/lib/opal/nodes/base.rb +12 -0
- data/lib/opal/nodes/call.rb +92 -33
- data/lib/opal/nodes/def.rb +26 -169
- data/lib/opal/nodes/hash.rb +10 -4
- data/lib/opal/nodes/helpers.rb +6 -3
- data/lib/opal/nodes/inline_args.rb +61 -0
- data/lib/opal/nodes/iter.rb +73 -82
- data/lib/opal/nodes/logic.rb +12 -2
- data/lib/opal/nodes/masgn.rb +1 -2
- data/lib/opal/nodes/node_with_args.rb +141 -0
- data/lib/opal/nodes/rescue.rb +121 -43
- data/lib/opal/nodes/scope.rb +24 -5
- data/lib/opal/nodes/super.rb +122 -54
- data/lib/opal/nodes/top.rb +0 -12
- data/lib/opal/nodes/yield.rb +2 -13
- data/lib/opal/parser.rb +67 -39
- data/lib/opal/parser/grammar.rb +3319 -2961
- data/lib/opal/parser/grammar.y +234 -46
- data/lib/opal/parser/lexer.rb +105 -17
- data/lib/opal/parser/sexp.rb +4 -0
- data/lib/opal/paths.rb +4 -0
- data/lib/opal/regexp_anchors.rb +19 -1
- data/lib/opal/sprockets.rb +21 -18
- data/lib/opal/sprockets/environment.rb +0 -8
- data/lib/opal/sprockets/processor.rb +13 -16
- data/lib/opal/sprockets/server.rb +6 -12
- data/lib/opal/version.rb +1 -1
- data/opal.gemspec +1 -0
- data/opal/corelib/array.rb +209 -131
- data/opal/corelib/basic_object.rb +7 -3
- data/opal/corelib/class.rb +11 -17
- data/opal/corelib/constants.rb +2 -2
- data/opal/corelib/enumerable.rb +178 -355
- data/opal/corelib/enumerator.rb +3 -46
- data/opal/corelib/error.rb +2 -2
- data/opal/corelib/file.rb +13 -1
- data/opal/corelib/hash.rb +26 -56
- data/opal/corelib/helpers.rb +10 -0
- data/opal/corelib/kernel.rb +6 -3
- data/opal/corelib/module.rb +62 -31
- data/opal/corelib/number.rb +7 -16
- data/opal/corelib/proc.rb +24 -9
- data/opal/corelib/range.rb +4 -13
- data/opal/corelib/runtime.js +515 -378
- data/opal/corelib/string.rb +21 -49
- data/opal/corelib/struct.rb +50 -35
- data/opal/corelib/unsupported.rb +18 -30
- data/opal/opal.rb +0 -1
- data/opal/opal/mini.rb +1 -0
- data/spec/README.md +6 -4
- data/spec/filters/bugs/array.rb +0 -42
- data/spec/filters/bugs/basicobject.rb +0 -2
- data/spec/filters/bugs/bigdecimal.rb +160 -0
- data/spec/filters/bugs/class.rb +0 -5
- data/spec/filters/bugs/date.rb +1 -48
- data/spec/filters/bugs/enumerable.rb +4 -12
- data/spec/filters/bugs/enumerator.rb +0 -1
- data/spec/filters/bugs/exception.rb +4 -3
- data/spec/filters/bugs/float.rb +4 -2
- data/spec/filters/bugs/kernel.rb +25 -10
- data/spec/filters/bugs/language.rb +119 -68
- data/spec/filters/bugs/method.rb +135 -0
- data/spec/filters/bugs/module.rb +13 -28
- data/spec/filters/bugs/proc.rb +18 -8
- data/spec/filters/bugs/range.rb +0 -3
- data/spec/filters/bugs/rational.rb +4 -0
- data/spec/filters/bugs/regexp.rb +68 -36
- data/spec/filters/bugs/string.rb +1 -1
- data/spec/filters/bugs/struct.rb +0 -12
- data/spec/filters/bugs/time.rb +1 -0
- data/spec/filters/bugs/unboundmethod.rb +2 -1
- data/spec/filters/unsupported/freeze.rb +3 -1
- data/spec/filters/unsupported/language.rb +0 -7
- data/spec/filters/unsupported/privacy.rb +7 -6
- data/spec/filters/unsupported/string.rb +10 -0
- data/spec/filters/unsupported/struct.rb +3 -0
- data/spec/filters/unsupported/symbol.rb +9 -0
- data/spec/filters/unsupported/taint.rb +0 -3
- data/spec/filters/unsupported/thread.rb +1 -0
- data/spec/lib/cli_runners/phantomjs_spec.rb +39 -0
- data/spec/lib/cli_spec.rb +42 -1
- data/spec/lib/compiler/call_spec.rb +700 -0
- data/spec/lib/compiler_spec.rb +46 -28
- data/spec/lib/config_spec.rb +13 -0
- data/spec/lib/parser/call_spec.rb +18 -0
- data/spec/lib/parser/def_spec.rb +29 -0
- data/spec/lib/parser/iter_spec.rb +15 -15
- data/spec/lib/parser/lambda_spec.rb +153 -12
- data/spec/lib/parser/string_spec.rb +5 -0
- data/spec/lib/parser/undef_spec.rb +1 -1
- data/spec/lib/parser/variables_spec.rb +24 -0
- data/spec/lib/paths_spec.rb +12 -5
- data/spec/lib/spec_helper.rb +5 -0
- data/spec/lib/sprockets/processor_spec.rb +6 -5
- data/spec/lib/sprockets_spec.rb +8 -0
- data/spec/mspec-opal/formatters.rb +188 -0
- data/spec/mspec-opal/runner.rb +193 -0
- data/spec/opal/core/enumerator/with_index_spec.rb +6 -0
- data/spec/opal/core/kernel/define_singleton_method_spec.rb +1 -1
- data/spec/opal/core/kernel/instance_variables_spec.rb +14 -0
- data/spec/opal/core/kernel/loop_spec.rb +1 -1
- data/spec/opal/core/kernel/raise_spec.rb +1 -1
- data/spec/opal/core/language/heredoc_spec.rb +42 -0
- data/spec/opal/core/language/rescue_spec.rb +18 -0
- data/spec/opal/core/language_spec.rb +22 -0
- data/spec/opal/core/module/const_defined_spec.rb +1 -2
- data/spec/opal/core/module/name_spec.rb +6 -0
- data/spec/opal/core/runtime/bridged_classes_spec.rb +14 -2
- data/spec/opal/core/runtime/rescue_spec.rb +12 -2
- data/spec/opal/core/runtime/super_spec.rb +1 -0
- data/spec/opal/core/string_spec.rb +21 -0
- data/spec/opal/stdlib/js_spec.rb +1 -1
- data/spec/opal/stdlib/native/hash_spec.rb +7 -0
- data/spec/opal/stdlib/promise/always_spec.rb +24 -5
- data/spec/opal/stdlib/promise/rescue_spec.rb +15 -6
- data/spec/opal/stdlib/promise/then_spec.rb +13 -5
- data/spec/opal/stdlib/promise/trace_spec.rb +5 -6
- data/spec/opal/stdlib/strscan/scan_spec.rb +1 -1
- data/spec/ruby_specs +122 -0
- data/spec/spec_helper.rb +3 -15
- data/stdlib/base64.rb +51 -121
- data/stdlib/bigdecimal.rb +231 -0
- data/stdlib/bigdecimal/bignumber.js.rb +11 -0
- data/stdlib/bigdecimal/kernel.rb +5 -0
- data/stdlib/date.rb +252 -10
- data/stdlib/native.rb +38 -38
- data/stdlib/nodejs/dir.rb +8 -6
- data/stdlib/nodejs/file.rb +28 -3
- data/stdlib/nodejs/node_modules/.bin/js-yaml +1 -0
- data/stdlib/nodejs/node_modules/js-yaml/node_modules/.bin/esparse +1 -0
- data/stdlib/nodejs/node_modules/js-yaml/node_modules/.bin/esvalidate +1 -0
- data/stdlib/nodejs/require.rb +1 -1
- data/stdlib/nodejs/yaml.rb +3 -2
- data/stdlib/opal-parser.rb +7 -2
- data/stdlib/pathname.rb +23 -1
- data/stdlib/phantomjs.rb +10 -0
- data/stdlib/promise.rb +38 -23
- data/tasks/building.rake +3 -3
- data/tasks/testing.rake +27 -14
- data/tasks/testing/mspec_special_calls.rb +1 -1
- data/tasks/testing/sprockets-phantomjs.js +4 -0
- data/test/opal/test_keyword.rb +110 -110
- data/test/opal/unsupported_and_bugs.rb +30 -0
- data/vendored-minitest/minitest/assertions.rb +1 -1
- metadata +65 -15
- data/.spectator +0 -2
- data/.spectator-mspec +0 -3
- data/opal/corelib/array/inheritance.rb +0 -127
- data/spec/rubyspecs +0 -139
data/lib/opal/nodes/rescue.rb
CHANGED
@@ -16,7 +16,13 @@ module Opal
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def compile
|
19
|
-
|
19
|
+
line "try {", expr(body), " } catch ($err) { "
|
20
|
+
|
21
|
+
indent do
|
22
|
+
line "if (Opal.rescue($err, [", expr(Sexp.new([:const, :StandardError])), "])) {"
|
23
|
+
line expr(rescue_val)
|
24
|
+
line "} else { throw $err; } }"
|
25
|
+
end
|
20
26
|
|
21
27
|
wrap '(function() {', '})()' unless stmt?
|
22
28
|
end
|
@@ -29,16 +35,56 @@ module Opal
|
|
29
35
|
|
30
36
|
def compile
|
31
37
|
push "try {"
|
32
|
-
|
38
|
+
|
39
|
+
in_ensure do
|
40
|
+
line compiler.process(body_sexp, @level)
|
41
|
+
end
|
42
|
+
|
33
43
|
line "} finally {"
|
34
|
-
|
44
|
+
|
45
|
+
indent do
|
46
|
+
if has_rescue_else?
|
47
|
+
# $no_errors indicates thate there were no error raised
|
48
|
+
unshift "var $no_errors = true; "
|
49
|
+
|
50
|
+
# when there's a begin;rescue;else;ensure;end statement,
|
51
|
+
# ruby returns a result of the 'else' branch
|
52
|
+
# but invokes it before 'ensure'.
|
53
|
+
# so, here we
|
54
|
+
# 1. save the result of calling else to $rescue_else_result
|
55
|
+
# 2. call ensure
|
56
|
+
# 2. return $rescue_else_result
|
57
|
+
line "var $rescue_else_result;"
|
58
|
+
line "if ($no_errors) { "
|
59
|
+
indent do
|
60
|
+
line "$rescue_else_result = (function() {"
|
61
|
+
indent do
|
62
|
+
line compiler.process(compiler.returns(scope.rescue_else_sexp), @level)
|
63
|
+
end
|
64
|
+
line "})();"
|
65
|
+
end
|
66
|
+
line "}"
|
67
|
+
line compiler.process(ensr_sexp, @level)
|
68
|
+
line "if ($no_errors) { return $rescue_else_result; }"
|
69
|
+
else
|
70
|
+
line compiler.process(ensr_sexp, @level)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
35
74
|
line "}"
|
36
75
|
|
37
|
-
wrap '(function() {', '; })()' if wrap_in_closure?
|
76
|
+
wrap '(function() { ', '; })()' if wrap_in_closure?
|
38
77
|
end
|
39
78
|
|
40
79
|
def body_sexp
|
41
|
-
wrap_in_closure?
|
80
|
+
if wrap_in_closure?
|
81
|
+
sexp = compiler.returns(begn)
|
82
|
+
# 'rescue' is an edge case that should be compiled to
|
83
|
+
# try { return function(){ ..rescue through try/catch.. }() }
|
84
|
+
sexp.type == :rescue ? s(:js_return, sexp) : sexp
|
85
|
+
else
|
86
|
+
sexp = begn
|
87
|
+
end
|
42
88
|
end
|
43
89
|
|
44
90
|
def ensr_sexp
|
@@ -46,7 +92,7 @@ module Opal
|
|
46
92
|
end
|
47
93
|
|
48
94
|
def wrap_in_closure?
|
49
|
-
recv? or expr?
|
95
|
+
recv? or expr? or has_rescue_else?
|
50
96
|
end
|
51
97
|
end
|
52
98
|
|
@@ -56,37 +102,74 @@ module Opal
|
|
56
102
|
children :body
|
57
103
|
|
58
104
|
def compile
|
59
|
-
|
105
|
+
scope.rescue_else_sexp = children[1..-1].detect { |sexp| sexp.type != :resbody }
|
106
|
+
has_rescue_handlers = false
|
107
|
+
|
108
|
+
if handle_rescue_else_manually?
|
109
|
+
line "var $no_errors = true;"
|
110
|
+
end
|
60
111
|
|
61
112
|
push "try {"
|
62
|
-
|
113
|
+
indent do
|
114
|
+
line process(body_code, @level)
|
115
|
+
end
|
63
116
|
line "} catch ($err) {"
|
64
117
|
|
65
|
-
|
66
|
-
|
118
|
+
indent do
|
119
|
+
if has_rescue_else?
|
120
|
+
line "$no_errors = false;"
|
121
|
+
end
|
67
122
|
|
68
|
-
|
69
|
-
|
70
|
-
|
123
|
+
children[1..-1].each_with_index do |child, idx|
|
124
|
+
# counting only rescue, ignoring rescue-else statement
|
125
|
+
if child.type == :resbody
|
126
|
+
has_rescue_handlers = true
|
71
127
|
|
72
|
-
|
73
|
-
|
74
|
-
|
128
|
+
push " else " unless idx == 0
|
129
|
+
line process(child, @level)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
# if no resbodys capture our error, then rethrow
|
134
|
+
push " else { throw $err; }"
|
75
135
|
end
|
76
136
|
|
77
137
|
line "}"
|
78
138
|
|
79
|
-
|
139
|
+
if handle_rescue_else_manually?
|
140
|
+
# here we must add 'finally' explicitly
|
141
|
+
push "finally {"
|
142
|
+
indent do
|
143
|
+
line "if ($no_errors) { "
|
144
|
+
indent do
|
145
|
+
line "return (function() {"
|
146
|
+
indent do
|
147
|
+
line compiler.process(compiler.returns(scope.rescue_else_sexp), @level)
|
148
|
+
end
|
149
|
+
line "})();"
|
150
|
+
end
|
151
|
+
line "}"
|
152
|
+
end
|
153
|
+
push "}"
|
154
|
+
end
|
155
|
+
|
156
|
+
# Wrap a try{} catch{} into a function
|
157
|
+
# when it's an expression
|
158
|
+
# or when there's a method call after begin;rescue;end
|
159
|
+
wrap '(function() { ', '})()' if expr? or recv?
|
80
160
|
end
|
81
161
|
|
82
162
|
def body_code
|
83
163
|
body_code = (body.type == :resbody ? s(:nil) : body)
|
164
|
+
body_code = compiler.returns body_code unless stmt?
|
165
|
+
body_code
|
166
|
+
end
|
84
167
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
168
|
+
# Returns true when there's no 'ensure' statement
|
169
|
+
# wrapping current rescue.
|
170
|
+
#
|
171
|
+
def handle_rescue_else_manually?
|
172
|
+
!scope.in_ensure? && scope.has_rescue_else?
|
90
173
|
end
|
91
174
|
end
|
92
175
|
|
@@ -96,36 +179,31 @@ module Opal
|
|
96
179
|
children :args, :body
|
97
180
|
|
98
181
|
def compile
|
99
|
-
push "if ("
|
182
|
+
push "if (Opal.rescue($err, ["
|
100
183
|
if rescue_exprs.empty?
|
101
|
-
# if no expressions are given, then catch
|
102
|
-
push
|
184
|
+
# if no expressions are given, then catch StandardError only
|
185
|
+
push expr(Sexp.new([:const, :StandardError]))
|
103
186
|
else
|
104
|
-
push "Opal.rescue($err, ["
|
105
187
|
rescue_exprs.each_with_index do |rexpr, idx|
|
106
188
|
push ', ' unless idx == 0
|
107
189
|
push expr(rexpr)
|
108
190
|
end
|
109
|
-
push "])"
|
110
191
|
end
|
111
|
-
push ") {"
|
112
|
-
|
113
|
-
if variable = rescue_variable
|
114
|
-
variable[2] = s(:js_tmp, '$err')
|
115
|
-
push expr(variable), ';'
|
116
|
-
end
|
117
|
-
|
118
|
-
# Need to ensure we clear the current exception out after the rescue block ends
|
119
|
-
line "try {"
|
120
|
-
indent do
|
121
|
-
line process(rescue_body, @level)
|
122
|
-
end
|
123
|
-
line "} finally {"
|
192
|
+
push "])) {"
|
124
193
|
indent do
|
125
|
-
|
194
|
+
if variable = rescue_variable
|
195
|
+
variable[2] = s(:js_tmp, '$err')
|
196
|
+
push expr(variable), ';'
|
197
|
+
end
|
198
|
+
|
199
|
+
# Need to ensure we clear the current exception out after the rescue block ends
|
200
|
+
line "try {"
|
201
|
+
indent do
|
202
|
+
line process(rescue_body, @level)
|
203
|
+
end
|
204
|
+
line '} finally { Opal.pop_exception() }'
|
126
205
|
end
|
127
206
|
line "}"
|
128
|
-
line "}"
|
129
207
|
end
|
130
208
|
|
131
209
|
def rescue_variable?(variable)
|
@@ -144,7 +222,7 @@ module Opal
|
|
144
222
|
|
145
223
|
def rescue_body
|
146
224
|
body_code = (body || s(:nil))
|
147
|
-
body_code = compiler.returns(body_code)
|
225
|
+
body_code = compiler.returns(body_code) unless stmt?
|
148
226
|
body_code
|
149
227
|
end
|
150
228
|
end
|
data/lib/opal/nodes/scope.rb
CHANGED
@@ -30,7 +30,9 @@ module Opal
|
|
30
30
|
attr_accessor :uses_super
|
31
31
|
attr_accessor :uses_zuper
|
32
32
|
|
33
|
-
attr_accessor :catch_return
|
33
|
+
attr_accessor :catch_return, :has_break
|
34
|
+
|
35
|
+
attr_accessor :rescue_else_sexp
|
34
36
|
|
35
37
|
def initialize(*)
|
36
38
|
super
|
@@ -169,14 +171,15 @@ module Opal
|
|
169
171
|
end
|
170
172
|
|
171
173
|
def has_local?(local)
|
172
|
-
return true if @locals.include? local or @args.include? local
|
174
|
+
return true if @locals.include? local or @args.include? local or @temps.include? local
|
173
175
|
return @parent.has_local?(local) if @parent and @type == :iter
|
174
|
-
|
175
176
|
false
|
176
177
|
end
|
177
178
|
|
178
|
-
def add_scope_temp(
|
179
|
-
|
179
|
+
def add_scope_temp(tmp)
|
180
|
+
return if has_temp?(tmp)
|
181
|
+
|
182
|
+
@temps.push(tmp)
|
180
183
|
end
|
181
184
|
|
182
185
|
def has_temp?(tmp)
|
@@ -277,6 +280,22 @@ module Opal
|
|
277
280
|
def uses_block?
|
278
281
|
@uses_block
|
279
282
|
end
|
283
|
+
|
284
|
+
def has_rescue_else?
|
285
|
+
!!rescue_else_sexp
|
286
|
+
end
|
287
|
+
|
288
|
+
def in_ensure
|
289
|
+
return unless block_given?
|
290
|
+
|
291
|
+
@in_ensure = true
|
292
|
+
result = yield
|
293
|
+
@in_ensure = false
|
294
|
+
end
|
295
|
+
|
296
|
+
def in_ensure?
|
297
|
+
!!@in_ensure
|
298
|
+
end
|
280
299
|
end
|
281
300
|
end
|
282
301
|
end
|
data/lib/opal/nodes/super.rb
CHANGED
@@ -5,92 +5,160 @@ module Opal
|
|
5
5
|
# This base class is used just to child the find_super_dispatcher method
|
6
6
|
# body. This is then used by actual super calls, or a defined?(super) style
|
7
7
|
# call.
|
8
|
-
class BaseSuperNode <
|
9
|
-
children :arglist, :
|
8
|
+
class BaseSuperNode < CallNode
|
9
|
+
children :arglist, :raw_iter
|
10
10
|
|
11
|
-
def
|
12
|
-
if arglist or iter
|
13
|
-
iter = expr(iter_sexp)
|
14
|
-
else
|
15
|
-
scope.uses_block!
|
16
|
-
iter = '$iter'
|
17
|
-
end
|
11
|
+
def compile
|
18
12
|
if scope.def?
|
19
13
|
scope.uses_block!
|
20
|
-
|
21
|
-
|
14
|
+
end
|
15
|
+
|
16
|
+
default_compile
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
# always on self
|
22
|
+
def recvr
|
23
|
+
s(:self)
|
24
|
+
end
|
22
25
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
26
|
+
def iter
|
27
|
+
# Need to support passing block up even if it's not referenced in this method at all
|
28
|
+
@iter ||= begin
|
29
|
+
if raw_iter
|
30
|
+
raw_iter
|
31
|
+
elsif arglist # TODO: Better understand this elsif vs. the else code path
|
32
|
+
s(:js_tmp, 'null')
|
27
33
|
else
|
28
|
-
|
29
|
-
|
30
|
-
push ")"
|
34
|
+
scope.uses_block!
|
35
|
+
s(:js_tmp, '$iter')
|
31
36
|
end
|
32
|
-
|
33
|
-
|
34
|
-
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def method_jsid
|
41
|
+
raise 'Not implemented, see #add_method'
|
42
|
+
end
|
43
|
+
|
44
|
+
# Need a way to pass self into the method invocation
|
45
|
+
def redefine_this?(temporary_receiver)
|
46
|
+
true
|
47
|
+
end
|
48
|
+
|
49
|
+
def arguments_array?
|
50
|
+
# zuper is an implicit super argument array
|
51
|
+
super || @implicit_args
|
52
|
+
end
|
53
|
+
|
54
|
+
def containing_def_scope
|
55
|
+
return scope if scope.def?
|
56
|
+
|
57
|
+
# using super in a block inside a method is allowed, e.g.
|
58
|
+
# def a
|
59
|
+
# { super }
|
60
|
+
# end
|
61
|
+
scope.find_parent_def
|
62
|
+
end
|
63
|
+
|
64
|
+
def defined_check_param
|
65
|
+
'false'
|
66
|
+
end
|
35
67
|
|
36
|
-
|
68
|
+
def implicit_arguments_param
|
69
|
+
@implicit_args ? 'true' : 'false'
|
70
|
+
end
|
71
|
+
|
72
|
+
def super_method_invocation
|
73
|
+
def_scope = containing_def_scope
|
74
|
+
method_jsid = def_scope.mid.to_s
|
75
|
+
current_func = def_scope.identify!
|
76
|
+
|
77
|
+
if def_scope.defs
|
78
|
+
class_name = def_scope.parent.name ? "$#{def_scope.parent.name}" : 'self.$$class.$$proto'
|
79
|
+
"Opal.find_super_dispatcher(self, '#{method_jsid}', #{current_func}, #{defined_check_param}, #{class_name})"
|
37
80
|
else
|
38
|
-
|
81
|
+
"Opal.find_super_dispatcher(self, '#{method_jsid}', #{current_func}, #{defined_check_param})"
|
39
82
|
end
|
40
83
|
end
|
41
84
|
|
42
|
-
def
|
43
|
-
|
85
|
+
def super_block_invocation
|
86
|
+
chain, cur_defn, mid = scope.get_super_chain
|
87
|
+
trys = chain.map { |c| "#{c}.$$def" }.join(' || ')
|
88
|
+
implicit = @implicit_args.to_s
|
89
|
+
|
90
|
+
"Opal.find_iter_super_dispatcher(self, #{mid}, (#{trys} || #{cur_defn}), #{defined_check_param}, #{implicit_arguments_param})"
|
44
91
|
end
|
45
92
|
|
46
|
-
def
|
47
|
-
|
93
|
+
def add_method(temporary_receiver)
|
94
|
+
super_call = if scope.def?
|
95
|
+
super_method_invocation
|
96
|
+
elsif scope.iter?
|
97
|
+
super_block_invocation
|
98
|
+
else
|
99
|
+
raise 'unexpected compilation error'
|
100
|
+
end
|
101
|
+
|
102
|
+
if temporary_receiver
|
103
|
+
push "(#{temporary_receiver} = ", receiver_fragment, ", ", super_call, ")"
|
104
|
+
else
|
105
|
+
push super_call
|
106
|
+
end
|
48
107
|
end
|
49
108
|
end
|
50
109
|
|
51
110
|
class DefinedSuperNode < BaseSuperNode
|
52
111
|
handle :defined_super
|
53
112
|
|
54
|
-
def
|
55
|
-
|
56
|
-
|
113
|
+
def defined_check_param
|
114
|
+
'true'
|
115
|
+
end
|
57
116
|
|
58
|
-
|
117
|
+
def compile
|
118
|
+
add_method(nil)
|
119
|
+
# will never come back null with method missing on
|
120
|
+
if compiler.method_missing?
|
121
|
+
wrap '(!(', '.$$stub) ? "super" : nil)'
|
122
|
+
else
|
123
|
+
# TODO: With method_missing support off, something breaks in runtime.js's chain
|
124
|
+
wrap '((', ') != null ? "super" : nil)'
|
125
|
+
end
|
59
126
|
end
|
60
127
|
end
|
61
128
|
|
62
129
|
class SuperNode < BaseSuperNode
|
63
130
|
handle :super
|
64
131
|
|
65
|
-
children :arglist, :iter
|
66
|
-
|
67
132
|
def compile
|
68
|
-
if arglist
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
133
|
+
if arglist == nil
|
134
|
+
@implicit_args = true
|
135
|
+
if containing_def_scope
|
136
|
+
containing_def_scope.uses_zuper = true
|
137
|
+
@arguments_without_block = [s(:js_tmp, '$zuper')]
|
138
|
+
# If the method we're in has a block and we're using a default super call with no args, we need to grab the block
|
139
|
+
# If an iter (block via braces) is provided, that takes precedence
|
140
|
+
if (block_arg = formal_block_parameter) && !iter
|
141
|
+
expr = s(:block_pass, s(:lvar, block_arg[1]))
|
142
|
+
@arguments_without_block << expr
|
143
|
+
end
|
79
144
|
else
|
80
|
-
|
145
|
+
@arguments_without_block = []
|
81
146
|
end
|
82
147
|
end
|
83
|
-
|
84
|
-
# compile our call to runtime to get super method
|
85
|
-
self.compile_dispatcher
|
86
|
-
|
87
|
-
push ".apply(self, "
|
88
|
-
push(*args)
|
89
|
-
push ")"
|
148
|
+
super
|
90
149
|
end
|
91
150
|
|
92
|
-
|
93
|
-
|
151
|
+
private
|
152
|
+
|
153
|
+
def formal_block_parameter
|
154
|
+
case containing_def_scope
|
155
|
+
when Opal::Nodes::IterNode
|
156
|
+
containing_def_scope.extract_block_arg
|
157
|
+
when Opal::Nodes::DefNode
|
158
|
+
containing_def_scope.block_arg
|
159
|
+
else
|
160
|
+
raise "Don't know what to do with scope #{containing_def_scope}"
|
161
|
+
end
|
94
162
|
end
|
95
163
|
end
|
96
164
|
end
|