opal 1.4.1 → 1.5.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. checksums.yaml +4 -4
  2. data/.eslintrc.js +5 -3
  3. data/.rubocop.yml +1 -0
  4. data/UNRELEASED.md +37 -2
  5. data/benchmark-ips/bm_js_symbols_vs_strings.rb +39 -14
  6. data/docs/releasing.md +10 -2
  7. data/lib/opal/ast/matcher.rb +77 -0
  8. data/lib/opal/cache.rb +1 -1
  9. data/lib/opal/cli_runners/applescript.rb +2 -0
  10. data/lib/opal/compiler.rb +18 -9
  11. data/lib/opal/nodes/call.rb +73 -28
  12. data/lib/opal/nodes/def.rb +31 -27
  13. data/lib/opal/nodes/definitions.rb +2 -0
  14. data/lib/opal/nodes/helpers.rb +4 -23
  15. data/lib/opal/nodes/if.rb +222 -0
  16. data/lib/opal/nodes/iter.rb +41 -37
  17. data/lib/opal/nodes/literal.rb +2 -2
  18. data/lib/opal/nodes/masgn.rb +15 -17
  19. data/lib/opal/nodes/node_with_args/shortcuts.rb +100 -0
  20. data/lib/opal/nodes/node_with_args.rb +1 -0
  21. data/lib/opal/nodes/top.rb +26 -10
  22. data/lib/opal/nodes.rb +0 -1
  23. data/lib/opal/parser/default_config.rb +3 -2
  24. data/lib/opal/repl.rb +1 -1
  25. data/lib/opal/rewriter.rb +13 -6
  26. data/lib/opal/rewriters/base.rb +12 -1
  27. data/lib/opal/rewriters/rubyspec/filters_rewriter.rb +1 -0
  28. data/lib/opal/version.rb +1 -1
  29. data/opal/corelib/array.rb +23 -28
  30. data/opal/corelib/binding.rb +14 -4
  31. data/opal/corelib/constants.rb +3 -3
  32. data/opal/corelib/hash.rb +2 -2
  33. data/opal/corelib/irb.rb +192 -0
  34. data/opal/corelib/math/polyfills.rb +127 -0
  35. data/opal/corelib/math.rb +14 -194
  36. data/opal/corelib/module.rb +23 -25
  37. data/opal/corelib/number.rb +63 -14
  38. data/opal/corelib/regexp.rb +2 -0
  39. data/opal/corelib/runtime.js +56 -20
  40. data/opal/corelib/string.rb +38 -59
  41. data/opal/corelib/time.rb +106 -68
  42. data/opal/opal/full.rb +0 -1
  43. data/opal/opal.rb +4 -1
  44. data/spec/filters/bugs/date.rb +0 -3
  45. data/spec/filters/bugs/datetime.rb +65 -0
  46. data/spec/filters/bugs/float.rb +0 -18
  47. data/spec/filters/bugs/hash.rb +0 -2
  48. data/spec/filters/bugs/language.rb +0 -3
  49. data/spec/filters/bugs/marshal.rb +0 -1
  50. data/spec/filters/bugs/string.rb +0 -30
  51. data/spec/filters/bugs/time.rb +18 -8
  52. data/spec/lib/cli_spec.rb +2 -2
  53. data/spec/lib/compiler_spec.rb +8 -8
  54. data/spec/lib/rewriters/base_spec.rb +1 -1
  55. data/spec/lib/rewriters/binary_operator_assignment_spec.rb +34 -59
  56. data/spec/lib/rewriters/block_to_iter_spec.rb +3 -6
  57. data/spec/lib/rewriters/dot_js_syntax_spec.rb +2 -5
  58. data/spec/lib/rewriters/for_rewriter_spec.rb +0 -1
  59. data/spec/lib/rewriters/forward_args_spec.rb +2 -3
  60. data/spec/lib/rewriters/js_reserved_words_spec.rb +2 -15
  61. data/spec/lib/rewriters/logical_operator_assignment_spec.rb +64 -89
  62. data/spec/lib/rewriters/numblocks_spec.rb +3 -5
  63. data/spec/lib/rewriters/opal_engine_check_spec.rb +2 -14
  64. data/spec/lib/rewriters/rubyspec/filters_rewriter_spec.rb +10 -2
  65. data/spec/opal/compiler/irb_spec.rb +4 -0
  66. data/spec/opal/core/language/super_spec.rb +26 -0
  67. data/spec/opal/core/regexp/assertions_spec.rb +19 -0
  68. data/spec/opal/core/string/to_proc_spec.rb +19 -0
  69. data/spec/ruby_specs +4 -0
  70. data/spec/support/rewriters_helper.rb +43 -23
  71. data/stdlib/date/date_time.rb +71 -0
  72. data/stdlib/date/formatters.rb +28 -0
  73. data/stdlib/date/infinity.rb +73 -0
  74. data/stdlib/date.rb +77 -214
  75. data/stdlib/opal/repl_js.rb +1 -1
  76. data/stdlib/{opal/replutils.rb → opal-replutils.rb} +3 -3
  77. data/stdlib/time.rb +39 -2
  78. data/stdlib/uri.rb +53 -0
  79. data/tasks/performance/asciidoctor_test.rb.erb +3 -1
  80. data/tasks/performance/optimization_status.rb +3 -2
  81. data/tasks/performance.rake +69 -35
  82. data/tasks/testing.rake +1 -0
  83. data/test/opal/test_uri.rb +35 -0
  84. data/yarn.lock +27 -5
  85. metadata +31 -18
  86. data/lib/opal/nodes/csend.rb +0 -24
  87. data/lib/opal/rewriters/explicit_writer_return.rb +0 -59
  88. data/spec/lib/rewriters/explicit_writer_return_spec.rb +0 -186
  89. data/stdlib/nodejs/irb.rb +0 -43
