From a091fc4b429b306a07baf040302086877c2d5bfd Mon Sep 17 00:00:00 2001 From: camc314 <18101008+camc314@users.noreply.github.com> Date: Wed, 9 Sep 2026 15:21:18 +0000 Subject: [PATCH] fix(parser): validate await context for await using declarations (#26495) Reject `await using` in non-async functions and ordinary generators, including `for` and `for...of` loop heads. Treat top-level `await using` as module syntax when the source type is unambiguous. --- crates/oxc_parser/src/js/declaration.rs | 10 ++ .../fixtures/oxc/js/declarations/using.snap | 18 +-- .../coverage/misc/fail/await-using-context.js | 11 ++ .../misc/pass/await-using-unambiguous.js | 1 + tasks/coverage/snapshots/codegen_misc.snap | 4 +- tasks/coverage/snapshots/formatter_misc.snap | 4 +- tasks/coverage/snapshots/lexer_misc.snap | 4 +- tasks/coverage/snapshots/parser_babel.snap | 104 ++++++++++++++++++ tasks/coverage/snapshots/parser_misc.snap | 60 +++++++++- tasks/coverage/snapshots/parser_test262.snap | 8 ++ .../coverage/snapshots/parser_typescript.snap | 58 +++++++--- tasks/coverage/snapshots/semantic_misc.snap | 4 +- .../coverage/snapshots/transformer_misc.snap | 4 +- tasks/transform_conformance/src/test_case.rs | 7 +- 14 files changed, 258 insertions(+), 39 deletions(-) create mode 100644 tasks/coverage/misc/fail/await-using-context.js create mode 100644 tasks/coverage/misc/pass/await-using-unambiguous.js diff --git a/crates/oxc_parser/src/js/declaration.rs b/crates/oxc_parser/src/js/declaration.rs index 1ff7326489..b451c8be44 100644 --- a/crates/oxc_parser/src/js/declaration.rs +++ b/crates/oxc_parser/src/js/declaration.rs @@ -189,6 +189,16 @@ impl<'a, C: Config> ParserImpl<'a, C> { let is_await = self.eat(Kind::Await); let kind = if is_await { + if !self.ctx.has_await() { + let error = diagnostics::await_expression(Span::sized(start, 5)); + if self.ctx.has_top_level() { + // Top-level `await using` is module syntax in unambiguous mode. + self.module_record_builder.set_module_syntax(); + self.error_on_script(error); + } else { + self.error(error); + } + } VariableDeclarationKind::AwaitUsing } else { VariableDeclarationKind::Using diff --git a/crates/oxc_semantic/tests/fixtures/oxc/js/declarations/using.snap b/crates/oxc_semantic/tests/fixtures/oxc/js/declarations/using.snap index 33db12cd3f..49e3b81e61 100644 --- a/crates/oxc_semantic/tests/fixtures/oxc/js/declarations/using.snap +++ b/crates/oxc_semantic/tests/fixtures/oxc/js/declarations/using.snap @@ -7,7 +7,7 @@ input_file: crates/oxc_semantic/tests/fixtures/oxc/js/declarations/using.js "children": [ { "children": [], - "flags": "ScopeFlags(0x0)", + "flags": "ScopeFlags(StrictMode)", "id": 1, "node": "BlockStatement", "symbols": [ @@ -22,7 +22,7 @@ input_file: crates/oxc_semantic/tests/fixtures/oxc/js/declarations/using.js }, { "children": [], - "flags": "ScopeFlags(0x0)", + "flags": "ScopeFlags(StrictMode)", "id": 2, "node": "BlockStatement", "symbols": [ @@ -37,7 +37,7 @@ input_file: crates/oxc_semantic/tests/fixtures/oxc/js/declarations/using.js }, { "children": [], - "flags": "ScopeFlags(0x0)", + "flags": "ScopeFlags(StrictMode)", "id": 3, "node": "BlockStatement", "symbols": [ @@ -52,7 +52,7 @@ input_file: crates/oxc_semantic/tests/fixtures/oxc/js/declarations/using.js }, { "children": [], - "flags": "ScopeFlags(0x0)", + "flags": "ScopeFlags(StrictMode)", "id": 4, "node": "BlockStatement", "symbols": [ @@ -69,13 +69,13 @@ input_file: crates/oxc_semantic/tests/fixtures/oxc/js/declarations/using.js "children": [ { "children": [], - "flags": "ScopeFlags(0x0)", + "flags": "ScopeFlags(StrictMode)", "id": 6, "node": "BlockStatement", "symbols": [] } ], - "flags": "ScopeFlags(0x0)", + "flags": "ScopeFlags(StrictMode)", "id": 5, "node": "ForOfStatement", "symbols": [ @@ -92,13 +92,13 @@ input_file: crates/oxc_semantic/tests/fixtures/oxc/js/declarations/using.js "children": [ { "children": [], - "flags": "ScopeFlags(0x0)", + "flags": "ScopeFlags(StrictMode)", "id": 8, "node": "BlockStatement", "symbols": [] } ], - "flags": "ScopeFlags(0x0)", + "flags": "ScopeFlags(StrictMode)", "id": 7, "node": "ForOfStatement", "symbols": [ @@ -112,7 +112,7 @@ input_file: crates/oxc_semantic/tests/fixtures/oxc/js/declarations/using.js ] } ], - "flags": "ScopeFlags(Top)", + "flags": "ScopeFlags(StrictMode | Top)", "id": 0, "node": "Program", "symbols": [] diff --git a/tasks/coverage/misc/fail/await-using-context.js b/tasks/coverage/misc/fail/await-using-context.js new file mode 100644 index 0000000000..d2884e3f0c --- /dev/null +++ b/tasks/coverage/misc/fail/await-using-context.js @@ -0,0 +1,11 @@ +function f() { + await using x = null; + for (await using y = null; ; ) {} + for (await using z of []) {} +} + +function* g() { + await using x = null; + for (await using y = null; ; ) {} + for (await using z of []) {} +} diff --git a/tasks/coverage/misc/pass/await-using-unambiguous.js b/tasks/coverage/misc/pass/await-using-unambiguous.js new file mode 100644 index 0000000000..55800a4ebb --- /dev/null +++ b/tasks/coverage/misc/pass/await-using-unambiguous.js @@ -0,0 +1 @@ +await using x = null; diff --git a/tasks/coverage/snapshots/codegen_misc.snap b/tasks/coverage/snapshots/codegen_misc.snap index 9f0463fac6..401749cdd1 100644 --- a/tasks/coverage/snapshots/codegen_misc.snap +++ b/tasks/coverage/snapshots/codegen_misc.snap @@ -1,3 +1,3 @@ codegen_misc Summary: -AST Parsed : 97/97 (100.00%) -Positive Passed: 97/97 (100.00%) +AST Parsed : 98/98 (100.00%) +Positive Passed: 98/98 (100.00%) diff --git a/tasks/coverage/snapshots/formatter_misc.snap b/tasks/coverage/snapshots/formatter_misc.snap index 3ef12ebc23..26b5bb5c05 100644 --- a/tasks/coverage/snapshots/formatter_misc.snap +++ b/tasks/coverage/snapshots/formatter_misc.snap @@ -1,3 +1,3 @@ formatter_misc Summary: -AST Parsed : 97/97 (100.00%) -Positive Passed: 97/97 (100.00%) +AST Parsed : 98/98 (100.00%) +Positive Passed: 98/98 (100.00%) diff --git a/tasks/coverage/snapshots/lexer_misc.snap b/tasks/coverage/snapshots/lexer_misc.snap index 9fe7bc4167..9783a61ed9 100644 --- a/tasks/coverage/snapshots/lexer_misc.snap +++ b/tasks/coverage/snapshots/lexer_misc.snap @@ -1,3 +1,3 @@ lexer_misc Summary: -AST Parsed : 297/297 (100.00%) -Positive Passed: 297/297 (100.00%) +AST Parsed : 299/299 (100.00%) +Positive Passed: 299/299 (100.00%) diff --git a/tasks/coverage/snapshots/parser_babel.snap b/tasks/coverage/snapshots/parser_babel.snap index 128b942dfc..bd81be1661 100644 --- a/tasks/coverage/snapshots/parser_babel.snap +++ b/tasks/coverage/snapshots/parser_babel.snap @@ -8823,6 +8823,15 @@ Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typesc ╰──── help: Wrap this declaration in a block statement + × `await` is only allowed within async functions and at the top levels of modules + ╭─[babel/packages/babel-parser/test/fixtures/es2026/async-explicit-resource-management/invalid-in-single-statement-context-sync/input.js:2:13] + 1 │ { + 2 │ while (1) await using a = foo; + · ───── + 3 │ for (;0;) await using b = foo; + ╰──── + help: Either remove this `await` or add the `async` keyword to the enclosing function + × Lexical declaration cannot appear in a single-statement context ╭─[babel/packages/babel-parser/test/fixtures/es2026/async-explicit-resource-management/invalid-in-single-statement-context-sync/input.js:2:13] 1 │ { @@ -8832,6 +8841,15 @@ Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typesc ╰──── help: Wrap this declaration in a block statement + × `await` is only allowed within async functions and at the top levels of modules + ╭─[babel/packages/babel-parser/test/fixtures/es2026/async-explicit-resource-management/invalid-in-single-statement-context-sync/input.js:3:13] + 2 │ while (1) await using a = foo; + 3 │ for (;0;) await using b = foo; + · ───── + 4 │ do await using c = foo; while (1); + ╰──── + help: Either remove this `await` or add the `async` keyword to the enclosing function + × Lexical declaration cannot appear in a single-statement context ╭─[babel/packages/babel-parser/test/fixtures/es2026/async-explicit-resource-management/invalid-in-single-statement-context-sync/input.js:3:13] 2 │ while (1) await using a = foo; @@ -8841,6 +8859,15 @@ Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typesc ╰──── help: Wrap this declaration in a block statement + × `await` is only allowed within async functions and at the top levels of modules + ╭─[babel/packages/babel-parser/test/fixtures/es2026/async-explicit-resource-management/invalid-in-single-statement-context-sync/input.js:4:6] + 3 │ for (;0;) await using b = foo; + 4 │ do await using c = foo; while (1); + · ───── + 5 │ if (1) await using d = foo; + ╰──── + help: Either remove this `await` or add the `async` keyword to the enclosing function + × Lexical declaration cannot appear in a single-statement context ╭─[babel/packages/babel-parser/test/fixtures/es2026/async-explicit-resource-management/invalid-in-single-statement-context-sync/input.js:4:6] 3 │ for (;0;) await using b = foo; @@ -8850,6 +8877,15 @@ Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typesc ╰──── help: Wrap this declaration in a block statement + × `await` is only allowed within async functions and at the top levels of modules + ╭─[babel/packages/babel-parser/test/fixtures/es2026/async-explicit-resource-management/invalid-in-single-statement-context-sync/input.js:5:10] + 4 │ do await using c = foo; while (1); + 5 │ if (1) await using d = foo; + · ───── + 6 │ with (1) await using e = foo; + ╰──── + help: Either remove this `await` or add the `async` keyword to the enclosing function + × Lexical declaration cannot appear in a single-statement context ╭─[babel/packages/babel-parser/test/fixtures/es2026/async-explicit-resource-management/invalid-in-single-statement-context-sync/input.js:5:10] 4 │ do await using c = foo; while (1); @@ -8859,6 +8895,15 @@ Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typesc ╰──── help: Wrap this declaration in a block statement + × `await` is only allowed within async functions and at the top levels of modules + ╭─[babel/packages/babel-parser/test/fixtures/es2026/async-explicit-resource-management/invalid-in-single-statement-context-sync/input.js:6:12] + 5 │ if (1) await using d = foo; + 6 │ with (1) await using e = foo; + · ───── + 7 │ label: await using f = foo; + ╰──── + help: Either remove this `await` or add the `async` keyword to the enclosing function + × Lexical declaration cannot appear in a single-statement context ╭─[babel/packages/babel-parser/test/fixtures/es2026/async-explicit-resource-management/invalid-in-single-statement-context-sync/input.js:6:12] 5 │ if (1) await using d = foo; @@ -8868,6 +8913,15 @@ Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typesc ╰──── help: Wrap this declaration in a block statement + × `await` is only allowed within async functions and at the top levels of modules + ╭─[babel/packages/babel-parser/test/fixtures/es2026/async-explicit-resource-management/invalid-in-single-statement-context-sync/input.js:7:10] + 6 │ with (1) await using e = foo; + 7 │ label: await using f = foo; + · ───── + 8 │ } + ╰──── + help: Either remove this `await` or add the `async` keyword to the enclosing function + × Lexical declaration cannot appear in a single-statement context ╭─[babel/packages/babel-parser/test/fixtures/es2026/async-explicit-resource-management/invalid-in-single-statement-context-sync/input.js:7:10] 6 │ with (1) await using e = foo; @@ -8913,6 +8967,13 @@ Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typesc ╰──── help: Wrap this declaration in a block statement + × `await` is only allowed within async functions and at the top levels of modules + ╭─[babel/packages/babel-parser/test/fixtures/es2026/async-explicit-resource-management/invalid-script-top-level-labeled-using-binding/input.js:1:8] + 1 │ label: await using x = bar(); + · ───── + ╰──── + help: Either remove this `await` or add the `async` keyword to the enclosing function + × Lexical declaration cannot appear in a single-statement context ╭─[babel/packages/babel-parser/test/fixtures/es2026/async-explicit-resource-management/invalid-script-top-level-labeled-using-binding/input.js:1:8] 1 │ label: await using x = bar(); @@ -8927,6 +8988,13 @@ Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typesc ╰──── help: Wrap this code in a block or use a module + × `await` is only allowed within async functions and at the top levels of modules + ╭─[babel/packages/babel-parser/test/fixtures/es2026/async-explicit-resource-management/invalid-script-top-level-using-binding/input.js:1:1] + 1 │ await using x = bar(); + · ───── + ╰──── + help: Either remove this `await` or add the `async` keyword to the enclosing function + × 'using' declarations are not allowed at the top level of a script ╭─[babel/packages/babel-parser/test/fixtures/es2026/async-explicit-resource-management/invalid-script-top-level-using-binding/input.js:1:1] 1 │ await using x = bar(); @@ -13786,6 +13854,15 @@ Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typesc ╰──── help: Try inserting a semicolon here + × `await` is only allowed within async functions and at the top levels of modules + ╭─[babel/packages/babel-parser/test/fixtures/typescript/declare/invalid-namespace-await-using/input.ts:2:3] + 1 │ declare namespace invalid_namespace_var { + 2 │ await using A; + · ───── + 3 │ await using A1 = 0; + ╰──── + help: Either remove this `await` or add the `async` keyword to the enclosing function + × TS(1546): 'await using' declarations are not allowed in ambient contexts. ╭─[babel/packages/babel-parser/test/fixtures/typescript/declare/invalid-namespace-await-using/input.ts:2:15] 1 │ declare namespace invalid_namespace_var { @@ -13794,6 +13871,15 @@ Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typesc 3 │ await using A1 = 0; ╰──── + × `await` is only allowed within async functions and at the top levels of modules + ╭─[babel/packages/babel-parser/test/fixtures/typescript/declare/invalid-namespace-await-using/input.ts:3:3] + 2 │ await using A; + 3 │ await using A1 = 0; + · ───── + 4 │ await using A2: number = 0; + ╰──── + help: Either remove this `await` or add the `async` keyword to the enclosing function + × TS(1546): 'await using' declarations are not allowed in ambient contexts. ╭─[babel/packages/babel-parser/test/fixtures/typescript/declare/invalid-namespace-await-using/input.ts:3:15] 2 │ await using A; @@ -13802,6 +13888,15 @@ Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typesc 4 │ await using A2: number = 0; ╰──── + × `await` is only allowed within async functions and at the top levels of modules + ╭─[babel/packages/babel-parser/test/fixtures/typescript/declare/invalid-namespace-await-using/input.ts:4:3] + 3 │ await using A1 = 0; + 4 │ await using A2: number = 0; + · ───── + 5 │ await using B, C; + ╰──── + help: Either remove this `await` or add the `async` keyword to the enclosing function + × TS(1546): 'await using' declarations are not allowed in ambient contexts. ╭─[babel/packages/babel-parser/test/fixtures/typescript/declare/invalid-namespace-await-using/input.ts:4:15] 3 │ await using A1 = 0; @@ -13810,6 +13905,15 @@ Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typesc 5 │ await using B, C; ╰──── + × `await` is only allowed within async functions and at the top levels of modules + ╭─[babel/packages/babel-parser/test/fixtures/typescript/declare/invalid-namespace-await-using/input.ts:5:3] + 4 │ await using A2: number = 0; + 5 │ await using B, C; + · ───── + 6 │ } + ╰──── + help: Either remove this `await` or add the `async` keyword to the enclosing function + × TS(1546): 'await using' declarations are not allowed in ambient contexts. ╭─[babel/packages/babel-parser/test/fixtures/typescript/declare/invalid-namespace-await-using/input.ts:5:15] 4 │ await using A2: number = 0; diff --git a/tasks/coverage/snapshots/parser_misc.snap b/tasks/coverage/snapshots/parser_misc.snap index c1090e9610..1f4f90049d 100644 --- a/tasks/coverage/snapshots/parser_misc.snap +++ b/tasks/coverage/snapshots/parser_misc.snap @@ -1,7 +1,7 @@ parser_misc Summary: -AST Parsed : 97/97 (100.00%) -Positive Passed: 97/97 (100.00%) -Negative Passed: 200/200 (100.00%) +AST Parsed : 98/98 (100.00%) +Positive Passed: 98/98 (100.00%) +Negative Passed: 201/201 (100.00%) × Cannot assign to 'arguments' in strict mode ╭─[misc/fail/arguments-eval-ambient.ts:2:13] @@ -228,6 +228,60 @@ Negative Passed: 200/200 (100.00%) 5 │ } ╰──── + × `await` is only allowed within async functions and at the top levels of modules + ╭─[misc/fail/await-using-context.js:2:3] + 1 │ function f() { + 2 │ await using x = null; + · ───── + 3 │ for (await using y = null; ; ) {} + ╰──── + help: Either remove this `await` or add the `async` keyword to the enclosing function + + × `await` is only allowed within async functions and at the top levels of modules + ╭─[misc/fail/await-using-context.js:3:8] + 2 │ await using x = null; + 3 │ for (await using y = null; ; ) {} + · ───── + 4 │ for (await using z of []) {} + ╰──── + help: Either remove this `await` or add the `async` keyword to the enclosing function + + × `await` is only allowed within async functions and at the top levels of modules + ╭─[misc/fail/await-using-context.js:4:8] + 3 │ for (await using y = null; ; ) {} + 4 │ for (await using z of []) {} + · ───── + 5 │ } + ╰──── + help: Either remove this `await` or add the `async` keyword to the enclosing function + + × `await` is only allowed within async functions and at the top levels of modules + ╭─[misc/fail/await-using-context.js:8:3] + 7 │ function* g() { + 8 │ await using x = null; + · ───── + 9 │ for (await using y = null; ; ) {} + ╰──── + help: Either remove this `await` or add the `async` keyword to the enclosing function + + × `await` is only allowed within async functions and at the top levels of modules + ╭─[misc/fail/await-using-context.js:9:8] + 8 │ await using x = null; + 9 │ for (await using y = null; ; ) {} + · ───── + 10 │ for (await using z of []) {} + ╰──── + help: Either remove this `await` or add the `async` keyword to the enclosing function + + × `await` is only allowed within async functions and at the top levels of modules + ╭─[misc/fail/await-using-context.js:10:8] + 9 │ for (await using y = null; ; ) {} + 10 │ for (await using z of []) {} + · ───── + 11 │ } + ╰──── + help: Either remove this `await` or add the `async` keyword to the enclosing function + × Expected `;` but found `,` ╭─[misc/fail/class-field-comma-expression.js:1:16] 1 │ class C { x = a,b } diff --git a/tasks/coverage/snapshots/parser_test262.snap b/tasks/coverage/snapshots/parser_test262.snap index 582eb9ccd6..47e9820f4c 100644 --- a/tasks/coverage/snapshots/parser_test262.snap +++ b/tasks/coverage/snapshots/parser_test262.snap @@ -27711,6 +27711,14 @@ Negative Passed: 4651/4651 (100.00%) ╰──── help: Wrap this declaration in a block statement + × `await` is only allowed within async functions and at the top levels of modules + ╭─[test262/test/language/statements/await-using/syntax/await-using-not-allowed-at-top-level-of-script.js:23:1] + 22 │ $DONOTEVALUATE(); + 23 │ await using x = null; + · ───── + ╰──── + help: Either remove this `await` or add the `async` keyword to the enclosing function + × 'using' declarations are not allowed at the top level of a script ╭─[test262/test/language/statements/await-using/syntax/await-using-not-allowed-at-top-level-of-script.js:23:1] 22 │ $DONOTEVALUATE(); diff --git a/tasks/coverage/snapshots/parser_typescript.snap b/tasks/coverage/snapshots/parser_typescript.snap index ce84be1546..3a08f3a4cd 100644 --- a/tasks/coverage/snapshots/parser_typescript.snap +++ b/tasks/coverage/snapshots/parser_typescript.snap @@ -28729,13 +28729,14 @@ Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/types/wit ╰──── help: Remove the `export` here and add `export { x }` as a separate statement to export the declaration - × 'using' declarations are not allowed at the top level of a script - ╭─[typescript/tests/cases/conformance/statements/VariableStatements/usingDeclarations/awaitUsingDeclarations.13.ts:1:1] - 1 │ await using x = null; - · ───────────────────── - 2 │ + × `await` is only allowed within async functions and at the top levels of modules + ╭─[typescript/tests/cases/conformance/statements/VariableStatements/usingDeclarations/awaitUsingDeclarations.13.ts:4:5] + 3 │ function f() { + 4 │ await using x = null; + · ───── + 5 │ } ╰──── - help: Wrap this code in a block or use a module + help: Either remove this `await` or add the `async` keyword to the enclosing function × Cannot use 'await using' in class static initialization block ╭─[typescript/tests/cases/conformance/statements/VariableStatements/usingDeclarations/awaitUsingDeclarations.14.ts:3:9] @@ -28753,6 +28754,15 @@ Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/types/wit 6 │ } ╰──── + × `await` is only allowed within async functions and at the top levels of modules + ╭─[typescript/tests/cases/conformance/statements/VariableStatements/usingDeclarations/awaitUsingDeclarations.16.ts:2:5] + 1 │ declare namespace N { + 2 │ await using x: { [Symbol.asyncDispose](): Promise }; + · ───── + 3 │ await using y: null; + ╰──── + help: Either remove this `await` or add the `async` keyword to the enclosing function + × TS(1546): 'await using' declarations are not allowed in ambient contexts. ╭─[typescript/tests/cases/conformance/statements/VariableStatements/usingDeclarations/awaitUsingDeclarations.16.ts:2:17] 1 │ declare namespace N { @@ -28761,6 +28771,15 @@ Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/types/wit 3 │ await using y: null; ╰──── + × `await` is only allowed within async functions and at the top levels of modules + ╭─[typescript/tests/cases/conformance/statements/VariableStatements/usingDeclarations/awaitUsingDeclarations.16.ts:3:5] + 2 │ await using x: { [Symbol.asyncDispose](): Promise }; + 3 │ await using y: null; + · ───── + 4 │ } + ╰──── + help: Either remove this `await` or add the `async` keyword to the enclosing function + × TS(1546): 'await using' declarations are not allowed in ambient contexts. ╭─[typescript/tests/cases/conformance/statements/VariableStatements/usingDeclarations/awaitUsingDeclarations.16.ts:3:17] 2 │ await using x: { [Symbol.asyncDispose](): Promise }; @@ -28769,6 +28788,15 @@ Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/types/wit 4 │ } ╰──── + × `await` is only allowed within async functions and at the top levels of modules + ╭─[typescript/tests/cases/conformance/statements/VariableStatements/usingDeclarations/awaitUsingDeclarations.16.ts:6:5] + 5 │ declare module 'M' { + 6 │ await using x: { [Symbol.asyncDispose](): Promise }; + · ───── + 7 │ await using y: null; + ╰──── + help: Either remove this `await` or add the `async` keyword to the enclosing function + × TS(1546): 'await using' declarations are not allowed in ambient contexts. ╭─[typescript/tests/cases/conformance/statements/VariableStatements/usingDeclarations/awaitUsingDeclarations.16.ts:6:17] 5 │ declare module 'M' { @@ -28777,6 +28805,15 @@ Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/types/wit 7 │ await using y: null; ╰──── + × `await` is only allowed within async functions and at the top levels of modules + ╭─[typescript/tests/cases/conformance/statements/VariableStatements/usingDeclarations/awaitUsingDeclarations.16.ts:7:5] + 6 │ await using x: { [Symbol.asyncDispose](): Promise }; + 7 │ await using y: null; + · ───── + 8 │ } + ╰──── + help: Either remove this `await` or add the `async` keyword to the enclosing function + × TS(1546): 'await using' declarations are not allowed in ambient contexts. ╭─[typescript/tests/cases/conformance/statements/VariableStatements/usingDeclarations/awaitUsingDeclarations.16.ts:7:17] 6 │ await using x: { [Symbol.asyncDispose](): Promise }; @@ -28882,15 +28919,6 @@ Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/types/wit 6 │ ╰──── - × `for await` loops are only allowed within async functions and at the top levels of modules - ╭─[typescript/tests/cases/conformance/statements/VariableStatements/usingDeclarations/awaitUsingDeclarationsInForAwaitOf.3.ts:5:5] - 4 │ - 5 │ for await (await using of x); - · ───── - 6 │ - ╰──── - help: Either remove this `await` or add the `async` keyword to the enclosing function - × The left-hand side of a for...in statement cannot be an await using declaration. ╭─[typescript/tests/cases/conformance/statements/VariableStatements/usingDeclarations/awaitUsingDeclarationsInForIn.ts:2:10] 1 │ async function main() { diff --git a/tasks/coverage/snapshots/semantic_misc.snap b/tasks/coverage/snapshots/semantic_misc.snap index 1253e7ba80..e3863b6a4e 100644 --- a/tasks/coverage/snapshots/semantic_misc.snap +++ b/tasks/coverage/snapshots/semantic_misc.snap @@ -1,6 +1,6 @@ semantic_misc Summary: -AST Parsed : 97/97 (100.00%) -Positive Passed: 93/97 (95.88%) +AST Parsed : 98/98 (100.00%) +Positive Passed: 94/98 (95.92%) semantic Error: tasks/coverage/misc/pass/declare-let-private.ts Bindings mismatch: after transform: ScopeId(0): ["private"] diff --git a/tasks/coverage/snapshots/transformer_misc.snap b/tasks/coverage/snapshots/transformer_misc.snap index 79ecce176b..c6e69de006 100644 --- a/tasks/coverage/snapshots/transformer_misc.snap +++ b/tasks/coverage/snapshots/transformer_misc.snap @@ -1,3 +1,3 @@ transformer_misc Summary: -AST Parsed : 97/97 (100.00%) -Positive Passed: 97/97 (100.00%) +AST Parsed : 98/98 (100.00%) +Positive Passed: 98/98 (100.00%) diff --git a/tasks/transform_conformance/src/test_case.rs b/tasks/transform_conformance/src/test_case.rs index 287443a109..50b03867ff 100644 --- a/tasks/transform_conformance/src/test_case.rs +++ b/tasks/transform_conformance/src/test_case.rs @@ -89,8 +89,11 @@ impl TestCase { fn source_type(path: &Path, options: &BabelOptions) -> SourceType { // Some babel test cases have a js extension, but contain typescript code. // Therefore, if the typescript plugin exists, enable typescript. - let mut source_type = - SourceType::from_path(path).unwrap().with_script(true).with_jsx(options.is_jsx()); + let mut source_type = SourceType::from_path(path).unwrap().with_jsx(options.is_jsx()); + // Preserve explicit module extensions; other fixtures default to scripts. + if !source_type.is_module() { + source_type = source_type.with_script(true); + } source_type = match options.source_type.as_deref() { Some("unambiguous") => source_type.with_unambiguous(true), Some("script") => source_type.with_script(true),