diff --git a/crates/oxc_semantic/src/scope.rs b/crates/oxc_semantic/src/scope.rs index 56498c12f32903..be50b57fba9128 100644 --- a/crates/oxc_semantic/src/scope.rs +++ b/crates/oxc_semantic/src/scope.rs @@ -165,6 +165,7 @@ impl ScopeTree { pub fn set_parent_id(&mut self, scope_id: ScopeId, parent_id: Option) { self.parent_ids[scope_id] = parent_id; if self.build_child_ids { + // Set this scope as child of parent scope if let Some(parent_id) = parent_id { self.child_ids[parent_id].push(scope_id); } @@ -247,12 +248,24 @@ impl ScopeTree { &mut self.bindings[scope_id] } + /// Return whether this `ScopeTree` has child IDs recorded + #[inline] + pub fn has_child_ids(&self) -> bool { + self.build_child_ids + } + /// Get the child scopes of a scope #[inline] pub fn get_child_ids(&self, scope_id: ScopeId) -> &[ScopeId] { &self.child_ids[scope_id] } + /// Get a mutable reference to a scope's children + #[inline] + pub fn get_child_ids_mut(&mut self, scope_id: ScopeId) -> &mut Vec { + &mut self.child_ids[scope_id] + } + /// Create a scope. #[inline] pub fn add_scope( diff --git a/crates/oxc_traverse/src/context/scoping.rs b/crates/oxc_traverse/src/context/scoping.rs index 05f54633b4cf8a..2ad9c60b268005 100644 --- a/crates/oxc_traverse/src/context/scoping.rs +++ b/crates/oxc_traverse/src/context/scoping.rs @@ -119,6 +119,12 @@ impl TraverseScoping { } fn insert_scope_below(&mut self, child_scope_ids: &[ScopeId], flags: ScopeFlags) -> ScopeId { + // Remove these scopes from parent's children + if self.scopes.has_child_ids() { + let current_child_scope_ids = self.scopes.get_child_ids_mut(self.current_scope_id); + current_child_scope_ids.retain(|scope_id| !child_scope_ids.contains(scope_id)); + } + // Create new scope as child of parent let new_scope_id = self.create_child_scope_of_current(flags);