fix(parser): reject generators in ambient contexts and overload signatures (TS1221/TS1222) (#22848)

A generator (`function*` / `*method`) is not allowed in an ambient context
(TS1221), and a generator overload signature with no body is not allowed
(TS1222). Mirrors tsc's `checkGrammarForGenerator`:

    declare function* f(): any;              // now TS1221
    declare namespace N { function* g(); }   // now TS1221
    declare class C { *m(); }                // now TS1221
    function* f(): any;                       // overload → now TS1222
    function* f() { yield 1; }

    function* f() { yield 1; }               // normal generator → still valid

The check lives in `parse_function` next to the TS1183 implementation-in-ambient
check and keys off `ctx.has_ambient()` / `body.is_none()`. Class methods are
covered too (`class.rs` does not check generators, so there is no duplicate
diagnostic).

Also fixes a latent bug: `parse_ts_declare_function` hard-coded `generator: false`
and never consumed the `*`, so `declare function* f()` silently dropped the
generator flag. It now eats the `*` and threads the flag through (which is what
lets TS1221 fire there).

parser_typescript +7 negative-pass (generatorInAmbientContext1-4, generatorOverloads1-3);
positive/AST stay 100%.
This commit is contained in:
Boshen committed 2026-05-31 08:02:50 +00:00
1 parent cc60d8d871
commit c360fb6e20
5 files changed
+134 -17

No files matched your search

+10
View File
@@ -1228,6 +1228,16 @@ pub fn implementation_in_ambient(span: Span) -> OxcDiagnostic {
ts_error("1183", "An implementation cannot be declared in ambient contexts.").with_label(span)
}
#[cold]
pub fn generator_in_ambient_context(span: Span) -> OxcDiagnostic {
ts_error("1221", "Generators are not allowed in an ambient context.").with_label(span)
}
#[cold]
pub fn overload_signature_generator(span: Span) -> OxcDiagnostic {
ts_error("1222", "An overload signature cannot be declared as a generator.").with_label(span)
}
#[cold]
pub fn initializers_not_allowed_in_ambient_contexts(span: Span) -> OxcDiagnostic {
ts_error("1039", "Initializers are not allowed in ambient contexts.").with_label(span)
+8
View File
@@ -302,6 +302,14 @@ impl<'a, C: Config> ParserImpl<'a, C> {
{
self.error(diagnostics::implementation_in_ambient(Span::empty(body.span.start)));
}
if generator {
if ctx.has_ambient() {
self.error(diagnostics::generator_in_ambient_context(self.end_span(span)));
} else if body.is_none() {
self.error(diagnostics::overload_signature_generator(self.end_span(span)));
}
}
self.verify_modifiers(
modifiers,
ModifierKinds::new([ModifierKind::Declare, ModifierKind::Async]),
+3 -2
View File
@@ -583,13 +583,14 @@ impl<'a, C: Config> ParserImpl<'a, C> {
) -> Box<'a, Function<'a>> {
let r#async = modifiers.contains(ModifierKind::Async);
self.expect(Kind::Function);
let generator = self.eat(Kind::Star);
let func_kind = FunctionKind::TSDeclaration;
let id = self.parse_function_id(func_kind, r#async, false);
let id = self.parse_function_id(func_kind, r#async, generator);
self.parse_function(
start_span,
id,
r#async,
false,
generator,
func_kind,
FormalParameterKind::FormalParameter,
modifiers,
@@ -12788,6 +12788,14 @@ Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typesc
╰────
help: Allowed modifiers are: private, protected, public, static, abstract, override, async
× TS(1221): Generators are not allowed in an ambient context.
╭─[babel/packages/babel-parser/test/fixtures/typescript/class/generator-method-with-modifiers/input.ts:7:13]
6 │ readonly *e() {}
7 │ declare *f() {}
· ─────
8 │ protected *g() {}
╰────
× TS(1183): An implementation cannot be declared in ambient contexts.
╭─[babel/packages/babel-parser/test/fixtures/typescript/class/generator-method-with-modifiers/input.ts:7:16]
6 │ readonly *e() {}
@@ -13085,6 +13093,14 @@ Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typesc
╰────
help: Allowed modifiers are: private, protected, public, static, abstract, override, async
× TS(1221): Generators are not allowed in an ambient context.
╭─[babel/packages/babel-parser/test/fixtures/typescript/class/optional-generator-method-with-invalid-modifiers/input.ts:4:14]
3 │ readonly *e?() { }
4 │ declare *f?() { }
· ──────
5 │ }
╰────
× TS(1183): An implementation cannot be declared in ambient contexts.
╭─[babel/packages/babel-parser/test/fixtures/typescript/class/optional-generator-method-with-invalid-modifiers/input.ts:4:17]
3 │ readonly *e?() { }
@@ -13119,6 +13135,14 @@ Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typesc
╰────
help: Allowed modifiers are: private, protected, public, static, abstract, override, async
× TS(1221): Generators are not allowed in an ambient context.
╭─[babel/packages/babel-parser/test/fixtures/typescript/class/optional-generator-method-with-invalid-modifiers/input.ts:10:19]
9 │ readonly *[e?.e]?() { }
10 │ declare *[f?.f]?() { }
· ──────
11 │ }
╰────
× TS(1183): An implementation cannot be declared in ambient contexts.
╭─[babel/packages/babel-parser/test/fixtures/typescript/class/optional-generator-method-with-invalid-modifiers/input.ts:10:22]
9 │ readonly *[e?.e]?() { }
+89 -15
View File
@@ -3,7 +3,7 @@ commit: e5509e21
parser_typescript Summary:
AST Parsed : 9779/9779 (100.00%)
Positive Passed: 9779/9779 (100.00%)
Negative Passed: 1621/2640 (61.40%)
Negative Passed: 1628/2640 (61.67%)
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/FunctionDeclaration3.ts
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/FunctionDeclaration4.ts
@@ -1302,20 +1302,6 @@ Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/es6/yield
Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/es6/yieldExpressions/YieldStarExpression1_es6.ts
Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/es6/yieldExpressions/generatorInAmbientContext1.ts
Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/es6/yieldExpressions/generatorInAmbientContext2.ts
Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/es6/yieldExpressions/generatorInAmbientContext3.d.ts
Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/es6/yieldExpressions/generatorInAmbientContext4.d.ts
Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/es6/yieldExpressions/generatorOverloads1.ts
Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/es6/yieldExpressions/generatorOverloads2.ts
Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/es6/yieldExpressions/generatorOverloads3.ts
Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck9.ts
Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/es7/exponentiationOperator/compoundExponentiationAssignmentLHSCanBeAssigned1.ts
@@ -19988,6 +19974,94 @@ Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/types/wit
3 │ }
╰────
× TS(1221): Generators are not allowed in an ambient context.
╭─[typescript/tests/cases/conformance/es6/yieldExpressions/generatorInAmbientContext1.ts:2:15]
1 │ declare class C {
2 │ *generator(): any;
· ────────
3 │ }
╰────
× TS(1221): Generators are not allowed in an ambient context.
╭─[typescript/tests/cases/conformance/es6/yieldExpressions/generatorInAmbientContext2.ts:2:5]
1 │ declare namespace M {
2 │ function *generator(): any;
· ───────────────────────────
3 │ }
╰────
× TS(1221): Generators are not allowed in an ambient context.
╭─[typescript/tests/cases/conformance/es6/yieldExpressions/generatorInAmbientContext3.d.ts:2:15]
1 │ declare class C {
2 │ *generator(): any;
· ────────
3 │ }
╰────
× TS(1221): Generators are not allowed in an ambient context.
╭─[typescript/tests/cases/conformance/es6/yieldExpressions/generatorInAmbientContext4.d.ts:2:5]
1 │ declare namespace M {
2 │ function *generator(): any;
· ───────────────────────────
3 │ }
╰────
× TS(1222): An overload signature cannot be declared as a generator.
╭─[typescript/tests/cases/conformance/es6/yieldExpressions/generatorOverloads1.ts:2:5]
1 │ namespace M {
2 │ function* f(s: string): Iterable<any>;
· ──────────────────────────────────────
3 │ function* f(s: number): Iterable<any>;
╰────
× TS(1222): An overload signature cannot be declared as a generator.
╭─[typescript/tests/cases/conformance/es6/yieldExpressions/generatorOverloads1.ts:3:5]
2 │ function* f(s: string): Iterable<any>;
3 │ function* f(s: number): Iterable<any>;
· ──────────────────────────────────────
4 │ function* f(s: any): Iterable<any> { }
╰────
× TS(1221): Generators are not allowed in an ambient context.
╭─[typescript/tests/cases/conformance/es6/yieldExpressions/generatorOverloads2.ts:2:5]
1 │ declare namespace M {
2 │ function* f(s: string): Iterable<any>;
· ──────────────────────────────────────
3 │ function* f(s: number): Iterable<any>;
╰────
× TS(1221): Generators are not allowed in an ambient context.
╭─[typescript/tests/cases/conformance/es6/yieldExpressions/generatorOverloads2.ts:3:5]
2 │ function* f(s: string): Iterable<any>;
3 │ function* f(s: number): Iterable<any>;
· ──────────────────────────────────────
4 │ function* f(s: any): Iterable<any>;
╰────
× TS(1221): Generators are not allowed in an ambient context.
╭─[typescript/tests/cases/conformance/es6/yieldExpressions/generatorOverloads2.ts:4:5]
3 │ function* f(s: number): Iterable<any>;
4 │ function* f(s: any): Iterable<any>;
· ───────────────────────────────────
5 │ }
╰────
× TS(1222): An overload signature cannot be declared as a generator.
╭─[typescript/tests/cases/conformance/es6/yieldExpressions/generatorOverloads3.ts:2:7]
1 │ class C {
2 │ *f(s: string): Iterable<any>;
· ───────────────────────────
3 │ *f(s: number): Iterable<any>;
╰────
× TS(1222): An overload signature cannot be declared as a generator.
╭─[typescript/tests/cases/conformance/es6/yieldExpressions/generatorOverloads3.ts:3:7]
2 │ *f(s: string): Iterable<any>;
3 │ *f(s: number): Iterable<any>;
· ───────────────────────────
4 │ *f(s: any): Iterable<any> { }
╰────
× A 'yield' expression is only allowed in a generator body.
╭─[typescript/tests/cases/conformance/es6/yieldExpressions/generatorTypeCheck32.ts:2:29]
1 │ var s: string;