mirror of
https://github.com/aphrody-labs/oxc.git
synced 2026-10-14 22:29:17 +00:00
fix(parser): recover await using object binding patterns (#26721)
Recognize object binding patterns after `await using` so invalid declarations retain their AST and report “Using declarations may not have binding patterns.” For example, `for (await using {} of []) {}` now recovers instead of aborting with an expected-semicolon error. Updates the existing Babel, Test262, and TypeScript diagnostic snapshots.
Known limitation: transforming the recovered loop with resource-management lowering enabled (`target: es2015`) still panics because the transformer assumes an identifier binding. The parser diagnostic is emitted before the panic.
This commit is contained in:
1 parent
432f7606c8
commit
313040530c
4 files changed
+37
-29
No files matched your search
@@ -40,20 +40,15 @@ impl<'a, C: Config> ParserImpl<'a, C> {
|
||||
pub(crate) fn is_using_statement(&mut self) -> bool {
|
||||
// `await using` requires `using` immediately after `await` on the same line. Cheaply peek
|
||||
// for it first, so the common `await <expr>` statement avoids the heavier `lookahead`
|
||||
// (checkpoint + rewind) and only `await using` pays for the binding-identifier check.
|
||||
// (checkpoint + rewind) and only `await using` pays for the declaration check.
|
||||
let next = self.lexer.peek_token();
|
||||
next.kind() == Kind::Using
|
||||
&& !next.is_on_new_line()
|
||||
&& self.lookahead(Self::is_next_token_using_keyword_then_binding_identifier)
|
||||
}
|
||||
|
||||
fn is_next_token_using_keyword_then_binding_identifier(&mut self) -> bool {
|
||||
self.bump_any();
|
||||
if !self.cur_token().is_on_new_line() && self.eat(Kind::Using) {
|
||||
self.cur_kind().is_binding_identifier() && !self.cur_token().is_on_new_line()
|
||||
} else {
|
||||
false
|
||||
}
|
||||
&& self.lookahead(|p| {
|
||||
p.bump_any(); // bump `await`
|
||||
// Also recognize object patterns so invalid declarations can recover.
|
||||
p.is_using_declaration()
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn parse_using_statement(&mut self, stmt_ctx: StatementContext) -> Statement<'a> {
|
||||
|
||||
@@ -9136,14 +9136,13 @@ Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typesc
|
||||
╰────
|
||||
help: Add an initializer (e.g. ` = undefined`) here
|
||||
|
||||
× Expected a semicolon or an implicit semicolon after a statement, but found none
|
||||
╭─[babel/packages/babel-parser/test/fixtures/es2026/async-explicit-resource-management/invalid-using-object-pattern/input.js:2:14]
|
||||
× Using declarations may not have binding patterns.
|
||||
╭─[babel/packages/babel-parser/test/fixtures/es2026/async-explicit-resource-management/invalid-using-object-pattern/input.js:2:15]
|
||||
1 │ async function f() {
|
||||
2 │ await using { foo } = f();
|
||||
· ▲
|
||||
· ───────
|
||||
3 │ }
|
||||
╰────
|
||||
help: Try inserting a semicolon here
|
||||
|
||||
× Using declarations may not have binding patterns.
|
||||
╭─[babel/packages/babel-parser/test/fixtures/es2026/explicit-resource-management/disallow-destructuring/input.js:1:17]
|
||||
@@ -15732,11 +15731,28 @@ Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typesc
|
||||
╰────
|
||||
help: Try inserting a semicolon here
|
||||
|
||||
× Expected a semicolon or an implicit semicolon after a statement, but found none
|
||||
╭─[babel/packages/babel-parser/test/fixtures/typescript/variable-declarator/invalid-definite-pattern-assignment-await-using/input.ts:2:14]
|
||||
× Missing initializer in destructuring declaration
|
||||
╭─[babel/packages/babel-parser/test/fixtures/typescript/variable-declarator/invalid-definite-pattern-assignment-await-using/input.ts:2:15]
|
||||
1 │ {
|
||||
2 │ await using {}! = {};
|
||||
· ▲
|
||||
· ──
|
||||
3 │ }
|
||||
╰────
|
||||
help: Add an initializer (e.g. ` = undefined`) here
|
||||
|
||||
× Using declarations may not have binding patterns.
|
||||
╭─[babel/packages/babel-parser/test/fixtures/typescript/variable-declarator/invalid-definite-pattern-assignment-await-using/input.ts:2:15]
|
||||
1 │ {
|
||||
2 │ await using {}! = {};
|
||||
· ──
|
||||
3 │ }
|
||||
╰────
|
||||
|
||||
× Expected a semicolon or an implicit semicolon after a statement, but found none
|
||||
╭─[babel/packages/babel-parser/test/fixtures/typescript/variable-declarator/invalid-definite-pattern-assignment-await-using/input.ts:2:17]
|
||||
1 │ {
|
||||
2 │ await using {}! = {};
|
||||
· ▲
|
||||
3 │ }
|
||||
╰────
|
||||
help: Try inserting a semicolon here
|
||||
|
||||
@@ -27684,14 +27684,13 @@ Negative Passed: 4651/4651 (100.00%)
|
||||
18 │ }
|
||||
╰────
|
||||
|
||||
× Expected a semicolon or an implicit semicolon after a statement, but found none
|
||||
╭─[test262/test/language/statements/await-using/syntax/await-using-invalid-objectbindingpattern.js:17:14]
|
||||
× Using declarations may not have binding patterns.
|
||||
╭─[test262/test/language/statements/await-using/syntax/await-using-invalid-objectbindingpattern.js:17:15]
|
||||
16 │ async function f() {
|
||||
17 │ await using {} = null;
|
||||
· ▲
|
||||
· ──
|
||||
18 │ }
|
||||
╰────
|
||||
help: Try inserting a semicolon here
|
||||
|
||||
× 'await using' declaration cannot appear in the bare case statement.
|
||||
╭─[test262/test/language/statements/await-using/syntax/await-using-invalid-switchstatement-caseclause.js:22:7]
|
||||
|
||||
@@ -28964,14 +28964,13 @@ Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/types/wit
|
||||
4 │ c = null;
|
||||
╰────
|
||||
|
||||
× Expected a semicolon or an implicit semicolon after a statement, but found none
|
||||
╭─[typescript/tests/cases/conformance/statements/VariableStatements/usingDeclarations/awaitUsingDeclarations.6.ts:2:16]
|
||||
× Using declarations may not have binding patterns.
|
||||
╭─[typescript/tests/cases/conformance/statements/VariableStatements/usingDeclarations/awaitUsingDeclarations.6.ts:2:17]
|
||||
1 │ {
|
||||
2 │ await using {a} = null;
|
||||
· ▲
|
||||
· ───
|
||||
3 │ }
|
||||
╰────
|
||||
help: Try inserting a semicolon here
|
||||
|
||||
× Using declarations may not have binding patterns.
|
||||
╭─[typescript/tests/cases/conformance/statements/VariableStatements/usingDeclarations/awaitUsingDeclarations.7.ts:3:17]
|
||||
@@ -29008,12 +29007,11 @@ Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/types/wit
|
||||
╰────
|
||||
help: Did you mean to use a for...of statement?
|
||||
|
||||
× Expected `;` but found `{`
|
||||
× Using declarations may not have binding patterns.
|
||||
╭─[typescript/tests/cases/conformance/statements/VariableStatements/usingDeclarations/awaitUsingDeclarationsInForOf.3.ts:2:22]
|
||||
1 │ async function main() {
|
||||
2 │ for (await using {} of []) {
|
||||
· ┬
|
||||
· ╰── `;` expected
|
||||
· ──
|
||||
3 │ }
|
||||
╰────
|
||||
|
||||
|
||||
Reference in new issue
Block a user