Skip to content

Commit

Permalink
Make await x ** y fail to parse
Browse files Browse the repository at this point in the history
Implement grammar restrictions to prevent ambiguity.

Issue:
  #984

The previous attempt at achieving this did not cover all cases:
  848d14e
  • Loading branch information
robpalme authored and marijnh committed Apr 29, 2021
1 parent 3f52326 commit 399de2d
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 5 deletions.
14 changes: 9 additions & 5 deletions acorn/src/expression.js
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ pp.buildBinary = function(startPos, startLoc, left, right, op, logical) {

// Parse unary operators, both prefix and postfix.

pp.parseMaybeUnary = function(refDestructuringErrors, sawUnary) {
pp.parseMaybeUnary = function(refDestructuringErrors, sawUnary, incDec) {
let startPos = this.start, startLoc = this.startLoc, expr
if (this.isContextual("await") && (this.inAsync || (!this.inFunction && this.options.allowAwaitOutsideFunction))) {
expr = this.parseAwait()
Expand All @@ -231,7 +231,7 @@ pp.parseMaybeUnary = function(refDestructuringErrors, sawUnary) {
node.operator = this.value
node.prefix = true
this.next()
node.argument = this.parseMaybeUnary(null, true)
node.argument = this.parseMaybeUnary(null, true, update)
this.checkExpressionErrors(refDestructuringErrors, true)
if (update) this.checkLValSimple(node.argument)
else if (this.strict && node.operator === "delete" &&
Expand All @@ -255,10 +255,14 @@ pp.parseMaybeUnary = function(refDestructuringErrors, sawUnary) {
}
}

if (!sawUnary && this.eat(tt.starstar))
return this.buildBinary(startPos, startLoc, expr, this.parseMaybeUnary(null, false), "**", false)
else
if (!incDec && this.eat(tt.starstar)) {
if (sawUnary)
this.unexpected(this.lastTokStart)
else
return this.buildBinary(startPos, startLoc, expr, this.parseMaybeUnary(null, false), "**", false)
} else {
return expr
}
}

function isPrivateFieldAccess(node) {
Expand Down
12 changes: 12 additions & 0 deletions test/tests-asyncawait.js
Original file line number Diff line number Diff line change
Expand Up @@ -3526,4 +3526,16 @@ testFail("abc: async function a() {}", "Unexpected token (1:5)", {ecmaVersion: 8

testFail("(async() => { await 4 ** 2 })()", "Unexpected token (1:22)", {ecmaVersion: 8})

test("(async() => { await (4 ** 2) })()", {}, {ecmaVersion: 8})

testFail("async() => (await 1 ** 3)", "Unexpected token (1:20)", {ecmaVersion: 8})

test("async() => (await (1 ** 3))", {}, {ecmaVersion: 8})

testFail("async() => await 5 ** 6", "Unexpected token (1:19)", {ecmaVersion: 8})

test("async() => await (5 ** 6)", {}, {ecmaVersion: 8})

testFail("async() => await (5) ** 6", "Unexpected token (1:21)", {ecmaVersion: 8})

testFail("4 + async() => 2", "Unexpected token (1:12)", {ecmaVersion: 8, loose: false})
2 changes: 2 additions & 0 deletions test/tests-es7.js
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,8 @@ testFail("~3 ** 2;", "Unexpected token (1:3)", { ecmaVersion: 7 });
testFail("!1 ** 2;", "Unexpected token (1:3)", { ecmaVersion: 7 });
testFail("-2** 2;", "Unexpected token (1:2)", { ecmaVersion: 7 });
testFail("+2** 2;", "Unexpected token (1:2)", { ecmaVersion: 7 });
testFail("-(i--) ** 2", "Unexpected token (1:7)", {ecmaVersion: 7});
testFail("+(i--) ** 2", "Unexpected token (1:7)", {ecmaVersion: 7});

// make sure base operand check doesn't affect other operators
test("-a * 5", {
Expand Down

0 comments on commit 399de2d

Please sign in to comment.