]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - tests/stress/array-from-with-iterator.js
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / tests / stress / array-from-with-iterator.js
diff --git a/tests/stress/array-from-with-iterator.js b/tests/stress/array-from-with-iterator.js
new file mode 100644 (file)
index 0000000..6d645e4
--- /dev/null
@@ -0,0 +1,129 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+function shouldThrow(func, message) {
+    var error = null;
+    try {
+        func();
+    } catch (e) {
+        error = e;
+    }
+    if (!error)
+        throw new Error("not thrown.");
+    if (String(error) !== message)
+        throw new Error("bad error: " + String(error));
+}
+
+var originalArray = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
+
+var array = Array.from(originalArray.values());
+shouldBe(array.length, originalArray.length);
+for (var i = 0; i < array.length; ++i) {
+    shouldBe(array[i], originalArray[i]);
+}
+
+function createIterator(callback) {
+    var array = [0,1,2,3,4,5];
+    var iterator = array[Symbol.iterator]();
+    iterator.return = function () {
+        iterator.returned = true;
+        if (callback)
+            return callback(this);
+        return { done: true, value: undefined };
+    };
+    iterator.returned = false;
+    return iterator;
+}
+
+var iterator = createIterator();
+var result = Array.from(iterator);
+shouldBe(result.length, 6);
+for (var i = 0; i < 6; ++i) {
+    shouldBe(result[i], i);
+}
+shouldBe(iterator.returned, false);
+
+// mapFn raises an error.
+var iterator = createIterator();
+shouldThrow(function () {
+    var result = Array.from(iterator, function () {
+        throw new Error('map func');
+    });
+}, "Error: map func");
+shouldBe(iterator.returned, true);
+
+// mapFn raises an error and iterator.return also raises an error.
+var iterator = createIterator(function () {
+    throw new Error('iterator.return');
+});
+
+// An error raised in iterator.return is discarded.
+shouldThrow(function () {
+    var result = Array.from(iterator, function () {
+        throw new Error('map func');
+    });
+}, "Error: map func");
+shouldBe(iterator.returned, true);
+
+// iterable[Symbol.iterator] is not a function.
+shouldThrow(function () {
+    var iterator = [].values();
+    iterator[Symbol.iterator] = {};
+    Array.from(iterator);
+}, "TypeError: Array.from requires that the property of the first argument, items[Symbol.iterator], when exists, be a function");
+
+// iterable[Symbol.iterator] raises an error.
+shouldThrow(function () {
+    var iterable = [];
+    iterable[Symbol.iterator] = function () {
+        throw new Error("iterator");
+    };
+    Array.from(iterable);
+}, "Error: iterator");
+
+// iterable[Symbol.iterator] lookup is only once.
+(function () {
+    var iterable = [0, 1, 2, 3, 4, 5];
+    var count = 0;
+    var iteratorCallCount = 0;
+    Object.defineProperty(iterable, Symbol.iterator, {
+        get() {
+            ++count;
+            return function () {
+                ++iteratorCallCount;
+                return this.values();
+            };
+        }
+    });
+    var generated = Array.from(iterable);
+    shouldBe(generated.length, iterable.length);
+    for (var i = 0; i < iterable.length; ++i) {
+        shouldBe(generated[i], iterable[i]);
+    }
+    shouldBe(count, 1);
+    shouldBe(iteratorCallCount, 1);
+}());
+
+// The Symbol.iterator method of the iterator generated by iterable[Symbol.iterator] is not looked up.
+(function () {
+    var iterable = [0, 1, 2, 3, 4, 5];
+    var count = 0;
+    iterable[Symbol.iterator] = function () {
+        ++count;
+        var iterator = this.values();
+        Object.defineProperty(iterator, Symbol.iterator, {
+            get() {
+                throw new Error('iterator[@@iterator] is touched');
+            }
+        });
+        return iterator;
+    };
+    var generated = Array.from(iterable);
+    shouldBe(generated.length, iterable.length);
+    for (var i = 0; i < iterable.length; ++i) {
+        shouldBe(generated[i], iterable[i]);
+    }
+    shouldBe(count, 1);
+}());