From cc7cc429e928869332efd68dd870cf4c86664918 Mon Sep 17 00:00:00 2001 From: Arun Kumar Mohan Date: Sun, 16 Feb 2020 00:52:16 -0500 Subject: [PATCH] Allow await when it is not in AsyncArrowHead --- .../babel-parser/src/parser/expression.js | 13 ++- packages/babel-parser/src/tokenizer/state.js | 5 + .../input.js | 1 + .../output.json | 104 ++++++++++++++++++ 4 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 packages/babel-parser/test/fixtures/es2017/async-functions/await-as-argument-identifier-in-non-async-functions/input.js create mode 100644 packages/babel-parser/test/fixtures/es2017/async-functions/await-as-argument-identifier-in-non-async-functions/output.json diff --git a/packages/babel-parser/src/parser/expression.js b/packages/babel-parser/src/parser/expression.js index 91f49064c372..18cd92163698 100644 --- a/packages/babel-parser/src/parser/expression.js +++ b/packages/babel-parser/src/parser/expression.js @@ -560,10 +560,15 @@ export default class ExpressionParser extends LValParser { stop: false, }; do { + const oldMaybeInAsyncArrowHead = this.state.maybeInAsyncArrowHead; + if (state.maybeAsyncArrow) { + this.state.maybeInAsyncArrowHead = true; + } base = this.parseSubscript(base, startPos, startLoc, noCalls, state); // After parsing a subscript, this isn't "async" for sure. state.maybeAsyncArrow = false; + this.state.maybeInAsyncArrowHead = oldMaybeInAsyncArrowHead; } while (!state.stop); return base; } @@ -953,15 +958,18 @@ export default class ExpressionParser extends LValParser { !this.canInsertSemicolon() ) { const oldMaybeInArrowParameters = this.state.maybeInArrowParameters; + const oldMaybeInAsyncArrowHead = this.state.maybeInAsyncArrowHead; const oldYieldPos = this.state.yieldPos; const oldAwaitPos = this.state.awaitPos; this.state.maybeInArrowParameters = true; + this.state.maybeInAsyncArrowHead = true; this.state.yieldPos = -1; this.state.awaitPos = -1; const params = [this.parseIdentifier()]; this.expect(tt.arrow); this.checkYieldAwaitInDefaultParams(); this.state.maybeInArrowParameters = oldMaybeInArrowParameters; + this.state.maybeInAsyncArrowHead = oldMaybeInAsyncArrowHead; this.state.yieldPos = oldYieldPos; this.state.awaitPos = oldAwaitPos; // let foo = async bar => {}; @@ -1296,6 +1304,9 @@ export default class ExpressionParser extends LValParser { this.shouldParseArrow() && (arrowNode = this.parseArrow(arrowNode)) ) { + if (!this.isAwaitAllowed() && !this.state.maybeInAsyncArrowHead) { + this.state.awaitPos = oldAwaitPos; + } this.checkYieldAwaitInDefaultParams(); this.state.yieldPos = oldYieldPos; this.state.awaitPos = oldAwaitPos; @@ -2128,7 +2139,7 @@ export default class ExpressionParser extends LValParser { } if ( this.state.awaitPos === -1 && - (this.state.maybeInArrowParameters || this.isAwaitAllowed()) + (this.state.maybeInAsyncArrowHead || this.isAwaitAllowed()) ) { this.state.awaitPos = this.state.start; } diff --git a/packages/babel-parser/src/tokenizer/state.js b/packages/babel-parser/src/tokenizer/state.js index 37cb3a413cf3..c9e46a3c962d 100644 --- a/packages/babel-parser/src/tokenizer/state.js +++ b/packages/babel-parser/src/tokenizer/state.js @@ -59,6 +59,11 @@ export default class State { // Flags to track inParameters: boolean = false; maybeInArrowParameters: boolean = false; + // This flag is used to track async arrow head across function declarations. + // e.g. async (foo = function (await) {}) => {} + // When parsing `await` in this expression, `maybeInAsyncArrowHead` is true + // but `maybeInArrowParameters` is false + maybeInAsyncArrowHead: boolean = false; inPipeline: boolean = false; inType: boolean = false; noAnonFunctionType: boolean = false; diff --git a/packages/babel-parser/test/fixtures/es2017/async-functions/await-as-argument-identifier-in-non-async-functions/input.js b/packages/babel-parser/test/fixtures/es2017/async-functions/await-as-argument-identifier-in-non-async-functions/input.js new file mode 100644 index 000000000000..37af6577300e --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2017/async-functions/await-as-argument-identifier-in-non-async-functions/input.js @@ -0,0 +1 @@ +(await) => {} diff --git a/packages/babel-parser/test/fixtures/es2017/async-functions/await-as-argument-identifier-in-non-async-functions/output.json b/packages/babel-parser/test/fixtures/es2017/async-functions/await-as-argument-identifier-in-non-async-functions/output.json new file mode 100644 index 000000000000..ffa6e2942ae3 --- /dev/null +++ b/packages/babel-parser/test/fixtures/es2017/async-functions/await-as-argument-identifier-in-non-async-functions/output.json @@ -0,0 +1,104 @@ +{ + "type": "File", + "start": 0, + "end": 13, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 13 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 13, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 13 + } + }, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "ExpressionStatement", + "start": 0, + "end": 13, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 13 + } + }, + "expression": { + "type": "ArrowFunctionExpression", + "start": 0, + "end": 13, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 13 + } + }, + "id": null, + "generator": false, + "async": false, + "params": [ + { + "type": "Identifier", + "start": 1, + "end": 6, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 6 + }, + "identifierName": "await" + }, + "name": "await" + } + ], + "body": { + "type": "BlockStatement", + "start": 11, + "end": 13, + "loc": { + "start": { + "line": 1, + "column": 11 + }, + "end": { + "line": 1, + "column": 13 + } + }, + "body": [], + "directives": [] + } + } + } + ], + "directives": [] + } +} \ No newline at end of file