regenerator
regenerator copied to clipboard
yield* should call iterator's .return() even if .throw() is null
Consider this code:
const iterable = {
[Symbol.iterator]: () => ({
next: () => ({ value: 1 }),
throw: undefined,
return: () => ({ done: !console.log(".return()") })
})
};
function* gf() {
yield* iterable;
}
const it = gf();
console.log(it.next());
console.log(it.throw());
It correctly logs
> Object {value: 1}
> .return()
> Uncaught TypeError: Cannot read property 'call' of undefined
If I change throw: undefined
to throw: null
it should behave the same, but regenerator doesn't call the .return()
method:
> Object {value: 1}
> Uncaught TypeError: Cannot read property 'call' of undefined
Specification:
14.4.14 Runtime Semantics: Evaluation
...
YieldExpression : yield * AssignmentExpression
...
6.b. Else if received.[[type]] is throw, then
i. Let throw be GetMethod(iterator, "throw").
ii. ReturnIfAbrupt(throw).
iii. If throw is not undefined, then
...
iv. Else,
1. NOTE: If iterator does not have a throw method, this throw is going to terminate the yield* loop. But first we need to give iterator a chance to clean up.
2. Let closeResult be IteratorClose(iterator, Completion{[[type]]: normal , [[value]]: empty, [[target]]:empty}).
7.3.9 GetMethod (O, P)
1. Assert: IsPropertyKey(P) is true.
2. Let func be GetV(O, P).
3. ReturnIfAbrupt(func).
4. If func is either undefined or null, return undefined.
If iterator.throw
is null
IteratorClose
must be called, because GetMethod
returns undefined