opal 1.2.0 → 1.3.0.alpha1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (159) hide show
  1. checksums.yaml +4 -4
  2. data/.eslintrc.await.js +6 -0
  3. data/.eslintrc.js +34 -0
  4. data/.github/workflows/build.yml +8 -0
  5. data/.rubocop.yml +9 -0
  6. data/CHANGELOG.md +4 -0
  7. data/README.md +1 -1
  8. data/Rakefile +1 -0
  9. data/UNRELEASED.md +64 -38
  10. data/docs/async.md +109 -0
  11. data/docs/roda-sprockets.md +0 -2
  12. data/exe/opal +2 -0
  13. data/exe/opal-repl +2 -2
  14. data/lib/opal/builder.rb +5 -1
  15. data/lib/opal/builder_processors.rb +7 -2
  16. data/lib/opal/cache/file_cache.rb +119 -0
  17. data/lib/opal/cache.rb +71 -0
  18. data/lib/opal/cli.rb +35 -1
  19. data/lib/opal/cli_options.rb +21 -0
  20. data/lib/opal/cli_runners/chrome.rb +21 -14
  21. data/lib/opal/cli_runners/chrome_cdp_interface.js +30285 -0
  22. data/lib/opal/cli_runners/{chrome.js → chrome_cdp_interface.rb} +27 -6
  23. data/lib/opal/cli_runners/compiler.rb +2 -1
  24. data/lib/opal/cli_runners/gjs.rb +27 -0
  25. data/lib/opal/cli_runners/mini_racer.rb +36 -0
  26. data/lib/opal/cli_runners/source-map-support-browser.js +276 -91
  27. data/lib/opal/cli_runners/source-map-support-node.js +276 -91
  28. data/lib/opal/cli_runners/source-map-support.js +60 -18
  29. data/lib/opal/cli_runners.rb +2 -0
  30. data/lib/opal/compiler.rb +99 -10
  31. data/lib/opal/fragment.rb +77 -14
  32. data/lib/opal/nodes/args/extract_kwrestarg.rb +6 -4
  33. data/lib/opal/nodes/args/extract_restarg.rb +10 -12
  34. data/lib/opal/nodes/args.rb +28 -0
  35. data/lib/opal/nodes/base.rb +29 -5
  36. data/lib/opal/nodes/call.rb +123 -2
  37. data/lib/opal/nodes/case.rb +7 -1
  38. data/lib/opal/nodes/class.rb +12 -2
  39. data/lib/opal/nodes/def.rb +3 -23
  40. data/lib/opal/nodes/definitions.rb +21 -4
  41. data/lib/opal/nodes/helpers.rb +2 -2
  42. data/lib/opal/nodes/if.rb +39 -9
  43. data/lib/opal/nodes/iter.rb +15 -3
  44. data/lib/opal/nodes/lambda.rb +3 -1
  45. data/lib/opal/nodes/literal.rb +13 -7
  46. data/lib/opal/nodes/logic.rb +2 -2
  47. data/lib/opal/nodes/module.rb +12 -2
  48. data/lib/opal/nodes/rescue.rb +59 -34
  49. data/lib/opal/nodes/scope.rb +88 -6
  50. data/lib/opal/nodes/super.rb +52 -25
  51. data/lib/opal/nodes/top.rb +13 -7
  52. data/lib/opal/nodes/while.rb +7 -1
  53. data/lib/opal/parser/patch.rb +2 -1
  54. data/lib/opal/repl.rb +137 -49
  55. data/lib/opal/rewriters/binary_operator_assignment.rb +10 -10
  56. data/lib/opal/rewriters/block_to_iter.rb +3 -3
  57. data/lib/opal/rewriters/for_rewriter.rb +7 -7
  58. data/lib/opal/rewriters/js_reserved_words.rb +5 -3
  59. data/lib/opal/source_map/file.rb +7 -4
  60. data/lib/opal/source_map/map.rb +17 -3
  61. data/lib/opal/version.rb +1 -1
  62. data/opal/corelib/array.rb +2 -2
  63. data/opal/corelib/binding.rb +46 -0
  64. data/opal/corelib/boolean.rb +54 -4
  65. data/opal/corelib/class.rb +2 -0
  66. data/opal/corelib/constants.rb +2 -2
  67. data/opal/corelib/error.rb +98 -12
  68. data/opal/corelib/io.rb +250 -38
  69. data/opal/corelib/kernel/format.rb +5 -2
  70. data/opal/corelib/kernel.rb +44 -23
  71. data/opal/corelib/main.rb +5 -0
  72. data/opal/corelib/method.rb +1 -0
  73. data/opal/corelib/module.rb +28 -0
  74. data/opal/corelib/number.rb +12 -1
  75. data/opal/corelib/random/seedrandom.js.rb +2 -2
  76. data/opal/corelib/regexp.rb +47 -3
  77. data/opal/corelib/runtime.js +152 -12
  78. data/opal/corelib/string/encoding.rb +17 -17
  79. data/opal/corelib/string.rb +2 -0
  80. data/opal/corelib/struct.rb +10 -3
  81. data/opal/corelib/trace_point.rb +57 -0
  82. data/opal/opal/full.rb +2 -0
  83. data/package.json +3 -2
  84. data/spec/filters/bugs/array.rb +0 -1
  85. data/spec/filters/bugs/basicobject.rb +0 -1
  86. data/spec/filters/bugs/binding.rb +27 -0
  87. data/spec/filters/bugs/enumerator.rb +132 -0
  88. data/spec/filters/bugs/exception.rb +70 -93
  89. data/spec/filters/bugs/float.rb +0 -1
  90. data/spec/filters/bugs/kernel.rb +3 -9
  91. data/spec/filters/bugs/language.rb +15 -58
  92. data/spec/filters/bugs/main.rb +16 -0
  93. data/spec/filters/bugs/matrix.rb +39 -0
  94. data/spec/filters/bugs/method.rb +0 -2
  95. data/spec/filters/bugs/module.rb +36 -79
  96. data/spec/filters/bugs/proc.rb +0 -1
  97. data/spec/filters/bugs/regexp.rb +0 -16
  98. data/spec/filters/bugs/trace_point.rb +12 -0
  99. data/spec/filters/bugs/warnings.rb +0 -4
  100. data/spec/filters/unsupported/freeze.rb +2 -0
  101. data/spec/filters/unsupported/privacy.rb +4 -0
  102. data/spec/lib/compiler_spec.rb +7 -1
  103. data/spec/lib/repl_spec.rb +4 -2
  104. data/spec/lib/source_map/file_spec.rb +1 -1
  105. data/spec/mspec-opal/formatters.rb +18 -4
  106. data/spec/mspec-opal/runner.rb +2 -2
  107. data/spec/opal/core/boolean_spec.rb +44 -0
  108. data/spec/opal/core/hash_spec.rb +8 -0
  109. data/spec/opal/core/number/to_s_spec.rb +11 -0
  110. data/spec/opal/stdlib/json/ext_spec.rb +3 -3
  111. data/spec/opal/stdlib/logger/logger_spec.rb +10 -1
  112. data/spec/ruby_specs +18 -0
  113. data/stdlib/await.rb +83 -0
  114. data/stdlib/base64.rb +4 -4
  115. data/stdlib/bigdecimal/bignumber.js.rb +4 -2
  116. data/stdlib/bigdecimal.rb +1 -0
  117. data/stdlib/gjs/io.rb +33 -0
  118. data/stdlib/gjs/kernel.rb +5 -0
  119. data/stdlib/gjs.rb +2 -0
  120. data/stdlib/js.rb +4 -0
  121. data/stdlib/json.rb +3 -3
  122. data/stdlib/logger.rb +1 -1
  123. data/stdlib/nashorn/file.rb +2 -0
  124. data/stdlib/nodejs/env.rb +7 -0
  125. data/stdlib/nodejs/file.rb +6 -41
  126. data/stdlib/nodejs/io.rb +21 -5
  127. data/stdlib/nodejs/js-yaml-3-6-1.js +2 -2
  128. data/stdlib/opal/miniracer.rb +6 -0
  129. data/stdlib/opal/platform.rb +4 -0
  130. data/stdlib/opal/repl_js.rb +5 -0
  131. data/stdlib/opal/replutils.rb +271 -0
  132. data/stdlib/opal-parser.rb +24 -11
  133. data/stdlib/opal-platform.rb +8 -0
  134. data/stdlib/promise/v2.rb +16 -4
  135. data/stdlib/promise.rb +14 -0
  136. data/stdlib/stringio.rb +13 -110
  137. data/stdlib/thread.rb +29 -0
  138. data/tasks/building.rake +10 -4
  139. data/tasks/linting-parse-eslint-results.js +39 -0
  140. data/tasks/linting.rake +38 -28
  141. data/tasks/performance/asciidoctor_test.rb.erb +6 -0
  142. data/tasks/performance/optimization_status.rb +77 -0
  143. data/tasks/performance.rake +149 -0
  144. data/tasks/testing.rake +9 -1
  145. data/test/nodejs/test_await.rb +169 -0
  146. data/test/opal/promisev2/test_error.rb +9 -3
  147. data/test/opal/unsupported_and_bugs.rb +5 -0
  148. data/vendored-minitest/minitest/benchmark.rb +9 -7
  149. data/vendored-minitest/minitest/test.rb +14 -12
  150. data/vendored-minitest/minitest.rb +19 -16
  151. data/yarn.lock +686 -117
  152. metadata +60 -23
  153. data/.jshintrc +0 -41
  154. data/spec/filters/unsupported/refinements.rb +0 -8
  155. data/vendored-minitest/minitest/hell.rb +0 -11
  156. data/vendored-minitest/minitest/parallel.rb +0 -65
  157. data/vendored-minitest/minitest/pride.rb +0 -4
  158. data/vendored-minitest/minitest/pride_plugin.rb +0 -142
  159. data/vendored-minitest/minitest/unit.rb +0 -45
