Bug 924040 - Update yield* to use @@iterator protocol. r=jwalden

This commit is contained in:
Andy Wingo 2013-10-17 12:36:04 +02:00
parent c7fe19aa1f
commit 5dc7836409
8 changed files with 103 additions and 9 deletions

View File

@ -5109,9 +5109,22 @@ EmitYieldStar(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *iter)
JS_ASSERT(bce->sc->isFunctionBox());
JS_ASSERT(bce->sc->asFunctionBox()->isStarGenerator());
if (!EmitTree(cx, bce, iter)) // ITER
if (!EmitTree(cx, bce, iter)) // ITERABLE
return false;
// Convert iterable to iterator.
if (Emit1(cx, bce, JSOP_DUP) < 0) // ITERABLE ITERABLE
return false;
if (!EmitAtomOp(cx, cx->names().std_iterator, JSOP_CALLPROP, bce)) // ITERABLE @@ITERATOR
return false;
if (Emit1(cx, bce, JSOP_SWAP) < 0) // @@ITERATOR ITERABLE
return false;
if (Emit1(cx, bce, JSOP_NOTEARG) < 0)
return false;
if (EmitCall(cx, bce, JSOP_CALL, 0) < 0) // ITER
return false;
CheckTypeSet(cx, bce, JSOP_CALL);
int depth = bce->stackDepth;
JS_ASSERT(depth >= 1);

View File

@ -10,16 +10,20 @@ function results(results) {
function next() {
return results[i++];
}
return { next: next }
var iter = { next: next }
var ret = {};
ret[std_iterator] = function () { return iter; }
return ret;
}
function* yield_results(expected) {
return yield* results(expected);
}
function collect_results(iter) {
function collect_results(iterable) {
var ret = [];
var result;
var iter = iterable[std_iterator]();
do {
result = iter.next();
ret.push(result);

View File

@ -8,6 +8,7 @@ function Iter() {
}
this.next = next;
this[std_iterator] = function () { return this; }
}
function* delegate(iter) { return yield* iter; }

View File

@ -0,0 +1,49 @@
// yield* calls @@iterator on the iterable to produce the iterator.
var log = '';
function IteratorWrapper(iterator) {
return {
next: function (val) {
log += 'n';
return iterator.next(val);
},
throw: function (exn) {
log += 't';
return iterator.throw(exn);
}
};
}
function IterableWrapper(iterable) {
var ret = {};
ret[std_iterator] = function () {
log += 'i';
return IteratorWrapper(iterable[std_iterator]());
}
return ret;
}
function* delegate(iter) { return yield* iter; }
var iter = delegate(IterableWrapper([1, 2, 3]));
assertIteratorResult(1, false, iter.next());
assertIteratorResult(2, false, iter.next());
assertIteratorResult(3, false, iter.next());
assertIteratorResult(undefined, true, iter.next());
assertEq(log, 'innnn');
iter = delegate([1, 2, 3]);
assertIteratorResult(1, false, iter.next());
assertIteratorResult(2, false, iter.next());
assertIteratorResult(3, false, iter.next());
assertIteratorResult(undefined, true, iter.next());
assertEq(log, 'innnn');
if (typeof reportCompare == "function")
reportCompare(true, true);

View File

@ -6,16 +6,20 @@ function results(results) {
function next() {
return results[i++];
}
return { next: next }
var iter = { next: next };
var ret = {};
ret[std_iterator] = function () { return iter; }
return ret;
}
function* yield_results(expected, n) {
return yield* n ? yield_results(expected, n - 1) : results(expected);
}
function collect_results(iter) {
function collect_results(iterable) {
var ret = [];
var result;
var iter = iterable[std_iterator]();
do {
result = iter.next();
ret.push(result);

View File

@ -15,13 +15,20 @@ function collect_results(iter) {
function Iter(val, count) {
function next() {
log += 'n';
return {
get done() { log += "d"; return count-- == 0; },
get value() { log += "v"; return val; }
}
}
function iterator() {
log += 'i';
return this;
}
this.next = next;
this[std_iterator] = iterator;
}
function* delegate(iter) { return yield* iter; }
@ -37,13 +44,13 @@ outer.next();
outer.next();
outer.next();
assertEq(log, "ddddddv");
assertEq(log, "indndndndndndv");
// Outer's dead, man. Outer's dead.
assertThrowsInstanceOf(outer.next.bind(outer), TypeError);
// No more checking the iterator.
assertEq(log, "ddddddv");
assertEq(log, "indndndndndndv");
if (typeof reportCompare == "function")
reportCompare(true, true);

View File

@ -2,10 +2,15 @@
function results(results) {
var i = 0;
function iterator() {
return this;
}
function next() {
return results[i++];
}
return { next: next }
var ret = { next: next }
ret[std_iterator] = iterator;
return ret;
}
function* yield_results(expected) {

View File

@ -3,9 +3,20 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
var std_iterator = (function() {
try {
for (var _ of new Proxy({}, { get: function(_, name) { throw name; } }))
break;
} catch (name) {
return name;
}
throw 'wat';
})();
function assertFalse(a) { assertEq(a, false) }
function assertTrue(a) { assertEq(a, true) }
function assertNotEq(found, not_expected) { assertFalse(found === expected) }
function assertIteratorResult(value, done, result) {
assertDeepEq(result, { value: value, done: done });
assertDeepEq(result.value, value);
assertEq(result.done, done);
}