data/lib/opal/nodes/if.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'opal/nodes/base'
4
+ require 'opal/ast/matcher'
4
5
 
5
6
  module Opal
6
7
  module Nodes
@@ -18,6 +19,8 @@ module Opal
18
19
  else
19
20
  compile_with_ternary
20
21
  end
22
+ elsif could_become_switch?
23
+ compile_with_switch
21
24
  else
22
25
  compile_with_if
23
26
  end
@@ -158,6 +161,225 @@ module Opal
158
161
  true
159
162
  end
160
163
  end
164
+
165
+ # NOTE: all following matcher will act on case/when statements in their rewitten form:
166
+ #
167
+ # bin/opal --sexp -e'case some_value_or_expression; when 123; when 456, 789; end'
168
+ #
169
+ # s(:top,
170
+ # s(:if,
171
+ # s(:send,
172
+ # s(:int, 123), :===,
173
+ # s(:lvasgn, "$ret_or_1",
174
+ # s(:send, nil, :some_value_or_expression))), nil,
175
+ # s(:if,
176
+ # s(:if,
177
+ # s(:send,
178
+ # s(:int, 456), :===,
179
+ # s(:js_tmp, "$ret_or_1")),
180
+ # s(:true),
181
+ # s(:send,
182
+ # s(:int, 789), :===,
183
+ # s(:js_tmp, "$ret_or_1"))), nil,
184
+ # s(:nil))))
185
+ #
186
+
187
+ # Matches: `case some_value_or_expression; when 123`
188
+ # Captures: [s(:int, 123), "$ret_or_1", s(:send, nil, :some_value_or_expression))]
189
+ SWITCH_TEST_MATCH = AST::Matcher.new do
190
+ s(:send,
191
+ cap(s(%i[float int sym str true false nil], :*)),
192
+ :===,
193
+ s(:lvasgn, cap(:*), cap(:*))
194
+ )
195
+ end
196
+
197
+ # Matches: case some_value_or_expression; when 123, 456; end
198
+ # Captures: [
199
+ # s(:int, 123),
200
+ # "$ret_or_1",
201
+ # s(:send, nil, :some_value_or_expression)),
202
+ # …here we delegate to either SWITCH_BRANCH_TEST_MATCH or SWITCH_BRANCH_TEST_MATCH_CONTINUED
203
+ # ]
204
+ SWITCH_TEST_MATCH_CONTINUED = AST::Matcher.new do
205
+ s(:if,
206
+ s(:send,
207
+ cap(s(%i[float int sym str true false nil], :*)),
208
+ :===,
209
+ s(:lvasgn, cap(:*), cap(:*))
210
+ ),
211
+ s(:true),
212
+ cap(:*)
213
+ )
214
+ end
215
+
216
+ # Matches: `when 456` (from `case foo; when 123; when 456; end`)
217
+ # Captures: [s(:int, 456), "$ret_or_1"]
218
+ SWITCH_BRANCH_TEST_MATCH = AST::Matcher.new do
219
+ s(:send,
220
+ cap(s(%i[float int sym str true false nil], :*)),
221
+ :===,
222
+ s(:js_tmp, cap(:*))
223
+ )
224
+ end
225
+
226
+ # Matches: `when 456`
227
+ # Captures: [
228
+ # s(:int, 789),
229
+ # "$ret_or_1",
230
+ # …here we delegate to either SWITCH_BRANCH_TEST_MATCH or SWITCH_BRANCH_TEST_MATCH_CONTINUED
231
+ # ]
232
+ SWITCH_BRANCH_TEST_MATCH_CONTINUED = AST::Matcher.new do
233
+ s(:if,
234
+ s(:send,
235
+ cap(s(%i[float int sym str true false nil], :*)),
236
+ :===,
237
+ s(:js_tmp, cap(:*))
238
+ ),
239
+ s(:true),
240
+ cap(:*)
241
+ )
242
+ end
243
+
244
+ def could_become_switch?
245
+ return false if expects_expression?
246
+
247
+ return true if sexp.meta[:switch_child]
248
+
249
+ test_match = SWITCH_TEST_MATCH.match(test) || SWITCH_TEST_MATCH_CONTINUED.match(test)
250
+ return false unless test_match
251
+ @switch_test, @switch_variable, @switch_first_test, additional_rules = *test_match
252
+
253
+ additional_rules = handle_additional_switch_rules(additional_rules)
254
+ return false unless additional_rules # It's ok for them to be empty, but false denotes a mismatch
255
+ @switch_additional_rules = additional_rules
256
+
257
+ return false unless valid_switch_body?(true_body)
258
+
259
+ could_become_switch_branch?(false_body)
260
+ end
261
+
262
+ def handle_additional_switch_rules(additional_rules)
263
+ switch_additional_rules = []
264
+ while additional_rules
265
+ match = SWITCH_BRANCH_TEST_MATCH.match(additional_rules) || SWITCH_BRANCH_TEST_MATCH_CONTINUED.match(additional_rules)
266
+ return false unless match
267
+
268
+ switch_test, switch_variable, additional_rules = *match
269
+ return false unless switch_variable == @switch_variable
270
+
271
+ switch_additional_rules << switch_test
272
+ end
273
+ switch_additional_rules
274
+ end
275
+
276
+ def could_become_switch_branch?(body)
277
+ if !body
278
+ return true
279
+ elsif body.type != :if
280
+ if valid_switch_body?(body)
281
+ body.meta[:switch_default] = true
282
+ return true
283
+ end
284
+ return false
285
+ end
286
+
287
+ test, true_body, false_body = *body
288
+
289
+ test_match = SWITCH_BRANCH_TEST_MATCH.match(test) || SWITCH_BRANCH_TEST_MATCH_CONTINUED.match(test)
290
+ unless test_match
291
+ if valid_switch_body?(body, true)
292
+ body.meta[:switch_default] = true
293
+ return true
294
+ end
295
+ end
296
+ switch_test, switch_variable, additional_rules = *test_match
297
+
298
+ switch_additional_rules = handle_additional_switch_rules(additional_rules)
299
+ return false unless switch_additional_rules # It's ok for them to be empty, but false denotes a mismatch
300
+
301
+ return false unless switch_variable == @switch_variable
302
+
303
+ return false unless valid_switch_body?(true_body)
304
+ return false unless could_become_switch_branch?(false_body)
305
+
306
+ body.meta.merge!(switch_child: true,
307
+ switch_test: switch_test,
308
+ switch_variable: @switch_variable,
309
+ switch_additional_rules: switch_additional_rules
310
+ )
311
+
312
+ true
313
+ end
314
+
315
+ def valid_switch_body?(body, check_variable = false)
316
+ case body
317
+ when AST::Node
318
+ case body.type
319
+ when :break, :redo, :retry
320
+ false
321
+ when :iter, :while
322
+ # Don't traverse the iters or whiles!
323
+ true
324
+ else
325
+ body.children.all? { |i| valid_switch_body?(i, check_variable) }
326
+ end
327
+ when @switch_variable
328
+ # Perhaps we ended abruptly and we lack a $ret_or variable... but sometimes
329
+ # we can ignore this.
330
+ !check_variable
331
+ else
332
+ true
333
+ end
334
+ end
335
+
336
+ def compile_with_switch
337
+ if sexp.meta[:switch_child]
338
+ @switch_variable = sexp.meta[:switch_variable]
339
+ @switch_additional_rules = sexp.meta[:switch_additional_rules]
340
+ compile_switch_case(sexp.meta[:switch_test])
341
+ else
342
+ line "switch (", expr(@switch_first_test), ") {"
343
+ indent do
344
+ compile_switch_case(@switch_test)
345
+ end
346
+ line "}"
347
+ end
348
+ end
349
+
350
+ def returning?(body)
351
+ %i[return js_return next].include?(body.type) ||
352
+ (body.type == :begin && %i[return js_return next].include?(body.children.last.type))
353
+ end
354
+
355
+ def compile_switch_case(test)
356
+ line "case ", expr(test), ":"
357
+ if @switch_additional_rules
358
+ @switch_additional_rules.each do |rule|
359
+ line "case ", expr(rule), ":"
360
+ end
361
+ end
362
+ indent do
363
+ line stmt(true_body)
364
+ line "break;" if !true_body || !returning?(true_body)
365
+ end
366
+ if false_body
367
+ if false_body.meta[:switch_default]
368
+ compile_switch_default
369
+ elsif false_body.meta[:switch_child]
370
+ push stmt(false_body)
371
+ end
372
+ else
373
+ push stmt(s(:nil))
374
+ end
375
+ end
376
+
377
+ def compile_switch_default
378
+ line "default:"
379
+ indent do
380
+ line stmt(false_body)
381
+ end
382
+ end
161
383
  end