@@ -45,6 +45,9 @@ module Opal
45
45
  handle_special do
46
46
  compiler.method_calls << meth.to_sym if record_method?
47
47
 
48
+ # if trying to access an lvar in eval or irb mode
49
+ return compile_eval_var if using_eval?
50
+
48
51
  # if trying to access an lvar in irb mode
49
52
  return compile_irb_var if using_irb?
50
53
 
@@ -81,8 +84,19 @@ module Opal
81
84
  iter || splat?
82
85
  end
83
86
 
87
+ def invoke_using_refinement?
88
+ !scope.scope.collect_refinements_temps.empty?
89
+ end
90
+
84
91
  def default_compile
85
- if invoke_using_send?
92
+ if auto_await?
93
+ push 'await '
94
+ scope.await_encountered = true
95
+ end
96
+
97
+ if invoke_using_refinement?
98
+ compile_using_refined_send
99
+ elsif invoke_using_send?
86
100
  compile_using_send
87
101
  else
88
102
  compile_simple_call_chain
@@ -109,6 +123,25 @@ module Opal
109
123
  push ')'
110
124
  end
111
125
 
126
+ # Compiles method call using `Opal.refined_send`
127
+ #
128
+ # @example
129
+ # a.b(c, &block)
130
+ #
131
+ # Opal.refined_send(a, 'b', [c], block, [[Opal.MyRefinements]])
132
+ #
133
+ def compile_using_refined_send
134
+ helper :refined_send
135
+
136
+ push '$refined_send('
137
+ compile_refinements
138
+ compile_receiver
139
+ compile_method_name
140
+ compile_arguments
141
+ compile_block_pass
142
+ push ')'
143
+ end
144
+
112
145
  def compile_receiver
