Parse async do expressions (#13043)

* parse async do expressions

* add test cases

* update test fixtures

* chore: add syntax-async-do-expressions

* generater support

* fix: do not transform async do expressions

* chore: add asyncDoExpressions to missing plugin helpers

* update ast types

* add more test cases

* throw when asyncDoExpressions is enabled but not doExpressions

* avoid add parentheses for async do expressions

* address review comments

* chore: update parser typings
This commit is contained in:
Huáng Jùnliàng
2021-04-07 12:24:33 -04:00
committed by Nicolò Ribaudo
parent f30c99aa24
commit 28d7442aae
76 changed files with 897 additions and 23 deletions

View File

@@ -1033,6 +1033,8 @@ export default class ExpressionParser extends LValParser {
);
} else if (this.match(tt.name)) {
return this.parseAsyncArrowUnaryFunction(id);
} else if (this.match(tt._do)) {
return this.parseDo(true);
}
}
@@ -1049,7 +1051,7 @@ export default class ExpressionParser extends LValParser {
}
case tt._do: {
return this.parseDo();
return this.parseDo(false);
}
case tt.regexp: {
@@ -1231,13 +1233,27 @@ export default class ExpressionParser extends LValParser {
}
// https://github.com/tc39/proposal-do-expressions
parseDo(): N.DoExpression {
// https://github.com/tc39/proposal-async-do-expressions
parseDo(isAsync: boolean): N.DoExpression {
this.expectPlugin("doExpressions");
if (isAsync) {
this.expectPlugin("asyncDoExpressions");
}
const node = this.startNode();
node.async = isAsync;
this.next(); // eat `do`
const oldLabels = this.state.labels;
this.state.labels = [];
node.body = this.parseBlock();
if (isAsync) {
// AsyncDoExpression :
// async [no LineTerminator here] do Block[~Yield, +Await, ~Return]
this.prodParam.enter(PARAM_AWAIT);
node.body = this.parseBlock();
this.prodParam.exit();
} else {
node.body = this.parseBlock();
}
this.state.labels = oldLabels;
return this.finishNode(node, "DoExpression");
}

View File

@@ -117,6 +117,18 @@ export function validatePlugins(plugins: PluginList) {
RECORD_AND_TUPLE_SYNTAX_TYPES.map(p => `'${p}'`).join(", "),
);
}
if (
hasPlugin(plugins, "asyncDoExpressions") &&
!hasPlugin(plugins, "doExpressions")
) {
const error = new Error(
"'asyncDoExpressions' requires 'doExpressions', please add 'doExpressions' to parser plugins.",
);
// $FlowIgnore
error.missingPlugins = "doExpressions"; // so @babel/core can provide better error message
throw error;
}
}
// These plugins are defined using a mixin which extends the parser class.

View File

@@ -402,6 +402,7 @@ export type ArrayExpression = NodeBase & {
export type DoExpression = NodeBase & {
type: "DoExpression",
body: ?BlockStatement,
async: boolean,
};
export type TupleExpression = NodeBase & {