Skip to content

fix(parser): reject function implementations in ambient contexts (TS1183)#22845

Merged
graphite-app[bot] merged 1 commit into
mainfrom
fix/implementation-in-ambient
May 30, 2026
Merged

fix(parser): reject function implementations in ambient contexts (TS1183)#22845
graphite-app[bot] merged 1 commit into
mainfrom
fix/implementation-in-ambient

Conversation

@Boshen

@Boshen Boshen commented May 30, 2026

Copy link
Copy Markdown
Member

A function declaration with a body is an implementation, which is not allowed in
an ambient context. oxc already emitted TS1183 ("An implementation cannot be
declared in ambient contexts") when the function carried its own declare
modifier, but missed functions that inherit the ambient context from an enclosing
declare module / declare namespace or a .d.ts file:

declare module "m" { function f() {} }   // now TS1183
declare namespace N { function f() {} }  // now TS1183
// foo.d.ts
function foo(): any {}                    // now TS1183

Bodyless signatures stay valid (declare module "m" { function f(): void; },
export declare function f(): void;).

The check now keys solely off ctx.has_ambient() instead of the function's own
declare modifier, scoped to function declarations. Class methods are excluded
because they are already validated in check_method_definition, which avoids a
duplicate diagnostic. This matches typescript-go's
checkGrammarStatementInAmbientContext / function-like body check, and babel.

The fast path is unchanged: has_ambient() is a cheap bitflag test that
short-circuits for all non-ambient code.

parser_babel +3 and parser_typescript +1 negative-pass; positive/AST stay 100%.

@github-actions github-actions Bot added the A-parser Area - Parser label May 30, 2026

Boshen commented May 30, 2026

Copy link
Copy Markdown
Member Author

How to use the Graphite Merge Queue

Add either label to this PR to merge it via the merge queue:

  • 0-merge - adds this PR to the back of the merge queue
  • hotfix - for urgent changes, fast-track this PR to the front of the merge queue

You must have a Graphite account in order to use the merge queue. Sign up using this link.

An organization admin has enabled the Graphite Merge Queue in this repository.

Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue.

This stack of pull requests is managed by Graphite. Learn more about stacking.

@Boshen Boshen marked this pull request as ready for review May 30, 2026 02:43
@codspeed-hq

codspeed-hq Bot commented May 30, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 57 untouched benchmarks


Comparing fix/implementation-in-ambient (2743ebe) with main (c645615)

Open in CodSpeed

@Boshen Boshen force-pushed the fix/implementation-in-ambient branch from df8e74c to 2743ebe Compare May 30, 2026 02:56
@Boshen Boshen requested a review from camc314 as a code owner May 30, 2026 02:56
@github-actions github-actions Bot added the A-linter Area - Linter label May 30, 2026
@Boshen Boshen added the 0-merge Merge with Graphite Merge Queue label May 30, 2026

Boshen commented May 30, 2026

Copy link
Copy Markdown
Member Author

Merge activity

…183) (#22845)

A function declaration with a body is an implementation, which is not allowed in
an ambient context. oxc already emitted TS1183 ("An implementation cannot be
declared in ambient contexts") when the function carried its own `declare`
modifier, but missed functions that inherit the ambient context from an enclosing
`declare module` / `declare namespace` or a `.d.ts` file:

    declare module "m" { function f() {} }   // now TS1183
    declare namespace N { function f() {} }  // now TS1183
    // foo.d.ts
    function foo(): any {}                    // now TS1183

Bodyless signatures stay valid (`declare module "m" { function f(): void; }`,
`export declare function f(): void;`).

The check now keys solely off `ctx.has_ambient()` instead of the function's own
`declare` modifier, scoped to function declarations. Class methods are excluded
because they are already validated in `check_method_definition`, which avoids a
duplicate diagnostic. This matches `typescript-go`'s
`checkGrammarStatementInAmbientContext` / function-like body check, and babel.

The fast path is unchanged: `has_ambient()` is a cheap bitflag test that
short-circuits for all non-ambient code.

parser_babel +3 and parser_typescript +1 negative-pass; positive/AST stay 100%.
@graphite-app graphite-app Bot force-pushed the fix/implementation-in-ambient branch from 2743ebe to 2eafea6 Compare May 30, 2026 03:15
@graphite-app graphite-app Bot merged commit 2eafea6 into main May 30, 2026
30 checks passed
@graphite-app graphite-app Bot removed the 0-merge Merge with Graphite Merge Queue label May 30, 2026
@graphite-app graphite-app Bot deleted the fix/implementation-in-ambient branch May 30, 2026 03:20
camc314 pushed a commit that referenced this pull request Jun 1, 2026
### 🚀 Features

- 9c71f2e ast, codegen, formatter: Add `WithClauseKeyword::as_str`
helper and use it (#22791) (camc314)

### 🐛 Bug Fixes

- cf5769c parser: Reject TypeScript declarations in single-statement
context (#22827) (Boshen)
- c360fb6 parser: Reject generators in ambient contexts and overload
signatures (TS1221/TS1222) (#22848) (Boshen)
- cc60d8d parser: Reject invalid index signature parameter types
(TS1268/TS1337) (#22852) (Boshen)
- 3d13e29 parser: Reject `declare` in an already-ambient context
(TS1038) (#22850) (Boshen)
- 5152854 parser: Reject statements in ambient contexts (TS1036)
(#22849) (Boshen)
- 4f9afc5 parser: Reject `export as namespace` inside a namespace body
(TS1316) (#22846) (Boshen)
- 2eafea6 parser: Reject function implementations in ambient contexts
(TS1183) (#22845) (Boshen)
- c645615 parser: Reject incompatible class member modifiers (#22843)
(Boshen)
- 276b78b parser: Reject module-referencing imports/exports in a
namespace body (#22836) (Boshen)
- 842ed1c parser: Parse `class implements` with `implements` as the
class name (#22801) (Boshen)

### ⚡ Performance

- 7e3a567 parser: Reuse cached token kind in delimited-list loops
(#22841) (Boshen)
- 9e741c2 parser: Use peek_token instead of lookahead on the modifier
path (#22842) (Boshen)
- 9e496a7 semantic: Defer declare lookup for empty accessors (#22810)
(camc314)
camc314 pushed a commit that referenced this pull request Jun 1, 2026
# Oxlint
### 🚀 Features

- e4b1f46 linter/typescript: Implement `method-signature-style` rule
(#22679) (Mikhail Baev)
- bc462ca linter/vue: Implement no-reserved-component-names rule
(#22741) (bab)
- ef9e751 linter/vue: Implement component-definition-name-casing rule
(#22818) (bab)
- d67f51a linter/vue: Implement require-prop-type-constructor rule
(#22708) (bab)
- 1444f82 linter/promise/spec-only: Add `Promise.try` to `Promise`
static methods (#22812) (Ben Saufley)
- 8422e8b linter/jsdoc: Implement `require-yields-description` rule
(#22805) (Mikhail Baev)
- fe93f97 linter/eslint: Implement `prefer-named-capture-group` rule
(#22759) (Sebastian Poxhofer)
- 1a7798b linter: Add suggestion for `unicorn/no-new-array` (#22682)
(Sysix)

### 🐛 Bug Fixes

- 760a9f9 linter: Report errors when writing to the filesystem (#22881)
(camc314)
- e5a2748 linter: Avoid no-unreachable false positive after conditional
loop (#22869) (camc314)
- 39d92d6 linter/arrow-body-style: Preserve comments within function
(#22854) (Sysix)
- 3d13e29 parser: Reject `declare` in an already-ambient context
(TS1038) (#22850) (Boshen)
- 5152854 parser: Reject statements in ambient contexts (TS1036)
(#22849) (Boshen)
- 2eafea6 parser: Reject function implementations in ambient contexts
(TS1183) (#22845) (Boshen)
- c645615 parser: Reject incompatible class member modifiers (#22843)
(Boshen)
- 4a1ca4a linter/export: Detect duplicate explicit exports (#22798)
(camc314)
- 0a9a735 linter/no-loop-func: Allow safe let closures (#22811)
(camc314)
- 1599f11 linter: Align lsp extends default plugins (#22788) (camc314)
- db32ec9 linter/no-accumulating-spread: Use loop as primary span
(#22800) (camc314)
- 33ec6b4 linter/consistent-test-it: Avoid adjacent describe leakage
(#22796) (camc314)
- 2606069 linter/no-array-sort: Unwrap parenthesized sort args (#22794)
(camc314)
- 9f2f709 linter/no-array-sort: Skip non compare fn sort arguments
(#22752) (Gaurav Dubey)
- 27268a0 linter/no-else-return: Preserve statement boundary in fixer
(#22687) (camc314)
- d9cb6d8 linter/no-empty-function: Allow functions callbacks with
`allow: functions` (#22764) (camc314)
- a40a314 linter/no-shadow-restricted-names: Ignore enum members
(#22762) (camc314)
- 82366d9 linter/no-cond-assign: Align ternary handling (#22761)
(camc314)

### 📚 Documentation

- 5e113ba linter: Add license notices for ported ESLint plugins (#22768)
(Boshen)
# Oxfmt
### 🚀 Features

- d75cbbf oxfmt: Format `parser:json` files by `oxc_formatter_json`
(#22709) (leaysgur)
- 49db054 formatter_json: Implement `oxc_formatter_json` (json variant
only) (#22641) (leaysgur)
- 9c71f2e ast, codegen, formatter: Add `WithClauseKeyword::as_str`
helper and use it (#22791) (camc314)

### 🐛 Bug Fixes

- d3cdd62 oxfmt: Skip formatting for whitespace-only file (#22780)
(leaysgur)
- 23f0cc8 formatter: Don't move comments inside variable declaration in
for in loop (#22776) (leaysgur)
- f200c40 formatter: Don't move comments inside variable declaration in
for of loop (#22773) (Leonabcd123)

### 📚 Documentation

- 845f393 oxfmt,formatter,formatter_json,formatter_core: Add/update
AGENTS.md (#22873) (leaysgur)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-linter Area - Linter A-parser Area - Parser

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant