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.
Files changed (222) hide show
  1. checksums.yaml +4 -4
  2. data/.eslintrc.js +1 -0
  3. data/.github/workflows/build.yml +0 -3
  4. data/.rubocop.yml +5 -1
  5. data/UNRELEASED.md +66 -2
  6. data/benchmark-ips/bm_truthy.rb +30 -0
  7. data/bin/opal-mspec +1 -3
  8. data/bin/opal-repl +1 -2
  9. data/bin/remove-filters +1 -4
  10. data/docs/compiled_ruby.md +10 -6
  11. data/exe/opal-repl +1 -3
  12. data/lib/opal/ast/builder.rb +1 -1
  13. data/lib/opal/cli.rb +2 -2
  14. data/lib/opal/cli_runners/nodejs.rb +9 -2
  15. data/lib/opal/cli_runners/source-map-support-browser.js +80 -216
  16. data/lib/opal/cli_runners/source-map-support-node.js +80 -216
  17. data/lib/opal/cli_runners/source-map-support.js +5 -1
  18. data/lib/opal/cli_runners/system_runner.rb +10 -4
  19. data/lib/opal/compiler.rb +3 -5
  20. data/lib/opal/fragment.rb +5 -1
  21. data/lib/opal/nodes/args/extract_block_arg.rb +1 -8
  22. data/lib/opal/nodes/args/extract_kwoptarg.rb +1 -3
  23. data/lib/opal/nodes/args/extract_optarg.rb +1 -3
  24. data/lib/opal/nodes/args/extract_post_arg.rb +2 -5
  25. data/lib/opal/nodes/args/extract_post_optarg.rb +2 -7
  26. data/lib/opal/nodes/args/initialize_iterarg.rb +1 -3
  27. data/lib/opal/nodes/args/prepare_post_args.rb +5 -1
  28. data/lib/opal/nodes/base.rb +3 -2
  29. data/lib/opal/nodes/call.rb +20 -9
  30. data/lib/opal/nodes/call_special.rb +50 -0
  31. data/lib/opal/nodes/class.rb +24 -15
  32. data/lib/opal/nodes/constants.rb +23 -5
  33. data/lib/opal/nodes/def.rb +20 -23
  34. data/lib/opal/nodes/defined.rb +5 -5
  35. data/lib/opal/nodes/definitions.rb +2 -2
  36. data/lib/opal/nodes/defs.rb +2 -5
  37. data/lib/opal/nodes/helpers.rb +48 -18
  38. data/lib/opal/nodes/if.rb +109 -8
  39. data/lib/opal/nodes/iter.rb +23 -16
  40. data/lib/opal/nodes/literal.rb +18 -4
  41. data/lib/opal/nodes/logic.rb +2 -1
  42. data/lib/opal/nodes/masgn.rb +4 -9
  43. data/lib/opal/nodes/module.rb +29 -19
  44. data/lib/opal/nodes/node_with_args.rb +1 -7
  45. data/lib/opal/nodes/scope.rb +54 -15
  46. data/lib/opal/nodes/singleton_class.rb +5 -3
  47. data/lib/opal/nodes/super.rb +3 -3
  48. data/lib/opal/nodes/top.rb +34 -31
  49. data/lib/opal/nodes/variables.rb +2 -2
  50. data/lib/opal/nodes/x_string.rb +3 -0
  51. data/lib/opal/nodes.rb +0 -1
  52. data/lib/opal/parser/patch.rb +75 -0
  53. data/lib/opal/parser/with_ruby_lexer.rb +1 -1
  54. data/lib/opal/regexp_anchors.rb +7 -7
  55. data/lib/opal/requires.rb +19 -0
  56. data/lib/opal/rewriters/pattern_matching.rb +1 -1
  57. data/lib/opal/rewriters/returnable_logic.rb +102 -4
  58. data/lib/opal/util.rb +2 -2
  59. data/lib/opal/version.rb +1 -1
  60. data/lib/opal.rb +1 -17
  61. data/opal/corelib/array/pack.rb +11 -11
  62. data/opal/corelib/array.rb +193 -152
  63. data/opal/corelib/basic_object.rb +14 -14
  64. data/opal/corelib/binding.rb +7 -7
  65. data/opal/corelib/boolean.rb +12 -15
  66. data/opal/corelib/class.rb +23 -1
  67. data/opal/corelib/comparable.rb +8 -8
  68. data/opal/corelib/complex/base.rb +2 -2
  69. data/opal/corelib/complex.rb +79 -88
  70. data/opal/corelib/constants.rb +9 -9
  71. data/opal/corelib/dir.rb +4 -3
  72. data/opal/corelib/enumerable.rb +140 -127
  73. data/opal/corelib/enumerator/arithmetic_sequence.rb +177 -0
  74. data/opal/corelib/enumerator/chain.rb +42 -0
  75. data/opal/corelib/enumerator/generator.rb +35 -0
  76. data/opal/corelib/enumerator/lazy.rb +243 -0
  77. data/opal/corelib/enumerator/yielder.rb +36 -0
  78. data/opal/corelib/enumerator.rb +45 -300
  79. data/opal/corelib/error/errno.rb +47 -0
  80. data/opal/corelib/error.rb +62 -60
  81. data/opal/corelib/file.rb +26 -12
  82. data/opal/corelib/hash.rb +98 -107
  83. data/opal/corelib/helpers.rb +62 -13
  84. data/opal/corelib/io.rb +47 -34
  85. data/opal/corelib/kernel/format.rb +29 -29
  86. data/opal/corelib/kernel.rb +86 -83
  87. data/opal/corelib/main.rb +14 -12
  88. data/opal/corelib/marshal/read_buffer.rb +15 -15
  89. data/opal/corelib/marshal/write_buffer.rb +45 -44
  90. data/opal/corelib/marshal.rb +3 -3
  91. data/opal/corelib/math.rb +50 -50
  92. data/opal/corelib/method.rb +12 -8
  93. data/opal/corelib/module.rb +96 -79
  94. data/opal/corelib/nil.rb +9 -11
  95. data/opal/corelib/number.rb +113 -118
  96. data/opal/corelib/numeric.rb +37 -33
  97. data/opal/corelib/object_space.rb +11 -10
  98. data/opal/corelib/pack_unpack/format_string_parser.rb +3 -3
  99. data/opal/corelib/pattern_matching/base.rb +7 -7
  100. data/opal/corelib/pattern_matching.rb +1 -1
  101. data/opal/corelib/proc.rb +15 -16
  102. data/opal/corelib/process/base.rb +2 -2
  103. data/opal/corelib/process/status.rb +21 -0
  104. data/opal/corelib/process.rb +5 -5
  105. data/opal/corelib/random/formatter.rb +11 -11
  106. data/opal/corelib/random/math_random.js.rb +1 -1
  107. data/opal/corelib/random/mersenne_twister.rb +3 -3
  108. data/opal/corelib/random/seedrandom.js.rb +3 -3
  109. data/opal/corelib/random.rb +17 -17
  110. data/opal/corelib/range.rb +51 -35
  111. data/opal/corelib/rational/base.rb +4 -4
  112. data/opal/corelib/rational.rb +61 -62
  113. data/opal/corelib/regexp.rb +47 -38
  114. data/opal/corelib/runtime.js +245 -139
  115. data/opal/corelib/string/encoding.rb +21 -21
  116. data/opal/corelib/string/unpack.rb +19 -14
  117. data/opal/corelib/string.rb +135 -128
  118. data/opal/corelib/struct.rb +59 -46
  119. data/opal/corelib/time.rb +47 -57
  120. data/opal/corelib/trace_point.rb +2 -2
  121. data/opal/corelib/unsupported.rb +31 -120
  122. data/opal/corelib/variables.rb +3 -3
  123. data/opal/opal/base.rb +9 -8
  124. data/opal/opal/full.rb +8 -8
  125. data/opal/opal/mini.rb +17 -17
  126. data/opal/opal.rb +17 -18
  127. data/opal.gemspec +1 -1
  128. data/spec/filters/bugs/array.rb +4 -24
  129. data/spec/filters/bugs/bigdecimal.rb +0 -23
  130. data/spec/filters/bugs/binding.rb +0 -1
  131. data/spec/filters/bugs/boolean.rb +3 -0
  132. data/spec/filters/bugs/class.rb +2 -0
  133. data/spec/filters/bugs/date.rb +0 -5
  134. data/spec/filters/bugs/encoding.rb +8 -50
  135. data/spec/filters/bugs/enumerable.rb +4 -1
  136. data/spec/filters/bugs/enumerator.rb +3 -36
  137. data/spec/filters/bugs/exception.rb +0 -2
  138. data/spec/filters/bugs/file.rb +0 -2
  139. data/spec/filters/bugs/float.rb +0 -3
  140. data/spec/filters/bugs/hash.rb +5 -3
  141. data/spec/filters/bugs/integer.rb +2 -3
  142. data/spec/filters/bugs/kernel.rb +2 -31
  143. data/spec/filters/bugs/language.rb +29 -49
  144. data/spec/filters/bugs/main.rb +0 -2
  145. data/spec/filters/bugs/marshal.rb +2 -3
  146. data/spec/filters/bugs/matrix.rb +0 -36
  147. data/spec/filters/bugs/module.rb +7 -61
  148. data/spec/filters/bugs/numeric.rb +0 -7
  149. data/spec/filters/bugs/objectspace.rb +1 -1
  150. data/spec/filters/bugs/pack_unpack.rb +0 -4
  151. data/spec/filters/bugs/proc.rb +0 -9
  152. data/spec/filters/bugs/random.rb +0 -5
  153. data/spec/filters/bugs/range.rb +1 -6
  154. data/spec/filters/bugs/regexp.rb +0 -3
  155. data/spec/filters/bugs/set.rb +8 -1
  156. data/spec/filters/bugs/string.rb +9 -34
  157. data/spec/filters/bugs/stringscanner.rb +8 -7
  158. data/spec/filters/bugs/struct.rb +2 -3
  159. data/spec/filters/bugs/symbol.rb +0 -1
  160. data/spec/filters/bugs/time.rb +0 -8
  161. data/spec/filters/bugs/unboundmethod.rb +0 -8
  162. data/spec/filters/bugs/warnings.rb +1 -7
  163. data/spec/filters/unsupported/freeze.rb +24 -0
  164. data/spec/filters/unsupported/integer.rb +1 -0
  165. data/spec/filters/unsupported/kernel.rb +12 -0
  166. data/spec/filters/unsupported/privacy.rb +3 -0
  167. data/spec/filters/unsupported/string.rb +2 -0
  168. data/spec/lib/builder_spec.rb +2 -2
  169. data/spec/lib/cli_spec.rb +1 -1
  170. data/spec/lib/compiler_spec.rb +37 -37
  171. data/spec/lib/simple_server_spec.rb +2 -2
  172. data/spec/lib/source_map/file_spec.rb +1 -1
  173. data/spec/opal/compiler/irb_spec.rb +2 -2
  174. data/spec/opal/core/kernel/puts_spec.rb +90 -0
  175. data/spec/opal/core/language/super_spec.rb +24 -0
  176. data/spec/ruby_specs +4 -2
  177. data/spec/support/rewriters_helper.rb +1 -1
  178. data/stdlib/bigdecimal.rb +7 -11
  179. data/stdlib/buffer/view.rb +2 -2
  180. data/stdlib/buffer.rb +2 -2
  181. data/stdlib/date.rb +5 -6
  182. data/stdlib/erb.rb +1 -0
  183. data/stdlib/js.rb +2 -1
  184. data/stdlib/native.rb +7 -8
  185. data/stdlib/nodejs/argf.rb +4 -4
  186. data/stdlib/nodejs/base.rb +29 -0
  187. data/stdlib/nodejs/dir.rb +1 -1
  188. data/stdlib/nodejs/env.rb +6 -9
  189. data/stdlib/nodejs/file.rb +23 -17
  190. data/stdlib/nodejs/fileutils.rb +3 -3
  191. data/stdlib/nodejs/io.rb +2 -20
  192. data/stdlib/nodejs/irb.rb +0 -0
  193. data/stdlib/nodejs/kernel.rb +2 -37
  194. data/stdlib/nodejs.rb +1 -3
  195. data/stdlib/opal/miniracer.rb +2 -0
  196. data/stdlib/opal/platform.rb +6 -13
  197. data/stdlib/opal/replutils.rb +16 -5
  198. data/stdlib/opal-parser.rb +2 -2
  199. data/stdlib/optparse/ac.rb +54 -0
  200. data/stdlib/optparse/date.rb +14 -0
  201. data/stdlib/optparse/kwargs.rb +22 -0
  202. data/stdlib/optparse/shellwords.rb +7 -0
  203. data/stdlib/optparse/time.rb +15 -0
  204. data/stdlib/optparse/uri.rb +7 -0
  205. data/stdlib/optparse/version.rb +69 -0
  206. data/stdlib/optparse.rb +2279 -0
  207. data/stdlib/pathname.rb +5 -6
  208. data/stdlib/pp.rb +18 -2
  209. data/stdlib/promise/v2.rb +18 -22
  210. data/stdlib/promise.rb +15 -21
  211. data/stdlib/set.rb +32 -32
  212. data/stdlib/shellwords.rb +240 -0
  213. data/stdlib/stringio.rb +3 -6
  214. data/stdlib/strscan.rb +5 -8
  215. data/stdlib/template.rb +2 -2
  216. data/stdlib/thread.rb +7 -9
  217. data/tasks/performance.rake +5 -2
  218. data/tasks/testing/mspec_special_calls.rb +0 -12
  219. data/tasks/testing.rake +55 -37
  220. data/test/nodejs/test_file.rb +11 -0
  221. metadata +55 -10
  222. data/lib/opal/nodes/case.rb +0 -114
