Reviewers: adamk,

Description:
Allow TypedArrays to be initialized with iterables

In ES6, the TypedArray constructor can be called either with an
array-like object or an iterable. The code previously handled
only array-like objects. This patch switches to supporting
iterables while throwing in an optimization to make Arrays
get allocated the old way, without an extra copy.

BUG=v8:4090
LOG=Y
R=adamk

Please review this at https://codereview.chromium.org/1181903003/

Base URL: https://chromium.googlesource.com/v8/v8.git@master

Affected files (+48, -1 lines):
  M src/typedarray.js
  M test/mjsunit/harmony/typedarrays.js


Index: src/typedarray.js
diff --git a/src/typedarray.js b/src/typedarray.js
index 65659147ee7777cf1e8bc69196d4fc09a4beee89..2f9d052fce771131e66f96853c03b7f9307cc1b2 100644
--- a/src/typedarray.js
+++ b/src/typedarray.js
@@ -130,6 +130,14 @@ function NAMEConstructByArrayLike(obj, arrayLike) {
   }
 }

+function NAMEConstructByIterable(obj, iterable) {
+  var list = new InternalArray();
+  for (var element of iterable) {
+    list.push(element);
+  }
+  return NAMEConstructByArrayLike(obj, list);
+}
+
 function NAMEConstructor(arg1, arg2, arg3) {
   if (%_IsConstructCall()) {
     if (IS_ARRAYBUFFER(arg1) || IS_SHAREDARRAYBUFFER(arg1)) {
@@ -138,7 +146,14 @@ function NAMEConstructor(arg1, arg2, arg3) {
                IS_BOOLEAN(arg1) || IS_UNDEFINED(arg1)) {
       NAMEConstructByLength(this, arg1);
     } else {
-      NAMEConstructByArrayLike(this, arg1);
+      var iteratorFn = arg1[Symbol.iterator];
+      if (IS_UNDEFINED(iteratorFn) || iteratorFn === $arrayValues) {
+        NAMEConstructByArrayLike(this, arg1);
+      } else {
+        // TODO(littledan): The code here is lazy and looks up @@iterator
+ // twice. Currently, that's fine, but it'll be observable with proxies.
+        NAMEConstructByIterable(this, arg1);
+      }
     }
   } else {
     throw MakeTypeError(kConstructorNotFunction, "NAME")
Index: test/mjsunit/harmony/typedarrays.js
diff --git a/test/mjsunit/harmony/typedarrays.js b/test/mjsunit/harmony/typedarrays.js index 70bd17e3382db1cdb115d5aae6e48cf9141bc82a..57057a844fc5933189ca7af42fd1b4df9de156e3 100644
--- a/test/mjsunit/harmony/typedarrays.js
+++ b/test/mjsunit/harmony/typedarrays.js
@@ -276,6 +276,38 @@ function TestTypedArray(constr, elementSize, typicalElement) {
   assertFalse(!!desc.writable);
   assertFalse(!!desc.set);
   assertEquals("function", typeof desc.get);
+
+  // Test that the constructor can be called with an iterable
+  function* gen() { for (var i = 0; i < 10; i++) yield i; }
+  var genArr = new constr(gen());
+  assertEquals(10, genArr.length);
+  assertEquals(0, genArr[0]);
+  assertEquals(9, genArr[9]);
+  // Arrays can be converted to TypedArrays
+  genArr = new constr([1, 2, 3]);
+  assertEquals(3, genArr.length);
+  assertEquals(1, genArr[0]);
+  assertEquals(3, genArr[2]);
+  // Redefining Array.prototype[Symbol.iterator] still works
+  var arrayIterator = Array.prototype[Symbol.iterator];
+  Array.prototype[Symbol.iterator] = gen;
+  genArr = new constr([1, 2, 3]);
+  assertEquals(10, genArr.length);
+  assertEquals(0, genArr[0]);
+  assertEquals(9, genArr[9]);
+  Array.prototype[Symbol.iterator] = arrayIterator;
+  // Other array-like things can be made into a TypedArray
+  var myObject = { 0: 5, 1: 6, length: 2 };
+  genArr = new constr(myObject);
+  assertEquals(2, genArr.length);
+  assertEquals(5, genArr[0]);
+  assertEquals(6, genArr[1]);
+  // Iterator takes precedence over array-like
+  myObject[Symbol.iterator] = gen;
+  genArr = new constr(myObject);
+  assertEquals(10, genArr.length);
+  assertEquals(0, genArr[0]);
+  assertEquals(9, genArr[9]);
 }

 TestTypedArray(Uint8Array, 1, 0xFF);


--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to