113
146
  push recv(receiver_sexp)
114
147
  end
@@ -135,6 +168,11 @@ module Opal
135
168
  end
136
169
  end
137
170
 
171
+ def compile_refinements
172
+ refinements = scope.collect_refinements_temps.map { |i| s(:js_tmp, i) }
173
+ push expr(s(:array, *refinements)), ', '
174
+ end
175
+
138
176
  def compile_break_catcher
139
177
  if iter_has_break?
140
178
  unshift 'return '
@@ -172,16 +210,34 @@ module Opal
172
210
  end
173
211
  end
174
212
 
213
+ def compile_eval_var
214
+ push meth.to_s
215
+ end
216
+
175
217
  # a variable reference in irb mode in top scope might be a var ref,
176
218
  # or it might be a method call
177
219
  def using_irb?
178
- @compiler.irb? && scope.top? && arglist == s(:arglist) && recvr.nil? && iter.nil?
220
+ @compiler.irb? && scope.top? && variable_like?
221
+ end
222
+
223
+ def using_eval?
224
+ @compiler.eval? && scope.top? && @compiler.scope_variables.include?(meth)
225
+ end
226
+
227
+ def variable_like?
228
+ arglist == s(:arglist) && recvr.nil? && iter.nil?
179
229
  end
180
230
 
