opal 1.1.1 → 1.2.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 (108) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +3 -2
  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/Gemfile +0 -4
  9. data/HACKING.md +1 -1
  10. data/README.md +19 -15
  11. data/UNRELEASED.md +41 -0
  12. data/benchmark-ips/bm_array_unshift.rb +7 -0
  13. data/bin/opal-mspec +2 -0
  14. data/docs/compiler.md +1 -1
  15. data/examples/rack/Gemfile +0 -1
  16. data/examples/rack/Gemfile.lock +0 -4
  17. data/lib/opal/cli.rb +1 -0
  18. data/lib/opal/cli_options.rb +4 -0
  19. data/lib/opal/cli_runners/nodejs.rb +4 -0
  20. data/lib/opal/cli_runners/source-map-support-browser.js +3 -1
  21. data/lib/opal/cli_runners/source-map-support-node.js +3 -1
  22. data/lib/opal/cli_runners/source-map-support.js +3 -1
  23. data/lib/opal/compiler.rb +2 -2
  24. data/lib/opal/nodes/args/arity_check.rb +1 -0
  25. data/lib/opal/nodes/args/parameters.rb +6 -0
  26. data/lib/opal/nodes/class.rb +1 -13
  27. data/lib/opal/nodes/literal.rb +14 -7
  28. data/lib/opal/nodes/module.rb +13 -9
  29. data/lib/opal/nodes/variables.rb +13 -4
  30. data/lib/opal/nodes/while.rb +54 -17
  31. data/lib/opal/parser.rb +1 -5
  32. data/lib/opal/parser/patch.rb +34 -0
  33. data/lib/opal/repl.rb +7 -0
  34. data/lib/opal/rewriter.rb +2 -0
  35. data/lib/opal/rewriters/arguments.rb +4 -1
  36. data/lib/opal/rewriters/forward_args.rb +54 -0
  37. data/lib/opal/rewriters/logical_operator_assignment.rb +5 -2
  38. data/lib/opal/rewriters/opal_engine_check.rb +5 -7
  39. data/lib/opal/version.rb +1 -1
  40. data/opal/corelib/array.rb +42 -20
  41. data/opal/corelib/array/pack.rb +6 -1
  42. data/opal/corelib/complex.rb +2 -0
  43. data/opal/corelib/constants.rb +3 -3
  44. data/opal/corelib/hash.rb +36 -38
  45. data/opal/corelib/module.rb +2 -7
  46. data/opal/corelib/number.rb +2 -180
  47. data/opal/corelib/numeric.rb +156 -0
  48. data/opal/corelib/object_space.rb +102 -0
  49. data/opal/corelib/random.rb +31 -66
  50. data/opal/corelib/random/formatter.rb +122 -0
  51. data/opal/corelib/range.rb +50 -19
  52. data/opal/corelib/runtime.js +82 -21
  53. data/opal/corelib/string.rb +86 -52
  54. data/opal/corelib/string/encoding.rb +140 -25
  55. data/opal/corelib/string/unpack.rb +26 -40
  56. data/opal/opal.rb +1 -0
  57. data/opal/opal/full.rb +1 -0
  58. data/spec/filters/bugs/array.rb +0 -22
  59. data/spec/filters/bugs/basicobject.rb +3 -0
  60. data/spec/filters/bugs/encoding.rb +0 -2
  61. data/spec/filters/bugs/exception.rb +1 -0
  62. data/spec/filters/bugs/float.rb +0 -2
  63. data/spec/filters/bugs/hash.rb +2 -7
  64. data/spec/filters/bugs/integer.rb +0 -2
  65. data/spec/filters/bugs/kernel.rb +16 -3
  66. data/spec/filters/bugs/language.rb +6 -14
  67. data/spec/filters/bugs/marshal.rb +1 -3
  68. data/spec/filters/bugs/module.rb +16 -1
  69. data/spec/filters/bugs/numeric.rb +4 -12
  70. data/spec/filters/bugs/objectspace.rb +67 -0
  71. data/spec/filters/bugs/pack_unpack.rb +0 -9
  72. data/spec/filters/bugs/pathname.rb +1 -0
  73. data/spec/filters/bugs/proc.rb +8 -0
  74. data/spec/filters/bugs/random.rb +3 -6
  75. data/spec/filters/bugs/range.rb +83 -113
  76. data/spec/filters/bugs/set.rb +2 -0
  77. data/spec/filters/bugs/string.rb +31 -70
  78. data/spec/filters/bugs/struct.rb +2 -0
  79. data/spec/filters/bugs/time.rb +8 -2
  80. data/spec/filters/unsupported/float.rb +3 -0
  81. data/spec/filters/unsupported/freeze.rb +1 -0
  82. data/spec/filters/unsupported/integer.rb +3 -0
  83. data/spec/filters/unsupported/refinements.rb +5 -0
  84. data/spec/filters/unsupported/string.rb +100 -95
  85. data/spec/filters/unsupported/time.rb +4 -0
  86. data/spec/lib/compiler_spec.rb +16 -0
  87. data/spec/lib/rewriters/forward_args_spec.rb +61 -0
  88. data/spec/lib/rewriters/logical_operator_assignment_spec.rb +1 -1
  89. data/spec/lib/rewriters/numblocks_spec.rb +44 -0
  90. data/spec/lib/rewriters/opal_engine_check_spec.rb +49 -4
  91. data/spec/opal/core/language/forward_args_spec.rb +53 -0
  92. data/spec/opal/core/language/infinite_range_spec.rb +13 -0
  93. data/spec/opal/core/language/memoization_spec.rb +16 -0
  94. data/spec/opal/core/module_spec.rb +38 -2
  95. data/spec/opal/core/number/to_i_spec.rb +28 -0
  96. data/spec/opal/core/runtime/bridged_classes_spec.rb +16 -0
  97. data/spec/opal/core/runtime/constants_spec.rb +20 -1
  98. data/spec/opal/core/string/subclassing_spec.rb +16 -0
  99. data/spec/opal/core/string/unpack_spec.rb +22 -0
  100. data/spec/opal/core/string_spec.rb +4 -4
  101. data/spec/ruby_specs +4 -1
  102. data/stdlib/json.rb +3 -1
  103. data/stdlib/securerandom.rb +55 -35
  104. data/tasks/testing.rake +6 -3
  105. data/test/nodejs/test_string.rb +25 -0
  106. data/vendored-minitest/minitest/assertions.rb +2 -0
  107. metadata +31 -10
  108. data/lib/opal/parser/with_c_lexer.rb +0 -15
