diff --git a/packages/babel-parser/src/parse-error/standard-errors.ts b/packages/babel-parser/src/parse-error/standard-errors.ts index ed4636eaed42..8221a6a53d4f 100644 --- a/packages/babel-parser/src/parse-error/standard-errors.ts +++ b/packages/babel-parser/src/parse-error/standard-errors.ts @@ -33,6 +33,8 @@ export default { "Can not use 'await' as identifier inside a static block.", AwaitExpressionFormalParameter: "'await' is not allowed in async function parameters.", + AwaitInUsingBinding: + "'await' is not allowed to be used as a name in 'using' declarations.", AwaitNotInAsyncContext: "'await' is only allowed within async functions and at the top levels of modules.", AwaitNotInAsyncFunction: "'await' is only allowed within async functions.", diff --git a/packages/babel-parser/src/parser/statement.ts b/packages/babel-parser/src/parser/statement.ts index 0a6d0bc4bc3c..d70623b0a70b 100644 --- a/packages/babel-parser/src/parser/statement.ts +++ b/packages/babel-parser/src/parser/statement.ts @@ -471,7 +471,7 @@ export default abstract class StatementParser extends ExpressionParser { return this.parseTryStatement(node as Undone); case tt._using: - // using [no LineTerminator here] BindingList[+Using] + // using [no LineTerminator here][lookahead != `await`] BindingList[+Using] if ( this.hasFollowingLineBreak() || this.state.containsEsc || @@ -1507,6 +1507,11 @@ export default abstract class StatementParser extends ExpressionParser { decl: Undone, kind: "var" | "let" | "const" | "using", ): void { + // Unlike "let" which must be handled in checkLVal, it suffices to check + // await here because `using` must not precede binding patterns. + if (kind === "using" && !this.inModule && this.match(tt._await)) { + this.raise(Errors.AwaitInUsingBinding, { at: this.state.startLoc }); + } const id = this.parseBindingAtom(); this.checkLVal(id, { in: { type: "VariableDeclarator" }, diff --git a/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-using-binding-await/input.js b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-using-binding-await/input.js new file mode 100644 index 000000000000..46ba5c6677af --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-using-binding-await/input.js @@ -0,0 +1,6 @@ +{ + using await = h(); +} +{ + using \u0061wait = h(); +} diff --git a/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-using-binding-await/options.json b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-using-binding-await/options.json new file mode 100644 index 000000000000..b412ffe6712f --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-using-binding-await/options.json @@ -0,0 +1,3 @@ +{ + "sourceType": "script" +} diff --git a/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-using-binding-await/output.json b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-using-binding-await/output.json new file mode 100644 index 000000000000..9e2e5614057c --- /dev/null +++ b/packages/babel-parser/test/fixtures/experimental/explicit-resource-management/invalid-using-binding-await/output.json @@ -0,0 +1,83 @@ +{ + "type": "File", + "start":0,"end":54,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":6,"column":1,"index":54}}, + "errors": [ + "SyntaxError: 'await' is not allowed to be used as a name in 'using' declarations. (2:8)", + "SyntaxError: 'await' is not allowed to be used as a name in 'using' declarations. (5:8)" + ], + "program": { + "type": "Program", + "start":0,"end":54,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":6,"column":1,"index":54}}, + "sourceType": "script", + "interpreter": null, + "body": [ + { + "type": "BlockStatement", + "start":0,"end":24,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":3,"column":1,"index":24}}, + "body": [ + { + "type": "VariableDeclaration", + "start":4,"end":22,"loc":{"start":{"line":2,"column":2,"index":4},"end":{"line":2,"column":20,"index":22}}, + "declarations": [ + { + "type": "VariableDeclarator", + "start":10,"end":21,"loc":{"start":{"line":2,"column":8,"index":10},"end":{"line":2,"column":19,"index":21}}, + "id": { + "type": "Identifier", + "start":10,"end":15,"loc":{"start":{"line":2,"column":8,"index":10},"end":{"line":2,"column":13,"index":15},"identifierName":"await"}, + "name": "await" + }, + "init": { + "type": "CallExpression", + "start":18,"end":21,"loc":{"start":{"line":2,"column":16,"index":18},"end":{"line":2,"column":19,"index":21}}, + "callee": { + "type": "Identifier", + "start":18,"end":19,"loc":{"start":{"line":2,"column":16,"index":18},"end":{"line":2,"column":17,"index":19},"identifierName":"h"}, + "name": "h" + }, + "arguments": [] + } + } + ], + "kind": "using" + } + ], + "directives": [] + }, + { + "type": "BlockStatement", + "start":25,"end":54,"loc":{"start":{"line":4,"column":0,"index":25},"end":{"line":6,"column":1,"index":54}}, + "body": [ + { + "type": "VariableDeclaration", + "start":29,"end":52,"loc":{"start":{"line":5,"column":2,"index":29},"end":{"line":5,"column":25,"index":52}}, + "declarations": [ + { + "type": "VariableDeclarator", + "start":35,"end":51,"loc":{"start":{"line":5,"column":8,"index":35},"end":{"line":5,"column":24,"index":51}}, + "id": { + "type": "Identifier", + "start":35,"end":45,"loc":{"start":{"line":5,"column":8,"index":35},"end":{"line":5,"column":18,"index":45},"identifierName":"await"}, + "name": "await" + }, + "init": { + "type": "CallExpression", + "start":48,"end":51,"loc":{"start":{"line":5,"column":21,"index":48},"end":{"line":5,"column":24,"index":51}}, + "callee": { + "type": "Identifier", + "start":48,"end":49,"loc":{"start":{"line":5,"column":21,"index":48},"end":{"line":5,"column":22,"index":49},"identifierName":"h"}, + "name": "h" + }, + "arguments": [] + } + } + ], + "kind": "using" + } + ], + "directives": [] + } + ], + "directives": [] + } +}