Implement %TypedArray%.reverse
authorDaniel Ehrenberg <dehrenberg@chromium.org>
Wed, 20 May 2015 00:38:59 +0000 (17:38 -0700)
committerAdam Klein <adamk@chromium.org>
Wed, 20 May 2015 00:38:49 +0000 (00:38 +0000)
This patch adds the reverse method to TypedArrays, together with a
test. The test also runs for normal Arrays, since I didn't see a
test for reversing dense arrays.

BUG=v8:3578
LOG=Y
R=arv@chromium.org

Review URL: https://codereview.chromium.org/1132723008

Patch from Daniel Ehrenberg <dehrenberg@chromium.org>.

Cr-Commit-Position: refs/heads/master@{#28493}

src/array.js
src/harmony-typedarray.js
test/mjsunit/harmony/typedarray-reverse.js [new file with mode: 0644]

index 93378cf..0d25f99 100644 (file)
@@ -12,6 +12,7 @@ var $arraySplice;
 var $arrayUnshift;
 var $innerArrayForEach;
 var $innerArrayEvery;
+var $innerArrayReverse;
 
 (function(global, shared, exports) {
 
@@ -564,18 +565,7 @@ function SparseReverse(array, len) {
 }
 
 
-function ArrayReverse() {
-  CHECK_OBJECT_COERCIBLE(this, "Array.prototype.reverse");
-
-  var array = TO_OBJECT_INLINE(this);
-  var len = TO_UINT32(array.length);
-
-  if (UseSparseVariant(array, len, IS_ARRAY(array), len)) {
-    %NormalizeElements(array);
-    SparseReverse(array, len);
-    return array;
-  }
-
+function InnerArrayReverse(array, len) {
   var j = len - 1;
   for (var i = 0; i < j; i++, j--) {
     var current_i = array[i];
@@ -600,6 +590,22 @@ function ArrayReverse() {
 }
 
 
+function ArrayReverse() {
+  CHECK_OBJECT_COERCIBLE(this, "Array.prototype.reverse");
+
+  var array = TO_OBJECT_INLINE(this);
+  var len = TO_UINT32(array.length);
+
+  if (UseSparseVariant(array, len, IS_ARRAY(array), len)) {
+    %NormalizeElements(array);
+    SparseReverse(array, len);
+    return array;
+  }
+
+  return InnerArrayReverse(array, len);
+}
+
+
 function ObservedArrayShift(len) {
   var first = this[0];
 
@@ -1609,5 +1615,6 @@ $arrayUnshift = ArrayUnshift;
 
 $innerArrayForEach = InnerArrayForEach;
 $innerArrayEvery = InnerArrayEvery;
+$innerArrayReverse = InnerArrayReverse;
 
 });
index 90679e0..59c9a79 100644 (file)
@@ -90,6 +90,15 @@ function TypedArrayFindIndex(predicate, thisArg) {
 }
 %FunctionSetLength(TypedArrayFindIndex, 1);
 
+// ES6 draft 05-18-15, section 22.2.3.21
+function TypedArrayReverse() {
+  if (!%IsTypedArray(this)) throw MakeTypeError(kNotTypedArray);
+
+  var length = %_TypedArrayGetLength(this);
+
+  return $innerArrayReverse(this, length);
+}
+
 
 // ES6 draft 08-24-14, section 22.2.2.2
 function TypedArrayOf() {
@@ -140,7 +149,8 @@ macro EXTEND_TYPED_ARRAY(NAME)
     "forEach", TypedArrayForEach,
     "find", TypedArrayFind,
     "findIndex", TypedArrayFindIndex,
-    "fill", TypedArrayFill
+    "fill", TypedArrayFill,
+    "reverse", TypedArrayReverse
   ]);
 endmacro
 
diff --git a/test/mjsunit/harmony/typedarray-reverse.js b/test/mjsunit/harmony/typedarray-reverse.js
new file mode 100644 (file)
index 0000000..98b7387
--- /dev/null
@@ -0,0 +1,56 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-arrays
+
+function ArrayMaker(x) {
+  return x;
+}
+ArrayMaker.prototype = Array.prototype;
+
+var arrayConstructors = [
+  Uint8Array,
+  Int8Array,
+  Uint16Array,
+  Int16Array,
+  Uint32Array,
+  Int32Array,
+  Uint8ClampedArray,
+  Float32Array,
+  Float64Array,
+  ArrayMaker  // Also test arrays
+];
+
+function assertArrayLikeEquals(value, expected, type) {
+  assertEquals(value.__proto__, type.prototype);
+  assertEquals(expected.length, value.length);
+  for (var i = 0; i < value.length; ++i) {
+    assertEquals(expected[i], value[i]);
+  }
+}
+
+for (var constructor of arrayConstructors) {
+  // Test reversing both even and odd length arrays
+  var a = new constructor([1, 2, 3]);
+  assertArrayLikeEquals(a.reverse(), [3, 2, 1], constructor);
+  assertArrayLikeEquals(a, [3, 2, 1], constructor);
+
+  a = new constructor([1, 2, 3, 4]);
+  assertArrayLikeEquals(a.reverse(), [4, 3, 2, 1], constructor);
+  assertArrayLikeEquals(a, [4, 3, 2, 1], constructor);
+
+  if (constructor != ArrayMaker) {
+    // Cannot be called on objects which are not TypedArrays
+    assertThrows(function () { a.reverse.call({ length: 0 }); }, TypeError);
+  } else {
+    // Array.reverse works on array-like objects
+    var x = { length: 2, 1: 5 };
+    a.reverse.call(x);
+    assertEquals(2, x.length);
+    assertFalse(Object.hasOwnProperty(x, '1'));
+    assertEquals(5, x[0]);
+  }
+
+  assertEquals(0, a.reverse.length);
+}