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
@@ -19,6 +19,8 @@ opal_unsupported_filter "Kernel" do
19
19
  fails "Kernel#eql? is a public instance method"
20
20
  fails "Kernel#fail is a private method"
21
21
  fails "Kernel#format is a private method"
22
+ fails "Kernel#initialize_clone returns the receiver" # Expected nil == #<Object:0x63440> to be truthy but was false
23
+ fails "Kernel#initialize_dup returns the receiver" # Expected nil == #<Object:0x4c314> to be truthy but was false
22
24
  fails "Kernel#inspect returns an untrusted string if self is untrusted"
23
25
  fails "Kernel#raise is a private method"
24
26
  fails "Kernel#sleep accepts a Rational"
@@ -27,9 +29,19 @@ opal_unsupported_filter "Kernel" do
27
29
  fails "Kernel#sprintf is a private method"
28
30
  fails "Kernel#to_s returns a tainted result if self is tainted"
29
31
  fails "Kernel#to_s returns an untrusted result if self is untrusted"
32
+ fails "Kernel#warn calls Warning.warn with category: nil if Warning.warn accepts keyword arguments" # NameError: uninitialized constant Warning
33
+ fails "Kernel#warn calls Warning.warn with given category keyword converted to a symbol" # NameError: uninitialized constant Warning
34
+ fails "Kernel#warn calls Warning.warn without keyword arguments if Warning.warn does not accept keyword arguments" # NameError: uninitialized constant Warning
30
35
  fails "Kernel#warn is a private method"
31
36
  fails "Kernel.Float raises a TypeError if #to_f returns an Integer"
32
37
  fails "Kernel.Integer calls to_i on Rationals"
33
38
  fails "Kernel.Integer returns a Fixnum or Bignum object"
34
39
  fails "Kernel.fail is a private method"
40
+ fails "Kernel.lambda when called without a literal block warns when proc isn't a lambda" # Expected warning: "ruby/core/kernel/lambda_spec.rb:142: warning: lambda without a literal block is deprecated; use the proc without lambda instead\n" but got: ""
41
+ fails "Kernel.printf formatting io is specified other formats s formats nil with width and precision" # Exception: format_string.indexOf is not a function
42
+ fails "Kernel.printf formatting io is specified other formats s formats nli with precision" # Exception: format_string.indexOf is not a function
43
+ fails "Kernel.printf formatting io is specified other formats s formats nli with width" # Exception: format_string.indexOf is not a function
44
+ fails "Kernel.printf formatting io is specified other formats s formats string with width and precision" # Exception: format_string.indexOf is not a function
45
+ fails "Kernel.printf formatting io is specified other formats s formats string with width" # Exception: format_string.indexOf is not a function
46
+ fails "Kernel.printf formatting io is specified other formats s substitutes '' for nil" # Exception: format_string.indexOf is not a function
35
47
  end
@@ -15,12 +15,15 @@ opal_unsupported_filter "private" do
15
15
  fails "Defining an 'initialize_copy' method sets the method's visibility to private"
16
16
  fails "Defining an 'initialize_dup' method sets the method's visibility to private"
17
17
  fails "Enumerator#initialize is a private method"
18
+ fails "Enumerator::Chain#initialize is a private method" # Expected Enumerator::Chain to have private instance method 'initialize' but it does not
18
19
  fails "Enumerator::Generator#initialize is a private method" # Expected Enumerator::Generator to have private instance method 'initialize' but it does not
19
20
  fails "Enumerator::Lazy#initialize is a private method" # Expected Enumerator::Lazy to have private instance method 'initialize' but it does not
20
21
  fails "Enumerator::Yielder#initialize is a private method" # Expected Enumerator::Yielder to have private instance method 'initialize' but it does not
21
22
  fails "Invoking a private getter method does not permit self as a receiver"
22
23
  fails "Kernel#block_given? is a private method"
23
24
  fails "Kernel#eval is a private method"
25
+ fails "Kernel#initialize_clone is a private instance method" # Expected Kernel to have private instance method 'initialize_clone' but it does not
26
+ fails "Kernel#initialize_dup is a private instance method" # Expected Kernel to have private instance method 'initialize_dup' but it does not
24
27
  fails "Kernel#iterator? is a private method"
