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.