Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 8 additions & 9 deletions crates/oxc_parser/src/js/declaration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,8 @@ impl<'a, C: Config> ParserImpl<'a, C> {
} else if decl.kind == VariableDeclarationKind::Const {
// It is a Syntax Error if Initializer is not present and IsConstantDeclaration of the LexicalDeclaration containing this LexicalBinding is true.
self.error(diagnostics::missing_initializer_in_const(decl.id.span()));
} else if decl.kind.is_using() {
self.error(diagnostics::using_declarations_must_be_initialized(decl.id.span()));
}
}
}
Expand All @@ -186,22 +188,19 @@ impl<'a, C: Config> ParserImpl<'a, C> {
// BindingList[?In, ?Yield, ?Await, ~Pattern]
let mut declarations = self.ast.vec();
loop {
let declaration =
self.parse_variable_declarator(VariableDeclarationParent::Statement, kind);
let decl_parent = if matches!(statement_ctx, StatementContext::For) {
VariableDeclarationParent::For
} else {
VariableDeclarationParent::Statement
};
let declaration = self.parse_variable_declarator(decl_parent, kind);

if !matches!(declaration.id, BindingPattern::BindingIdentifier(_)) {
self.error(diagnostics::invalid_identifier_in_using_declaration(
declaration.id.span(),
));
}

// Excluding `for` loops, an initializer is required in a UsingDeclaration.
if declaration.init.is_none() && !matches!(statement_ctx, StatementContext::For) {
self.error(diagnostics::using_declarations_must_be_initialized(
declaration.id.span(),
));
}

declarations.push(declaration);
if !self.eat(Kind::Comma) {
break;
Expand Down
65 changes: 8 additions & 57 deletions tasks/coverage/snapshots/parser_babel.snap
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@ commit: 308c8d85
parser_babel Summary:
AST Parsed : 2227/2227 (100.00%)
Positive Passed: 2214/2227 (99.42%)
Negative Passed: 1675/1692 (99.00%)
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/es2026/explicit-resource-management/invalid-for-using-of-no-initializer/input.js

Negative Passed: 1676/1692 (99.05%)
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/cast/unparenthesized-assert-and-assign/input.ts

Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/cast/unparenthesized-type-assertion-and-assign/input.ts
Expand Down Expand Up @@ -8949,6 +8947,13 @@ Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typesc
· ──
╰────

× Using declarations must have an initializer.
╭─[babel/packages/babel-parser/test/fixtures/es2026/explicit-resource-management/invalid-for-using-of-no-initializer/input.js:1:12]
1 │ for (using of;of.isValid;);
· ──
╰────
help: Add an initializer (e.g. ` = undefined`) here

× Lexical declaration cannot appear in a single-statement context
╭─[babel/packages/babel-parser/test/fixtures/es2026/explicit-resource-management/invalid-in-single-statement-context/input.js:2:13]
1 │ {
Expand Down Expand Up @@ -13175,15 +13180,6 @@ Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typesc
╰────
help: Try inserting a semicolon here

× Using declarations must have an initializer.
╭─[babel/packages/babel-parser/test/fixtures/typescript/declare/invalid-namespace-await-using/input.ts:2:15]
1 │ declare namespace invalid_namespace_var {
2 │ await using A;
· ─
3 │ await using A1 = 0;
╰────
help: Add an initializer (e.g. ` = undefined`) here

× TS(1039): Initializers are not allowed in ambient contexts.
╭─[babel/packages/babel-parser/test/fixtures/typescript/declare/invalid-namespace-await-using/input.ts:3:20]
2 │ await using A;
Expand All @@ -13200,33 +13196,6 @@ Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typesc
5 │ await using B, C;
╰────

× Using declarations must have an initializer.
╭─[babel/packages/babel-parser/test/fixtures/typescript/declare/invalid-namespace-await-using/input.ts:5:15]
4 │ await using A2: number = 0;
5 │ await using B, C;
· ─
6 │ }
╰────
help: Add an initializer (e.g. ` = undefined`) here

× Using declarations must have an initializer.
╭─[babel/packages/babel-parser/test/fixtures/typescript/declare/invalid-namespace-await-using/input.ts:5:18]
4 │ await using A2: number = 0;
5 │ await using B, C;
· ─
6 │ }
╰────
help: Add an initializer (e.g. ` = undefined`) here

× Using declarations must have an initializer.
╭─[babel/packages/babel-parser/test/fixtures/typescript/declare/invalid-namespace-using/input.ts:2:9]
1 │ declare namespace invalid_namespace_var {
2 │ using A;
· ─
3 │ using A1 = 0;
╰────
help: Add an initializer (e.g. ` = undefined`) here

× TS(1039): Initializers are not allowed in ambient contexts.
╭─[babel/packages/babel-parser/test/fixtures/typescript/declare/invalid-namespace-using/input.ts:3:14]
2 │ using A;
Expand All @@ -13243,24 +13212,6 @@ Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typesc
5 │ using B, C;
╰────

× Using declarations must have an initializer.
╭─[babel/packages/babel-parser/test/fixtures/typescript/declare/invalid-namespace-using/input.ts:5:9]
4 │ using A2: number = 0;
5 │ using B, C;
· ─
6 │ }
╰────
help: Add an initializer (e.g. ` = undefined`) here

× Using declarations must have an initializer.
╭─[babel/packages/babel-parser/test/fixtures/typescript/declare/invalid-namespace-using/input.ts:5:12]
4 │ using A2: number = 0;
5 │ using B, C;
· ─
6 │ }
╰────
help: Add an initializer (e.g. ` = undefined`) here

× TS(1039): Initializers are not allowed in ambient contexts.
╭─[babel/packages/babel-parser/test/fixtures/typescript/declare/invalid-namespace-var/input.ts:2:11]
1 │ declare namespace invalid_namespace_var {
Expand Down
95 changes: 12 additions & 83 deletions tasks/coverage/snapshots/parser_typescript.snap
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ commit: 34725489
parser_typescript Summary:
AST Parsed : 9831/9834 (99.97%)
Positive Passed: 9820/9834 (99.86%)
Negative Passed: 1528/2578 (59.27%)
Negative Passed: 1527/2578 (59.23%)
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/FunctionDeclaration3.ts

Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/FunctionDeclaration4.ts
Expand Down Expand Up @@ -1954,9 +1954,11 @@ Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/scanner/e

Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/statements/VariableStatements/usingDeclarations/awaitUsingDeclarations.14.ts

Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/statements/VariableStatements/usingDeclarations/awaitUsingDeclarations.16.ts

Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/statements/VariableStatements/usingDeclarations/awaitUsingDeclarationsInForOf.4.ts

Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/statements/VariableStatements/usingDeclarations/usingDeclarationsInForOf.4.ts
Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/statements/VariableStatements/usingDeclarations/usingDeclarations.16.ts

Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/statements/for-inStatements/for-inStatementsArrayErrors.ts

Expand Down Expand Up @@ -25842,42 +25844,6 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/parser/ecmasc
╰────
help: Wrap this code in a block or use a module

× Using declarations must have an initializer.
╭─[typescript/tests/cases/conformance/statements/VariableStatements/usingDeclarations/awaitUsingDeclarations.16.ts:2:17]
1 │ declare namespace N {
2 │ await using x: { [Symbol.asyncDispose](): Promise<void> };
· ─
3 │ await using y: null;
╰────
help: Add an initializer (e.g. ` = undefined`) here

× Using declarations must have an initializer.
╭─[typescript/tests/cases/conformance/statements/VariableStatements/usingDeclarations/awaitUsingDeclarations.16.ts:3:17]
2 │ await using x: { [Symbol.asyncDispose](): Promise<void> };
3 │ await using y: null;
· ─
4 │ }
╰────
help: Add an initializer (e.g. ` = undefined`) here

× Using declarations must have an initializer.
╭─[typescript/tests/cases/conformance/statements/VariableStatements/usingDeclarations/awaitUsingDeclarations.16.ts:6:17]
5 │ declare module 'M' {
6 │ await using x: { [Symbol.asyncDispose](): Promise<void> };
· ─
7 │ await using y: null;
╰────
help: Add an initializer (e.g. ` = undefined`) here

× Using declarations must have an initializer.
╭─[typescript/tests/cases/conformance/statements/VariableStatements/usingDeclarations/awaitUsingDeclarations.16.ts:7:17]
6 │ await using x: { [Symbol.asyncDispose](): Promise<void> };
7 │ await using y: null;
· ─
8 │ }
╰────
help: Add an initializer (e.g. ` = undefined`) here

× Using declaration cannot appear in the bare case statement.
╭─[typescript/tests/cases/conformance/statements/VariableStatements/usingDeclarations/awaitUsingDeclarations.17.ts:3:9]
2 │ case 0:
Expand Down Expand Up @@ -25993,15 +25959,6 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/parser/ecmasc
╰────
help: Did you mean to use a for...of statement?

× Missing initializer in destructuring declaration
╭─[typescript/tests/cases/conformance/statements/VariableStatements/usingDeclarations/awaitUsingDeclarationsInForOf.3.ts:2:22]
1 │ async function main() {
2 │ for (await using {} of []) {
· ──
3 │ }
╰────
help: Add an initializer (e.g. ` = undefined`) here

× Using declarations may not have binding patterns.
╭─[typescript/tests/cases/conformance/statements/VariableStatements/usingDeclarations/awaitUsingDeclarationsInForOf.3.ts:2:22]
1 │ async function main() {
Expand Down Expand Up @@ -26043,42 +26000,6 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/parser/ecmasc
╰────
help: Remove the `export` here and add `export { x }` as a separate statement to export the declaration

× Using declarations must have an initializer.
╭─[typescript/tests/cases/conformance/statements/VariableStatements/usingDeclarations/usingDeclarations.16.ts:2:11]
1 │ declare namespace N {
2 │ using x: { [Symbol.dispose](): void };
· ─
3 │ using y: null;
╰────
help: Add an initializer (e.g. ` = undefined`) here

× Using declarations must have an initializer.
╭─[typescript/tests/cases/conformance/statements/VariableStatements/usingDeclarations/usingDeclarations.16.ts:3:11]
2 │ using x: { [Symbol.dispose](): void };
3 │ using y: null;
· ─
4 │ }
╰────
help: Add an initializer (e.g. ` = undefined`) here

× Using declarations must have an initializer.
╭─[typescript/tests/cases/conformance/statements/VariableStatements/usingDeclarations/usingDeclarations.16.ts:6:11]
5 │ declare module 'M' {
6 │ using x: { [Symbol.dispose](): void };
· ─
7 │ using y: null;
╰────
help: Add an initializer (e.g. ` = undefined`) here

× Using declarations must have an initializer.
╭─[typescript/tests/cases/conformance/statements/VariableStatements/usingDeclarations/usingDeclarations.16.ts:7:11]
6 │ using x: { [Symbol.dispose](): void };
7 │ using y: null;
· ─
8 │ }
╰────
help: Add an initializer (e.g. ` = undefined`) here

× Using declaration cannot appear in the bare case statement.
╭─[typescript/tests/cases/conformance/statements/VariableStatements/usingDeclarations/usingDeclarations.17.ts:3:9]
2 │ case 0:
Expand Down Expand Up @@ -26180,6 +26101,14 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/parser/ecmasc
2 │ }
╰────

× Using declarations must have an initializer.
╭─[typescript/tests/cases/conformance/statements/VariableStatements/usingDeclarations/usingDeclarationsInForOf.4.ts:3:12]
2 │ for (using of: null = null;;) break;
3 │ for (using of;;) break;
· ──
╰────
help: Add an initializer (e.g. ` = undefined`) here

× Illegal break statement
╭─[typescript/tests/cases/conformance/statements/breakStatements/invalidDoWhileBreakStatements.ts:4:1]
3 │ // naked break not allowed
Expand Down
Loading