Browse Source

intial update to new mutations

Evan Almloff 2 years ago
parent
commit
dcad2fe8a2

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

@@ -5,8 +5,6 @@ pub mod node;
 pub mod node_ref;
 pub mod real_dom;
 pub mod state;
-#[doc(hidden)]
-pub mod traversable;
 pub mod tree;
 pub mod utils;
 

+ 7 - 21
packages/native-core/src/node.rs

@@ -1,4 +1,4 @@
-use crate::{state::State, tree::NodeId, RealNodeId};
+use crate::{state::State, tree::NodeId};
 use dioxus_core::ElementId;
 use rustc_hash::{FxHashMap, FxHashSet};
 
@@ -13,12 +13,15 @@ pub struct Node<S: State> {
 
 #[derive(Debug, Clone)]
 pub struct NodeData {
+    /// The id of the node
+    pub node_id: NodeId,
     /// The id of the node in the vdom.
     pub element_id: Option<ElementId>,
     /// Additional inforation specific to the node type
     pub node_type: NodeType,
     /// The number of parents before the root node. The root node has height 1.
     pub height: u16,
+    height_dirty: bool,
 }
 
 /// A type of node with data specific to the node type. The types are a subset of the [VNode] types.
@@ -29,7 +32,7 @@ pub enum NodeType {
     },
     Element {
         tag: String,
-        namespace: Option<&'static str>,
+        namespace: Option<String>,
         attributes: FxHashMap<OwnedAttributeDiscription, OwnedAttributeValue>,
         listeners: FxHashSet<String>,
     },
@@ -44,29 +47,12 @@ impl<S: State> Node<S> {
                 element_id: None,
                 node_type,
                 height: 0,
+                node_id: NodeId(0),
+                height_dirty: true,
             },
         }
     }
 
