diff --git a/crates/oxc_transformer/src/proposals/explicit_resource_management.rs b/crates/oxc_transformer/src/proposals/explicit_resource_management.rs index b8437536fd9bd..1cade3e47b90b 100644 --- a/crates/oxc_transformer/src/proposals/explicit_resource_management.rs +++ b/crates/oxc_transformer/src/proposals/explicit_resource_management.rs @@ -115,7 +115,11 @@ impl<'a> Traverse<'a> for ExplicitResourceManagement<'a, '_> { let scope_id = match &mut for_of_stmt.body { Statement::BlockStatement(block) => block.scope_id(), - _ => ctx.create_child_scope(for_of_stmt_scope_id, ScopeFlags::empty()), + _ => ctx.insert_scope_below_statement_from_scope_id( + &for_of_stmt.body, + for_of_stmt.scope_id(), + ScopeFlags::empty(), + ), }; ctx.scoping_mut().set_symbol_scope_id(for_of_init_symbol_id, scope_id); ctx.scoping_mut().move_binding(for_of_stmt_scope_id, scope_id, &for_of_init_name); diff --git a/crates/oxc_traverse/src/context/mod.rs b/crates/oxc_traverse/src/context/mod.rs index 7ba88f97b1105..08bf4db2771db 100644 --- a/crates/oxc_traverse/src/context/mod.rs +++ b/crates/oxc_traverse/src/context/mod.rs @@ -261,6 +261,25 @@ impl<'a> TraverseCtx<'a> { self.scoping.insert_scope_below_statement(stmt, flags) } + /// Insert a scope into scope tree below a statement. + /// + /// Statement must be in provided scope. + /// New scope is created as child of the provided scope. + /// All child scopes of the statement are reassigned to be children of the new scope. + /// + /// `flags` provided are amended to inherit from parent scope's flags. + /// + /// This is a shortcut for `ctx.scoping.insert_scope_below_statement_from_scope_id`. + #[inline] + pub fn insert_scope_below_statement_from_scope_id( + &mut self, + stmt: &Statement, + scope_id: ScopeId, + flags: ScopeFlags, + ) -> ScopeId { + self.scoping.insert_scope_below_statement_from_scope_id(stmt, scope_id, flags) + } + /// Insert a scope into scope tree below an expression. /// /// Expression must be in current scope. diff --git a/crates/oxc_traverse/src/context/scoping.rs b/crates/oxc_traverse/src/context/scoping.rs index cb3e1778fc6b5..7d16977ddc30a 100644 --- a/crates/oxc_traverse/src/context/scoping.rs +++ b/crates/oxc_traverse/src/context/scoping.rs @@ -99,7 +99,25 @@ impl TraverseScoping { pub fn insert_scope_below_statement(&mut self, stmt: &Statement, flags: ScopeFlags) -> ScopeId { let mut collector = ChildScopeCollector::new(); collector.visit_statement(stmt); - self.insert_scope_below(&collector.scope_ids, flags) + self.insert_scope_below(self.current_scope_id, &collector.scope_ids, flags) + } + + /// Insert a scope into scope tree below a statement. + /// + /// Statement must be in provided scope. + /// New scope is created as child of the provided scope. + /// All child scopes of the statement are reassigned to be children of the new scope. + /// + /// `flags` provided are amended to inherit from parent scope's flags. + pub fn insert_scope_below_statement_from_scope_id( + &mut self, + stmt: &Statement, + scope_id: ScopeId, + flags: ScopeFlags, + ) -> ScopeId { + let mut collector = ChildScopeCollector::new(); + collector.visit_statement(stmt); + self.insert_scope_below(scope_id, &collector.scope_ids, flags) } /// Insert a scope into scope tree below an expression. @@ -116,7 +134,7 @@ impl TraverseScoping { ) -> ScopeId { let mut collector = ChildScopeCollector::new(); collector.visit_expression(expr); - self.insert_scope_below(&collector.scope_ids, flags) + self.insert_scope_below(self.current_scope_id, &collector.scope_ids, flags) } /// Insert a scope into scope tree below a `Vec` of statements. @@ -133,17 +151,22 @@ impl TraverseScoping { ) -> ScopeId { let mut collector = ChildScopeCollector::new(); collector.visit_statements(stmts); - self.insert_scope_below(&collector.scope_ids, flags) + self.insert_scope_below(self.current_scope_id, &collector.scope_ids, flags) } - fn insert_scope_below(&mut self, child_scope_ids: &[ScopeId], flags: ScopeFlags) -> ScopeId { + fn insert_scope_below( + &mut self, + scope_id: ScopeId, + child_scope_ids: &[ScopeId], + flags: ScopeFlags, + ) -> ScopeId { // Remove these scopes from parent's children if self.scoping.has_scope_child_ids() { - self.scoping.remove_child_scopes(self.current_scope_id, child_scope_ids); + self.scoping.remove_child_scopes(scope_id, child_scope_ids); } // Create new scope as child of parent - let new_scope_id = self.create_child_scope_of_current(flags); + let new_scope_id = self.create_child_scope(scope_id, flags); // Set scopes as children of new scope instead for &child_id in child_scope_ids { diff --git a/tasks/transform_conformance/snapshots/oxc.snap.md b/tasks/transform_conformance/snapshots/oxc.snap.md index 0d62a20647819..c3e400a25e771 100644 --- a/tasks/transform_conformance/snapshots/oxc.snap.md +++ b/tasks/transform_conformance/snapshots/oxc.snap.md @@ -1,6 +1,6 @@ commit: 578ac4df -Passed: 139/229 +Passed: 140/229 # All Passed: * babel-plugin-transform-class-static-block @@ -315,21 +315,10 @@ x Output mismatch x Output mismatch -# babel-plugin-proposal-explicit-resource-management (0/3) +# babel-plugin-proposal-explicit-resource-management (1/3) * export-class-name/input.js x Output mismatch -* for-of-no-block/input.js -Scope children mismatch: -after transform: ScopeId(1): [ScopeId(2), ScopeId(3), ScopeId(4), ScopeId(5), ScopeId(7)] -rebuilt : ScopeId(1): [ScopeId(2), ScopeId(3), ScopeId(5), ScopeId(7)] -Scope children mismatch: -after transform: ScopeId(4): [] -rebuilt : ScopeId(3): [ScopeId(4)] -Scope parent mismatch: -after transform: ScopeId(3): Some(ScopeId(1)) -rebuilt : ScopeId(4): Some(ScopeId(3)) - * function-with-scopes-in-params/input.js Bindings mismatch: after transform: ScopeId(1): ["_usingCtx", "a", "b", "x", "y"]