瀏覽代碼

Merge branch 'upstream' into fix-future-on-dropped-scope

Evan Almloff 2 年之前
父節點
當前提交
d13d1fb1c9
共有 3 個文件被更改,包括 48 次插入17 次删除
  1. 36 0
      examples/drops.rs
  2. 7 2
      packages/core/src/arena.rs
  3. 5 15
      packages/core/src/diff.rs

+ 36 - 0
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!{
+            drop_child {}
+        })
+    }
+}
+
+fn drop_child(cx: Scope) -> Element {
+    cx.use_hook(|| Drops);
+    render! {
+        div{}
+    }
+}
+
+struct Drops;
+
+impl Drop for Drops {
+    fn drop(&mut self) {
+        println!("Dropped!");
+    }
+}

+ 7 - 2
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() {

+ 5 - 15
packages/core/src/diff.rs

@@ -916,35 +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);
-        let scope_id = scope.0;
-        let scope = unsafe { self.scopes.get_unchecked_mut(scope.0) };
-        // Drop all the futures once the hooks are dropped
-        for task_id in scope.spawned_tasks.borrow_mut().drain() {
-            scope.tasks.remove(task_id);
-        }
-        self.scopes.remove(scope_id);
+        // Now drop all the resouces
+        self.drop_scope(scope);
     }
 
     fn find_first_element(&self, node: &'b VNode<'b>) -> ElementId {