25
28
  fails "Kernel#local_variables is a private method"
26
29
  fails "Kernel#methods returns private singleton methods defined by obj.meth"
@@ -419,6 +419,7 @@ opal_unsupported_filter "String" do
419
419
  fails "String#lstrip! raises a RuntimeError on a frozen instance that is modified"
420
420
  fails "String#lstrip! raises a RuntimeError on a frozen instance that would not be modified"
421
421
  fails "String#lstrip! returns nil if no modifications were made"
422
+ fails "String#lstrip! strips leading \\0" # NotImplementedError: String#lstrip! not supported. Mutable String methods are not supported in Opal.
422
423
  fails "String#match matches \\G at the start of the string"
423
424
  fails "String#next taints the result if self is tainted"
424
425
  fails "String#next! is equivalent to succ, but modifies self in place (still returns self)"
@@ -554,6 +555,7 @@ opal_unsupported_filter "String" do
554
555
  fails "String#strip! modifies self removing trailing NULL bytes and whitespace"
555
556
  fails "String#strip! raises a RuntimeError on a frozen instance that is modified"
556
557
  fails "String#strip! raises a RuntimeError on a frozen instance that would not be modified"
558
+ fails "String#strip! removes leading and trailing NULL bytes and whitespace" # NotImplementedError: String#strip! not supported. Mutable String methods are not supported in Opal.
557
559
  fails "String#strip! returns nil if no modifications where made"
558
560
  fails "String#sub with pattern and Hash ignores non-String keys" # Expected "tazoo" == "taboo" to be truthy but was false
559
561
  fails "String#sub with pattern and Hash taints the result if a hash value is tainted"
@@ -76,14 +76,14 @@ RSpec.describe Opal::Builder do
76
76
  expect(Opal::Config.compiler_options[:arity_check]).to eq(false)
77
77
  builder = described_class.new
78
78
  builder.build_str('def foo; end', 'foo')
79
- expect(builder.to_s).not_to include('$foo$1.$$parameters = []')
79
+ expect(builder.to_s).not_to include('$$parameters: []')
80
80
 
81
81
  Opal::Config.arity_check_enabled = true
82
82
  expect(Opal::Config.arity_check_enabled).to eq(true)
83
83
  expect(Opal::Config.compiler_options[:arity_check]).to eq(true)
84
84
  builder = described_class.new
85
85
  builder.build_str('def foo; end', 'foo')
86
- expect(builder.to_s).to include('$foo$1.$$parameters = []')
86
+ expect(builder.to_s).to include('$$parameters: []')
87
87
  end
88
88
 
89
89
  describe '#missing_require_severity' do
data/spec/lib/cli_spec.rb CHANGED
@@ -223,7 +223,7 @@ RSpec.describe Opal::CLI do
223
223
  let(:options) { { parse_comments: true, evals: [code], runner: :compiler } }
224
224
 
225
225
  it 'sets $$comment prop for compiled methods' do
226
- expect_output_of { subject.run }.to include('$$comments = ["# multiline", "# comment"]')
226
+ expect_output_of { subject.run }.to include('$$comments: ["# multiline", "# comment"]')
227
227
  end
228
228
  end
229
229
 
@@ -35,7 +35,7 @@ RSpec.describe Opal::Compiler do
35
35
  expect_compiled("123E+10").to include("return 1230000000000")
36
36
  expect_compiled("false").to include("return false")
37
37
  expect_compiled("true").to include("return true")
38
- expect_compiled("nil").to include("return nil")
38
+ expect_compiled("0;nil").to include("return nil") # NB: Empty nil return is compiled-out
39
39
  end
40
40
 
41
41
  it "should compile ruby strings" do
@@ -66,15 +66,15 @@ RSpec.describe Opal::Compiler do
66
66
 
67
67
  it "should compile method calls" do
68
68
  expect_compiled("self.inspect").to include("$inspect()")
69
- expect_compiled("self.map { |a| a + 10 }").to include("$map")
69
+ expect_compiled("self.map { |a| a + 10 }").to include("'map'")
70
70
  end