@@ -20,7 +20,7 @@ module Opal
20
20
  get_node = lhs.updated(get_type) # lhs
21
21
  condition_node = s(root_type, get_node, rhs) # lhs || rhs
22
22
 
23
- if get_type == :const && root_type == :or
23
+ if %i[const cvar].include?(get_type) && root_type == :or
24
24
  # defined?(lhs)
25
25
  defined_node = s(:defined?, get_node)
26
26
  # LHS = defined?(LHS) ? (LHS || rhs) : rhs
@@ -51,7 +51,10 @@ module Opal
51
51
  GlobalVariableHandler = GET_SET[:gvar, :gvasgn]
52
52
 
53
53
  # Takes `@@lhs ||= rhs`
54
- # Produces `@@lhs = @@lhs || rhs`
54
+ # Produces `@@lhs = defined?(@@lhs) ? (@@lhs || rhs) : rhs`
55
+ #
56
+ # Takes `@@lhs &&= rhs`
57
+ # Produces `@@lhs = @@lhs && rhs`
55
58
  ClassVariableHandler = GET_SET[:cvar, :cvasgn]
56
59
 
57
60
  # Takes `recvr.meth ||= rhs`
@@ -9,14 +9,12 @@ module Opal
9
9
  test, true_body, false_body = *node.children
10
10
 
11
11
  if skip_check_present?(test)
