Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow await when it is not in AsyncArrowHead #11148

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 12 additions & 1 deletion packages/babel-parser/src/parser/expression.js
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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 => {};
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
Expand Down
5 changes: 5 additions & 0 deletions packages/babel-parser/src/tokenizer/state.js
Expand Up @@ -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;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not clear to me what the difference between these two flags should be. Isn't the arrow head its parameters?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The maybeInAsyncArrowHead lives across function declarations.

async (foo = function (await) {}) => {}

When parsing await, maybeInAsyncArrowHead is true but maybeInArrowParameters is false.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should add a comment in the code explaining it 👍

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nicolo-ribaudo Done. Let me know if we can make it better.

inPipeline: boolean = false;
inType: boolean = false;
noAnonFunctionType: boolean = false;
Expand Down
@@ -0,0 +1 @@
(await) => {}
@@ -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": []
}
}