71
71
 
72
72
  it "adds method missing stubs" do
73
- expect_compiled("self.puts 'hello'").to include("Opal.add_stubs(['$puts'])")
73
+ expect_compiled("self.puts 'hello'").to include("Opal.add_stubs('puts')")
74
74
  end
75
75
 
76
76
  it 'adds method missing stubs with operators' do
77
- expect_compiled("class Foo; end; Foo.new > 5").to include("Opal.add_stubs(['$>', '$new'])")
77
+ expect_compiled("class Foo; end; Foo.new > 5").to include("Opal.add_stubs('>,new')")
78
78
  end
79
79
 
80
80
  it "should compile constant lookups" do
@@ -99,8 +99,8 @@ RSpec.describe Opal::Compiler do
99
99
  end
100
100
 
101
101
  context "when function name is not valid" do
102
- it "skips generating a name" do
103
- expect_compiled("def test_method?; end").to include("function()")
102
+ it "generates a name in a safe way" do
103
+ expect_compiled("def test_method?; end").to include("function $test_method$ques$1()")
104
104
  end
105
105
  end
106
106
  end
@@ -207,34 +207,42 @@ RSpec.describe Opal::Compiler do
207
207
  expect_compiled('foo = 42 if 2 > 3').to include('if ($rb_gt(2, 3))')
208
208
  expect_compiled('foo = 42 if 2.5 > 3.5').to include('if ($rb_gt(2.5, 3.5))')
209
209
  expect_compiled('foo = 42 if true > false').to include('if ($rb_gt(true, false))')
210
-
211
- expect_compiled('foo = 42 if 2 == 3').to include("if ((2)['$=='](3))")
212
- expect_compiled('foo = 42 if 2.5 == 3.5').to include("if ((2.5)['$=='](3.5))")
213
- expect_compiled('foo = 42 if true == false').to include("if (true['$=='](false))")
214
210
  end
215
211
 
216
212
  it 'adds nil check for strings' do
217
213
  expect_compiled('foo = 42 if "test" > "bar"').to include('if ($truthy($rb_gt("test", "bar")))')
218
214
  end
219
215
 
220
- it 'specifically == excludes nil check for strings' do
221
- expect_compiled('foo = 42 if "test" == "bar"').to include("if (\"test\"['$=='](\"bar\"))")
222
- end
223
-
224
216
  it 'adds nil check for lvars' do
225
217
  expect_compiled("bar = 4\nfoo = 42 if bar > 5").to include('if ($truthy($rb_gt(bar, 5)))')
226
218
  end
227
219
 
228
- it 'specifically == excludes nil check for lvars' do
229
- expect_compiled("bar = 4\nfoo = 42 if bar == 5").to include("if (bar['$=='](5))")
220
+ it 'adds nil check for constants' do
221
+ expect_compiled("foo = 42 if Test > 4").to include("if ($truthy($rb_gt($$('Test'), 4))) ")
230
222
  end
231
223
 
232
- it 'adds nil check for constants' do
233
- expect_compiled("foo = 42 if Test > 4").to include("if ($truthy($rb_gt($$($nesting, 'Test'), 4))) ")
224
+ it 'converts each == call inside if to an $eqeq wrapper, which does a truthy check' do
225
+ expect_compiled('foo = 42 if 2 == 3').to include("if ($eqeq(2, 3))")
226
+ expect_compiled('foo = 42 if 2.5 == 3.5').to include("if ($eqeq(2.5, 3.5))")
227
+ expect_compiled('foo = 42 if true == false').to include("if ($eqeq(true, false))")
228
+ expect_compiled('foo = 42 if "test" == "bar"').to include("if ($eqeq(\"test\", \"bar\"))")
229
+ expect_compiled("bar = 4\nfoo = 42 if bar == 5").to include("if ($eqeq(bar, 5))")
230
+ expect_compiled("foo = 42 if Test == 4").to include("if ($eqeq($$('Test'), 4))")
231
+ expect_compiled("bar = 4\nfoo = 42 if bar == 5").to include("if ($eqeq(bar, 5))")
232
+ end
233
+
234
+ it "doesn't convert ==/=== calls to $eqeq(eq) wrappers outside of an if" do
235
+ expect_compiled("bar == 5").not_to include("$eqeq(bar, 5)")
234
236
  end
