opal 0.9.4 → 0.10.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (193) hide show
  1. checksums.yaml +4 -4
  2. data/.gitattributes +1 -0
  3. data/.gitignore +2 -3
  4. data/.gitmodules +5 -2
  5. data/.jshintrc +1 -8
  6. data/.rspec +1 -1
  7. data/.travis.yml +15 -23
  8. data/CHANGELOG.md +511 -326
  9. data/CODE_OF_CONDUCT.md +13 -15
  10. data/CONTRIBUTING.md +26 -216
  11. data/Gemfile +20 -12
  12. data/Guardfile +2 -2
  13. data/HACKING.md +230 -0
  14. data/README.md +6 -7
  15. data/bin/opal-mspec +1 -1
  16. data/config.ru +2 -2
  17. data/docs/faq.md +1 -1
  18. data/docs/source_maps.md +1 -1
  19. data/lib/opal.rb +1 -0
  20. data/lib/opal/builder.rb +1 -1
  21. data/lib/opal/cli.rb +30 -28
  22. data/lib/opal/cli_options.rb +3 -0
  23. data/lib/opal/cli_runners.rb +14 -1
  24. data/lib/opal/cli_runners/{apple_script.rb → applescript.rb} +3 -3
  25. data/lib/opal/cli_runners/nashorn.rb +2 -2
  26. data/lib/opal/cli_runners/nodejs.rb +2 -2
  27. data/lib/opal/cli_runners/phantom.js +24 -0
  28. data/lib/opal/cli_runners/phantomjs.rb +10 -10
  29. data/lib/opal/cli_runners/server.rb +3 -3
  30. data/lib/opal/compiler.rb +43 -4
  31. data/lib/opal/config.rb +3 -1
  32. data/lib/opal/errors.rb +13 -0
  33. data/lib/opal/fragment.rb +0 -13
  34. data/lib/opal/nodes.rb +10 -0
  35. data/lib/opal/nodes/args/initialize_kwargs.rb +28 -0
  36. data/lib/opal/nodes/args/kwarg.rb +29 -0
  37. data/lib/opal/nodes/args/kwoptarg.rb +29 -0
  38. data/lib/opal/nodes/args/kwrestarg.rb +39 -0
  39. data/lib/opal/nodes/args/mlhsarg.rb +79 -0
  40. data/lib/opal/nodes/args/normarg.rb +26 -0
  41. data/lib/opal/nodes/args/optarg.rb +27 -0
  42. data/lib/opal/nodes/args/post_args.rb +200 -0
  43. data/lib/opal/nodes/args/post_kwargs.rb +31 -0
  44. data/lib/opal/nodes/args/restarg.rb +33 -0
  45. data/lib/opal/nodes/base.rb +12 -0
  46. data/lib/opal/nodes/call.rb +92 -33
  47. data/lib/opal/nodes/def.rb +26 -169
  48. data/lib/opal/nodes/hash.rb +10 -4
  49. data/lib/opal/nodes/helpers.rb +6 -3
  50. data/lib/opal/nodes/inline_args.rb +61 -0
  51. data/lib/opal/nodes/iter.rb +73 -82
  52. data/lib/opal/nodes/logic.rb +12 -2
  53. data/lib/opal/nodes/masgn.rb +1 -2
  54. data/lib/opal/nodes/node_with_args.rb +141 -0
  55. data/lib/opal/nodes/rescue.rb +121 -43
  56. data/lib/opal/nodes/scope.rb +24 -5
  57. data/lib/opal/nodes/super.rb +122 -54
  58. data/lib/opal/nodes/top.rb +0 -12
  59. data/lib/opal/nodes/yield.rb +2 -13
  60. data/lib/opal/parser.rb +67 -39
  61. data/lib/opal/parser/grammar.rb +3319 -2961
  62. data/lib/opal/parser/grammar.y +234 -46
  63. data/lib/opal/parser/lexer.rb +105 -17
  64. data/lib/opal/parser/sexp.rb +4 -0
  65. data/lib/opal/paths.rb +4 -0
  66. data/lib/opal/regexp_anchors.rb +19 -1
  67. data/lib/opal/sprockets.rb +21 -18
  68. data/lib/opal/sprockets/environment.rb +0 -8
  69. data/lib/opal/sprockets/processor.rb +13 -16
  70. data/lib/opal/sprockets/server.rb +6 -12
  71. data/lib/opal/version.rb +1 -1
  72. data/opal.gemspec +1 -0
  73. data/opal/corelib/array.rb +209 -131
  74. data/opal/corelib/basic_object.rb +7 -3
  75. data/opal/corelib/class.rb +11 -17
  76. data/opal/corelib/constants.rb +2 -2
  77. data/opal/corelib/enumerable.rb +178 -355
  78. data/opal/corelib/enumerator.rb +3 -46
  79. data/opal/corelib/error.rb +2 -2
  80. data/opal/corelib/file.rb +13 -1
  81. data/opal/corelib/hash.rb +26 -56
  82. data/opal/corelib/helpers.rb +10 -0
  83. data/opal/corelib/kernel.rb +6 -3
  84. data/opal/corelib/module.rb +62 -31
  85. data/opal/corelib/number.rb +7 -16
  86. data/opal/corelib/proc.rb +24 -9
  87. data/opal/corelib/range.rb +4 -13
  88. data/opal/corelib/runtime.js +515 -378
  89. data/opal/corelib/string.rb +21 -49
  90. data/opal/corelib/struct.rb +50 -35
  91. data/opal/corelib/unsupported.rb +18 -30
  92. data/opal/opal.rb +0 -1
  93. data/opal/opal/mini.rb +1 -0
  94. data/spec/README.md +6 -4
  95. data/spec/filters/bugs/array.rb +0 -42
  96. data/spec/filters/bugs/basicobject.rb +0 -2
  97. data/spec/filters/bugs/bigdecimal.rb +160 -0
  98. data/spec/filters/bugs/class.rb +0 -5
  99. data/spec/filters/bugs/date.rb +1 -48
  100. data/spec/filters/bugs/enumerable.rb +4 -12
  101. data/spec/filters/bugs/enumerator.rb +0 -1
  102. data/spec/filters/bugs/exception.rb +4 -3
  103. data/spec/filters/bugs/float.rb +4 -2
  104. data/spec/filters/bugs/kernel.rb +25 -10
  105. data/spec/filters/bugs/language.rb +119 -68
  106. data/spec/filters/bugs/method.rb +135 -0
  107. data/spec/filters/bugs/module.rb +13 -28
  108. data/spec/filters/bugs/proc.rb +18 -8
  109. data/spec/filters/bugs/range.rb +0 -3
  110. data/spec/filters/bugs/rational.rb +4 -0
  111. data/spec/filters/bugs/regexp.rb +68 -36
  112. data/spec/filters/bugs/string.rb +1 -1
  113. data/spec/filters/bugs/struct.rb +0 -12
  114. data/spec/filters/bugs/time.rb +1 -0
  115. data/spec/filters/bugs/unboundmethod.rb +2 -1
  116. data/spec/filters/unsupported/freeze.rb +3 -1
  117. data/spec/filters/unsupported/language.rb +0 -7
  118. data/spec/filters/unsupported/privacy.rb +7 -6
  119. data/spec/filters/unsupported/string.rb +10 -0
  120. data/spec/filters/unsupported/struct.rb +3 -0
  121. data/spec/filters/unsupported/symbol.rb +9 -0
  122. data/spec/filters/unsupported/taint.rb +0 -3
  123. data/spec/filters/unsupported/thread.rb +1 -0
  124. data/spec/lib/cli_runners/phantomjs_spec.rb +39 -0
  125. data/spec/lib/cli_spec.rb +42 -1
  126. data/spec/lib/compiler/call_spec.rb +700 -0
  127. data/spec/lib/compiler_spec.rb +46 -28
  128. data/spec/lib/config_spec.rb +13 -0
  129. data/spec/lib/parser/call_spec.rb +18 -0
  130. data/spec/lib/parser/def_spec.rb +29 -0
  131. data/spec/lib/parser/iter_spec.rb +15 -15
  132. data/spec/lib/parser/lambda_spec.rb +153 -12
  133. data/spec/lib/parser/string_spec.rb +5 -0
  134. data/spec/lib/parser/undef_spec.rb +1 -1
  135. data/spec/lib/parser/variables_spec.rb +24 -0
  136. data/spec/lib/paths_spec.rb +12 -5
  137. data/spec/lib/spec_helper.rb +5 -0
  138. data/spec/lib/sprockets/processor_spec.rb +6 -5
  139. data/spec/lib/sprockets_spec.rb +8 -0
  140. data/spec/mspec-opal/formatters.rb +188 -0
  141. data/spec/mspec-opal/runner.rb +193 -0
  142. data/spec/opal/core/enumerator/with_index_spec.rb +6 -0
  143. data/spec/opal/core/kernel/define_singleton_method_spec.rb +1 -1
  144. data/spec/opal/core/kernel/instance_variables_spec.rb +14 -0
  145. data/spec/opal/core/kernel/loop_spec.rb +1 -1
  146. data/spec/opal/core/kernel/raise_spec.rb +1 -1
  147. data/spec/opal/core/language/heredoc_spec.rb +42 -0
  148. data/spec/opal/core/language/rescue_spec.rb +18 -0
  149. data/spec/opal/core/language_spec.rb +22 -0
  150. data/spec/opal/core/module/const_defined_spec.rb +1 -2
  151. data/spec/opal/core/module/name_spec.rb +6 -0
  152. data/spec/opal/core/runtime/bridged_classes_spec.rb +14 -2
  153. data/spec/opal/core/runtime/rescue_spec.rb +12 -2
  154. data/spec/opal/core/runtime/super_spec.rb +1 -0
  155. data/spec/opal/core/string_spec.rb +21 -0
  156. data/spec/opal/stdlib/js_spec.rb +1 -1
  157. data/spec/opal/stdlib/native/hash_spec.rb +7 -0
  158. data/spec/opal/stdlib/promise/always_spec.rb +24 -5
  159. data/spec/opal/stdlib/promise/rescue_spec.rb +15 -6
  160. data/spec/opal/stdlib/promise/then_spec.rb +13 -5
  161. data/spec/opal/stdlib/promise/trace_spec.rb +5 -6
  162. data/spec/opal/stdlib/strscan/scan_spec.rb +1 -1
  163. data/spec/ruby_specs +122 -0
  164. data/spec/spec_helper.rb +3 -15
  165. data/stdlib/base64.rb +51 -121
  166. data/stdlib/bigdecimal.rb +231 -0
  167. data/stdlib/bigdecimal/bignumber.js.rb +11 -0
  168. data/stdlib/bigdecimal/kernel.rb +5 -0
  169. data/stdlib/date.rb +252 -10
  170. data/stdlib/native.rb +38 -38
  171. data/stdlib/nodejs/dir.rb +8 -6
  172. data/stdlib/nodejs/file.rb +28 -3
  173. data/stdlib/nodejs/node_modules/.bin/js-yaml +1 -0
  174. data/stdlib/nodejs/node_modules/js-yaml/node_modules/.bin/esparse +1 -0
  175. data/stdlib/nodejs/node_modules/js-yaml/node_modules/.bin/esvalidate +1 -0
  176. data/stdlib/nodejs/require.rb +1 -1
  177. data/stdlib/nodejs/yaml.rb +3 -2
  178. data/stdlib/opal-parser.rb +7 -2
  179. data/stdlib/pathname.rb +23 -1
  180. data/stdlib/phantomjs.rb +10 -0
  181. data/stdlib/promise.rb +38 -23
  182. data/tasks/building.rake +3 -3
  183. data/tasks/testing.rake +27 -14
  184. data/tasks/testing/mspec_special_calls.rb +1 -1
  185. data/tasks/testing/sprockets-phantomjs.js +4 -0
  186. data/test/opal/test_keyword.rb +110 -110
  187. data/test/opal/unsupported_and_bugs.rb +30 -0
  188. data/vendored-minitest/minitest/assertions.rb +1 -1
  189. metadata +65 -15
  190. data/.spectator +0 -2
  191. data/.spectator-mspec +0 -3
  192. data/opal/corelib/array/inheritance.rb +0 -127
  193. data/spec/rubyspecs +0 -139
