opal 1.8.0.alpha1 → 1.8.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
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)