235
237
 
236
- it 'specifically == excludes nil check for constants' do
237
- expect_compiled("foo = 42 if Test == 4").to include("if ($$($nesting, 'Test')['$=='](4))")
238
+ it 'converts each === call inside if to an $eqeqeq wrapper, which does a truthy check' do
239
+ expect_compiled('foo = 42 if 2 === 3').to include("if ($eqeqeq(2, 3))")
240
+ expect_compiled('foo = 42 if 2.5 === 3.5').to include("if ($eqeqeq(2.5, 3.5))")
241
+ expect_compiled('foo = 42 if true === false').to include("if ($eqeqeq(true, false))")
242
+ expect_compiled('foo = 42 if "test" === "bar"').to include("if ($eqeqeq(\"test\", \"bar\"))")
243
+ expect_compiled("bar = 4\nfoo = 42 if bar === 5").to include("if ($eqeqeq(bar, 5))")
244
+ expect_compiled("foo = 42 if Test === 4").to include("if ($eqeqeq($$('Test'), 4))")
245
+ expect_compiled("bar = 4\nfoo = 42 if bar === 5").to include("if ($eqeqeq(bar, 5))")
238
246
  end
239
247
  end
240
248
 
@@ -258,36 +266,28 @@ RSpec.describe Opal::Compiler do
258
266
  end
259
267
 
260
268
  it 'adds nil check for constants' do
261
- expect_compiled("foo = 42 if Test").to include("if ($truthy($$($nesting, 'Test')))")
269
+ expect_compiled("foo = 42 if Test").to include("if ($truthy($$('Test')))")
262
270
  end
263
271
  end
264
272
  end
265
273
 
266
274
  context 'parentheses' do
267
275
  context 'with operators' do
268
- it 'adds nil check for primitives' do
269
- expect_compiled('foo = 42 if (2 > 3)').to include('if ($truthy($rb_gt(2, 3))')
270
- expect_compiled('foo = 42 if (2.5 > 3.5)').to include('if ($truthy($rb_gt(2.5, 3.5))')
271
- expect_compiled('foo = 42 if (true > false)').to include('if ($truthy($rb_gt(true, false))')
272
-
273
- expect_compiled('foo = 42 if (2 == 3)').to include("if ($truthy((2)['$=='](3))")
274
- expect_compiled('foo = 42 if (2.5 == 3.5)').to include("if ($truthy((2.5)['$=='](3.5))")
275
- expect_compiled('foo = 42 if (true == false)').to include("if ($truthy(true['$=='](false)))")
276
- end
277
-
278
276
  it 'adds nil check for strings' do
279
277
  expect_compiled('foo = 42 if ("test" > "bar")').to include('if ($truthy($rb_gt("test", "bar"))')
280
- expect_compiled('foo = 42 if ("test" == "bar")').to include("if ($truthy(\"test\"['$=='](\"bar\"))")
281
278
  end
282
279
 
283
280
  it 'adds nil check for lvars' do
284
281
  expect_compiled("bar = 4\nfoo = 42 if (bar > 5)").to include('if ($truthy($rb_gt(bar, 5))')
285
- expect_compiled("bar = 4\nfoo = 42 if (bar == 5)").to include("if ($truthy(bar['$=='](5))) ")
286
282
  end
287
283
 
288
- it 'adds nil check for constants' do
289
- expect_compiled("foo = 42 if (Test > 4)").to include("if ($truthy($rb_gt($$($nesting, 'Test'), 4))")
290
- expect_compiled("foo = 42 if (Test == 4)").to include("if ($truthy($$($nesting, 'Test')['$=='](4))")
284
+ it 'converts == expressions to $eqeq checks' do
285
+ expect_compiled('foo = 42 if (2 == 3)').to include("if ($eqeq(2, 3))")
286
+ expect_compiled('foo = 42 if (2.5 == 3.5)').to include("if ($eqeq(2.5, 3.5))")
287
+ expect_compiled('foo = 42 if (true == false)').to include("if ($eqeq(true, false))")
288
+ expect_compiled('foo = 42 if ("test" == "bar")').to include("if ($eqeq(\"test\", \"bar\")")
289
+ expect_compiled("bar = 4\nfoo = 42 if (bar == 5)").to include("if ($eqeq(bar, 5))")
290
+ expect_compiled("foo = 42 if (Test == 4)").to include("if ($eqeq($$('Test'), 4))")
291
291
  end
