Procházet zdrojové kódy

create node watcher API

Evan Almloff před 2 roky
rodič
revize
bd07d7754c

+ 6 - 10
packages/native-core/src/dioxus.rs

@@ -77,14 +77,14 @@ impl DioxusState {
                 }
                 }
                 CreatePlaceholder { id } => {
                 CreatePlaceholder { id } => {
                     let node = NodeType::Placeholder;
                     let node = NodeType::Placeholder;
-                    let node = rdom.create_node(node, true);
+                    let node = rdom.create_node(node);
                     let node_id = node.id();
                     let node_id = node.id();
                     self.set_element_id(node, id);
                     self.set_element_id(node, id);
                     self.stack.push(node_id);
                     self.stack.push(node_id);
                 }
                 }
                 CreateTextNode { value, id } => {
                 CreateTextNode { value, id } => {
                     let node_data = NodeType::Text(value.to_string());
                     let node_data = NodeType::Text(value.to_string());
-                    let node = rdom.create_node(node_data, true);
+                    let node = rdom.create_node(node_data);
                     let node_id = node.id();
                     let node_id = node.id();
                     self.set_element_id(node, id);
                     self.set_element_id(node, id);
                     self.stack.push(node_id);
                     self.stack.push(node_id);
@@ -228,20 +228,16 @@ fn create_template_node(rdom: &mut RealDom, node: &TemplateNode) -> NodeId {
                     .collect(),
                     .collect(),
                 listeners: FxHashSet::default(),
                 listeners: FxHashSet::default(),
             });
             });
-            let node_id = rdom.create_node(node, true).id();
+            let node_id = rdom.create_node(node).id();
             for child in *children {
             for child in *children {
                 let child_id = create_template_node(rdom, child);
                 let child_id = create_template_node(rdom, child);
                 rdom.add_child(node_id, child_id);
                 rdom.add_child(node_id, child_id);
             }
             }
             node_id
             node_id
         }
         }
-        TemplateNode::Text { text } => rdom
-            .create_node(NodeType::Text(text.to_string()), true)
-            .id(),
-        TemplateNode::Dynamic { .. } => rdom.create_node(NodeType::Placeholder, true).id(),
-        TemplateNode::DynamicText { .. } => {
-            rdom.create_node(NodeType::Text(String::new()), true).id()
-        }
+        TemplateNode::Text { text } => rdom.create_node(NodeType::Text(text.to_string())).id(),
+        TemplateNode::Dynamic { .. } => rdom.create_node(NodeType::Placeholder).id(),
+        TemplateNode::DynamicText { .. } => rdom.create_node(NodeType::Text(String::new())).id(),
     }
     }
 }
 }
 
 

+ 2 - 1
packages/native-core/src/lib.rs

@@ -13,6 +13,7 @@ pub mod dioxus;
 pub mod layout_attributes;
 pub mod layout_attributes;
 pub mod node;
 pub mod node;
 pub mod node_ref;
 pub mod node_ref;
+pub mod node_watcher;
 mod passes;
 mod passes;
 pub mod real_dom;
 pub mod real_dom;
 pub mod tree;
 pub mod tree;
@@ -22,7 +23,7 @@ pub mod prelude {
     pub use crate::node::{ElementNode, FromAnyValue, NodeType, OwnedAttributeView};
     pub use crate::node::{ElementNode, FromAnyValue, NodeType, OwnedAttributeView};
     pub use crate::node_ref::{AttributeMaskBuilder, NodeMaskBuilder, NodeView};
     pub use crate::node_ref::{AttributeMaskBuilder, NodeMaskBuilder, NodeView};
     pub use crate::passes::{Dependancy, Pass};
     pub use crate::passes::{Dependancy, Pass};
-    pub use crate::real_dom::{NodeImmutable, NodeMut, NodeMutRaw, NodeMutable, NodeRef, RealDom};
+    pub use crate::real_dom::{NodeImmutable, NodeMut, NodeRef, RealDom};
     pub use crate::tree::NodeId;
     pub use crate::tree::NodeId;
     pub use crate::SendAnyMap;
     pub use crate::SendAnyMap;
 }
 }

+ 15 - 0
packages/native-core/src/node_watcher.rs

@@ -0,0 +1,15 @@
+use crate::{node::FromAnyValue, NodeMut};
+
+/// A trait for watching for changes in the DOM tree.
+pub trait NodeWatcher<V: FromAnyValue + Send + Sync> {
+    /// Called after a node is added to the tree.
+    fn on_node_added(&self, _node: NodeMut<V>) {}
+    /// Called before a node is removed from the tree.
+    fn on_node_removed(&self, _node: NodeMut<V>) {}
+    /// Called after a node is moved to a new parent.
+    fn on_node_moved(&self, _node: NodeMut<V>) {}
+    // /// Called after the text content of a node is changed.
+    // fn on_text_changed(&self, _node: NodeMut<V>) {}
+    // /// Called after an attribute of an element is changed.
+    // fn on_attribute_changed(&self, _node: NodeMut<V>, attribute: &str) {}
+}

+ 3 - 3
packages/native-core/src/passes.rs

