From 8548b324f17bb8f83bfe770a9394c1929928c191 Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Sun, 15 Jan 2023 21:23:49 -0600 Subject: [PATCH] fix dropping nested scopes --- packages/core/src/arena.rs | 42 ++++++++++---------------------- packages/core/src/diff.rs | 2 +- packages/core/src/nodes.rs | 8 ------ packages/core/src/virtual_dom.rs | 2 +- 4 files changed, 15 insertions(+), 39 deletions(-) diff --git a/packages/core/src/arena.rs b/packages/core/src/arena.rs index 39beaa490..75ef20ee1 100644 --- a/packages/core/src/arena.rs +++ b/packages/core/src/arena.rs @@ -88,7 +88,9 @@ impl VirtualDom { } // Drop a scope and all its children - pub(crate) fn drop_scope(&mut self, id: ScopeId) { + // + // Note: This will not remove any ids from the arena + pub(crate) fn drop_scope(&mut self, id: ScopeId, recursive: bool) { self.dirty_scopes.remove(&DirtyScope { height: self.scopes[id.0].height, id, @@ -96,18 +98,13 @@ impl VirtualDom { self.ensure_drop_safety(id); - if let Some(root) = self.scopes[id.0].as_ref().try_root_node() { - if let RenderReturn::Ready(node) = unsafe { root.extend_lifetime_ref() } { - self.drop_scope_inner(node) + if recursive { + if let Some(root) = self.scopes[id.0].as_ref().try_root_node() { + if let RenderReturn::Ready(node) = unsafe { root.extend_lifetime_ref() } { + self.drop_scope_inner(node) + } } } - if let Some(root) = unsafe { self.scopes[id.0].as_ref().previous_frame().try_load_node() } { - if let RenderReturn::Ready(node) = unsafe { root.extend_lifetime_ref() } { - self.drop_scope_inner(node) - } - } - - self.scopes[id.0].props.take(); let scope = &mut self.scopes[id.0]; @@ -121,37 +118,24 @@ impl VirtualDom { for task_id in scope.spawned_tasks.borrow_mut().drain() { scope.tasks.remove(task_id); } + + self.scopes.remove(id.0); } fn drop_scope_inner(&mut self, node: &VNode) { - node.clear_listeners(); node.dynamic_nodes.iter().for_each(|node| match node { DynamicNode::Component(c) => { if let Some(f) = c.scope.get() { - self.drop_scope(f); + self.drop_scope(f, true); } c.props.take(); } DynamicNode::Fragment(nodes) => { nodes.iter().for_each(|node| self.drop_scope_inner(node)) } - DynamicNode::Placeholder(t) => { - if let Some(id) = t.id.get() { - self.try_reclaim(id); - } - } - DynamicNode::Text(t) => { - if let Some(id) = t.id.get() { - self.try_reclaim(id); - } - } + DynamicNode::Placeholder(_) => {} + DynamicNode::Text(_) => {} }); - - for id in &node.root_ids { - if id.0 != 0 { - self.try_reclaim(id); - } - } } /// Descend through the tree, removing any borrowed props and listeners diff --git a/packages/core/src/diff.rs b/packages/core/src/diff.rs index 42cb9c3ff..dbbec6664 100644 --- a/packages/core/src/diff.rs +++ b/packages/core/src/diff.rs @@ -934,7 +934,7 @@ impl<'b> VirtualDom { *comp.props.borrow_mut() = unsafe { std::mem::transmute(props) }; // Now drop all the resouces - self.drop_scope(scope); + self.drop_scope(scope, false); } fn find_first_element(&self, node: &'b VNode<'b>) -> ElementId { diff --git a/packages/core/src/nodes.rs b/packages/core/src/nodes.rs index dd7e245ba..1ca3d532f 100644 --- a/packages/core/src/nodes.rs +++ b/packages/core/src/nodes.rs @@ -195,14 +195,6 @@ impl<'a> VNode<'a> { } } } - - pub(crate) fn clear_listeners(&self) { - for attr in self.dynamic_attrs { - if let AttributeValue::Listener(l) = &attr.value { - l.borrow_mut().take(); - } - } - } } /// A static layout of a UI tree that describes a set of dynamic and static nodes. diff --git a/packages/core/src/virtual_dom.rs b/packages/core/src/virtual_dom.rs index d051e4de2..9380bcaaf 100644 --- a/packages/core/src/virtual_dom.rs +++ b/packages/core/src/virtual_dom.rs @@ -682,6 +682,6 @@ impl VirtualDom { impl Drop for VirtualDom { fn drop(&mut self) { // Simply drop this scope which drops all of its children - self.drop_scope(ScopeId(0)); + self.drop_scope(ScopeId(0), true); } }