fix(transformer/explicit-resource-managment): preserve shadowed for-head block#22451
Conversation
Merging this PR will not alter performance
Comparing Footnotes
|
There was a problem hiding this comment.
Pull request overview
Fixes an Explicit Resource Management transformer scoping bug where a for (using … of …) head binding could end up in the same lexical scope as a shadowing declaration in the loop body, producing invalid output (duplicate bindings).
Changes:
- Detect when the
forloop body scope already binds the same identifier as theusinghead binding, and wrap the original body in an additional block scope to preserve correct shadowing. - Adjust scope insertion / binding moves so the transformed AST and semantic scopes remain consistent for both block and non-block loop bodies.
- Update Babel conformance snapshots to reflect the newly passing fixture.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| tasks/transform_conformance/snapshots/babel.snap.md | Snapshot update reflecting one more passing Babel explicit-resource-management case. |
| crates/oxc_transformer/src/es2026/explicit_resource_management.rs | Adds scope-collision detection and wraps loop bodies to preserve correct shadowing and avoid redeclaration errors. |
Merge activity
|
…ead block (#22451) Given: ``` for (using x of y) { const x = z; } ``` Previously we would produce ``` var _usingCtx2 = require("@oxc-project/runtime/helpers/usingCtx"); for (const _x of y) try { var _usingCtx = _usingCtx2(); const x = _usingCtx.u(_x); const x = z; } catch (_) { _usingCtx.e = _; } finally { _usingCtx.d(); } ``` Now we produce ``` var _usingCtx2 = require("@oxc-project/runtime/helpers/usingCtx"); for (const _x of y) try { var _usingCtx = _usingCtx2(); const x = _usingCtx.u(_x); { const x = z; } } catch (_) { _usingCtx.e = _; } finally { _usingCtx.d(); } ``` Which avoids a syntax error - cannot create a duplicate var named `x`.
475448f to
3ce3431
Compare
### 🐛 Bug Fixes - 0f26de6 ecmascript: Resolve identifier value type via tracked constants (#22234) (Alexander Lichter) - c27a8cf minifier: Normalize `{ x: x }` shorthand so adjacent-if merge is idempotent (#22401) (Dunqing) - e431a0e parser: Break extends clause loop on fatal error (#22517) (Boshen) - e9ec7c6 minifier: Fold optional chains by base nullishness (#22236) (Alexander Lichter) - e6090e7 transformer: Keep enum IIFE when a non-inlinable value reference remains (#22501) (Dunqing) - 931b7d6 transformer: Inline const enum members through type-cast wrappers (#22500) (Dunqing) - b9615b2 codegen: Preserve string quotes in require() calls during minification (#22475) (zennnnnnn11) - c73c159 transformer/async-to-generator: Reparent parameter initializer scopes (#22507) (camc314) - ecfd3ca transformer/async-to-generator: Move only parameter bindings (#22503) (camc314) - 3ce3431 transformer/explicit-resource-managment: Preserve shadowed for-head block (#22451) (camc314) ### ⚡ Performance - ce92c6c semantic: `#[inline]` `Scoping::get_binding` (#22414) (Dunqing) - 98be95c regular_expression: Track regex flags via bitflags (#22427) (Boshen) - dbbc059 jsdoc: Skip should_attach_jsdoc when no remaining comments (#22409) (Boshen) - 217d7d8 minifier: Index `SymbolValues` by `SymbolId` (#22441) (Dunqing) - d782b78 minifier: Use BitSet for LiveUsageCollector live references (#22425) (Boshen)
Given:
Previously we would produce
Now we produce
Which avoids a syntax error - cannot create a duplicate var named
x.