162
384
 
163
385
  class IFlipFlop < Base
@@ -8,45 +8,12 @@ module Opal
8
8
  class IterNode < NodeWithArgs
9
9
  handle :iter
10
10
 
11
- children :inline_args, :body
11
+ children :inline_args, :stmts
12
12
 
13
13
  def compile
14
14
  is_lambda! if scope.lambda_definition?
15
15
 
16
- inline_params = nil
17
-
18
- to_vars = identity = body_code = nil
19
-
20
- in_scope do
21
- identity = scope.identify!
22
-
23
- inline_params = process(inline_args)
24
-
25
- compile_arity_check
26
-
27
- body_code = stmt(returned_body)
28
-
29
- add_temp "self = #{identity}.$$s == null ? this : #{identity}.$$s" if @define_self
30
-
31
- to_vars = scope.to_vars
32
-
33
- line body_code
34
-
35
- if scope.catch_return
36
- unshift "try {\n"
37
- line '} catch ($returner) { if ($returner === Opal.returner) { return $returner.$v }'
38
- push ' throw $returner; }'
39
- end
40
- end
41
-
42
- unshift to_vars
43
-
44
- if await_encountered
45
- unshift "async function #{identity}(", inline_params, '){'
46
- else
47
- unshift "function #{identity}(", inline_params, '){'
48
- end
49
- push '}'
16
+ compile_body_or_shortcut
50
17
 
