Skip to content

Commit

Permalink
Require .next method on delegate iterator (#630)
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolo-ribaudo authored Nov 14, 2022
1 parent 81a1429 commit 18dcd03
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 17 deletions.
35 changes: 18 additions & 17 deletions packages/runtime/runtime.js
Original file line number Diff line number Diff line change
Expand Up @@ -329,31 +329,32 @@ var runtime = (function (exports) {
// delegate iterator, or by modifying context.method and context.arg,
// setting context.delegate to null, and returning the ContinueSentinel.
function maybeInvokeDelegate(delegate, context) {
var method = delegate.iterator[context.method];
var methodName = context.method;
var method = delegate.iterator[methodName];
if (method === undefined) {
// A .throw or .return when the delegate iterator has no .throw
// method always terminates the yield* loop.
// method, or a missing .next mehtod, always terminate the
// yield* loop.
context.delegate = null;

if (context.method === "throw") {
// Note: ["return"] must be used for ES3 parsing compatibility.
if (delegate.iterator["return"]) {
// If the delegate iterator has a return method, give it a
// chance to clean up.
context.method = "return";
context.arg = undefined;
maybeInvokeDelegate(delegate, context);
// Note: ["return"] must be used for ES3 parsing compatibility.
if (methodName === "throw" && delegate.iterator["return"]) {
// If the delegate iterator has a return method, give it a
// chance to clean up.
context.method = "return";
context.arg = undefined;
maybeInvokeDelegate(delegate, context);

if (context.method === "throw") {
// If maybeInvokeDelegate(context) changed context.method from
// "return" to "throw", let that override the TypeError below.
return ContinueSentinel;
}
if (context.method === "throw") {
// If maybeInvokeDelegate(context) changed context.method from
// "return" to "throw", let that override the TypeError below.
return ContinueSentinel;
}

}
if (methodName !== "return") {
context.method = "throw";
context.arg = new TypeError(
"The iterator does not provide a 'throw' method");
"The iterator does not provide a '" + methodName + "' method");
}

return ContinueSentinel;
Expand Down
12 changes: 12 additions & 0 deletions test/tests.es6.js
Original file line number Diff line number Diff line change
Expand Up @@ -1503,6 +1503,18 @@ describe("delegated yield", function() {

check(gen(iterator), [], "1foo");
});

it("should throw if the delegated iterable's iterator doesn't have .next", function() {
var it = function* () {
yield* {
[Symbol.iterator]: x => [],
};
}();

assert.throws(() => {
it.next();
}, TypeError);
});
});

(fullCompatibility
Expand Down

0 comments on commit 18dcd03

Please sign in to comment.