opal 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (125) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +4 -4
  3. data/.github/ISSUE_TEMPLATE/bug-report.md +47 -0
  4. data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
  5. data/.github/workflows/build.yml +11 -5
  6. data/.gitignore +1 -0
  7. data/.jshintrc +1 -1
  8. data/.rubocop.yml +2 -1
  9. data/CHANGELOG.md +95 -1
  10. data/Gemfile +0 -4
  11. data/HACKING.md +1 -1
  12. data/README.md +19 -15
  13. data/UNRELEASED.md +37 -96
  14. data/benchmark-ips/bm_array_unshift.rb +7 -0
  15. data/bin/build-browser-source-map-support +2 -3
  16. data/bin/opal-mspec +2 -0
  17. data/docs/compiler.md +1 -1
  18. data/examples/rack/Gemfile +0 -1
  19. data/examples/rack/Gemfile.lock +0 -4
  20. data/lib/opal/cli.rb +1 -0
  21. data/lib/opal/cli_options.rb +4 -0
  22. data/lib/opal/cli_runners/nodejs.rb +5 -1
  23. data/lib/opal/cli_runners/source-map-support-browser.js +8 -2
  24. data/lib/opal/cli_runners/source-map-support-node.js +3706 -0
  25. data/lib/opal/cli_runners/source-map-support.js +3 -1
  26. data/lib/opal/compiler.rb +2 -2
  27. data/lib/opal/nodes/args/arity_check.rb +1 -0
  28. data/lib/opal/nodes/args/parameters.rb +6 -0
  29. data/lib/opal/nodes/class.rb +1 -13
  30. data/lib/opal/nodes/literal.rb +14 -7
  31. data/lib/opal/nodes/module.rb +13 -9
  32. data/lib/opal/nodes/variables.rb +13 -4
  33. data/lib/opal/nodes/while.rb +54 -17
  34. data/lib/opal/parser.rb +1 -5
  35. data/lib/opal/parser/patch.rb +44 -0
  36. data/lib/opal/repl.rb +7 -0
  37. data/lib/opal/rewriter.rb +4 -0
  38. data/lib/opal/rewriters/arguments.rb +4 -1
  39. data/lib/opal/rewriters/forward_args.rb +54 -0
  40. data/lib/opal/rewriters/logical_operator_assignment.rb +5 -2
  41. data/lib/opal/rewriters/opal_engine_check.rb +5 -7
  42. data/lib/opal/rewriters/pattern_matching.rb +287 -0
  43. data/lib/opal/version.rb +1 -1
  44. data/opal/corelib/array.rb +42 -20
  45. data/opal/corelib/array/pack.rb +6 -1
  46. data/opal/corelib/complex.rb +2 -0
  47. data/opal/corelib/constants.rb +3 -3
  48. data/opal/corelib/hash.rb +45 -38
  49. data/opal/corelib/module.rb +2 -7
  50. data/opal/corelib/number.rb +2 -180
  51. data/opal/corelib/numeric.rb +156 -0
  52. data/opal/corelib/object_space.rb +102 -0
  53. data/opal/corelib/pattern_matching.rb +159 -0
  54. data/opal/corelib/random.rb +31 -66
  55. data/opal/corelib/random/formatter.rb +122 -0
  56. data/opal/corelib/range.rb +50 -19
  57. data/opal/corelib/runtime.js +82 -21
  58. data/opal/corelib/string.rb +86 -52
  59. data/opal/corelib/string/encoding.rb +140 -25
  60. data/opal/corelib/string/unpack.rb +26 -40
  61. data/opal/opal.rb +1 -0
  62. data/opal/opal/full.rb +2 -0
  63. data/package.json +1 -1
  64. data/spec/filters/bugs/array.rb +0 -23
  65. data/spec/filters/bugs/basicobject.rb +3 -0
  66. data/spec/filters/bugs/encoding.rb +0 -2
  67. data/spec/filters/bugs/exception.rb +1 -0
  68. data/spec/filters/bugs/float.rb +0 -2
  69. data/spec/filters/bugs/hash.rb +3 -13
  70. data/spec/filters/bugs/integer.rb +0 -2
  71. data/spec/filters/bugs/kernel.rb +16 -3
  72. data/spec/filters/bugs/language.rb +27 -90
  73. data/spec/filters/bugs/marshal.rb +1 -3
  74. data/spec/filters/bugs/module.rb +16 -1
  75. data/spec/filters/bugs/numeric.rb +4 -12
  76. data/spec/filters/bugs/objectspace.rb +67 -0
  77. data/spec/filters/bugs/pack_unpack.rb +0 -9
  78. data/spec/filters/bugs/pathname.rb +1 -0
  79. data/spec/filters/bugs/proc.rb +8 -0
  80. data/spec/filters/bugs/random.rb +3 -6
  81. data/spec/filters/bugs/range.rb +83 -113
  82. data/spec/filters/bugs/set.rb +2 -0
  83. data/spec/filters/bugs/string.rb +32 -70
  84. data/spec/filters/bugs/struct.rb +2 -10
  85. data/spec/filters/bugs/time.rb +8 -2
  86. data/spec/filters/unsupported/float.rb +3 -0
  87. data/spec/filters/unsupported/freeze.rb +1 -0
  88. data/spec/filters/unsupported/integer.rb +3 -0
  89. data/spec/filters/unsupported/refinements.rb +8 -0
  90. data/spec/filters/unsupported/string.rb +100 -95
  91. data/spec/filters/unsupported/time.rb +4 -0
  92. data/spec/lib/compiler_spec.rb +16 -0
  93. data/spec/lib/rewriters/forward_args_spec.rb +61 -0
  94. data/spec/lib/rewriters/logical_operator_assignment_spec.rb +1 -1
  95. data/spec/lib/rewriters/numblocks_spec.rb +44 -0
  96. data/spec/lib/rewriters/opal_engine_check_spec.rb +49 -4
  97. data/spec/opal/core/language/forward_args_spec.rb +53 -0
  98. data/spec/opal/core/language/infinite_range_spec.rb +13 -0
  99. data/spec/opal/core/language/memoization_spec.rb +16 -0
  100. data/spec/opal/core/language/pattern_matching_spec.rb +124 -0
  101. data/spec/opal/core/module_spec.rb +38 -2
  102. data/spec/opal/core/number/to_i_spec.rb +28 -0
  103. data/spec/opal/core/runtime/bridged_classes_spec.rb +16 -0
  104. data/spec/opal/core/runtime/constants_spec.rb +20 -1
  105. data/spec/opal/core/string/subclassing_spec.rb +16 -0
  106. data/spec/opal/core/string/unpack_spec.rb +22 -0
  107. data/spec/opal/core/string_spec.rb +4 -4
  108. data/spec/ruby_specs +4 -1
  109. data/stdlib/json.rb +3 -1
  110. data/stdlib/promise/v1.rb +1 -0
  111. data/stdlib/promise/v2.rb +386 -0
  112. data/stdlib/securerandom.rb +55 -35
  113. data/tasks/releasing.rake +1 -1
  114. data/tasks/testing.rake +6 -4
  115. data/test/nodejs/test_string.rb +25 -0
  116. data/test/opal/promisev2/test_always.rb +63 -0
  117. data/test/opal/promisev2/test_error.rb +16 -0
  118. data/test/opal/promisev2/test_rescue.rb +59 -0
  119. data/test/opal/promisev2/test_then.rb +90 -0
  120. data/test/opal/promisev2/test_trace.rb +52 -0
  121. data/test/opal/promisev2/test_value.rb +16 -0
  122. data/test/opal/promisev2/test_when.rb +35 -0
  123. data/vendored-minitest/minitest/assertions.rb +2 -0
  124. metadata +47 -8
  125. data/lib/opal/parser/with_c_lexer.rb +0 -15