51
18
  blockopts = []
52
19
  blockopts << "$$arity: #{arity}"
@@ -83,6 +50,43 @@ module Opal
83
50
  scope.relative_access if @define_relative_access
84
51
  end
85
52
 
53
+ def compile_body
54
+ inline_params = nil
55
+
56
+ to_vars = identity = body_code = nil
57
+
58
+ in_scope do
59
+ identity = scope.identify!
60
+
61
+ inline_params = process(inline_args)
62
+
63
+ compile_arity_check
64
+
65
+ body_code = stmt(returned_body)
66
+
67
+ add_temp "self = #{identity}.$$s == null ? this : #{identity}.$$s" if @define_self
68
+
69
+ to_vars = scope.to_vars
70
+
71
+ line body_code
72
+
73
+ if scope.catch_return
74
+ unshift "try {\n"
75
+ line '} catch ($returner) { if ($returner === Opal.returner) { return $returner.$v }'
76
+ push ' throw $returner; }'
77
+ end
78
+ end
79
+
80
+ unshift to_vars
81
+
82
+ if await_encountered
83
+ unshift "async function #{identity}(", inline_params, '){'
84
+ else
85
+ unshift "function #{identity}(", inline_params, '){'
86
+ end
87
+ push '}'
88
+ end
89
+
86
90
  def compile_block_arg
87
91
  if block_arg
88
92
  scope.prepare_block
