Browse Source

clear borrowed props after ensure_drop_safety

Evan Almloff 1 year ago
parent
commit
992ac4a3fb

+ 7 - 4
packages/core/src/arena.rs

@@ -2,6 +2,7 @@ use crate::{
     innerlude::DirtyScope, nodes::RenderReturn, nodes::VNode, virtual_dom::VirtualDom,
     AttributeValue, DynamicNode, ScopeId,
 };
+use std::ptr::NonNull;
 
 /// An Element's unique identifier.
 ///
@@ -13,8 +14,8 @@ pub struct ElementId(pub usize);
 
 /// An Element that can be bubbled to's unique identifier.
 ///
-/// `ElementId` is a `usize` that is unique across the entire VirtualDOM - but not unique across time. If a component is
-/// unmounted, then the `ElementId` will be reused for a new component.
+/// `BubbleId` is a `usize` that is unique across the entire VirtualDOM - but not unique across time. If a component is
+/// unmounted, then the `BubbleId` will be reused for a new component.
 #[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
 pub struct BubbleId(pub usize);
@@ -25,7 +26,7 @@ pub struct ElementRef<'a> {
     pub(crate) path: ElementPath,
 
     // The actual template
-    pub(crate) template: Option<*const VNode<'a>>,
+    pub(crate) template: Option<NonNull<VNode<'a>>>,
 
     // The scope the element belongs to
     pub(crate) scope: ScopeId,
@@ -182,9 +183,11 @@ impl VirtualDom {
                 *props = None;
             }
         }
+        let scope = &self.scopes[scope_id.0];
+        scope.borrowed_props.borrow_mut().clear();
 
         // Now that all the references are gone, we can safely drop our own references in our listeners.
-        let mut listeners = self.scopes[scope_id.0].attributes_to_drop.borrow_mut();
+        let mut listeners = scope.attributes_to_drop.borrow_mut();
         listeners.drain(..).for_each(|listener| {
             let listener = unsafe { &*listener };
             match &listener.value {

+ 4 - 4
packages/core/src/create.rs

@@ -187,7 +187,7 @@ impl<'b> VirtualDom {
                     path: ElementPath {
                         path: &template.template.get().node_paths[idx],
                     },
-                    template: Some(template),
+                    template: Some(template.into()),
                     scope: self.runtime.current_scope_id().unwrap_or(ScopeId(0)),
                 };
                 self.create_dynamic_node(template_ref, node)
@@ -197,7 +197,7 @@ impl<'b> VirtualDom {
                     path: ElementPath {
                         path: &template.template.get().node_paths[idx],
                     },
-                    template: Some(template),
+                    template: Some(template.into()),
                     scope: self.runtime.current_scope_id().unwrap_or(ScopeId(0)),
                 };
                 parent.set(Some(self.next_element_ref(template_ref)));
@@ -286,7 +286,7 @@ impl<'b> VirtualDom {
                 path: ElementPath {
                     path: &template.template.get().node_paths[idx],
                 },
-                template: Some(template),
+                template: Some(template.into()),
                 scope: self.runtime.current_scope_id().unwrap_or(ScopeId(0)),
             };
             let m = self.create_dynamic_node(boundary_ref, &template.dynamic_nodes[idx]);
@@ -340,7 +340,7 @@ impl<'b> VirtualDom {
                 let path = &template.template.get().attr_paths[idx];
                 let element_ref = ElementRef {
                     path: ElementPath { path },
-                    template: Some(template),
+                    template: Some(template.into()),
                     scope: self.runtime.current_scope_id().unwrap_or(ScopeId(0)),
                 };
                 self.set_template(id, element_ref);

+ 2 - 2
packages/core/src/diff.rs

@@ -144,7 +144,7 @@ impl<'b> VirtualDom {
             .enumerate()
             .for_each(|(dyn_node_idx, (left_node, right_node))| {
                 let current_ref = ElementRef {
-                    template: Some(right_template),
+                    template: Some(right_template.into()),
                     path: ElementPath {
                         path: left_template.template.get().node_paths[dyn_node_idx],
                     },
@@ -176,7 +176,7 @@ impl<'b> VirtualDom {
                 right.id.set(left.id.get());
                 right.parent.set(left.parent.get());
                 // Update the template
-                self.update_template(left.id.get().unwrap(), parent.template.unwrap());
+                self.update_template(left.id.get().unwrap(), parent.template.unwrap().as_ptr());
             },
             (Component(left), Component(right)) => self.diff_vcomponent(left, right, Some(parent)),
             (Placeholder(left), Fragment(right)) => self.replace_placeholder(left, *right, parent),

+ 7 - 3
packages/core/src/virtual_dom.rs

@@ -371,8 +371,12 @@ impl VirtualDom {
             // Loop through each dynamic attribute (in a depth first order) in this template before moving up to the template's parent.
             while let Some(el_ref) = parent_path {
                 // safety: we maintain references of all vnodes in the element slab
-                let template =
-                    unsafe { &*el_ref.template.expect("template reference should be valid") };
+                let template = unsafe {
+                    el_ref
+                        .template
+                        .expect("template reference should be valid")
+                        .as_ref()
+                };
                 let node_template = template.template.get();
                 let target_path = el_ref.path;
 
@@ -422,7 +426,7 @@ impl VirtualDom {
             // Otherwise, we just call the listener on the target element
             if let Some(el_ref) = parent_path {
                 // safety: we maintain references of all vnodes in the element slab
-                let template = unsafe { &*el_ref.template.unwrap() };
+                let template = unsafe { el_ref.template.unwrap().as_ref() };
                 let node_template = template.template.get();
                 let target_path = el_ref.path;