181
231
  def sexp_with_arglist
182
232
  @sexp.updated(nil, [recvr, meth, arglist])
183
233
  end
184
234
 
235
+ def auto_await?
236
+ awaited_set = compiler.async_await
237
+
238
+ awaited_set && awaited_set != true && awaited_set.match?(meth.to_s)
239
+ end
240
+
185
241
  # Handle "special" method calls, e.g. require(). Subclasses can override
186
242
  # this method. If this method returns nil, then the method will continue
187
243
  # to be generated by CallNode.
@@ -273,6 +329,24 @@ module Opal
273
329
  end
274
330
  end
275
331
 
332
+ # Refinements support
333
+ add_special :using do |compile_default|
334
+ if scope.accepts_using? && arglist.children.count == 1
335
+ using_refinement(arglist.children.first)
336
+ else
337
+ compile_default.call
338
+ end
339
+ end
340
+
341
+ def using_refinement(arg)
342
+ prev, curr = *scope.refinements_temp
343
+ if prev
344
+ push "(#{curr} = #{prev}.slice(), #{curr}.push(", expr(arg), '), self)'
345
+ else
346
+ push "(#{curr} = [", expr(arg), '], self)'
347
+ end
348
+ end
349
+
276
350
  add_special :debugger do
277
351
  push fragment 'debugger'
278
352
  end
@@ -281,6 +355,12 @@ module Opal
281
355
  push fragment "Opal.hash({ arity_check: #{compiler.arity_check?} })"
282
356
  end
283
357
 
358
+ add_special :lambda do |compile_default|
359
+ scope.defines_lambda do
360
+ compile_default.call
361
+ end
362
+ end
363
+
284
364
  add_special :nesting do |compile_default|
285
365
  push_nesting = push_nesting?
286
366
  push '(Opal.Module.$$nesting = $nesting, ' if push_nesting
@@ -295,6 +375,47 @@ module Opal
295
375
  push ')' if push_nesting
296
376
  end
297
377
 
378
+ # This can be refactored in terms of binding, but it would 'corelib/binding'
379
+ # to be required in existing code.
380
+ add_special :eval do |compile_default|
381
+ next compile_default.call if arglist.children.length != 1 || ![s(:self), nil].include?(recvr)
382
+
383
+ temp = scope.new_temp
384
+ scope_variables = scope.scope_locals.map(&:to_s).inspect
385
+ push "(#{temp} = ", expr(arglist)
386
+ push ", typeof Opal.compile === 'function' ? eval(Opal.compile(#{temp}"
387
+ push ', {scope_variables: ', scope_variables
388
+ push ", arity_check: #{compiler.arity_check?}, file: '(eval)', eval: true})) : "
389
+ push "self.$eval(#{temp}))"
390
+ end
391
+
392
+ add_special :binding do
393
+ push "Opal.Binding.$new("
394
+ push " function($code, $value) {"
395
+ push " if (typeof $value === 'undefined') {"
396
+ push " return eval($code);"
397
+ push " }"
398
+ push " else {"
399
+ push " return eval($code + ' = $value');"
400
+ push " }"
401
+ push " },"
402
+ push " ", scope.scope_locals.map(&:to_s).inspect, ","
403
+ push " self,"
404
+ push " ", source_location
405
+ push ")"
406
+ end
407
+
408
+ add_special :__await__ do |compile_default|
409
+ if compiler.async_await
410
+ push fragment '(await ('
411
+ push process(recvr)
412
+ push fragment '))'
413
+ scope.await_encountered = true
414
+ else
415
+ compile_default.call
416
+ end
417
+ end
418
+
298
419
  def push_nesting?
299
420
  recv = children.first
300
421
 
@@ -13,7 +13,13 @@ module Opal
13
13
  compiler.in_case do
14
14
  compile_code
15
15
 