@@ -108,13 +112,13 @@ module Opal
108
112
  @sexp = @sexp.updated(
109
113
  nil, [
110
114
  args.updated(nil, valid_args),
111
- body
115
+ stmts
112
116
  ]
113
117
  )
114
118
  end
115
119
 
116
120
  def returned_body
117
- compiler.returns(body || s(:nil))
121
+ compiler.returns(stmts || s(:nil))
118
122
  end
119
123
 
120
124
  def has_top_level_mlhs_arg?
@@ -326,7 +326,7 @@ module Opal
326
326
  children :value
327
327
 
328
328
  def compile
329
- push "Opal.Rational.$new(#{value.numerator}, #{value.denominator})"
329
+ push "#{top_scope.absolute_const}('Rational').$new(#{value.numerator}, #{value.denominator})"
330
330
  end
331
331
  end
332
332
 
@@ -338,7 +338,7 @@ module Opal
338
338
  children :value
339
339
 
340
340
  def compile
341
- push "Opal.Complex.$new(#{value.real}, #{value.imag})"
341
+ push "#{top_scope.absolute_const}('Complex').$new(#{value.real}, #{value.imag})"
342
342
  end
343
343
  end
344
344
  end
@@ -11,24 +11,22 @@ module Opal
11
11
  children :lhs, :rhs
12
12
 
13
13
  def compile
14
- array = scope.new_temp
15
-
16
- if rhs.type == :array
17
- push "#{array} = ", expr(rhs)
18
- rhs_len = rhs.children.any? { |c| c.type == :splat } ? nil : rhs.children.size
19
- compile_masgn(lhs.children, array, rhs_len)
20
- push ", #{array}" # a mass assignment evaluates to the RHS
21
- else
22
- helper :to_ary
23
- retval = scope.new_temp
24
- push "#{retval} = ", expr(rhs)
25
- push ", #{array} = $to_ary(#{retval})"
26
- compile_masgn(lhs.children, array)
27
- push ", #{retval}"
28
- scope.queue_temp(retval)
14
+ with_temp do |array|
15
+ if rhs.type == :array
16
+ push "#{array} = ", expr(rhs)
17
+ rhs_len = rhs.children.any? { |c| c.type == :splat } ? nil : rhs.children.size
18
+ compile_masgn(lhs.children, array, rhs_len)
19
+ push ", #{array}" # a mass assignment evaluates to the RHS
20
+ else
21
+ helper :to_ary
22
+ with_temp do |retval|
23
+ push "#{retval} = ", expr(rhs)
24
+ push ", #{array} = $to_ary(#{retval})"
25
+ compile_masgn(lhs.children, array)
26
+ push ", #{retval}"
27
+ end
28
+ end
29
29
  end
30
-
31
- scope.queue_temp(array)
32
30
  end
33
31
 
