Skip to content

fix(transformer): replace ambient dot defines#23231

Merged
graphite-app[bot] merged 1 commit into
mainfrom
codex/fix-ambient-dot-defines
Jun 11, 2026
Merged

fix(transformer): replace ambient dot defines#23231
graphite-app[bot] merged 1 commit into
mainfrom
codex/fix-ambient-dot-defines

Conversation

@camc314

@camc314 camc314 commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Summary

Dot define replacement now treats ambient TypeScript declarations as replaceable global roots. This fixes cases like service worker code that declares self for type checking while still expecting self.__WB_MANIFEST to be replaced.

Before this change, dot defines only matched when the root identifier was unresolved/global:

foo.bar

would replace only if foo had no local symbol. In the bug case:

declare let self: ServiceWorkerGlobalScope;
precacheAndRoute(self.__WB_MANIFEST);

semantic analysis resolves self to the local declare let self symbol, so ident.is_global_reference(scoping) returned false and self.__WB_MANIFEST was treated as shadowed.

The new helper still allows true globals, but also allows symbols marked ambient:

.is_none_or(|symbol_id| scoping.symbol_flags(symbol_id).is_ambient())

That means:

  • unresolved self -> replace
  • declare let self -> replace, because it is TypeScript-only and not a runtime binding
  • let self or function parameter self -> do not replace, because those are real runtime shadows

So this fixes the bug without making dot defines scope-insensitive.

Fixes #23224

@camc314 camc314 marked this pull request as ready for review June 10, 2026 11:55
@camc314 camc314 requested a review from overlookmotel as a code owner June 10, 2026 11:55
Copilot AI review requested due to automatic review settings June 10, 2026 11:55
@camc314 camc314 requested a review from Dunqing as a code owner June 10, 2026 11:55
@codspeed-hq

codspeed-hq Bot commented Jun 10, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 52 untouched benchmarks
⏩ 19 skipped benchmarks1


Comparing codex/fix-ambient-dot-defines (614d742) with main (79cd905)

Open in CodSpeed

Footnotes

  1. 19 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes ReplaceGlobalDefines dot-define replacement to treat TypeScript ambient declarations (e.g. declare let self: ...) as replaceable global roots, matching esbuild/Vite behavior while still respecting true runtime shadowing.

Changes:

  • Introduces is_global_or_ambient_reference to treat unresolved references and ambient symbols as eligible define roots.
  • Switches dot-define matching and identifier-define replacement to use the new helper (instead of is_global_reference).
  • Adds an integration test for ambient declare let with dot-define replacement.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
crates/oxc_transformer_plugins/src/replace_global_defines.rs Adds and uses a helper to allow ambient TS symbols to behave like globals for define replacement roots.
crates/oxc_transformer_plugins/tests/integrations/replace_global_defines.rs Adds a test covering dot-define replacement when the root is introduced via declare let.

Comment thread crates/oxc_transformer_plugins/tests/integrations/replace_global_defines.rs Outdated
@camc314 camc314 added the A-formatter Area - Formatter label Jun 10, 2026
@sapphi-red sapphi-red added A-transformer Area - Transformer / Transpiler and removed A-formatter Area - Formatter labels Jun 10, 2026
@Dunqing Dunqing added the 0-merge Merge with Graphite Merge Queue label Jun 11, 2026

Dunqing commented Jun 11, 2026

Copy link
Copy Markdown
Member

Merge activity

  • Jun 11, 1:48 AM UTC: The merge label '0-merge' was detected. This PR will be added to the Graphite merge queue once it meets the requirements.
  • Jun 11, 1:48 AM UTC: Dunqing added this pull request to the Graphite merge queue.
  • Jun 11, 1:50 AM UTC: The Graphite merge queue couldn't merge this PR because it was not satisfying all requirements (Failed CI: 'Test Linux').
  • Jun 11, 7:04 AM UTC: The merge label '0-merge' was detected. This PR will be added to the Graphite merge queue once it meets the requirements.
  • Jun 11, 7:05 AM UTC: camc314 added this pull request to the Graphite merge queue.
  • Jun 11, 7:09 AM UTC: Merged by the Graphite merge queue.

graphite-app Bot pushed a commit that referenced this pull request Jun 11, 2026
## Summary