292
292
  end
293
293
 
@@ -311,7 +311,7 @@ RSpec.describe Opal::Compiler do
311
311
  end
312
312
 
313
313
  it 'adds nil check for constants' do
314
- expect_compiled("foo = 42 if (Test)").to include("if ($truthy($$($nesting, 'Test'))")
314
+ expect_compiled("foo = 42 if (Test)").to include("if ($truthy($$('Test'))")
315
315
  end
316
316
  end
317
317
  end
@@ -47,10 +47,10 @@ RSpec.describe Opal::SimpleServer do
47
47
 
48
48
  it 'respects config set in Opal::Config' do
49
49
  Opal::Config.arity_check_enabled = false
50
- expect(get('/assets/console.js').body).not_to include('$Console_clear$1.$$parameters = []')
50
+ expect(get('/assets/console.js').body).not_to include('$$parameters: []')
51
51
 
52
52
  Opal::Config.arity_check_enabled = true
53
53
  self.app = described_class.new(main: 'console')
54
- expect(get('/assets/console.js').body).to include('$Console_clear$1.$$parameters = []')
54
+ expect(get('/assets/console.js').body).to include('$$parameters: []')
55
55
  end
56
56
  end
@@ -19,7 +19,7 @@ RSpec.describe Opal::SourceMap::File do
19
19
  fragment(line: nil, column: nil, source_map_name: nil, code: "\n ", sexp_type: :top),
20
20
  fragment(line: nil, column: nil, source_map_name: nil, code: "var self = Opal.top, $nesting = [], nil = Opal.nil, $$$ = Opal.$$$, $$ = Opal.$$, $breaker = Opal.breaker, $slice = Opal.slice;\n", sexp_type: :top),
21
21
  fragment(line: nil, column: nil, source_map_name: nil, code: "\n ", sexp_type: :top),
22
- fragment(line: nil, column: nil, source_map_name: nil, code: "Opal.add_stubs(['$puts']);", sexp_type: :top),
22
+ fragment(line: nil, column: nil, source_map_name: nil, code: "Opal.add_stubs('puts');", sexp_type: :top),
23
23
  fragment(line: nil, column: nil, source_map_name: nil, code: "\n ", sexp_type: :top),
24
24
  fragment(line: 1, column: 0, source_map_name: nil, code: "\n ", sexp_type: :begin),
25
25
  fragment(line: nil, column: nil, source_map_name: "self", code: "self", sexp_type: :self),
@@ -5,14 +5,14 @@ describe Opal::Compiler do
5
5
  describe "irb parser option" do
6
6
  it "creates Opal.irb_vars if it does not exist" do
7
7
  $global["Opal"].irb_vars = nil
8
- eval_js compile("nil", :irb => true)
8
+ eval_js compile("0;nil", :irb => true)
9
9
 
10
10
  ($global["Opal"].irb_vars == nil).should be_false
11
11
  end
12
12
 
13
13
  it "does not create Opal.irb_vars if :irb option not passed" do
14
14
  $global["Opal"].irb_vars = nil
15
- eval_js compile("nil")
15
+ eval_js compile("0;nil")
16
16
 
17
17
  ($global["Opal"].irb_vars == nil).should be_true
18
18
  end
