diff --git a/crates/oxc_semantic/src/post_transform_checker.rs b/crates/oxc_semantic/src/post_transform_checker.rs index 3c909061be4b79..075840105d2b02 100644 --- a/crates/oxc_semantic/src/post_transform_checker.rs +++ b/crates/oxc_semantic/src/post_transform_checker.rs @@ -421,11 +421,11 @@ impl<'s> PostTransformChecker<'s> { } // Check children match - let child_ids = self - .get_pair(scope_ids, |data, scope_id| data.scopes.get_child_ids(scope_id).to_vec()); - if self.remap_scope_ids_sets(&child_ids).is_mismatch() { - self.errors.push_mismatch("Scope children mismatch", scope_ids, child_ids); - } + // let child_ids = self + // .get_pair(scope_ids, |data, scope_id| data.scopes.get_child_ids(scope_id).to_vec()); + // if self.remap_scope_ids_sets(&child_ids).is_mismatch() { + // self.errors.push_mismatch("Scope children mismatch", scope_ids, child_ids); + // } // NB: Skip checking node IDs match - transformer does not set `AstNodeId`s } diff --git a/crates/oxc_semantic/src/scope.rs b/crates/oxc_semantic/src/scope.rs index 746cb5db0466c2..cadc8433dc9081 100644 --- a/crates/oxc_semantic/src/scope.rs +++ b/crates/oxc_semantic/src/scope.rs @@ -28,8 +28,6 @@ pub type UnresolvedReferences = FxHashMap>; pub struct ScopeTree { /// Maps a scope to the parent scope it belongs in. parent_ids: IndexVec>, - /// Maps a scope to direct children scopes. - child_ids: IndexVec>, /// Maps a scope to its node id. node_ids: IndexVec, flags: IndexVec, @@ -67,46 +65,6 @@ impl ScopeTree { std::iter::successors(Some(scope_id), |scope_id| self.parent_ids[*scope_id]) } - /// Iterate over scopes contained by a scope in breadth-first order. - /// - /// Unlike [`ancestors`], this iterator will not include the scope itself. - /// - /// [`ancestors`]: ScopeTree::ancestors - pub fn descendants(&self, scope_id: ScopeId) -> impl Iterator + '_ { - // Has to be a `fn` and pass arguments because we can't - // have recursive closures - fn add_to_list( - parent_id: ScopeId, - child_ids: &IndexVec>, - items: &mut Vec, - ) { - if let Some(children) = child_ids.get(parent_id) { - for child_id in children { - items.push(*child_id); - add_to_list(*child_id, child_ids, items); - } - } - } - - let mut list = vec![]; - - add_to_list(scope_id, &self.child_ids, &mut list); - - list.into_iter() - } - - /// 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] - } - pub fn descendants_from_root(&self) -> impl Iterator + '_ { self.parent_ids.iter_enumerated().map(|(scope_id, _)| scope_id) } @@ -173,9 +131,6 @@ impl ScopeTree { pub fn set_parent_id(&mut self, scope_id: ScopeId, parent_id: Option) { self.parent_ids[scope_id] = parent_id; - if let Some(parent_id) = parent_id { - self.child_ids[parent_id].push(scope_id); - } } /// Get a variable binding by name that was declared in the top-level scope @@ -266,12 +221,7 @@ impl ScopeTree { node_id: AstNodeId, flags: ScopeFlags, ) -> ScopeId { - let scope_id = self.add_scope_impl(Some(parent_id), node_id, flags); - - // Set this scope as child of parent scope - self.child_ids[parent_id].push(scope_id); - - scope_id + self.add_scope_impl(Some(parent_id), node_id, flags) } /// Create the root [`Program`] scope. @@ -295,7 +245,6 @@ impl ScopeTree { flags: ScopeFlags, ) -> ScopeId { let scope_id = self.parent_ids.push(parent_id); - self.child_ids.push(vec![]); self.flags.push(flags); self.bindings.push(Bindings::default()); self.node_ids.push(node_id); @@ -317,7 +266,6 @@ impl ScopeTree { /// Reserve memory for an `additional` number of scopes. pub fn reserve(&mut self, additional: usize) { self.parent_ids.reserve(additional); - self.child_ids.reserve(additional); self.flags.reserve(additional); self.bindings.reserve(additional); self.node_ids.reserve(additional); diff --git a/crates/oxc_traverse/src/context/scoping.rs b/crates/oxc_traverse/src/context/scoping.rs index 92e899552125b7..4150adac3508d8 100644 --- a/crates/oxc_traverse/src/context/scoping.rs +++ b/crates/oxc_traverse/src/context/scoping.rs @@ -119,10 +119,6 @@ impl TraverseScoping { } fn insert_scope_below(&mut self, child_scope_ids: &[ScopeId], flags: ScopeFlags) -> ScopeId { - // Remove these scopes from parent's children - 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); diff --git a/crates/oxc_wasm/src/lib.rs b/crates/oxc_wasm/src/lib.rs index 36094186e50571..6f1a8a912aa7bf 100644 --- a/crates/oxc_wasm/src/lib.rs +++ b/crates/oxc_wasm/src/lib.rs @@ -331,13 +331,21 @@ impl Oxc { ) { let space = " ".repeat(depth * 2); + let scope_tree = semantic.scopes(); for scope_id in scope_ids { - let flags = semantic.scopes().get_flags(*scope_id); - let next_scope_ids = semantic.scopes().get_child_ids(*scope_id); + let flags = scope_tree.get_flags(*scope_id); + let child_scope_ids = scope_tree + .descendants_from_root() + .filter(|id| { + scope_tree + .get_parent_id(*id) + .is_some_and(|parent_id| parent_id == *scope_id) + }) + .collect::>(); scope_text .push_str(&format!("{space}Scope{:?} ({flags:?}) {{\n", scope_id.index() + 1)); - let bindings = semantic.scopes().get_bindings(*scope_id); + let bindings = scope_tree.get_bindings(*scope_id); let binding_space = " ".repeat((depth + 1) * 2); if !bindings.is_empty() { scope_text.push_str(&format!("{binding_space}Bindings: {{")); @@ -350,7 +358,7 @@ impl Oxc { scope_text.push_str(&format!("\n{binding_space}}}\n")); } - write_scope_text(semantic, scope_text, depth + 1, next_scope_ids); + write_scope_text(semantic, scope_text, depth + 1, &child_scope_ids); scope_text.push_str(&format!("{space}}}\n")); } }