-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Normative: avoid triggering throw
in corner case in async generators
#2818
Conversation
I like the sound of option 3. Can you go into more detail about the effects of such a change? |
Edit: moved reply to above comment to #2819. |
That is the reason why I don't like the first option - if I can even see a fourth option: Don't await the result from an inner iterator in That said, of all these I do prefer option 3. (I mean, I'd be even happier if not even |
The story I'd tell, if we stick what that behavior, is that it's not looping part which is awaiting, but rather the
That option was discussed and rejected during the original design of async iterators - it's option 2 in these slides; see also discussion in the notes and the issue tracker. I'd definitely prefer to avoid changing the behavior |
Closing as we got consensus for the alternative #2819. We may need to revive this if that PR turns out not to be web compatible, though. |
Fixes #2813.
The idea is that if you are doing
yield* m
on a manual async iteratorm
(i.e., one which is not an async generator), it is possible for the inner iterator to yield{ next: promise, done: false }
. And if that promise rejects, it is treated as if someone had called.throw
on the outer generator (the one doingyield*
). That's inconsistent with the way the spec usually consumes iterators and is almost certainly a bug caused by the factoring ofAsyncGeneratorYield
. (Async generators await their result before yielding it, so it doesn't come up without a manually implemented iterator.)There's only really three consistent options, that I can see.
.throw
or.return
should be called on the inner iterator (as if calling.next
had thrown)yield*
as being a completely transparent delegation to the inner iterator). This option would also reduce the number of microtask ticks entailed by async generators doingyield*
in general. I've opened an alternative PR in Normative: avoid mostly-redundantawait
in asyncyield*
#2819 which implements this option.This PR takes the first option.
I don't really like the second option, because
for await
does not treat an async iterator yielding a promise as being a protocol violation - see this snippet.I actually kind of prefer the third option, but it has broader implications than this PR does, and so is more likely to break stuff. On the other hand, it also would improve the performance of async generators, which is nice.
As mentioned in the issue, this does not match any existing engine, but engines are inconsistent here, so the change in this PR is probably web compatible.