Browse Source

make dioxus dependancy optional

Evan Almloff 2 years ago
parent
commit
6fe00c4f78

+ 7 - 3
packages/native-core/Cargo.toml

@@ -11,10 +11,9 @@ keywords = ["dom", "ui", "gui", "react"]
 
 
 [dependencies]
-dioxus-core = { path = "../core", version = "^0.3.0" }
-dioxus-html = { path = "../html", version = "^0.3.0" }
-dioxus-core-macro = { path = "../core-macro", version = "^0.3.0" }
+dioxus-core = { path = "../core", version = "^0.3.0", optional = true }
 
+keyboard-types = "0.6.2"
 taffy = "0.2.1"
 smallvec = "1.6"
 rustc-hash = "1.1.0"
@@ -34,3 +33,8 @@ rayon = "1.6.1"
 rand = "0.8.5"
 dioxus = { path = "../dioxus", version = "^0.3.0" }
 tokio = { version = "*", features = ["full"] }
+dioxus-native-core = { path = ".", features = ["dioxus"] }
+
+[features]
+default = ["dioxus"]
+dioxus = ["dioxus-core"]

+ 254 - 0
packages/native-core/src/dioxus.rs

@@ -0,0 +1,254 @@
+use dioxus_core::{BorrowedAttributeValue, ElementId, Mutations, TemplateNode};
+use rustc_hash::{FxHashMap, FxHashSet};
+
+use crate::{
+    node::{ElementNode, FromAnyValue, NodeType, OwnedAttributeDiscription, OwnedAttributeValue},
+    prelude::{NodeImmutable, NodeMutable},
+    real_dom::NodeTypeMut,
+    NodeId, NodeMut, RealDom,
+};
+
+pub struct DioxusState {
+    templates: FxHashMap<String, Vec<NodeId>>,
+    stack: Vec<NodeId>,
+    node_id_mapping: Vec<Option<NodeId>>,
+}
+
+impl DioxusState {
+    pub fn new(rdom: &mut RealDom) -> Self {
+        rdom.insert_slab::<ElementId>();
+        let root_id = rdom.root_id();
+        let mut root = rdom.get_mut(root_id).unwrap();
+        root.insert(ElementId(0));
+        Self {
+            templates: FxHashMap::default(),
+            stack: vec![root_id],
+            node_id_mapping: vec![Some(root_id)],
+        }
+    }
+
+    pub fn element_to_node_id(&self, element_id: ElementId) -> NodeId {
+        self.node_id_mapping.get(element_id.0).unwrap().unwrap()
+    }
+
+    fn set_element_id(&mut self, mut node: NodeMut, element_id: ElementId) {
+        let node_id = node.id();
+        node.insert(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);
+    }
+
+    pub fn load_child(&self, rdom: &RealDom, path: &[u8]) -> NodeId {
+        let mut current = rdom.get(*self.stack.last().unwrap()).unwrap();
+        for i in path {
+            let new_id = current.child_ids().unwrap()[*i as usize];
+            current = rdom.get(new_id).unwrap();
+        }
+        current.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(&mut self, rdom: &mut RealDom, mutations: Mutations) {
+        for template in mutations.templates {
+            let mut template_root_ids = Vec::new();
+            for root in template.roots {
+                let id = create_template_node(rdom, root);
+                template_root_ids.push(id);
+            }
+            self.templates
+                .insert(template.name.to_string(), template_root_ids);
+        }
+
+        for e in mutations.edits {
+            use dioxus_core::Mutation::*;
+            match e {
+                AppendChildren { id, m } => {
+                    let children = self.stack.split_off(self.stack.len() - m);
+                    let parent = self.element_to_node_id(id);
+                    for child in children {
+                        rdom.add_child(parent, child);
+                    }
+                }
+                AssignId { path, id } => {
+                    let node_id = self.load_child(rdom, path);
+                    self.set_element_id(rdom.get_mut(node_id).unwrap(), id);
+                }
+                CreatePlaceholder { id } => {
+                    let node = NodeType::Placeholder;
+                    let node = rdom.create_node(node, true);
+                    let node_id = node.id();
+                    self.set_element_id(node, id);
+                    self.stack.push(node_id);
+                }
+                CreateTextNode { value, id } => {
+                    let node_data = NodeType::Text(value.to_string());
+                    let node = rdom.create_node(node_data, true);
+                    let node_id = node.id();
+                    self.set_element_id(node, id);
+                    self.stack.push(node_id);
+                }
+                HydrateText { path, value, id } => {
+                    let node_id = self.load_child(rdom, path);
+                    let node = rdom.get_mut(node_id).unwrap();
+                    self.set_element_id(node, id);
+                    let mut node = rdom.get_mut(node_id).unwrap();
+                    if let NodeTypeMut::Text(text) = node.node_type_mut() {
+                        *text = value.to_string();
+                    } else {
+                        node.set_type(NodeType::Text(value.to_string()));
+                    }
+                }
+                LoadTemplate { name, index, id } => {
+                    let template_id = self.templates[name][index];
+                    let clone_id = rdom.clone_node(template_id);
+                    let clone = rdom.get_mut(clone_id).unwrap();
+                    self.set_element_id(clone, id);
+                    self.stack.push(clone_id);
+                }
+                ReplaceWith { id, m } => {
+                    let new_nodes = self.stack.split_off(self.stack.len() - m);
+                    let old_node_id = self.element_to_node_id(id);
+                    for new in new_nodes {
+                        let mut node = rdom.get_mut(new).unwrap();
+                        node.insert_before(old_node_id);
+                    }
+                    rdom.remove(old_node_id);
+                }
+                ReplacePlaceholder { path, m } => {
+                    let new_nodes = self.stack.split_off(self.stack.len() - m);
+                    let old_node_id = self.load_child(rdom, path);
+                    for new in new_nodes {
+                        let mut node = rdom.get_mut(new).unwrap();
+                        node.insert_before(old_node_id);
+                    }
+                    rdom.remove(old_node_id);
+                }
+                InsertAfter { id, m } => {
+                    let new_nodes = self.stack.split_off(self.stack.len() - m);
+                    let old_node_id = self.element_to_node_id(id);
+                    for new in new_nodes.into_iter().rev() {
+                        let mut node = rdom.get_mut(new).unwrap();
+                        node.insert_after(old_node_id);
+                    }
+                }
+                InsertBefore { id, m } => {
+                    let new_nodes = self.stack.split_off(self.stack.len() - m);
+                    let old_node_id = self.element_to_node_id(id);
+                    for new in new_nodes {
+                        rdom.tree.insert_before(old_node_id, new);
+                    }
+                }
+                SetAttribute {
+                    name,
+                    value,
+                    id,
+                    ns,
+                } => {
+                    let node_id = self.element_to_node_id(id);
+                    let mut node = rdom.get_mut(node_id).unwrap();
+                    if let NodeTypeMut::Element(element) = &mut node.node_type_mut() {
+                        if let BorrowedAttributeValue::None = &value {
+                            element.remove_attributes(&OwnedAttributeDiscription {
+                                name: name.to_string(),
+                                namespace: ns.map(|s| s.to_string()),
+                                volatile: false,
+                            });
+                        } else {
+                            element.set_attribute(
+                                OwnedAttributeDiscription {
+                                    name: name.to_string(),
+                                    namespace: ns.map(|s| s.to_string()),
+                                    volatile: false,
+                                },
+                                OwnedAttributeValue::from(value),
+                            );
+                        }
+                    }
+                }
+                SetText { value, id } => {
+                    let node_id = self.element_to_node_id(id);
+                    let mut node = rdom.get_mut(node_id).unwrap();
+                    if let NodeTypeMut::Text(text) = node.node_type_mut() {
+                        *text = value.to_string();
+                    }
+                }
+                NewEventListener { name, id } => {
+                    let node_id = self.element_to_node_id(id);
+                    let mut node = rdom.get_mut(node_id).unwrap();
+                    node.add_event_listener(name);
+                }
+                RemoveEventListener { id, name } => {
+                    let node_id = self.element_to_node_id(id);
+                    let mut node = rdom.get_mut(node_id).unwrap();
+                    node.remove_event_listener(name);
+                }
+                Remove { id } => {
+                    let node_id = self.element_to_node_id(id);
+                    rdom.remove(node_id);
+                }
+                PushRoot { id } => {
+                    let node_id = self.element_to_node_id(id);
+                    self.stack.push(node_id);
+                }
+            }
+        }
+    }
+}
+
+fn create_template_node(rdom: &mut RealDom, node: &TemplateNode) -> NodeId {
+    match node {
+        TemplateNode::Element {
+            tag,
+            namespace,
+            attrs,
+            children,
+        } => {
+            let node = NodeType::Element(ElementNode {
+                tag: tag.to_string(),
+                namespace: namespace.map(|s| s.to_string()),
+                attributes: attrs
+                    .iter()
+                    .filter_map(|attr| match attr {
+                        dioxus_core::TemplateAttribute::Static {
+                            name,
+                            value,
+                            namespace,
+                        } => Some((
+                            OwnedAttributeDiscription {
+                                namespace: namespace.map(|s| s.to_string()),
+                                name: name.to_string(),
+                                volatile: false,
+                            },
+                            OwnedAttributeValue::Text(value.to_string()),
+                        )),
+                        dioxus_core::TemplateAttribute::Dynamic { .. } => None,
+                    })
+                    .collect(),
+                listeners: FxHashSet::default(),
+            });
+            let node_id = rdom.create_node(node, true).id();
+            for child in *children {
+                let child_id = create_template_node(rdom, child);
+                rdom.add_child(node_id, child_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()
+        }
+    }
+}
+
+trait NodeImmutableDioxusExt<V: FromAnyValue + Send + Sync>: NodeImmutable<V> {
+    fn mounted_id(&self) -> Option<ElementId> {
+        self.get().copied()
+    }
+}
+
+impl<T: NodeImmutable<V>, V: FromAnyValue + Send + Sync> NodeImmutableDioxusExt<V> for T {}

+ 11 - 27
packages/native-core/src/lib.rs

@@ -8,6 +8,8 @@ pub use real_dom::{NodeMut, NodeRef, RealDom};
 use rustc_hash::FxHasher;
 pub use tree::NodeId;
 
+#[cfg(feature = "dioxus")]
+pub mod dioxus;
 pub mod layout_attributes;
 pub mod node;
 pub mod node_ref;
@@ -16,33 +18,15 @@ pub mod real_dom;
 pub mod tree;
 pub mod utils;
 
+pub mod prelude {
+    pub use crate::node::{ElementNode, FromAnyValue, NodeType, OwnedAttributeView};
+    pub use crate::node_ref::{AttributeMaskBuilder, NodeMaskBuilder, NodeView};
+    pub use crate::passes::{Dependancy, Pass};
+    pub use crate::real_dom::{NodeImmutable, NodeMut, NodeMutRaw, NodeMutable, NodeRef, RealDom};
+    pub use crate::tree::NodeId;
+    pub use crate::SendAnyMap;
+}
+
 pub type FxDashMap<K, V> = dashmap::DashMap<K, V, BuildHasherDefault<FxHasher>>;
 pub type FxDashSet<K> = dashmap::DashSet<K, BuildHasherDefault<FxHasher>>;
 pub type SendAnyMap = anymap::Map<dyn Any + Send + Sync + 'static>;
-
-/// Used in derived state macros
-#[derive(Eq, PartialEq)]
-#[doc(hidden)]
-pub struct HeightOrdering {
-    pub height: u16,
-    pub id: NodeId,
-}
-
-impl HeightOrdering {
-    pub fn new(height: u16, id: NodeId) -> Self {
-        HeightOrdering { height, id }
-    }
-}
-
-// not the ordering after height is just for deduplication it can be any ordering as long as it is consistent
-impl Ord for HeightOrdering {
-    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
-        self.height.cmp(&other.height).then(self.id.cmp(&other.id))
-    }
-}
-
-impl PartialOrd for HeightOrdering {
-    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
-        Some(self.cmp(other))
-    }
-}

+ 13 - 39
packages/native-core/src/node.rs

@@ -1,20 +1,8 @@
-use crate::tree::NodeId;
-use dioxus_core::{AnyValue, BorrowedAttributeValue, ElementId};
 use rustc_hash::{FxHashMap, FxHashSet};
-use std::fmt::Debug;
+use std::{any::Any, fmt::Debug};
 
 #[derive(Debug, Clone)]
-pub struct NodeData<V: FromAnyValue = ()> {
-    /// 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<V>,
-}
-
-#[derive(Debug, Clone)]
-pub struct ElementNode<V: FromAnyValue> {
+pub struct ElementNode<V: FromAnyValue = ()> {
     pub tag: String,
     pub namespace: Option<String>,
     pub attributes: FxHashMap<OwnedAttributeDiscription, OwnedAttributeValue<V>>,
@@ -29,21 +17,6 @@ pub enum NodeType<V: FromAnyValue = ()> {
     Placeholder,
 }
 
-impl<V: FromAnyValue> NodeData<V> {
-    pub(crate) fn new(node_type: NodeType<V>) -> Self {
-        NodeData {
-            element_id: None,
-            node_type,
-            node_id: NodeId(0),
-        }
-    }
-
-    /// get the mounted id of the node
-    pub fn mounted_id(&self) -> Option<ElementId> {
-        self.element_id
-    }
-}
-
 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
 pub struct OwnedAttributeDiscription {
     pub name: String,
@@ -72,11 +45,11 @@ pub enum OwnedAttributeValue<V: FromAnyValue = ()> {
 }
 
 pub trait FromAnyValue: Clone + 'static {
-    fn from_any_value(value: &dyn AnyValue) -> Self;
+    fn from_any_value(value: &dyn Any) -> Self;
 }
 
 impl FromAnyValue for () {
-    fn from_any_value(_: &dyn AnyValue) -> Self {}
+    fn from_any_value(_: &dyn Any) -> Self {}
 }
 
 impl<V: FromAnyValue> Debug for OwnedAttributeValue<V> {
@@ -91,15 +64,16 @@ impl<V: FromAnyValue> Debug for OwnedAttributeValue<V> {
     }
 }
 
-impl<V: FromAnyValue> From<BorrowedAttributeValue<'_>> for OwnedAttributeValue<V> {
-    fn from(value: BorrowedAttributeValue<'_>) -> Self {
+#[cfg(feature = "dioxus")]
+impl<V: FromAnyValue> From<dioxus_core::BorrowedAttributeValue<'_>> for OwnedAttributeValue<V> {
+    fn from(value: dioxus_core::BorrowedAttributeValue<'_>) -> Self {
         match value {
-            BorrowedAttributeValue::Text(text) => Self::Text(text.to_string()),
-            BorrowedAttributeValue::Float(float) => Self::Float(float),
-            BorrowedAttributeValue::Int(int) => Self::Int(int),
-            BorrowedAttributeValue::Bool(bool) => Self::Bool(bool),
-            BorrowedAttributeValue::Any(any) => Self::Custom(V::from_any_value(&*any)),
-            BorrowedAttributeValue::None => panic!("None attribute values result in removing the attribute, not converting it to a None value.")
+            dioxus_core::BorrowedAttributeValue::Text(text) => Self::Text(text.to_string()),
+            dioxus_core::BorrowedAttributeValue::Float(float) => Self::Float(float),
+            dioxus_core::BorrowedAttributeValue::Int(int) => Self::Int(int),
+            dioxus_core::BorrowedAttributeValue::Bool(bool) => Self::Bool(bool),
+            dioxus_core::BorrowedAttributeValue::Any(any) => Self::Custom(V::from_any_value(any.as_any())),
+            dioxus_core::BorrowedAttributeValue::None => panic!("None attribute values result in removing the attribute, not converting it to a None value.")
         }
     }
 }

+ 11 - 15
packages/native-core/src/node_ref.rs

@@ -1,42 +1,38 @@
-use dioxus_core::ElementId;
 use rustc_hash::FxHashSet;
 
 use crate::{
-    node::{ElementNode, FromAnyValue, NodeData, NodeType, OwnedAttributeView},
+    node::{ElementNode, FromAnyValue, NodeType, OwnedAttributeView},
     NodeId,
 };
 
 /// A view into a [VNode] with limited access.
 #[derive(Debug)]
 pub struct NodeView<'a, V: FromAnyValue = ()> {
-    inner: &'a NodeData<V>,
+    id: NodeId,
+    inner: &'a NodeType<V>,
     mask: &'a NodeMask,
 }
 
 impl<'a, V: FromAnyValue> NodeView<'a, V> {
     /// Create a new NodeView from a VNode, and mask.
-    pub fn new(node: &'a NodeData<V>, view: &'a NodeMask) -> Self {
+    pub fn new(id: NodeId, node: &'a NodeType<V>, view: &'a NodeMask) -> Self {
         Self {
             inner: node,
             mask: view,
+            id,
         }
     }
 
-    /// Get the id of the node
-    pub fn id(&self) -> Option<ElementId> {
-        self.inner.element_id
-    }
-
     /// Get the node id of the node
     pub fn node_id(&self) -> NodeId {
-        self.inner.node_id
+        self.id
     }
 
     /// Get the tag of the node if the tag is enabled in the mask
     pub fn tag(&self) -> Option<&'a str> {
         self.mask
             .tag
-            .then_some(match &self.inner.node_type {
+            .then_some(match &self.inner {
                 NodeType::Element(ElementNode { tag, .. }) => Some(&**tag),
                 _ => None,
             })
@@ -47,7 +43,7 @@ impl<'a, V: FromAnyValue> NodeView<'a, V> {
     pub fn namespace(&self) -> Option<&'a str> {
         self.mask
             .namespace
-            .then_some(match &self.inner.node_type {
+            .then_some(match &self.inner {
                 NodeType::Element(ElementNode { namespace, .. }) => namespace.as_deref(),
                 _ => None,
             })
@@ -58,7 +54,7 @@ impl<'a, V: FromAnyValue> NodeView<'a, V> {
     pub fn attributes<'b>(
         &'b self,
     ) -> Option<impl Iterator<Item = OwnedAttributeView<'a, V>> + 'b> {
-        match &self.inner.node_type {
+        match &self.inner {
             NodeType::Element(ElementNode { attributes, .. }) => Some(
                 attributes
                     .iter()
@@ -76,7 +72,7 @@ impl<'a, V: FromAnyValue> NodeView<'a, V> {
     pub fn text(&self) -> Option<&str> {
         self.mask
             .text
-            .then_some(match &self.inner.node_type {
+            .then_some(match &self.inner {
                 NodeType::Text(text) => Some(&**text),
                 _ => None,
             })
@@ -86,7 +82,7 @@ impl<'a, V: FromAnyValue> NodeView<'a, V> {
     /// Get the listeners if it is enabled in the mask
     pub fn listeners(&self) -> Option<impl Iterator<Item = &'a str> + '_> {
         if self.mask.listeners {
-            match &self.inner.node_type {
+            match &self.inner {
                 NodeType::Element(ElementNode { listeners, .. }) => {
                     Some(listeners.iter().map(|l| &**l))
                 }

+ 30 - 687
packages/native-core/src/passes.rs

@@ -7,7 +7,7 @@ use std::collections::BTreeMap;
 use std::marker::PhantomData;
 use std::sync::Arc;
 
-use crate::node::{FromAnyValue, NodeData};
+use crate::node::{FromAnyValue, NodeType};
 use crate::node_ref::{NodeMaskBuilder, NodeView};
 use crate::real_dom::RealDom;
 use crate::tree::{SlabEntry, Tree, TreeStateView};
@@ -129,26 +129,35 @@ pub trait Pass<V: FromAnyValue + Send + Sync = ()>: Any + Send + Sync {
     ) -> Self;
 
     fn validate() {
-        // no type can be a child and parent dependency
-        for type_id in Self::parent_type_ids().iter().copied() {
-            for type_id2 in Self::child_type_ids().iter().copied() {
-                if type_id == type_id2 {
-                    panic!("type cannot be both a parent and child dependency");
-                }
-            }
-        }
         // this type should not be a node dependency
         for type_id in Self::node_type_ids().iter().copied() {
             if type_id == TypeId::of::<Self>() {
                 panic!("The current type cannot be a node dependency");
             }
         }
+        // this type cannot be both a parent and child dependency
+        assert!(
+            Self::parent_type_ids()
+                .iter()
+                .any(|type_id| *type_id != TypeId::of::<Self>())
+                && Self::child_type_ids()
+                    .iter()
+                    .any(|type_id| *type_id != TypeId::of::<Self>()),
+            "The current type cannot be a parent and child dependency"
+        );
         // no states have the same type id
-        if Self::all_dependanices()
+        if Self::child_type_ids()
             .iter()
-            .collect::<FxDashSet<_>>()
+            .collect::<FxHashSet<_>>()
             .len()
-            != Self::all_dependanices().len()
+            != Self::child_type_ids().len()
+            || Self::parent_type_ids()
+                .iter()
+                .collect::<FxHashSet<_>>()
+                .len()
+                != Self::parent_type_ids().len()
+            || Self::node_type_ids().iter().collect::<FxHashSet<_>>().len()
+                != Self::node_type_ids().len()
         {
             panic!("all states must have unique type ids");
         }
@@ -178,28 +187,21 @@ pub trait Pass<V: FromAnyValue + Send + Sync = ()>: Any + Send + Sync {
                     let myself: SlabEntry<'static, Self> = unsafe {
                         std::mem::transmute(tree.get_slab_mut::<Self>().unwrap().entry(node_id))
                     };
-                    let node_data = tree.get_single::<NodeData<V>>(node_id).unwrap();
+                    let node_data = tree.get_single::<NodeType<V>>(node_id).unwrap();
                     let node = tree.get::<Self::NodeDependencies>(node_id).unwrap();
                     let children = tree.children::<Self::ChildDependencies>(node_id);
                     let parent = tree.parent::<Self::ParentDependencies>(node_id);
 
+                    let view = NodeView::new(node_id, node_data, &node_mask);
                     if myself.value.is_none() {
-                        *myself.value = Some(Self::create(
-                            NodeView::new(node_data, &node_mask),
-                            node,
-                            parent,
-                            children,
-                            context,
-                        ));
+                        *myself.value = Some(Self::create(view, node, parent, children, context));
                         true
                     } else {
-                        myself.value.as_mut().unwrap().pass(
-                            NodeView::new(node_data, &node_mask),
-                            node,
-                            parent,
-                            children,
-                            context,
-                        )
+                        myself
+                            .value
+                            .as_mut()
+                            .unwrap()
+                            .pass(view, node, parent, children, context)
                     }
                 },
             ) as PassCallback,
@@ -409,7 +411,7 @@ pub fn resolve_passes<V: FromAnyValue + Send + Sync>(
                             .iter()
                             .filter(|id| **id != pass.this_type_id)
                             .copied()
-                            .chain(std::iter::once(TypeId::of::<NodeData<V>>())),
+                            .chain(std::iter::once(TypeId::of::<NodeType<V>>())),
                         [pass.this_type_id],
                     );
                     let dirty_nodes = dirty_nodes.clone();
@@ -432,662 +434,3 @@ pub fn resolve_passes<V: FromAnyValue + Send + Sync>(
     }
     std::sync::Arc::try_unwrap(nodes_updated).unwrap()
 }
-
-// #[test]
-// fn node_pass() {
-//     use crate::real_dom::RealDom;
-//     use crate::tree::{Tree, TreeLike};
-
-//     #[derive(Debug, Default, Clone, PartialEq)]
-//     struct Number(i32);
-
-//     impl State for Number {
-//         fn create_passes() -> Box<[TypeErasedPass<Self>]> {
-//             Box::new([Number::to_type_erased()])
-//         }
-//     }
-
-//     impl AnyMapLike for Number {
-//         fn get<T: Any+Sync+Send>(&self) -> Option<&T> {
-//             if TypeId::of::<Self>() == TypeId::of::<T>() {
-//                 Some(unsafe { &*(self as *const Self as *const T) })
-//             } else {
-//                 None
-//             }
-//         }
-
-//         fn get_mut<T: Any+Sync+Send>(&mut self) -> Option<&mut T> {
-//             if TypeId::of::<Self>() == TypeId::of::<T>() {
-//                 Some(unsafe { &mut *(self as *mut Self as *mut T) })
-//             } else {
-//                 None
-//             }
-//         }
-//     }
-
-//     impl Pass for Number {
-//         type ChildDependencies = ();
-//         type NodeDependencies = ();
-//         type ParentDependencies = ();
-//         type Ctx = ();
-//         const MASK: NodeMask = NodeMask::new();
-
-//         fn pass<'a>(
-//             &mut self,
-//             node_view: NodeView,
-//             node: <Self::NodeDependencies as Dependancy>::ElementBorrowed<'a>,
-//             parent: Option<<Self::ParentDependencies as Dependancy>::ElementBorrowed<'a>>,
-//             children: Option<
-//                 impl Iterator<Item = <Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>,
-//             >,
-//             context: <Self::Ctx as Dependancy>::ElementBorrowed<'a>,
-//         ) -> bool {
-//             self.0 += 1;
-//             true
-//         }
-//     }
-
-//     let mut tree: RealDom<Number> = RealDom::new();
-//     tree.dirty_nodes.insert(TypeId::of::<Number>(), NodeId(0));
-//     tree.update_state(SendAnyMap::new());
-
-//     assert_eq!(tree.get(tree.root()).unwrap().state.0, 1);
-// }
-
-// #[test]
-// fn dependant_node_pass() {
-//     use crate::real_dom::RealDom;
-
-//     #[derive(Debug, Default, Clone, PartialEq)]
-//     struct AddNumber(i32);
-
-//     impl Pass for AddNumber {
-//         type ChildDependencies = ();
-//         type NodeDependencies = (SubtractNumber,);
-//         type ParentDependencies = ();
-//         type Ctx = ();
-//         const MASK: NodeMask = NodeMask::new();
-
-//         fn pass<'a>(
-//             &mut self,
-//             node_view: NodeView,
-//             node: <Self::NodeDependencies as Dependancy>::ElementBorrowed<'a>,
-//             parent: Option<<Self::ParentDependencies as Dependancy>::ElementBorrowed<'a>>,
-//             children: Option<
-//                 impl Iterator<Item = <Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>,
-//             >,
-//             context: <Self::Ctx as Dependancy>::ElementBorrowed<'a>,
-//         ) -> bool {
-//             self.0 += 1;
-//             true
-//         }
-//     }
-
-//     #[derive(Debug, Default, Clone, PartialEq)]
-//     struct SubtractNumber(i32);
-
-//     impl Pass for SubtractNumber {
-//         type ChildDependencies = ();
-//         type NodeDependencies = ();
-//         type ParentDependencies = ();
-//         type Ctx = ();
-//         const MASK: NodeMask = NodeMask::new();
-
-//         fn pass<'a>(
-//             &mut self,
-//             node_view: NodeView,
-//             node: <Self::NodeDependencies as Dependancy>::ElementBorrowed<'a>,
-//             parent: Option<<Self::ParentDependencies as Dependancy>::ElementBorrowed<'a>>,
-//             children: Option<
-//                 impl Iterator<Item = <Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>,
-//             >,
-//             context: <Self::Ctx as Dependancy>::ElementBorrowed<'a>,
-//         ) -> bool {
-//             self.0 -= 1;
-//             true
-//         }
-//     }
-
-//     #[derive(Debug, Default, Clone, PartialEq)]
-//     struct NumberState {
-//         add_number: AddNumber,
-//         subtract_number: SubtractNumber,
-//     }
-
-//     impl AnyMapLike for NumberState {
-//         fn get<T: Any+Sync+Send>(&self) -> Option<&T> {
-//             if TypeId::of::<AddNumber>() == TypeId::of::<T>() {
-//                 Some(unsafe { &*(&self.add_number as *const AddNumber as *const T) })
-//             } else if TypeId::of::<SubtractNumber>() == TypeId::of::<T>() {
-//                 Some(unsafe { &*(&self.subtract_number as *const SubtractNumber as *const T) })
-//             } else {
-//                 None
-//             }
-//         }
-
-//         fn get_mut<T: Any+Sync+Send>(&mut self) -> Option<&mut T> {
-//             if TypeId::of::<AddNumber>() == TypeId::of::<T>() {
-//                 Some(unsafe { &mut *(&mut self.add_number as *mut AddNumber as *mut T) })
-//             } else if TypeId::of::<SubtractNumber>() == TypeId::of::<T>() {
-//                 Some(unsafe { &mut *(&mut self.subtract_number as *mut SubtractNumber as *mut T) })
-//             } else {
-//                 None
-//             }
-//         }
-//     }
-
-//     impl State for NumberState {
-//         fn create_passes() -> Box<[TypeErasedPass<Self>]> {
-//             Box::new([
-//                 AddNumber::to_type_erased(),
-//                 SubtractNumber::to_type_erased(),
-//             ])
-//         }
-//     }
-
-//     let mut tree: RealDom<NumberState> = RealDom::new();
-//     tree.dirty_nodes
-//         .insert(TypeId::of::<SubtractNumber>(), NodeId(0));
-//     tree.update_state(dirty_nodes, SendAnyMap::new());
-
-//     assert_eq!(
-//         tree.get(tree.root()).unwrap().state,
-//         NumberState {
-//             add_number: AddNumber(1),
-//             subtract_number: SubtractNumber(-1)
-//         }
-//     );
-// }
-
-// #[test]
-// fn independant_node_pass() {
-//     use crate::real_dom::RealDom;
-//     use crate::tree::{Tree, TreeLike};
-
-//     #[derive(Debug, Default, Clone, PartialEq)]
-//     struct AddNumber(i32);
-
-//     impl Pass for AddNumber {
-//         type ChildDependencies = ();
-//         type NodeDependencies = ();
-//         type ParentDependencies = ();
-//         type Ctx = ();
-//         const MASK: NodeMask = NodeMask::new();
-
-//         fn pass<'a>(
-//             &mut self,
-//             node_view: NodeView,
-//             node: <Self::NodeDependencies as Dependancy>::ElementBorrowed<'a>,
-//             parent: Option<<Self::ParentDependencies as Dependancy>::ElementBorrowed<'a>>,
-//             children: Option<
-//                 impl Iterator<Item = <Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>,
-//             >,
-//             context: <Self::Ctx as Dependancy>::ElementBorrowed<'a>,
-//         ) -> bool {
-//             self.0 += 1;
-//             true
-//         }
-//     }
-
-//     #[derive(Debug, Default, Clone, PartialEq)]
-//     struct SubtractNumber(i32);
-
-//     impl Pass for SubtractNumber {
-//         type ChildDependencies = ();
-//         type NodeDependencies = ();
-//         type ParentDependencies = ();
-//         type Ctx = ();
-//         const MASK: NodeMask = NodeMask::new();
-
-//         fn pass<'a>(
-//             &mut self,
-//             node_view: NodeView,
-//             node: <Self::NodeDependencies as Dependancy>::ElementBorrowed<'a>,
-//             parent: Option<<Self::ParentDependencies as Dependancy>::ElementBorrowed<'a>>,
-//             children: Option<
-//                 impl Iterator<Item = <Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>,
-//             >,
-//             context: <Self::Ctx as Dependancy>::ElementBorrowed<'a>,
-//         ) -> bool {
-//             self.0 -= 1;
-//             true
-//         }
-//     }
-
-//     #[derive(Debug, Default, Clone, PartialEq)]
-//     struct NumberState {
-//         add_number: AddNumber,
-//         subtract_number: SubtractNumber,
-//     }
-
-//     impl AnyMapLike for NumberState {
-//         fn get<T: Any+Sync+Send>(&self) -> Option<&T> {
-//             if TypeId::of::<AddNumber>() == TypeId::of::<T>() {
-//                 Some(unsafe { &*(&self.add_number as *const AddNumber as *const T) })
-//             } else if TypeId::of::<SubtractNumber>() == TypeId::of::<T>() {
-//                 Some(unsafe { &*(&self.subtract_number as *const SubtractNumber as *const T) })
-//             } else {
-//                 None
-//             }
-//         }
-
-//         fn get_mut<T: Any+Sync+Send>(&mut self) -> Option<&mut T> {
-//             if TypeId::of::<AddNumber>() == TypeId::of::<T>() {
-//                 Some(unsafe { &mut *(&mut self.add_number as *mut AddNumber as *mut T) })
-//             } else if TypeId::of::<SubtractNumber>() == TypeId::of::<T>() {
-//                 Some(unsafe { &mut *(&mut self.subtract_number as *mut SubtractNumber as *mut T) })
-//             } else {
-//                 None
-//             }
-//         }
-//     }
-
-//     impl State for NumberState {
-//         fn create_passes() -> Box<[TypeErasedPass<Self>]> {
-//             Box::new([
-//                 AddNumber::to_type_erased(),
-//                 SubtractNumber::to_type_erased(),
-//             ])
-//         }
-//     }
-
-//     let mut tree: RealDom<NumberState> = RealDom::new();
-//     tree.dirty_nodes
-//         .insert(TypeId::of::<SubtractNumber>(), NodeId(0));
-//     tree.update_state(SendAnyMap::new());
-
-//     assert_eq!(
-//         tree.get(tree.root()).unwrap().state,
-//         NumberState {
-//             add_number: AddNumber(0),
-//             subtract_number: SubtractNumber(-1)
-//         }
-//     );
-// }
-
-// #[test]
-// fn down_pass() {
-//     use crate::real_dom::RealDom;
-//     use crate::tree::{Tree, TreeLike};
-
-//     #[derive(Debug, Default, Clone, PartialEq)]
-//     struct AddNumber(i32);
-
-//     impl Pass for AddNumber {
-//         type ChildDependencies = ();
-//         type NodeDependencies = ();
-//         type ParentDependencies = (AddNumber,);
-//         type Ctx = ();
-//         const MASK: NodeMask = NodeMask::new();
-
-//         fn pass<'a>(
-//             &mut self,
-//             node_view: NodeView,
-//             node: <Self::NodeDependencies as Dependancy>::ElementBorrowed<'a>,
-//             parent: Option<<Self::ParentDependencies as Dependancy>::ElementBorrowed<'a>>,
-//             children: Option<
-//                 impl Iterator<Item = <Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>,
-//             >,
-//             context: <Self::Ctx as Dependancy>::ElementBorrowed<'a>,
-//         ) -> bool {
-//             if let Some((parent,)) = parent {
-//                 *self.0 += *parent.0;
-//             }
-//             true
-//         }
-//     }
-
-//     #[derive(Debug, Default, Clone, PartialEq)]
-//     struct NumberState {
-//         add_number: AddNumber,
-//     }
-
-//     impl AnyMapLike for NumberState {
-//         fn get<T: Any+Sync+Send>(&self) -> Option<&T> {
-//             if TypeId::of::<AddNumber>() == TypeId::of::<T>() {
-//                 Some(unsafe { &*(&self.add_number as *const AddNumber as *const T) })
-//             } else {
-//                 None
-//             }
-//         }
-
-//         fn get_mut<T: Any+Sync+Send>(&mut self) -> Option<&mut T> {
-//             if TypeId::of::<AddNumber>() == TypeId::of::<T>() {
-//                 Some(unsafe { &mut *(&mut self.add_number as *mut AddNumber as *mut T) })
-//             } else {
-//                 None
-//             }
-//         }
-//     }
-
-//     impl State for NumberState {
-//         fn create_passes() -> Box<[TypeErasedPass<Self>]> {
-//             Box::new([AddNumber::to_type_erased()])
-//         }
-//     }
-
-//     let mut tree: RealDom<NumberState> = RealDom::new();
-//     let parent = tree.root();
-//     let child1 = tree.create_node(1);
-//     tree.add_child(parent, child1);
-//     let grandchild1 = tree.create_node(1);
-//     tree.add_child(child1, grandchild1);
-//     let child2 = tree.create_node(1);
-//     tree.add_child(parent, child2);
-//     let grandchild2 = tree.create_node(1);
-//     tree.add_child(child2, grandchild2);
-
-//     tree.dirty_nodes
-//         .insert(TypeId::of::<AddNumber>(), NodeId(0));
-//     tree.update_state(SendAnyMap::new());
-
-//     assert_eq!(tree.get(tree.root()).unwrap().state.add_number.0, 1);
-//     assert_eq!(tree.get(child1).unwrap().state.add_number.0, 2);
-//     assert_eq!(tree.get(grandchild1).unwrap().state.add_number.0, 3);
-//     assert_eq!(tree.get(child2).unwrap().state.add_number.0, 2);
-//     assert_eq!(tree.get(grandchild2).unwrap().state.add_number.0, 3);
-// }
-
-// #[test]
-// fn dependant_down_pass() {
-//     use crate::tree::{Tree, TreeLike};
-//     // 0
-//     let mut tree = Tree::new(1);
-//     let parent = tree.root();
-//     // 1
-//     let child1 = tree.create_node(1);
-//     tree.add_child(parent, child1);
-//     // 2
-//     let grandchild1 = tree.create_node(1);
-//     tree.add_child(child1, grandchild1);
-//     // 3
-//     let child2 = tree.create_node(1);
-//     tree.add_child(parent, child2);
-//     // 4
-//     let grandchild2 = tree.create_node(1);
-//     tree.add_child(child2, grandchild2);
-
-//     struct AddPass;
-//     impl Pass for AddPass {
-//         fn pass_id(&self) -> PassId {
-//             PassId(0)
-//         }
-
-//         fn dependancies(&self) -> &'static [PassId] {
-//             &[PassId(1)]
-//         }
-
-//         fn dependants(&self) -> &'static [PassId] {
-//             &[]
-//         }
-
-//         fn mask(&self) -> MemberMask {
-//             MemberMask(0)
-//         }
-//     }
-//     impl DownwardPass<i32> for AddPass {
-//         fn pass(&self, node: &mut i32, parent: Option<&mut i32>, _: &SendAnyMap) -> PassReturn {
-//             if let Some(parent) = parent {
-//                 *node += *parent;
-//             } else {
-//             }
-//             PassReturn {
-//                 progress: true,
-//                 mark_dirty: true,
-//             }
-//         }
-//     }
-
-//     struct SubtractPass;
-//     impl Pass for SubtractPass {
-//         fn pass_id(&self) -> PassId {
-//             PassId(1)
-//         }
-
-//         fn dependancies(&self) -> &'static [PassId] {
-//             &[]
-//         }
-
-//         fn dependants(&self) -> &'static [PassId] {
-//             &[PassId(0)]
-//         }
-
-//         fn mask(&self) -> MemberMask {
-//             MemberMask(0)
-//         }
-//     }
-//     impl DownwardPass<i32> for SubtractPass {
-//         fn pass(&self, node: &mut i32, parent: Option<&mut i32>, _: &SendAnyMap) -> PassReturn {
-//             if let Some(parent) = parent {
-//                 *node -= *parent;
-//             } else {
-//             }
-//             PassReturn {
-//                 progress: true,
-//                 mark_dirty: true,
-//             }
-//         }
-//     }
-
-//     let add_pass = AnyPass::Downward(&AddPass);
-//     let subtract_pass = AnyPass::Downward(&SubtractPass);
-//     let passes = vec![&add_pass, &subtract_pass];
-//     let dirty_nodes: DirtyNodeStates = DirtyNodeStates::default();
-//     dirty_nodes.insert(PassId(1), tree.root());
-//     resolve_passes(&mut tree, dirty_nodes, passes, SendAnyMap::new());
-
-//     // Tree before:
-//     // 1=\
-//     //   1=\
-//     //     1
-//     //   1=\
-//     //     1
-//     // Tree after subtract:
-//     // 1=\
-//     //   0=\
-//     //     1
-//     //   0=\
-//     //     1
-//     // Tree after add:
-//     // 1=\
-//     //   1=\
-//     //     2
-//     //   1=\
-//     //     2
-//     assert_eq!(tree.get(tree.root()).unwrap(), &1);
-//     assert_eq!(tree.get(child1).unwrap(), &1);
-//     assert_eq!(tree.get(grandchild1).unwrap(), &2);
-//     assert_eq!(tree.get(child2).unwrap(), &1);
-//     assert_eq!(tree.get(grandchild2).unwrap(), &2);
-// }
-
-// #[test]
-// fn up_pass() {
-//     use crate::tree::{Tree, TreeLike};
-//     // Tree before:
-//     // 0=\
-//     //   0=\
-//     //     1
-//     //   0=\
-//     //     1
-//     // Tree after:
-//     // 2=\
-//     //   1=\
-//     //     1
-//     //   1=\
-//     //     1
-//     let mut tree = Tree::new(0);
-//     let parent = tree.root();
-//     let child1 = tree.create_node(0);
-//     tree.add_child(parent, child1);
-//     let grandchild1 = tree.create_node(1);
-//     tree.add_child(child1, grandchild1);
-//     let child2 = tree.create_node(0);
-//     tree.add_child(parent, child2);
-//     let grandchild2 = tree.create_node(1);
-//     tree.add_child(child2, grandchild2);
-
-//     struct AddPass;
-//     impl Pass for AddPass {
-//         fn pass_id(&self) -> PassId {
-//             PassId(0)
-//         }
-
-//         fn dependancies(&self) -> &'static [PassId] {
-//             &[]
-//         }
-
-//         fn dependants(&self) -> &'static [PassId] {
-//             &[]
-//         }
-
-//         fn mask(&self) -> MemberMask {
-//             MemberMask(0)
-//         }
-//     }
-//     impl UpwardPass<i32> for AddPass {
-//         fn pass<'a>(
-//             &self,
-//             node: &mut i32,
-//             children: &mut dyn Iterator<Item = &'a mut i32>,
-//             _: &SendAnyMap,
-//         ) -> PassReturn {
-//             *node += children.map(|i| *i).sum::<i32>();
-//             PassReturn {
-//                 progress: true,
-//                 mark_dirty: true,
-//             }
-//         }
-//     }
-
-//     let add_pass = AnyPass::Upward(&AddPass);
-//     let passes = vec![&add_pass];
-//     let dirty_nodes: DirtyNodeStates = DirtyNodeStates::default();
-//     dirty_nodes.insert(PassId(0), grandchild1);
-//     dirty_nodes.insert(PassId(0), grandchild2);
-//     resolve_passes(&mut tree, dirty_nodes, passes, SendAnyMap::new());
-
-//     assert_eq!(tree.get(tree.root()).unwrap(), &2);
-//     assert_eq!(tree.get(child1).unwrap(), &1);
-//     assert_eq!(tree.get(grandchild1).unwrap(), &1);
-//     assert_eq!(tree.get(child2).unwrap(), &1);
-//     assert_eq!(tree.get(grandchild2).unwrap(), &1);
-// }
-
-// #[test]
-// fn dependant_up_pass() {
-//     use crate::tree::{Tree, TreeLike};
-//     // 0
-//     let mut tree = Tree::new(0);
-//     let parent = tree.root();
-//     // 1
-//     let child1 = tree.create_node(0);
-//     tree.add_child(parent, child1);
-//     // 2
-//     let grandchild1 = tree.create_node(1);
-//     tree.add_child(child1, grandchild1);
-//     // 3
-//     let child2 = tree.create_node(0);
-//     tree.add_child(parent, child2);
-//     // 4
-//     let grandchild2 = tree.create_node(1);
-//     tree.add_child(child2, grandchild2);
-
-//     struct AddPass;
-//     impl Pass for AddPass {
-//         fn pass_id(&self) -> PassId {
-//             PassId(0)
-//         }
-
-//         fn dependancies(&self) -> &'static [PassId] {
-//             &[PassId(1)]
-//         }
-
-//         fn dependants(&self) -> &'static [PassId] {
-//             &[]
-//         }
-
-//         fn mask(&self) -> MemberMask {
-//             MemberMask(0)
-//         }
-//     }
-//     impl UpwardPass<i32> for AddPass {
-//         fn pass<'a>(
-//             &self,
-//             node: &mut i32,
-//             children: &mut dyn Iterator<Item = &'a mut i32>,
-//             _: &SendAnyMap,
-//         ) -> PassReturn {
-//             *node += children.map(|i| *i).sum::<i32>();
-//             PassReturn {
-//                 progress: true,
-//                 mark_dirty: true,
-//             }
-//         }
-//     }
-
-//     struct SubtractPass;
-//     impl Pass for SubtractPass {
-//         fn pass_id(&self) -> PassId {
-//             PassId(1)
-//         }
-
-//         fn dependancies(&self) -> &'static [PassId] {
-//             &[]
-//         }
-
-//         fn dependants(&self) -> &'static [PassId] {
-//             &[PassId(0)]
-//         }
-
-//         fn mask(&self) -> MemberMask {
-//             MemberMask(0)
-//         }
-//     }
-//     impl UpwardPass<i32> for SubtractPass {
-//         fn pass<'a>(
-//             &self,
-//             node: &mut i32,
-//             children: &mut dyn Iterator<Item = &'a mut i32>,
-//             _: &SendAnyMap,
-//         ) -> PassReturn {
-//             *node -= children.map(|i| *i).sum::<i32>();
-//             PassReturn {
-//                 progress: true,
-//                 mark_dirty: true,
-//             }
-//         }
-//     }
-
-//     let add_pass = AnyPass::Upward(&AddPass);
-//     let subtract_pass = AnyPass::Upward(&SubtractPass);
-//     let passes = vec![&add_pass, &subtract_pass];
-//     let dirty_nodes: DirtyNodeStates = DirtyNodeStates::default();
-//     dirty_nodes.insert(PassId(1), grandchild1);
-//     dirty_nodes.insert(PassId(1), grandchild2);
-//     resolve_passes(&mut tree, dirty_nodes, passes, SendAnyMap::new());
-
-//     // Tree before:
-//     // 0=\
-//     //   0=\
-//     //     1
-//     //   0=\
-//     //     1
-//     // Tree after subtract:
-//     // 2=\
-//     //   -1=\
-//     //      1
-//     //   -1=\
-//     //      1
-//     // Tree after add:
-//     // 2=\
-//     //   0=\
-//     //     1
-//     //   0=\
-//     //     1
-//     assert_eq!(tree.get(tree.root()).unwrap(), &2);
-//     assert_eq!(tree.get(child1).unwrap(), &0);
-//     assert_eq!(tree.get(grandchild1).unwrap(), &1);
-//     assert_eq!(tree.get(child2).unwrap(), &0);
-//     assert_eq!(tree.get(grandchild2).unwrap(), &1);
-// }

+ 156 - 333
packages/native-core/src/real_dom.rs

@@ -1,15 +1,13 @@
-use dioxus_core::{BorrowedAttributeValue, ElementId, Mutations, TemplateNode};
-
 use rustc_hash::{FxHashMap, FxHashSet};
 use std::any::{Any, TypeId};
 use std::collections::VecDeque;
 
 use crate::node::{
-    ElementNode, FromAnyValue, NodeData, NodeType, OwnedAttributeDiscription, OwnedAttributeValue,
+    ElementNode, FromAnyValue, NodeType, OwnedAttributeDiscription, OwnedAttributeValue,
 };
 use crate::node_ref::{AttributeMask, NodeMask, NodeMaskBuilder};
 use crate::passes::{resolve_passes, DirtyNodeStates, TypeErasedPass};
-use crate::tree::{EntryBuilder, NodeId, Tree};
+use crate::tree::{NodeId, Tree};
 use crate::{FxDashSet, SendAnyMap};
 
 /// A Dom that can sync with the VirtualDom mutations intended for use in lazy renderers.
@@ -20,11 +18,7 @@ use crate::{FxDashSet, SendAnyMap};
 /// To allow custom values to be passed into attributes implement FromAnyValue on a type that can represent your custom value and specify the V generic to be that type. If you have many different custom values, it can be useful to use a enum type to represent the varients.
 pub struct RealDom<V: FromAnyValue + Send + Sync = ()> {
     pub(crate) tree: Tree,
-    /// a map from element id to real node id
-    node_id_mapping: Vec<Option<NodeId>>,
     nodes_listening: FxHashMap<String, FxHashSet<NodeId>>,
-    stack: Vec<NodeId>,
-    templates: FxHashMap<String, Vec<NodeId>>,
     pub(crate) passes: Box<[TypeErasedPass<V>]>,
     passes_updated: FxHashMap<NodeId, FxHashSet<TypeId>>,
     nodes_updated: FxHashMap<NodeId, NodeMask>,
@@ -34,19 +28,17 @@ pub struct RealDom<V: FromAnyValue + Send + Sync = ()> {
 impl<V: FromAnyValue + Send + Sync> RealDom<V> {
     pub fn new(mut passes: Box<[TypeErasedPass<V>]>) -> RealDom<V> {
         let mut tree = Tree::new();
-        tree.insert_slab::<NodeData<V>>();
+        tree.insert_slab::<NodeType<V>>();
         for pass in passes.iter() {
             (pass.create)(&mut tree);
         }
         let root_id = tree.root();
-        let mut root_node: NodeData<V> = NodeData::new(NodeType::Element(ElementNode {
+        let root_node: NodeType<V> = NodeType::Element(ElementNode {
             tag: "Root".to_string(),
             namespace: Some("Root".to_string()),
             attributes: FxHashMap::default(),
             listeners: FxHashSet::default(),
-        }));
-        root_node.element_id = Some(ElementId(0));
-        root_node.node_id = root_id;
+        });
         tree.insert(root_id, root_node);
 
         // resolve dependants for each pass
@@ -71,10 +63,7 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
 
         RealDom {
             tree,
-            node_id_mapping: vec![Some(root_id)],
             nodes_listening: FxHashMap::default(),
-            stack: vec![root_id],
-            templates: FxHashMap::default(),
             passes,
             passes_updated,
             nodes_updated,
@@ -114,239 +103,23 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
         }
     }
 
-    pub fn element_to_node_id(&self, element_id: ElementId) -> NodeId {
-        self.node_id_mapping.get(element_id.0).unwrap().unwrap()
-    }
-
-    fn set_element_id(&mut self, node_id: NodeId, element_id: ElementId) {
-        let mut node = self.tree.get_mut::<NodeData>(node_id).unwrap();
-        let node_id = node.node_id;
-        node.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]) -> NodeId {
-        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,
-        mut node: NodeData<V>,
-        id: Option<ElementId>,
-        mark_dirty: bool,
-    ) -> EntryBuilder<'_> {
+    pub fn create_node(&mut self, node: NodeType<V>, mark_dirty: bool) -> NodeMut<'_, V> {
         let mut node_entry = self.tree.create_node();
-        let node_id = node_entry.id();
+        let id = node_entry.id();
         if mark_dirty {
             self.passes_updated
-                .entry(node_id)
+                .entry(id)
                 .or_default()
                 .extend(self.passes.iter().map(|x| x.this_type_id));
         }
-        node.node_id = node_id;
-        node.element_id = id;
         node_entry.insert(node);
-        node_entry
+        NodeMut::new(id, self)
     }
 
-    fn add_child(&mut self, node_id: NodeId, child_id: NodeId) {
+    pub fn add_child(&mut self, node_id: NodeId, child_id: NodeId) {
         self.tree.add_child(node_id, child_id);
     }
 
-    fn create_template_node(&mut self, node: &TemplateNode) -> NodeId {
-        match node {
-            TemplateNode::Element {
-                tag,
-                namespace,
-                attrs,
-                children,
-            } => {
-                let node = NodeData::new(NodeType::Element(ElementNode {
-                    tag: tag.to_string(),
-                    namespace: namespace.map(|s| s.to_string()),
-                    attributes: attrs
-                        .iter()
-                        .filter_map(|attr| match attr {
-                            dioxus_core::TemplateAttribute::Static {
-                                name,
-                                value,
-                                namespace,
-                            } => Some((
-                                OwnedAttributeDiscription {
-                                    namespace: namespace.map(|s| s.to_string()),
-                                    name: name.to_string(),
-                                    volatile: false,
-                                },
-                                OwnedAttributeValue::Text(value.to_string()),
-                            )),
-                            dioxus_core::TemplateAttribute::Dynamic { .. } => None,
-                        })
-                        .collect(),
-                    listeners: FxHashSet::default(),
-                }));
-                let node_id = self.create_node(node, None, true).id();
-                for child in *children {
-                    let child_id = self.create_template_node(child);
-                    self.add_child(node_id, child_id);
-                }
-                node_id
-            }
-            TemplateNode::Text { text } => self
-                .create_node(NodeData::new(NodeType::Text(text.to_string())), None, true)
-                .id(),
-            TemplateNode::Dynamic { .. } => self
-                .create_node(NodeData::new(NodeType::Placeholder), None, true)
-                .id(),
-            TemplateNode::DynamicText { .. } => self
-                .create_node(NodeData::new(NodeType::Text(String::new())), None, true)
-                .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(&mut self, mutations: Mutations) {
-        for template in mutations.templates {
-            let mut template_root_ids = Vec::new();
-            for root in template.roots {
-                let id = self.create_template_node(root);
-                template_root_ids.push(id);
-            }
-            self.templates
-                .insert(template.name.to_string(), template_root_ids);
-        }
-
-        for e in mutations.edits {
-            use dioxus_core::Mutation::*;
-            match e {
-                AppendChildren { id, m } => {
-                    let children = self.stack.split_off(self.stack.len() - m);
-                    let parent = self.element_to_node_id(id);
-                    for child in children {
-                        self.add_child(parent, child);
-                    }
-                }
-                AssignId { path, id } => {
-                    self.set_element_id(self.load_child(path), id);
-                }
-                CreatePlaceholder { id } => {
-                    let node = NodeData::new(NodeType::Placeholder);
-                    let node_id = self.create_node(node, None, true).id();
-                    self.set_element_id(node_id, id);
-                    self.stack.push(node_id);
-                }
-                CreateTextNode { value, id } => {
-                    let node_data = NodeData::new(NodeType::Text(value.to_string()));
-                    let node_id = self.create_node(node_data, None, true).id();
-                    self.set_element_id(node_id, id);
-                    self.stack.push(node_id);
-                }
-                HydrateText { path, value, id } => {
-                    let node_id = self.load_child(path);
-                    self.set_element_id(node_id, id);
-                    let mut node = self.get_mut(node_id).unwrap();
-                    if let NodeTypeMut::Text(text) = node.node_type_mut() {
-                        *text = value.to_string();
-                    } else {
-                        node.set_type(NodeType::Text(value.to_string()));
-                    }
-                }
-                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);
-                    self.stack.push(clone_id);
-                }
-                ReplaceWith { id, m } => {
-                    let new_nodes = self.stack.split_off(self.stack.len() - m);
-                    let old_node_id = self.element_to_node_id(id);
-                    for new in new_nodes {
-                        self.insert_before(old_node_id, new);
-                    }
-                    self.remove(old_node_id);
-                }
-                ReplacePlaceholder { path, m } => {
-                    let new_nodes = self.stack.split_off(self.stack.len() - m);
-                    let old_node_id = self.load_child(path);
-                    for new in new_nodes {
-                        self.insert_before(old_node_id, new);
-                    }
-                    self.remove(old_node_id);
-                }
-                InsertAfter { id, m } => {
-                    let new_nodes = self.stack.split_off(self.stack.len() - m);
-                    let old_node_id = self.element_to_node_id(id);
-                    for new in new_nodes.into_iter().rev() {
-                        self.insert_after(old_node_id, new);
-                    }
-                }
-                InsertBefore { id, m } => {
-                    let new_nodes = self.stack.split_off(self.stack.len() - m);
-                    let old_node_id = self.element_to_node_id(id);
-                    for new in new_nodes {
-                        self.tree.insert_before(old_node_id, new);
-                    }
-                }
-                SetAttribute {
-                    name,
-                    value,
-                    id,
-                    ns,
-                } => {
-                    let node_id = self.element_to_node_id(id);
-                    let mut node = self.get_mut(node_id).unwrap();
-                    if let NodeTypeMut::Element(element) = &mut node.node_type_mut() {
-                        if let BorrowedAttributeValue::None = &value {
-                            element.remove_attributes(&OwnedAttributeDiscription {
-                                name: name.to_string(),
-                                namespace: ns.map(|s| s.to_string()),
-                                volatile: false,
-                            });
-                        } else {
-                            element.set_attribute(
-                                OwnedAttributeDiscription {
-                                    name: name.to_string(),
-                                    namespace: ns.map(|s| s.to_string()),
-                                    volatile: false,
-                                },
-                                OwnedAttributeValue::from(value),
-                            );
-                        }
-                    }
-                }
-                SetText { value, id } => {
-                    let node_id = self.element_to_node_id(id);
-                    let mut node = self.get_mut(node_id).unwrap();
-                    if let NodeTypeMut::Text(text) = node.node_type_mut() {
-                        *text = value.to_string();
-                    }
-                }
-                NewEventListener { name, id } => {
-                    let node_id = self.element_to_node_id(id);
-                    self.add_event_listener(node_id, name);
-                }
-                RemoveEventListener { id, name } => {
-                    let node_id = self.element_to_node_id(id);
-                    self.remove_event_listener(node_id, name);
-                }
-                Remove { id } => {
-                    let node_id = self.element_to_node_id(id);
-                    self.remove(node_id);
-                }
-                PushRoot { id } => {
-                    let node_id = self.element_to_node_id(id);
-                    self.stack.push(node_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: &str) -> Vec<NodeRef<V>> {
@@ -376,10 +149,10 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
         self.tree.root()
     }
 
-    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 new_node = node.node_data().clone();
-        let new_id = self.create_node(new_node, None, true).id();
+        let new_node = node.node_type().clone();
+        let new_id = self.create_node(new_node, true).id();
 
         let children = self.tree.children_ids(node_id).unwrap().to_vec();
         for child in children {
@@ -389,26 +162,18 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
         new_id
     }
 
-    pub fn root(&self) -> NodeId {
-        self.tree.root()
-    }
-
-    pub fn get(&self, id: impl IntoNodeId<V>) -> Option<NodeRef<'_, V>> {
+    pub fn get(&self, id: NodeId) -> Option<NodeRef<'_, V>> {
         let id = id.into_node_id(self);
         self.tree.contains(id).then_some(NodeRef { id, dom: self })
     }
 
-    pub fn get_mut(&mut self, id: impl IntoNodeId<V>) -> Option<NodeMut<'_, V>> {
+    pub fn get_mut(&mut self, id: NodeId) -> Option<NodeMut<'_, V>> {
         let id = id.into_node_id(self);
-        self.tree.contains(id).then(|| NodeMut {
-            id,
-            dirty: NodeMask::default(),
-            dom: self,
-        })
+        self.tree.contains(id).then(|| NodeMut::new(id, self))
     }
 
     /// 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: impl IntoNodeId<V>) -> Option<NodeMutRaw<V>> {
+    pub fn get_mut_raw(&mut self, id: NodeId) -> Option<NodeMutRaw<V>> {
         let id = id.into_node_id(self);
         self.tree
             .contains(id)
@@ -439,7 +204,7 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
         )
     }
 
-    fn remove(&mut self, id: NodeId) {
+    pub fn remove(&mut self, id: NodeId) {
         if let Some(parent_id) = self.tree.parent_id(id) {
             self.mark_child_changed(parent_id);
         }
@@ -454,52 +219,8 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
         self.tree.replace(old, new);
     }
 
-    pub fn insert_before(&mut self, id: NodeId, new: NodeId) {
-        if let Some(parent_id) = self.tree.parent_id(id) {
-            self.mark_child_changed(parent_id);
-            self.mark_parent_added_or_removed(new);
-        }
-        self.tree.insert_before(id, new);
-    }
-
-    pub fn insert_after(&mut self, id: NodeId, new: NodeId) {
-        if let Some(parent_id) = self.tree.parent_id(id) {
-            self.mark_child_changed(parent_id);
-            self.mark_parent_added_or_removed(new);
-        }
-        self.tree.insert_after(id, new);
-    }
-
-    pub fn add_event_listener(&mut self, id: NodeId, event: &str) {
-        let mut node = self.get_mut(id).unwrap();
-        if let NodeTypeMut::Element(mut element) = node.node_type_mut() {
-            element.listeners_mut().insert(event.to_string());
-            drop(node);
-            match self.nodes_listening.get_mut(event) {
-                Some(hs) => {
-                    hs.insert(id);
-                }
-                None => {
-                    let mut hs = FxHashSet::default();
-                    hs.insert(id);
-                    self.nodes_listening.insert(event.to_string(), hs);
-                }
-            }
-        }
-    }
-
-    pub fn remove_event_listener(&mut self, id: NodeId, event: &str) {
-        {
-            let mut node = self.get_mut(id).unwrap();
-            if let NodeTypeMut::Element(mut element) = node.node_type_mut() {
-                element.listeners_mut().remove(event);
-            }
-        }
-        self.nodes_listening.get_mut(event).unwrap().remove(&id);
-    }
-
     pub fn traverse_depth_first(&self, mut f: impl FnMut(NodeRef<V>)) {
-        let mut stack = vec![self.root()];
+        let mut stack = vec![self.root_id()];
         while let Some(id) = stack.pop() {
             if let Some(node) = self.get(id) {
                 f(node);
@@ -512,7 +233,7 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
 
     pub fn traverse_breadth_first(&self, mut f: impl FnMut(NodeRef<V>)) {
         let mut queue = VecDeque::new();
-        queue.push_back(self.root());
+        queue.push_back(self.root_id());
         while let Some(id) = queue.pop_front() {
             if let Some(node) = self.get(id) {
                 f(node);
@@ -526,7 +247,7 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
     }
 
     pub fn traverse_depth_first_mut(&mut self, mut f: impl FnMut(NodeMut<V>)) {
-        let mut stack = vec![self.root()];
+        let mut stack = vec![self.root_id()];
         while let Some(id) = stack.pop() {
             if let Some(children) = self.tree.children_ids(id) {
                 let children = children.iter().copied().rev().collect::<Vec<_>>();
@@ -541,7 +262,7 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
 
     pub fn traverse_breadth_first_mut(&mut self, mut f: impl FnMut(NodeMut<V>)) {
         let mut queue = VecDeque::new();
-        queue.push_back(self.root());
+        queue.push_back(self.root_id());
         while let Some(id) = queue.pop_front() {
             if let Some(children) = self.tree.children_ids(id) {
                 let children = children.to_vec();
@@ -554,6 +275,10 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
             }
         }
     }
+
+    pub fn insert_slab<T: Any + Send + Sync>(&mut self) {
+        self.tree.insert_slab::<T>();
+    }
 }
 
 pub trait IntoNodeId<V: FromAnyValue + Send + Sync> {
@@ -566,27 +291,13 @@ impl<V: FromAnyValue + Send + Sync> IntoNodeId<V> for NodeId {
     }
 }
 
-impl<V: FromAnyValue + Send + Sync> IntoNodeId<V> for ElementId {
-    fn into_node_id(self, rdom: &RealDom<V>) -> NodeId {
-        rdom.element_to_node_id(self)
-    }
-}
-
 pub trait NodeImmutable<V: FromAnyValue + Send + Sync>: Sized {
     fn real_dom(&self) -> &RealDom<V>;
 
     fn id(&self) -> NodeId;
 
-    fn mounted_id(&self) -> Option<ElementId> {
-        self.node_data().mounted_id()
-    }
-
-    fn node_data(&self) -> &NodeData<V> {
-        self.get().unwrap()
-    }
-
     fn node_type(&self) -> &NodeType<V> {
-        &self.node_data().node_type
+        self.get().unwrap()
     }
 
     fn get<T: Any + Sync + Send>(&self) -> Option<&T> {
@@ -621,8 +332,29 @@ pub trait NodeImmutable<V: FromAnyValue + Send + Sync>: Sized {
 }
 
 pub trait NodeMutable<V: FromAnyValue + Send + Sync>: Sized + NodeImmutable<V> {
-    fn get_mut<T: Any + Sync + Send>(&mut self) -> Option<&mut T>;
-    fn insert<T: Any + Sync + Send>(&mut self, value: T);
+    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 insert_before(&mut self, old: NodeId) {
+        let id = self.id();
+        self.real_dom_mut().tree.insert_before(old, id);
+    }
+    fn add_event_listener(&mut self, event: &str);
+    fn remove_event_listener(&mut self, event: &str);
 }
 
 #[derive(Clone, Copy)]
@@ -647,6 +379,16 @@ pub struct NodeMut<'a, V: FromAnyValue + Send + Sync = ()> {
     dirty: NodeMask,
 }
 
+impl<'a, V: FromAnyValue + Send + Sync> NodeMut<'a, V> {
+    pub fn new(id: NodeId, dom: &'a mut RealDom<V>) -> Self {
+        Self {
+            id,
+            dom,
+            dirty: NodeMask::default(),
+        }
+    }
+}
+
 impl<'a, V: FromAnyValue + Send + Sync> NodeImmutable<V> for NodeMut<'a, V> {
     fn real_dom(&self) -> &RealDom<V> {
         self.dom
@@ -658,19 +400,78 @@ 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> {
+        self.dom
+    }
+
     fn get_mut<T: Any + Sync + Send>(&mut self) -> Option<&mut T> {
-        todo!("get_mut with mark as dirty")
+        // mark the node state as dirty
+        self.dom
+            .passes_updated
+            .entry(self.id)
+            .or_default()
+            .insert(TypeId::of::<T>());
+        self.dom.tree.get_mut(self.id)
+    }
+
+    fn insert<T: Any + Sync + Send>(&mut self, value: T) {
+        // mark the node state as dirty
+        self.dom
+            .passes_updated
+            .entry(self.id)
+            .or_default()
+            .insert(TypeId::of::<T>());
+        self.dom.tree.insert(self.id, value);
+    }
+
+    fn insert_after(&mut self, old: NodeId) {
+        let id = self.id();
+        if let Some(parent_id) = self.dom.tree.parent_id(old) {
+            self.dom.mark_child_changed(parent_id);
+            self.dom.mark_parent_added_or_removed(id);
+        }
+        self.dom.tree.insert_after(old, id);
     }
 
-    fn insert<T: Any + Sync + Send>(&mut self, _: T) {
-        todo!("insert with mark as dirty")
+    fn insert_before(&mut self, old: NodeId) {
+        let id = self.id();
+        if let Some(parent_id) = self.dom.tree.parent_id(old) {
+            self.dom.mark_child_changed(parent_id);
+            self.dom.mark_parent_added_or_removed(id);
+        }
+        self.dom.tree.insert_before(old, id);
+    }
+
+    fn add_event_listener(&mut self, event: &str) {
+        let id = self.id();
+        if let NodeTypeMut::Element(mut element) = self.node_type_mut() {
+            element.listeners_mut().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 NodeTypeMut::Element(mut element) = self.node_type_mut() {
+            element.listeners_mut().remove(event);
+        }
+        self.dom.nodes_listening.get_mut(event).unwrap().remove(&id);
     }
 }
 
 impl<'a, V: FromAnyValue + Send + Sync> NodeMut<'a, V> {
     pub fn node_type_mut(&mut self) -> NodeTypeMut<'_, V> {
         let Self { id, dom, dirty } = self;
-        let node_type = &mut dom.tree.get_mut::<NodeData<V>>(*id).unwrap().node_type;
+        let node_type = dom.tree.get_mut::<NodeType<V>>(*id).unwrap();
         match node_type {
             NodeType::Element(element) => NodeTypeMut::Element(ElementNodeMut { element, dirty }),
             NodeType::Text(text) => {
@@ -682,20 +483,15 @@ impl<'a, V: FromAnyValue + Send + Sync> NodeMut<'a, V> {
     }
 
     pub fn set_type(&mut self, new: NodeType<V>) {
-        self.dom
-            .tree
-            .get_mut::<NodeData<V>>(self.id)
-            .unwrap()
-            .node_type = new;
+        *self.dom.tree.get_mut::<NodeType<V>>(self.id).unwrap() = new;
         self.dirty = NodeMaskBuilder::ALL.build();
     }
 }
 
 impl<V: FromAnyValue + Send + Sync> Drop for NodeMut<'_, V> {
     fn drop(&mut self) {
-        let node_id = self.node_data().node_id;
         let mask = std::mem::take(&mut self.dirty);
-        self.dom.mark_dirty(node_id, mask);
+        self.dom.mark_dirty(self.id, mask);
     }
 }
 
@@ -780,6 +576,12 @@ pub struct NodeMutRaw<'a, V: FromAnyValue + Send + Sync = ()> {
     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
@@ -791,11 +593,32 @@ impl<'a, V: FromAnyValue + Send + Sync> NodeImmutable<V> for NodeMutRaw<'a, V> {
 }
 
 impl<'a, V: FromAnyValue + Send + Sync> NodeMutable<V> for NodeMutRaw<'a, V> {
-    fn get_mut<T: Any + Sync + Send>(&mut self) -> Option<&mut T> {
-        self.dom.tree.get_mut::<T>(self.id)
+    fn real_dom_mut(&mut self) -> &mut RealDom<V> {
+        self.dom
     }
 
-    fn insert<T: Any + Sync + Send>(&mut self, value: T) {
-        self.dom.tree.insert(self.id, value);
+    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);
     }
 }

+ 1 - 13
packages/native-core/src/tree.rs

@@ -659,7 +659,7 @@ impl AnySlab {
     }
 }
 
-pub struct EntryBuilder<'a> {
+pub(crate) struct EntryBuilder<'a> {
     id: NodeId,
     inner: &'a mut AnySlab,
 }
@@ -671,18 +671,6 @@ impl EntryBuilder<'_> {
             .insert(self.id, value);
     }
 
-    pub fn get<T: Any + Sync + Send>(&self) -> Option<&T> {
-        self.inner.read_slab().get(self.id)
-    }
-
-    pub fn get_mut<T: Any + Sync + Send>(&mut self) -> Option<&mut T> {
-        self.inner.write_slab().get_mut(self.id)
-    }
-
-    pub fn remove(self) {
-        self.inner.remove(self.id);
-    }
-
     pub fn id(&self) -> NodeId {
         self.id
     }

+ 41 - 71
packages/native-core/src/utils/cursor.rs

@@ -1,6 +1,6 @@
 use std::{cmp::Ordering, ops::Range};
 
-use dioxus_html::input_data::keyboard_types::{Code, Key, Modifiers};
+use keyboard_types::{Code, Key, Modifiers};
 
 /// This contains the information about the text that is used by the cursor to handle navigation.
 pub trait Text {
@@ -221,26 +221,28 @@ impl Cursor {
     /// Handle moving the cursor with the given key.
     pub fn handle_input<T: Text + ?Sized>(
         &mut self,
-        data: &dioxus_html::KeyboardData,
+        code: &Code,
+        key: &Key,
+        modifiers: &Modifiers,
         text: &mut impl TextEditable<T>,
         max_text_length: usize,
     ) {
         use Code::*;
-        match data.code() {
+        match code {
             ArrowUp => {
                 self.move_cursor(
                     |c| c.up(text.as_ref()),
-                    data.modifiers().contains(Modifiers::SHIFT),
+                    modifiers.contains(Modifiers::SHIFT),
                 );
             }
             ArrowDown => {
                 self.move_cursor(
                     |c| c.down(text.as_ref()),
-                    data.modifiers().contains(Modifiers::SHIFT),
+                    modifiers.contains(Modifiers::SHIFT),
                 );
             }
             ArrowRight => {
-                if data.modifiers().contains(Modifiers::CONTROL) {
+                if modifiers.contains(Modifiers::CONTROL) {
                     self.move_cursor(
                         |c| {
                             let mut change = 1;
@@ -255,17 +257,17 @@ impl Cursor {
                             }
                             c.move_col(change as i32, text.as_ref());
                         },
-                        data.modifiers().contains(Modifiers::SHIFT),
+                        modifiers.contains(Modifiers::SHIFT),
                     );
                 } else {
                     self.move_cursor(
                         |c| c.right(text.as_ref()),
-                        data.modifiers().contains(Modifiers::SHIFT),
+                        modifiers.contains(Modifiers::SHIFT),
                     );
                 }
             }
             ArrowLeft => {
-                if data.modifiers().contains(Modifiers::CONTROL) {
+                if modifiers.contains(Modifiers::CONTROL) {
                     self.move_cursor(
                         |c| {
                             let mut change = -1;
@@ -279,23 +281,23 @@ impl Cursor {
                             }
                             c.move_col(change, text.as_ref());
                         },
-                        data.modifiers().contains(Modifiers::SHIFT),
+                        modifiers.contains(Modifiers::SHIFT),
                     );
                 } else {
                     self.move_cursor(
                         |c| c.left(text.as_ref()),
-                        data.modifiers().contains(Modifiers::SHIFT),
+                        modifiers.contains(Modifiers::SHIFT),
                     );
                 }
             }
             End => {
                 self.move_cursor(
                     |c| c.col = c.len_line(text.as_ref()),
-                    data.modifiers().contains(Modifiers::SHIFT),
+                    modifiers.contains(Modifiers::SHIFT),
                 );
             }
             Home => {
-                self.move_cursor(|c| c.col = 0, data.modifiers().contains(Modifiers::SHIFT));
+                self.move_cursor(|c| c.col = 0, modifiers.contains(Modifiers::SHIFT));
             }
             Backspace => {
                 self.start.realize_col(text.as_ref());
@@ -305,7 +307,7 @@ impl Cursor {
                 } else if start_idx > 0 {
                     self.start.left(text.as_ref());
                     text.delete_range(start_idx - 1..start_idx);
-                    if data.modifiers().contains(Modifiers::CONTROL) {
+                    if modifiers.contains(Modifiers::CONTROL) {
                         start_idx = self.start.idx(text.as_ref());
                         while start_idx > 0
                             && text
@@ -340,7 +342,7 @@ impl Cursor {
             }
             _ => {
                 self.start.realize_col(text.as_ref());
-                if let Key::Character(character) = data.key() {
+                if let Key::Character(character) = key {
                     if text.as_ref().length() + 1 - self.selection_len(text.as_ref())
                         <= max_text_length
                     {
@@ -460,13 +462,9 @@ fn cursor_input() {
 
     for _ in 0..5 {
         cursor.handle_input(
-            &dioxus_html::KeyboardData::new(
-                dioxus_html::input_data::keyboard_types::Key::ArrowRight,
-                dioxus_html::input_data::keyboard_types::Code::ArrowRight,
-                dioxus_html::input_data::keyboard_types::Location::Standard,
-                false,
-                Modifiers::empty(),
-            ),
+            &keyboard_types::Code::ArrowRight,
+            &keyboard_types::Key::ArrowRight,
+            &Modifiers::empty(),
             &mut text,
             10,
         );
@@ -474,13 +472,9 @@ fn cursor_input() {
 
     for _ in 0..5 {
         cursor.handle_input(
-            &dioxus_html::KeyboardData::new(
-                dioxus_html::input_data::keyboard_types::Key::Backspace,
-                dioxus_html::input_data::keyboard_types::Code::Backspace,
-                dioxus_html::input_data::keyboard_types::Location::Standard,
-                false,
-                Modifiers::empty(),
-            ),
+            &keyboard_types::Code::Backspace,
+            &keyboard_types::Key::Backspace,
+            &Modifiers::empty(),
             &mut text,
             10,
         );
@@ -491,61 +485,41 @@ fn cursor_input() {
     let goal_text = "hello world\nhi";
     let max_width = goal_text.len();
     cursor.handle_input(
-        &dioxus_html::KeyboardData::new(
-            dioxus_html::input_data::keyboard_types::Key::Character("h".to_string()),
-            dioxus_html::input_data::keyboard_types::Code::KeyH,
-            dioxus_html::input_data::keyboard_types::Location::Standard,
-            false,
-            Modifiers::empty(),
-        ),
+        &keyboard_types::Code::KeyH,
+        &keyboard_types::Key::Character("h".to_string()),
+        &Modifiers::empty(),
         &mut text,
         max_width,
     );
 
     cursor.handle_input(
-        &dioxus_html::KeyboardData::new(
-            dioxus_html::input_data::keyboard_types::Key::Character("e".to_string()),
-            dioxus_html::input_data::keyboard_types::Code::KeyE,
-            dioxus_html::input_data::keyboard_types::Location::Standard,
-            false,
-            Modifiers::empty(),
-        ),
+        &keyboard_types::Code::KeyE,
+        &keyboard_types::Key::Character("e".to_string()),
+        &Modifiers::empty(),
         &mut text,
         max_width,
     );
 
     cursor.handle_input(
-        &dioxus_html::KeyboardData::new(
-            dioxus_html::input_data::keyboard_types::Key::Character("l".to_string()),
-            dioxus_html::input_data::keyboard_types::Code::KeyL,
-            dioxus_html::input_data::keyboard_types::Location::Standard,
-            false,
-            Modifiers::empty(),
-        ),
+        &keyboard_types::Code::KeyL,
+        &keyboard_types::Key::Character("l".to_string()),
+        &Modifiers::empty(),
         &mut text,
         max_width,
     );
 
     cursor.handle_input(
-        &dioxus_html::KeyboardData::new(
-            dioxus_html::input_data::keyboard_types::Key::Character("l".to_string()),
-            dioxus_html::input_data::keyboard_types::Code::KeyL,
-            dioxus_html::input_data::keyboard_types::Location::Standard,
-            false,
-            Modifiers::empty(),
-        ),
+        &keyboard_types::Code::KeyL,
+        &keyboard_types::Key::Character("l".to_string()),
+        &Modifiers::empty(),
         &mut text,
         max_width,
     );
 
     cursor.handle_input(
-        &dioxus_html::KeyboardData::new(
-            dioxus_html::input_data::keyboard_types::Key::Character("o".to_string()),
-            dioxus_html::input_data::keyboard_types::Code::KeyO,
-            dioxus_html::input_data::keyboard_types::Location::Standard,
-            false,
-            Modifiers::empty(),
-        ),
+        &keyboard_types::Code::KeyO,
+        &keyboard_types::Key::Character("o".to_string()),
+        &Modifiers::empty(),
         &mut text,
         max_width,
     );
@@ -553,13 +527,9 @@ fn cursor_input() {
     // these should be ignored
     for _ in 0..10 {
         cursor.handle_input(
-            &dioxus_html::KeyboardData::new(
-                dioxus_html::input_data::keyboard_types::Key::Character("o".to_string()),
-                dioxus_html::input_data::keyboard_types::Code::KeyO,
-                dioxus_html::input_data::keyboard_types::Location::Standard,
-                false,
-                Modifiers::empty(),
-            ),
+            &keyboard_types::Code::KeyO,
+            &keyboard_types::Key::Character("o".to_string()),
+            &Modifiers::empty(),
             &mut text,
             max_width,
         );

+ 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;

+ 5 - 4
packages/native-core/src/utils/persistant_iterator.rs

@@ -13,6 +13,7 @@ pub enum ElementProduced {
     /// The iterator reached the end of the tree and looped back to the root
     Looped(NodeId),
 }
+
 impl ElementProduced {
     pub fn id(&self) -> NodeId {
         match self {
@@ -141,7 +142,7 @@ impl PersistantElementIter {
         } else {
             let (last, old_child_idx) = self.stack.last_mut().unwrap();
             let node = rdom.get(*last).unwrap();
-            match &node.node_data().node_type {
+            match node.node_type() {
                 NodeType::Element(ElementNode { .. }) => {
                     let children = node.child_ids().unwrap();
                     *old_child_idx = old_child_idx.map(|i| i + 1);
@@ -153,7 +154,7 @@ impl PersistantElementIter {
                     } else {
                         let id = children[child_idx];
                         if let NodeType::Element(ElementNode { .. }) =
-                            rdom.get(id).unwrap().node_data().node_type
+                            rdom.get(id).unwrap().node_type()
                         {
                             self.stack.push((id, NodePosition::AtNode));
                         }
@@ -178,7 +179,7 @@ impl PersistantElementIter {
             rdom: &RealDom<V>,
         ) -> NodeId {
             let node = rdom.get(new_node).unwrap();
-            match &node.node_data().node_type {
+            match node.node_type() {
                 NodeType::Element(ElementNode { .. }) => {
                     let children = node.child_ids().unwrap();
                     if children.is_empty() {
@@ -197,7 +198,7 @@ impl PersistantElementIter {
         } else {
             let (last, old_child_idx) = self.stack.last_mut().unwrap();
             let node = rdom.get(*last).unwrap();
-            match &node.node_data().node_type {
+            match node.node_type() {
                 NodeType::Element(ElementNode { .. }) => {
                     let children = node.child_ids().unwrap();
                     // if we have children, go to the next child

+ 620 - 0
packages/native-core/tests/passes.rs

@@ -0,0 +1,620 @@
+use dioxus::prelude::*;
+use dioxus_native_core::node::NodeType;
+use dioxus_native_core::prelude::*;
+use std::any::TypeId;
+use std::sync::{Arc, Mutex};
+
+fn create_blank_element() -> NodeType {
+    NodeType::Element(ElementNode {
+        tag: "div".to_owned(),
+        namespace: None,
+        attributes: HashMap::new(),
+        listeners: HashMap::new(),
+    })
+}
+
+#[test]
+fn node_pass() {
+    #[derive(Debug, Default, Clone, PartialEq)]
+    struct Number(i32);
+
+    impl Pass for Number {
+        type ChildDependencies = ();
+        type NodeDependencies = ();
+        type ParentDependencies = ();
+        const NODE_MASK: NodeMaskBuilder = NodeMaskBuilder::new();
+
+        fn pass<'a>(
+            &mut self,
+            node_view: NodeView,
+            node: <Self::NodeDependencies as Dependancy>::ElementBorrowed<'a>,
+            parent: Option<<Self::ParentDependencies as Dependancy>::ElementBorrowed<'a>>,
+            children: Option<Vec<<Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>>,
+            context: &SendAnyMap,
+        ) -> bool {
+            self.0 += 1;
+            true
+        }
+
+        fn create<'a>(
+            node_view: NodeView<()>,
+            node: <Self::NodeDependencies as Dependancy>::ElementBorrowed<'a>,
+            parent: Option<<Self::ParentDependencies as Dependancy>::ElementBorrowed<'a>>,
+            children: Option<Vec<<Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>>,
+            context: &SendAnyMap,
+        ) -> Self {
+            let mut myself = Self::default();
+            myself.pass(node_view, node, parent, children, context);
+            myself
+        }
+    }
+
+    let mut tree: RealDom = RealDom::new(Box::new([Number::to_type_erased()]));
+    tree.update_state(SendAnyMap::new(), false);
+
+    assert_eq!(tree.get(tree.root_id()).unwrap().get(), Some(&Number(1)));
+
+    // mark the node as dirty
+    tree.get_mut(tree.root_id()).unwrap().get_mut::<Number>();
+
+    tree.update_state(SendAnyMap::new(), false);
+    assert_eq!(tree.get(tree.root_id()).unwrap().get(), Some(&Number(2)));
+}
+
+#[test]
+fn dependant_node_pass() {
+    #[derive(Debug, Default, Clone, PartialEq)]
+    struct AddNumber(i32);
+
+    impl Pass for AddNumber {
+        type ChildDependencies = ();
+        type NodeDependencies = (SubtractNumber,);
+        type ParentDependencies = ();
+        const NODE_MASK: NodeMaskBuilder = NodeMaskBuilder::new();
+
+        fn pass<'a>(
+            &mut self,
+            node_view: NodeView,
+            node: <Self::NodeDependencies as Dependancy>::ElementBorrowed<'a>,
+            parent: Option<<Self::ParentDependencies as Dependancy>::ElementBorrowed<'a>>,
+            children: Option<Vec<<Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>>,
+            context: &SendAnyMap,
+        ) -> bool {
+            self.0 += 1;
+            true
+        }
+
+        fn create<'a>(
+            node_view: NodeView<()>,
+            node: <Self::NodeDependencies as Dependancy>::ElementBorrowed<'a>,
+            parent: Option<<Self::ParentDependencies as Dependancy>::ElementBorrowed<'a>>,
+            children: Option<Vec<<Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>>,
+            context: &SendAnyMap,
+        ) -> Self {
+            let mut myself = Self::default();
+            myself.pass(node_view, node, parent, children, context);
+            myself
+        }
+    }
+
+    #[derive(Debug, Default, Clone, PartialEq)]
+    struct SubtractNumber(i32);
+
+    impl Pass for SubtractNumber {
+        type ChildDependencies = ();
+        type NodeDependencies = ();
+        type ParentDependencies = ();
+        const NODE_MASK: NodeMaskBuilder = NodeMaskBuilder::new();
+
+        fn pass<'a>(
+            &mut self,
+            node_view: NodeView,
+            node: <Self::NodeDependencies as Dependancy>::ElementBorrowed<'a>,
+            parent: Option<<Self::ParentDependencies as Dependancy>::ElementBorrowed<'a>>,
+            children: Option<Vec<<Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>>,
+            context: &SendAnyMap,
+        ) -> bool {
+            self.0 -= 1;
+            true
+        }
+
+        fn create<'a>(
+            node_view: NodeView<()>,
+            node: <Self::NodeDependencies as Dependancy>::ElementBorrowed<'a>,
+            parent: Option<<Self::ParentDependencies as Dependancy>::ElementBorrowed<'a>>,
+            children: Option<Vec<<Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>>,
+            context: &SendAnyMap,
+        ) -> Self {
+            let mut myself = Self::default();
+            myself.pass(node_view, node, parent, children, context);
+            myself
+        }
+    }
+
+    let mut tree: RealDom = RealDom::new(Box::new([
+        AddNumber::to_type_erased(),
+        SubtractNumber::to_type_erased(),
+    ]));
+    tree.update_state(SendAnyMap::new(), false);
+
+    let root = tree.get(tree.root_id()).unwrap();
+    assert_eq!(root.get(), Some(&AddNumber(1)));
+    assert_eq!(root.get(), Some(&SubtractNumber(-1)));
+
+    // mark the subtract state as dirty, it should update the add state
+    tree.get_mut(tree.root_id())
+        .unwrap()
+        .get_mut::<SubtractNumber>();
+
+    tree.update_state(SendAnyMap::new(), false);
+    let root = tree.get(tree.root_id()).unwrap();
+    assert_eq!(root.get(), Some(&AddNumber(2)));
+    assert_eq!(root.get(), Some(&SubtractNumber(-2)));
+
+    // mark the add state as dirty, it should ~not~ update the subtract state
+    tree.get_mut(tree.root_id()).unwrap().get_mut::<AddNumber>();
+
+    tree.update_state(SendAnyMap::new(), false);
+    let root = tree.get(tree.root_id()).unwrap();
+    assert_eq!(root.get(), Some(&AddNumber(3)));
+    assert_eq!(root.get(), Some(&SubtractNumber(-2)));
+}
+
+#[test]
+fn independant_node_pass() {
+    #[derive(Debug, Default, Clone, PartialEq)]
+    struct AddNumber(i32);
+
+    impl Pass for AddNumber {
+        type ChildDependencies = ();
+        type NodeDependencies = ();
+        type ParentDependencies = ();
+
+        const NODE_MASK: NodeMaskBuilder = NodeMaskBuilder::new();
+
+        fn pass<'a>(
+            &mut self,
+            node_view: NodeView,
+            node: <Self::NodeDependencies as Dependancy>::ElementBorrowed<'a>,
+            parent: Option<<Self::ParentDependencies as Dependancy>::ElementBorrowed<'a>>,
+            children: Option<Vec<<Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>>,
+            context: &SendAnyMap,
+        ) -> bool {
+            self.0 += 1;
+            true
+        }
+
+        fn create<'a>(
+            node_view: NodeView<()>,
+            node: <Self::NodeDependencies as Dependancy>::ElementBorrowed<'a>,
+            parent: Option<<Self::ParentDependencies as Dependancy>::ElementBorrowed<'a>>,
+            children: Option<Vec<<Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>>,
+            context: &SendAnyMap,
+        ) -> Self {
+            let mut myself = Self::default();
+            myself.pass(node_view, node, parent, children, context);
+            myself
+        }
+    }
+
+    #[derive(Debug, Default, Clone, PartialEq)]
+    struct SubtractNumber(i32);
+
+    impl Pass for SubtractNumber {
+        type ChildDependencies = ();
+        type NodeDependencies = ();
+        type ParentDependencies = ();
+
+        const NODE_MASK: NodeMaskBuilder = NodeMaskBuilder::new();
+
+        fn pass<'a>(
+            &mut self,
+            node_view: NodeView,
+            node: <Self::NodeDependencies as Dependancy>::ElementBorrowed<'a>,
+            parent: Option<<Self::ParentDependencies as Dependancy>::ElementBorrowed<'a>>,
+            children: Option<Vec<<Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>>,
+            context: &SendAnyMap,
+        ) -> bool {
+            self.0 -= 1;
+            true
+        }
+
+        fn create<'a>(
+            node_view: NodeView<()>,
+            node: <Self::NodeDependencies as Dependancy>::ElementBorrowed<'a>,
+            parent: Option<<Self::ParentDependencies as Dependancy>::ElementBorrowed<'a>>,
+            children: Option<Vec<<Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>>,
+            context: &SendAnyMap,
+        ) -> Self {
+            let mut myself = Self::default();
+            myself.pass(node_view, node, parent, children, context);
+            myself
+        }
+    }
+
+    let mut tree: RealDom = RealDom::new(Box::new([
+        AddNumber::to_type_erased(),
+        SubtractNumber::to_type_erased(),
+    ]));
+    tree.update_state(SendAnyMap::new(), false);
+
+    let root = tree.get(tree.root_id()).unwrap();
+    assert_eq!(root.get(), Some(&AddNumber(1)));
+    assert_eq!(root.get(), Some(&SubtractNumber(-1)));
+
+    // mark the subtract state as dirty, it should ~not~ update the add state
+    tree.get_mut(tree.root_id())
+        .unwrap()
+        .get_mut::<SubtractNumber>();
+
+    tree.update_state(SendAnyMap::new(), false);
+
+    let root = tree.get(tree.root_id()).unwrap();
+    assert_eq!(root.get(), Some(&AddNumber(1)));
+    assert_eq!(root.get(), Some(&SubtractNumber(-2)));
+
+    // mark the add state as dirty, it should ~not~ update the subtract state
+    tree.get_mut(tree.root_id()).unwrap().get_mut::<AddNumber>();
+
+    tree.update_state(SendAnyMap::new(), false);
+
+    let root = tree.get(tree.root_id()).unwrap();
+    assert_eq!(root.get(), Some(&AddNumber(2)));
+    assert_eq!(root.get(), Some(&SubtractNumber(-2)));
+}
+
+#[test]
+fn down_pass() {
+    #[derive(Debug, Clone, PartialEq)]
+    struct AddNumber(i32);
+
+    impl Default for AddNumber {
+        fn default() -> Self {
+            Self(1)
+        }
+    }
+
+    impl Pass for AddNumber {
+        type ChildDependencies = ();
+        type NodeDependencies = ();
+        type ParentDependencies = (AddNumber,);
+
+        const NODE_MASK: NodeMaskBuilder = NodeMaskBuilder::new();
+
+        fn pass<'a>(
+            &mut self,
+            node_view: NodeView,
+            node: <Self::NodeDependencies as Dependancy>::ElementBorrowed<'a>,
+            parent: Option<<Self::ParentDependencies as Dependancy>::ElementBorrowed<'a>>,
+            children: Option<Vec<<Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>>,
+            context: &SendAnyMap,
+        ) -> bool {
+            if let Some((parent,)) = parent {
+                *self.0 += *parent.0;
+            }
+            true
+        }
+    }
+
+    let mut tree: RealDom = RealDom::new(Box::new([AddNumber::to_type_erased()]));
+    let parent = tree.root_id();
+    let child1 = tree.create_node(create_blank_element(), true);
+    tree.add_child(parent, child1);
+    let grandchild1 = tree.create_node(create_blank_element(), true);
+    tree.add_child(child1, grandchild1);
+    let child2 = tree.create_node(create_blank_element(), true);
+    tree.add_child(parent, child2);
+    let grandchild2 = tree.create_node(create_blank_element(), true);
+    tree.add_child(child2, grandchild2);
+
+    tree.dirty_nodes
+        .insert(TypeId::of::<AddNumber>(), NodeId(0));
+    tree.update_state(SendAnyMap::new(), false);
+
+    assert_eq!(tree.get(tree.root_id()).unwrap().state.add_number.0, 1);
+    assert_eq!(tree.get(child1).unwrap().state.add_number.0, 2);
+    assert_eq!(tree.get(grandchild1).unwrap().state.add_number.0, 3);
+    assert_eq!(tree.get(child2).unwrap().state.add_number.0, 2);
+    assert_eq!(tree.get(grandchild2).unwrap().state.add_number.0, 3);
+}
+
+// #[test]
+// fn dependant_down_pass() {
+//     // 0
+//     let mut tree = Tree::new(1);
+//     let parent = tree.root_id();
+//     // 1
+//     let child1 = tree.create_node(1);
+//     tree.add_child(parent, child1);
+//     // 2
+//     let grandchild1 = tree.create_node(1);
+//     tree.add_child(child1, grandchild1);
+//     // 3
+//     let child2 = tree.create_node(1);
+//     tree.add_child(parent, child2);
+//     // 4
+//     let grandchild2 = tree.create_node(1);
+//     tree.add_child(child2, grandchild2);
+
+//     struct AddPass;
+//     impl Pass for AddPass {
+//         fn pass_id(&self) -> PassId {
+//             PassId(0)
+//         }
+
+//         fn dependancies(&self) -> &'static [PassId] {
+//             &[PassId(1)]
+//         }
+
+//         fn dependants(&self) -> &'static [PassId] {
+//             &[]
+//         }
+
+//         fn mask(&self) -> MemberMask {
+//             MemberMask(0)
+//         }
+//     }
+//     impl DownwardPass<i32> for AddPass {
+//         fn pass(&self, node: &mut i32, parent: Option<&mut i32>, _: &SendAnyMap) -> PassReturn {
+//             if let Some(parent) = parent {
+//                 *node += *parent;
+//             } else {
+//             }
+//             PassReturn {
+//                 progress: true,
+//                 mark_dirty: true,
+//             }
+//         }
+//     }
+
+//     struct SubtractPass;
+//     impl Pass for SubtractPass {
+//         fn pass_id(&self) -> PassId {
+//             PassId(1)
+//         }
+
+//         fn dependancies(&self) -> &'static [PassId] {
+//             &[]
+//         }
+
+//         fn dependants(&self) -> &'static [PassId] {
+//             &[PassId(0)]
+//         }
+
+//         fn mask(&self) -> MemberMask {
+//             MemberMask(0)
+//         }
+//     }
+//     impl DownwardPass<i32> for SubtractPass {
+//         fn pass(&self, node: &mut i32, parent: Option<&mut i32>, _: &SendAnyMap) -> PassReturn {
+//             if let Some(parent) = parent {
+//                 *node -= *parent;
+//             } else {
+//             }
+//             PassReturn {
+//                 progress: true,
+//                 mark_dirty: true,
+//             }
+//         }
+//     }
+
+//     let add_pass = AnyPass::Downward(&AddPass);
+//     let subtract_pass = AnyPass::Downward(&SubtractPass);
+//     let passes = vec![&add_pass, &subtract_pass];
+//     let dirty_nodes: DirtyNodeStates = DirtyNodeStates::default();
+//     dirty_nodes.insert(PassId(1), tree.root_id());
+//     resolve_passes(&mut tree, dirty_nodes, passes, SendAnyMap::new());
+
+//     // Tree before:
+//     // 1=\
+//     //   1=\
+//     //     1
+//     //   1=\
+//     //     1
+//     // Tree after subtract:
+//     // 1=\
+//     //   0=\
+//     //     1
+//     //   0=\
+//     //     1
+//     // Tree after add:
+//     // 1=\
+//     //   1=\
+//     //     2
+//     //   1=\
+//     //     2
+//     assert_eq!(tree.get(tree.root_id()).unwrap(), &1);
+//     assert_eq!(tree.get(child1).unwrap(), &1);
+//     assert_eq!(tree.get(grandchild1).unwrap(), &2);
+//     assert_eq!(tree.get(child2).unwrap(), &1);
+//     assert_eq!(tree.get(grandchild2).unwrap(), &2);
+// }
+
+// #[test]
+// fn up_pass() {
+//     // Tree before:
+//     // 0=\
+//     //   0=\
+//     //     1
+//     //   0=\
+//     //     1
+//     // Tree after:
+//     // 2=\
+//     //   1=\
+//     //     1
+//     //   1=\
+//     //     1
+//     let mut tree = Tree::new(0);
+//     let parent = tree.root_id();
+//     let child1 = tree.create_node(0);
+//     tree.add_child(parent, child1);
+//     let grandchild1 = tree.create_node(1);
+//     tree.add_child(child1, grandchild1);
+//     let child2 = tree.create_node(0);
+//     tree.add_child(parent, child2);
+//     let grandchild2 = tree.create_node(1);
+//     tree.add_child(child2, grandchild2);
+
+//     struct AddPass;
+//     impl Pass for AddPass {
+//         fn pass_id(&self) -> PassId {
+//             PassId(0)
+//         }
+
+//         fn dependancies(&self) -> &'static [PassId] {
+//             &[]
+//         }
+
+//         fn dependants(&self) -> &'static [PassId] {
+//             &[]
+//         }
+
+//         fn mask(&self) -> MemberMask {
+//             MemberMask(0)
+//         }
+//     }
+//     impl UpwardPass<i32> for AddPass {
+//         fn pass<'a>(
+//             &self,
+//             node: &mut i32,
+//             children: &mut dyn Iterator<Item = &'a mut i32>,
+//             _: &SendAnyMap,
+//         ) -> PassReturn {
+//             *node += children.map(|i| *i).sum::<i32>();
+//             PassReturn {
+//                 progress: true,
+//                 mark_dirty: true,
+//             }
+//         }
+//     }
+
+//     let add_pass = AnyPass::Upward(&AddPass);
+//     let passes = vec![&add_pass];
+//     let dirty_nodes: DirtyNodeStates = DirtyNodeStates::default();
+//     dirty_nodes.insert(PassId(0), grandchild1);
+//     dirty_nodes.insert(PassId(0), grandchild2);
+//     resolve_passes(&mut tree, dirty_nodes, passes, SendAnyMap::new());
+
+//     assert_eq!(tree.get(tree.root_id()).unwrap(), &2);
+//     assert_eq!(tree.get(child1).unwrap(), &1);
+//     assert_eq!(tree.get(grandchild1).unwrap(), &1);
+//     assert_eq!(tree.get(child2).unwrap(), &1);
+//     assert_eq!(tree.get(grandchild2).unwrap(), &1);
+// }
+
+// #[test]
+// fn dependant_up_pass() {
+//     // 0
+//     let mut tree = Tree::new(0);
+//     let parent = tree.root_id();
+//     // 1
+//     let child1 = tree.create_node(0);
+//     tree.add_child(parent, child1);
+//     // 2
+//     let grandchild1 = tree.create_node(1);
+//     tree.add_child(child1, grandchild1);
+//     // 3
+//     let child2 = tree.create_node(0);
+//     tree.add_child(parent, child2);
+//     // 4
+//     let grandchild2 = tree.create_node(1);
+//     tree.add_child(child2, grandchild2);
+
+//     struct AddPass;
+//     impl Pass for AddPass {
+//         fn pass_id(&self) -> PassId {
+//             PassId(0)
+//         }
+
+//         fn dependancies(&self) -> &'static [PassId] {
+//             &[PassId(1)]
+//         }
+
+//         fn dependants(&self) -> &'static [PassId] {
+//             &[]
+//         }
+
+//         fn mask(&self) -> MemberMask {
+//             MemberMask(0)
+//         }
+//     }
+//     impl UpwardPass<i32> for AddPass {
+//         fn pass<'a>(
+//             &self,
+//             node: &mut i32,
+//             children: &mut dyn Iterator<Item = &'a mut i32>,
+//             _: &SendAnyMap,
+//         ) -> PassReturn {
+//             *node += children.map(|i| *i).sum::<i32>();
+//             PassReturn {
+//                 progress: true,
+//                 mark_dirty: true,
+//             }
+//         }
+//     }
+
+//     struct SubtractPass;
+//     impl Pass for SubtractPass {
+//         fn pass_id(&self) -> PassId {
+//             PassId(1)
+//         }
+
+//         fn dependancies(&self) -> &'static [PassId] {
+//             &[]
+//         }
+
+//         fn dependants(&self) -> &'static [PassId] {
+//             &[PassId(0)]
+//         }
+
+//         fn mask(&self) -> MemberMask {
+//             MemberMask(0)
+//         }
+//     }
+//     impl UpwardPass<i32> for SubtractPass {
+//         fn pass<'a>(
+//             &self,
+//             node: &mut i32,
+//             children: &mut dyn Iterator<Item = &'a mut i32>,
+//             _: &SendAnyMap,
+//         ) -> PassReturn {
+//             *node -= children.map(|i| *i).sum::<i32>();
+//             PassReturn {
+//                 progress: true,
+//                 mark_dirty: true,
+//             }
+//         }
+//     }
+
+//     let add_pass = AnyPass::Upward(&AddPass);
+//     let subtract_pass = AnyPass::Upward(&SubtractPass);
+//     let passes = vec![&add_pass, &subtract_pass];
+//     let dirty_nodes: DirtyNodeStates = DirtyNodeStates::default();
+//     dirty_nodes.insert(PassId(1), grandchild1);
+//     dirty_nodes.insert(PassId(1), grandchild2);
+//     resolve_passes(&mut tree, dirty_nodes, passes, SendAnyMap::new());
+
+//     // Tree before:
+//     // 0=\
+//     //   0=\
+//     //     1
+//     //   0=\
+//     //     1
+//     // Tree after subtract:
+//     // 2=\
+//     //   -1=\
+//     //      1
+//     //   -1=\
+//     //      1
+//     // Tree after add:
+//     // 2=\
+//     //   0=\
+//     //     1
+//     //   0=\
+//     //     1
+//     assert_eq!(tree.get(tree.root_id()).unwrap(), &2);
+//     assert_eq!(tree.get(child1).unwrap(), &0);
+//     assert_eq!(tree.get(grandchild1).unwrap(), &1);
+//     assert_eq!(tree.get(child2).unwrap(), &0);
+//     assert_eq!(tree.get(grandchild2).unwrap(), &1);
+// }