@@ -442,7 +442,12 @@ class Array
442
442
  output = output.concat(part);
443
443
  });
444
444
 
445
- return output;
445
+ if (format.match(/^(U\*?)+$/)) {
446
+ return output;
447
+ }
448
+ else {
449
+ return Opal.enc(output, "binary");
450
+ }
446
451
  }
447
452
  end
448
453
  end
@@ -245,6 +245,8 @@ class Complex < Numeric
245
245
 
246
246
  alias rectangular rect
247
247
 
248
+ undef step
249
+
248
250
  def to_f
249
251
  unless @imag == 0
250
252
  raise RangeError, "can't convert #{self} into Float"
@@ -1,8 +1,8 @@
1
1
  RUBY_PLATFORM = 'opal'
2
2
  RUBY_ENGINE = 'opal'
3
- RUBY_VERSION = '3.0.0'
4
- RUBY_ENGINE_VERSION = '1.1.0'
5
- RUBY_RELEASE_DATE = '2021-02-19'
3
+ RUBY_VERSION = '3.0.2'
4
+ RUBY_ENGINE_VERSION = '1.2.0'
5
+ RUBY_RELEASE_DATE = '2021-07-28'
6
6
  RUBY_PATCHLEVEL = 0
7
7
  RUBY_REVISION = '0'