@@ -380,12 +380,12 @@ impl_dependancy!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O);
 impl_dependancy!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P);
 impl_dependancy!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P);
 
 
 pub fn resolve_passes<V: FromAnyValue + Send + Sync>(
 pub fn resolve_passes<V: FromAnyValue + Send + Sync>(
-    tree: &mut RealDom<V>,
+    dom: &mut RealDom<V>,
     dirty_nodes: DirtyNodeStates,
     dirty_nodes: DirtyNodeStates,
     ctx: SendAnyMap,
     ctx: SendAnyMap,
     parallel: bool,
     parallel: bool,
 ) -> FxDashSet<NodeId> {
 ) -> FxDashSet<NodeId> {
-    let passes = &tree.passes;
+    let passes = &dom.dirty_nodes.passes;
     let mut resolved_passes: FxHashSet<TypeId> = FxHashSet::default();
     let mut resolved_passes: FxHashSet<TypeId> = FxHashSet::default();
     let mut resolving = Vec::new();
     let mut resolving = Vec::new();
     let nodes_updated = Arc::new(FxDashSet::default());
     let nodes_updated = Arc::new(FxDashSet::default());
@@ -393,7 +393,7 @@ pub fn resolve_passes<V: FromAnyValue + Send + Sync>(
     let mut pass_indexes_remaining: Vec<_> = (0..passes.len()).collect::<Vec<_>>();
     let mut pass_indexes_remaining: Vec<_> = (0..passes.len()).collect::<Vec<_>>();
     while !pass_indexes_remaining.is_empty() {
     while !pass_indexes_remaining.is_empty() {
         let mut currently_in_use = FxHashSet::<TypeId>::default();
         let mut currently_in_use = FxHashSet::<TypeId>::default();
-        let dynamically_borrowed_tree = tree.tree.dynamically_borrowed();
+        let dynamically_borrowed_tree = dom.tree.dynamically_borrowed();
         rayon::in_place_scope(|s| {
         rayon::in_place_scope(|s| {
             let mut i = 0;
             let mut i = 0;
             while i < pass_indexes_remaining.len() {
             while i < pass_indexes_remaining.len() {

+ 152 - 140
packages/native-core/src/real_dom.rs

@@ -2,20 +2,22 @@ use rustc_hash::{FxHashMap, FxHashSet};
 use std::any::{Any, TypeId};
 use std::any::{Any, TypeId};
 use std::collections::VecDeque;
 use std::collections::VecDeque;
 use std::rc::Rc;
 use std::rc::Rc;
+use std::sync::RwLock;
 
 
 use crate::node::{
 use crate::node::{
     ElementNode, FromAnyValue, NodeType, OwnedAttributeDiscription, OwnedAttributeValue,
     ElementNode, FromAnyValue, NodeType, OwnedAttributeDiscription, OwnedAttributeValue,
 };
 };
 use crate::node_ref::{NodeMask, NodeMaskBuilder};
 use crate::node_ref::{NodeMask, NodeMaskBuilder};
+use crate::node_watcher::NodeWatcher;
 use crate::passes::{resolve_passes, DirtyNodeStates, TypeErasedPass};
 use crate::passes::{resolve_passes, DirtyNodeStates, TypeErasedPass};
 use crate::prelude::AttributeMaskBuilder;
 use crate::prelude::AttributeMaskBuilder;
 use crate::tree::{NodeId, Tree};
 use crate::tree::{NodeId, Tree};
 use crate::{FxDashSet, SendAnyMap};
 use crate::{FxDashSet, SendAnyMap};
 
 
-struct NodesDirty<V: FromAnyValue + Send + Sync> {
+pub(crate) struct NodesDirty<V: FromAnyValue + Send + Sync> {
     passes_updated: FxHashMap<NodeId, FxHashSet<TypeId>>,
     passes_updated: FxHashMap<NodeId, FxHashSet<TypeId>>,
     nodes_updated: FxHashMap<NodeId, NodeMask>,
     nodes_updated: FxHashMap<NodeId, NodeMask>,
-    passes: Rc<Box<[TypeErasedPass<V>]>>,
+    pub(crate) passes: Box<[TypeErasedPass<V>]>,
 }
 }
 
 
 impl<V: FromAnyValue + Send + Sync> NodesDirty<V> {
 impl<V: FromAnyValue + Send + Sync> NodesDirty<V> {
@@ -35,7 +37,7 @@ impl<V: FromAnyValue + Send + Sync> NodesDirty<V> {
 
 
     fn mark_parent_added_or_removed(&mut self, node_id: NodeId) {
     fn mark_parent_added_or_removed(&mut self, node_id: NodeId) {
         let hm = self.passes_updated.entry(node_id).or_default();
         let hm = self.passes_updated.entry(node_id).or_default();
-        for pass in &**self.passes {
+        for pass in &*self.passes {
             if pass.parent_dependant {
             if pass.parent_dependant {
                 hm.insert(pass.this_type_id);
                 hm.insert(pass.this_type_id);
             }
             }
@@ -44,7 +46,7 @@ impl<V: FromAnyValue + Send + Sync> NodesDirty<V> {
 
 
     fn mark_child_changed(&mut self, node_id: NodeId) {
     fn mark_child_changed(&mut self, node_id: NodeId) {
         let hm = self.passes_updated.entry(node_id).or_default();
         let hm = self.passes_updated.entry(node_id).or_default();
-        for pass in &**self.passes {
+        for pass in &*self.passes {
             if pass.child_dependant {
             if pass.child_dependant {
                 hm.insert(pass.this_type_id);
                 hm.insert(pass.this_type_id);
             }
             }
@@ -52,6 +54,8 @@ impl<V: FromAnyValue + Send + Sync> NodesDirty<V> {
     }
     }
 }
 }
 
 
+type NodeWatchers<V> = Rc<RwLock<Vec<Box<dyn NodeWatcher<V>>>>>;
+
 /// A Dom that can sync with the VirtualDom mutations intended for use in lazy renderers.
 /// A Dom that can sync with the VirtualDom mutations intended for use in lazy renderers.
 /// The render state passes from parent to children and or accumulates state from children to parents.
 /// The render state passes from parent to children and or accumulates state from children to parents.
 /// To get started implement [crate::state::ParentDepState], [crate::state::NodeDepState], or [crate::state::ChildDepState] and call [RealDom::apply_mutations] to update the dom and [RealDom::update_state] to update the state of the nodes.
 /// To get started implement [crate::state::ParentDepState], [crate::state::NodeDepState], or [crate::state::ChildDepState] and call [RealDom::apply_mutations] to update the dom and [RealDom::update_state] to update the state of the nodes.
@@ -61,8 +65,8 @@ impl<V: FromAnyValue + Send + Sync> NodesDirty<V> {
 pub struct RealDom<V: FromAnyValue + Send + Sync = ()> {
 pub struct RealDom<V: FromAnyValue + Send + Sync = ()> {
     pub(crate) tree: Tree,
     pub(crate) tree: Tree,
     nodes_listening: FxHashMap<String, FxHashSet<NodeId>>,
     nodes_listening: FxHashMap<String, FxHashSet<NodeId>>,
-    pub(crate) passes: Rc<Box<[TypeErasedPass<V>]>>,
-    dirty_nodes: NodesDirty<V>,
+    pub(crate) dirty_nodes: NodesDirty<V>,
+    node_watchers: NodeWatchers<V>,
     phantom: std::marker::PhantomData<V>,
     phantom: std::marker::PhantomData<V>,
 }
 }
 
 
@@ -94,7 +98,6 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
                 }
                 }
             }
             }
         }
         }
-        let passes = Rc::new(passes);
 
 
         let mut passes_updated = FxHashMap::default();
         let mut passes_updated = FxHashMap::default();
         let mut nodes_updated = FxHashMap::default();
         let mut nodes_updated = FxHashMap::default();
@@ -106,34 +109,32 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
         RealDom {
         RealDom {
             tree,
             tree,
             nodes_listening: FxHashMap::default(),
             nodes_listening: FxHashMap::default(),
-            passes: passes.clone(),
             dirty_nodes: NodesDirty {
             dirty_nodes: NodesDirty {
                 passes_updated,
                 passes_updated,
                 nodes_updated,
                 nodes_updated,
                 passes,
                 passes,
             },
             },
+            node_watchers: Default::default(),
             phantom: std::marker::PhantomData,
             phantom: std::marker::PhantomData,
         }
         }
     }
     }
 
 
-    pub fn create_node(&mut self, node: NodeType<V>, mark_dirty: bool) -> NodeMut<'_, V> {
+    pub fn create_node(&mut self, node: NodeType<V>) -> NodeMut<'_, V> {
         let mut node_entry = self.tree.create_node();
         let mut node_entry = self.tree.create_node();
         let id = node_entry.id();
         let id = node_entry.id();
-        if mark_dirty {
-            self.dirty_nodes
-                .passes_updated
-                .entry(id)
-                .or_default()
-                .extend(self.passes.iter().map(|x| x.this_type_id));
-        }
+        self.dirty_nodes
+            .passes_updated
+            .entry(id)
+            .or_default()
+            .extend(self.dirty_nodes.passes.iter().map(|x| x.this_type_id));
         node_entry.insert(node);
         node_entry.insert(node);
+        let watchers = self.node_watchers.clone();
+        for watcher in &*watchers.read().unwrap() {
+            watcher.on_node_added(NodeMut::new(id, self));
+        }
         NodeMut::new(id, self)
         NodeMut::new(id, self)
     }
     }
 
 
-    pub fn add_child(&mut self, node_id: NodeId, child_id: NodeId) {
-        self.tree.add_child(node_id, child_id);
-    }
-
     /// Find all nodes that are listening for an event, sorted by there height in the dom progressing starting at the bottom and progressing up.
     /// Find all nodes that are listening for an event, sorted by there height in the dom progressing starting at the bottom and progressing up.
     /// This can be useful to avoid creating duplicate events.
     /// This can be useful to avoid creating duplicate events.
     pub fn get_listening_sorted(&self, event: &str) -> Vec<NodeRef<V>> {
     pub fn get_listening_sorted(&self, event: &str) -> Vec<NodeRef<V>> {
@@ -166,12 +167,12 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
     pub fn clone_node(&mut self, node_id: NodeId) -> NodeId {
     pub fn clone_node(&mut self, node_id: NodeId) -> NodeId {
         let node = self.get(node_id).unwrap();
         let node = self.get(node_id).unwrap();
         let new_node = node.node_type().clone();
         let new_node = node.node_type().clone();
-        let new_id = self.create_node(new_node, true).id();
+        let new_id = self.create_node(new_node).id();
 
 
         let children = self.tree.children_ids(node_id).unwrap().to_vec();
         let children = self.tree.children_ids(node_id).unwrap().to_vec();
         for child in children {
         for child in children {
             let child_id = self.clone_node(child);
             let child_id = self.clone_node(child);
-            self.add_child(new_id, child_id);
+            self.get_mut(new_id).unwrap().add_child(child_id);
         }
         }
         new_id
         new_id
     }
     }
@@ -187,11 +188,9 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
     }
     }
 
 
     /// WARNING: This escapes the reactive system that the real dom uses. Any changes made with this method will not trigger updates in states when [RealDom::update_state] is called.
     /// WARNING: This escapes the reactive system that the real dom uses. Any changes made with this method will not trigger updates in states when [RealDom::update_state] is called.
-    pub fn get_mut_raw(&mut self, id: NodeId) -> Option<NodeMutRaw<V>> {
+    pub fn get_state_mut_raw<T: Any + Send + Sync>(&mut self, id: NodeId) -> Option<&mut T> {
         let id = id.into_node_id(self);
         let id = id.into_node_id(self);
-        self.tree
-            .contains(id)
-            .then_some(NodeMutRaw { id, dom: self })
+        self.tree.get_mut(id)
     }
     }
 
 
     /// Update the state of the dom, after appling some mutations. This will keep the nodes in the dom up to date with their VNode counterparts.
     /// Update the state of the dom, after appling some mutations. This will keep the nodes in the dom up to date with their VNode counterparts.
@@ -202,7 +201,8 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
     ) -> (FxDashSet<NodeId>, FxHashMap<NodeId, NodeMask>) {
     ) -> (FxDashSet<NodeId>, FxHashMap<NodeId, NodeMask>) {
         let passes = std::mem::take(&mut self.dirty_nodes.passes_updated);
         let passes = std::mem::take(&mut self.dirty_nodes.passes_updated);
         let nodes_updated = std::mem::take(&mut self.dirty_nodes.nodes_updated);
         let nodes_updated = std::mem::take(&mut self.dirty_nodes.nodes_updated);
-        let dirty_nodes = DirtyNodeStates::with_passes(self.passes.iter().map(|p| p.this_type_id));
+        let dirty_nodes =
+            DirtyNodeStates::with_passes(self.dirty_nodes.passes.iter().map(|p| p.this_type_id));
         for (node_id, passes) in passes {
         for (node_id, passes) in passes {
             // remove any nodes that were created and then removed in the same mutations from the dirty nodes list
             // remove any nodes that were created and then removed in the same mutations from the dirty nodes list
             if let Some(height) = self.tree.height(node_id) {
             if let Some(height) = self.tree.height(node_id) {
@@ -218,21 +218,6 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
         )
         )
     }
     }
 
 
-    pub fn remove(&mut self, id: NodeId) {
-        if let Some(parent_id) = self.tree.parent_id(id) {
-            self.dirty_nodes.mark_child_changed(parent_id);
-        }
-        self.tree.remove(id)
-    }
-
-    pub fn replace(&mut self, old: NodeId, new: NodeId) {
-        if let Some(parent_id) = self.tree.parent_id(old) {
-            self.dirty_nodes.mark_child_changed(parent_id);
-            self.dirty_nodes.mark_parent_added_or_removed(new);
-        }
-        self.tree.replace(old, new);
-    }
-
     pub fn traverse_depth_first(&self, mut f: impl FnMut(NodeRef<V>)) {
     pub fn traverse_depth_first(&self, mut f: impl FnMut(NodeRef<V>)) {
         let mut stack = vec![self.root_id()];
         let mut stack = vec![self.root_id()];
         while let Some(id) = stack.pop() {
         while let Some(id) = stack.pop() {
@@ -293,6 +278,10 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
     pub fn insert_slab<T: Any + Send + Sync>(&mut self) {
     pub fn insert_slab<T: Any + Send + Sync>(&mut self) {
         self.tree.insert_slab::<T>();
         self.tree.insert_slab::<T>();
     }
     }
+
+    pub fn add_node_watcher(&mut self, watcher: impl NodeWatcher<V> + 'static) {
+        self.node_watchers.write().unwrap().push(Box::new(watcher));
+    }
 }
 }
 
 
 pub trait IntoNodeId<V: FromAnyValue + Send + Sync> {
 pub trait IntoNodeId<V: FromAnyValue + Send + Sync> {
@@ -343,40 +332,52 @@ pub trait NodeImmutable<V: FromAnyValue + Send + Sync>: Sized {
             dom: self.real_dom(),
             dom: self.real_dom(),
         })
         })
     }
     }
-}
 
 
-pub trait NodeMutable<V: FromAnyValue + Send + Sync>: Sized + NodeImmutable<V> {
-    fn real_dom_mut(&mut self) -> &mut RealDom<V>;
-    fn get_mut<T: Any + Sync + Send>(&mut self) -> Option<&mut T> {
-        let id = self.id();
-        self.real_dom_mut().tree.get_mut(id)
-    }
-    fn insert<T: Any + Sync + Send>(&mut self, value: T) {
-        let id = self.id();
-        self.real_dom_mut().tree.insert(id, value);
-    }
-    fn add_child(&mut self, child: NodeId) {
-        let id = self.id();
-        self.real_dom_mut().tree.add_child(id, child);
-    }
-    fn insert_after(&mut self, old: NodeId) {
-        let id = self.id();
-        self.real_dom_mut().tree.insert_after(old, id);
+    fn next(&self) -> Option<NodeRef<V>> {
+        let parent = self.parent_id()?;
+        let children = self.real_dom().tree.children_ids(parent)?;
+        let index = children.iter().position(|id| *id == self.id())?;
+        if index + 1 < children.len() {
+            Some(NodeRef {
+                id: children[index + 1],
+                dom: self.real_dom(),
+            })
+        } else {
+            None
+        }
     }
     }
-    fn insert_before(&mut self, old: NodeId) {
-        let id = self.id();
-        self.real_dom_mut().tree.insert_before(old, id);
+
+    fn prev(&self) -> Option<NodeRef<V>> {
+        let parent = self.parent_id()?;
+        let children = self.real_dom().tree.children_ids(parent)?;
+        let index = children.iter().position(|id| *id == self.id())?;
+        if index > 0 {
+            Some(NodeRef {
+                id: children[index - 1],
+                dom: self.real_dom(),
+            })
+        } else {
+            None
+        }
     }
     }
-    fn add_event_listener(&mut self, event: &str);
-    fn remove_event_listener(&mut self, event: &str);
 }
 }
 
 
-#[derive(Clone, Copy)]
 pub struct NodeRef<'a, V: FromAnyValue + Send + Sync = ()> {
 pub struct NodeRef<'a, V: FromAnyValue + Send + Sync = ()> {
     id: NodeId,
     id: NodeId,
     dom: &'a RealDom<V>,
     dom: &'a RealDom<V>,
 }
 }
 
 
+impl<'a, V: FromAnyValue + Send + Sync> Clone for NodeRef<'a, V> {
+    fn clone(&self) -> Self {
+        Self {
+            id: self.id,
+            dom: self.dom,
+        }
+    }
+}
+
+impl<'a, V: FromAnyValue + Send + Sync> Copy for NodeRef<'a, V> {}
+
 impl<'a, V: FromAnyValue + Send + Sync> NodeImmutable<V> for NodeRef<'a, V> {
 impl<'a, V: FromAnyValue + Send + Sync> NodeImmutable<V> for NodeRef<'a, V> {
     fn real_dom(&self) -> &RealDom<V> {
     fn real_dom(&self) -> &RealDom<V> {
         self.dom
         self.dom
@@ -408,12 +409,12 @@ impl<'a, V: FromAnyValue + Send + Sync> NodeImmutable<V> for NodeMut<'a, V> {
     }
     }
 }
 }
 
 
-impl<'a, V: FromAnyValue + Send + Sync> NodeMutable<V> for NodeMut<'a, V> {
-    fn real_dom_mut(&mut self) -> &mut RealDom<V> {
+impl<'a, V: FromAnyValue + Send + Sync> NodeMut<'a, V> {
+    pub fn real_dom_mut(&mut self) -> &mut RealDom<V> {
         self.dom
         self.dom
     }
     }
 
 
-    fn get_mut<T: Any + Sync + Send>(&mut self) -> Option<&mut T> {
+    pub fn get_mut<T: Any + Sync + Send>(&mut self) -> Option<&mut T> {
         // mark the node state as dirty
         // mark the node state as dirty
         self.dom
         self.dom
             .dirty_nodes
             .dirty_nodes
@@ -424,7 +425,7 @@ impl<'a, V: FromAnyValue + Send + Sync> NodeMutable<V> for NodeMut<'a, V> {
         self.dom.tree.get_mut(self.id)
         self.dom.tree.get_mut(self.id)
     }
     }
 
 
-    fn insert<T: Any + Sync + Send>(&mut self, value: T) {
+    pub fn insert<T: Any + Sync + Send>(&mut self, value: T) {
         // mark the node state as dirty
         // mark the node state as dirty
         self.dom
         self.dom
             .dirty_nodes
             .dirty_nodes
@@ -435,25 +436,87 @@ impl<'a, V: FromAnyValue + Send + Sync> NodeMutable<V> for NodeMut<'a, V> {
         self.dom.tree.insert(self.id, value);
         self.dom.tree.insert(self.id, value);
     }
     }
 
 
-    fn insert_after(&mut self, old: NodeId) {
+    pub fn next_mut(self) -> Option<NodeMut<'a, V>> {
+        let parent = self.parent_id()?;
+        let children = self.dom.tree.children_ids(parent)?;
+        let index = children.iter().position(|id| *id == self.id)?;
+        if index + 1 < children.len() {
+            Some(NodeMut::new(children[index + 1], self.dom))
+        } else {
+            None
+        }
+    }
+
+    pub fn prev_mut(self) -> Option<NodeMut<'a, V>> {
+        let parent = self.parent_id()?;
+        let children = self.dom.tree.children_ids(parent)?;
+        let index = children.iter().position(|id| *id == self.id)?;
+        if index > 0 {
+            Some(NodeMut::new(children[index - 1], self.dom))
+        } else {
+            None
+        }
+    }
+
+    pub fn add_child(&mut self, child: NodeId) {
+        self.dom.dirty_nodes.mark_child_changed(self.id);
+        self.dom.dirty_nodes.mark_parent_added_or_removed(child);
+        self.dom.tree.add_child(self.id, child);
+        NodeMut::new(child, self.dom).mark_moved();
+    }
+
+    pub fn insert_after(&mut self, old: NodeId) {
         let id = self.id();
         let id = self.id();
         if let Some(parent_id) = self.dom.tree.parent_id(old) {
         if let Some(parent_id) = self.dom.tree.parent_id(old) {
             self.dom.dirty_nodes.mark_child_changed(parent_id);
             self.dom.dirty_nodes.mark_child_changed(parent_id);
             self.dom.dirty_nodes.mark_parent_added_or_removed(id);
             self.dom.dirty_nodes.mark_parent_added_or_removed(id);
         }
         }
         self.dom.tree.insert_after(old, id);
         self.dom.tree.insert_after(old, id);
+        self.mark_moved();
     }
     }
 
 
-    fn insert_before(&mut self, old: NodeId) {
+    pub fn insert_before(&mut self, old: NodeId) {
         let id = self.id();
         let id = self.id();
         if let Some(parent_id) = self.dom.tree.parent_id(old) {
         if let Some(parent_id) = self.dom.tree.parent_id(old) {
             self.dom.dirty_nodes.mark_child_changed(parent_id);
             self.dom.dirty_nodes.mark_child_changed(parent_id);
             self.dom.dirty_nodes.mark_parent_added_or_removed(id);
             self.dom.dirty_nodes.mark_parent_added_or_removed(id);
         }
         }
         self.dom.tree.insert_before(old, id);
         self.dom.tree.insert_before(old, id);
+        self.mark_moved();
+    }
+
+    pub fn remove(&mut self) {
+        let id = self.id();
+        self.mark_removed();
+        if let Some(parent_id) = self.real_dom_mut().tree.parent_id(id) {
+            self.real_dom_mut()
+                .dirty_nodes
+                .mark_child_changed(parent_id);
+        }
+        if let Some(children_ids) = self.child_ids() {
+            let children_ids_vec = children_ids.to_vec();
+            for child in children_ids_vec {
+                self.dom.get_mut(child).unwrap().remove();
+            }
+        }
+        self.dom.tree.remove_single(id);
+    }
+
+    pub fn replace(&mut self, new: NodeId) {
+        self.mark_removed();
+        if let Some(parent_id) = self.parent_id() {
+            self.real_dom_mut()
+                .dirty_nodes
+                .mark_child_changed(parent_id);
+            self.real_dom_mut()
+                .dirty_nodes
+                .mark_parent_added_or_removed(new);
+        }
+        let id = self.id();
+        self.dom.tree.replace(id, new);
     }
     }
 
 
-    fn add_event_listener(&mut self, event: &str) {
+    pub fn add_event_listener(&mut self, event: &str) {
         let id = self.id();
         let id = self.id();
         let node_type: &mut NodeType<V> = self.dom.tree.get_mut(self.id).unwrap();
         let node_type: &mut NodeType<V> = self.dom.tree.get_mut(self.id).unwrap();
         if let NodeType::Element(ElementNode { listeners, .. }) = node_type {
         if let NodeType::Element(ElementNode { listeners, .. }) = node_type {
@@ -474,7 +537,7 @@ impl<'a, V: FromAnyValue + Send + Sync> NodeMutable<V> for NodeMut<'a, V> {
         }
         }
     }
     }
 
 
-    fn remove_event_listener(&mut self, event: &str) {
+    pub fn remove_event_listener(&mut self, event: &str) {
         let id = self.id();
         let id = self.id();
         let node_type: &mut NodeType<V> = self.dom.tree.get_mut(self.id).unwrap();
         let node_type: &mut NodeType<V> = self.dom.tree.get_mut(self.id).unwrap();
         if let NodeType::Element(ElementNode { listeners, .. }) = node_type {
         if let NodeType::Element(ElementNode { listeners, .. }) = node_type {
@@ -486,9 +549,21 @@ impl<'a, V: FromAnyValue + Send + Sync> NodeMutable<V> for NodeMut<'a, V> {
             self.dom.nodes_listening.get_mut(event).unwrap().remove(&id);
             self.dom.nodes_listening.get_mut(event).unwrap().remove(&id);
         }
         }
     }
     }
-}
 
 
-impl<'a, V: FromAnyValue + Send + Sync> NodeMut<'a, V> {
+    fn mark_removed(&mut self) {
+        let watchers = self.dom.node_watchers.clone();
+        for watcher in &*watchers.read().unwrap() {
+            watcher.on_node_removed(NodeMut::new(self.id(), self.dom));
+        }
+    }
+
+    fn mark_moved(&mut self) {
+        let watchers = self.dom.node_watchers.clone();
+        for watcher in &*watchers.read().unwrap() {
+            watcher.on_node_moved(NodeMut::new(self.id(), self.dom));
+        }
+    }
+
     pub fn node_type_mut(&mut self) -> NodeTypeMut<'_, V> {
     pub fn node_type_mut(&mut self) -> NodeTypeMut<'_, V> {
         let Self { id, dom } = self;
         let Self { id, dom } = self;
         let RealDom {
         let RealDom {
@@ -503,6 +578,7 @@ impl<'a, V: FromAnyValue + Send + Sync> NodeMut<'a, V> {
             }),
             }),
             NodeType::Text(text) => {
             NodeType::Text(text) => {
                 dirty_nodes.mark_dirty(self.id, NodeMaskBuilder::new().with_text().build());
                 dirty_nodes.mark_dirty(self.id, NodeMaskBuilder::new().with_text().build());
+
                 NodeTypeMut::Text(text)
                 NodeTypeMut::Text(text)
             }
             }
             NodeType::Placeholder => NodeTypeMut::Placeholder,
             NodeType::Placeholder => NodeTypeMut::Placeholder,
@@ -554,18 +630,6 @@ impl<V: FromAnyValue + Send + Sync> ElementNodeMut<'_, V> {
         &self.element.attributes
         &self.element.attributes
     }
     }
 
 
-    pub fn attributes_mut(
-        &mut self,
-    ) -> &mut FxHashMap<OwnedAttributeDiscription, OwnedAttributeValue<V>> {
-        self.dirty_nodes.mark_dirty(
-            self.id,
-            NodeMaskBuilder::new()
-                .with_attrs(AttributeMaskBuilder::All)
-                .build(),
-        );
-        &mut self.element.attributes
-    }
-
     pub fn set_attribute(
     pub fn set_attribute(
         &mut self,
         &mut self,
         name: OwnedAttributeDiscription,
         name: OwnedAttributeDiscription,
@@ -610,55 +674,3 @@ impl<V: FromAnyValue + Send + Sync> ElementNodeMut<'_, V> {
         &self.element.listeners
         &self.element.listeners
     }
     }
 }
 }
-
-pub struct NodeMutRaw<'a, V: FromAnyValue + Send + Sync = ()> {
-    id: NodeId,
-    dom: &'a mut RealDom<V>,
-}
-
-impl<'a, V: FromAnyValue + Send + Sync> NodeMutRaw<'a, V> {
-    fn node_type_mut(&mut self) -> &mut NodeType<V> {
-        self.dom.tree.get_mut::<NodeType<V>>(self.id).unwrap()
-    }
-}
-
-impl<'a, V: FromAnyValue + Send + Sync> NodeImmutable<V> for NodeMutRaw<'a, V> {
-    fn real_dom(&self) -> &RealDom<V> {
-        self.dom
-    }
-
-    fn id(&self) -> NodeId {
-        self.id
-    }
-}
-
-impl<'a, V: FromAnyValue + Send + Sync> NodeMutable<V> for NodeMutRaw<'a, V> {
-    fn real_dom_mut(&mut self) -> &mut RealDom<V> {
-        self.dom
-    }
-
-    fn add_event_listener(&mut self, event: &str) {
-        let id = self.id();
-        if let NodeType::Element(element) = self.node_type_mut() {
-            element.listeners.insert(event.to_string());
-            match self.dom.nodes_listening.get_mut(event) {
-                Some(hs) => {
-                    hs.insert(id);
-                }
-                None => {
-                    let mut hs = FxHashSet::default();
-                    hs.insert(id);
-                    self.dom.nodes_listening.insert(event.to_string(), hs);
-                }
-            }
-        }
-    }
-
-    fn remove_event_listener(&mut self, event: &str) {
-        let id = self.id();
-        if let NodeType::Element(element) = self.node_type_mut() {
-            element.listeners.remove(event);
-        }
-        self.dom.nodes_listening.get_mut(event).unwrap().remove(&id);
-    }
-}

+ 12 - 0
packages/native-core/src/tree.rs

@@ -80,6 +80,18 @@ impl Tree {
         recurse(self, id);
         recurse(self, id);
     }
     }
 
 
+    pub fn remove_single(&mut self, id: NodeId) {
+        {
+            let node_data_mut = self.node_slab_mut();
+            if let Some(parent) = node_data_mut.get(id).unwrap().parent {
+                let parent = node_data_mut.get_mut(parent).unwrap();
+                parent.children.retain(|&child| child != id);
+            }
+        }
+
+        self.nodes.remove(id);
+    }
+
     fn set_height(&mut self, node: NodeId, height: u16) {
     fn set_height(&mut self, node: NodeId, height: u16) {
         let children = {
         let children = {
             let mut node = self.get_node_data_mut(node);
             let mut node = self.get_node_data_mut(node);

+ 2 - 2
packages/native-core/src/utils/mod.rs

@@ -1,3 +1,3 @@
-// mod persistant_iterator;
-// pub use persistant_iterator::*;
+mod persistant_iterator;
+pub use persistant_iterator::*;
 pub mod cursor;
 pub mod cursor;

+ 91 - 172
packages/native-core/src/utils/persistant_iterator.rs

@@ -1,10 +1,15 @@
+use smallvec::SmallVec;
+
 use crate::{
 use crate::{
-    node::{ElementNode, FromAnyValue, NodeType},
+    node::FromAnyValue,
+    node_watcher::NodeWatcher,
     real_dom::{NodeImmutable, RealDom},
     real_dom::{NodeImmutable, RealDom},
-    NodeId,
+    NodeId, NodeRef,
+};
+use std::{
+    fmt::Debug,
+    sync::{Arc, Mutex},
 };
 };
-use dioxus_core::{Mutation, Mutations};
-use std::fmt::Debug;
 
 
 #[derive(Debug)]
 #[derive(Debug)]
 pub enum ElementProduced {
 pub enum ElementProduced {
@@ -23,27 +28,36 @@ impl ElementProduced {
     }
     }
 }
 }
 
 
-#[derive(Debug)]
-enum NodePosition {
-    AtNode,
-    InChild(usize),
+struct PersistantElementIterUpdater<V> {
+    stack: Arc<Mutex<smallvec::SmallVec<[NodeId; 5]>>>,
+    phantom: std::marker::PhantomData<V>,
 }
 }
 
 
-impl NodePosition {
-    fn map(&self, mut f: impl FnMut(usize) -> usize) -> Self {
-        match self {
-            Self::AtNode => Self::AtNode,
-            Self::InChild(i) => Self::InChild(f(*i)),
+impl<V: FromAnyValue + Sync + Send> NodeWatcher<V> for PersistantElementIterUpdater<V> {
+    fn on_node_moved(&self, node: crate::NodeMut<V>) {
+        // if any element is moved, update its parents in the stack
+        let mut stack = self.stack.lock().unwrap();
+        let moved = node.id();
+        let rdom = node.real_dom();
+        if let Some(r) = stack.iter().position(|el_id| *el_id == moved) {
+            let back = &stack[r..];
+            let mut new = SmallVec::new();
+            let mut parent = node.parent_id();
+            while let Some(p) = parent.and_then(|id| rdom.get(id)) {
+                new.push(p.id());
+                parent = p.parent_id();
+            }
+            new.extend(back.iter().copied());
+            *stack = new;
         }
         }
     }
     }
 
 
-    fn get_or_insert(&mut self, child_idx: usize) -> usize {
-        match self {
-            Self::AtNode => {
-                *self = Self::InChild(child_idx);
-                child_idx
-            }
-            Self::InChild(i) => *i,
+    fn on_node_removed(&self, node: crate::NodeMut<V>) {
+        // if any element is removed in the chain, remove it and its children from the stack
+        let mut stack = self.stack.lock().unwrap();
+        let removed = node.id();
+        if let Some(r) = stack.iter().position(|el_id| *el_id == removed) {
+            stack.truncate(r);
         }
         }
     }
     }
 }
 }
@@ -53,118 +67,47 @@ impl NodePosition {
 /// Iterate through it with [PersistantElementIter::next] [PersistantElementIter::prev], and update it with [PersistantElementIter::prune] (with data from [`dioxus_core::prelude::VirtualDom::work_with_deadline`]).
 /// Iterate through it with [PersistantElementIter::next] [PersistantElementIter::prev], and update it with [PersistantElementIter::prune] (with data from [`dioxus_core::prelude::VirtualDom::work_with_deadline`]).
 /// The iterator loops around when it reaches the end or the beginning.
 /// The iterator loops around when it reaches the end or the beginning.
 pub struct PersistantElementIter {
 pub struct PersistantElementIter {
-    // stack of elements and fragments
-    stack: smallvec::SmallVec<[(NodeId, NodePosition); 5]>,
-}
-
-impl Default for PersistantElementIter {
-    fn default() -> Self {
-        PersistantElementIter {
-            stack: smallvec::smallvec![(NodeId(0), NodePosition::AtNode)],
-        }
-    }
+    // stack of elements and fragments, the last element is the last element that was yielded
+    stack: Arc<Mutex<smallvec::SmallVec<[NodeId; 5]>>>,
 }
 }
 
 
 impl PersistantElementIter {
 impl PersistantElementIter {
-    pub fn new() -> Self {
-        Self::default()
-    }
+    pub fn create<V: FromAnyValue + Send + Sync>(rdom: &mut RealDom<V>) -> Self {
+        let inner = Arc::new(Mutex::new(smallvec::smallvec![NodeId(0)]));
 
 
-    /// remove stale element refreneces
-    /// returns true if the focused element is removed
-    pub fn prune<V: FromAnyValue + Send + Sync>(
-        &mut self,
-        mutations: &Mutations,
-        rdom: &RealDom<V>,
-    ) -> bool {
-        let mut changed = false;
-        let ids_removed: Vec<_> = mutations
-            .edits
-            .iter()
-            .filter_map(|m| {
-                // nodes within templates will never be removed
-                match m {
-                    Mutation::Remove { id } => Some(rdom.element_to_node_id(*id)),
-                    Mutation::ReplaceWith { id, .. } => Some(rdom.element_to_node_id(*id)),
-                    _ => None,
-                }
-            })
-            .collect();
-        // if any element is removed in the chain, remove it and its children from the stack
-        if let Some(r) = self
-            .stack
-            .iter()
-            .position(|(el_id, _)| ids_removed.iter().any(|id| el_id == id))
-        {
-            self.stack.truncate(r);
-            changed = true;
-        }
-        // if a child is removed or inserted before or at the current element, update the child index
-        for (el_id, child_idx) in self.stack.iter_mut() {
-            if let NodePosition::InChild(child_idx) = child_idx {
-                if let Some(children) = &rdom.get(*el_id).unwrap().child_ids() {
-                    for m in &mutations.edits {
-                        match m {
-                            Mutation::Remove { id } => {
-                                let id = rdom.element_to_node_id(*id);
-                                if children.iter().take(*child_idx + 1).any(|c| *c == id) {
-                                    *child_idx -= 1;
-                                }
-                            }
-                            Mutation::InsertBefore { id, m } => {
-                                let id = rdom.element_to_node_id(*id);
-                                if children.iter().take(*child_idx + 1).any(|c| *c == id) {
-                                    *child_idx += *m;
-                                }
-                            }
-                            Mutation::InsertAfter { id, m } => {
-                                let id = rdom.element_to_node_id(*id);
-                                if children.iter().take(*child_idx).any(|c| *c == id) {
-                                    *child_idx += *m;
-                                }
-                            }
-                            _ => (),
-                        }
-                    }
-                }
-            }
-        }
-        changed
+        rdom.add_node_watcher(PersistantElementIterUpdater {
+            stack: inner.clone(),
+            phantom: std::marker::PhantomData,
+        });
+
+        PersistantElementIter { stack: inner }
     }
     }
 
 
     /// get the next element
     /// get the next element
     pub fn next<V: FromAnyValue + Send + Sync>(&mut self, rdom: &RealDom<V>) -> ElementProduced {
     pub fn next<V: FromAnyValue + Send + Sync>(&mut self, rdom: &RealDom<V>) -> ElementProduced {
-        if self.stack.is_empty() {
+        let mut stack = self.stack.lock().unwrap();
+        if stack.is_empty() {
             let id = NodeId(0);
             let id = NodeId(0);
-            let new = (id, NodePosition::AtNode);
-            self.stack.push(new);
+            let new = id;
+            stack.push(new);
             ElementProduced::Looped(id)
             ElementProduced::Looped(id)
         } else {
         } else {
-            let (last, old_child_idx) = self.stack.last_mut().unwrap();
-            let node = rdom.get(*last).unwrap();
-            match node.node_type() {
-                NodeType::Element(ElementNode { .. }) => {
-                    let children = node.child_ids().unwrap();
-                    *old_child_idx = old_child_idx.map(|i| i + 1);
-                    // if we have children, go to the next child
-                    let child_idx = old_child_idx.get_or_insert(0);
-                    if child_idx >= children.len() {
-                        self.pop();
-                        self.next(rdom)
-                    } else {
-                        let id = children[child_idx];
-                        if let NodeType::Element(ElementNode { .. }) =
-                            rdom.get(id).unwrap().node_type()
-                        {
-                            self.stack.push((id, NodePosition::AtNode));
-                        }
-                        ElementProduced::Progressed(id)
+            loop {
+                let last = stack.pop().unwrap();
+                if let Some(current) = rdom.get(last) {
+                    if let Some(new) = current.next() {
+                        // the next element exists, add it to the stack and return it
+                        let new = new.id();
+                        stack.push(new);
+                        return ElementProduced::Progressed(new);
                     }
                     }
-                }
-
-                NodeType::Text { .. } | NodeType::Placeholder { .. } => {
-                    // we are at a leaf, so we are done
-                    ElementProduced::Progressed(self.pop())
+                    // otherwise, continue the loop and go to the parent
+                } else {
+                    // if there is no parent, loop back to the root
+                    let new = NodeId(0);
+                    stack.clear();
+                    stack.push(new);
+                    return ElementProduced::Looped(new);
                 }
                 }
             }
             }
         }
         }
@@ -174,68 +117,44 @@ impl PersistantElementIter {
     pub fn prev<V: FromAnyValue + Send + Sync>(&mut self, rdom: &RealDom<V>) -> ElementProduced {
     pub fn prev<V: FromAnyValue + Send + Sync>(&mut self, rdom: &RealDom<V>) -> ElementProduced {
         // recursively add the last child element to the stack
         // recursively add the last child element to the stack
         fn push_back<V: FromAnyValue + Send + Sync>(
         fn push_back<V: FromAnyValue + Send + Sync>(
-            stack: &mut smallvec::SmallVec<[(NodeId, NodePosition); 5]>,
-            new_node: NodeId,
-            rdom: &RealDom<V>,
+            stack: &mut smallvec::SmallVec<[NodeId; 5]>,
+            node: NodeRef<V>,
         ) -> NodeId {
         ) -> NodeId {
-            let node = rdom.get(new_node).unwrap();
-            match node.node_type() {
-                NodeType::Element(ElementNode { .. }) => {
-                    let children = node.child_ids().unwrap();
-                    if children.is_empty() {
-                        new_node
-                    } else {
-                        stack.push((new_node, NodePosition::InChild(children.len() - 1)));
-                        push_back(stack, *children.last().unwrap(), rdom)
-                    }
+            stack.push(node.id());
+            if let Some(children) = node.children() {
+                if let Some(last) = children.last() {
+                    push_back(stack, *last)
+                } else {
+                    node.id()
                 }
                 }
-                _ => new_node,
+            } else {
+                node.id()
             }
             }
         }
         }
-        if self.stack.is_empty() {
-            let new_node = NodeId(0);
-            ElementProduced::Looped(push_back(&mut self.stack, new_node, rdom))
+        let mut stack = self.stack.lock().unwrap();
+        if stack.is_empty() {
+            let id = NodeId(0);
+            let last = push_back(&mut stack, rdom.get(id).unwrap());
+            ElementProduced::Looped(last)
         } else {
         } else {
-            let (last, old_child_idx) = self.stack.last_mut().unwrap();
-            let node = rdom.get(*last).unwrap();
-            match node.node_type() {
-                NodeType::Element(ElementNode { .. }) => {
-                    let children = node.child_ids().unwrap();
-                    // if we have children, go to the next child
-                    if let NodePosition::InChild(0) = old_child_idx {
-                        ElementProduced::Progressed(self.pop())
-                    } else {
-                        *old_child_idx = old_child_idx.map(|i| i - 1);
-                        if let NodePosition::InChild(child_idx) = old_child_idx {
-                            if *child_idx >= children.len() || children.is_empty() {
-                                self.pop();
-                                self.prev(rdom)
-                            } else {
-                                let new_node = children[*child_idx];
-                                ElementProduced::Progressed(push_back(
-                                    &mut self.stack,
-                                    new_node,
-                                    rdom,
-                                ))
-                            }
-                        } else {
-                            self.pop();
-                            self.prev(rdom)
-                        }
+            loop {
+                let last = stack.pop().unwrap();
+                if let Some(current) = rdom.get(last) {
+                    if let Some(new) = current.prev() {
+                        // the next element exists, add it to the stack and return it
+                        let new = push_back(&mut stack, new);
+                        return ElementProduced::Progressed(new);
                     }
                     }
-                }
-
-                NodeType::Text { .. } | NodeType::Placeholder { .. } => {
-                    // we are at a leaf, so we are done
-                    ElementProduced::Progressed(self.pop())
+                    // otherwise, continue the loop and go to the parent
+                } else {
+                    // if there is no parent, loop back to the root
+                    let id = NodeId(0);
+                    let last = push_back(&mut stack, rdom.get(id).unwrap());
+                    return ElementProduced::Looped(last);
                 }
                 }
             }
             }
         }
         }
     }
     }
-
-    fn pop(&mut self) -> NodeId {
-        self.stack.pop().unwrap().0
-    }
 }
 }
 
 
 #[test]
 #[test]

+ 8 - 8
packages/native-core/tests/passes.rs

@@ -307,14 +307,14 @@ fn down_pass() {
     }
     }
 
 
     let mut tree: RealDom = RealDom::new(Box::new([AddNumber::to_type_erased()]));
     let mut tree: RealDom = RealDom::new(Box::new([AddNumber::to_type_erased()]));
-    let grandchild1 = tree.create_node(create_blank_element(), true);
+    let grandchild1 = tree.create_node(create_blank_element());
     let grandchild1 = grandchild1.id();
     let grandchild1 = grandchild1.id();
-    let mut child1 = tree.create_node(create_blank_element(), true);
+    let mut child1 = tree.create_node(create_blank_element());
     child1.add_child(grandchild1);
     child1.add_child(grandchild1);
     let child1 = child1.id();
     let child1 = child1.id();
-    let grandchild2 = tree.create_node(create_blank_element(), true);
+    let grandchild2 = tree.create_node(create_blank_element());
     let grandchild2 = grandchild2.id();
     let grandchild2 = grandchild2.id();
-    let mut child2 = tree.create_node(create_blank_element(), true);
+    let mut child2 = tree.create_node(create_blank_element());
     child2.add_child(grandchild2);
     child2.add_child(grandchild2);
     let child2 = child2.id();
     let child2 = child2.id();
     let mut parent = tree.get_mut(tree.root_id()).unwrap();
     let mut parent = tree.get_mut(tree.root_id()).unwrap();
@@ -395,14 +395,14 @@ fn up_pass() {
     }
     }
 
 
     let mut tree: RealDom = RealDom::new(Box::new([AddNumber::to_type_erased()]));
     let mut tree: RealDom = RealDom::new(Box::new([AddNumber::to_type_erased()]));
-    let grandchild1 = tree.create_node(create_blank_element(), true);
+    let grandchild1 = tree.create_node(create_blank_element());
     let grandchild1 = grandchild1.id();
     let grandchild1 = grandchild1.id();
-    let mut child1 = tree.create_node(create_blank_element(), true);
+    let mut child1 = tree.create_node(create_blank_element());
     child1.add_child(grandchild1);
     child1.add_child(grandchild1);
     let child1 = child1.id();
     let child1 = child1.id();
-    let grandchild2 = tree.create_node(create_blank_element(), true);
+    let grandchild2 = tree.create_node(create_blank_element());
     let grandchild2 = grandchild2.id();
     let grandchild2 = grandchild2.id();
-    let mut child2 = tree.create_node(create_blank_element(), true);
+    let mut child2 = tree.create_node(create_blank_element());
     child2.add_child(grandchild2);
     child2.add_child(grandchild2);
     let child2 = child2.id();
     let child2 = child2.id();
     let mut parent = tree.get_mut(tree.root_id()).unwrap();
     let mut parent = tree.get_mut(tree.root_id()).unwrap();