Skip to content

Commit 2c53a72

Browse files
committed
fix(transformer/using): correctly reparent scopes in for of stmt (oxc-project#9960)
1 parent 5983760 commit 2c53a72

File tree

4 files changed

+55
-20
lines changed

4 files changed

+55
-20
lines changed

crates/oxc_transformer/src/proposals/explicit_resource_management.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,11 @@ impl<'a> Traverse<'a> for ExplicitResourceManagement<'a, '_> {
115115

116116
let scope_id = match &mut for_of_stmt.body {
117117
Statement::BlockStatement(block) => block.scope_id(),
118-
_ => ctx.create_child_scope(for_of_stmt_scope_id, ScopeFlags::empty()),
118+
_ => ctx.insert_scope_below_statement_from_scope_id(
119+
&for_of_stmt.body,
120+
for_of_stmt.scope_id(),
121+
ScopeFlags::empty(),
122+
),
119123
};
120124
ctx.scoping_mut().set_symbol_scope_id(for_of_init_symbol_id, scope_id);
121125
ctx.scoping_mut().move_binding(for_of_stmt_scope_id, scope_id, &for_of_init_name);

crates/oxc_traverse/src/context/mod.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,25 @@ impl<'a> TraverseCtx<'a> {
261261
self.scoping.insert_scope_below_statement(stmt, flags)
262262
}
263263

264+
/// Insert a scope into scope tree below a statement.
265+
///
266+
/// Statement must be in provided scope.
267+
/// New scope is created as child of the provided scope.
268+
/// All child scopes of the statement are reassigned to be children of the new scope.
269+
///
270+
/// `flags` provided are amended to inherit from parent scope's flags.
271+
///
272+
/// This is a shortcut for `ctx.scoping.insert_scope_below_statement_from_scope_id`.
273+
#[inline]
274+
pub fn insert_scope_below_statement_from_scope_id(
275+
&mut self,
276+
stmt: &Statement,
277+
scope_id: ScopeId,
278+
flags: ScopeFlags,
279+
) -> ScopeId {
280+
self.scoping.insert_scope_below_statement_from_scope_id(stmt, scope_id, flags)
281+
}
282+
264283
/// Insert a scope into scope tree below an expression.
265284
///
266285
/// Expression must be in current scope.

crates/oxc_traverse/src/context/scoping.rs

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,25 @@ impl TraverseScoping {
9999
pub fn insert_scope_below_statement(&mut self, stmt: &Statement, flags: ScopeFlags) -> ScopeId {
100100
let mut collector = ChildScopeCollector::new();
101101
collector.visit_statement(stmt);
102-
self.insert_scope_below(&collector.scope_ids, flags)
102+
self.insert_scope_below(self.current_scope_id, &collector.scope_ids, flags)
103+
}
104+
105+
/// Insert a scope into scope tree below a statement.
106+
///
107+
/// Statement must be in provided scope.
108+
/// New scope is created as child of the provided scope.
109+
/// All child scopes of the statement are reassigned to be children of the new scope.
110+
///
111+
/// `flags` provided are amended to inherit from parent scope's flags.
112+
pub fn insert_scope_below_statement_from_scope_id(
113+
&mut self,
114+
stmt: &Statement,
115+
scope_id: ScopeId,
116+
flags: ScopeFlags,
117+
) -> ScopeId {
118+
let mut collector = ChildScopeCollector::new();
119+
collector.visit_statement(stmt);
120+
self.insert_scope_below(scope_id, &collector.scope_ids, flags)
103121
}
104122

105123
/// Insert a scope into scope tree below an expression.
@@ -116,7 +134,7 @@ impl TraverseScoping {
116134
) -> ScopeId {
117135
let mut collector = ChildScopeCollector::new();
118136
collector.visit_expression(expr);
119-
self.insert_scope_below(&collector.scope_ids, flags)
137+
self.insert_scope_below(self.current_scope_id, &collector.scope_ids, flags)
120138
}
121139

122140
/// Insert a scope into scope tree below a `Vec` of statements.
@@ -133,17 +151,22 @@ impl TraverseScoping {
133151
) -> ScopeId {
134152
let mut collector = ChildScopeCollector::new();
135153
collector.visit_statements(stmts);
136-
self.insert_scope_below(&collector.scope_ids, flags)
154+
self.insert_scope_below(self.current_scope_id, &collector.scope_ids, flags)
137155
}
138156

139-
fn insert_scope_below(&mut self, child_scope_ids: &[ScopeId], flags: ScopeFlags) -> ScopeId {
157+
fn insert_scope_below(
158+
&mut self,
159+
scope_id: ScopeId,
160+
child_scope_ids: &[ScopeId],
161+
flags: ScopeFlags,
162+
) -> ScopeId {
140163
// Remove these scopes from parent's children
141164
if self.scoping.has_scope_child_ids() {
142-
self.scoping.remove_child_scopes(self.current_scope_id, child_scope_ids);
165+
self.scoping.remove_child_scopes(scope_id, child_scope_ids);
143166
}
144167

145168
// Create new scope as child of parent
146-
let new_scope_id = self.create_child_scope_of_current(flags);
169+
let new_scope_id = self.create_child_scope(scope_id, flags);
147170

148171
// Set scopes as children of new scope instead
149172
for &child_id in child_scope_ids {

tasks/transform_conformance/snapshots/oxc.snap.md

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
commit: 578ac4df
22

3-
Passed: 139/229
3+
Passed: 140/229
44

55
# All Passed:
66
* babel-plugin-transform-class-static-block
@@ -315,21 +315,10 @@ x Output mismatch
315315
x Output mismatch
316316

317317

318-
# babel-plugin-proposal-explicit-resource-management (0/3)
318+
# babel-plugin-proposal-explicit-resource-management (1/3)
319319
* export-class-name/input.js
320320
x Output mismatch
321321

322-
* for-of-no-block/input.js
323-
Scope children mismatch:
324-
after transform: ScopeId(1): [ScopeId(2), ScopeId(3), ScopeId(4), ScopeId(5), ScopeId(7)]
325-
rebuilt : ScopeId(1): [ScopeId(2), ScopeId(3), ScopeId(5), ScopeId(7)]
326-
Scope children mismatch:
327-
after transform: ScopeId(4): []
328-
rebuilt : ScopeId(3): [ScopeId(4)]
329-
Scope parent mismatch:
330-
after transform: ScopeId(3): Some(ScopeId(1))
331-
rebuilt : ScopeId(4): Some(ScopeId(3))
332-
333322
* function-with-scopes-in-params/input.js
334323
Bindings mismatch:
335324
after transform: ScopeId(1): ["_usingCtx", "a", "b", "x", "y"]

0 commit comments

Comments
 (0)