@@ -0,0 +1,90 @@
1
+ describe "IO#puts" do
2
+ before :each do
3
+ @before_separator = $/
4
+ @io = IO.new(123)
5
+ ScratchPad.record []
6
+ def @io.write(str)
7
+ ScratchPad << str
8
+ end
9
+ end
10
+
11
+ after :each do
12
+ ScratchPad.clear
13
+ @io.close if @io
14
+ suppress_warning {$/ = @before_separator}
15
+ end
16
+
17
+ it "writes just a newline when given no args" do
18
+ @io.puts.should == nil
19
+ ScratchPad.recorded.join("").should == "\n"
20
+ end
21
+
22
+ it "writes just a newline when given just a newline" do
23
+ @io.puts("\n").should == nil
24
+ ScratchPad.recorded.should == ["\n"]
25
+ end
26
+
27
+ it "writes empty string with a newline when given nil as an arg" do
28
+ @io.puts(nil).should == nil
29
+ ScratchPad.recorded.join("").should == "\n"
30
+ end
31
+
32
+ it "writes empty string with a newline when when given nil as multiple args" do
33
+ @io.puts(nil, nil).should == nil
34
+ ScratchPad.recorded.join("").should == "\n\n"
35
+ end
36
+
37
+ it "calls :to_s before writing non-string objects that don't respond to :to_ary" do
38
+ object = mock('hola')
39
+ object.should_receive(:to_s).and_return("hola")
40
+
41
+ @io.puts(object).should == nil
42
+ ScratchPad.recorded.join("").should == "hola\n"
43
+ end
44
+
45
+ # it "returns general object info if :to_s does not return a string" do
46
+ # object = mock('hola')
47
+ # object.should_receive(:to_s).and_return(false)
48
+ #
49
+ # @io.puts(object).should == nil
50
+ # ScratchPad.recorded.join("").should == object.inspect.split(" ")[0] + ">\n"
51
+ # end
52
+
53
+ it "writes each arg if given several" do
54
+ @io.puts(1, "two", 3).should == nil
55
+ ScratchPad.recorded.join("").should == "1\ntwo\n3\n"
56
+ end
57
+
58
+ it "flattens a nested array before writing it" do
59
+ @io.puts([1, 2, [3]]).should == nil
60
+ ScratchPad.recorded.join("").should == "1\n2\n3\n"
61
+ end
62
+
63
+ it "writes nothing for an empty array" do
64
+ @io.puts([]).should == nil
65
+ ScratchPad.recorded.should == []
66
+ end
67
+
68
+ # it "writes [...] for a recursive array arg" do
69
+ # x = []
70
+ # x << 2 << x
71
+ # @io.puts(x).should == nil
72
+ # ScratchPad.recorded.join("").should == "2\n[...]\n"
73
+ # end
74
+
75
+ it "writes a newline after objects that do not end in newlines" do
76
+ @io.puts(5).should == nil
77
+ ScratchPad.recorded.join("").should == "5\n"
78
+ end
79
+
80
+ it "does not write a newline after objects that end in newlines" do
81
+ @io.puts("5\n").should == nil
82
+ ScratchPad.recorded.join("").should == "5\n"
83
+ end
84
+
85
+ it "ignores the $/ separator global" do
86
+ suppress_warning {$/ = ":"}
87
+ @io.puts(5).should == nil
88
+ ScratchPad.recorded.join("").should == "5\n"
89
+ end
90
+ end
@@ -0,0 +1,24 @@
1
+ describe "a block with super" do
2
+ it "can be used to define multiple methods" do
3
+ block = proc {
4
+ super()
5
+ }
6
+
7
+ c1 = Class.new {
8
+ def foo; :foo; end
9
+ def bar; :bar; end
10
+ def foo_bar; [foo, bar]; end
11
+ }
12
+
13
+ c2 = Class.new(c1) {
14
+ define_method :foo, block
15
+ define_method :bar, block
16
+ define_method :foo_bar, block
17
+ }
18
+
19
+ obj = c2.new
20
+ obj.foo.should == :foo
21
+ obj.bar.should == :bar
22
+ obj.foo_bar.should == [:foo, :bar]
23
+ end
24
+ end
data/spec/ruby_specs CHANGED
@@ -39,8 +39,8 @@ ruby/core/complex
39
39
 
40
40
  ruby/core/enumerable
41
41
  ruby/core/enumerator
42
- !ruby/core/enumerator/arithmetic_sequence
43
- !ruby/core/enumerator/chain
42
+ ruby/core/enumerator/arithmetic_sequence
43
+ ruby/core/enumerator/chain
44
44
  ruby/core/enumerator/generator
