opal 1.8.0.alpha1 → 1.8.0.beta1

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 (90) hide show
  1. checksums.yaml +4 -4
  2. data/.eslintrc.js +1 -0
  3. data/README.md +7 -7
  4. data/UNRELEASED.md +14 -0
  5. data/docs/releasing.md +8 -16
  6. data/lib/opal/cli_runners/chrome.rb +5 -1
  7. data/lib/opal/nodes/closure.rb +15 -7
  8. data/lib/opal/nodes/defined.rb +1 -1
  9. data/lib/opal/nodes/literal.rb +10 -6
  10. data/lib/opal/nodes/rescue.rb +1 -1
  11. data/lib/opal/simple_server.rb +2 -2
  12. data/lib/opal/version.rb +1 -1
  13. data/opal/corelib/array.rb +39 -21
  14. data/opal/corelib/class.rb +26 -8
  15. data/opal/corelib/complex.rb +1 -1
  16. data/opal/corelib/constants.rb +2 -2
  17. data/opal/corelib/enumerator/arithmetic_sequence.rb +1 -1
  18. data/opal/corelib/error.rb +10 -0
  19. data/opal/corelib/hash.rb +30 -18
  20. data/opal/corelib/kernel.rb +0 -1
  21. data/opal/corelib/module.rb +44 -5
  22. data/opal/corelib/number.rb +28 -1
  23. data/opal/corelib/range.rb +1 -1
  24. data/opal/corelib/rational.rb +1 -1
  25. data/opal/corelib/runtime.js +124 -42
  26. data/opal/corelib/string.rb +36 -8
  27. data/opal/corelib/struct.rb +1 -1
  28. data/opal/corelib/time.rb +1 -1
  29. data/spec/filters/bugs/array.rb +58 -0
  30. data/spec/filters/bugs/basicobject.rb +7 -0
  31. data/spec/filters/bugs/bigdecimal.rb +1 -2
  32. data/spec/filters/bugs/binding.rb +1 -0
  33. data/spec/filters/bugs/class.rb +2 -3
  34. data/spec/filters/bugs/complex.rb +3 -0
  35. data/spec/filters/bugs/date.rb +5 -2
  36. data/spec/filters/bugs/datetime.rb +1 -0
  37. data/spec/filters/bugs/delegate.rb +1 -2
  38. data/spec/filters/bugs/encoding.rb +1 -1
  39. data/spec/filters/bugs/enumerable.rb +11 -0
  40. data/spec/filters/bugs/enumerator.rb +15 -2
  41. data/spec/filters/bugs/exception.rb +9 -4
  42. data/spec/filters/bugs/file.rb +2 -0
  43. data/spec/filters/bugs/float.rb +1 -0
  44. data/spec/filters/bugs/freeze.rb +5 -49
  45. data/spec/filters/bugs/hash.rb +1 -0
  46. data/spec/filters/bugs/integer.rb +5 -6
  47. data/spec/filters/bugs/kernel.rb +12 -5
  48. data/spec/filters/bugs/language.rb +33 -15
  49. data/spec/filters/bugs/marshal.rb +63 -4
  50. data/spec/filters/bugs/method.rb +2 -10
  51. data/spec/filters/bugs/module.rb +18 -7
  52. data/spec/filters/bugs/objectspace.rb +2 -0
  53. data/spec/filters/bugs/pathname.rb +1 -0
  54. data/spec/filters/bugs/proc.rb +4 -2
  55. data/spec/filters/bugs/random.rb +0 -3
  56. data/spec/filters/bugs/range.rb +1 -1
  57. data/spec/filters/bugs/rational.rb +2 -0
  58. data/spec/filters/bugs/refinement.rb +19 -0
  59. data/spec/filters/bugs/regexp.rb +27 -5
  60. data/spec/filters/bugs/ruby-32.rb +0 -4
  61. data/spec/filters/bugs/set.rb +10 -2
  62. data/spec/filters/bugs/singleton.rb +0 -2
  63. data/spec/filters/bugs/string.rb +140 -1
  64. data/spec/filters/bugs/struct.rb +15 -5
  65. data/spec/filters/bugs/time.rb +56 -2
  66. data/spec/filters/bugs/trace_point.rb +1 -0
  67. data/spec/filters/bugs/unboundmethod.rb +4 -9
  68. data/spec/filters/bugs/warnings.rb +0 -1
  69. data/spec/filters/platform/firefox/exception.rb +3 -3
  70. data/spec/filters/platform/firefox/kernel.rb +1 -0
  71. data/spec/filters/platform/safari/exception.rb +2 -2
  72. data/spec/filters/platform/safari/float.rb +1 -0
  73. data/spec/filters/platform/safari/kernel.rb +1 -0
  74. data/spec/filters/platform/safari/literal_regexp.rb +2 -2
  75. data/spec/filters/unsupported/hash.rb +1 -1
  76. data/spec/lib/compiler_spec.rb +4 -0
  77. data/spec/opal/core/class/clone_spec.rb +36 -0
  78. data/spec/opal/core/object_id_spec.rb +0 -6
  79. data/spec/opal/language/predefined_spec.rb +20 -0
  80. data/spec/opal/language/yield_spec.rb +43 -0
  81. data/spec/ruby_specs +0 -2
  82. data/stdlib/bigdecimal.rb +2 -0
  83. data/stdlib/delegate.rb +3 -4
  84. data/stdlib/pathname.rb +1 -1
  85. data/stdlib/promise/v2.rb +22 -7
  86. data/stdlib/stringio.rb +2 -0
  87. data/tasks/testing.rake +15 -11
  88. data/test/opal/promisev2/test_always.rb +14 -0
  89. data/test/opal/unsupported_and_bugs.rb +0 -8
  90. metadata +10 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c756d4ba883cb8f7c7bdfefa6b88cf4a2db0604d1ef8a906d7c58add76eee1bf