data/lib/opal/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  module Opal
2
2
  # WHEN RELEASING:
3
3
  # Remember to update RUBY_ENGINE_VERSION in opal/corelib/constants.rb too!
4
- VERSION = '0.9.4'
4
+ VERSION = '0.10.0.beta1'
5
5
  end
data/opal.gemspec CHANGED
@@ -34,4 +34,5 @@ Gem::Specification.new do |s|
34
34
  s.add_development_dependency 'yard', '~> 0.8.7'
35
35
  s.add_development_dependency 'rack-test'
36
36
  s.add_development_dependency 'opal-minitest'
37
+ s.add_development_dependency 'coveralls'
37
38
  end
@@ -7,8 +7,18 @@ class Array < `Array`
7
7
  # Mark all javascript arrays as being valid ruby arrays
8
8
  `def.$$is_array = true`
9
9
 
10
+ %x{
11
+ function toArraySubclass(obj, klass) {
12
+ if (klass.$$name === Opal.Array) {
13
+ return obj;
14
+ } else {
15
+ return klass.$allocate().$replace(#{`obj`.to_a});
16
+ }
17
+ }
18
+ }
19
+
10
20
  def self.[](*objects)
11
- objects
21
+ `toArraySubclass(objects, self)`
12
22
  end
13
23
 
14
24
  def initialize(size = nil, obj = nil, &block)
@@ -25,9 +35,11 @@ class Array < `Array`
25
35
 
26
36
  if `arguments.length === 1`
27
37
  if Array === size
28
- return size.to_a
38
+ replace(size.to_a)
39
+ return self
29
40
  elsif size.respond_to? :to_ary
30
- return size.to_ary
41
+ replace(size.to_ary)
42
+ return self
31
43
  end
32
44
  end
33
45
 
@@ -49,11 +61,6 @@ class Array < `Array`
49
61
  else {
50
62
  for (i = 0, value; i < size; i++) {
51
63
  value = block(i);
52
-
53
- if (value === $breaker) {
54
- return $breaker.$v;
55
- }
56
-
57
64
  self[i] = value;
58
65
  }
59
66
  }
@@ -62,10 +69,6 @@ class Array < `Array`
62
69
  }