16
- wrap '(function() {', '})()' if needs_closure?
16
+ if needs_closure?
17
+ if scope.await_encountered
18
+ wrap '(await (async function() {', '})())'
19
+ else
20
+ wrap '(function() {', '})()'
21
+ end
22
+ end
17
23
  end
18
24
  end
19
25
 
@@ -13,13 +13,23 @@ module Opal
13
13
  name, base = name_and_base
14
14
  helper :klass
15
15
 
16
- push '(function($base, $super, $parent_nesting) {'
17
16
  line " var self = $klass($base, $super, '#{name}');"
18
17
  in_scope do
19
18
  scope.name = name
20
19
  compile_body
21
20
  end
22
- line '})(', base, ', ', super_code, ', $nesting)'
21
+
22
+ if await_encountered
23
+ await_begin = '(await '
24
+ await_end = ')'
25
+ async = 'async '
26
+ parent.await_encountered = true
27
+ else
28
+ await_begin, await_end, async = '', '', ''
29
+ end
30
+
31
+ unshift "#{await_begin}(#{async}function($base, $super, $parent_nesting) {"
32
+ line '})(', base, ', ', super_code, ", $nesting)#{await_end}"
23
33
  end
24
34
 
25
35
  def super_code
@@ -33,10 +33,6 @@ module Opal
33
33
 
34
34
  compile_arity_check
35
35
 
36
- if scope.uses_zuper
37
- prepare_super
38
- end
39
-
40
36
  unshift "\n#{current_indent}", scope.to_vars
41
37
 
42
38
  line stmt_code
@@ -61,6 +57,9 @@ module Opal
61
57
  unshift ') {'
62
58
  unshift(inline_params)
63
59
  unshift "function#{function_name}("
60
+ if await_encountered
61
+ unshift "async "
62
+ end
64
63
  unshift "#{scope_name} = " if scope_name
65
64
  line '}'
66
65
 
@@ -91,28 +90,9 @@ module Opal
91
90
  end
92
91
  end
93
92
 
94
- def source_location
95
- file = @sexp.loc.expression.source_buffer.name
96
- file = "<internal:#{file}>" if file.start_with?("corelib/")
97
- file = "<js:#{file}>" if file.end_with?(".js")
98
- line = @sexp.loc.line
99
- "['#{file}', #{line}]"
100
- end
101
-
102
93
  def comments_code
103
94
  '[' + comments.map { |comment| comment.text.inspect }.join(', ') + ']'
104
95
  end
105
-
106
- def prepare_super
107
- add_local '$zuper'
108
- add_local '$zuper_i'
109
- add_local '$zuper_ii'
110
-
111
- line '// Prepare super implicit arguments'
112
- line 'for($zuper_i = 0, $zuper_ii = arguments.length, $zuper = new Array($zuper_ii); $zuper_i < $zuper_ii; $zuper_i++) {'
113
- line ' $zuper[$zuper_i] = arguments[$zuper_i];'
114
- line '}'
115
- end
116
96
  end
117
97
  end
118
98
  end
@@ -22,7 +22,19 @@ module Opal
22
22
  children :new_name, :old_name
23
23
 
24
24
  def compile
25
- push 'Opal.alias(self, ', expr(new_name), ', ', expr(old_name), ')'
25
+ # We only need to check one type, because parser otherwise denies invalid expressions
26
+ case new_name.type
27
+ when :gvar # This is a gvar alias: alias $a $b
28
+ helper :alias_gvar
29
+ new_name_str = new_name.children.first.to_s[1..-1].inspect
30
+ old_name_str = old_name.children.first.to_s[1..-1].inspect
31
+ push '$alias_gvar(', new_name_str, ', ', old_name_str, ')'
32
+ when :dsym, :sym # This is a method alias: alias a b
33
+ helper :alias
34
+ push '$alias(self, ', expr(new_name), ', ', expr(old_name), ')'
35
+ else # Nothing else is available, but just in case, drop an error
36
+ error "Opal doesn't know yet how to alias with #{new_name.type}"
37
+ end
26
38
  end
27
39
  end
28
40
 
@@ -41,7 +53,12 @@ module Opal
41
53
  compile_inline_children(returned_children, @level)
42
54
  else
43
55
  compile_children(returned_children, @level)
