Skip to content

Commit

Permalink
Further refine handling of await in class fields
Browse files Browse the repository at this point in the history
FIX: Properly allow await inside an async arrow function inside a class field
initializer.

Issue #1338
  • Loading branch information
marijnh committed Dec 29, 2024
1 parent b6a98df commit 9e365f7
Show file tree
Hide file tree
Showing 4 changed files with 15 additions and 9 deletions.
2 changes: 1 addition & 1 deletion acorn/src/expression.js
Original file line number Diff line number Diff line change
Expand Up @@ -1043,7 +1043,7 @@ pp.checkUnreserved = function({start, end, name}) {
this.raiseRecoverable(start, "Cannot use 'yield' as identifier inside a generator")
if (this.inAsync && name === "await")
this.raiseRecoverable(start, "Cannot use 'await' as identifier inside an async function")
if (this.currentThisScope().inClassFieldInit && name === "arguments")
if (this.currentScope().inClassFieldInit && name === "arguments")
this.raiseRecoverable(start, "Cannot use 'arguments' in class field initializer")
if (this.inClassStaticBlock && (name === "arguments" || name === "await"))
this.raise(start, `Cannot use ${name} in class static initialization block`)
Expand Down
11 changes: 5 additions & 6 deletions acorn/src/state.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,15 +99,14 @@ export class Parser {

get inFunction() { return (this.currentVarScope().flags & SCOPE_FUNCTION) > 0 }

get inGenerator() { return (this.currentVarScope().flags & SCOPE_GENERATOR) > 0 && !this.currentVarScope().inClassFieldInit }
get inGenerator() { return (this.currentVarScope().flags & SCOPE_GENERATOR) > 0 && !this.currentScope().inClassFieldInit }

get inAsync() { return (this.currentVarScope().flags & SCOPE_ASYNC) > 0 && !this.currentVarScope().inClassFieldInit }
get inAsync() { return (this.currentScope().flags & SCOPE_ASYNC) > 0 && !this.currentScope().inClassFieldInit }

get canAwait() {
if (this.currentThisScope().inClassFieldInit) return false
for (let i = this.scopeStack.length - 1; i >= 0; i--) {
let scope = this.scopeStack[i]
if (scope.flags & SCOPE_CLASS_STATIC_BLOCK) return false
if (scope.flags & SCOPE_CLASS_STATIC_BLOCK || scope.inClassFieldInit) return false
if (scope.flags & SCOPE_FUNCTION) return (scope.flags & SCOPE_ASYNC) > 0
}
return (this.inModule && this.options.ecmaVersion >= 13) || this.options.allowAwaitOutsideFunction
Expand All @@ -123,8 +122,8 @@ export class Parser {
get treatFunctionsAsVar() { return this.treatFunctionsAsVarInScope(this.currentScope()) }

get allowNewDotTarget() {
const {flags, inClassFieldInit} = this.currentThisScope()
return (flags & (SCOPE_FUNCTION | SCOPE_CLASS_STATIC_BLOCK)) > 0 || inClassFieldInit
const {flags} = this.currentThisScope()
return (flags & (SCOPE_FUNCTION | SCOPE_CLASS_STATIC_BLOCK)) > 0 || this.currentScope().inClassFieldInit
}

get inClassStaticBlock() {
Expand Down
2 changes: 1 addition & 1 deletion acorn/src/statement.js
Original file line number Diff line number Diff line change
Expand Up @@ -742,7 +742,7 @@ pp.parseClassField = function(field) {

if (this.eat(tt.eq)) {
// To raise SyntaxError if 'arguments' exists in the initializer.
const scope = this.currentThisScope()
const scope = this.currentScope()
const inClassFieldInit = scope.inClassFieldInit
scope.inClassFieldInit = true
field.value = this.parseMaybeAssign()
Expand Down
9 changes: 8 additions & 1 deletion test/tests-asyncawait.js
Original file line number Diff line number Diff line change
Expand Up @@ -3541,4 +3541,11 @@ testFail("4 + async() => 2", "Unexpected token (1:12)", {ecmaVersion: 8, loose:

testFail("async function𝐬 f() {}", "Unexpected token (1:17)", {ecmaVersion: 8})

testFail("async () => class { x = await 1 }", "Cannot use 'await' as identifier inside an async function (1:24)", {ecmaVersion: 2024})
testFail("async () => class { x = await 1 }", "Unexpected token (1:30)", {ecmaVersion: 2024})

test("async () => class { x = async () => await 1 }", {}, {ecmaVersion: 2024})

test("async () => class { x = await }", {}, {ecmaVersion: 2024})

testFail("async () => class { x = await }", "Cannot use keyword 'await' outside an async function (1:24)",
{ecmaVersion: 2024, sourceType: "module"})

0 comments on commit 9e365f7

Please sign in to comment.