12
- false_body = s(:nil)
12
+ process(true_body || s(:nil))
13
+ elsif skip_check_present_not?(test)
14
+ process(false_body || s(:nil))
15
+ else
16
+ super
13
17
  end
14
-
15
- if skip_check_present_not?(test)
16
- true_body = s(:nil)
17
- end
18
-
19
- node.updated(nil, process_all([test, true_body, false_body]))
20
18
  end
21
19
 
22
20
  def skip_check_present?(test)
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.1.1'
6
+ VERSION = '1.2.0.beta1'
7
7
  end
@@ -196,7 +196,7 @@ class Array < `Array`
196
196
  result = result.concat(converted);
197
197
  }
198
198
 
199
- return toArraySubclass(result, #{self.class});
199
+ return result;
200
200
  }
201
201
  end
202
202
 
@@ -361,7 +361,7 @@ class Array < `Array`
361
361
  }
362
362
 
363
363
  result = self.slice(from, to);
364
- return toArraySubclass(result, self.$class());
364
+ return result;
365
365
  }
366
366
 
367
367
  function $array_slice_index_length(self, index, length) {
@@ -394,7 +394,7 @@ class Array < `Array`
394
394
 
395
395
  result = self.slice(index, index + length);
396
396
  }
397
- return toArraySubclass(result, self.$class());
397
+ return result;
398
398
  }
399
399
  }
400
400
 
@@ -883,7 +883,9 @@ class Array < `Array`
883
883
  self
884
884
  end
885
885
 
886
- alias difference -
886
+ def difference(*arrays)
887
+ arrays.reduce(to_a.dup) { |a, b| a - b }
888
+ end
887
889
 
888
890
  def dig(idx, *idxs)
889
891
  item = self[idx]
@@ -1180,7 +1182,7 @@ class Array < `Array`
1180
1182
  level = $coerce_to(level, #{Integer}, 'to_int');
1181
1183
  }
1182
1184
 
1183
- return toArraySubclass(_flatten(self, level), #{self.class});
1185
+ return _flatten(self, level);
1184
1186
  }
1185
1187
  end
1186
1188
 
@@ -1335,7 +1337,9 @@ class Array < `Array`
1335
1337
  }
1336
1338
  end
1337
1339
 
1338
- alias intersection &
1340
+ def intersection(*arrays)
1341
+ arrays.reduce(to_a.dup) { |a, b| a & b }
1342
+ end
1339
1343
 
1340
1344
  def join(sep = nil)
1341
1345
  return '' if `self.length === 0`
@@ -2165,10 +2169,19 @@ class Array < `Array`
2165
2169
  end
2166
2170
 
2167
2171
  def to_a
2168
- self
2172
+ %x{
2173
+ if (self.$$class === Opal.Array) {
2174
+ return self;
2175
+ }
2176
+ else {
2177
+ return Opal.Array.$new(self);
2178
+ }
2179
+ }
2169
2180
  end
2170
2181
 
2171
- alias to_ary to_a
2182
+ def to_ary
2183
+ self
2184
+ end
2172
2185
 
2173
2186
  def to_h(&block)
2174
2187
  array = self
@@ -2224,7 +2237,9 @@ class Array < `Array`
2224
2237
  result
2225
2238
  end
2226
2239
 
2227
- alias union |
2240
+ def union(*arrays)
2241
+ arrays.reduce(uniq) { |a, b| a | b }
2242
+ end
2228
2243
 
2229
2244
  def uniq(&block)
2230
2245
  %x{
@@ -2248,7 +2263,7 @@ class Array < `Array`
2248
2263
  }
2249
2264
  }
2250
2265
 
2251
- return toArraySubclass(#{`hash`.values}, #{self.class});
2266
+ return #{`hash`.values};
2252
2267
  }
2253
2268
  end
2254
2269
 
@@ -2276,12 +2291,23 @@ class Array < `Array`
2276
2291
 
2277
2292
  def unshift(*objects)