44
- wrap '(function() {', '})()'
56
+
57
+ if scope.parent.await_encountered
58
+ wrap '(await (async function() {', '})())'
59
+ else
60
+ wrap '(function() {', '})()'
61
+ end
45
62
  end
46
63
  end
47
64
 
@@ -58,7 +75,7 @@ module Opal
58
75
 
59
76
  def compile_children(children, level)
60
77
  children.each do |child|
61
- line process(child, level), ';'
78
+ line process(child, level), fragment(';', loc: false)
62
79
  end
63
80
  end
64
81
 
@@ -76,7 +93,7 @@ module Opal
76
93
  end
77
94
 
78
95
  processed_children.reject(&:empty?).each_with_index do |child, idx|
79
- push ', ' unless idx == 0
96
+ push fragment(', ', loc: false) unless idx == 0
80
97
  push child
81
98
  end
82
99
  end
@@ -35,12 +35,12 @@ module Opal
35
35
  end
36
36
 
37
37
  def line(*strs)
38
- push "\n#{current_indent}"
38
+ push fragment("\n#{current_indent}", loc: false)
39
39
  push(*strs)
40
40
  end
41
41
 
42
42
  def empty_line
43
- push "\n"
43
+ push fragment("\n", loc: false)
44
44
  end
45
45
 
46
46
  def js_truthy(sexp)
data/lib/opal/nodes/if.rb CHANGED
@@ -33,7 +33,13 @@ module Opal
33
33
  push '}'
34
34
  end
35
35
 
36
- wrap '(function() {', '; return nil; })()' if needs_wrapper?
36
+ if needs_wrapper?
37
+ if scope.await_encountered
38
+ wrap '(await (async function() {', '; return nil; })())'
39
+ else
40
+ wrap '(function() {', '; return nil; })()'
41
+ end
42
+ end
37
43
  end
38
44
 
39
45
  def truthy
@@ -52,20 +58,44 @@ module Opal
52
58
  class IFlipFlop < Base
53
59
  handle :iflipflop
54
60
 
61
+ children :from, :to
62
+
63
+ # Is this an exclusive flip flop? If no, run both branches
64
+ def excl
65
+ ""
66
+ end
67
+
68
+ # We create a function that we put in the top scope, that stores the state of our
69
+ # flip-flop. We pass to it functions that are ran with the current binding.
55
70
  def compile
56
- # Unsupported
57
- # Always compiles to 'true' to not break generated JS
58
- push 'true'
71
+ helper :truthy
72
+
73
+ fun_name = top_scope.new_temp
74
+ ff = "#{fun_name}.$$ff"
75
+
76
+ push "(typeof #{fun_name} === 'undefined' ? (#{fun_name} = function(from, to){"
77
+ push " if (typeof #{ff} === 'undefined') #{ff} = false;"
78
+ push " var retval = #{ff};"
79
+ push " if (!#{ff}) {"
80
+ push " #{ff} = retval = $truthy(from());"
81
+ push " }"
82
+ push " #{excl}if (#{ff}) {"
83
+ push " if ($truthy(to())) #{ff} = false;"
84
+ push " }"
85
+ push " return retval;"
86
+ push "}) : #{fun_name})("
87
+ push " function() { ", stmt(compiler.returns(from)), " },"
88
+ push " function() { ", stmt(compiler.returns(to)), " }"
89
+ push ")"
59
90
  end
60
91
  end
61
92
 
62
- class EFlipFlop < Base
93
+ class EFlipFlop < IFlipFlop
63
94
  handle :eflipflop
64
95
 
65
- def compile
66
- # Unsupported
67
- # Always compiles to 'true' to not break generated JS
68
- push 'true'
96
+ # Is this an exclusive flip flop? If yes, run only a single branch
97
+ def excl
98
+ "else "
69
99
  end
70
100
  end
71
101
  end
@@ -11,6 +11,8 @@ module Opal
11
11
  children :inline_args, :body
12
12
 
13
13
  def compile
14
+ is_lambda! if scope.lambda_definition?
15
+
14
16
  inline_params = nil
15
17
 
16
18
  to_vars = identity = body_code = nil
@@ -25,13 +27,23 @@ module Opal
25
27
 
26
28
  body_code = stmt(returned_body)
27
29
  to_vars = scope.to_vars
28
- end
29
30
 