63
70
  end
64
71
 
65
- def self.new(*args, &block)
66
- [].initialize(*args, &block)
67
- end
68
-
69
72
  def self.try_convert(obj)
70
73
  Opal.coerce_to? obj, Array, :to_ary
71
74
  end
@@ -120,10 +123,6 @@ class Array < `Array`
120
123
  def *(other)
121
124
  return join(other.to_str) if other.respond_to? :to_str
122
125
 
123
- unless other.respond_to? :to_int
124
- raise TypeError, "no implicit conversion of #{other.class} into Integer"
125
- end
126
-
127
126
  other = Opal.coerce_to other, Integer, :to_int
128
127
 
129
128
  if `other < 0`
@@ -131,13 +130,14 @@ class Array < `Array`
131
130
  end
132
131
 
133
132
  %x{
134
- var result = [];
133
+ var result = [],
134
+ converted = #{self.to_a};
135
135
 
136
136
  for (var i = 0; i < other; i++) {
137
- result = result.concat(self);
137
+ result = result.concat(converted);
138
138
  }
139
139
 
140
- return result;
140
+ return toArraySubclass(result, #{self.class});
141
141
  }
142
142
  end
143
143
 
@@ -159,7 +159,7 @@ class Array < `Array`
159
159
  end
160
160
 
161
161
  return [] if `self.length === 0`
162
- return clone if `other.length === 0`
162
+ return clone.to_a if `other.length === 0`
163
163
 
164
164
  %x{
165
165
  var result = [], hash = #{{}}, i, length, item;
@@ -232,9 +232,9 @@ class Array < `Array`
232
232
  }
233
233
 
234
234
  if (array.constructor !== Array)
235
- array = array.literal;
235
+ array = #{`array`.to_a};
236
236
  if (other.constructor !== Array)
237
- other = other.literal;
237
+ other = #{`other`.to_a};
238
238
 
239
239
  if (array.length !== other.length) {
240
240
  return false;
@@ -271,7 +271,7 @@ class Array < `Array`
271
271
  def [](index, length = undefined)
272
272
  %x{
273
273
  var size = self.length,
274
- exclude, from, to;
274
+ exclude, from, to, result;
275
275
 
276
276
  if (index.$$is_range) {
277
277
  exclude = index.exclude;
@@ -302,7 +302,7 @@ class Array < `Array`
302
302
  to += 1;
303
303
  }
304
304
 
305
- return self.slice(from, to);
305
+ result = self.slice(from, to)
306
306
  }
307
307
  else {
308
308
  index = #{Opal.coerce_to(index, Integer, :to_int)};
@@ -329,9 +329,11 @@ class Array < `Array`
329
329
  return nil;
330
330
  }
331
331
 
332
- return self.slice(index, index + length);
332
+ result = self.slice(index, index + length);
333
333
  }
334
334
  }