Dot define replacement now treats ambient TypeScript declarations as replaceable global roots. This fixes cases like service worker code that declares `self` for type checking while still expecting `self.__WB_MANIFEST` to be replaced.

Before this change, dot defines only matched when the root identifier was unresolved/global:

```ts
foo.bar
```

would replace only if `foo` had no local symbol. In the bug case:

```ts
declare let self: ServiceWorkerGlobalScope;
precacheAndRoute(self.__WB_MANIFEST);
```

semantic analysis resolves `self` to the local `declare let self` symbol, so `ident.is_global_reference(scoping)` returned `false` and `self.__WB_MANIFEST` was treated as shadowed.

The new helper still allows true globals, but also allows symbols marked ambient:

```rust
.is_none_or(|symbol_id| scoping.symbol_flags(symbol_id).is_ambient())
```

That means:

- unresolved `self` -> replace
- `declare let self` -> replace, because it is TypeScript-only and not a runtime binding
- `let self` or function parameter `self` -> do not replace, because those are real runtime shadows

So this fixes the bug without making dot defines scope-insensitive.

Fixes #23224
@graphite-app graphite-app Bot force-pushed the codex/fix-ambient-dot-defines branch from ae1007e to 053af85 Compare June 11, 2026 01:49
@graphite-app graphite-app Bot removed the 0-merge Merge with Graphite Merge Queue label Jun 11, 2026
@camc314 camc314 added the 0-merge Merge with Graphite Merge Queue label Jun 11, 2026
## Summary

Dot define replacement now treats ambient TypeScript declarations as replaceable global roots. This fixes cases like service worker code that declares `self` for type checking while still expecting `self.__WB_MANIFEST` to be replaced.

Before this change, dot defines only matched when the root identifier was unresolved/global:

```ts
foo.bar
```

would replace only if `foo` had no local symbol. In the bug case:

```ts
declare let self: ServiceWorkerGlobalScope;
precacheAndRoute(self.__WB_MANIFEST);
```

semantic analysis resolves `self` to the local `declare let self` symbol, so `ident.is_global_reference(scoping)` returned `false` and `self.__WB_MANIFEST` was treated as shadowed.

The new helper still allows true globals, but also allows symbols marked ambient:

```rust
.is_none_or(|symbol_id| scoping.symbol_flags(symbol_id).is_ambient())
```

That means:

- unresolved `self` -> replace
- `declare let self` -> replace, because it is TypeScript-only and not a runtime binding
- `let self` or function parameter `self` -> do not replace, because those are real runtime shadows

So this fixes the bug without making dot defines scope-insensitive.

Fixes #23224
@graphite-app graphite-app Bot force-pushed the codex/fix-ambient-dot-defines branch from 614d742 to 52d0c31 Compare June 11, 2026 07:06
@graphite-app graphite-app Bot merged commit 52d0c31 into main Jun 11, 2026
29 checks passed
@graphite-app graphite-app Bot removed the 0-merge Merge with Graphite Merge Queue label Jun 11, 2026
@graphite-app graphite-app Bot deleted the codex/fix-ambient-dot-defines branch June 11, 2026 07:09
Boshen added a commit that referenced this pull request Jun 15, 2026
### 💥 BREAKING CHANGES