2278
2293
  %x{
2279
- for (var i = objects.length - 1; i >= 0; i--) {
2280
- self.unshift(objects[i]);
2294
+ var selfLength = self.length
2295
+ var objectsLength = objects.length
2296
+ if (objectsLength == 0) return self;
2297
+ var index = selfLength - objectsLength
2298
+ for (var i = 0; i < objectsLength; i++) {
2299
+ self.push(self[index + i])
2300
+ }
2301
+ var len = selfLength - 1
2302
+ while (len - objectsLength >= 0) {
2303
+ self[len] = self[len - objectsLength]
2304
+ len--
2305
+ }
2306
+ for (var j = 0; j < objectsLength; j++) {
2307
+ self[j] = objects[j]
2281
2308
  }
2309
+ return self;
2282
2310
  }
2283
-
2284
- self
2285
2311
  end
2286
2312
 
2287
2313
  alias prepend unshift
@@ -2332,12 +2358,8 @@ class Array < `Array`
2332
2358
  if (o.$$is_array) {
2333
2359
  continue;
2334
2360
  }
2335
- if (o.$$is_enumerator) {
2336
- if (o.$size() === Infinity) {
2337
- others[j] = o.$take(size);
2338
- } else {
2339
- others[j] = o.$to_a();
2340
- }
2361
+ if (o.$$is_range || o.$$is_enumerator) {
2362
+ others[j] = o.$take(size);
2341
2363
  continue;
2342
2364
  }
2343
2365
  others[j] = #{(
@@ -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.1'
5
- RUBY_RELEASE_DATE = '2021-02-23'
3
+ RUBY_VERSION = '3.0.2'
4
+ RUBY_ENGINE_VERSION = '1.2.0.beta1'
5
+ RUBY_RELEASE_DATE = '2021-07-23'
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
@@ -762,53 +762,51 @@ class Hash
762
762
 
763
763
  alias member? has_key?
764
764
 
765
- def merge(other, &block)
766
- dup.merge!(other, &block)
765
+ def merge(*others, &block)
766
+ dup.merge!(*others, &block)
767
767
  end
768
768
 
769
- def merge!(other, &block)
769
+ def merge!(*others, &block)
770
770
  %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;
771
+ var i, j, other, other_keys, length, key, value, other_value;
772
+ for (i = 0; i < others.length; ++i) {
773
+ other = #{Opal.coerce_to!(`others[i]`, Hash, :to_hash)};
774
+ other_keys = other.$$keys, length = other_keys.length;
775
+
776
+ if (block === nil) {
777
+ for (j = 0; j < length; j++) {
778
+ key = other_keys[j];
779
+
780
+ if (key.$$is_string) {
781
+ other_value = other.$$smap[key];
782
+ } else {
783
+ other_value = key.value;
784
+ key = key.key;
785
+ }
786
+
787
+ Opal.hash_put(self, key, other_value);
786
788
  }
789
+ } else {
790
+ for (j = 0; j < length; j++) {
791
+ key = other_keys[j];
787
792
 
788
- Opal.hash_put(self, key, other_value);
789
- }
793
+ if (key.$$is_string) {
794
+ other_value = other.$$smap[key];
795
+ } else {
796
+ other_value = key.value;
797
+ key = key.key;
798
+ }
790
799
 
791
- return self;
792
- }
800
+ value = Opal.hash_get(self, key);
793
801
 
794
- for (i = 0; i < length; i++) {
795
- key = other_keys[i];
802
+ if (value === undefined) {
803
+ Opal.hash_put(self, key, other_value);
804
+ continue;
805
+ }
796
806
 
797
- if (key.$$is_string) {
798
- other_value = other.$$smap[key];
799
- } else {
800
- other_value = key.value;
801
- key = key.key;
802
- }
803
-
804
- value = Opal.hash_get(self, key);
805
-
806
- if (value === undefined) {
807
- Opal.hash_put(self, key, other_value);
808
- continue;
807
+ Opal.hash_put(self, key, block(key, value, other_value));
808
+ }
809
809
  }
810
-
811
- Opal.hash_put(self, key, block(key, value, other_value));
812
810
  }
813
811
 
814
812
  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