45
45
  ruby/core/enumerator/lazy
46
46
  ruby/core/enumerator/yielder
@@ -198,7 +198,9 @@ ruby/library/matrix/vector
198
198
  ruby/library/pp
199
199
  ruby/library/securerandom
200
200
  ruby/library/set
201
+ ruby/library/shellwords
201
202
  ruby/library/singleton
202
203
  ruby/library/stringio/each_line_spec
203
204
  ruby/library/stringio/each_spec
204
205
  ruby/library/stringscanner
206
+ ruby/library/optionparser
@@ -29,7 +29,7 @@ module RewritersHelper
29
29
  def parse_without_rewriting(source)
30
30
  buffer = Opal::Parser::SourceBuffer.new('(eval)')
31
31
  buffer.source = source
32
- parser = Parser::Ruby30.new
32
+ parser = Parser::Ruby31.new
33
33
  parser.parse(buffer)
34
34
  end
35
35
  end
data/stdlib/bigdecimal.rb CHANGED
@@ -67,8 +67,6 @@ class BigDecimal < Numeric
67
67
  end
68
68
  end
69
69
 
70
- alias === ==
71
-
72
70
  def <=>(other)
73
71
  result = case other
74
72
  when self.class
@@ -123,8 +121,6 @@ class BigDecimal < Numeric
123
121
  self.class.new(result)
124
122
  end
125
123
 
126
- alias + add
127
-
128
124
  def ceil(n = nil)
129
125
  unless bignumber.JS.isFinite
130
126
  raise FloatDomainError, "Computation results to 'Infinity'"
@@ -188,8 +184,6 @@ class BigDecimal < Numeric
188
184
  self.class.new(bignumber.JS.minus(other.bignumber))
189
185
  end
190
186
 
191
- alias - minus
192
-
193
187
  def mult(other, digits = nil)
194
188
  other, _ = coerce(other)
195
189
 
@@ -200,8 +194,6 @@ class BigDecimal < Numeric
200
194
  self.class.new(bignumber.JS.times(other.bignumber).JS.round(digits, self.class.mode(ROUND_MODE)))
201
195
  end
202
196
 
203
- alias * mult
204
-
205
197
  def nan?
206
198
  bignumber.JS.isNaN
207
199
  end
@@ -211,8 +203,6 @@ class BigDecimal < Numeric
211
203
  self.class.new(bignumber.JS.dividedBy(other.bignumber))
212
204
  end
213
205
 
214
- alias / quo
215
-
216
206
  def sign
217
207
  if bignumber.JS.isNaN
218
208
  return SIGN_NaN
@@ -234,9 +224,15 @@ class BigDecimal < Numeric
234
224
  def to_s(s = '')
235
225
  bignumber.JS.toString
236
226
  end
237
- alias inspect to_s
238
227
 
239
228
  def zero?
240
229
  bignumber.JS.isZero
241
230
  end
231
+
232
+ alias === ==
233
+ alias + add
234
+ alias - minus
235
+ alias * mult
236
+ alias / quo
237
+ alias inspect to_s
242
238
  end
@@ -27,8 +27,6 @@ class Buffer
27
27
  `#{@native}.byteLength`
28
28
  end
29
29
 
30
- alias size length
31
-
32
30
  def get(offset, bits = 8, type = :unsigned, little = false)
33
31
  `#{@native}["get" + #{Buffer.name_for bits, type}](offset, little)`
34
32
  end
@@ -104,5 +102,7 @@ class Buffer
104
102
  def set_float64(offset, value, little = false)
105
103
  `#{@native}.setFloat64(offset, value, little)`
106
104
  end
105
+
106
+ alias size length
107
107
  end
108
108
  end
data/stdlib/buffer.rb CHANGED
@@ -30,8 +30,6 @@ class Buffer
30
30
  `#{@native}.byteLength`
31
31
  end
32
32
 
33
- alias size length
34
-
35
33
  def to_a(bits = 8, type = :unsigned)
36
34
  Array.new(self, bits, type)
37
35
  end
@@ -43,4 +41,6 @@ class Buffer
43
41
  def to_s