-    /// link a child node
-    fn add_child(&mut self, child: RealNodeId) {
-        if let NodeType::Element { children, .. } = &mut self.node_data.node_type {
-            children.push(child);
-        }
-    }
-
-    /// remove a child node
-    fn remove_child(&mut self, child: RealNodeId) {
-        if let NodeType::Element { children, .. } = &mut self.node_data.node_type {
-            children.retain(|c| c != &child);
-        }
-    }
-
-    /// link the parent node
-    fn set_parent(&mut self, parent: RealNodeId) {
-        self.node_data.parent = Some(parent);
-    }
-
     /// get the mounted id of the node
     pub fn mounted_id(&self) -> Option<ElementId> {
         self.node_data.element_id

+ 32 - 20
packages/native-core/src/node_ref.rs

@@ -42,7 +42,7 @@ impl<'a> NodeView<'a> {
         self.mask
             .namespace
             .then_some(match &self.inner.node_type {
-                NodeType::Element { namespace, .. } => *namespace,
+                NodeType::Element { namespace, .. } => namespace.as_deref(),
                 _ => None,
             })
             .flatten()
@@ -93,7 +93,7 @@ impl<'a> NodeView<'a> {
 pub enum AttributeMask {
     All,
     /// A list of attribute names that are visible, this list must be sorted
-    Dynamic(Vec<&'static str>),
+    Dynamic(Vec<String>),
     /// A list of attribute names that are visible, this list must be sorted
     Static(&'static [&'static str]),
 }
@@ -105,14 +105,14 @@ impl AttributeMask {
     fn contains_attribute(&self, attr: &str) -> bool {
         match self {
             AttributeMask::All => true,
-            AttributeMask::Dynamic(l) => l.binary_search(&attr).is_ok(),
+            AttributeMask::Dynamic(l) => l.binary_search_by_key(&attr, |s| s.as_str()).is_ok(),
             AttributeMask::Static(l) => l.binary_search(&attr).is_ok(),
         }
     }
 
     /// Create a new dynamic attribute mask with a single attribute
-    pub fn single(new: &'static str) -> Self {
-        Self::Dynamic(vec![new])
+    pub fn single(new: &str) -> Self {
+        Self::Dynamic(vec![new.to_string()])
     }
 
     /// Ensure the attribute list is sorted.
@@ -133,15 +133,27 @@ impl AttributeMask {
     /// Combine two attribute masks
     pub fn union(&self, other: &Self) -> Self {
         let new = match (self, other) {
-            (AttributeMask::Dynamic(s), AttributeMask::Dynamic(o)) => AttributeMask::Dynamic(
-                union_ordered_iter(s.iter().copied(), o.iter().copied(), s.len() + o.len()),
-            ),
-            (AttributeMask::Static(s), AttributeMask::Dynamic(o)) => AttributeMask::Dynamic(
-                union_ordered_iter(s.iter().copied(), o.iter().copied(), s.len() + o.len()),
-            ),
-            (AttributeMask::Dynamic(s), AttributeMask::Static(o)) => AttributeMask::Dynamic(
-                union_ordered_iter(s.iter().copied(), o.iter().copied(), s.len() + o.len()),
-            ),
+            (AttributeMask::Dynamic(s), AttributeMask::Dynamic(o)) => {
+                AttributeMask::Dynamic(union_ordered_iter(
+                    s.iter().map(|s| s.as_str()),
+                    o.iter().map(|s| s.as_str()),
+                    s.len() + o.len(),
+                ))
+            }
+            (AttributeMask::Static(s), AttributeMask::Dynamic(o)) => {
+                AttributeMask::Dynamic(union_ordered_iter(
+                    s.iter().copied(),
+                    o.iter().map(|s| s.as_str()),
+                    s.len() + o.len(),
+                ))
+            }
+            (AttributeMask::Dynamic(s), AttributeMask::Static(o)) => {
+                AttributeMask::Dynamic(union_ordered_iter(
+                    s.iter().map(|s| s.as_str()),
+                    o.iter().copied(),
+                    s.len() + o.len(),
+                ))
+            }
             (AttributeMask::Static(s), AttributeMask::Static(o)) => AttributeMask::Dynamic(
                 union_ordered_iter(s.iter().copied(), o.iter().copied(), s.len() + o.len()),
             ),
@@ -153,9 +165,9 @@ impl AttributeMask {
 
     /// Check if two attribute masks overlap
     fn overlaps(&self, other: &Self) -> bool {
-        fn overlaps_iter(
-            self_iter: impl Iterator<Item = &'static str>,
-            mut other_iter: impl Iterator<Item = &'static str>,
+        fn overlaps_iter<'a>(
+            self_iter: impl Iterator<Item = &'a str>,
+            mut other_iter: impl Iterator<Item = &'a str>,
         ) -> bool {
             if let Some(mut other_attr) = other_iter.next() {
                 for self_attr in self_iter {
@@ -180,13 +192,13 @@ impl AttributeMask {
             (AttributeMask::Dynamic(v), AttributeMask::All) => !v.is_empty(),
             (AttributeMask::Static(s), AttributeMask::All) => !s.is_empty(),
             (AttributeMask::Dynamic(v1), AttributeMask::Dynamic(v2)) => {
-                overlaps_iter(v1.iter().copied(), v2.iter().copied())
+                overlaps_iter(v1.iter().map(|s| s.as_str()), v2.iter().map(|s| s.as_str()))
             }
             (AttributeMask::Dynamic(v), AttributeMask::Static(s)) => {
-                overlaps_iter(v.iter().copied(), s.iter().copied())
+                overlaps_iter(v.iter().map(|s| s.as_str()), s.iter().copied())
             }
             (AttributeMask::Static(s), AttributeMask::Dynamic(v)) => {
-                overlaps_iter(v.iter().copied(), s.iter().copied())
+                overlaps_iter(v.iter().map(|s| s.as_str()), s.iter().copied())
             }
             (AttributeMask::Static(s1), AttributeMask::Static(s2)) => {
                 overlaps_iter(s1.iter().copied(), s2.iter().copied())

+ 266 - 617
packages/native-core/src/real_dom.rs

@@ -1,13 +1,11 @@
 use anymap::AnyMap;
-use dioxus_core::{ElementId, Mutations, VNode};
+use dioxus_core::{ElementId, Mutations};
 use rustc_hash::{FxHashMap, FxHashSet};
-use slab::Slab;
-use std::ops::{Index, IndexMut};
+use std::ops::{Deref, DerefMut, Index, IndexMut};
 
-use crate::node::{Node, NodeType};
+use crate::node::{Node, NodeData, NodeType, OwnedAttributeDiscription};
 use crate::node_ref::{AttributeMask, NodeMask};
 use crate::state::State;
-use crate::traversable::Traversable;
 use crate::tree::{NodeId, Tree, TreeLike, TreeView};
 use crate::RealNodeId;
 
@@ -18,8 +16,10 @@ use crate::RealNodeId;
 pub struct RealDom<S: State> {
     tree: Tree<Node<S>>,
     /// a map from element id to real node id
-    node_id_mapping: Vec<RealNodeId>,
-    nodes_listening: FxHashMap<&'static str, FxHashSet<RealNodeId>>,
+    node_id_mapping: Vec<Option<RealNodeId>>,
+    nodes_listening: FxHashMap<String, FxHashSet<RealNodeId>>,
+    stack: Vec<RealNodeId>,
+    templates: FxHashMap<String, Vec<RealNodeId>>,
 }
 
 impl<S: State> Default for RealDom<S> {
@@ -32,369 +32,307 @@ impl<S: State> RealDom<S> {
     pub fn new() -> RealDom<S> {
         let mut root = Node::new(NodeType::Element {
             tag: "Root".to_string(),
-            namespace: Some("Root"),
+            namespace: Some("Root".to_string()),
             attributes: FxHashMap::default(),
             listeners: FxHashSet::default(),
-            children: Vec::new(),
         });
         root.node_data.element_id = Some(ElementId(0));
-        let tree = Tree::new(root);
+        let mut tree = Tree::new(root);
         let root_id = tree.root();
-        tree.get_mut(root_id).unwrap().node_data.id = root_id;
+        tree.get_mut(root_id).unwrap().node_data.node_id = root_id;
 
         RealDom {
             tree,
             node_id_mapping: Vec::new(),
             nodes_listening: FxHashMap::default(),
+            stack: vec![root_id],
+            templates: FxHashMap::default(),
         }
     }
 
+    fn element_to_node_id(&self, element_id: ElementId) -> RealNodeId {
+        self.node_id_mapping.get(element_id.0).unwrap().unwrap()
+    }
+
+    fn set_element_id(&mut self, node_id: NodeId, element_id: ElementId) {
+        let node = self.tree.get_mut(node_id).unwrap();
+        let node_id = node.node_data.node_id;
+        node.node_data.element_id = Some(element_id);
+        if self.node_id_mapping.len() <= element_id.0 {
+            self.node_id_mapping.resize(element_id.0 + 1, None);
+        }
+        self.node_id_mapping[element_id.0] = Some(node_id);
+    }
+
+    fn load_child(&self, path: &[u8]) -> RealNodeId {
+        let mut current = *self.stack.last().unwrap();
+        for i in path {
+            current = self.tree.children_ids(current).unwrap()[*i as usize];
+        }
+        current
+    }
+
+    fn create_node(&mut self, node: Node<S>) -> RealNodeId {
+        let node_id = self.tree.create_node(node);
+        let node = self.tree.get_mut(node_id).unwrap();
+        node.node_data.node_id = node_id;
+        node_id
+    }
+
     /// Updates the dom with some mutations and return a set of nodes that were updated. Pass the dirty nodes to update_state.
-    pub fn apply_mutations(
+    pub fn apply_mutations<'a>(
         &mut self,
-        mutations_vec: Vec<Mutations>,
+        mutations_vec: Vec<Mutations<'a>>,
     ) -> Vec<(RealNodeId, NodeMask)> {
-        let mut nodes_updated = Vec::new();
-        nodes_updated.push((RealNodeId::ElementId(ElementId(0)), NodeMask::ALL));
+        let mut nodes_updated: Vec<(RealNodeId, NodeMask)> = Vec::new();
         for mutations in mutations_vec {
             for e in mutations.edits {
                 use dioxus_core::Mutation::*;
                 match e {
-                    AppendChildren { root, children } => {
-                        let target = self.resolve_maybe_id(root);
-                        for id in children {
-                            let id = RealNodeId::ElementId(ElementId(id as usize));
-                            self.mark_dirty(id, NodeMask::ALL, &mut nodes_updated);
-                            self.link_child(id, target).unwrap();
+                    AppendChildren { m } => {
+                        let data = self.stack.split_off(m);
+                        let (parent, children) = data.split_first().unwrap();
+                        for child in children {
+                            self.tree.add_child(*parent, *child);
+                            nodes_updated.push((*parent, NodeMask::ALL));
                         }
                     }
-                    ReplaceWith { root, nodes } => {
-                        let id_to_replace = self.resolve_maybe_id(root);
-                        let target = self[id_to_replace].node_data.parent.unwrap();
-                        for id in nodes {
-                            let id = RealNodeId::ElementId(ElementId(id as usize));
-                            self.mark_dirty(id, NodeMask::ALL, &mut nodes_updated);
-                            self.link_child_before(id, target, id_to_replace).unwrap();
-                        }
-                        self.remove(id_to_replace).unwrap();
-                    }
-                    InsertAfter { root, nodes } => {
-                        let root = self.resolve_maybe_id(root);
-                        let target = self.parent(root).unwrap();
-                        for id in nodes {
-                            let id = RealNodeId::ElementId(ElementId(id as usize));
-                            self.mark_dirty(id, NodeMask::ALL, &mut nodes_updated);
-                            self.link_child_after(id, target, root).unwrap();
-                        }
-                    }
-                    InsertBefore { root, nodes } => {
-                        let root = self.resolve_maybe_id(root);
-                        let target = self.parent(root).unwrap();
-                        for id in nodes {
-                            let id = RealNodeId::ElementId(ElementId(id as usize));
-                            self.mark_dirty(id, NodeMask::ALL, &mut nodes_updated);
-                            self.link_child_before(id, target, root).unwrap();
-                        }
-                    }
-                    Remove { root } => {
-                        let id = self.resolve_maybe_id(root);
-                        if let Some(parent) = self.parent(id) {
-                            self.mark_dirty(parent, NodeMask::NONE, &mut nodes_updated);
-                        }
-                        self.remove(id).unwrap();
-                    }
-                    CreateTextNode { root, text } => {
-                        let n = Node::new(NodeType::Text {
-                            text: text.to_string(),
-                        });
-                        let id = self.insert(n, root, &mut nodes_updated);
-                        self.mark_dirty(id, NodeMask::ALL, &mut nodes_updated);
-                        if let Some((parent, remaining)) = self.parents_queued.last_mut() {
-                            *remaining -= 1;
-                            let parent = *parent;
-                            if *remaining == 0 {
-                                self.parents_queued.pop();
-                            }
-                            self.link_child(id, parent).unwrap();
-                        }
-                        self.last = Some(id);
+                    AssignId { path, id } => {
+                        self.set_element_id(self.load_child(&path), id);
                     }
-                    CreateElement {
-                        root,
-                        tag,
-                        children,
-                    } => {
-                        let n = Node::new(NodeType::Element {
-                            tag: tag.to_string(),
+                    CreateElement { name } => {
+                        let node = Node::new(NodeType::Element {
+                            tag: name.to_string(),
                             namespace: None,
                             attributes: FxHashMap::default(),
                             listeners: FxHashSet::default(),
-                            children: Vec::new(),
                         });
-                        let id = self.insert(n, root, &mut nodes_updated);
-                        self.mark_dirty(id, NodeMask::ALL, &mut nodes_updated);
-                        if let Some((parent, remaining)) = self.parents_queued.last_mut() {
-                            *remaining -= 1;
-                            let parent = *parent;
-                            if *remaining == 0 {
-                                self.parents_queued.pop();
-                            }
-                            self.link_child(id, parent).unwrap();
-                        }
-                        self.last = Some(id);
-                        if children > 0 {
-                            self.parents_queued.push((id, children));
-                        }
+                        let id = self.create_node(node);
+                        self.stack.push(id);
+                        nodes_updated.push((id, NodeMask::ALL));
                     }
-                    CreateElementNs {
-                        root,
-                        tag,
-                        ns,
-                        children,
-                    } => {
-                        let n = Node::new(NodeType::Element {
-                            tag: tag.to_string(),
-                            namespace: Some(ns),
+                    CreateElementNamespace { name, namespace } => {
+                        let node = Node::new(NodeType::Element {
+                            tag: name.to_string(),
+                            namespace: Some(namespace.to_string()),
                             attributes: FxHashMap::default(),
                             listeners: FxHashSet::default(),
-                            children: Vec::new(),
                         });
-                        let id = self.insert(n, root, &mut nodes_updated);
-                        self.mark_dirty(id, NodeMask::ALL, &mut nodes_updated);
-                        if let Some((parent, remaining)) = self.parents_queued.last_mut() {
-                            *remaining -= 1;
-                            let parent = *parent;
-                            if *remaining == 0 {
-                                self.parents_queued.pop();
-                            }
-                            self.link_child(id, parent).unwrap();
-                        }
-                        self.last = Some(id);
-                        if children > 0 {
-                            self.parents_queued.push((id, children));
-                        }
+                        let id = self.create_node(node);
+                        self.stack.push(id);
+                        nodes_updated.push((id, NodeMask::ALL));
                     }
-                    CreatePlaceholder { root } => {
-                        let n = Node::new(NodeType::Placeholder);
-                        let id = self.insert(n, root, &mut nodes_updated);
-                        self.mark_dirty(id, NodeMask::ALL, &mut nodes_updated);
-                        if let Some((parent, remaining)) = self.parents_queued.last_mut() {
-                            *remaining -= 1;
-                            let parent = *parent;
-                            if *remaining == 0 {
-                                self.parents_queued.pop();
-                            }
-                            self.link_child(id, parent).unwrap();
+                    CreatePlaceholder { id } => {
+                        let node = Node::new(NodeType::Placeholder);
+                        let node_id = self.create_node(node);
+                        self.set_element_id(node_id, id);
+                        self.stack.push(node_id);
+                        nodes_updated.push((node_id, NodeMask::ALL));
+                    }
+                    CreateStaticPlaceholder => {
+                        let node = Node::new(NodeType::Placeholder);
+                        let id = self.create_node(node);
+                        self.stack.push(id);
+                        nodes_updated.push((id, NodeMask::ALL));
+                    }
+                    CreateStaticText { value } => {
+                        let node = Node::new(NodeType::Text {
+                            text: value.to_string(),
+                        });
+                        let id = self.create_node(node);
+                        self.stack.push(id);
+                        nodes_updated.push((id, NodeMask::new().with_text()));
+                    }
+                    CreateTextNode { value, id } => {
+                        let node = Node::new(NodeType::Text {
+                            text: value.to_string(),
+                        });
+                        let node_id = self.create_node(node);
+                        let node = self.tree.get_mut(node_id).unwrap();
+                        node.node_data.element_id = Some(id);
+                        self.stack.push(node_id);
+                        nodes_updated.push((node_id, NodeMask::new().with_text()));
+                    }
+                    HydrateText { path, value, id } => {
+                        let node_id = self.load_child(path);
+                        self.set_element_id(node_id, id);
+                        let node = self.tree.get_mut(node_id).unwrap();
+                        if let NodeType::Text { text } = &mut node.node_data.node_type {
+                            *text = value.to_string();
                         }
-                        self.last = Some(id);
+                        nodes_updated.push((node_id, NodeMask::new().with_text()));
                     }
-                    NewEventListener {
-                        event_name,
-                        scope: _,
-                        root,
-                    } => {
-                        let id = self.resolve_maybe_id(root);
-                        self.mark_dirty(id, NodeMask::new().with_listeners(), &mut nodes_updated);
-                        match &mut self[id].node_data.node_type {
-                            NodeType::Text { .. } => panic!("Text nodes cannot have listeners"),
-                            NodeType::Element { listeners, .. } => {
-                                listeners.insert(event_name.to_string());
-                            }
-                            NodeType::Placeholder => panic!("Placeholder cannot have listeners"),
+                    LoadTemplate { name, index, id } => {
+                        let template_id = self.templates[name][index];
+                        let clone_id = self.clone_node(template_id);
+                        self.set_element_id(clone_id, id);
+                    }
+                    ReplaceWith { id, m } => {
+                        let new_nodes = self.stack.split_off(m);
+                        let old_node_id = self.element_to_node_id(id);
+                        for new in new_nodes {
+                            self.tree.insert_after(old_node_id, new);
+                            nodes_updated.push((new, NodeMask::ALL));
                         }
-                        if let Some(v) = self.nodes_listening.get_mut(event_name) {
-                            v.insert(id);
-                        } else {
-                            let mut hs = FxHashSet::default();
-                            hs.insert(id);
-                            self.nodes_listening.insert(event_name, hs);
+                        self.tree.remove(old_node_id);
+                    }
+                    ReplacePlaceholder { path, m } => {
+                        let new_nodes = self.stack.split_off(m);
+                        let old_node_id = self.load_child(path);
+                        for new in new_nodes {
+                            self.tree.insert_after(old_node_id, new);
+                            nodes_updated.push((new, NodeMask::ALL));
                         }
+                        self.tree.remove(old_node_id);
                     }
-                    RemoveEventListener { root, event } => {
-                        let id = self.resolve_maybe_id(root);
-                        self.mark_dirty(id, NodeMask::new().with_listeners(), &mut nodes_updated);
-                        let v = self.nodes_listening.get_mut(event).unwrap();
-                        v.remove(&id);
+                    InsertAfter { id, m } => {
+                        let new_nodes = self.stack.split_off(m);
+                        let old_node_id = self.element_to_node_id(id);
+                        for new in new_nodes {
+                            self.tree.insert_after(old_node_id, new);
+                            nodes_updated.push((new, NodeMask::ALL));
+                        }
                     }
-                    SetText {
-                        root,
-                        text: new_text,
-                    } => {
-                        let id = self.resolve_maybe_id(root);
-                        self.mark_dirty(id, NodeMask::new().with_text(), &mut nodes_updated);
-                        let target = &mut self[id];
-                        match &mut target.node_data.node_type {
-                            NodeType::Text { text } => {
-                                *text = new_text.to_string();
-                            }
-                            _ => unreachable!(),
+                    InsertBefore { id, m } => {
+                        let new_nodes = self.stack.split_off(m);
+                        let old_node_id = self.element_to_node_id(id);
+                        for new in new_nodes {
+                            self.tree.insert_before(old_node_id, new);
+                            nodes_updated.push((new, NodeMask::ALL));
                         }
                     }
+                    SaveTemplate { name, m } => {
+                        let template = self.stack.split_off(m);
+                        self.templates.insert(name.to_string(), template);
+                    }
                     SetAttribute {
-                        root,
-                        field,
-                        ns,
+                        name,
                         value,
+                        id,
+                        ns,
                     } => {
-                        let id = self.resolve_maybe_id(root);
-                        if let NodeType::Element { attributes, .. } =
-                            &mut self[id].node_data.node_type
+                        let node_id = self.element_to_node_id(id);
+                        let node = self.tree.get_mut(node_id).unwrap();
+                        if let NodeType::Element { attributes, .. } = &mut node.node_data.node_type
                         {
                             attributes.insert(
                                 OwnedAttributeDiscription {
-                                    name: field.to_owned(),
-                                    namespace: ns.map(|a| a.to_owned()),
+                                    name: name.to_string(),
+                                    namespace: ns.map(|s| s.to_string()),
                                     volatile: false,
                                 },
-                                value.into(),
+                                crate::node::OwnedAttributeValue::Text(value.to_string()),
                             );
-                        } else {
-                            panic!("tried to call set attribute on a non element");
+                            nodes_updated.push((
+                                node_id,
+                                NodeMask::new_with_attrs(AttributeMask::single(name)),
+                            ));
                         }
-                        self.mark_dirty(
-                            id,
-                            NodeMask::new_with_attrs(AttributeMask::single(field)),
-                            &mut nodes_updated,
-                        );
                     }
-                    RemoveAttribute {
-                        root, name: field, ..
-                    } => {
-                        let id = self.resolve_maybe_id(root);
-                        self.mark_dirty(
-                            id,
-                            NodeMask::new_with_attrs(AttributeMask::single(field)),
-                            &mut nodes_updated,
-                        );
+                    SetStaticAttribute { name, value, ns } => {
+                        let node_id = self.stack.last().unwrap();
+                        let node = self.tree.get_mut(*node_id).unwrap();
+                        if let NodeType::Element { attributes, .. } = &mut node.node_data.node_type
+                        {
+                            attributes.insert(
+                                OwnedAttributeDiscription {
+                                    name: name.to_string(),
+                                    namespace: ns.map(|s| s.to_string()),
+                                    volatile: false,
+                                },
+                                crate::node::OwnedAttributeValue::Text(value.to_string()),
+                            );
+                            nodes_updated.push((
+                                *node_id,
+                                NodeMask::new_with_attrs(AttributeMask::single(name)),
+                            ));
+                        }
                     }
-                    CloneNode { id, new_id } => {
-                        let id = self.resolve_maybe_id(id);
-                        self.clone_node_into(id, &mut nodes_updated, Some(new_id));
+                    SetBoolAttribute { name, value, id } => {
+                        let node_id = self.element_to_node_id(id);
+                        let node = self.tree.get_mut(node_id).unwrap();
+                        if let NodeType::Element { attributes, .. } = &mut node.node_data.node_type
+                        {
+                            attributes.insert(
+                                OwnedAttributeDiscription {
+                                    name: name.to_string(),
+                                    namespace: None,
+                                    volatile: false,
+                                },
+                                crate::node::OwnedAttributeValue::Bool(value),
+                            );
+                            nodes_updated.push((
+                                node_id,
+                                NodeMask::new_with_attrs(AttributeMask::single(name)),
+                            ));
+                        }
                     }
-                    CloneNodeChildren { id, new_ids } => {
-                        let id = self.resolve_maybe_id(id);
-                        let bounded_self: &mut Self = self;
-                        let unbounded_self: &mut Self =
-                            unsafe { std::mem::transmute(bounded_self) };
-                        if let NodeType::Element { children, .. } = &self[id].node_data.node_type {
-                            for (old_id, new_id) in children.iter().zip(new_ids) {
-                                let child_id = unbounded_self.clone_node_into(
-                                    *old_id,
-                                    &mut nodes_updated,
-                                    Some(new_id),
-                                );
-                                unbounded_self[child_id].node_data.parent = None;
-                            }
+                    SetInnerText { value } => {
+                        let node_id = *self.stack.last().unwrap();
+                        let node = self.tree.get_mut(node_id).unwrap();
+                        if let NodeType::Element { .. } = &mut node.node_data.node_type {
+                            self.tree.remove_all_children(node_id);
+                            let text_node = Node::new(NodeType::Text {
+                                text: value.to_string(),
+                            });
+                            let text_node_id = self.create_node(text_node);
+                            self.tree.add_child(node_id, text_node_id);
                         }
                     }
-                    FirstChild {} => {
-                        if let NodeType::Element { children, .. } =
-                            &self[self.last.unwrap()].node_data.node_type
-                        {
-                            self.last = Some(children[0]);
-                        } else {
-                            panic!("tried to call first child on a non element");
+                    SetText { value, id } => {
+                        let node_id = self.element_to_node_id(id);
+                        let node = self.tree.get_mut(node_id).unwrap();
+                        if let NodeType::Text { text } = &mut node.node_data.node_type {
+                            *text = value.to_string();
                         }
+                        nodes_updated.push((node_id, NodeMask::new().with_text()));
                     }
-                    NextSibling {} => {
-                        let id = self.last.unwrap();
-                        if let Some(parent) = self.parent(id) {
-                            if let NodeType::Element { children, .. } =
-                                &self[parent].node_data.node_type
-                            {
-                                let index = children.iter().position(|a| *a == id).unwrap();
-                                self.last = Some(children[index + 1]);
+                    NewEventListener {
+                        event_name,
+                        scope: _,
+                        id,
+                    } => {
+                        let node_id = self.element_to_node_id(id);
+                        let node = self.tree.get_mut(node_id).unwrap();
+                        if let NodeType::Element { listeners, .. } = &mut node.node_data.node_type {
+                            match self.nodes_listening.get_mut(event_name) {
+                                Some(hs) => {
+                                    hs.insert(node_id);
+                                }
+                                None => {
+                                    let mut hs = FxHashSet::default();
+                                    hs.insert(node_id);
+                                    self.nodes_listening.insert(event_name.to_string(), hs);
+                                }
                             }
-                        } else {
-                            panic!("tried to call next sibling on a non element");
+                            listeners.insert(event_name.to_string());
                         }
                     }
-                    ParentNode {} => {
-                        if let Some(parent) = self.parent(self.last.unwrap()) {
-                            self.last = Some(parent);
-                        } else {
-                            panic!("tried to call parent node on a non element");
+                    RemoveEventListener { id, event } => {
+                        let node_id = self.element_to_node_id(id);
+                        let node = self.tree.get_mut(node_id).unwrap();
+                        if let NodeType::Element { listeners, .. } = &mut node.node_data.node_type {
+                            listeners.remove(event);
                         }
+                        self.nodes_listening
+                            .get_mut(event)
+                            .unwrap()
+                            .remove(&node_id);
                     }
-                    StoreWithId { id } => {
-                        let old_id = self.last.unwrap();
-                        let node = self.internal_nodes.remove(old_id.as_unaccessable_id());
-                        let new_id = self.insert(*node, Some(id), &mut nodes_updated);
-                        self.update_id(old_id, new_id, &mut nodes_updated);
-                    }
-                    SetLastNode { id } => {
-                        self.last =
-                            Some(RealNodeId::ElementId(dioxus_core::ElementId(id as usize)));
+                    Remove { id } => {
+                        let node_id = self.element_to_node_id(id);
+                        self.remove(node_id);
                     }
                 }
             }
         }
 
         // remove any nodes that were created and then removed in the same mutations from the dirty nodes list
-        nodes_updated.retain(|n| match n.0 {
-            RealNodeId::ElementId(id) => self.nodes.get(id.0).and_then(|o| o.as_ref()).is_some(),
-            RealNodeId::UnaccessableId(id) => self.internal_nodes.get(id).is_some(),
-        });
+        nodes_updated.retain(|n| self.tree.get(n.0).is_some());
 
         nodes_updated
     }
 
-    /// Update refrences to an old node id to a new node id
-    fn update_id(
-        &mut self,
-        old_id: RealNodeId,
-        new_id: RealNodeId,
-        nodes_updated: &mut Vec<(RealNodeId, NodeMask)>,
-    ) {
-        // this is safe because a node cannot have itself as a child or parent
-        let unbouned_self = unsafe { &mut *(self as *mut Self) };
-        // update parent's link to child id
-        if let Some(parent) = self[new_id].node_data.parent {
-            if let NodeType::Element { children, .. } = &mut self[parent].node_data.node_type {
-                for c in children {
-                    if *c == old_id {
-                        *c = new_id;
-                        break;
-                    }
-                }
-            }
-        }
-        // update child's link to parent id
-        if let NodeType::Element { children, .. } = &self[new_id].node_data.node_type {
-            for child_id in children {
-                unbouned_self[*child_id].node_data.parent = Some(new_id);
-            }
-        }
-        // update dirty nodes
-        for (node, _) in nodes_updated {
-            if *node == old_id {
-                *node = new_id;
-            }
-        }
-        // update nodes listening
-        for v in self.nodes_listening.values_mut() {
-            if v.contains(&old_id) {
-                v.remove(&old_id);
-                v.insert(new_id);
-            }
-        }
-        // update last
-        if let Some(last) = self.last {
-            if last == old_id {
-                self.last = Some(new_id);
-            }
-        }
-    }
-
-    fn mark_dirty(
-        &self,
-        gid: RealNodeId,
-        mask: NodeMask,
-        dirty_nodes: &mut Vec<(RealNodeId, NodeMask)>,
-    ) {
-        dirty_nodes.push((gid, mask));
-    }
-
     /// 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.
     pub fn update_state(
         &mut self,
@@ -405,140 +343,6 @@ impl<S: State> RealDom<S> {
         S::update(&nodes_updated, &mut state_tree, &node_tree, &ctx)
     }
 
-    /// Link a child and parent together
-    fn link_child(&mut self, child_id: RealNodeId, parent_id: RealNodeId) -> Option<()> {
-        let parent = &mut self[parent_id];
-        parent.add_child(child_id);
-        let parent_height = parent.node_data.height;
-        self[child_id].set_parent(parent_id);
-        self.set_height(child_id, parent_height + 1);
-
-        Some(())
-    }
-
-    /// Link a child and parent together with the child inserted before a marker
-    fn link_child_before(
-        &mut self,
-        child_id: RealNodeId,
-        parent_id: RealNodeId,
-        marker: RealNodeId,
-    ) -> Option<()> {
-        let parent = &mut self[parent_id];
-        if let NodeType::Element { children, .. } = &mut parent.node_data.node_type {
-            let index = children.iter().position(|a| *a == marker)?;
-            children.insert(index, child_id);
-        }
-        let parent_height = parent.node_data.height;
-        self[child_id].set_parent(parent_id);
-        self.set_height(child_id, parent_height + 1);
-
-        Some(())
-    }
-
-    /// Link a child and parent together with the child inserted after a marker
-    fn link_child_after(
-        &mut self,
-        child_id: RealNodeId,
-        parent_id: RealNodeId,
-        marker: RealNodeId,
-    ) -> Option<()> {
-        let parent = &mut self[parent_id];
-        if let NodeType::Element { children, .. } = &mut parent.node_data.node_type {
-            let index = children.iter().position(|a| *a == marker)?;
-            children.insert(index + 1, child_id);
-        }
-        let parent_height = parent.node_data.height;
-        self[child_id].set_parent(parent_id);
-        self.set_height(child_id, parent_height + 1);
-
-        Some(())
-    }
-
-    /// Recursively increase the height of a node and its children
-    fn set_height(&mut self, id: RealNodeId, height: u16) {
-        let node = &mut self[id];
-        node.node_data.height = height;
-        if let NodeType::Element { children, .. } = &node.node_data.node_type {
-            for c in children.clone() {
-                self.set_height(c, height + 1);
-            }
-        }
-    }
-
-    // remove a node and it's children from the dom.
-    fn remove(&mut self, id: RealNodeId) -> Option<Node<S>> {
-        // We do not need to remove the node from the parent's children list for children.
-        fn inner<S: State>(dom: &mut RealDom<S>, id: RealNodeId) -> Option<Node<S>> {
-            let mut node = match id {
-                RealNodeId::ElementId(id) => *dom.nodes[id.0].take()?,
-                RealNodeId::UnaccessableId(id) => *dom.internal_nodes.remove(id),
-            };
-            if let NodeType::Element { children, .. } = &mut node.node_data.node_type {
-                for c in children {
-                    inner(dom, *c);
-                }
-            }
-            Some(node)
-        }
-        let mut node = match id {
-            RealNodeId::ElementId(id) => *self.nodes[id.0].take()?,
-            RealNodeId::UnaccessableId(id) => *self.internal_nodes.remove(id),
-        };
-        if let Some(parent) = node.node_data.parent {
-            let parent = &mut self[parent];
-            parent.remove_child(id);
-        }
-        if let NodeType::Element { children, .. } = &mut node.node_data.node_type {
-            for c in children {
-                inner(self, *c)?;
-            }
-        }
-        Some(node)
-    }
-
-    fn resize_to(&mut self, id: usize) {
-        let current_len = self.nodes.len();
-        if current_len - 1 < id {
-            self.nodes.extend((0..1 + id - current_len).map(|_| None));
-        }
-    }
-
-    fn insert(
-        &mut self,
-        mut node: Node<S>,
-        id: Option<u64>,
-        nodes_updated: &mut Vec<(RealNodeId, NodeMask)>,
-    ) -> RealNodeId {
-        match id {
-            Some(id) => {
-                let id = id as usize;
-                self.resize_to(id);
-                let real_id = RealNodeId::ElementId(ElementId(id));
-                node.node_data.id = Some(real_id);
-                // move the old node to a new unaccessable id
-                if let Some(mut old) = self.nodes[id].take() {
-                    let old_id = old.node_data.id.unwrap();
-                    let entry = self.internal_nodes.vacant_entry();
-                    let id = entry.key();
-                    let new_id = RealNodeId::UnaccessableId(id);
-                    old.node_data.id = Some(real_id);
-                    entry.insert(old);
-                    self.update_id(old_id, new_id, nodes_updated);
-                }
-                self.nodes[id] = Some(Box::new(node));
-                real_id
-            }
-            None => {
-                let entry = self.internal_nodes.vacant_entry();
-                let id = entry.key();
-                let real_id = RealNodeId::UnaccessableId(id);
-                node.node_data.id = Some(real_id);
-                entry.insert(Box::new(node));
-                real_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.
     /// This can be useful to avoid creating duplicate events.
     pub fn get_listening_sorted(&self, event: &'static str) -> Vec<&Node<S>> {
@@ -551,162 +355,37 @@ impl<S: State> RealDom<S> {
         }
     }
 
-    /// Check if the dom contains a node and its children.
-    pub fn contains_node(&self, node: &VNode) -> bool {
-        match node {
-            VNode::Component(_) => {
-                todo!()
-            }
-            VNode::Element(e) => {
-                if let Some(id) = e.id.get() {
-                    let dom_node = &self[id];
-                    match &dom_node.node_data.node_type {
-                        NodeType::Element {
-                            tag,
-                            namespace,
-                            children,
-                            attributes,
-                            listeners,
-                        } => {
-                            tag == e.tag
-                                && namespace == &e.namespace
-                                && children
-                                    .iter()
-                                    .zip(
-                                        e.children
-                                            .iter()
-                                            .map(|c| RealNodeId::ElementId(c.mounted_id())),
-                                    )
-                                    .all(|(c1, c2)| *c1 == c2)
-                                && e.children.iter().all(|c| {
-                                    self.contains_node(c)
-                                        && self[RealNodeId::ElementId(c.mounted_id())]
-                                            .node_data
-                                            .parent
-                                            == e.id.get().map(RealNodeId::ElementId)
-                                })
-                                && attributes
-                                    .iter()
-                                    .zip(e.attributes.iter())
-                                    .all(|((disc, val), b)| *disc == b.attribute && *val == b.value)
-                                && listeners
-                                    .iter()
-                                    .zip(e.listeners.iter())
-                                    .all(|(a, b)| *a == b.event)
-                        }
-                        _ => false,
-                    }
-                } else {
-                    true
-                }
-            }
-            VNode::Fragment(f) => f.children.iter().all(|c| self.contains_node(c)),
-            VNode::Placeholder(_) => true,
-            VNode::Text(t) => {
-                if let Some(id) = t.id.get() {
-                    let dom_node = &self[RealNodeId::ElementId(id)];
-                    match &dom_node.node_data.node_type {
-                        NodeType::Text { text } => t.text == text,
-                        _ => false,
-                    }
-                } else {
-                    true
-                }
-            }
-            VNode::TemplateRef(_) => todo!(),
-        }
-    }
-
     /// Return the number of nodes in the dom.
     pub fn size(&self) -> usize {
         // The dom has a root node, ignore it.
-        self.nodes.iter().filter(|n| n.is_some()).count() - 1
+        self.tree.size() - 1
     }
 
     /// Returns the id of the root node.
-    pub fn root_id(&self) -> usize {
-        self.root
-    }
-
-    /// Call a function for each node in the dom, depth first.
-    pub fn traverse_depth_first(&self, mut f: impl FnMut(&Node<S>)) {
-        fn inner<S: State>(dom: &RealDom<S>, id: RealNodeId, f: &mut impl FnMut(&Node<S>)) {
-            let node = &dom[id];
-            f(node);
-            if let NodeType::Element { children, .. } = &node.node_data.node_type {
-                for c in children {
-                    inner(dom, *c, f);
-                }
-            }
-        }
-        if let NodeType::Element { children, .. } = &self
-            [RealNodeId::ElementId(ElementId(self.root))]
-        .node_data
-        .node_type
-        {
-            for c in children {
-                inner(self, *c, &mut f);
-            }
-        }
+    pub fn root_id(&self) -> NodeId {
+        self.tree.root()
     }
 
-    /// Call a function for each node in the dom, depth first.
-    pub fn traverse_depth_first_mut(&mut self, mut f: impl FnMut(&mut Node<S>)) {
-        fn inner<S: State>(dom: &mut RealDom<S>, id: RealNodeId, f: &mut impl FnMut(&mut Node<S>)) {
-            let node = &mut dom[id];
-            f(node);
-            if let NodeType::Element { children, .. } = &mut node.node_data.node_type {
-                for c in children.clone() {
-                    inner(dom, c, f);
-                }
-            }
-        }
-        let root = self.root;
-        if let NodeType::Element { children, .. } = &mut self
-            [RealNodeId::ElementId(ElementId(root))]
-        .node_data
-        .node_type
-        {
-            for c in children.clone() {
-                inner(self, c, &mut f);
-            }
-        }
-    }
-
-    pub fn split(
-        &mut self,
-    ) -> (
-        impl Traversable<Id = RealNodeId, Node = S> + '_,
-        impl Traversable<Id = RealNodeId, Node = NodeData> + '_,
-    ) {
+    pub fn split(&mut self) -> (impl TreeView<S> + '_, impl TreeView<NodeData> + '_) {
         let raw = self as *mut Self;
-        // this is safe beacuse the traversable trait does not allow mutation of the position of elements, and within elements the access is disjoint.
+        // this is safe beacuse the treeview trait does not allow mutation of the position of elements, and within elements the access is disjoint.
         (
             unsafe { &mut *raw }.map(|n| &n.state, |n| &mut n.state),
             unsafe { &mut *raw }.map(|n| &n.node_data, |n| &mut n.node_data),
         )
     }
 
-    /// Recurively clones a node and marks it and it's children as dirty.
-    fn clone_node_into(
-        &mut self,
-        id: RealNodeId,
-        nodes_updated: &mut Vec<(RealNodeId, NodeMask)>,
-        new_id: Option<u64>,
-    ) -> RealNodeId {
-        let new_id = self.insert(self[id].clone(), new_id, nodes_updated);
-        nodes_updated.push((new_id, NodeMask::ALL));
-        // this is safe because no node has itself as a child.
-        let unbounded_self = unsafe { &mut *(self as *mut Self) };
-        let mut node = &mut self[new_id];
-        node.node_data.height = 0;
-        if let NodeType::Element { children, .. } = &mut node.node_data.node_type {
-            for c in children {
-                let child_id = unbounded_self.clone_node_into(*c, nodes_updated, None);
-                *c = child_id;
-                let parent_height = node.node_data.height;
-                unbounded_self[child_id].set_parent(new_id);
-                unbounded_self.set_height(child_id, parent_height + 1);
+    fn clone_node(&mut self, node_id: NodeId) -> RealNodeId {
+        let node = self.tree.get(node_id).unwrap();
+        let new_node = node.clone();
+        let new_id = self.create_node(new_node);
+        let self_ptr = self as *mut Self;
+        for child in self.tree.children_ids(node_id).unwrap() {
+            unsafe {
+                // this is safe because no node has itself as a child
+                let self_mut = &mut *self_ptr;
+                let child_id = self_mut.clone_node(*child);
+                self_mut.tree.add_child(new_id, child_id);
             }
         }
         new_id
@@ -716,8 +395,8 @@ impl<S: State> RealDom<S> {
 impl<S: State> Index<ElementId> for RealDom<S> {
     type Output = Node<S>;
 
-    fn index(&self, idx: ElementId) -> &Self::Output {
-        self.get(RealNodeId::ElementId(idx)).unwrap()
+    fn index(&self, id: ElementId) -> &Self::Output {
+        self.tree.get(self.element_to_node_id(id)).unwrap()
     }
 }
 
@@ -725,62 +404,32 @@ impl<S: State> Index<RealNodeId> for RealDom<S> {
     type Output = Node<S>;
 
     fn index(&self, idx: RealNodeId) -> &Self::Output {
-        self.get(idx).unwrap()
+        self.tree.get(idx).unwrap()
     }
 }
 
 impl<S: State> IndexMut<ElementId> for RealDom<S> {
-    fn index_mut(&mut self, idx: ElementId) -> &mut Self::Output {
-        self.get_mut(RealNodeId::ElementId(idx)).unwrap()
+    fn index_mut(&mut self, id: ElementId) -> &mut Self::Output {
+        self.tree.get_mut(self.element_to_node_id(id)).unwrap()
     }
 }
 
 impl<S: State> IndexMut<RealNodeId> for RealDom<S> {
     fn index_mut(&mut self, idx: RealNodeId) -> &mut Self::Output {
-        self.get_mut(idx).unwrap()
+        self.tree.get_mut(idx).unwrap()
     }
 }
 
-impl<T: State> Traversable for RealDom<T> {
-    type Id = RealNodeId;
-    type Node = Node<T>;
-
-    fn height(&self, id: Self::Id) -> Option<u16> {
-        let node = <Self as Traversable>::get(self, id);
-        Some(node?.node_data.height)
-    }
-
-    fn get(&self, id: Self::Id) -> Option<&Self::Node> {
-        match id {
-            RealNodeId::ElementId(id) => {
-                self.nodes.get(id.0).and_then(|b| b.as_ref().map(|b| &**b))
-            }
-            RealNodeId::UnaccessableId(id) => self.internal_nodes.get(id).map(|b| &**b),
-        }
-    }
-
-    fn get_mut(&mut self, id: Self::Id) -> Option<&mut Self::Node> {
-        match id {
-            RealNodeId::ElementId(id) => self
-                .nodes
-                .get_mut(id.0)
-                .and_then(|b| b.as_mut().map(|b| &mut **b)),
-            RealNodeId::UnaccessableId(id) => self.internal_nodes.get_mut(id).map(|b| &mut **b),
-        }
-    }
+impl<S: State> Deref for RealDom<S> {
+    type Target = Tree<Node<S>>;
 
-    fn children(&self, id: Self::Id) -> &[Self::Id] {
-        if let Some(node) = <Self as Traversable>::get(self, id) {
-            match &node.node_data.node_type {
-                NodeType::Element { children, .. } => children,
-                _ => &[],
-            }
-        } else {
-            &[]
-        }
+    fn deref(&self) -> &Self::Target {
+        &self.tree
     }
+}
 
-    fn parent(&self, id: Self::Id) -> Option<Self::Id> {
-        self.get(id).and_then(|n| n.node_data.parent)
+impl<S: State> DerefMut for RealDom<S> {
+    fn deref_mut(&mut self) -> &mut Self::Target {
+        &mut self.tree
     }
 }

+ 10 - 13
packages/native-core/src/state.rs

@@ -1,17 +1,18 @@
-use std::{cmp::Ordering, fmt::Debug};
+use std::cmp::Ordering;
 
 use crate::node::NodeData;
 use crate::node_ref::{NodeMask, NodeView};
+use crate::tree::TreeView;
 use crate::RealNodeId;
 use anymap::AnyMap;
 use rustc_hash::FxHashSet;
 
 /// Join two sorted iterators
-pub(crate) fn union_ordered_iter<T: Ord + Debug>(
-    s_iter: impl Iterator<Item = T>,
-    o_iter: impl Iterator<Item = T>,
+pub(crate) fn union_ordered_iter<'a>(
+    s_iter: impl Iterator<Item = &'a str>,
+    o_iter: impl Iterator<Item = &'a str>,
     new_len_guess: usize,
-) -> Vec<T> {
+) -> Vec<String> {
     let mut s_peekable = s_iter.peekable();
     let mut o_peekable = o_iter.peekable();
     let mut v = Vec::with_capacity(new_len_guess);
@@ -22,7 +23,7 @@ pub(crate) fn union_ordered_iter<T: Ord + Debug>(
                     break;
                 }
                 Ordering::Less => {
-                    v.push(o_peekable.next().unwrap());
+                    v.push(o_peekable.next().unwrap().to_string());
                 }
                 Ordering::Equal => {
                     o_peekable.next();
@@ -30,10 +31,10 @@ pub(crate) fn union_ordered_iter<T: Ord + Debug>(
                 }
             }
         }
-        v.push(s_peekable.next().unwrap());
+        v.push(s_peekable.next().unwrap().to_string());
     }
     for o_i in o_peekable {
-        v.push(o_i);
+        v.push(o_i.to_string());
     }
     for w in v.windows(2) {
         debug_assert!(w[1] > w[0]);
@@ -207,11 +208,7 @@ pub trait NodeDepState<DepState = ()> {
 /// Do not implement this trait. It is only meant to be derived and used through [crate::real_dom::RealDom].
 pub trait State: Default + Clone {
     #[doc(hidden)]
-    fn update<
-        'a,
-        T: Traversable<Node = Self, Id = RealNodeId>,
-        T2: Traversable<Node = NodeData, Id = RealNodeId>,
-    >(
+    fn update<'a, T: TreeView<Self>, T2: TreeView<NodeData>>(
         dirty: &[(RealNodeId, NodeMask)],
         state_tree: &'a mut T,
         rdom: &'a T2,

+ 108 - 65
packages/native-core/src/tree.rs

@@ -7,7 +7,7 @@ use std::collections::VecDeque;
 use std::marker::PhantomData;
 use std::sync::Arc;
 
-#[derive(PartialEq, Eq, Clone, Copy, Debug, PartialOrd, Ord)]
+#[derive(Hash, PartialEq, Eq, Clone, Copy, Debug, PartialOrd, Ord)]
 pub struct NodeId(pub usize);
 
 #[derive(PartialEq, Eq, Clone, Debug)]
@@ -23,6 +23,31 @@ pub struct Tree<T> {
     root: NodeId,
 }
 
+impl<T> Tree<T> {
+    fn try_remove(&mut self, id: NodeId) -> Option<Node<T>> {
+        self.nodes.try_remove(id.0).map(|node| {
+            if let Some(parent) = node.parent {
+                self.nodes
+                    .get_mut(parent.0)
+                    .unwrap()
+                    .children
+                    .retain(|child| child != &id);
+            }
+            for child in &node.children {
+                self.remove_recursive(*child);
+            }
+            node
+        })
+    }
+
+    fn remove_recursive(&mut self, node: NodeId) {
+        let node = self.nodes.remove(node.0);
+        for child in node.children {
+            self.remove_recursive(child);
+        }
+    }
+}
+
 pub trait TreeView<T>: Sized {
     type Iterator<'a>: Iterator<Item = &'a T>
     where
@@ -152,15 +177,19 @@ pub trait TreeView<T>: Sized {
 pub trait TreeLike<T>: TreeView<T> {
     fn new(root: T) -> Self;
 
-    fn add_child(&mut self, parent: NodeId, value: T) -> NodeId;
+    fn create_node(&mut self, value: T) -> NodeId;
+
+    fn add_child(&mut self, parent: NodeId, child: NodeId);
 
     fn remove(&mut self, id: NodeId) -> Option<T>;
 
-    fn replace(&mut self, id: NodeId, value: T);
+    fn remove_all_children(&mut self, id: NodeId) -> Vec<T>;
+
+    fn replace(&mut self, old: NodeId, new: NodeId);
 
-    fn insert_before(&mut self, id: NodeId, value: T) -> NodeId;
+    fn insert_before(&mut self, id: NodeId, new: NodeId);
 
-    fn insert_after(&mut self, id: NodeId, value: T) -> NodeId;
+    fn insert_after(&mut self, id: NodeId, new: NodeId);
 }
 
 pub struct ChildNodeIterator<'a, T, Tr: TreeView<T>> {
@@ -304,78 +333,75 @@ impl<T> TreeLike<T> for Tree<T> {
         Self { nodes, root }
     }
 
-    fn add_child(&mut self, parent: NodeId, value: T) -> NodeId {
-        let node = Node {
+    fn create_node(&mut self, value: T) -> NodeId {
+        NodeId(self.nodes.insert(Node {
             value,
-            parent: Some(parent),
+            parent: None,
             children: Vec::new(),
-        };
-        let id = self.nodes.insert(node);
-        self.nodes
-            .get_mut(parent.0)
-            .unwrap()
-            .children
-            .push(NodeId(id));
-        NodeId(id)
+        }))
+    }
+
+    fn add_child(&mut self, parent: NodeId, new: NodeId) {
+        self.nodes.get_mut(parent.0).unwrap().children.push(new);
+        self.nodes.get_mut(new.0).unwrap().parent = Some(parent);
     }
 
     fn remove(&mut self, id: NodeId) -> Option<T> {
-        self.nodes.try_remove(id.0).map(|node| {
-            if let Some(parent) = node.parent {
-                self.nodes
-                    .get_mut(parent.0)
-                    .unwrap()
-                    .children
-                    .retain(|child| child != &id);
+        self.try_remove(id).map(|node| node.value)
+    }
+
+    fn remove_all_children(&mut self, id: NodeId) -> Vec<T> {
+        let mut children = Vec::new();
+        let self_mut = self as *mut Self;
+        for child in self.children_ids(id).unwrap() {
+            unsafe {
+                // Safety: No node has itself as a child
+                children.push((*self_mut).remove(*child).unwrap());
             }
-            node.value
-        })
+        }
+        children
     }
 
-    fn replace(&mut self, id: NodeId, value: T) {
+    fn replace(&mut self, old_id: NodeId, new_id: NodeId) {
+        // remove the old node
         let old = self
-            .nodes
-            .get_mut(id.0)
+            .try_remove(old_id)
             .expect("tried to replace a node that doesn't exist");
-        old.value = value;
+        // update the parent's link to the child
+        if let Some(parent_id) = old.parent {
+            let parent = self.nodes.get_mut(parent_id.0).unwrap();
+            for id in &mut parent.children {
+                if *id == old_id {
+                    *id = new_id;
+                }
+            }
+        }
     }
 
-    fn insert_before(&mut self, id: NodeId, value: T) -> NodeId {
+    fn insert_before(&mut self, id: NodeId, new: NodeId) {
         let node = self.nodes.get(id.0).unwrap();
         let parent_id = node.parent.expect("tried to insert before root");
-        let new = Node {
-            value,
-            parent: Some(parent_id),
-            children: Vec::new(),
-        };
-        let new_id = NodeId(self.nodes.insert(new));
+        self.nodes.get_mut(new.0).unwrap().parent = Some(parent_id);
         let parent = self.nodes.get_mut(parent_id.0).unwrap();
         let index = parent
             .children
             .iter()
             .position(|child| child == &id)
             .unwrap();
-        parent.children.insert(index, new_id);
-        new_id
+        parent.children.insert(index, new);
     }
 
-    fn insert_after(&mut self, id: NodeId, value: T) -> NodeId {
+    fn insert_after(&mut self, id: NodeId, new: NodeId) {
         let node = self.nodes.get(id.0).unwrap();
         let parent_id = node.parent.expect("tried to insert before root");
-        let new = Node {
-            value,
-            parent: Some(parent_id),
-            children: Vec::new(),
-        };
-        let new_id = NodeId(self.nodes.insert(new));
+        self.nodes.get_mut(new.0).unwrap().parent = Some(parent_id);
         let parent = self.nodes.get_mut(parent_id.0).unwrap();
         let index = parent
             .children
             .iter()
             .position(|child| child == &id)
             .unwrap();
-        parent.children.insert(index + 1, new_id);
-        new_id
+        parent.children.insert(index + 1, new);
     }
 }
 
@@ -498,7 +524,7 @@ pub struct SharedView<'a, T, Tr: TreeView<T>> {
 impl<'a, T, Tr: TreeView<T>> SharedView<'a, T, Tr> {
     /// Checks if a node is currently locked. Returns None if the node does not exist.
     pub fn check_lock(&self, id: NodeId) -> Option<bool> {
-        let mut locks = self.node_locks.read();
+        let locks = self.node_locks.read();
         locks.get(id.0).map(|lock| lock.is_locked())
     }
 }
@@ -616,7 +642,8 @@ impl<'a, T, Tr: TreeView<T>> TreeView<T> for SharedView<'a, T, Tr> {
 fn creation() {
     let mut tree = Tree::new(1);
     let parent = tree.root();
-    let child = tree.add_child(parent, 0);
+    let child = tree.create_node(0);
+    tree.add_child(parent, child);
 
     println!("Tree: {:#?}", tree);
     assert_eq!(tree.size(), 2);
@@ -631,9 +658,12 @@ fn creation() {
 fn insertion() {
     let mut tree = Tree::new(0);
     let parent = tree.root();
-    let child = tree.add_child(parent, 2);
-    let before = tree.insert_before(child, 1);
-    let after = tree.insert_after(child, 3);
+    let child = tree.create_node(2);
+    tree.add_child(parent, child);
+    let before = tree.create_node(1);
+    tree.insert_before(child, before);
+    let after = tree.create_node(3);
+    tree.insert_after(child, after);
 
     println!("Tree: {:#?}", tree);
     assert_eq!(tree.size(), 4);
@@ -651,9 +681,12 @@ fn insertion() {
 fn deletion() {
     let mut tree = Tree::new(0);
     let parent = tree.root();
-    let child = tree.add_child(parent, 2);
-    let before = tree.insert_before(child, 1);
-    let after = tree.insert_after(child, 3);
+    let child = tree.create_node(2);
+    tree.add_child(parent, child);
+    let before = tree.create_node(1);
+    tree.insert_before(child, before);
+    let after = tree.create_node(3);
+    tree.insert_after(child, after);
 
     println!("Tree: {:#?}", tree);
     assert_eq!(tree.size(), 4);
@@ -702,7 +735,8 @@ fn shared_view() {
     use std::thread;
     let mut tree = Tree::new(1);
     let parent = tree.root();
-    let child = tree.add_child(parent, 0);
+    let child = tree.create_node(0);
+    tree.add_child(parent, child);
 
     let shared = SharedView::new(&mut tree);
 
@@ -737,7 +771,8 @@ fn map() {
     }
     let mut tree = Tree::new(Value::new(1));
     let parent = tree.root();
-    let child = tree.add_child(parent, Value::new(0));
+    let child = tree.create_node(Value::new(0));
+    tree.add_child(parent, child);
 
     let mut mapped = tree.map(|x| &x.value, |x| &mut x.value);
 
@@ -752,10 +787,14 @@ fn map() {
 fn traverse_depth_first() {
     let mut tree = Tree::new(0);
     let parent = tree.root();
-    let child1 = tree.add_child(parent, 1);
-    tree.add_child(child1, 2);
-    let child2 = tree.add_child(parent, 3);
-    tree.add_child(child2, 4);
+    let child1 = tree.create_node(1);
+    tree.add_child(parent, child1);
+    let grandchild1 = tree.create_node(2);
+    tree.add_child(child1, grandchild1);
+    let child2 = tree.create_node(3);
+    tree.add_child(parent, child2);
+    let grandchild2 = tree.create_node(4);
+    tree.add_child(child2, grandchild2);
 
     let mut node_count = 0;
     tree.traverse_depth_first(move |node| {
@@ -768,10 +807,14 @@ fn traverse_depth_first() {
 fn traverse_breadth_first() {
     let mut tree = Tree::new(0);
     let parent = tree.root();
-    let child1 = tree.add_child(parent, 1);
-    tree.add_child(child1, 3);
-    let child2 = tree.add_child(parent, 2);
-    tree.add_child(child2, 4);
+    let child1 = tree.create_node(1);
+    tree.add_child(parent, child1);
+    let grandchild1 = tree.create_node(3);
+    tree.add_child(child1, grandchild1);
+    let child2 = tree.create_node(2);
+    tree.add_child(parent, child2);
+    let grandchild2 = tree.create_node(4);
+    tree.add_child(child2, grandchild2);
 
     let mut node_count = 0;
     tree.traverse_breadth_first(move |node| {