@@ -37,6 +37,7 @@ module Opal
37
37
  case child.type
38
38
  when :str
39
39
  value = child.loc.expression.source
40
+ scope.self if value.include? 'self'
40
41
  push Fragment.new(value, scope, child)
41
42
  when :begin, :gvar, :ivar, :nil
42
43
  push expr(child)
@@ -81,6 +82,8 @@ module Opal
81
82
  def extract_last_value(last_child)
82
83
  last_value = last_child.loc.expression.source.rstrip
83
84
 
85
+ scope.self if last_value.include? 'self'
86
+
84
87
  if (@returning || expr?) && last_value.end_with?(';')
85
88
  compiler.warning(
86
89
  'Removed semicolon ending x-string expression, interpreted as unintentional',
data/lib/opal/nodes.rb CHANGED
@@ -20,7 +20,6 @@ require 'opal/nodes/logic'
20
20
  require 'opal/nodes/definitions'
21
21
  require 'opal/nodes/yield'
22
22
  require 'opal/nodes/rescue'
23
- require 'opal/nodes/case'
24
23
  require 'opal/nodes/super'
25
24
  require 'opal/nodes/top'
26
25
  require 'opal/nodes/while'
@@ -48,6 +48,81 @@ if RUBY_ENGINE == 'opal'
48
48
  diagnostic :error, :lvar_name, { name: name }, loc
49
49
  end
50
50
  end
51
+
52
+ # Taken From:
53
+ # https://github.com/whitequark/parser/blob/a7c638b7b205db9213a56897b41a8e5620df766e/lib/parser/builders/default.rb#L388
54
+ def dedent_string(node, dedent_level)
55
+ unless dedent_level.nil?
56
+ dedenter = ::Parser::Lexer::Dedenter.new(dedent_level)
57
+
58
+ case node.type
59
+ when :str
60
+ node = node.updated(nil, [dedenter.dedent(node.children.first)])
61
+ when :dstr, :xstr
62
+ children = node.children.map do |str_node|
63
+ if str_node.type == :str
64
+ str_node = str_node.updated(nil, [dedenter.dedent(str_node.children.first)])
65
+ next nil if str_node.children.first.empty?
66
+ else
67
+ dedenter.interrupt
68
+ end
69
+ str_node
70
+ end
71
+
72
+ node = node.updated(nil, children.compact)
73
+ end
74
+ end
75
+
76
+ node
77
+ end
78
+ end
79
+
80
+ class Parser::Lexer::Dedenter
81
+ # Taken From:
82
+ # https://github.com/whitequark/parser/blob/b7a08031523d05b2f76b0bab22fac00b1d3fe653/lib/parser/lexer/dedenter.rb#L36
83
+ def dedent(string)
84
+ original_encoding = string.encoding
85
+ # Prevent the following error when processing binary encoded source.
86
+ # "\xC0".split # => ArgumentError (invalid byte sequence in UTF-8)
87
+ lines = string.force_encoding(Encoding::BINARY).split("\\\n")
88
+ if lines.length == 1
89
+ # If the line continuation sequence was found but there is no second
90
+ # line, it was not really a line continuation and must be ignored.
91
+ lines = [string.force_encoding(original_encoding)]
92
+ else
93
+ lines.map! { |s| s.force_encoding(original_encoding) }
94
+ end
95
+
96
+ lines.each_with_index do |line, index|
97
+ next if (index == 0) && !@at_line_begin
98
+ left_to_remove = @dedent_level
99
+ remove = 0
100
+
101
+ line.each_char do |char|
102
+ break if left_to_remove <= 0
103
+ case char
104
+ when "\s"
105
+ remove += 1
106
+ left_to_remove -= 1
107
+ when "\t"
108
+ break if TAB_WIDTH * (remove / TAB_WIDTH + 1) > @dedent_level
109
+ remove += 1
110
+ left_to_remove -= TAB_WIDTH
111
+ else
112
+ # no more spaces or tabs
113
+ break
114
+ end
115
+ end
116
+
117
+ lines[index] = line[remove..-1]
118
+ end
119
+
120
+ string = lines.join
121
+
122
+ @at_line_begin = string.end_with?("\n")
123
+
124
+ string
125
+ end
51
126
  end
52
127
  end
53
128
 
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class Opal::Parser::WithRubyLexer < Parser::Ruby30
3
+ class Opal::Parser::WithRubyLexer < Parser::Ruby31
4
4
  include Opal::Parser::DefaultConfig
5
5
  Opal::Parser.default_parser_class = self
6
6
  end
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Opal
4
- REGEXP_START = RUBY_ENGINE == 'opal' ? '^' : '\A'
5
- REGEXP_END = RUBY_ENGINE == 'opal' ? '$' : '\z'
4
+ self::REGEXP_START = RUBY_ENGINE == 'opal' ? '^' : '\A'
5
+ self::REGEXP_END = RUBY_ENGINE == 'opal' ? '$' : '\z'
6
6
 
7
7
  # Unicode characters in ranges
8
8
  # \u0001 - \u002F (blank unicode characters + space + !"#$%&'()*+,-./ chars)
@@ -11,7 +11,7 @@ module Opal
11
11
  # \u0060 (` char)
12
12
  # \u007B - \u007F ({|}~ chars})
13
13
  # are not allowed to be used in identifier in the beggining or middle of its name
14
- FORBIDDEN_STARTING_IDENTIFIER_CHARS = '\u0001-\u002F\u003A-\u0040\u005B-\u005E\u0060\u007B-\u007F'
14
+ self::FORBIDDEN_STARTING_IDENTIFIER_CHARS = '\u0001-\u002F\u003A-\u0040\u005B-\u005E\u0060\u007B-\u007F'
15
15
 
16
16
  # Unicode characters in ranges
17
17
  # \u0001 - \u0020 (blank unicode characters + space)
@@ -23,11 +23,11 @@ module Opal
23
23
  # \u007B - \u007F ({|}~ chars})
24
24
  # are not allowed to be used in identifier in the end of its name
25
25
  # In fact, FORBIDDEN_STARTING_IDENTIFIER_CHARS = FORBIDDEN_ENDING_IDENTIFIER_CHARS + \u0021 ('?') + \u003F ('!')
26
- FORBIDDEN_ENDING_IDENTIFIER_CHARS = '\u0001-\u0020\u0022-\u002F\u003A-\u003E\u0040\u005B-\u005E\u0060\u007B-\u007F'
27
- INLINE_IDENTIFIER_REGEXP = Regexp.new("[^#{FORBIDDEN_STARTING_IDENTIFIER_CHARS}]*[^#{FORBIDDEN_ENDING_IDENTIFIER_CHARS}]")
26
+ self::FORBIDDEN_ENDING_IDENTIFIER_CHARS = '\u0001-\u0020\u0022-\u002F\u003A-\u003E\u0040\u005B-\u005E\u0060\u007B-\u007F'
27
+ self::INLINE_IDENTIFIER_REGEXP = Regexp.new("[^#{self::FORBIDDEN_STARTING_IDENTIFIER_CHARS}]*[^#{self::FORBIDDEN_ENDING_IDENTIFIER_CHARS}]")
28
28
 
29
29
  # For constants rules are pretty much the same, but ':' is allowed and '?!' are not.
30
30
  # Plus it may start with a '::' which indicates that the constant comes from toplevel.
31
- FORBIDDEN_CONST_NAME_CHARS = '\u0001-\u0020\u0021-\u002F\u003B-\u003F\u0040\u005B-\u005E\u0060\u007B-\u007F'
32
- CONST_NAME_REGEXP = Regexp.new("#{REGEXP_START}(::)?[A-Z][^#{FORBIDDEN_CONST_NAME_CHARS}]*#{REGEXP_END}")
31
+ self::FORBIDDEN_CONST_NAME_CHARS = '\u0001-\u0020\u0021-\u002F\u003B-\u003F\u0040\u005B-\u005E\u0060\u007B-\u007F'
32
+ self::CONST_NAME_REGEXP = Regexp.new("#{self::REGEXP_START}(::)?[A-Z][^#{self::FORBIDDEN_CONST_NAME_CHARS}]*#{self::REGEXP_END}")
33
33
  end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'opal/config'
4
+ require 'opal/compiler'
5
+ require 'opal/builder'
6
+ require 'opal/builder_processors'
7
+ require 'opal/erb'
8
+ require 'opal/paths'
9
+ require 'opal/version'
10
+ require 'opal/errors'
11
+ require 'opal/source_map'
12
+ require 'opal/deprecations'
13
+
14
+ # Opal is a ruby to javascript compiler, with a runtime for running
15
+ # in any JavaScript environment.
16
+ module Opal
17
+ autoload :Server, 'opal/server' if RUBY_ENGINE != 'opal'
18
+ autoload :SimpleServer, 'opal/simple_server'
19
+ end
@@ -60,7 +60,7 @@ module Opal
60
60
  # raise NoMatchingPatternError, from
61
61
  def raise_no_matching_pattern_error(from)
62
62
  s(:send, nil, :raise,
63
- s(:const, nil, :NoMatchingPatternError),
63
+ s(:const, s(:cbase), :NoMatchingPatternError),
64
64
  s(:lvar, from)
65
65
  )
66
66
  end
@@ -11,22 +11,120 @@ module Opal
11
11
  "$ret_or_#{@counter}"
12
12
  end
13
13
 
14
+ def free_tmp
15
+ @counter -= 1
16
+ end
17
+
14
18
  def reset_tmp_counter!
15
19
  @counter = nil
16
20
  end
17
21
 
22
+ def on_if(node)
23
+ test, = *node.children
24
+ # The if_test metadata signifies that we don't care about the return value except if it's
25
+ # truthy or falsy. And those tests will be carried out by the respective $truthy helper calls.
26
+ test.meta[:if_test] = true if test
27
+ super
28
+ end
29
+
30
+ def on_case(node)
31
+ lhs, *whens, els = *node.children
32
+ els ||= s(:nil)
33
+ lhs_tmp = next_tmp if lhs
34
+
35
+ out = build_if_from_when(node, lhs, lhs_tmp, whens, els)
36
+ free_tmp if lhs
37
+ out
38
+ end
39
+
40
+ # `a || b` / `a or b`
18
41
  def on_or(node)
19
42
  lhs, rhs = *node.children
20
- lhs_tmp = next_tmp
21
43
 
22
- node.updated(:if, [s(:lvasgn, lhs_tmp, process(lhs)), s(:js_tmp, lhs_tmp), process(rhs)])
44
+ if node.meta[:if_test]
45
+ # Let's forward the if_test to the lhs and rhs - since we don't care about the exact return
46
+ # value of our or, we neither do care about a return value of our lhs or rhs.
47
+ lhs.meta[:if_test] = rhs.meta[:if_test] = true
48
+ out = process(node.updated(:if, [lhs, s(:true), rhs]))
49
+ else
50
+ lhs_tmp = next_tmp
51
+ out = process(node.updated(:if, [s(:lvasgn, lhs_tmp, lhs), s(:js_tmp, lhs_tmp), rhs]))
52
+ free_tmp
53
+ end
54
+ out
23
55
  end
24
56
 
57
+ # `a && b` / `a and b`
25
58
  def on_and(node)
26
59
  lhs, rhs = *node.children
27
- lhs_tmp = next_tmp
28
60
 
29
- node.updated(:if, [s(:lvasgn, lhs_tmp, process(lhs)), process(rhs), s(:js_tmp, lhs_tmp)])
61
+ if node.meta[:if_test]
62
+ lhs.meta[:if_test] = rhs.meta[:if_test] = true
63
+ out = process(node.updated(:if, [lhs, rhs, s(:false)]))
64
+ else
65
+ lhs_tmp = next_tmp
66
+ out = process(node.updated(:if, [s(:lvasgn, lhs_tmp, lhs), rhs, s(:js_tmp, lhs_tmp)]))
67
+ free_tmp
68
+ end
69
+ out
70
+ end
71
+
72
+ # Parser sometimes generates parentheses as a begin node. If it's a single node begin value, then
73
+ # let's forward the if_test metadata.
74
+ def on_begin(node)
75
+ if node.meta[:if_test] && node.children.count == 1
76
+ node.children.first.meta[:if_test] = true
77
+ end
78
+ node.meta.delete(:if_test)
79
+ super
80
+ end
81
+
82
+ private
83
+
84
+ def build_if_from_when(node, lhs, lhs_tmp, whens, els)
85
+ first_when, *next_whens = *whens
86
+
87
+ *parts, expr = *first_when.children
88
+
89
+ rule = build_rule_from_parts(node, lhs, lhs_tmp, parts)
90
+
91
+ first_when.updated(:if, [rule, process(expr), next_whens.empty? ? process(els) : build_if_from_when(nil, nil, lhs_tmp, next_whens, els)])
92
+ end
93
+
94
+ def build_rule_from_parts(node, lhs, lhs_tmp, parts)
95
+ lhs = if node && lhs_tmp
96
+ node.updated(:lvasgn, [lhs_tmp, process(lhs)])
97
+ else
98
+ s(:js_tmp, lhs_tmp)
99
+ end
100
+
101
+ first_part, *next_parts = *parts
102
+
103
+ subrule = if first_part.type == :splat
104
+ splat_on = first_part.children.first
105
+ iter_val = next_tmp
106
+ block = s(:send, process(splat_on), :any?,
107
+ s(:iter,
108
+ s(:args, s(:arg, iter_val)),
109
+ build_rule_from_parts(nil, nil, lhs_tmp, [s(:lvar, iter_val)])
110
+ )
111
+ )
112
+ if node && lhs_tmp
113
+ s(:begin, lhs, block)
114
+ else
115
+ block
116
+ end
117
+ elsif lhs_tmp
118
+ s(:send, process(first_part), :===, lhs)
119
+ else
120
+ process(first_part)
121
+ end
122
+
123
+ if next_parts.empty?
124
+ subrule
125
+ else
126
+ s(:if, subrule, s(:true), build_rule_from_parts(nil, nil, lhs_tmp, next_parts))
127
+ end
30
128
  end
31
129
  end
32
130
  end
data/lib/opal/util.rb CHANGED
@@ -14,8 +14,8 @@ module Opal
14
14
  #
15
15
  # @param str [String] string to minify
16
16
  # @return [String]
17
- def uglify(source)
18
- sh 'bin/yarn -s run terser -c', data: source
17
+ def uglify(source, mangle: false)
18
+ sh "bin/yarn -s run terser -c #{'-m' if mangle}", data: source
19
19
  end
20
20
 
21
21
  # Gzip code to check file size.
data/lib/opal/version.rb CHANGED
@@ -3,5 +3,5 @@
3
3
  module Opal
4
4
  # WHEN RELEASING:
5
5
  # Remember to update RUBY_ENGINE_VERSION in opal/corelib/constants.rb too!
6
- VERSION = '1.3.2'
6
+ VERSION = '1.4.0.alpha1'
7
7
  end
data/lib/opal.rb CHANGED
@@ -1,19 +1,3 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'opal/config'
4
- require 'opal/compiler'
5
- require 'opal/builder'
6
- require 'opal/builder_processors'
7
- require 'opal/erb'
8
- require 'opal/paths'
9
- require 'opal/version'
10
- require 'opal/errors'
11
- require 'opal/source_map'
12
- require 'opal/deprecations'
13
-
14
- # Opal is a ruby to javascript compiler, with a runtime for running
15
- # in any JavaScript environment.
16
- module Opal
17
- autoload :Server, 'opal/server'
18
- autoload :SimpleServer, 'opal/simple_server'
19
- end
3
+ require 'opal/requires'
@@ -2,7 +2,7 @@
2
2
 
3
3
  require 'corelib/pack_unpack/format_string_parser'
4
4
 
5
- class Array
5
+ class ::Array
6
6
  %x{
7
7
  // Format Parser
8
8
  var eachDirectiveAndCount = Opal.PackUnpack.eachDirectiveAndCount;
@@ -93,7 +93,7 @@ class Array
93
93
  var buffer = callback(data);
94
94
 
95
95
  return buffer.map(function(item) {
96
- return $coerce_to(item, #{Integer}, 'to_int')
96
+ return $coerce_to(item, #{::Integer}, 'to_int')
97
97
  });
98
98
  }
99
99
  }
@@ -103,7 +103,7 @@ class Array
103
103
  var buffer = callback(data);
104
104
 
105
105
  return buffer.map(function(item) {
106
- return $coerce_to(item, #{String}, 'to_str')
106
+ return $coerce_to(item, #{::String}, 'to_str')
107
107
  });
108
108
  }
109
109
  }
@@ -116,7 +116,7 @@ class Array
116
116
  return String.fromCodePoint(item);
117
117
  } catch (error) {
118
118
  if (error instanceof RangeError) {
119
- #{raise RangeError, 'value out of range'};
119
+ #{::Kernel.raise ::RangeError, 'value out of range'};
120
120
  }
121
121
  throw error;
122
122
  }
@@ -199,7 +199,7 @@ class Array
199
199
  }
