await should be allowed when it is not in AsyncArrowHead

Bug Report

  • I would like to work on a fix!

Current Behavior
A clear and concise description of the behavior.
The following snippet will throw SyntaxError: Await cannot be used as name inside an async function (1:1)

Input Code

  • REPL or Repo link if applicable: REPL
(await) => {}

Expected behavior/code
It should not throw because it is not in async arrow parameters, which means await is a plain identifier and should be allowed in ArrowParameters because it does not have [Await] production parameter.
https://tc39.es/ecma262/#sec-arrow-function-definitions

Babel Configuration
REPL, no plugins are enabled

Environment

REPL

Possible Solution

Should revisit how awaitPos is tracked in the parser. You can pay attention to

this.state.awaitPos === 1 &&
(this.state.maybeInArrowParameters || this.isAwaitAllowed())
) {
this.state.awaitPos = this.state.start;

where awaitPos is updated when it may be in arrow parameters. It was used to track awaitPos on cases like

async ( x = (await) => {}) => {}

however it becomes overkill when it is not in async arrow parameters. Consider add a new parser state maybeInAsyncArrowHead when parsing ambiguous async arrow

https://github.com/babel/babel/blob/master/packages/babel-parser/src/parser/expression.js#L649

It should be similar to maybeAsyncArrow but it should have longer lifecycle — maybeInAsyncArrowHead should be true during the whole async arrow parameters. i.e.

// top level
async ( // maybeInAsyncArrowHead : true
  x = ( // maybeInAsyncArrowHead : true
    await // register the `awaitPos`
  ) => async ( // oldMaybeInAsyncArrowHead should be saved, new maybeInAsyncArrowHead should be true
    y
  ) => {}
); // we does not see an arrow, so the parsed ambiguous async arrow is indeed a CallExpression, reset `awaitPos`.

When we are sure we are not parsing an async arrow, i.e. async(foo), we should reset awaitPos if state.maybeInAsyncArrowHead is false.

Then we can replace maybeInArrowParameters by maybeInAsyncArrowHead it should not record awaitPos for (await) => {}.

1 possible answer(s) on “await should be allowed when it is not in AsyncArrowHead

  1. An update on this issue: I took my time to debug the parse function on the input (await) => {} and was able to get a feel for the parser flow. There’s a lot going on in it but I have a basic idea of the process. I have started working on my PR and will submit a WIP PR in the next few days.