opal 1.2.0 → 1.3.0.alpha1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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