While composing an async generator function, I noticed that the following construct results in a SyntaxError:
async function * foo() {
  await yield bar; // Can not use 'yield' as identifier inside a generator
}
Even though reversing the order of the contextual keywords is perfectly acceptable:
async function * foo() {
  yield await bar; // OK
}
After reading the error carefully, I was able to correct the syntax by wrapping the UnaryExpression within the AwaitExpression in parentheses to avoid parsing the token yield as an identifier instead of a contextual keyword:
async function * foo() {
  await (yield bar); // OK
}
But this begs the question, what specific static semantics in ECMAScript 2018 are involved that cause yield to be parsed as an identifier in this context, while await does not require special treatment?
 
                        
It's a matter of precedence of the
awaitoperator, which forms aUnaryExpression(and has one as its operand), unlike theyieldoperator which forms anAssignmentExpression(and has one as its optional operand). AnAssignmentExpressiondoes not form aUnaryExpression, which means that you simply are not allowed to nest them like that.When the
awaitexpression is parsed, the next token fed to the parse is used to form aUnaryExpression, and the only choice foryieldto do that is as anIdentifierReference(totally ignoring thebarthat follows after it). Of course in a generator parsing context that is not allowed, leading to the confusing error message.Notice that both forms of nesting (
await (yield …)andyield (await …)) are totally unnecessary anyway, as theyieldkeyword in an asynchronous generator function already does await both the yielded value and the resumption value internally, so you should just omit theawaitkeyword and use onlyyield.