fix(parser): reject statements in ambient contexts (TS1036)#22849
Conversation
How to use the Graphite Merge QueueAdd either label to this PR to merge it via 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. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 77029dc0ae
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Merging this PR will not alter performance
Comparing |
Merge activity
|
77029dc to
f61431c
Compare
A non-declaration statement (`if`/`for`/`while`/expression/`try`/block/etc.) is not
allowed directly inside an ambient block — a `.d.ts` top level or a `declare`
namespace/module body:
declare namespace M { while (true); } // now TS1036
// foo.d.ts
foo(); // now TS1036
declare namespace M { export const x = 1; } // declarations stay valid
namespace N { while (true); } // non-ambient namespace: valid
Implemented inline in `parse_directives_and_statements`. Ambient-ness is captured
once at block entry (`(is_top_level || in_ts_namespace_body) && has_ambient()`),
which excludes function bodies (they report TS1183 for the body instead) and keeps
non-ambient blocks unaffected. A statement is flagged when it is neither a
`Declaration` nor a `ModuleDeclaration` (so imports/exports keep their specific
namespace diagnostics). The error is reported once per block, matching tsc's
`checkGrammarStatementInAmbientContext`. The hot path is unchanged: `has_ambient()`
short-circuits for all non-ambient code.
Three linter fixtures used invalid ambient statements and are updated to valid TS:
`no_shadow` (`declare; foo5: boolean;` -> `declare var foo5: boolean;`),
`check_tag_names` (a `.d.ts` block -> `declare namespace`), and
`prefer_namespace_keyword` (an assignment in a module body -> an ambient binding).
parser_typescript +18 negative-pass; positive/AST stay 100%.
f61431c to
5152854
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 51528545ea
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
### 🚀 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)
# 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)

A non-declaration statement (
if/for/while/expression/try/block/etc.) is notallowed directly inside an ambient block — a
.d.tstop level or adeclarenamespace/module body:
Implemented inline in
parse_directives_and_statements. Ambient-ness is capturedonce at block entry (
(is_top_level || in_ts_namespace_body) && has_ambient()),which excludes function bodies (they report TS1183 for the body instead) and keeps
non-ambient blocks unaffected. A statement is flagged when it is neither a
Declarationnor aModuleDeclaration(so imports/exports keep their specificnamespace diagnostics). The error is reported once per block, matching tsc's
checkGrammarStatementInAmbientContext. The hot path is unchanged:has_ambient()short-circuits for all non-ambient code.
Three linter fixtures used invalid ambient statements and are updated to valid TS:
no_shadow(declare; foo5: boolean;->declare var foo5: boolean;),check_tag_names(a.d.tsblock ->declare namespace), andprefer_namespace_keyword(an assignment in a module body -> an ambient binding).parser_typescript +18 negative-pass; positive/AST stay 100%.