4
- data.tar.gz: e88f7de8d6add79b64c7d6b896fbd1c94f51edd34754e6da3ceb59e3fa501134
3
+ metadata.gz: 506ba9114548fa5c492467950421043dbf46d0b72df49eab40c5a62e6f6c2ce6
4
+ data.tar.gz: e59c280933851d6de0a63f42b19139e5b16c90f68fe0c4652cf555a5ef7e1968
5
5
  SHA512:
6
- metadata.gz: 1d9e3b8b4cc8decc9fc5644eb842ee84290bb0c6f231de362d259a691570296ac9fab95e400dccda20d317e12b7f3d58334d816a8f5279b304d0435d15ac699f
7
- data.tar.gz: '02883fef4e6869c54b718c370ddd03a934e50698eb37638da6788d212286fbc57ecab6c5e0c2c46bd02931ff75e39455f09a6de462157433b03cb8535d1ce76b'
6
+ metadata.gz: 8536d4701b9197c3cee876bb35bb3fd34cee5726241069d108fa12f8c83753c43d8bc6ac8f95fd867ee5da23ba98b2c8a1b3e284a56df7b6656ffa17850b36c4
7
+ data.tar.gz: b0f0283471809563e3ea29afcef0b911109aa7d9d9a1f04701c34f48facc8654f20cacc3bd7061273bf74d837c7ae1256d13249e1eb9371e6faa94e3f54fa22b
data/.eslintrc.js CHANGED
@@ -32,6 +32,7 @@ module.exports = {
32
32
  "Proxy": "readonly",
33
33
  "Reflect": "readonly",
34
34
  "Uint8Array": "readonly",
35
+ "Int32Array": "readonly",
35
36
  "WeakRef": "readonly",
36
37
  "Map": "readonly",
37
38
  }
data/README.md CHANGED
@@ -145,12 +145,7 @@ The test suite can be run using:
145
145
 
146
146
  $ bundle exec rake
147
147
 
148
- This will command will run all RSpec and MSpec examples in sequence.
149
-
150
- #### Automated runs
151
-
152
- A `Guardfile` with decent mappings between specs and lib/corelib/stdlib files is in place.
153
- Run `bundle exec guard -i` to start `guard`.
148
+ This command will run all RSpec and MSpec examples in sequence.
154
149
 
155
150
 
156
151
  ### MSpec
@@ -170,6 +165,11 @@ visit `http://localhost:9292/` in any web browser.
170
165
  $ rake rspec
171
166
 
172
167
 
168
+ ### Automated runs
169
+
170
+ A `Guardfile` with decent mappings between specs and lib/corelib/stdlib files is in place.
171
+ Run `bundle exec guard -i` to start `guard`.
172
+
173
173
  ## Code Overview
174
174
 
175
175
  What code is supposed to run where?
@@ -247,7 +247,7 @@ Support this project by becoming a sponsor. Your logo will show up here with a l
247
247
 
248
248
  ### Sponsored Contributions
249
249
 
250
- <a href="https://nebulab.it/?utm_source=github&utm_medium=sponsors" target="_blank"><img src="https://nebulab.com/assets/img/logo-nebulab_black.svg" alt="Nebulab Logo"></a>
250
+ <a href="https://nebulab.it/?utm_source=github&utm_medium=sponsors" target="_blank"><img src="https://raw.githubusercontent.com/solidusio/brand/master/partners/Nebulab/logo-dark-light.svg" alt="Nebulab Logo"></a>
251
251
 
252
252
 
253
253
  ## License
data/UNRELEASED.md CHANGED
@@ -41,6 +41,8 @@ This release brings a lot of performance improvements, our tests on Asciidoctor
41
41
  ### Compatibility
42
42
 
43
43
  - Add a magic-comment that will disable x-string compilation to JavaScript (#2543)
44
+ - Pass value in `PromiseV2#always` just like `PromiseV1#always` does it (#2579)
45
+ - `#hash` now returns integers #2582)
44
46
 
45
47
  ### Fixed
46
48
 
@@ -53,6 +55,13 @@ This release brings a lot of performance improvements, our tests on Asciidoctor
53
55
  - Propagate removal of method from included/prepended modules (#2553)
54
56
  - Restore `nodejs/yaml` functionality (#2551)
55
57
  - Fix sine `Range#size` edge cases (#2541)
58
+ - Use a Map instead of a POJO for the jsid_cache (#2584)
59
+ - Fix `String#object_id`, `String#__id__`, `String#hash` to match CRuby's behavior (#2576)
60
+ - Lowercase response headers in `SimpleServer` for rack 3.0 compatibility (#2578)
61
+ - Fix `Module#clone` and `Module#dup` to properly copy methods (#2572)
62
+ - Chrome runner fix: support code that contains `</script>` (#2581)
63
+ - Do not skip `$truthy` when left hand side of a comparison is `self` (#2596)
64
+ - Unexpected `return`/`break` should raise `LocalJumpError` (#2591)
56
65
 
57
66
  ### Added
58
67
 
@@ -67,6 +76,7 @@ This release brings a lot of performance improvements, our tests on Asciidoctor
67
76
  ### Documentation
68
77
 
69
78
  - Bridging documentation (#2541)
79
+ - Fix Typo in Running tests Section of README.md File (#2580)
70
80
 
71
81
  ### Performance
72
82
 
@@ -78,6 +88,10 @@ This release brings a lot of performance improvements, our tests on Asciidoctor
78
88
  - Optimize argument slicing in runtime for performance (#2555)
79
89
  - Closure: Generate a JavaScript object, not an Error, gain up to 15% on Asciidoctor (#2556)
80
90
  - Optimize `String#split` and `String#start_with` (#2560)
91
+ - Compute `$@` dynamically (#2592)
92
+ - Optimize the `$prop` helper (#2597)
93
+ - Improve `Array.push()` performance when pushing many items (#2565)
94
+ -
81
95
 
82
96
  ### Internal
83
97
 
data/docs/releasing.md CHANGED
@@ -8,21 +8,14 @@ _This guide is a work-in-progress._
8
8
 
9
9
  All of the following is now covered by `bin/rake release:prepare VERSION=v1.2.3`
10
10
 
11
- ### Updating the version
12
-
13
- - Update `lib/opal/version.rb`
14
- - Update `opal/corelib/constants.rb` with the same version number along with release dates
15
-
16
- ### Updating the changelog
17
-
18
- - Ensure all the unreleased changes are documented in UNRELEASED.md
19
- - [skip for pre-releases] Run `bin/rake changelog VERSION=v1.2.3` specifying the version number you're about to release
20
- - [skip for pre-releases] Empty UNRELEASED.md
21
-
22
- ### The commit
23
-
24
- - Commit the updated changelog along with the version bump using this commit message:
25
- "Release v1.2.3"
11
+ 1. Update the version
12
+ - Update `lib/opal/version.rb`
13
+ - Update `opal/corelib/constants.rb` with the same version number along with release dates
14
+ 2. Update the changelog
15
+ - Ensure all the unreleased changes are documented in UNRELEASED.md
16
+ - [skip for pre-releases] Run `bin/rake changelog VERSION=v1.2.3` specifying the version number you're about to release
17
+ - [skip for pre-releases] Empty UNRELEASED.md
18
+ 3. Commit the updated changelog along with the version bump using this commit message: "Release v1.2.3"
26
19
 
27
20
  ---
28
21
 
@@ -56,4 +49,3 @@ All of the following is now covered by `bin/rake release:prepare VERSION=v1.2.3`
56
49
  - Create a new pull request that:
57
50
  - Updates a version to `v1.x.0.dev` in both `lib/opal/version.rb` and `opal/corelib/constants.rb`
58
51
  - Remember to merge that PR before merging anything else next once we decide to not release any more point releases from `master`.
59
-
@@ -70,6 +70,10 @@ module Opal
70
70
  ext = builder.output_extension
71
71
  module_type = ' type="module"' if builder.esm?
72
72
 
73
+ # Some maps may contain `</script>` fragment (eg. in strings) which would close our
74
+ # `<script>` tag prematurely. For this case, we need to escape the `</script>` tag.
75
+ map_json = map.to_json.gsub(/(<\/scr)(ipt>)/i, '\1"+"\2')
76
+
73
77
  # Chrome can't handle huge data passed to `addScriptToEvaluateOnLoad`
74
78
  # https://groups.google.com/a/chromium.org/forum/#!topic/chromium-discuss/U5qyeX_ydBo
75
79
  # The only way is to create temporary files and pass them to chrome.
@@ -86,7 +90,7 @@ module Opal
86
90
  sourceMapSupport.install({
87
91
  retrieveSourceMap: function(path) {
88
92
  return path.endsWith('/index.#{ext}') ? {
89
- url: './index.map', map: #{map.to_json}
93
+ url: './index.map', map: #{map_json}
90
94
  } : null;
91
95
  }
92
96
  });
@@ -102,7 +102,7 @@ module Opal
102
102
  def generate_thrower(type, closure, value)
103
103
  id = closure.register_catcher(type)
104
104
  closure.register_thrower(type, id)
105
- push id, '.$throw(', expr_or_empty(value), ')'
105
+ push id, '.$throw(', expr_or_nil(value), ', ', scope.identify!, '.$$is_lambda)'
106
106
  id
107
107
  end
108
108
 
@@ -113,11 +113,11 @@ module Opal
113
113
  id = closure.throwers[type]
114
114
  else
115
115
  id = compiler.unique_temp('t_')
116
- scope = closure.node.scope&.parent || top_scope
117
- scope.add_scope_temp("#{id} = $thrower('#{type}')")
116
+ parent_scope = closure.node.scope&.parent || top_scope
117
+ parent_scope.add_scope_temp("#{id} = $thrower('#{type}')")
118
118
  closure.register_thrower(type, id)
119
119
  end
120
- push id, '.$throw(', expr_or_empty(value), ')'
120
+ push id, '.$throw(', expr_or_nil(value), ', ', scope.identify!, '.$$is_lambda)'
121
121
  id
122
122
  end
123
123
 
@@ -132,7 +132,7 @@ module Opal
132
132
  if iter_closure
133
133
  generate_thrower_without_catcher(:return, iter_closure, value)
134
134
  elsif compiler.eval?
135
- push 'Opal.t_eval_return.$throw(', expr_or_empty(value), ')'
135
+ push 'Opal.t_eval_return.$throw(', expr_or_nil(value), ', false)'
136
136
  else
137
137
  error 'Invalid return'
138
138
  end
@@ -211,9 +211,11 @@ module Opal
211
211
 
212
212
  helper :thrower
213
213
 
214
+ catchers_without_eval_return = catchers.grep_v(:eval_return)
215
+
214
216
  push "} catch($e) {"
215
217
  indent do
216
- @closure.catchers.each do |type|
218
+ catchers.each do |type|
217
219
  case type
218
220
  when :eval_return
219
221
  line "if ($e === Opal.t_eval_return) return $e.$v;"
@@ -225,9 +227,15 @@ module Opal
225
227
  end
226
228
  line "}"
227
229
 
230
+ unless catchers_without_eval_return.empty?
231
+ push " finally {", *catchers_without_eval_return.map { |type| "$t_#{type}.is_orphan = true;" }, "}"
232
+ end
233
+
228
234
  unshift "return " if closure_is? SEND
229
235
 
230
- unshift "var ", catchers.map { |type| "$t_#{type} = $thrower('#{type}')" }.join(", "), "; "
236
+ unless catchers_without_eval_return.empty?
237
+ unshift "var ", catchers_without_eval_return.map { |type| "$t_#{type} = $thrower('#{type}')" }.join(", "), "; "
238
+ end
231
239
  unshift "try { "
232
240
 
233
241
  unless closure_is? JS_FUNCTION
@@ -80,7 +80,7 @@ module Opal
80
80
  push ' if (Opal.rescue($err, [Opal.Exception])) {'
81
81
  push ' try {'
82
82
  push ' return false;'
83
- push ' } finally { Opal.pop_exception() }'
83
+ push ' } finally { Opal.pop_exception($err); }'
84
84
  push ' } else { throw $err; }'
85
85
  push '}})())'
86
86
 
@@ -5,14 +5,10 @@ require 'opal/nodes/base'
5
5
  module Opal
6
6
  module Nodes
7
7
  class ValueNode < Base
8
- handle :true, :false, :self, :nil
8
+ handle :true, :false, :nil
9
9
 
10
10
  def compile
11
- if type == :self
12
- push scope.self
13
- else
14
- push type.to_s
15
- end
11
+ push type.to_s
16
12
  end
17
13
 
18
14
  def self.truthy_optimize?
@@ -20,6 +16,14 @@ module Opal
20
16
  end
21
17
  end
22
18
 
19
+ class SelfNode < Base
20
+ handle :self
21
+
22
+ def compile
23
+ push scope.self
24
+ end
25
+ end
26
+
23
27
  class NumericNode < Base
24
28
  handle :int, :float
25
29
 
@@ -211,7 +211,7 @@ module Opal
211
211
  line stmt(rescue_body)
212
212
  end
213
213
  end
214
- line '} finally { Opal.pop_exception(); }'
214
+ line '} finally { Opal.pop_exception($err); }'
215
215
  end
216
216
  line '}'
217
217
  end
@@ -51,7 +51,7 @@ class Opal::SimpleServer
51
51
  asset = fetch_asset(path)
52
52
  [
53
53
  200,
54
- { 'Content-Type' => 'application/javascript' },
54
+ { 'content-type' => 'application/javascript' },
55
55
  [asset[:data], "\n", asset[:map].to_data_uri_comment],
56
56
  ]
57
57
  end
@@ -99,6 +99,6 @@ class Opal::SimpleServer
99
99
  </html>
100
100
  HTML
101
101
  end
102
- [200, { 'Content-Type' => 'text/html' }, [html]]
102
+ [200, { 'content-type' => 'text/html' }, [html]]
103
103
  end
104
104
  end
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.8.0.alpha1'
6
+ VERSION = '1.8.0.beta1'
7
7
  end
@@ -1,4 +1,4 @@
1
- # helpers: truthy, falsy, hash_ids, yield1, hash_get, hash_put, hash_delete, coerce_to, respond_to, deny_frozen_access, freeze
1
+ # helpers: truthy, falsy, yield1, hash_get, hash_put, hash_delete, coerce_to, respond_to, deny_frozen_access, freeze, opal32_init, opal32_add
2
2
  # backtick_javascript: true
3
3
 
4
4
  require 'corelib/enumerable'
@@ -76,6 +76,22 @@ class ::Array < `Array`
76
76
  }
77
77
  return #{`array`.to_a};
78
78
  }
79
+
80
+ function fast_push(arr, objects) {
81
+ // push.apply() for arrays longer than 32767 may cause various argument errors in browsers
82
+ // but it is significantly faster than a for loop, which pushes each element separately
83
+ // but apply() has a overhead by itself, for a small number of elements
84
+ // the for loop is significantly faster
85
+ // this is using the best option depending on objects.length
86
+ var length = objects.length;
87
+ if (length > 6 && length < 32767) {
88
+ arr.push.apply(arr, objects);
89
+ } else {
90
+ for (var i = 0; i < length; i++) {
91
+ arr.push(objects[i]);
92
+ }
93
+ }
94
+ }
79
95
  }
80
96
 
81
97
  def self.[](*objects)
@@ -99,7 +115,7 @@ class ::Array < `Array`
99
115
  }
100
116
 
101
117
  if (arguments.length === 0) {
102
- self.splice(0, self.length);
118
+ if (self.length > 0) self.splice(0, self.length);
103
119
  return self;
104
120
  }
105
121
 
@@ -253,7 +269,7 @@ class ::Array < `Array`
253
269
  end
254
270
 
255
271
  %x{
256
- if (#{hash} === #{other.hash}) {
272
+ if (#{self} === #{other}) {
257
273
  return 0;
258
274
  }
259
275
 
@@ -1216,7 +1232,7 @@ class ::Array < `Array`
1216
1232
  result.push(ary);
1217
1233
  break;
1218
1234
  default:
1219
- result.push.apply(result, _flatten(ary, level - 1));
1235
+ fast_push(result, _flatten(ary, level - 1));
1220
1236
  }
1221
1237
  }
1222
1238
  return result;
@@ -1260,27 +1276,31 @@ class ::Array < `Array`
1260
1276
  `$freeze(self)`
1261
1277
  end
1262
1278
 
1279
+ `var $hash_ids`
1280
+
1263
1281
  def hash
1264
1282
  %x{
1265
1283
  var top = ($hash_ids === undefined),
1266
- result = ['A'],
1284
+ result = $opal32_init(),
1267
1285
  hash_id = self.$object_id(),
1268
1286
  item, i, key;
1269
1287
 
1270
- try {
1271
- if (top) {
1272
- $hash_ids = Object.create(null);
1273
- }
1288
+ result = $opal32_add(result, 0xA);
1289
+ result = $opal32_add(result, self.length);
1274
1290
 
1275
- // return early for recursive structures
1276
- if ($hash_ids[hash_id]) {
1277
- return 'self';
1278
- }
1291
+ if (top) {
1292
+ $hash_ids = Object.create(null);
1293
+ }
1294
+ // return early for recursive structures
1295
+ else if ($hash_ids[hash_id]) {
1296
+ return $opal32_add(result, 0x01010101);
1297
+ }
1279
1298
 
1299
+ try {
1280
1300
  for (key in $hash_ids) {
1281
1301
  item = $hash_ids[key];
1282
1302
  if (#{eql?(`item`)}) {
1283
- return 'self';
1303
+ return $opal32_add(result, 0x01010101);
1284
1304
  }
1285
1305
  }
1286
1306
 
@@ -1288,10 +1308,10 @@ class ::Array < `Array`
1288
1308
 
1289
1309
  for (i = 0; i < self.length; i++) {
1290
1310
  item = self[i];
1291
- result.push(item.$hash());
1311
+ result = $opal32_add(result, item.$hash());
1292
1312
  }
1293
1313
 
1294
- return result.join(',');
1314
+ return result;
1295
1315
  } finally {
1296
1316
  if (top) {
1297
1317
  $hash_ids = undefined;
@@ -1741,9 +1761,7 @@ class ::Array < `Array`
1741
1761
  %x{
1742
1762
  $deny_frozen_access(self);
1743
1763
 
1744
- for (var i = 0, length = objects.length; i < length; i++) {
1745
- self.push(objects[i]);
1746
- }
1764
+ fast_push(self, objects);
1747
1765
  }
1748
1766
 
1749
1767
  self
@@ -1801,8 +1819,8 @@ class ::Array < `Array`
1801
1819
  other = `convertToArray(other)`
1802
1820
 
1803
1821
  %x{
1804
- self.splice(0, self.length);
1805
- self.push.apply(self, other);
1822
+ if (self.length > 0) self.splice(0, self.length);
1823
+ fast_push(self, other);
1806
1824
  }
1807
1825
 
1808
1826
  self
@@ -24,6 +24,32 @@ class ::Class
24
24
  }
25
25
  end
26
26
 
27
+ def clone(freeze: nil)
28
+ unless freeze.nil? || freeze == true || freeze == false
29
+ raise ArgumentError, "unexpected value for freeze: #{freeze.class}"
30
+ end
31
+
32
+ copy = `Opal.allocate_class(nil, self.$$super)`
33
+ copy.copy_instance_variables(self)
34
+ copy.copy_singleton_methods(self)
35
+ copy.initialize_clone(self, freeze: freeze)
36
+
37
+ if freeze == true || (freeze.nil? && frozen?)
38
+ copy.freeze
39
+ end
40
+
41
+ copy
42
+ end
43
+
44
+ def dup
45
+ copy = `Opal.allocate_class(nil, self.$$super)`
46
+
47
+ copy.copy_instance_variables(self)
48
+ copy.initialize_dup(self)
49
+
50
+ copy
51
+ end
52
+
27
53
  def descendants
28
54
  subclasses + subclasses.map(&:descendants).flatten
29
55
  end
@@ -31,14 +57,6 @@ class ::Class
31
57
  def inherited(cls)
32
58
  end
33
59
 
34
- def initialize_dup(original)
35
- initialize_copy(original)
36
- %x{
37
- self.$$name = null;
38
- self.$$full_name = null;
39
- }
40
- end
41
-
42
60
  def new(*args, &block)
43
61
  %x{
44
62
  var object = #{allocate};
@@ -180,7 +180,7 @@ class ::Complex < ::Numeric
180
180
  end
181
181
 
182
182
  def hash
183
- "Complex:#{@real}:#{@imag}"
183
+ [::Complex, @real, @imag].hash
184
184
  end
185
185
 
186
186
  def infinite?
@@ -1,8 +1,8 @@
1
1
  ::RUBY_PLATFORM = 'opal'
2
2
  ::RUBY_ENGINE = 'opal'
3
3
  ::RUBY_VERSION = '3.2.0'
4
- ::RUBY_ENGINE_VERSION = '1.8.0.alpha1'
5
- ::RUBY_RELEASE_DATE = '2023-08-04'
4
+ ::RUBY_ENGINE_VERSION = '1.8.0.beta1'
5
+ ::RUBY_RELEASE_DATE = '2023-10-12'
6
6
  ::RUBY_PATCHLEVEL = 0
7
7
  ::RUBY_REVISION = '0'
8
8
  ::RUBY_COPYRIGHT = 'opal - Copyright (C) 2011-2023 Adam Beynon and the Opal contributors'
@@ -153,7 +153,7 @@ class ::Enumerator
153
153
  end
154
154
 
155
155
  def hash
156
- [self.begin, self.end, step, exclude_end?].hash
156
+ [ArithmeticSequence, self.begin, self.end, step, exclude_end?].hash
157
157
  end
158
158
 
159
159
  def inspect
@@ -316,6 +316,16 @@ class ::KeyError
316
316
  end
317
317
  end
318
318
 
319
+ class ::LocalJumpError
320
+ attr_reader :exit_value, :reason
321
+
322
+ def initialize(message, exit_value = nil, reason = :noreason)
323
+ super message
324
+ @exit_value = exit_value
325
+ @reason = reason
326
+ end
327
+ end
328
+
319
329
  module ::JS
320
330
  class Error
321
331
  end
data/opal/corelib/hash.rb CHANGED
@@ -1,4 +1,4 @@
1
- # helpers: yield1, hash_clone, hash_delete, hash_each, hash_get, hash_put, deny_frozen_access, freeze
1
+ # helpers: yield1, hash_clone, hash_delete, hash_each, hash_get, hash_put, deny_frozen_access, freeze, opal32_init, opal32_add
2
2
  # backtick_javascript: true
3
3
 
4
4
  require 'corelib/enumerable'
@@ -481,41 +481,53 @@ class ::Hash < `Map`
481
481
  }
482
482
  end
483
483
 
484
+ `var $hash_ids`
485
+
484
486
  def hash
485
487
  %x{
486
- var top = (Opal.hash_ids === undefined),
488
+ var top = ($hash_ids === undefined),
487
489
  hash_id = self.$object_id(),
488
- result = ['Hash'],
489
- key, item;
490
+ result = $opal32_init(),
491
+ key, item, i,
492
+ size = self.size, ary = new Int32Array(size);
490
493
 
491
- try {
492
- if (top) {
493
- Opal.hash_ids = Object.create(null);
494
- }
494
+ result = $opal32_add(result, 0x4);
495
+ result = $opal32_add(result, size);
495
496
 
496
- if (Opal[hash_id]) {
497
- return 'self';
498
- }
497
+ if (top) {
498
+ $hash_ids = Object.create(null);
499
+ }
500
+ else if ($hash_ids[hash_id]) {
501
+ return $opal32_add(result, 0x01010101);
502
+ }
499
503
 
500
- for (key in Opal.hash_ids) {
501
- item = Opal.hash_ids[key];
504
+ try {
505
+ for (key in $hash_ids) {
506
+ item = $hash_ids[key];
502
507
  if (#{eql?(`item`)}) {
503
- return 'self';
508
+ return $opal32_add(result, 0x01010101);
504
509
  }
505
510
  }
506
511
 
507
- Opal.hash_ids[hash_id] = self;
512
+ $hash_ids[hash_id] = self;
513
+ i = 0
508
514
 
509
515
  $hash_each(self, false, function(key, value) {
510
- result.push([key, value.$hash()]);
516
+ ary[i] = [0x70414952, key, value].$hash();
517
+ i++;
511
518
  return [false, false];
512
519
  });
513
520
 
514
- return result.sort().join();
521
+ ary = ary.sort();
522
+
523
+ for (i = 0; i < ary.length; i++) {
524
+ result = $opal32_add(result, ary[i]);
525
+ }
515
526
 
527
+ return result;
516
528
  } finally {
517
529
  if (top) {
518
- Opal.hash_ids = undefined;
530
+ $hash_ids = undefined;
519
531
  }
520
532
  }
521
533
  }
@@ -687,7 +687,6 @@ module ::Kernel
687
687
  }
688
688
 
689
689
  #{$!} = exception;
690
- #{$@} = #{`exception`.backtrace};
691
690
 
692
691
  throw exception;
693
692
  }
@@ -733,11 +733,50 @@ class ::Module
733
733
  }
734
734
  end
735
735
 
736
- def dup
737
- copy = super
738
- copy.copy_class_variables(self)
739
- copy.copy_constants(self)
740
- copy
736
+ %x{
737
+ function copyInstanceMethods(from, to) {
738
+ var i, method_names = Opal.own_instance_methods(from);
739
+ for (i = 0; i < method_names.length; i++) {
740
+ var name = method_names[i],
741
+ jsid = $jsid(name),
742
+ body = from.$$prototype[jsid],
743
+ wrapped = Opal.wrapMethodBody(body);
744
+
745
+ wrapped.$$jsid = name;
746
+ Opal.defn(to, jsid, wrapped);
747
+ }
748
+ }
749
+
750
+ function copyIncludedModules(from, to) {
751
+ var modules = from.$$own_included_modules;
752
+ for (var i = modules.length - 1; i >= 0; i--) {
753
+ Opal.append_features(modules[i], to);
754
+ }
755
+ }
756
+
757
+ function copyPrependedModules(from, to) {
758
+ var modules = from.$$own_prepended_modules;
759
+ for (var i = modules.length - 1; i >= 0; i--) {
760
+ Opal.prepend_features(modules[i], to);
761
+ }
762
+ }
763
+ }
764
+
765
+ def initialize_copy(other)
766
+ %x{
767
+ copyInstanceMethods(other, self);
768
+ copyIncludedModules(other, self);
769
+ copyPrependedModules(other, self);
770
+ self.$$cloned_from = other.$$cloned_from.concat(other);
771
+ }
772
+ copy_class_variables(other)
773
+ copy_constants(other)
774
+ end
775
+
776
+ def initialize_dup(other)
777
+ super
778
+ # Unlike other classes, Module's singleton methods are copied on Object#dup.
779
+ copy_singleton_methods(other)
741
780
  end
742
781
 
743
782
  def copy_class_variables(other)