From 992ac4a3fb550b88c25d6a242f70fe8f40aac4d4 Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Wed, 6 Sep 2023 16:12:01 -0500 Subject: [PATCH] clear borrowed props after ensure_drop_safety --- packages/core/src/arena.rs | 11 +++++++---- packages/core/src/create.rs | 8 ++++---- packages/core/src/diff.rs | 4 ++-- packages/core/src/virtual_dom.rs | 10 +++++++--- 4 files changed, 20 insertions(+), 13 deletions(-) diff --git a/packages/core/src/arena.rs b/packages/core/src/arena.rs index 5fb5fa6cb..6430934f5 100644 --- a/packages/core/src/arena.rs +++ b/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>>, // 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 { diff --git a/packages/core/src/create.rs b/packages/core/src/create.rs index 759ee97d9..44b344380 100644 --- a/packages/core/src/create.rs +++ b/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); diff --git a/packages/core/src/diff.rs b/packages/core/src/diff.rs index edaa0048e..cbff0621e 100644 --- a/packages/core/src/diff.rs +++ b/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), diff --git a/packages/core/src/virtual_dom.rs b/packages/core/src/virtual_dom.rs index eedfd6b9b..6601f2793 100644 --- a/packages/core/src/virtual_dom.rs +++ b/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;