335
+
336
+ return toArraySubclass(result, #{self.class})
335
337
  }
336
338
  end
337
339
 
@@ -483,10 +485,7 @@ class Array < `Array`
483
485
  val = self[mid];
484
486
  ret = block(val);
485
487
 
486
- if (ret === $breaker) {
487
- return $breaker.$v;
488
- }
489
- else if (ret === true) {
488
+ if (ret === true) {
490
489
  satisfied = val;
491
490
  smaller = true;
492
491
  }
@@ -527,10 +526,6 @@ class Array < `Array`
527
526
  while (true) {
528
527
  for (i = 0, length = self.length; i < length; i++) {
529
528
  value = Opal.yield1(block, self[i]);
530
-
531
- if (value === $breaker) {
532
- return $breaker.$v;
533
- }
534
529
  }
535
530
  }
536
531
  }
@@ -543,10 +538,6 @@ class Array < `Array`
543
538
  while (n > 0) {
544
539
  for (i = 0, length = self.length; i < length; i++) {
545
540
  value = Opal.yield1(block, self[i]);
546
-
547
- if (value === $breaker) {
548
- return $breaker.$v;
549
- }
550
541
  }
551
542
 
552
543
  n--;
@@ -563,19 +554,6 @@ class Array < `Array`
563
554
  self
564
555
  end
565
556
 
566
- def clone
567
- copy = []
568
- copy.copy_singleton_methods(self)
569
- copy.initialize_clone(self)
570
- copy
571
- end
572
-
573
- def dup
574
- copy = []
575
- copy.initialize_dup(self)
576
- copy
577
- end
578
-
579
557
  def initialize_copy(other)
580
558
  replace other
581
559
  end
@@ -588,11 +566,6 @@ class Array < `Array`
588
566
 
589
567
  for (var i = 0, length = self.length; i < length; i++) {
590
568
  var value = Opal.yield1(block, self[i]);
591
-
592
- if (value === $breaker) {
593
- return $breaker.$v;
594
- }
595
-
596
569
  result.push(value);
597
570
  }
598
571
 
@@ -606,11 +579,6 @@ class Array < `Array`
606
579
  %x{
607
580
  for (var i = 0, length = self.length; i < length; i++) {
608
581
  var value = Opal.yield1(block, self[i]);
609
-
610
- if (value === $breaker) {
611
- return $breaker.$v;
612
- }
613
-
614
582
  self[i] = value;
615
583
  }
616
584
  }
@@ -680,6 +648,34 @@ class Array < `Array`
680
648
  self
681
649
  end
682
650
 
651
+ def repeated_combination(n)
652
+ num = Opal.coerce_to! n, Integer, :to_int
653
+
654
+ unless block_given?
655
+ return enum_for(:repeated_combination, num){ `binomial_coefficient(self.length + num - 1, num)` }
656
+ end
657
+
658
+ %x{
659
+ function iterate(max, from, buffer, self) {
660
+ if (buffer.length == max) {
661
+ var copy = buffer.slice();
662
+ #{yield `copy`}
663
+ return;
664
+ }
665
+ for (var i = from; i < self.length; i++) {
666
+ buffer.push(self[i]);
667
+ iterate(max, i, buffer, self);
668
+ buffer.pop();
669
+ }
670
+ }
671
+
672
+ if (num >= 0) {
673
+ iterate(num, 0, [], self);
674
+ }
675
+ }
676
+ self
677
+ end
678
+
683
679
  def compact
684
680
  %x{
685
681
  var result = [];
@@ -775,9 +771,7 @@ class Array < `Array`
775
771
 
776
772
  %x{
777
773
  for (var i = 0, length = self.length, value; i < length; i++) {
778
- if ((value = block(self[i])) === $breaker) {
779
- return $breaker.$v;
780
- }
774
+ value = block(self[i]);
781
775
 
782
776
  if (value !== false && value !== nil) {
783
777
  self.splice(i, 1);
@@ -807,10 +801,6 @@ class Array < `Array`
807
801
  %x{
808
802
  for (var i = 0, length = self.length; i < length; i++) {
809
803
  var value = Opal.yield1(block, self[i]);
810
-
811
- if (value == $breaker) {
812
- return $breaker.$v;
813
- }
814
804
  }
815
805
  }
816
806
 
@@ -823,10 +813,6 @@ class Array < `Array`
823
813
  %x{
824
814
  for (var i = 0, length = self.length; i < length; i++) {
825
815
  var value = Opal.yield1(block, i);
826
-
827
- if (value === $breaker) {
828
- return $breaker.$v;
829
- }
830
816
  }
831
817
  }
832
818
 
@@ -981,11 +967,6 @@ class Array < `Array`
981
967
  %x{
982
968
  for (length = #@length; left < right; left++) {
983
969
  value = block(left);
984
-
985
- if (value === $breaker) {
986
- return $breaker.$v;
987
- }
988
-
989
970
  self[left] = value;
990
971
  }
991
972
  }
@@ -1050,7 +1031,7 @@ class Array < `Array`
1050
1031
 
1051
1032
  switch (level) {
1052
1033
  case undefined:
1053
- result.push.apply(result, _flatten(ary));
1034
+ result = result.concat(_flatten(ary));
1054
1035
  break;
1055
1036
  case 0:
1056
1037
  result.push(ary);
@@ -1066,7 +1047,7 @@ class Array < `Array`
1066
1047
  level = #{Opal.coerce_to(`level`, Integer, :to_int)};
1067
1048
  }
1068
1049
 
1069
- return _flatten(self, level);
1050
+ return toArraySubclass(_flatten(self, level), #{self.class});
1070
1051
  }
1071
1052
  end
1072
1053
 
@@ -1158,9 +1139,7 @@ class Array < `Array`
1158
1139
  }
1159
1140
  else if (block !== nil) {
1160
1141
  for (i = 0, length = self.length; i < length; i++) {
1161
- if ((value = block(self[i])) === $breaker) {
1162
- return $breaker.$v;
1163
- }
1142
+ value = block(self[i]);
1164
1143
 
1165
1144
  if (value !== false && value !== nil) {
1166
1145
  return i;
@@ -1285,9 +1264,7 @@ class Array < `Array`
1285
1264
 
1286
1265
  %x{
1287
1266
  for (var i = 0, length = self.length, value; i < length; i++) {
1288
- if ((value = block(self[i])) === $breaker) {
1289
- return $breaker.$v;
1290
- }
1267
+ value = block(self[i]);
1291
1268
 
1292
1269
  if (value === false || value === nil) {
1293
1270
  self.splice(i, 1);
@@ -1329,8 +1306,23 @@ class Array < `Array`
1329
1306
 
1330
1307
  alias map! collect!
1331
1308
 
1309
+ %x{
1310
+ // Returns the product of from, from-1, ..., from - how_many + 1.
1311
+ function descending_factorial(from, how_many) {
1312
+ var count = how_many >= 0 ? 1 : 0;
1313
+ while (how_many) {
1314
+ count *= from;
1315
+ from--;
1316
+ how_many--;
1317
+ }
1318
+ return count;
1319
+ }
1320
+ }
1321
+
1332
1322
  def permutation(num = undefined, &block)
1333
- return enum_for(:permutation, num){self.size} unless block_given?
1323
+ unless block_given?
1324
+ return enum_for(:permutation, num){ `descending_factorial(self.length, num === undefined ? self.length : num)` }
1325
+ end
1334
1326
 
1335
1327
  %x{
1336
1328
  var permute, offensive, output;
@@ -1395,6 +1387,30 @@ class Array < `Array`
1395
1387
  self
1396
1388
  end
1397
1389
 
1390
+ def repeated_permutation(n)
1391
+ num = Opal.coerce_to! n, Integer, :to_int
1392
+ return enum_for(:repeated_permutation, num){ num >= 0 ? self.size ** num : 0 } unless block_given?
1393
+
1394
+ %x{
1395
+ function iterate(max, buffer, self) {
1396
+ if (buffer.length == max) {
1397
+ var copy = buffer.slice();
1398
+ #{yield `copy`}
1399
+ return;
1400
+ }
1401
+ for (var i = 0; i < self.length; i++) {
1402
+ buffer.push(self[i]);
1403
+ iterate(max, buffer, self);
1404
+ buffer.pop();
1405
+ }
1406
+ }
1407
+
1408
+ iterate(num, [], self.slice());
1409
+ }
1410
+
1411
+ self
1412
+ end
1413
+
1398
1414
  def pop(count = undefined)
1399
1415
  if `count === undefined`
1400
1416
  return if `self.length === 0`
@@ -1499,9 +1515,7 @@ class Array < `Array`
1499
1515
  var result = [];
1500
1516
 
1501
1517
  for (var i = 0, length = self.length, value; i < length; i++) {
1502
- if ((value = block(self[i])) === $breaker) {
1503
- return $breaker.$v;
1504
- }
1518
+ value = block(self[i]);
1505
1519
 
1506
1520
  if (value === false || value === nil) {
1507
1521
  result.push(self[i]);
@@ -1571,9 +1585,9 @@ class Array < `Array`
1571
1585
  if (i >= self.length) {
1572
1586
  break;
1573
1587
  }
1574
- if ((value = block(self[i])) === $breaker) {
1575
- return $breaker.$v;
1576
- }
1588
+
1589
+ value = block(self[i]);
1590
+
1577
1591
  if (value !== false && value !== nil) {
1578
1592
  return i;
1579
1593
  }
@@ -1753,9 +1767,7 @@ class Array < `Array`
1753
1767
  for (var i = 0, length = self.length, item, value; i < length; i++) {
1754
1768
  item = self[i];
1755
1769
 
1756
- if ((value = Opal.yield1(block, item)) === $breaker) {
1757
- return $breaker.$v;
1758
- }
1770
+ value = Opal.yield1(block, item);
1759
1771
 
1760
1772
  if (value !== false && value !== nil) {
1761
1773
  result.push(item);
@@ -1796,7 +1808,7 @@ class Array < `Array`
1796
1808
  alias size length
1797
1809
 
1798
1810
  def shuffle(rng = undefined)
1799
- dup.shuffle!(rng)
1811
+ dup.to_a.shuffle!(rng)
1800
1812
  end
1801
1813
 
1802
1814
  def shuffle!(rng = undefined)
@@ -1843,21 +1855,88 @@ class Array < `Array`
1843
1855
  alias slice []
1844
1856
 
1845
1857
  def slice!(index, length = undefined)
1846
- %x{
1847
- if (index < 0) {
1848
- index += self.length;
1849
- }
1858
+ result = nil
1850
1859
 
1851
- if (length != null) {
1852
- return self.splice(index, length);
1853
- }
1860
+ if `length === undefined`
1861
+ if Range === index
1862
+ range = index
1863
+ result = self[range]
1854
1864
 
1855
- if (index < 0 || index >= self.length) {
1856
- return nil;
1857
- }
1865
+ range_start = Opal.coerce_to(range.begin, Integer, :to_int)
1866
+ range_end = Opal.coerce_to(range.end, Integer, :to_int)
1858
1867
 
1859
- return self.splice(index, 1)[0];
1860
- }
1868
+ %x{
1869
+ if (range_start < 0) {
1870
+ range_start += self.length;
1871
+ }
1872
+
1873
+ if (range_end < 0) {
1874
+ range_end += self.length;
1875
+ } else if (range_end >= self.length) {
1876
+ range_end = self.length - 1;
1877
+ if (range.exclude) {
1878
+ range_end += 1;
1879
+ }
1880
+ }
1881
+
1882
+ var range_length = range_end - range_start;
1883
+ if (range.exclude) {
1884
+ range_end -= 1;
1885
+ } else {
1886
+ range_length += 1;
1887
+ }
1888
+
1889
+ if (range_start < self.length && range_start >= 0 && range_end < self.length && range_end >= 0 && range_length > 0) {
1890
+ self.splice(range_start, range_length);
1891
+ }
1892
+ }
1893
+ else
1894
+ start = Opal.coerce_to(index, Integer, :to_int)
1895
+ %x{
1896
+ if (start < 0) {
1897
+ start += self.length;
1898
+ }
1899
+
1900
+ if (start < 0 || start >= self.length) {
1901
+ return nil;
1902
+ }
1903
+
1904
+ result = self[start];
1905
+
1906
+ if (start === 0) {
1907
+ self.shift();
1908
+ } else {
1909
+ self.splice(start, 1);
1910
+ }
1911
+ }
1912
+ end
1913
+ else
1914
+ start = Opal.coerce_to(index, Integer, :to_int)
1915
+ length = Opal.coerce_to(length, Integer, :to_int)
1916
+
1917
+ %x{
1918
+ if (length < 0) {
1919
+ return nil;
1920
+ }
1921
+
1922
+ var end = start + length;
1923
+
1924
+ result = #{self[start, length]};
1925
+
1926
+ if (start < 0) {
1927
+ start += self.length;
1928
+ }
1929
+
1930
+ if (start + length > self.length) {
1931
+ length = self.length - start;
1932
+ }
1933
+
1934
+ if (start < self.length && start >= 0) {
1935
+ self.splice(start, length);
1936
+ }
1937
+ }
1938
+ end
1939
+ result
1861
1940
  end
1862
1941
 
1863
1942
  def sort(&block)
@@ -1870,28 +1949,15 @@ class Array < `Array`
1870
1949
  };
1871
1950
  }
1872
1951
 
1873
- try {
1874
- return self.slice().sort(function(x, y) {
1875
- var ret = block(x, y);
1952
+ return self.slice().sort(function(x, y) {
1953
+ var ret = block(x, y);
1876
1954
 
1877
- if (ret === $breaker) {
1878
- throw $breaker;
1879
- }
1880
- else if (ret === nil) {
1881
- #{raise ArgumentError, "comparison of #{`x`.inspect} with #{`y`.inspect} failed"};
1882
- }
1883
-
1884
- return #{`ret` > 0} ? 1 : (#{`ret` < 0} ? -1 : 0);
1885
- });
1886
- }
1887
- catch (e) {
1888
- if (e === $breaker) {
1889
- return $breaker.$v;
1955
+ if (ret === nil) {
1956
+ #{raise ArgumentError, "comparison of #{`x`.inspect} with #{`y`.inspect} failed"};
1890
1957
  }
1891
- else {
1892
- throw e;
1893
- }
1894
- }
1958
+
1959
+ return #{`ret` > 0} ? 1 : (#{`ret` < 0} ? -1 : 0);
1960
+ });
1895
1961
  }
1896
1962
  end
1897
1963
 
@@ -1915,6 +1981,12 @@ class Array < `Array`
1915
1981
  }
1916
1982
  end
1917
1983
 
1984
+ def sort_by!(&block)
1985
+ return enum_for(:sort_by!){self.size} unless block_given?
1986
+
1987
+ replace sort_by(&block)
1988
+ end
1989
+
1918
1990
  def take(count)
1919
1991
  %x{
1920
1992
  if (count < 0) {
@@ -1932,9 +2004,7 @@ class Array < `Array`
1932
2004
  for (var i = 0, length = self.length, item, value; i < length; i++) {
1933
2005
  item = self[i];
1934
2006
 
1935
- if ((value = block(item)) === $breaker) {
1936
- return $breaker.$v;
1937
- }
2007
+ value = block(item);
1938
2008
 
1939
2009
  if (value === false || value === nil) {
1940
2010
  return result;
@@ -2026,7 +2096,7 @@ class Array < `Array`
2026
2096
  }
2027
2097
  }
2028
2098
 
2029
- return hash.$values();
2099
+ return toArraySubclass(#{`hash`.values}, #{self.class});
2030
2100
  }
2031
2101
  end
2032
2102
 
@@ -2149,4 +2219,12 @@ class Array < `Array`
2149
2219
  return result;
2150
2220
  }
2151
2221
  end
2222
+
2223
+ def self.inherited(klass)
2224
+ %x{
2225
+ klass.$$proto.$to_a = function() {
2226
+ return this.slice(0, this.length);
2227
+ }
2228
+ }
2229
+ end
2152
2230
  end