30
- line body_code
31
+ line body_code
32
+
33
+ if scope.catch_return
34
+ unshift "try {\n"
35
+ line '} catch ($returner) { if ($returner === Opal.returner) { return $returner.$v }'
36
+ push ' throw $returner; }'
37
+ end
38
+ end
31
39
 
32
40
  unshift to_vars
33
41
 
34
- unshift "(#{identity} = function(", inline_params, '){'
42
+ if await_encountered
43
+ unshift "(#{identity} = async function(", inline_params, '){'
44
+ else
45
+ unshift "(#{identity} = function(", inline_params, '){'
46
+ end
35
47
  push "}, #{identity}.$$s = self,"
36
48
  push " #{identity}.$$brk = $brk," if contains_break?
37
49
  push " #{identity}.$$arity = #{arity},"
@@ -11,7 +11,9 @@ module Opal
11
11
  def compile
12
12
  helper :lambda
13
13
 
14
- push '$lambda(', expr(iter), ')'
14
+ scope.defines_lambda do
15
+ push '$lambda(', expr(iter), ')'
16
+ end
15
17
  end
16
18
  end
17
19
  end
@@ -152,9 +152,6 @@ module Opal
152
152
  case value
153
153
  when ''
154
154
  push('/(?:)/')
155
- when %r{\?<\w+\>}
156
- message = "named captures are not supported in javascript: #{value.inspect}"
157
- push "self.$raise(new SyntaxError('#{message}'))"
158
155
  else
159
156
  push "#{Regexp.new(value).inspect}#{flags.join}"
160
157
  end
@@ -164,11 +161,10 @@ module Opal
164
161
  *values, flags_sexp = *children
165
162
  self.flags = flags_sexp.children.map(&:to_s)
166
163
 
167
- self.value = case values.length
168
- when 0
164
+ self.value = if values.empty?
169
165
  # empty regexp, we can process it inline
170
166
  s(:str, '')
171
- when 1
167
+ elsif single_line?(values)
172
168
  # simple plain regexp, we can put it inline
173
169
  values[0]
174
170
  else
@@ -200,6 +196,16 @@ module Opal
200
196
  def raw_value
201
197
  self.value = @sexp.loc.expression.source
202
198
  end
199
+
200
+ private
201
+
202
+ def single_line?(values)
203
+ return false if values.length > 1
204
+
205
+ value = values[0]
206
+ # JavaScript doesn't support multiline regexp
207
+ value.type != :str || !value.children[0].include?("\n")
208
+ end
203
209
  end
204
210
 
205
211
  # $_ = 'foo'; call if /foo/
@@ -229,7 +235,7 @@ module Opal
229
235
  push ' + '
230
236
 
231
237
  if part.type == :str
232
- push part.children[0].inspect
238
+ push expr(part)
233
239
  else
234
240
  push '(', expr(part), ')'
235
241
  end
@@ -126,13 +126,13 @@ module Opal
126
126
  end
127
127
 
128
128
  def return_in_iter?
129
- if scope.iter? && parent_def = scope.find_parent_def
129
+ if (scope.iter? && !scope.lambda?) && parent_def = scope.find_parent_def
130
130
  parent_def
131
131
  end
132
132
  end
133
133
 
134
134
  def return_expr_in_def?
135
- return scope if expr? && scope.def?
135
+ return scope if expr? && (scope.def? || scope.lambda?)
136
136
  end
137
137
 
138
138
  def scope_to_catch_return
@@ -13,13 +13,23 @@ module Opal
13
13
  name, base = name_and_base
14
14
  helper :module
15
15
 
16
- push '(function($base, $parent_nesting) {'
17
16
  line " var self = $module($base, '#{name}');"
18
17
  in_scope do
19
18
  scope.name = name
20
19
  compile_body
21
20
  end
22
- line '})(', base, ', $nesting)'
21
+
22
+ if await_encountered
23
+ await_begin = '(await '
24
+ await_end = ')'
25
+ async = 'async '
26
+ parent.await_encountered = true
27
+ else
28
+ await_begin, await_end, async = '', '', ''
29
+ end
30
+
31
+ unshift "#{await_begin}(#{async}function($base, $parent_nesting) {"
32
+ line '})(', base, ", $nesting)#{await_end}"
23
33
  end
24
34
 
25
35
  private