8
8
  RUBY_COPYRIGHT = 'opal - Copyright (C) 2013-2021 Adam Beynon and the Opal contributors'
data/opal/corelib/hash.rb CHANGED
@@ -476,6 +476,15 @@ class Hash
476
476
 
477
477
  alias eql? ==
478
478
 
479
+ def except(*keys)
480
+ dup.except!(*keys)
481
+ end
482
+
483
+ def except!(*keys)
484
+ keys.each { |key| delete(key) }
485
+ self
486
+ end
487
+
479
488
  def fetch(key, defaults = undefined, &block)
480
489
  %x{
481
490
  var value = Opal.hash_get(self, key);
@@ -762,53 +771,51 @@ class Hash
762
771
 
763
772
  alias member? has_key?
764
773
 
765
- def merge(other, &block)
766
- dup.merge!(other, &block)
774
+ def merge(*others, &block)
775
+ dup.merge!(*others, &block)
767
776
  end
768
777
 
769
- def merge!(other, &block)
778
+ def merge!(*others, &block)
770
779
  %x{
771
- if (!other.$$is_hash) {
772
- other = #{Opal.coerce_to!(other, Hash, :to_hash)};
773
- }
774
-
775
- var i, other_keys = other.$$keys, length = other_keys.length, key, value, other_value;
776
-
777
- if (block === nil) {
778
- for (i = 0; i < length; i++) {
779
- key = other_keys[i];
780
-
781
- if (key.$$is_string) {
782
- other_value = other.$$smap[key];
783
- } else {
784
- other_value = key.value;
785
- key = key.key;
780
+ var i, j, other, other_keys, length, key, value, other_value;
781
+ for (i = 0; i < others.length; ++i) {
782
+ other = #{Opal.coerce_to!(`others[i]`, Hash, :to_hash)};
783
+ other_keys = other.$$keys, length = other_keys.length;
784
+
785
+ if (block === nil) {
786
+ for (j = 0; j < length; j++) {
787
+ key = other_keys[j];
788
+
789
+ if (key.$$is_string) {
790
+ other_value = other.$$smap[key];
791
+ } else {
792
+ other_value = key.value;
793
+ key = key.key;
794
+ }
795
+
796
+ Opal.hash_put(self, key, other_value);
786
797
  }
798
+ } else {
799
+ for (j = 0; j < length; j++) {
800
+ key = other_keys[j];
787
801
 
788
- Opal.hash_put(self, key, other_value);
789
- }
790
-
791
- return self;
792
- }
793
-
794
- for (i = 0; i < length; i++) {
795
- key = other_keys[i];
802
+ if (key.$$is_string) {
803
+ other_value = other.$$smap[key];
804
+ } else {
805
+ other_value = key.value;
806
+ key = key.key;
807
+ }
796
808
 
797
- if (key.$$is_string) {
798
- other_value = other.$$smap[key];
799
- } else {
800
- other_value = key.value;
801
- key = key.key;
802
- }
809
+ value = Opal.hash_get(self, key);
803
810
 
804
- value = Opal.hash_get(self, key);
811
+ if (value === undefined) {
812
+ Opal.hash_put(self, key, other_value);
813
+ continue;
814
+ }
805
815
 
806
- if (value === undefined) {
807
- Opal.hash_put(self, key, other_value);
808
- continue;
816
+ Opal.hash_put(self, key, block(key, value, other_value));
817
+ }
809
818
  }
810
-
811
- Opal.hash_put(self, key, block(key, value, other_value));
812
819
  }
813
820
 
814
821
  return self;
@@ -204,13 +204,8 @@ class Module
204
204
 
205
205
  def class_variable_get(name)
206
206
  name = Opal.class_variable_name!(name)
207
- %x{
208
- var value = Opal.class_variables(self)[name];
209
- if (value == null) {
210
- #{raise NameError.new("uninitialized class variable #{name} in #{self}", name)}
211
- }
212
- return value;
213
- }
207
+
208
+ `Opal.class_variable_get(self, name, false)`
214
209
  end
215
210
 
216
211
  def class_variable_set(name, value)
@@ -379,7 +379,7 @@ class Number < Numeric
379
379
  end
380
380
 
381
381
  def chr(encoding = undefined)
382
- `String.fromCharCode(self)`
382
+ `Opal.enc(String.fromCharCode(self), encoding || "BINARY")`
383
383
  end
384
384
 
385
385
  def denominator
@@ -668,184 +668,6 @@ class Number < Numeric
668
668
  end
669
669
  end
670
670
 
671
- def step(limit = undefined, step = undefined, to: undefined, by: undefined, &block)
672
- %x{
673
- if (limit !== undefined && to !== undefined) {
674
- #{raise ArgumentError, 'to is given twice'}
675
- }
676
-
677
- if (step !== undefined && by !== undefined) {
678
- #{raise ArgumentError, 'step is given twice'}
679
- }
680
-
681
- function validateParameters() {
682
- if (to !== undefined) {
683
- limit = to;
684
- }
685
-
686
- if (limit === undefined) {
687
- limit = nil;
688
- }
689
-
690
- if (step === nil) {
691
- #{raise TypeError, 'step must be numeric'}
692
- }
693
-
694
- if (step === 0) {
695
- #{raise ArgumentError, "step can't be 0"}
696
- }
697
-
698
- if (by !== undefined) {
699
- step = by;
700
- }
701
-
702
- if (step === nil || step == null) {
703
- step = 1;
704
- }
705
-
706
- var sign = #{step <=> 0};
707
-
708
- if (sign === nil) {
709
- #{raise ArgumentError, "0 can't be coerced into #{step.class}"}
710
- }
711
-
712
- if (limit === nil || limit == null) {
713
- limit = sign > 0 ? #{Float::INFINITY} : #{-Float::INFINITY};
714
- }
715
-
716
- #{Opal.compare(self, limit)}
717
- }
718
-
719
- function stepFloatSize() {
720
- if ((step > 0 && self > limit) || (step < 0 && self < limit)) {
721
- return 0;
722
- } else if (step === Infinity || step === -Infinity) {
723
- return 1;
724
- } else {
725
- var abs = Math.abs, floor = Math.floor,
726
- err = (abs(self) + abs(limit) + abs(limit - self)) / abs(step) * #{Float::EPSILON};
727
-
728
- if (err === Infinity || err === -Infinity) {
729
- return 0;
730
- } else {
731
- if (err > 0.5) {
732
- err = 0.5;
733
- }
734
-
735
- return floor((limit - self) / step + err) + 1
736
- }
737
- }
738
- }
739
-
740
- function stepSize() {
741
- validateParameters();
742
-
743
- if (step === 0) {
744
- return Infinity;
745
- }
746
-
747
- if (step % 1 !== 0) {
748
- return stepFloatSize();
749
- } else if ((step > 0 && self > limit) || (step < 0 && self < limit)) {
750
- return 0;
751
- } else {
752
- var ceil = Math.ceil, abs = Math.abs,
753
- lhs = abs(self - limit) + 1,
754
- rhs = abs(step);
755
-
756
- return ceil(lhs / rhs);
757
- }
758
- }
759
- }
760
-
761
- unless block_given?
762
- positional_args = []
763
- keyword_args = {}
764
-
765
- %x{
766
- if (limit !== undefined) {
767
- positional_args.push(limit);
768
- }
769
-
770
- if (step !== undefined) {
771
- positional_args.push(step);
772
- }
773
-
774
- if (to !== undefined) {
775
- Opal.hash_put(keyword_args, "to", to);
776
- }
777
-
778
- if (by !== undefined) {
779
- Opal.hash_put(keyword_args, "by", by);
780
- }
781
-
782
- if (#{keyword_args.any?}) {
783
- positional_args.push(keyword_args);
784
- }
785
- }
786
-
787
- return enum_for(:step, *positional_args) { `stepSize()` }
788
- end
789
-
790
- %x{
791
- validateParameters();
792
-
793
- if (step === 0) {
794
- while (true) {
795
- block(self);
796
- }
797
- }
798
-
799
- if (self % 1 !== 0 || limit % 1 !== 0 || step % 1 !== 0) {
800
- var n = stepFloatSize();
801
-
802
- if (n > 0) {
803
- if (step === Infinity || step === -Infinity) {
804
- block(self);
805
- } else {
806
- var i = 0, d;
807
-
808
- if (step > 0) {
809
- while (i < n) {
810
- d = i * step + self;
811
- if (limit < d) {
812
- d = limit;
813
- }
814
- block(d);
815
- i += 1;
816
- }
817
- } else {
818
- while (i < n) {
819
- d = i * step + self;
820
- if (limit > d) {
821
- d = limit;
822
- }
823
- block(d);
824
- i += 1
825
- }
826
- }
827
- }
828
- }
829
- } else {
830
- var value = self;
831
-
832
- if (step > 0) {
833
- while (value <= limit) {
834
- block(value);
835
- value += step;
836
- }
837
- } else {
838
- while (value >= limit) {
839
- block(value);
840
- value += step
841
- }
842
- }
843
- }
844
-
845
- return self;
846
- }
847
- end
848
-
849
671
  alias succ next
850
672
 
851
673
  def times(&block)
@@ -865,7 +687,7 @@ class Number < Numeric
865
687
  end
866
688
 
867
689
  def to_i
868
- `parseInt(self, 10)`
690
+ `self < 0 ? Math.ceil(self) : Math.floor(self)`
869
691
  end
870
692
 
871
693
  alias to_int to_i
@@ -145,6 +145,162 @@ class Numeric
145
145
  to_f.round(digits)
146
146
  end
147
147
 
148
+ def step(limit = undefined, step = undefined, to: undefined, by: undefined, &block)
149
+ %x{
150
+ if (limit !== undefined && to !== undefined) {
151
+ #{raise ArgumentError, 'to is given twice'}
152
+ }
153
+
154
+ if (step !== undefined && by !== undefined) {
155
+ #{raise ArgumentError, 'step is given twice'}
156
+ }
157
+
158
+ if (to !== undefined) {
159
+ limit = to;
160
+ }
161
+
162
+ if (by !== undefined) {
163
+ step = by;
164
+ }
165
+
166
+ if (limit === undefined) {
167
+ limit = nil;
168
+ }
169
+
170
+ function validateParameters() {
171
+ if (step === nil) {
172
+ #{raise TypeError, 'step must be numeric'}
173
+ }
174
+
175
+ if (step != null && #{step == 0}) {
176
+ #{raise ArgumentError, "step can't be 0"}
177
+ }
178
+
179
+ if (step === nil || step == null) {
180
+ step = 1;
181
+ }
182
+
183
+ var sign = #{step <=> 0};
184
+
185
+ if (sign === nil) {
186
+ #{raise ArgumentError, "0 can't be coerced into #{step.class}"}
187
+ }
188
+
189
+ if (limit === nil || limit == null) {
190
+ limit = sign > 0 ? #{Float::INFINITY} : #{-Float::INFINITY};
191
+ }
192
+
193
+ #{Opal.compare(self, limit)}
194
+ }
195
+
196
+ function stepFloatSize() {
197
+ if ((step > 0 && self > limit) || (step < 0 && self < limit)) {
198
+ return 0;
199
+ } else if (step === Infinity || step === -Infinity) {
200
+ return 1;
201
+ } else {
202
+ var abs = Math.abs, floor = Math.floor,
203
+ err = (abs(self) + abs(limit) + abs(limit - self)) / abs(step) * #{Float::EPSILON};
204
+
205
+ if (err === Infinity || err === -Infinity) {
206
+ return 0;
207
+ } else {
208
+ if (err > 0.5) {
209
+ err = 0.5;
210
+ }
211
+
212
+ return floor((limit - self) / step + err) + 1
213
+ }
214
+ }
215
+ }
216
+
217
+ function stepSize() {
218
+ validateParameters();
219
+
220
+ if (step === 0) {
221
+ return Infinity;
222
+ }
223
+
224
+ if (step % 1 !== 0) {
225
+ return stepFloatSize();
226
+ } else if ((step > 0 && self > limit) || (step < 0 && self < limit)) {
227
+ return 0;
228
+ } else {
229
+ var ceil = Math.ceil, abs = Math.abs,
230
+ lhs = abs(self - limit) + 1,
231
+ rhs = abs(step);
232
+
233
+ return ceil(lhs / rhs);
234
+ }
235
+ }
236
+
237
+ }
238
+
239
+ return enum_for(:step, limit, step, &`stepSize`) unless block_given?
240
+
241
+ %x{
242
+ validateParameters();
243
+
244
+ var isDesc = #{step.negative?},
245
+ isInf = #{step == 0} ||
246
+ (limit === Infinity && !isDesc) ||
247
+ (limit === -Infinity && isDesc);
248
+
249
+ if (self.$$is_number && step.$$is_number && limit.$$is_number) {
250
+ if (self % 1 === 0 && (isInf || limit % 1 === 0) && step % 1 === 0) {
251
+ var value = self;
252
+
253
+ if (isInf) {
254
+ for (;; value += step) {
255
+ block(value);
256
+ }
257
+ } else if (isDesc) {
258
+ for (; value >= limit; value += step) {
259
+ block(value);
260
+ }
261
+ } else {
262
+ for (; value <= limit; value += step) {
263
+ block(value);
264
+ }
265
+ }
266
+
267
+ return self;
268
+ } else {
269
+ var begin = #{to_f}.valueOf();
270
+ step = #{step.to_f}.valueOf();
271
+ limit = #{limit.to_f}.valueOf();
272
+
273
+ var n = stepFloatSize();
274
+
275
+ if (!isFinite(step)) {
276
+ if (n !== 0) block(begin);
277
+ } else if (step === 0) {
278
+ while (true) {
279
+ block(begin);
280
+ }
281
+ } else {
282
+ for (var i = 0; i < n; i++) {
283
+ var d = i * step + self;
284
+ if (step >= 0 ? limit < d : limit > d) {
285
+ d = limit;
286
+ }
287
+ block(d);
288
+ }
289
+ }
290
+
291
+ return self;
292
+ }
293
+ }
294
+ }
295
+
296
+ counter = self
297
+
298
+ while `isDesc ? #{counter >= limit} : #{counter <= limit}`
299
+ yield counter
300
+ counter += step
301
+ end
302
+ end
303
+
148
304
  def to_c
149
305
  Complex(self, 0)
150
306
  end