- 7a24911 codegen: [**BREAKING**] Borrow sourcemaps from codegen
(#23422) (Boshen)
- bb0ed44 transformer: [**BREAKING**] Disable styled-components
transpileTemplateLiterals by default (#23171) (Boshen)

### 🚀 Features

- 1490a0a linter/react: Implement react-compiler rule (#23202) (Boshen)
- 6c0bdf0 transformer/react-refresh: Support `module.property.useHook()`
(#23190) (Dunqing)
- 47991bd semantic: Report TS1228 for invalid type predicates (#23174)
(camc314)
- 1d3af58 parser: Add TS2398 parameter property diagnostic (#23216)
(camc314)
- 44313da semantic: Add `scope_is_descendant_of` api (#22313) (camc314)
- e5050c0 parser: Improve diagnostic for rest initializer (#23205)
(camc314)
- ec266bb transformer: Run React Compiler as a feature-gated transform
pass (#23201) (Boshen)
- e7374fe parser: Report error for `const` modifier on interface type
parameter (#23173) (camc314)
- a7c1c9b parser: Report ambient definite variable assertions (#23165)
(camc314)
- d169fcd parser: Report invalid class definite assertions (#23164)
(camc314)
- 00244d8 parser: Report definite property initializer errors (#23160)
(camc314)

### 🐛 Bug Fixes

- 52d0c31 transformer: Replace ambient dot defines (#23231) (camc314)
- 2c28748 transformer/class: Parent generated constructors to class
scope (#23222) (camc314)
- 8edd234 parser: Report accessor definite assertion on token (#23203)
(camc314)
- de38a3f react_compiler: Keep imports referenced only by a local
re-export (#23176) (Boshen)
- f5721c2 codegen: Preserve parentheses around `intrinsic` type
reference (#23156) (Boshen)
- e89f81d parser: Don't emit TS1477 for parenthesized instantiation
expression (#23147) (Boshen)
- 8a04149 parser: Reject module-referencing imports/exports in a
namespace body (#22829) (Boshen)

### ⚡ Performance

- 2783295 parser: Table-driven operator precedence lookup (#23346)
(Boshen)
- 231d5de parser: Single-match member expression dispatch (#23347)
(Boshen)
- e89729b codegen: Accept one-shot wrap closures (#23265) (camc314)
- a6c11fa parser: Force-inline read_non_decimal to fold per-digit number
dispatch (#23157) (Boshen)
- d74964c parser: Store class definite assertion offset (#23170)
(camc314)
- f0fda4d parser: Shrink-wrap cold diagnostic tails out of hot frames
(#23159) (Boshen)
- a082180 parser: Store definite assertion offset (#23167) (camc314)
- 534f9c6 oxc: Conditionally rebuild semantic in compiler pipeline
(#23153) (Boshen)
- b435c6a parser: Skip checkpoint for `infer T extends U` constraint in
disallow context (#23128) (Boshen)
- 7464dce parser: Peek instead of checkpoint/rewind for `export default`
modifier (#23124) (Boshen)
- 80a9a32 parser: Fast-path single-keyword TS declarations (#23083)
(Boshen)
- da1a6c6 diagnostics: Migrate to allocation-optimized oxc-miette
(#23094) (Boshen)
- b7b08ce parser: Peek once for the static modifier disambiguation
(#23079) (Boshen)
- e7e07a3 parser: Fold unary dispatch into a single match (#23076)
(Boshen)

### 📚 Documentation

- d241add semantic: Add `AGENTS.md` test guidance for agents (#23441)
(camc314)
- 026f1ae parser: Add `AGENTS.md` test guidance for agents (#23440)
(camc314)
- 09755ac transformer: Add `AGENTS.md` test guidance for agents (#23439)
(camc314)
- e6bdfd4 lexer: Correct reference link for `byte_handlers!` (#23313)
(Dunqing)
- 65b6d7a allocator: Fix memory leaks in `Arena` examples (#23257)
(overlookmotel)

Co-authored-by: Boshen <1430279+Boshen@users.noreply.github.com>
camc314 added a commit that referenced this pull request Jul 3, 2026
## Summary

Dot define replacement now treats ambient TypeScript declarations as replaceable global roots. This fixes cases like service worker code that declares `self` for type checking while still expecting `self.__WB_MANIFEST` to be replaced.

Before this change, dot defines only matched when the root identifier was unresolved/global:

```ts
foo.bar
```

would replace only if `foo` had no local symbol. In the bug case:

```ts
declare let self: ServiceWorkerGlobalScope;
precacheAndRoute(self.__WB_MANIFEST);
```

semantic analysis resolves `self` to the local `declare let self` symbol, so `ident.is_global_reference(scoping)` returned `false` and `self.__WB_MANIFEST` was treated as shadowed.

The new helper still allows true globals, but also allows symbols marked ambient:

```rust
.is_none_or(|symbol_id| scoping.symbol_flags(symbol_id).is_ambient())
```

That means:

- unresolved `self` -> replace
- `declare let self` -> replace, because it is TypeScript-only and not a runtime binding
- `let self` or function parameter `self` -> do not replace, because those are real runtime shadows

So this fixes the bug without making dot defines scope-insensitive.

Fixes #23224
camc314 pushed a commit that referenced this pull request Jul 3, 2026
### 💥 BREAKING CHANGES

- 7a24911 codegen: [**BREAKING**] Borrow sourcemaps from codegen
(#23422) (Boshen)
- bb0ed44 transformer: [**BREAKING**] Disable styled-components
transpileTemplateLiterals by default (#23171) (Boshen)

### 🚀 Features

- 1490a0a linter/react: Implement react-compiler rule (#23202) (Boshen)
- 6c0bdf0 transformer/react-refresh: Support `module.property.useHook()`
(#23190) (Dunqing)
- 47991bd semantic: Report TS1228 for invalid type predicates (#23174)
(camc314)
- 1d3af58 parser: Add TS2398 parameter property diagnostic (#23216)
(camc314)
- 44313da semantic: Add `scope_is_descendant_of` api (#22313) (camc314)
- e5050c0 parser: Improve diagnostic for rest initializer (#23205)
(camc314)
- ec266bb transformer: Run React Compiler as a feature-gated transform
pass (#23201) (Boshen)
- e7374fe parser: Report error for `const` modifier on interface type
parameter (#23173) (camc314)
- a7c1c9b parser: Report ambient definite variable assertions (#23165)
(camc314)
- d169fcd parser: Report invalid class definite assertions (#23164)
(camc314)
- 00244d8 parser: Report definite property initializer errors (#23160)
(camc314)

### 🐛 Bug Fixes

- 52d0c31 transformer: Replace ambient dot defines (#23231) (camc314)
- 2c28748 transformer/class: Parent generated constructors to class
scope (#23222) (camc314)
- 8edd234 parser: Report accessor definite assertion on token (#23203)
(camc314)
- de38a3f react_compiler: Keep imports referenced only by a local
re-export (#23176) (Boshen)
- f5721c2 codegen: Preserve parentheses around `intrinsic` type
reference (#23156) (Boshen)
- e89f81d parser: Don't emit TS1477 for parenthesized instantiation
expression (#23147) (Boshen)
- 8a04149 parser: Reject module-referencing imports/exports in a
namespace body (#22829) (Boshen)

### ⚡ Performance

- 2783295 parser: Table-driven operator precedence lookup (#23346)
(Boshen)
- 231d5de parser: Single-match member expression dispatch (#23347)
(Boshen)
- e89729b codegen: Accept one-shot wrap closures (#23265) (camc314)
- a6c11fa parser: Force-inline read_non_decimal to fold per-digit number
dispatch (#23157) (Boshen)
- d74964c parser: Store class definite assertion offset (#23170)
(camc314)
- f0fda4d parser: Shrink-wrap cold diagnostic tails out of hot frames
(#23159) (Boshen)
- a082180 parser: Store definite assertion offset (#23167) (camc314)
- 534f9c6 oxc: Conditionally rebuild semantic in compiler pipeline
(#23153) (Boshen)
- b435c6a parser: Skip checkpoint for `infer T extends U` constraint in
disallow context (#23128) (Boshen)
- 7464dce parser: Peek instead of checkpoint/rewind for `export default`
modifier (#23124) (Boshen)
- 80a9a32 parser: Fast-path single-keyword TS declarations (#23083)
(Boshen)
- da1a6c6 diagnostics: Migrate to allocation-optimized oxc-miette
(#23094) (Boshen)
- b7b08ce parser: Peek once for the static modifier disambiguation
(#23079) (Boshen)
- e7e07a3 parser: Fold unary dispatch into a single match (#23076)
(Boshen)

### 📚 Documentation

- d241add semantic: Add `AGENTS.md` test guidance for agents (#23441)
(camc314)
- 026f1ae parser: Add `AGENTS.md` test guidance for agents (#23440)
(camc314)
- 09755ac transformer: Add `AGENTS.md` test guidance for agents (#23439)
(camc314)
- e6bdfd4 lexer: Correct reference link for `byte_handlers!` (#23313)
(Dunqing)
- 65b6d7a allocator: Fix memory leaks in `Arena` examples (#23257)
(overlookmotel)

Co-authored-by: Boshen <1430279+Boshen@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-transformer Area - Transformer / Transpiler

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(transformer): ambient declare should not block dot define replacement

4 participants