34
32
  # 'len' is how many rhs items are we sure we have
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Opal
4
+ module Nodes
5
+ class NodeWithArgs < ScopeNode
6
+ # Shortcuts for the simplest kinds of methods
7
+ Shortcut = Struct.new(:name, :for, :when, :transform) do
8
+ def match?(node)
9
+ node.instance_exec(&self.when)
10
+ end
11
+
12
+ def compile(node)
13
+ node.helper name
14
+ node.instance_exec(&transform)
15
+ end
16
+ end
17
+
18
+ @shortcuts = []
19
+ @shortcuts_for = {}
20
+ def self.define_shortcut(name, **kwargs, &block)
21
+ kwargs[:for] ||= :def
22
+ @shortcuts << Shortcut.new(name, kwargs[:for], kwargs[:when], block)
23
+ end
24
+
25
+ def self.shortcuts_for(node_type)
26
+ @shortcuts_for[node_type] ||=
27
+ @shortcuts.select do |shortcut|
28
+ [node_type, :*].include? shortcut.for
29
+ end
30
+ end
31
+
32
+ def compile_body_or_shortcut
33
+ # The shortcuts don't check arity. If we want to check arity,
34
+ # we can't use them.
35
+ return compile_body if compiler.arity_check?
36
+
37
+ node_type = is_a?(DefNode) ? :def : :iter
38
+
39
+ NodeWithArgs.shortcuts_for(node_type).each do |shortcut|
40
+ if shortcut.match?(self)
41
+ if ENV['OPAL_DEBUG_SHORTCUTS']
42
+ node_desc = node_type == :def ? "def #{mid}" : "iter"
43
+ warn "* shortcut #{shortcut.name} used for #{node_desc}"
44
+ end
45
+
46
+ return shortcut.compile(self)
47
+ end
48
+ end
49
+
50
+ compile_body
51
+ end
52
+
53
+ # Shortcut definitions
54
+ # --------------------
55
+
56
+ # def a; self; end
57
+ define_shortcut :return_self, when: -> { stmts.type == :self } do
58
+ push '$return_self'
59
+ end
60
+
61
+ def simple_value?(node = stmts)
62
+ %i[true false nil int float str sym].include?(node.type)
63
+ end
64
+
65
+ # def a; 123; end
66
+ define_shortcut :return_val, for: :*, when: -> { simple_value? } do
67
+ push '$return_val(', expr(stmts), ')'
68
+ end
69
+
70
+ # def a; @x; end
71
+ define_shortcut :return_ivar, when: -> { stmts.type == :ivar } do
72
+ name = stmts.children.first.to_s[1..-1].to_sym
73
+ push '$return_ivar(', expr(stmts.updated(:sym, [name])), ')'
74
+ end
75
+
76
+ # def a; @x = 5; end
77
+ define_shortcut :assign_ivar, when: -> {
78
+ stmts.type == :ivasgn &&
79
+ inline_args.children.length == 1 &&
80
+ inline_args.children.last.type == :arg &&
81
+ stmts.children.last.type == :lvar &&
82
+ stmts.children.last.children.last == inline_args.children.last.children.last
83
+ } do
84
+ name = stmts.children.first.to_s[1..-1].to_sym
85
+ name = expr(stmts.updated(:sym, [name]))
86
+ push '$assign_ivar(', name, ')'
87
+ end
88
+
89
+ # def a(x); @x = x; end
90
+ define_shortcut :assign_ivar_val, when: -> {
91
+ stmts.type == :ivasgn &&
92
+ simple_value?(stmts.children.last)
93
+ } do
94
+ name = stmts.children.first.to_s[1..-1].to_sym
95
+ name = expr(stmts.updated(:sym, [name]))
96
+ push '$assign_ivar_val(', name, ', ', expr(stmts.children.last), ')'
97
+ end
98
+ end
99
+ end
100
+ end
@@ -2,6 +2,7 @@
2
2
 
3
3
  require 'opal/nodes/scope'
4
4
  require 'opal/nodes/args/parameters'
5
+ require 'opal/nodes/node_with_args/shortcuts'
5
6
 
6
7
  module Opal
7
8
  module Nodes
@@ -14,14 +14,22 @@ module Opal
14
14
 
15
15
  def compile
16
16
  compiler.top_scope = self
17
+ compiler.dynamic_cache_result = true if sexp.meta[:dynamic_cache_result]
17
18
 
18
19
  push version_comment
19
20
 
20
- in_scope do
21
- if body == s(:nil)
22
- # A shortpath for empty (stub?) modules.
23
- line 'return Opal.nil;'
21
+ helper :return_val if compiler.eof_content
22
+
23
+ if body == s(:nil)
24
+ # A shortpath for empty (stub?) modules.
25
+ if compiler.requirable? || compiler.esm? || compiler.eval?
26
+ unshift 'Opal.return_val(Opal.nil); '
27
+ definition
24
28
  else
29
+ unshift 'Opal.nil; '
30
+ end
31
+ else
32
+ in_scope do
25
33
  line '"use strict";' if compiler.use_strict?
26
34
 
27
35
  body_code = stmt(stmts)
@@ -47,20 +55,28 @@ module Opal
47
55
 
48
56
  line body_code
49
57
  end
58
+
59
+ opening
60
+ definition
61
+ closing
62
+ end
63
+ end
64
+
65
+ def definition
66
+ if compiler.requirable?
67
+ unshift "Opal.modules[#{Opal::Compiler.module_name(compiler.file).inspect}] = "
68
+ elsif compiler.esm?
69
+ unshift 'export default '
50
70
  end
51
- opening
52
- closing
53
71
  end
54
72
 
55
73
  def opening
56
74
  async_prefix = "async " if await_encountered
57
75
 
58
76
  if compiler.requirable?
59
- unshift "Opal.modules[#{Opal::Compiler.module_name(compiler.file).inspect}] = #{async_prefix}function(Opal) {"
77
+ unshift "#{async_prefix}function(Opal) {"
60
78
  elsif compiler.eval?
