As reported on es-discuss, in async generators, await yield and async yield x both generate early errors. However, this doesn't align with yield and is partially inconsistent with itself, since every single one of these are legal in async generator contexts:
await (yield) and await (yield x)yield await xawait await xyield yield and yield yield xShouldn't await yield and await yield x be legal, respectively equivalent to those in the first bullet? I see no reason why await shouldn't be treated just as a simple keyword unary operator. (To me, this just sounds like a spec bug.)
@isiahmeadows
since every single one of these are legal in async generator contexts:
await await xyield yield and yield yield x
Can you provide working examples of the last two list items, particularly await await x?
(async() => {
console.log(await await fetch('').blob())
})()
throws a TypeError
(async() => {
console.log(await (await fetch('')).blob())
})()
does not.
this is because a YieldExpression is a production of an AssignmentExpression, not a UnaryExpression.
I'm not entirely sure what the ramifications of moving YieldExpression to UnaryExpression would be, but seeing as this behaviour currently exists I'm assuming it was done for a specific reason.
@guest271314
(async() => {
let res = await await Promise.resolve(42);
console.log(res);
})()
```js
function *gen() {
let res = yield yield;
}
```js
function *gen() {
let res = yield yield 42;
}
@jfet97 Is [42, undefined] the expected result of the last block of code?
@jfet97 Is
[42, undefined]the expected result of the last block of code?
Not exactly, please see here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators#Advanced_generators
@jfet97 What detail describes the result of [...gen()] for the last block of code at the link? If a Promise is being passed to the async iterator would not the pattern be
let obj = {
async*[Symbol.asyncIterator]() {
const res = yield await <value>;
if (res && typeof res === <some type>)
// do stuff with res
}
}
https://github.com/guest271314/GraphInterest/blob/master/GraphInterest.js#L42, https://github.com/guest271314/GraphInterest/blob/master/GraphInterest.js#L43.
What is the expected result of const res = await yield;?
@guest271314 @jfet97 just to clarify, this issue is about syntax, not runtime behaviour.
This all relates to the different precedences of the yield operator (low) and of await (high). In terms of the grammar, the operand of high precedence unary operator cannot start with a low precedence operator.
see https://esdiscuss.org/topic/precedence-of-yield-operator
@guest271314 @jfet97 just to clarify, this issue is about syntax, not runtime behaviour.
I know, I opened the question on es-discuss ;)
As usual with precedence, the (perhaps unsatisfactory) answer is to learn the rules and use parenthesis when necessary.
As usual with precedence, the (perhaps unsatisfactory) answer is to learn the rules and use parenthesis when necessary.
In my opinion you are absolutely right! I never dwelt on the reasons why cases like:
function* gen() {
3 + yield 42;
}
are forbidden by the grammar.
Thanks to @allenwb for your illuminating answer.
Also, neither await (yield x) nor yield (await x) are of much use in asynchronous generator functions anyway. yield already awaits all promises passed to it as an operand or becoming a result (next() argument), so no await operator is necessary. (TBH I was a bit surprised by this behaviour at first, it would have allowed some interesting ways of concurrency).
Changing precedence would break many programs and have very few benefit.
@allenwb So would the proper fix here be making await a low-precedence operator, at the same precedence as yield?
Edit: Someone in that thread did mention a hypothetical await with the same precedence as yield.
We couldn't change the precedence of await without breaking many existing programs. I don't think there's really anything to be fixed here.
@isiahmeadows The proper fix for what issue and use case?
@allenwb So would the proper fix here be making await a low-precedence operator, at the same precedence as yield?
Absolutely not. The current behavior is not a bug. This was an intentional design decision made by TC39 consensus after consideration of the the different use cases for await and yield.
And even if it had been unintentional, changing it now would be a massive breaking change.
It's time to close this issue as "works as intended"
Most helpful comment
Absolutely not. The current behavior is not a bug. This was an intentional design decision made by TC39 consensus after consideration of the the different use cases for
awaitandyield.And even if it had been unintentional, changing it now would be a massive breaking change.
It's time to close this issue as "works as intended"