瀏覽代碼

move mounted info to the VDOM

Evan Almloff 1 年之前
父節點
當前提交
8eb2b74832

+ 30 - 5
packages/core/src/arena.rs

@@ -1,4 +1,4 @@
-use crate::{innerlude::DirtyScope, nodes::VNode, virtual_dom::VirtualDom, ScopeId};
+use crate::{innerlude::DirtyScope, virtual_dom::VirtualDom, ScopeId};
 
 /// An Element's unique identifier.
 ///
@@ -13,16 +13,41 @@ pub struct ElementId(pub usize);
 /// `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 VNodeId(pub usize);
+#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub(crate) struct MountId(pub(crate) usize);
+
+impl Default for MountId {
+    fn default() -> Self {
+        Self(usize::MAX)
+    }
+}
+
+impl MountId {
+    pub(crate) fn new(id: usize) -> Self {
+        debug_assert_ne!(id, usize::MAX);
+        Self(id)
+    }
+
+    pub(crate) fn as_usize(self) -> Option<usize> {
+        if self.0 == usize::MAX {
+            None
+        } else {
+            Some(self.0)
+        }
+    }
+
+    pub(crate) fn is_none(self) -> bool {
+        self.0 == usize::MAX
+    }
+}
 
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, Copy)]
 pub struct ElementRef {
     // the pathway of the real element inside the template
     pub(crate) path: ElementPath,
 
     // The actual element
-    pub(crate) element: VNode,
+    pub(crate) mount: MountId,
 }
 
 #[derive(Clone, Copy, Debug)]

+ 6 - 5
packages/core/src/diff/component.rs

