Make collection iterators actually iterable

The ES6 spec calls for this so these iterators are usable in for-of loops, with spread operators, etc.
This commit is contained in:
Scott Kyle 2016-03-19 19:55:19 -07:00
parent b5ce02c0ce
commit 8c66bab8aa
2 changed files with 50 additions and 32 deletions

View File

@ -20,6 +20,19 @@
var arrayPrototype = Array.prototype;
// eslint-disable-next-line no-undef
var iteratorSymbol = typeof Symbol != 'undefined' && Symbol.iterator;
var iteratorPrototype = {};
if (iteratorSymbol) {
// These iterators should themselves be iterable.
Object.defineProperty(iteratorPrototype, iteratorSymbol, {
value: function() {
return this;
}
});
}
[
'join',
'slice',
@ -43,35 +56,36 @@ var arrayPrototype = Array.prototype;
var self = this;
var index = 0;
return {
next: function() {
if (!self || index >= self.length) {
self = null;
return {done: true, value: undefined};
}
return Object.create(iteratorPrototype, {
next: {
value: function() {
if (!self || index >= self.length) {
self = null;
return {done: true, value: undefined};
}
var value;
switch (methodName) {
case 'entries':
value = [index, self[index]];
break;
case 'keys':
value = index;
break;
default:
value = self[index];
}
var value;
switch (methodName) {
case 'entries':
value = [index, self[index]];
break;
case 'keys':
value = index;
break;
default:
value = self[index];
}
index++;
return {done: false, value: value};
index++;
return {done: false, value: value};
}
}
};
});
};
exports[methodName] = {value: method};
});
/* global Symbol */
if (typeof Symbol != 'undefined' && Symbol.iterator) {
exports[Symbol.iterator] = exports.values;
if (iteratorSymbol) {
exports[iteratorSymbol] = exports.values;
}

View File

@ -576,20 +576,24 @@ module.exports = BaseTest.extend({
TestCase.assertEqual(list.reduce(function(n, p) {return n + p.age}, 0), 33);
TestCase.assertEqual(list.reduceRight(function(n, p) {return n + p.age}, 0), 33);
[
'entries',
'keys',
'values',
typeof Symbol != 'undefined' && Symbol.iterator, // eslint-disable-line no-undef
].forEach(function(methodName) {
if (!methodName) {
return;
}
// eslint-disable-next-line no-undef
var iteratorSymbol = typeof Symbol != 'undefined' && Symbol.iterator;
var iteratorMethodNames = ['entries', 'keys', 'values'];
if (iteratorSymbol) {
iteratorMethodNames.push(iteratorSymbol);
}
iteratorMethodNames.forEach(function(methodName) {
var iterator = list[methodName]();
var count = 0;
var result;
if (iteratorSymbol) {
// This iterator should itself be iterable.
TestCase.assertEqual(iterator[iteratorSymbol](), iterator);
}
while ((result = iterator.next()) && !result.done) {
var value = result.value;