61
79
  unshift "(#{async_prefix}function(Opal, self) {"
62
- elsif compiler.esm?
63
- unshift "export default Opal.queue(#{async_prefix}function(Opal) {"
64
80
  else
65
81
  unshift "Opal.queue(#{async_prefix}function(Opal) {"
66
82
  end
@@ -108,7 +124,7 @@ module Opal
108
124
  def compile_end_construct
109
125
  if content = compiler.eof_content
110
126
  line 'var $__END__ = Opal.Object.$new();'
111
- line "$__END__.$read = function() { return #{content.inspect}; };"
127
+ line "$__END__.$read = $return_val(#{content.inspect});"
112
128
  end
113
129
  end
114
130
 
data/lib/opal/nodes.rb CHANGED
@@ -5,7 +5,6 @@ require 'opal/nodes/literal'
5
5
  require 'opal/nodes/variables'
6
6
  require 'opal/nodes/constants'
7
7
  require 'opal/nodes/call'
8
- require 'opal/nodes/csend'
9
8
  require 'opal/nodes/call_special'
10
9
  require 'opal/nodes/module'
11
10
  require 'opal/nodes/class'
@@ -29,8 +29,9 @@ module Opal
29
29
  end
30
30
 
31
31
  def parse(source_buffer)
32
- parsed = super
33
- rewriten = rewrite(parsed)
32
+ parsed = super || ::Opal::AST::Node.new(:nil)
33
+ wrapped = ::Opal::AST::Node.new(:top, [parsed])
34
+ rewriten = rewrite(wrapped)
34
35
  rewriten
35
36
  end
36
37
 
data/lib/opal/repl.rb CHANGED
@@ -164,7 +164,7 @@ module Opal
164
164
  load_opal
165
165
  raise e
166
166
  rescue EOFError, Errno::EPIPE
167
- exit $?.exitstatus
167
+ exit $?.nil? ? 0 : $?.exitstatus
168
168
  end
169
169
 
170
170
  def readline
data/lib/opal/rewriter.rb CHANGED
@@ -2,7 +2,6 @@
2
2
 
3
3
  require 'opal/rewriters/opal_engine_check'
4
4
  require 'opal/rewriters/for_rewriter'
5
- require 'opal/rewriters/explicit_writer_return'
6
5
  require 'opal/rewriters/js_reserved_words'
7
6
  require 'opal/rewriters/block_to_iter'
8
7
  require 'opal/rewriters/dot_js_syntax'
@@ -19,6 +18,8 @@ require 'opal/rewriters/forward_args'
19
18
 
20
19
  module Opal
21
20
  class Rewriter
21
+ @disabled = false
22
+
22
23
  class << self
23
24
  def list
24
25
  @list ||= []
@@ -32,15 +33,21 @@ module Opal
32
33
  list.delete(rewriter)
33
34
  end
34
35
 
35
- def disable
36
- @disabled = true
36
+ def disable(except: nil)
37
+ old_disabled = @disabled
38
+ @disabled = except || true
37
39
  yield
38
40
  ensure
39
- @disabled = false
41
+ @disabled = old_disabled
40
42
  end
41
43
 
42
44
  def disabled?
43
- @disabled if defined?(@disabled)
45
+ @disabled == true
46
+ end
47
+
48
+ def rewritter_disabled?(rewriter)
49
+ return false if @disabled == false
50
+ @disabled != rewriter
44
51
  end
45
52
  end
46
53
 
@@ -54,7 +61,6 @@ module Opal
54
61
  use Rewriters::JsReservedWords
55
62
  use Rewriters::LogicalOperatorAssignment
56
63
  use Rewriters::BinaryOperatorAssignment
57
- use Rewriters::ExplicitWriterReturn
58
64
  use Rewriters::Hashes::KeyDuplicatesRewriter
59
65
  use Rewriters::ReturnableLogic
60
66
  use Rewriters::DumpArgs
@@ -69,6 +75,7 @@ module Opal
69
75
  return @sexp if self.class.disabled?
70
76
 
71
77
  self.class.list.each do |rewriter_class|
78
+ next if self.class.rewritter_disabled?(rewriter_class)
72
79
  rewriter = rewriter_class.new
73
80
  @sexp = rewriter.process(@sexp)
74
81
  end