@@ -2,7 +2,7 @@ use std::ops::Deref;
 
 use crate::{
     any_props::AnyProps,
-    innerlude::{DirtyScope, ElementRef, VComponent, VNodeMount, WriteMutations},
+    innerlude::{DirtyScope, ElementRef, MountId, VComponent, WriteMutations},
     nodes::RenderReturn,
     nodes::VNode,
     scopes::ScopeId,
@@ -53,7 +53,7 @@ impl VirtualDom {
 impl VNode {
     pub(crate) fn diff_vcomponent(
         &self,
-        mount: &mut VNodeMount,
+        mount: MountId,
         idx: usize,
         new: &VComponent,
         old: &VComponent,
@@ -97,16 +97,17 @@ impl VNode {
             id: scope_id,
         });
     }
+
     fn replace_vcomponent(
         &self,
-        mount: &mut VNodeMount,
+        mount: MountId,
         idx: usize,
         new: &VComponent,
         parent: Option<ElementRef>,
         dom: &mut VirtualDom,
         to: &mut impl WriteMutations,
     ) {
-        let scope = ScopeId(mount.mounted_dynamic_nodes[idx]);
+        let scope = ScopeId(dom.mounts[mount.0].mounted_dynamic_nodes[idx]);
 
         let _m = self.create_component_node(mount, idx, new, parent, dom, to);
 
@@ -118,7 +119,7 @@ impl VNode {
 
     pub(super) fn create_component_node(
         &self,
-        _mount: &mut VNodeMount,
+        _mount: MountId,
         _idx: usize,
         component: &VComponent,
         parent: Option<ElementRef>,

+ 1 - 1
packages/core/src/diff/iterator.rs

@@ -434,7 +434,7 @@ impl VNode {
     ) -> usize {
         let template = self.template.get();
 
-        let mount = self.assert_mounted();
+        let mount = dom.mounts.get(self.mount.get().0).unwrap();
 
         template
             .roots

+ 3 - 3
packages/core/src/diff/mod.rs

@@ -2,7 +2,7 @@
 
 use crate::{
     arena::ElementId,
-    innerlude::{ElementRef, VNodeMount, WriteMutations},
+    innerlude::{ElementRef, MountId, WriteMutations},
     nodes::VNode,
     scopes::ScopeId,
     virtual_dom::VirtualDom,
@@ -49,7 +49,7 @@ impl VirtualDom {
     fn nodes_to_placeholder(
         &mut self,
         to: &mut impl WriteMutations,
-        mount: &mut VNodeMount,
+        mount: MountId,
         dyn_node_idx: usize,
         old_nodes: &[VNode],
     ) {
@@ -57,7 +57,7 @@ impl VirtualDom {
         let placeholder = self.next_element();
 
         // Set the id of the placeholder
-        mount.mounted_dynamic_nodes[dyn_node_idx] = placeholder.0;
+        self.mounts[mount.0].mounted_dynamic_nodes[dyn_node_idx] = placeholder.0;
 
         to.create_placeholder(placeholder);
 

+ 67 - 72
packages/core/src/diff/node.rs

@@ -1,8 +1,7 @@
+use crate::innerlude::MountId;
 use crate::{Attribute, AttributeValue, DynamicNode::*};
 use crate::{VNode, VirtualDom, WriteMutations};
 use core::iter::Peekable;
-use std::cell::Ref;
-use std::cell::RefMut;
 
 use crate::{
     arena::ElementId,
@@ -30,17 +29,22 @@ impl VNode {
                 if let Some(&template) = map.get(&byte_index) {
                     new.template.set(template);
                     if template != self.template.get() {
-                        let parent = self.parent();
+                        let mount_id = self.mount.get();
+                        let parent = dom.mounts[mount_id.0].parent;
                         return self.replace([new], parent, dom, to);
                     }
                 }
             }
         }
 
-        {
-            // Copy over the mount information
-            *new.mount.borrow_mut() = self.mount.borrow_mut().take();
-        }
+        // Copy over the mount information
+        let mount_id = self.mount.get();
+        new.mount.set(mount_id);
+
+        let mount = &mut dom.mounts[mount_id.0];
+
+        // Update the reference to the node for bubbling events
+        mount.node = new.clone_with_parent();
 
         // If the templates are the same, we don't need to do anything, except copy over the mount information
         if self == new {
@@ -52,9 +56,6 @@ impl VNode {
             return self.light_diff_templates(new, dom, to);
         }
 
-        let mut mount = self.assert_mounted_mut();
-        let mount = &mut *mount;
-
         // If the templates are the same, we can diff the attributes and children
         // Start with the attributes
         self.dynamic_attrs
@@ -74,13 +75,13 @@ impl VNode {
             .zip(new.dynamic_nodes.iter())
             .enumerate()
             .for_each(|(dyn_node_idx, (old, new))| {
-                self.diff_dynamic_node(mount, dyn_node_idx, old, new, dom, to)
+                self.diff_dynamic_node(mount_id, dyn_node_idx, old, new, dom, to)
             });
     }
 
     fn diff_dynamic_node(
         &self,
-        mount: &mut VNodeMount,
+        mount: MountId,
         idx: usize,
         old_node: &DynamicNode,
         new_node: &DynamicNode,
@@ -88,21 +89,24 @@ impl VNode {
         to: &mut impl WriteMutations,
     ) {
         let parent = || ElementRef {
-            element: self.clone_with_parent(),
+            mount,
             path: ElementPath {
                 path: self.template.get().node_paths[idx],
             },
         };
         match (old_node, new_node) {
-            (Text(old), Text(new)) => self.diff_vtext( to, mount, idx, old, new),
+            (Text(old), Text(new)) => {
+                let mount = &dom.mounts[mount.0];
+                self.diff_vtext( to, mount, idx, old, new)
+            },
             (Placeholder(_), Placeholder(_)) => {},
             (Fragment(old), Fragment(new)) => dom.diff_non_empty_fragment(to, old, new, Some(parent())),
             (Component(old), Component(new)) => {
-				let scope_id = ScopeId(mount.mounted_dynamic_nodes[idx]);
+				let scope_id = ScopeId(dom.mounts[mount.0].mounted_dynamic_nodes[idx]);
                 self.diff_vcomponent(mount, idx, new, old, scope_id, Some(parent()), dom, to)
             },
             (Placeholder(_), Fragment(right)) => {
-                let placeholder_id = ElementId(mount.mounted_dynamic_nodes[idx]);
+                let placeholder_id = ElementId(dom.mounts[mount.0].mounted_dynamic_nodes[idx]);
                 dom.replace_placeholder(to, placeholder_id, right, Some(parent()))},
             (Fragment(left), Placeholder(_)) => {
                 dom.nodes_to_placeholder(to, mount, idx, left,)
@@ -112,7 +116,7 @@ impl VNode {
     }
 
     pub(crate) fn find_first_element(&self, dom: &VirtualDom) -> ElementId {
-        let mount = self.assert_mounted();
+        let mount = &dom.mounts[self.mount.get().0];
         match &self.template.get().roots[0] {
             TemplateNode::Element { .. } | TemplateNode::Text { text: _ } => mount.root_ids[0],
             TemplateNode::Dynamic { id } | TemplateNode::DynamicText { id } => {
@@ -135,7 +139,7 @@ impl VNode {
     }
 
     pub(crate) fn find_last_element(&self, dom: &VirtualDom) -> ElementId {
-        let mount = self.assert_mounted();
+        let mount = &dom.mounts[self.mount.get().0];
         match &self.template.get().roots.last().unwrap() {
             TemplateNode::Element { .. } | TemplateNode::Text { text: _ } => {
                 *mount.root_ids.last().unwrap()
@@ -195,25 +199,25 @@ impl VNode {
         to: &mut impl WriteMutations,
         gen_muts: bool,
     ) {
-        let mount = self.assert_mounted();
+        let mount = self.mount.get();
 
         // Clean up any attributes that have claimed a static node as dynamic for mount/unmounts
         // Will not generate mutations!
-        self.reclaim_attributes(&mount, dom, to);
+        self.reclaim_attributes(mount, dom, to);
 
         // Remove the nested dynamic nodes
         // We don't generate mutations for these, as they will be removed by the parent (in the next line)
         // But we still need to make sure to reclaim them from the arena and drop their hooks, etc
-        self.remove_nested_dyn_nodes(&mount, dom, to);
+        self.remove_nested_dyn_nodes(mount, dom, to);
 
         // Clean up the roots, assuming we need to generate mutations for these
         // This is done last in order to preserve Node ID reclaim order (reclaim in reverse order of claim)
-        self.reclaim_roots(&mount, dom, to, gen_muts);
+        self.reclaim_roots(mount, dom, to, gen_muts);
     }
 
     fn reclaim_roots(
         &self,
-        mount: &VNodeMount,
+        mount: MountId,
         dom: &mut VirtualDom,
         to: &mut impl WriteMutations,
         gen_muts: bool,
@@ -223,6 +227,7 @@ impl VNode {
                 let dynamic_node = &self.dynamic_nodes[id];
                 self.remove_dynamic_node(mount, dom, to, idx, dynamic_node, gen_muts);
             } else {
+                let mount = &dom.mounts[mount.0];
                 let id = ElementId(mount.mounted_dynamic_nodes[idx]);
                 if gen_muts {
                     to.remove_node(id);
@@ -234,7 +239,7 @@ impl VNode {
 
     fn remove_nested_dyn_nodes(
         &self,
-        mount: &VNodeMount,
+        mount: MountId,
         dom: &mut VirtualDom,
         to: &mut impl WriteMutations,
     ) {
@@ -250,7 +255,7 @@ impl VNode {
 
     fn remove_dynamic_node(
         &self,
-        mount: &VNodeMount,
+        mount: MountId,
         dom: &mut VirtualDom,
         to: &mut impl WriteMutations,
         idx: usize,
@@ -259,11 +264,11 @@ impl VNode {
     ) {
         match node {
             Component(_comp) => {
-                let scope_id = ScopeId(mount.mounted_dynamic_nodes[idx]);
+                let scope_id = ScopeId(dom.mounts[mount.0].mounted_dynamic_nodes[idx]);
                 dom.remove_component_node(to, scope_id, gen_muts);
             }
             Text(_) | Placeholder(_) => {
-                let id = ElementId(mount.mounted_dynamic_nodes[idx]);
+                let id = ElementId(dom.mounts[mount.0].mounted_dynamic_nodes[idx]);
                 dom.remove_element_id(to, id, gen_muts)
             }
             Fragment(nodes) => nodes
@@ -272,18 +277,6 @@ impl VNode {
         };
     }
 
-    pub(super) fn assert_mounted(&self) -> Ref<'_, VNodeMount> {
-        Ref::map(self.mount.borrow(), |mount| {
-            mount.as_ref().expect("to be mounted")
-        })
-    }
-
-    fn assert_mounted_mut(&self) -> RefMut<'_, VNodeMount> {
-        RefMut::map(self.mount.borrow_mut(), |mount| {
-            mount.as_mut().expect("to be mounted")
-        })
-    }
-
     fn templates_are_different(&self, other: &VNode) -> bool {
         let self_node_name = self.template.get().name;
         let other_node_name = other.template.get().name;
@@ -293,7 +286,7 @@ impl VNode {
 
     pub(super) fn reclaim_attributes(
         &self,
-        mount: &VNodeMount,
+        mount: MountId,
         dom: &mut VirtualDom,
         _to: &mut impl WriteMutations,
     ) {
@@ -307,7 +300,7 @@ impl VNode {
                 continue;
             }
 
-            let next_id = mount.mounted_attributes[idx];
+            let next_id = dom.mounts[mount.0].mounted_attributes[idx];
 
             // only reclaim the new element if it's different from the previous one
             if id != Some(next_id) {
@@ -372,20 +365,22 @@ impl VNode {
         dom: &mut VirtualDom,
         to: &mut impl WriteMutations,
     ) {
-        let parent = new.parent();
+        let mount_id = self.mount.get();
+        let mount = &dom.mounts[mount_id.0];
+        let parent = mount.parent;
         match matching_components(self, new) {
             None => self.replace([new], parent, dom, to),
             Some(components) => {
-                let mut mount = self.assert_mounted_mut();
                 for (idx, (old_component, new_component)) in components.into_iter().enumerate() {
-                    let scope_id = ScopeId(self.assert_mounted().mounted_dynamic_nodes[idx]);
+                    let mount = &dom.mounts[mount_id.0];
+                    let scope_id = ScopeId(mount.mounted_dynamic_nodes[idx]);
                     self.diff_vcomponent(
-                        &mut mount,
+                        mount_id,
                         idx,
                         old_component,
                         new_component,
                         scope_id,
-                        parent.clone(),
+                        parent,
                         dom,
                         to,
                     )
@@ -453,18 +448,18 @@ impl VNode {
             )
         };
 
-        let mut node = self.mount.borrow_mut();
-
         // Initialize the mount information for this template
-        *node = Some(VNodeMount {
+        let entry = dom.mounts.vacant_entry();
+        let mount = MountId(entry.key());
+        self.mount.set(mount);
+        entry.insert(VNodeMount {
+            node: self.clone_with_parent(),
             parent,
             root_ids: vec![ElementId(0); template.roots.len()].into_boxed_slice(),
             mounted_attributes: vec![ElementId(0); template.attr_paths.len()].into_boxed_slice(),
             mounted_dynamic_nodes: vec![0; template.node_paths.len()].into_boxed_slice(),
         });
 
-        let mount = node.as_mut().unwrap();
-
         template
             .roots
             .iter()
@@ -499,7 +494,7 @@ impl VNode {
 impl VNode {
     fn write_static_text_root(
         &self,
-        mount: &mut VNodeMount,
+        mount: MountId,
         idx: usize,
         dom: &mut VirtualDom,
         to: &mut impl WriteMutations,
@@ -513,7 +508,7 @@ impl VNode {
 
     fn write_dynamic_root(
         &self,
-        mount: &mut VNodeMount,
+        mount: MountId,
         idx: usize,
         dom: &mut VirtualDom,
         to: &mut impl WriteMutations,
@@ -525,7 +520,7 @@ impl VNode {
                     path: ElementPath {
                         path: self.template.get().node_paths[idx],
                     },
-                    element: self.clone_with_parent(),
+                    mount,
                 });
                 self.create_component_node(mount, idx, component, parent, dom, to)
             }
@@ -534,7 +529,7 @@ impl VNode {
                     path: ElementPath {
                         path: self.template.get().node_paths[idx],
                     },
-                    element: self.clone_with_parent(),
+                    mount,
                 });
                 dom.create_children(to, frag, parent)
             }
@@ -558,7 +553,7 @@ impl VNode {
     /// We want to make sure we write these nodes while on top of the root
     fn write_element_root(
         &self,
-        mount: &mut VNodeMount,
+        mount: MountId,
         root_idx: usize,
         dynamic_attrs: &mut Peekable<impl Iterator<Item = (usize, &'static [u8])>>,
         dynamic_nodes_iter: &mut Peekable<impl Iterator<Item = ((usize, usize), &'static [u8])>>,
@@ -601,7 +596,7 @@ impl VNode {
     #[allow(unused)]
     fn load_placeholders(
         &self,
-        mount: &mut VNodeMount,
+        mount: MountId,
         dynamic_nodes_iter: &mut Peekable<impl Iterator<Item = ((usize, usize), &'static [u8])>>,
         dynamic_nodes: &[(usize, &'static [u8])],
         root_idx: u8,
@@ -633,7 +628,7 @@ impl VNode {
 
     fn write_attrs_on_root(
         &self,
-        mount: &mut VNodeMount,
+        mount: MountId,
         attrs: &mut Peekable<impl Iterator<Item = (usize, &'static [u8])>>,
         root_idx: u8,
         root: ElementId,
@@ -659,14 +654,14 @@ impl VNode {
 
     fn write_attribute(
         &self,
-        mount: &mut VNodeMount,
+        mount: MountId,
         idx: usize,
         id: ElementId,
         dom: &mut VirtualDom,
         to: &mut impl WriteMutations,
     ) {
         // Make sure we set the attribute's associated id
-        mount.mounted_attributes[idx] = id;
+        dom.mounts[mount.0].mounted_attributes[idx] = id;
 
         let attribute = &self.dynamic_attrs[idx];
 
@@ -676,7 +671,7 @@ impl VNode {
                 let path = &self.template.get().attr_paths[idx];
                 let element_ref = ElementRef {
                     path: ElementPath { path },
-                    element: self.clone_with_parent(),
+                    mount,
                 };
                 dom.elements[id.0] = Some(element_ref);
                 to.create_event_listener(&attribute.name[2..], id);
@@ -689,14 +684,14 @@ impl VNode {
 
     fn load_template_root(
         &self,
-        mount: &mut VNodeMount,
+        mount: MountId,
         root_idx: usize,
         dom: &mut VirtualDom,
         to: &mut impl WriteMutations,
     ) -> ElementId {
         // Get an ID for this root since it's a real root
         let this_id = dom.next_element();
-        mount.root_ids[root_idx] = this_id;
+        dom.mounts[mount.0].root_ids[root_idx] = this_id;
 
         to.load_template(self.template.get().name, root_idx, this_id);
 
@@ -732,7 +727,7 @@ impl VNode {
 
     pub(crate) fn create_dynamic_node(
         &self,
-        mount: &mut VNodeMount,
+        mount: MountId,
         index: usize,
         dom: &mut VirtualDom,
         to: &mut impl WriteMutations,
@@ -747,7 +742,7 @@ impl VNode {
                     path: ElementPath {
                         path: self.template.get().node_paths[index],
                     },
-                    element: self.clone_with_parent(),
+                    mount,
                 });
                 self.create_component_node(mount, index, component, parent, dom, to)
             }
@@ -756,7 +751,7 @@ impl VNode {
                     path: ElementPath {
                         path: self.template.get().node_paths[index],
                     },
-                    element: self.clone_with_parent(),
+                    mount,
                 });
                 dom.create_children(to, frag, parent)
             }
@@ -766,7 +761,7 @@ impl VNode {
     /// Mount a root node and return its ID and the path to the node
     fn mount_dynamic_node_with_path(
         &self,
-        mount: &mut VNodeMount,
+        mount: MountId,
         idx: usize,
         dom: &mut VirtualDom,
     ) -> (ElementId, &'static [u8]) {
@@ -781,7 +776,7 @@ impl VNode {
 
     fn create_dynamic_text(
         &self,
-        mount: &mut VNodeMount,
+        mount: MountId,
         idx: usize,
         text: &VText,
         dom: &mut VirtualDom,
@@ -798,7 +793,7 @@ impl VNode {
 
     pub(crate) fn create_placeholder(
         &self,
-        mount: &mut VNodeMount,
+        mount: MountId,
         idx: usize,
         dom: &mut VirtualDom,
         to: &mut impl WriteMutations,
@@ -813,10 +808,10 @@ impl VNode {
     }
 }
 
-impl VNodeMount {
-    fn mount_node(&mut self, node_index: usize, dom: &mut VirtualDom) -> ElementId {
+impl MountId {
+    fn mount_node(self, node_index: usize, dom: &mut VirtualDom) -> ElementId {
         let id = dom.next_element();
-        self.mounted_dynamic_nodes[node_index] = id.0;
+        dom.mounts[self.0].mounted_dynamic_nodes[node_index] = id.0;
         id
     }
 }

+ 5 - 10
packages/core/src/nodes.rs

@@ -1,8 +1,7 @@
 use crate::any_props::{BoxedAnyProps, VProps};
-use crate::innerlude::{ElementRef, EventHandler};
+use crate::innerlude::{ElementRef, EventHandler, MountId};
 use crate::Properties;
 use crate::{arena::ElementId, Element, Event};
-use std::cell::RefCell;
 use std::ops::Deref;
 use std::rc::Rc;
 use std::vec;
@@ -54,6 +53,9 @@ pub(crate) struct VNodeMount {
     /// The parent of this node
     pub parent: Option<ElementRef>,
 
+    /// A back link to the original node
+    pub node: VNode,
+
     /// The IDs for the roots of this template - to be used when moving the template around and removing it from
     /// the actual Dom
     pub root_ids: Box<[ElementId]>,
@@ -96,7 +98,7 @@ pub struct VNode {
     vnode: Rc<VNodeInner>,
 
     /// The mount information for this template
-    pub(crate) mount: Rc<RefCell<Option<VNodeMount>>>,
+    pub(crate) mount: Cell<MountId>,
 }
 
 impl Clone for VNode {
@@ -131,13 +133,6 @@ impl VNode {
         }
     }
 
-    /// Try to get the parent of this node
-    ///
-    /// This will fail if the VNode is not mounted
-    pub(crate) fn parent(&self) -> Option<ElementRef> {
-        self.mount.borrow().as_ref()?.parent.clone()
-    }
-
     /// Create a template with no nodes that will be skipped over during diffing
     pub fn empty() -> Element {
         Some(Self {

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

@@ -16,13 +16,13 @@ impl VirtualDom {
         let entry = self.scopes.vacant_entry();
         let id = ScopeId(entry.key());
 
-        let scope = entry.insert(Box::new(ScopeState {
+        let scope = entry.insert(ScopeState {
             runtime: self.runtime.clone(),
             context_id: id,
 
             props,
             last_rendered_node: Default::default(),
-        }));
+        });
 
         let context =
             ScopeContext::new(name, id, parent_id, height, self.runtime.scheduler.clone());

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

@@ -6,7 +6,7 @@ use crate::{
     any_props::{BoxedAnyProps, VProps},
     arena::ElementId,
     innerlude::{
-        DirtyScope, ElementRef, ErrorBoundary, NoOpMutations, Scheduler, SchedulerMsg,
+        DirtyScope, ElementRef, ErrorBoundary, NoOpMutations, Scheduler, SchedulerMsg, VNodeMount,
         WriteMutations,
     },
     nodes::RenderReturn,
@@ -180,7 +180,8 @@ use std::{any::Any, cell::Cell, collections::BTreeSet, future::Future, rc::Rc};
 /// }
 /// ```
 pub struct VirtualDom {
-    pub(crate) scopes: Slab<Box<ScopeState>>,
+    // TODO: I don't think we need the box here anymore?
+    pub(crate) scopes: Slab<ScopeState>,
 
     pub(crate) dirty_scopes: BTreeSet<DirtyScope>,
 
@@ -193,6 +194,9 @@ pub struct VirtualDom {
     // The element ids that are used in the renderer
     pub(crate) elements: Slab<Option<ElementRef>>,
 
+    // Once nodes are mounted, the information about where they are mounted is stored here
+    pub(crate) mounts: Slab<VNodeMount>,
+
     pub(crate) runtime: Rc<Runtime>,
 
     // Currently suspended scopes
@@ -267,6 +271,7 @@ impl VirtualDom {
             templates: Default::default(),
             queued_templates: Default::default(),
             elements: Default::default(),
+            mounts: Default::default(),
             suspended_scopes: Default::default(),
         };
 
@@ -289,7 +294,7 @@ impl VirtualDom {
     ///
     /// This is useful for inserting or removing contexts from a scope, or rendering out its root node
     pub(crate) fn get_scope(&self, id: ScopeId) -> Option<&ScopeState> {
-        self.scopes.get(id.0).map(|s| &**s)
+        self.scopes.get(id.0)
     }
 
     /// Get the single scope at the top of the VirtualDom tree that will always be around
@@ -381,7 +386,7 @@ impl VirtualDom {
             while let Some(path) = parent_node {
                 let mut listeners = vec![];
 
-                let el_ref = &path.element;
+                let el_ref = &self.mounts[path.mount.0].node;
                 let node_template = el_ref.template.get();
                 let target_path = path.path;
 
@@ -417,13 +422,13 @@ impl VirtualDom {
                     }
                 }
 
-                let mount = el_ref.mount.borrow();
-                parent_node = mount.as_ref().unwrap().parent.clone();
+                let mount = el_ref.mount.get().as_usize();
+                parent_node = mount.and_then(|id| self.mounts.get(id).and_then(|el| el.parent));
             }
         } else {
             // Otherwise, we just call the listener on the target element
             if let Some(path) = parent_node {
-                let el_ref = &path.element;
+                let el_ref = &self.mounts[path.mount.0].node;
                 let node_template = el_ref.template.get();
                 let target_path = path.path;