opal 1.5.0 → 1.6.0.alpha1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (135) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/build.yml +5 -1
  3. data/CHANGELOG.md +41 -28
  4. data/HACKING.md +23 -0
  5. data/UNRELEASED.md +43 -0
  6. data/benchmark/run.rb +1 -0
  7. data/docs/compiled_ruby.md +8 -0
  8. data/docs/compiler.md +1 -1
  9. data/docs/compiler_directives.md +1 -1
  10. data/docs/getting_started.md +17 -0
  11. data/docs/headless_chrome.md +1 -1
  12. data/docs/index.md +123 -0
  13. data/docs/templates.md +37 -37
  14. data/docs/unsupported_features.md +0 -4
  15. data/lib/opal/builder.rb +59 -39
  16. data/lib/opal/builder_scheduler/prefork.rb +259 -0
  17. data/lib/opal/builder_scheduler/sequential.rb +13 -0
  18. data/lib/opal/builder_scheduler.rb +29 -0
  19. data/lib/opal/cache/file_cache.rb +5 -0
  20. data/lib/opal/cli.rb +22 -18
  21. data/lib/opal/cli_options.rb +4 -0
  22. data/lib/opal/cli_runners/chrome.rb +13 -9
  23. data/lib/opal/cli_runners/chrome_cdp_interface.rb +19 -2
  24. data/lib/opal/cli_runners/compiler.rb +1 -1
  25. data/lib/opal/cli_runners/gjs.rb +3 -1
  26. data/lib/opal/cli_runners/mini_racer.rb +5 -3
  27. data/lib/opal/cli_runners/nodejs.rb +3 -3
  28. data/lib/opal/cli_runners/server.rb +13 -28
  29. data/lib/opal/cli_runners/system_runner.rb +5 -3
  30. data/lib/opal/cli_runners.rb +7 -6
  31. data/lib/opal/compiler.rb +25 -2
  32. data/lib/opal/config.rb +10 -0
  33. data/lib/opal/nodes/args/ensure_kwargs_are_kwargs.rb +2 -6
  34. data/lib/opal/nodes/args/extract_kwarg.rb +3 -4
  35. data/lib/opal/nodes/args/extract_kwargs.rb +3 -1
  36. data/lib/opal/nodes/args/extract_kwoptarg.rb +1 -1
  37. data/lib/opal/nodes/args/extract_kwrestarg.rb +4 -1
  38. data/lib/opal/nodes/args/extract_optarg.rb +1 -1
  39. data/lib/opal/nodes/args/extract_post_arg.rb +1 -1
  40. data/lib/opal/nodes/args/extract_post_optarg.rb +1 -1
  41. data/lib/opal/nodes/args/extract_restarg.rb +2 -2
  42. data/lib/opal/nodes/args/initialize_iterarg.rb +1 -1
  43. data/lib/opal/nodes/args/initialize_shadowarg.rb +1 -1
  44. data/lib/opal/nodes/args/prepare_post_args.rb +4 -2
  45. data/lib/opal/nodes/base.rb +14 -3
  46. data/lib/opal/nodes/call.rb +10 -14
  47. data/lib/opal/nodes/class.rb +3 -1
  48. data/lib/opal/nodes/closure.rb +250 -0
  49. data/lib/opal/nodes/def.rb +7 -11
  50. data/lib/opal/nodes/definitions.rb +4 -2
  51. data/lib/opal/nodes/if.rb +12 -2
  52. data/lib/opal/nodes/iter.rb +11 -17
  53. data/lib/opal/nodes/logic.rb +15 -63
  54. data/lib/opal/nodes/module.rb +3 -1
  55. data/lib/opal/nodes/rescue.rb +23 -15
  56. data/lib/opal/nodes/scope.rb +7 -1
  57. data/lib/opal/nodes/top.rb +27 -4
  58. data/lib/opal/nodes/while.rb +42 -26
  59. data/lib/opal/nodes.rb +1 -0
  60. data/lib/opal/os.rb +59 -0
  61. data/lib/opal/rewriter.rb +2 -0
  62. data/lib/opal/rewriters/returnable_logic.rb +14 -0
  63. data/lib/opal/rewriters/thrower_finder.rb +90 -0
  64. data/lib/opal/simple_server.rb +12 -6
  65. data/lib/opal/source_map/file.rb +1 -1
  66. data/lib/opal/source_map/map.rb +9 -1
  67. data/lib/opal/util.rb +1 -1
  68. data/lib/opal/version.rb +1 -1
  69. data/opal/corelib/array.rb +68 -3
  70. data/opal/corelib/basic_object.rb +1 -0
  71. data/opal/corelib/comparable.rb +1 -1
  72. data/opal/corelib/complex.rb +1 -0
  73. data/opal/corelib/constants.rb +2 -2
  74. data/opal/corelib/enumerable.rb +4 -2
  75. data/opal/corelib/enumerator/chain.rb +4 -0
  76. data/opal/corelib/enumerator/generator.rb +5 -3
  77. data/opal/corelib/enumerator/lazy.rb +3 -1
  78. data/opal/corelib/enumerator/yielder.rb +2 -4
  79. data/opal/corelib/enumerator.rb +3 -1
  80. data/opal/corelib/error/errno.rb +2 -1
  81. data/opal/corelib/error.rb +13 -2
  82. data/opal/corelib/hash.rb +40 -2
  83. data/opal/corelib/kernel.rb +56 -5
  84. data/opal/corelib/module.rb +60 -4
  85. data/opal/corelib/proc.rb +8 -5
  86. data/opal/corelib/rational.rb +1 -0
  87. data/opal/corelib/regexp.rb +15 -1
  88. data/opal/corelib/runtime.js +307 -238
  89. data/opal/corelib/string/encoding.rb +0 -6
  90. data/opal/corelib/string.rb +28 -7
  91. data/opal/corelib/time.rb +18 -12
  92. data/opal/corelib/unsupported.rb +2 -14
  93. data/spec/filters/bugs/delegate.rb +11 -0
  94. data/spec/filters/bugs/kernel.rb +1 -3
  95. data/spec/filters/bugs/language.rb +3 -23
  96. data/spec/filters/bugs/method.rb +0 -1
  97. data/spec/filters/bugs/module.rb +0 -3
  98. data/spec/filters/bugs/proc.rb +0 -3
  99. data/spec/filters/bugs/set.rb +4 -16
  100. data/spec/filters/bugs/stringscanner.rb +0 -1
  101. data/spec/filters/bugs/unboundmethod.rb +0 -2
  102. data/spec/filters/unsupported/array.rb +0 -58
  103. data/spec/filters/unsupported/freeze.rb +8 -192
  104. data/spec/filters/unsupported/hash.rb +0 -25
  105. data/spec/filters/unsupported/kernel.rb +0 -1
  106. data/spec/filters/unsupported/privacy.rb +17 -0
  107. data/spec/lib/builder_spec.rb +14 -0
  108. data/spec/lib/cli_runners/server_spec.rb +2 -3
  109. data/spec/lib/cli_spec.rb +1 -1
  110. data/spec/lib/compiler_spec.rb +1 -1
  111. data/spec/opal/core/language/if_spec.rb +13 -0
  112. data/spec/opal/core/module_spec.rb +8 -0
  113. data/spec/ruby_specs +2 -1
  114. data/spec/spec_helper.rb +4 -0
  115. data/stdlib/await.rb +44 -7
  116. data/stdlib/delegate.rb +427 -6
  117. data/stdlib/headless_chrome.rb +6 -2
  118. data/stdlib/nodejs/file.rb +2 -1
  119. data/stdlib/opal-parser.rb +1 -1
  120. data/stdlib/opal-platform.rb +1 -1
  121. data/stdlib/opal-replutils.rb +5 -3
  122. data/stdlib/promise.rb +3 -0
  123. data/stdlib/rbconfig.rb +4 -1
  124. data/stdlib/ruby2_keywords.rb +60 -0
  125. data/stdlib/set.rb +21 -0
  126. data/stdlib/strscan.rb +27 -49
  127. data/tasks/performance.rake +41 -35
  128. data/tasks/releasing.rake +1 -0
  129. data/tasks/testing/mspec_special_calls.rb +1 -0
  130. data/tasks/testing.rake +13 -8
  131. data/test/nodejs/test_await.rb +39 -1
  132. metadata +27 -14
  133. data/docs/faq.md +0 -17
  134. data/lib/opal/rewriters/break_finder.rb +0 -36
  135. data/spec/opal/core/kernel/freeze_spec.rb +0 -15
