From 69a347a551f1497930dc237f0be93d3f7f3c2f1b Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Sun, 15 Jan 2023 10:02:24 -0800 Subject: [PATCH 1/2] fix: scopes not dropping their hooks --- examples/drops.rs | 36 ++++++++++++++++++++++++++++++++++++ packages/core/src/arena.rs | 9 +++++++-- packages/core/src/diff.rs | 14 +++++--------- 3 files changed, 48 insertions(+), 11 deletions(-) create mode 100644 examples/drops.rs diff --git a/examples/drops.rs b/examples/drops.rs new file mode 100644 index 000000000..bdec61aac --- /dev/null +++ b/examples/drops.rs @@ -0,0 +1,36 @@ +use dioxus::prelude::*; + +fn main() { + dioxus_desktop::launch(app); +} + +fn app(cx: Scope) -> Element { + let count = if cx.generation() % 2 == 0 { 10 } else { 0 }; + + println!("Generation: {}", cx.generation()); + + if cx.generation() < 10 { + cx.needs_update(); + } + + render! { + (0..count).map(|_| rsx!{ + Comp {} + }) + } +} + +fn Comp(cx: Scope) -> Element { + cx.use_hook(|| Drops); + render! { + div{} + } +} + +struct Drops; + +impl Drop for Drops { + fn drop(&mut self) { + println!("Dropped!"); + } +} diff --git a/packages/core/src/arena.rs b/packages/core/src/arena.rs index a1a211527..13ded6f5d 100644 --- a/packages/core/src/arena.rs +++ b/packages/core/src/arena.rs @@ -1,8 +1,8 @@ use std::ptr::NonNull; use crate::{ - nodes::RenderReturn, nodes::VNode, virtual_dom::VirtualDom, AttributeValue, DynamicNode, - ScopeId, + innerlude::DirtyScope, nodes::RenderReturn, nodes::VNode, virtual_dom::VirtualDom, + AttributeValue, DynamicNode, ScopeId, }; use bumpalo::boxed::Box as BumpBox; @@ -89,6 +89,11 @@ impl VirtualDom { // Drop a scope and all its children pub(crate) fn drop_scope(&mut self, id: ScopeId) { + self.dirty_scopes.remove(&DirtyScope { + height: self.scopes[id.0].height, + id, + }); + self.ensure_drop_safety(id); if let Some(root) = self.scopes[id.0].as_ref().try_root_node() { diff --git a/packages/core/src/diff.rs b/packages/core/src/diff.rs index 410eec55c..42cb9c3ff 100644 --- a/packages/core/src/diff.rs +++ b/packages/core/src/diff.rs @@ -916,29 +916,25 @@ impl<'b> VirtualDom { } fn remove_component_node(&mut self, comp: &VComponent, gen_muts: bool) { + // Remove the component reference from the vcomponent so they're not tied together let scope = comp .scope .take() .expect("VComponents to always have a scope"); + // Remove the component from the dom match unsafe { self.scopes[scope.0].root_node().extend_lifetime_ref() } { RenderReturn::Ready(t) => self.remove_node(t, gen_muts), RenderReturn::Aborted(placeholder) => self.remove_placeholder(placeholder, gen_muts), _ => todo!(), }; + // Restore the props back to the vcomponent in case it gets rendered again let props = self.scopes[scope.0].props.take(); - - self.dirty_scopes.remove(&DirtyScope { - height: self.scopes[scope.0].height, - id: scope, - }); - *comp.props.borrow_mut() = unsafe { std::mem::transmute(props) }; - // make sure to wipe any of its props and listeners - self.ensure_drop_safety(scope); - self.scopes.remove(scope.0); + // Now drop all the resouces + self.drop_scope(scope); } fn find_first_element(&self, node: &'b VNode<'b>) -> ElementId { From c6d4398e36165943aa1cb8033138bd6d19a92175 Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Sun, 15 Jan 2023 10:12:22 -0800 Subject: [PATCH 2/2] make clippy happy --- examples/drops.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/drops.rs b/examples/drops.rs index bdec61aac..71a791990 100644 --- a/examples/drops.rs +++ b/examples/drops.rs @@ -15,12 +15,12 @@ fn app(cx: Scope) -> Element { render! { (0..count).map(|_| rsx!{ - Comp {} + drop_child {} }) } } -fn Comp(cx: Scope) -> Element { +fn drop_child(cx: Scope) -> Element { cx.use_hook(|| Drops); render! { div{}