200
200
  } else {
201
201
  if (buffer.length < count) {
202
- #{raise ArgumentError, 'too few arguments'};
202
+ #{::Kernel.raise ::ArgumentError, 'too few arguments'};
203
203
  }
204
204
  for (var i = 0; i < count; i++) {
205
205
  chunkData = callback(buffer);
@@ -225,9 +225,9 @@ class Array
225
225
  if (source === nil) {
226
226
  source = '';
227
227
  } else if (source === undefined) {
228
- #{raise ArgumentError, 'too few arguments'};
228
+ #{::Kernel.raise ::ArgumentError, 'too few arguments'};
229
229
  } else {
230
- source = $coerce_to(source, #{String}, 'to_str');
230
+ source = $coerce_to(source, #{::String}, 'to_str');
231
231
  }
232
232
 
233
233
  buffer = buffer.slice(1, buffer.length);
@@ -388,7 +388,7 @@ class Array
388
388
  }
389
389
 
390
390
  def pack(format)
391
- format = Opal.coerce_to!(format, String, :to_str).gsub(/\s/, '').delete("\000")
391
+ format = ::Opal.coerce_to!(format, ::String, :to_str).gsub(/\s/, '').delete("\000")
392
392
 
393
393
  %x{
394
394
  var output = '';
@@ -408,7 +408,7 @@ class Array
408
408
  chunkReader = readChunk[directive];
409
409
 
410
410
  if (chunkReader == null) {
411
- #{raise "Unsupported pack directive #{`directive`.inspect} (no chunk reader defined)"}
411
+ #{::Kernel.raise "Unsupported pack directive #{`directive`.inspect} (no chunk reader defined)"}
412
412
  }
413
413
 
414
414
  var chunkData = chunkReader(buffer, count);
@@ -418,7 +418,7 @@ class Array
418
418
  var handler = handlers[directive];
419
419
 
420
420
  if (handler == null) {
421
- #{raise "Unsupported pack directive #{`directive`.inspect} (no handler defined)"}
421
+ #{::Kernel.raise "Unsupported pack directive #{`directive`.inspect} (no handler defined)"}
422
422
  }
423
423
 
424
424
  return handler(chunk);
@@ -431,7 +431,7 @@ class Array
431
431
  var shouldAutocomplete = autocompletion[directive]
432
432
 
433
433
  if (shouldAutocomplete == null) {
434
- #{raise "Unsupported pack directive #{`directive`.inspect} (no autocompletion rule defined)"}
434
+ #{::Kernel.raise "Unsupported pack directive #{`directive`.inspect} (no autocompletion rule defined)"}
435
435
  }
436
436
 
437
437
  if (shouldAutocomplete) {