@@ -1,4 +1,4 @@
1
- # helpers: truthy, falsy, hash_ids, yield1, hash_get, hash_put, hash_delete, coerce_to, respond_to
1
+ # helpers: truthy, falsy, hash_ids, yield1, hash_get, hash_put, hash_delete, coerce_to, respond_to, deny_frozen_access, freeze
2
2
 
3
3
  require 'corelib/enumerable'
4
4
  require 'corelib/numeric'
@@ -76,6 +76,8 @@ class ::Array < `Array`
76
76
 
77
77
  def initialize(size = nil, obj = nil, &block)
78
78
  %x{
79
+ $deny_frozen_access(self);
80
+
79
81
  if (obj !== nil && block !== nil) {
80
82
  #{::Kernel.warn('warning: block supersedes default value argument')}
81
83
  }
@@ -239,6 +241,7 @@ class ::Array < `Array`
239
241
  end
240
242
 
241
243
  def <<(object)
244
+ `$deny_frozen_access(self)`
242
245
  `self.push(object)`
243
246
 
244
247
  self
@@ -441,6 +444,8 @@ class ::Array < `Array`
441
444
  end
442
445
 
443
446
  def []=(index, value, extra = undefined)
447
+ `$deny_frozen_access(self)`
448
+
444
449
  data = nil
445
450
  %x{
446
451
  var i, size = self.length;
@@ -668,6 +673,8 @@ class ::Array < `Array`
668
673
  end
669
674
 
670
675
  def clear
676
+ `$deny_frozen_access(self)`
677
+
671
678
  `self.splice(0, self.length)`
672
679
 
673
680
  self
@@ -704,6 +711,8 @@ class ::Array < `Array`
704
711
  return enum_for(:collect!) { size } unless block_given?
705
712
 
706
713
  %x{
714
+ $deny_frozen_access(self);
715
+
707
716
  for (var i = 0, length = self.length; i < length; i++) {
708
717
  var value = $yield1(block, self[i]);
709
718
  self[i] = value;
@@ -819,6 +828,8 @@ class ::Array < `Array`
819
828
 
820
829
  def compact!
821
830
  %x{
831
+ $deny_frozen_access(self);
832
+
822
833
  var original = self.length;
823
834
 
824
835
  for (var i = 0, length = self.length; i < length; i++) {
@@ -835,6 +846,8 @@ class ::Array < `Array`
835
846
  end
836
847
 
837
848
  def concat(*others)
849
+ `$deny_frozen_access(self)`
850
+
838
851
  others = others.map do |other|
839
852
  other = if ::Array === other
840
853
  other.to_a
@@ -866,6 +879,8 @@ class ::Array < `Array`
866
879
 
867
880
  for (var i = 0, length = original; i < length; i++) {
868
881
  if (#{`self[i]` == object}) {
882
+ $deny_frozen_access(self);
883
+
869
884
  self.splice(i, 1);
870
885
 
871
886
  length--;
@@ -885,6 +900,8 @@ class ::Array < `Array`
885
900
 
886
901
  def delete_at(index)
887
902
  %x{
903
+ $deny_frozen_access(self);
904
+
888
905
  index = $coerce_to(index, #{::Integer}, 'to_int');
889
906
 
890
907
  if (index < 0) {
@@ -905,7 +922,11 @@ class ::Array < `Array`
905
922
 
906
923
  def delete_if(&block)
907
924
  return enum_for(:delete_if) { size } unless block_given?
908
- %x{filterIf(self, $falsy, block)}
925
+ %x{
926
+ $deny_frozen_access(self);
927
+
928
+ filterIf(self, $falsy, block)
929
+ }
909
930
  self
910
931
  end
911
932
 
@@ -1064,6 +1085,8 @@ class ::Array < `Array`
1064
1085
 
1065
1086
  def fill(*args, &block)
1066
1087
  %x{
1088
+ $deny_frozen_access(self);
1089
+
1067
1090
  var i, length, value;
1068
1091
  }
1069
1092
 
@@ -1216,6 +1239,8 @@ class ::Array < `Array`
1216
1239
 
1217
1240
  def flatten!(level = undefined)
1218
1241
  %x{
1242
+ $deny_frozen_access(self);
1243
+
1219
1244
  var flattened = #{flatten level};
1220
1245
 
1221
1246
  if (self.length == flattened.length) {
@@ -1236,6 +1261,12 @@ class ::Array < `Array`
1236
1261
  self
1237
1262
  end
1238
1263
 
1264
+ def freeze
1265
+ return self if frozen?
1266
+
1267
+ `$freeze(self)`
1268
+ end
1269
+
1239
1270
  def hash
1240
1271
  %x{
1241
1272
  var top = ($hash_ids === undefined),
@@ -1322,6 +1353,8 @@ class ::Array < `Array`
1322
1353
 
1323
1354
  def insert(index, *objects)
1324
1355
  %x{
1356
+ $deny_frozen_access(self);
1357
+
1325
1358
  index = $coerce_to(index, #{::Integer}, 'to_int');
1326
1359
 
1327
1360
  if (objects.length > 0) {
@@ -1446,7 +1479,11 @@ class ::Array < `Array`
1446
1479
 
1447
1480
  def keep_if(&block)
1448
1481
  return enum_for(:keep_if) { size } unless block_given?
1449
- %x{filterIf(self, $truthy, block)}
1482
+ %x{
1483
+ $deny_frozen_access(self);
1484
+
1485
+ filterIf(self, $truthy, block)
1486
+ }
1450
1487
  self
1451
1488
  end
1452
1489
 
@@ -1590,6 +1627,8 @@ class ::Array < `Array`
1590
1627
  end
1591
1628
 
1592
1629
  def pop(count = undefined)
1630
+ `$deny_frozen_access(self)`
1631
+
1593
1632
  if `count === undefined`
1594
1633
  return if `self.length === 0`
1595
1634
  return `self.pop()`
@@ -1664,6 +1703,8 @@ class ::Array < `Array`
1664
1703
 
1665
1704
  def push(*objects)
1666
1705
  %x{
1706
+ $deny_frozen_access(self);
1707
+
1667
1708
  for (var i = 0, length = objects.length; i < length; i++) {
1668
1709
  self.push(objects[i]);
1669
1710
  }
@@ -1708,6 +1749,8 @@ class ::Array < `Array`
1708
1749
  def reject!(&block)
1709
1750
  return enum_for(:reject!) { size } unless block_given?
1710
1751
 
1752
+ `$deny_frozen_access(self)`
1753
+
1711
1754
  original = length
1712
1755
  delete_if(&block)
1713
1756
 
@@ -1717,6 +1760,8 @@ class ::Array < `Array`
1717
1760
  end
1718
1761
 
1719
1762
  def replace(other)
1763
+ `$deny_frozen_access(self)`
1764
+
1720
1765
  other = if ::Array === other
1721
1766
  other.to_a
1722
1767
  else
@@ -1736,6 +1781,8 @@ class ::Array < `Array`
1736
1781
  end
1737
1782
 
1738
1783
  def reverse!
1784
+ `$deny_frozen_access(self)`
1785
+
1739
1786
  `self.reverse()`
1740
1787
  end
1741
1788
 
@@ -1809,6 +1856,8 @@ class ::Array < `Array`
1809
1856
 
1810
1857
  def rotate!(cnt = 1)
1811
1858
  %x{
1859
+ $deny_frozen_access(self);
1860
+
1812
1861
  if (self.length === 0 || self.length === 1) {
1813
1862
  return self;
1814
1863
  }
@@ -1967,6 +2016,8 @@ class ::Array < `Array`
1967
2016
  return enum_for(:select!) { size } unless block_given?
1968
2017
 
1969
2018
  %x{
2019
+ $deny_frozen_access(self)
2020
+
1970
2021
  var original = self.length;
1971
2022
  #{ keep_if(&block) };
1972
2023
  return self.length === original ? nil : self;
@@ -1974,6 +2025,8 @@ class ::Array < `Array`
1974
2025
  end
1975
2026
 
1976
2027
  def shift(count = undefined)
2028
+ `$deny_frozen_access(self)`
2029
+
1977
2030
  if `count === undefined`
1978
2031
  return if `self.length === 0`
1979
2032
  return `shiftNoArg(self)`
@@ -1996,6 +2049,8 @@ class ::Array < `Array`
1996
2049
 
1997
2050
  def shuffle!(rng = undefined)
1998
2051
  %x{
2052
+ $deny_frozen_access(self);
2053
+
1999
2054
  var randgen, i = self.length, j, tmp;
2000
2055
 
2001
2056
  if (rng !== undefined) {
@@ -2036,6 +2091,8 @@ class ::Array < `Array`
2036
2091
  end
2037
2092
 
2038
2093
  def slice!(index, length = undefined)
2094
+ `$deny_frozen_access(self)`
2095
+
2039
2096
  result = nil
2040
2097
 
2041
2098
  if `length === undefined`
@@ -2144,6 +2201,8 @@ class ::Array < `Array`
2144
2201
 
2145
2202
  def sort!(&block)
2146
2203
  %x{
2204
+ $deny_frozen_access(self)
2205
+
2147
2206
  var result;
2148
2207
 
2149
2208
  if (#{block_given?}) {
@@ -2165,6 +2224,8 @@ class ::Array < `Array`
2165
2224
  def sort_by!(&block)
2166
2225
  return enum_for(:sort_by!) { size } unless block_given?
2167
2226
 
2227
+ `$deny_frozen_access(self)`
2228
+
2168
2229
  replace sort_by(&block)
2169
2230
  end
2170
2231
 
@@ -2297,6 +2358,8 @@ class ::Array < `Array`
2297
2358
 
2298
2359
  def uniq!(&block)
2299
2360
  %x{
2361
+ $deny_frozen_access(self);
2362
+
2300
2363
  var original_length = self.length, hash = #{{}}, i, length, item, key;
2301
2364
 
2302
2365
  for (i = 0, length = original_length; i < length; i++) {
@@ -2319,6 +2382,8 @@ class ::Array < `Array`
2319
2382
 
2320
2383
  def unshift(*objects)
2321
2384
  %x{
2385
+ $deny_frozen_access(self);
2386
+
2322
2387
  var selfLength = self.length
2323
2388
  var objectsLength = objects.length
2324
2389
  if (objectsLength == 0) return self;
@@ -51,6 +51,7 @@ class ::BasicObject
51
51
  def !
52
52
  false
53
53
  end
54
+ ::Opal.pristine :!
54
55
 
55
56
  def !=(other)
56
57
  !(self == other)
@@ -40,7 +40,7 @@ module ::Comparable
40
40
 
41
41
  // check for infinite recursion
42
42
  if (self.$$comparable) {
43
- delete self.$$comparable;
43
+ self.$$comparable = false;
44
44
  return false;
45
45
  }
46
46
  }
@@ -23,6 +23,7 @@ class ::Complex < ::Numeric
23
23
  def initialize(real, imag = 0)
24
24
  @real = real
25
25
  @imag = imag
26
+ freeze
26
27
  end
27
28
 
28
29
  def coerce(other)
@@ -1,8 +1,8 @@
1
1
  ::RUBY_PLATFORM = 'opal'
2
2
  ::RUBY_ENGINE = 'opal'
3
3
  ::RUBY_VERSION = '3.1.0'
4
- ::RUBY_ENGINE_VERSION = '1.5.0'
5
- ::RUBY_RELEASE_DATE = '2022-04-13'
4
+ ::RUBY_ENGINE_VERSION = '1.6.0.alpha1'
5
+ ::RUBY_RELEASE_DATE = '2022-11-11'
6
6
  ::RUBY_PATCHLEVEL = 0
7
7
  ::RUBY_REVISION = '0'
8
8
  ::RUBY_COPYRIGHT = 'opal - Copyright (C) 2013-2022 Adam Beynon and the Opal contributors'
@@ -1,4 +1,4 @@
1
- # helpers: truthy, coerce_to, yield1, yieldX
1
+ # helpers: truthy, coerce_to, yield1, yieldX, deny_frozen_access
2
2
 
3
3
  module ::Enumerable
4
4
  %x{
@@ -128,7 +128,7 @@ module ::Enumerable
128
128
 
129
129
  def collect_concat(&block)
130
130
  return enum_for(:collect_concat) { enumerator_size } unless block_given?
131
- map { |item| yield item }.flatten(1)
131
+ map(&block).flatten(1)
132
132
  end
133
133
 
134
134
  def compact
@@ -1230,6 +1230,8 @@ module ::Enumerable
1230
1230
  end
1231
1231
 
1232
1232
  def tally(hash = undefined)
1233
+ `if (hash && hash !== nil) { $deny_frozen_access(hash); }`
1234
+
1233
1235
  out = group_by(&:itself).transform_values(&:count)
1234
1236
  if hash
1235
1237
  out.each { |k, v| hash[k] = hash.fetch(k, 0) + v }
@@ -1,6 +1,10 @@
1
+ # helpers: deny_frozen_access
2
+
1
3
  class ::Enumerator
2
4
  class self::Chain < self
3
5
  def initialize(*enums)
6
+ `$deny_frozen_access(self)`
7
+
4
8
  @enums = enums
5
9
  @iterated = []
6
10
  @object = self
@@ -1,10 +1,12 @@
1
- # helpers: breaker
1
+ # helpers: deny_frozen_access
2
2
 
3
3
  class Enumerator
4
4
  class Generator
5
5
  include ::Enumerable
6
6
 
7
7
  def initialize(&block)
8
+ `$deny_frozen_access(self)`
9
+
8
10
  ::Kernel.raise ::LocalJumpError, 'no block given' unless block
9
11
 
10
12
  @block = block
@@ -20,8 +22,8 @@ class Enumerator
20
22
  Opal.yieldX(#{@block}, args);
21
23
  }
22
24
  catch (e) {
23
- if (e === $breaker) {
24
- return $breaker.$v;
25
+ if (e && e.$thrower_type == "breaker") {
26
+ return e.$v;
25
27
  }
26
28
  else {
27
29
  throw e;
@@ -1,4 +1,4 @@
1
- # helpers: truthy, coerce_to, yield1, yieldX
1
+ # helpers: truthy, coerce_to, yield1, yieldX, deny_frozen_access
2
2
 
3
3
  class ::Enumerator
4
4
  class self::Lazy < self
@@ -11,6 +11,8 @@ class ::Enumerator
11
11
  end
12
12
 
13
13
  def initialize(object, size = nil, &block)
14
+ `$deny_frozen_access(self)`
15
+
14
16
  unless block_given?
15
17
  ::Kernel.raise ::ArgumentError, 'tried to call lazy new without a block'
16
18
  end
@@ -1,5 +1,3 @@
1
- # helpers: breaker
2
-
3
1
  class Enumerator
4
2
  class Yielder
5
3
  def initialize(&block)
@@ -13,8 +11,8 @@ class Enumerator
13
11
  %x{
14
12
  var value = Opal.yieldX(#{@block}, values);
15
13
 
16
- if (value === $breaker) {
17
- throw $breaker;
14
+ if (value && value.$thrower_type == "break") {
15
+ throw value;
18
16
  }
19
17
 
20
18
  return value;
@@ -1,4 +1,4 @@
1
- # helpers: slice, coerce_to
1
+ # helpers: slice, coerce_to, deny_frozen_access
2
2
 
3
3
  require 'corelib/enumerable'
4
4
 
@@ -22,6 +22,8 @@ class ::Enumerator
22
22
  end
23
23
 
24
24
  def initialize(*, &block)
25
+ `$deny_frozen_access(self)`
26
+
25
27
  @cursor = 0
26
28
  if block
27
29
  @object = Generator.new(&block)
@@ -6,7 +6,8 @@ module ::Errno
6
6
  [:EMFILE, 'Too many open files', 24],
7
7
  [:EACCES, 'Permission denied', 13],
8
8
  [:EPERM, 'Operation not permitted', 1],
9
- [:ENOENT, 'No such file or directory', 2]
9
+ [:ENOENT, 'No such file or directory', 2],
10
+ [:ENAMETOOLONG, 'File name too long', 36]
10
11
  ]
11
12
 
12
13
  klass = nil
@@ -2,6 +2,8 @@ class ::Exception < `Error`
2
2
  `Opal.prop(self.$$prototype, '$$is_exception', true)`
3
3
  `var stack_trace_limit`
4
4
 
5
+ `Error.stackTraceLimit = 100`
6
+
5
7
  def self.new(*args)
6
8
  %x{
7
9
  var message = (args.length > 0) ? args[0] : nil;
@@ -75,10 +77,10 @@ class ::Exception < `Error`
75
77
  var backtrace = self.stack;
76
78
 
77
79
  if (typeof(backtrace) !== 'undefined' && backtrace.$$is_string) {
78
- return self.backtrace = correct_backtrace(backtrace.split("\n").slice(0, 15));
80
+ return self.backtrace = correct_backtrace(backtrace.split("\n"));
79
81
  }
80
82
  else if (backtrace) {
81
- return self.backtrace = correct_backtrace(backtrace.slice(0, 15));
83
+ return self.backtrace = correct_backtrace(backtrace);
82
84
  }
83
85
 
84
86
  return [];
@@ -244,6 +246,15 @@ class ::FiberError < ::StandardError; end
244
246
 
245
247
  ::Object.autoload :Errno, 'corelib/error/errno'
246
248
 
249
+ class ::FrozenError < ::RuntimeError
250
+ attr_reader :receiver
251
+
252
+ def initialize(message, receiver: nil)
253
+ super message
254
+ @receiver = receiver
255
+ end
256
+ end
257
+
247
258
  class ::UncaughtThrowError < ::ArgumentError
248
259
  attr_reader :tag, :value
249
260
 
data/opal/corelib/hash.rb CHANGED
@@ -1,4 +1,4 @@
1
- # helpers: yield1, hash, hash_init, hash_get, hash_put, hash_delete
1
+ # helpers: yield1, hash, hash_init, hash_get, hash_put, hash_delete, deny_frozen_access, freeze
2
2
 
3
3
  require 'corelib/enumerable'
4
4
 
@@ -84,6 +84,8 @@ class ::Hash
84
84
 
85
85
  def initialize(defaults = undefined, &block)
86
86
  %x{
87
+ $deny_frozen_access(self);
88
+
87
89
  if (defaults !== undefined && block !== nil) {
88
90
  #{::Kernel.raise ::ArgumentError, 'wrong number of arguments (1 for 0)'}
89
91
  }
@@ -189,6 +191,8 @@ class ::Hash
189
191
 
190
192
  def []=(key, value)
191
193
  %x{
194
+ $deny_frozen_access(self);
195
+
192
196
  $hash_put(self, key, value);
193
197
  return value;
194
198
  }
@@ -216,6 +220,8 @@ class ::Hash
216
220
 
217
221
  def clear
218
222
  %x{
223
+ $deny_frozen_access(self);
224
+
219
225
  $hash_init(self);
220
226
  return self;
221
227
  }
@@ -257,6 +263,8 @@ class ::Hash
257
263
 
258
264
  def compact!
259
265
  %x{
266
+ $deny_frozen_access(self);
267
+
260
268
  var changes_were_made = false;
261
269
 
262
270
  for (var i = 0, keys = self.$$keys, length = keys.length, key, value, obj; i < length; i++) {
@@ -284,6 +292,8 @@ class ::Hash
284
292
 
285
293
  def compare_by_identity
286
294
  %x{
295
+ $deny_frozen_access(self);
296
+
287
297
  var i, ii, key, keys = self.$$keys, identity_hash;
288
298
 
289
299
  if (self.$$by_identity) return self;
@@ -324,6 +334,8 @@ class ::Hash
324
334
 
325
335
  def default=(object)
326
336
  %x{
337
+ $deny_frozen_access(self);
338
+
327
339
  self.$$proc = nil;
328
340
  self.$$none = object;
329
341
 
@@ -342,6 +354,8 @@ class ::Hash
342
354
 
343
355
  def default_proc=(default_proc)
344
356
  %x{
357
+ $deny_frozen_access(self);
358
+
345
359
  var proc = default_proc;
346
360
 
347
361
  if (proc !== nil) {
@@ -361,6 +375,7 @@ class ::Hash
361
375
 
362
376
  def delete(key, &block)
363
377
  %x{
378
+ $deny_frozen_access(self);
364
379
  var value = $hash_delete(self, key);
365
380
 
366
381
  if (value !== undefined) {
@@ -379,6 +394,8 @@ class ::Hash
379
394
  return enum_for(:delete_if) { size } unless block
380
395
 
381
396
  %x{
397
+ $deny_frozen_access(self);
398
+
382
399
  for (var i = 0, keys = self.$$keys, length = keys.length, key, value, obj; i < length; i++) {
383
400
  key = keys[i];
384
401
 
@@ -458,7 +475,7 @@ class ::Hash
458
475
  return enum_for(:each_value) { size } unless block
459
476
 
460
477
  %x{
461
- for (var i = 0, keys = self.$$keys, length = keys.length, key; i < length; i++) {
478
+ for (var i = 0, keys = self.$$keys.slice(), length = keys.length, key; i < length; i++) {
462
479
  key = keys[i];
463
480
 
464
481
  block(key.$$is_string ? self.$$smap[key] : key.value);
@@ -540,6 +557,12 @@ class ::Hash
540
557
  }
541
558
  end
542
559
 
560
+ def freeze
561
+ return self if frozen?
562
+
563
+ `$freeze(self)`
564
+ end
565
+
543
566
  def has_key?(key)
544
567
  `$hash_get(self, key) !== undefined`
545
568
  end
@@ -714,6 +737,8 @@ class ::Hash
714
737
  return enum_for(:keep_if) { size } unless block
715
738
 
716
739
  %x{
740
+ $deny_frozen_access(self);
741
+
717
742
  for (var i = 0, keys = self.$$keys, length = keys.length, key, value, obj; i < length; i++) {
718
743
  key = keys[i];
719
744
 
@@ -766,6 +791,7 @@ class ::Hash
766
791
 
767
792
  def merge!(*others, &block)
768
793
  %x{
794
+ $deny_frozen_access(self);
769
795
  var i, j, other, other_keys, length, key, value, other_value;
770
796
  for (i = 0; i < others.length; ++i) {
771
797
  other = #{::Opal.coerce_to!(`others[i]`, ::Hash, :to_hash)};
@@ -834,6 +860,7 @@ class ::Hash
834
860
 
835
861
  def rehash
836
862
  %x{
863
+ $deny_frozen_access(self);
837
864
  Opal.hash_rehash(self);
838
865
  return self;
839
866
  }
@@ -870,6 +897,8 @@ class ::Hash
870
897
  return enum_for(:reject!) { size } unless block
871
898
 
872
899
  %x{
900
+ $deny_frozen_access(self);
901
+
873
902
  var changes_were_made = false;
874
903
 
875
904
  for (var i = 0, keys = self.$$keys, length = keys.length, key, value, obj; i < length; i++) {
@@ -898,6 +927,8 @@ class ::Hash
898
927
  end
899
928
 
900
929
  def replace(other)
930
+ `$deny_frozen_access(self);`
931
+
901
932
  other = ::Opal.coerce_to!(other, ::Hash, :to_hash)
902
933
 
903
934
  %x{
@@ -957,6 +988,8 @@ class ::Hash
957
988
  return enum_for(:select!) { size } unless block
958
989
 
959
990
  %x{
991
+ $deny_frozen_access(self);
992
+
960
993
  var result = nil;
961
994
 
962
995
  for (var i = 0, keys = self.$$keys, length = keys.length, key, value, obj; i < length; i++) {
@@ -986,6 +1019,7 @@ class ::Hash
986
1019
 
987
1020
  def shift
988
1021
  %x{
1022
+ $deny_frozen_access(self);
989
1023
  var keys = self.$$keys,
990
1024
  key;
991
1025
 
@@ -1100,6 +1134,8 @@ class ::Hash
1100
1134
  return enum_for(:transform_keys!) { size } unless block
1101
1135
 
1102
1136
  %x{
1137
+ $deny_frozen_access(self);
1138
+
1103
1139
  var keys = Opal.slice.call(self.$$keys),
1104
1140
  i, length = keys.length, key, value, new_key;
1105
1141
 
@@ -1152,6 +1188,8 @@ class ::Hash
1152
1188
  return enum_for(:transform_values!) { size } unless block
1153
1189
 
1154
1190
  %x{
1191
+ $deny_frozen_access(self);
1192
+
1155
1193
  for (var i = 0, keys = self.$$keys, length = keys.length, key, value; i < length; i++) {
1156
1194
  key = keys[i];
1157
1195