blob: 6d645e4a96f2567a093cd3fcf1181d0d466a3a42 [file] [log] [blame]
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);
}());