44
42
  to_a.to_a.pack('c*')
45
43
  end
44
+
45
+ alias size length
46
46
  end
data/stdlib/date.rb CHANGED
@@ -83,8 +83,6 @@ class Date
83
83
  ABBR_DAYNAMES = %w[Sun Mon Tue Wed Thu Fri Sat]
84
84
 
85
85
  class << self
86
- alias civil new
87
-
88
86
  def wrap(native)
89
87
  instance = allocate
90
88
  `#{instance}.date = #{native}`
@@ -344,6 +342,8 @@ class Date
344
342
  def gregorian_leap?(year)
345
343
  `(new Date(#{year}, 1, 29).getMonth()-1) === 0`
346
344
  end
345
+
346
+ alias civil new
347
347
  end
348
348
 
349
349
  def initialize(year = -4712, month = 1, day = 1, start = ITALY)
@@ -472,8 +472,6 @@ class Date
472
472
  }
473
473
  end
474
474
 
475
- alias eql? ==
476
-
477
475
  def clone
478
476
  Date.wrap(`new Date(#{@date}.getTime())`)
479
477
  end
@@ -588,8 +586,6 @@ class Date
588
586
  }
589
587
  end
590
588
 
591
- alias succ next
592
-
593
589
  def sunday?
594
590
  wday == 0
595
591
  end
@@ -680,4 +676,7 @@ class Date
680
676
  return [31, (leap ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month]
681
677
  }
682
678
  }
679
+
680
+ alias eql? ==
681
+ alias succ next
683
682
  end
data/stdlib/erb.rb CHANGED
@@ -10,6 +10,7 @@ class ERB
10
10
  end
11
11
 
12
12
  alias h html_escape
13
+
13
14
  module_function :h
14
15
  module_function :html_escape
15
16
  end
data/stdlib/js.rb CHANGED
@@ -58,11 +58,12 @@ module JS
58
58
  args << block if block
59
59
  g.JS[func].JS.apply(g, args)
60
60
  end
61
- alias method_missing call
62
61
 
63
62
  def [](name)
64
63
  `Opal.global[#{name}]`
65
64
  end
66
65
 
66
+ alias method_missing call
67
+
67
68
  extend self
68
69
  end
data/stdlib/native.rb CHANGED
@@ -261,10 +261,6 @@ class Native::Object < BasicObject
261
261
  `Opal.hasOwnProperty.call(#{@native}, #{name})`
262
262
  end
263
263
 
264
- alias key? has_key?
265
- alias include? has_key?
266
- alias member? has_key?
267
-
268
264
  def each(*args)
269
265
  if block_given?
270
266
  %x{
@@ -341,8 +337,6 @@ class Native::Object < BasicObject
341
337
  `Opal.is_a(self, klass)`
342
338
  end
343
339
 
344
- alias kind_of? is_a?
345
-
346
340
  def instance_of?(klass)
347
341
  `self.$$class === klass`
348
342
  end
@@ -358,6 +352,11 @@ class Native::Object < BasicObject
358
352
  def inspect
359
353
  "#<Native:#{`String(#{@native})`}>"
360
354
  end
355
+
356
+ alias include? has_key?
357
+ alias key? has_key?
358
+ alias kind_of? is_a?
359
+ alias member? has_key?
361
360
  end
362
361
 
363
362
  class Native::Array
@@ -435,11 +434,11 @@ class Native::Array
435
434
  `#{@native}[#{@length}]`
436
435
  end
437
436
 
438
- alias to_ary to_a
439
-
440
437
  def inspect
441
438
  to_a.inspect
442
439
  end
440
+
441
+ alias to_ary to_a
443
442
  end
444
443
 
445
444
  class Numeric
@@ -99,12 +99,12 @@ class << ARGF
99
99
  file.eof?
100
100
  end
101
101
 
102
- alias to_io file
103
- alias to_i fileno
104
- alias skip close
105
- alias path filename
106
102
  alias each_line each
107
103
  alias eof eof?
104
+ alias path filename
105
+ alias skip close
106
+ alias to_i fileno
107
+ alias to_io file
108
108
  end
109
109
 
110
110
  ARGF.lineno = 1