Jelajahi Sumber

work on integrating new pass system

Evan Almloff 2 tahun lalu
induk
melakukan
9e971fbe11

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

@@ -14,8 +14,6 @@ pub mod state;
 pub mod tree;
 pub mod utils;
 
-/// A id for a node that lives in the real dom.
-pub type RealNodeId = NodeId;
 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 anymap::any::Any + Send + Sync + 'static>;
@@ -25,11 +23,11 @@ pub type SendAnyMap = anymap::Map<dyn anymap::any::Any + Send + Sync + 'static>;
 #[doc(hidden)]
 pub struct HeightOrdering {
     pub height: u16,
-    pub id: RealNodeId,
+    pub id: NodeId,
 }
 
 impl HeightOrdering {
-    pub fn new(height: u16, id: RealNodeId) -> Self {
+    pub fn new(height: u16, id: NodeId) -> Self {
         HeightOrdering { height, id }
     }
 }

+ 11 - 10
packages/native-core/src/node.rs

@@ -21,23 +21,24 @@ pub struct NodeData {
     pub node_type: NodeType,
 }
 
+#[derive(Debug, Clone)]
+pub struct ElementNode {
+    pub tag: String,
+    pub namespace: Option<String>,
+    pub attributes: FxHashMap<OwnedAttributeDiscription, OwnedAttributeValue>,
+    pub listeners: FxHashSet<String>,
+}
+
 /// A type of node with data specific to the node type. The types are a subset of the [VNode] types.
 #[derive(Debug, Clone)]
 pub enum NodeType {
-    Text {
-        text: String,
-    },
-    Element {
-        tag: String,
-        namespace: Option<String>,
-        attributes: FxHashMap<OwnedAttributeDiscription, OwnedAttributeValue>,
-        listeners: FxHashSet<String>,
-    },
+    Text(String),
+    Element(ElementNode),
     Placeholder,
 }
 
 impl<S: State> Node<S> {
-    pub(crate) fn new(node_type: NodeType) -> Self {
+    pub fn new(node_type: NodeType) -> Self {
         Node {
             state: S::default(),
             node_data: NodeData {

+ 57 - 8
packages/native-core/src/node_ref.rs

@@ -1,9 +1,9 @@
 use dioxus_core::ElementId;
 
 use crate::{
-    node::{NodeData, NodeType, OwnedAttributeView},
+    node::{ElementNode, NodeData, NodeType, OwnedAttributeView},
     state::union_ordered_iter,
-    RealNodeId,
+    NodeId,
 };
 
 /// A view into a [VNode] with limited access.
@@ -28,7 +28,7 @@ impl<'a> NodeView<'a> {
     }
 
     /// Get the node id of the node
-    pub fn node_id(&self) -> RealNodeId {
+    pub fn node_id(&self) -> NodeId {
         self.inner.node_id
     }
 
@@ -37,7 +37,7 @@ impl<'a> NodeView<'a> {
         self.mask
             .tag
             .then_some(match &self.inner.node_type {
-                NodeType::Element { tag, .. } => Some(&**tag),
+                NodeType::Element(ElementNode { tag, .. }) => Some(&**tag),
                 _ => None,
             })
             .flatten()
@@ -48,7 +48,7 @@ impl<'a> NodeView<'a> {
         self.mask
             .namespace
             .then_some(match &self.inner.node_type {
-                NodeType::Element { namespace, .. } => namespace.as_deref(),
+                NodeType::Element(ElementNode { namespace, .. }) => namespace.as_deref(),
                 _ => None,
             })
             .flatten()
@@ -57,7 +57,7 @@ impl<'a> NodeView<'a> {
     /// Get any attributes that are enabled in the mask
     pub fn attributes<'b>(&'b self) -> Option<impl Iterator<Item = OwnedAttributeView<'a>> + 'b> {
         match &self.inner.node_type {
-            NodeType::Element { attributes, .. } => Some(
+            NodeType::Element(ElementNode { attributes, .. }) => Some(
                 attributes
                     .iter()
                     .filter(move |(attr, _)| self.mask.attritutes.contains_attribute(&attr.name))
@@ -75,7 +75,7 @@ impl<'a> NodeView<'a> {
         self.mask
             .text
             .then_some(match &self.inner.node_type {
-                NodeType::Text { text } => Some(&**text),
+                NodeType::Text(text) => Some(&**text),
                 _ => None,
             })
             .flatten()
@@ -85,7 +85,9 @@ impl<'a> NodeView<'a> {
     pub fn listeners(&self) -> Option<impl Iterator<Item = &'a str> + '_> {
         if self.mask.listeners {
             match &self.inner.node_type {
-                NodeType::Element { listeners, .. } => Some(listeners.iter().map(|l| &**l)),
+                NodeType::Element(ElementNode { listeners, .. }) => {
+                    Some(listeners.iter().map(|l| &**l))
+                }
                 _ => None,
             }
         } else {
@@ -238,6 +240,28 @@ impl NodeMask {
         .with_element()
         .with_listeners();
 
+    pub fn from_node(node: &NodeType) -> Self {
+        match node {
+            NodeType::Text { .. } => Self::new().with_text(),
+            NodeType::Element(ElementNode {
+                tag: _,
+                namespace: _,
+                attributes,
+                listeners,
+            }) => {
+                let mut mask = Self::new_with_attrs(AttributeMask::Dynamic(
+                    attributes.keys().map(|key| key.name.clone()).collect(),
+                ))
+                .with_element();
+                if !listeners.is_empty() {
+                    mask = mask.with_listeners();
+                }
+                mask
+            }
+            NodeType::Placeholder => Self::new().with_element(),
+        }
+    }
+
     /// Check if two masks overlap
     pub fn overlaps(&self, other: &Self) -> bool {
         (self.tag && other.tag)
@@ -280,12 +304,22 @@ impl NodeMask {
         self
     }
 
+    /// Set the mask to view the tag
+    pub fn set_tag(&mut self) {
+        self.tag = true;
+    }
+
     /// Allow the mask to view the namespace
     pub const fn with_namespace(mut self) -> Self {
         self.namespace = true;
         self
     }
 
+    /// Set the mask to view the namespace
+    pub fn set_namespace(&mut self) {
+        self.namespace = true;
+    }
+
     /// Allow the mask to view the namespace and tag
     pub const fn with_element(self) -> Self {
         self.with_namespace().with_tag()
@@ -297,9 +331,24 @@ impl NodeMask {
         self
     }
 
+    /// Set the mask to view the text
+    pub fn set_text(&mut self) {
+        self.text = true;
+    }
+
     /// Allow the mask to view the listeners
     pub const fn with_listeners(mut self) -> Self {
         self.listeners = true;
         self
     }
+
+    /// Set the mask to view the listeners
+    pub fn set_listeners(&mut self) {
+        self.listeners = true;
+    }
+
+    /// Allow the mask to view the given attributes
+    pub fn add_attributes(&mut self, attributes: AttributeMask) {
+        self.attritutes = self.attritutes.union(&attributes);
+    }
 }

+ 661 - 547
packages/native-core/src/passes.rs

@@ -1,16 +1,14 @@
-use anymap::any;
 use anymap::AnyMap;
 use rustc_hash::FxHashMap;
 use rustc_hash::FxHashSet;
 use std::any::{Any, TypeId};
 use std::collections::BTreeMap;
-use std::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign};
-use std::sync::atomic::{AtomicU64, Ordering};
 use std::sync::Arc;
 
 use crate::node::Node;
 use crate::node_ref::NodeView;
 use crate::state::State;
+use crate::tree::TreeViewMut;
 use crate::tree::{Tree, TreeView};
 use crate::{FxDashMap, FxDashSet, SendAnyMap};
 use crate::{NodeId, NodeMask};
@@ -70,9 +68,6 @@ pub trait Pass: Any {
     {
         TypeErasedPass {
             this_type_id: TypeId::of::<Self>(),
-            parent_type_ids: Self::parent_type_ids().into_iter().collect(),
-            child_type_ids: Self::child_type_ids().into_iter().collect(),
-            node_type_ids: Self::node_type_ids().into_iter().collect(),
             combined_dependancy_type_ids: Self::all_dependanices().into_iter().collect(),
             dependants: FxHashSet::default(),
             mask: Self::MASK,
@@ -155,10 +150,7 @@ pub trait Pass: Any {
 
 pub struct TypeErasedPass<T: AnyMapLike + State> {
     pub(crate) this_type_id: TypeId,
-    parent_type_ids: FxHashSet<TypeId>,
-    child_type_ids: FxHashSet<TypeId>,
-    node_type_ids: FxHashSet<TypeId>,
-    combined_dependancy_type_ids: FxHashSet<TypeId>,
+    pub(crate) combined_dependancy_type_ids: FxHashSet<TypeId>,
     pub(crate) dependants: FxHashSet<TypeId>,
     pub(crate) mask: NodeMask,
     pass: PassCallback<T>,
@@ -392,7 +384,7 @@ impl DirtyNodeStates {
 pub fn resolve_passes<T: AnyMapLike + State + Send>(
     tree: &mut Tree<Node<T>>,
     dirty_nodes: DirtyNodeStates,
-    mut passes: &[TypeErasedPass<T>],
+    passes: &[TypeErasedPass<T>],
     ctx: SendAnyMap,
 ) -> FxDashSet<NodeId> {
     let dirty_states = Arc::new(dirty_nodes);
@@ -446,539 +438,661 @@ pub fn resolve_passes<T: AnyMapLike + State + Send>(
     std::sync::Arc::try_unwrap(nodes_updated).unwrap()
 }
 
-#[test]
-fn node_pass() {
-    use crate::tree::{Tree, TreeLike};
-    let mut tree = Tree::new(0);
-
-    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 NodePass<i32> for AddPass {
-        fn pass(&self, node: &mut i32, _: &SendAnyMap) -> bool {
-            *node += 1;
-            true
-        }
-    }
-
-    let add_pass = AnyPass::Node(&AddPass);
-    let passes = vec![&add_pass];
-    let dirty_nodes: DirtyNodeStates = DirtyNodeStates::default();
-    dirty_nodes.insert(PassId(0), tree.root());
-    resolve_passes(&mut tree, dirty_nodes, passes, SendAnyMap::new());
-
-    assert_eq!(tree.get(tree.root()).unwrap(), &1);
-}
-
-#[test]
-fn dependant_node_pass() {
-    use crate::tree::{Tree, TreeLike};
-    let mut tree = Tree::new(0);
-
-    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 NodePass<i32> for AddPass {
-        fn pass(&self, node: &mut i32, _: &SendAnyMap) -> bool {
-            *node += 1;
-            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 NodePass<i32> for SubtractPass {
-        fn pass(&self, node: &mut i32, _: &SendAnyMap) -> bool {
-            *node -= 1;
-            true
-        }
-    }
-
-    let add_pass = AnyPass::Node(&AddPass);
-    let subtract_pass = AnyPass::Node(&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());
-
-    assert_eq!(*tree.get(tree.root()).unwrap(), 0);
-}
-
-#[test]
-fn independant_node_pass() {
-    use crate::tree::{Tree, TreeLike};
-    let mut tree = Tree::new((0, 0));
-
-    struct AddPass1;
-    impl Pass for AddPass1 {
-        fn pass_id(&self) -> PassId {
-            PassId(0)
-        }
-
-        fn dependancies(&self) -> &'static [PassId] {
-            &[]
-        }
-
-        fn dependants(&self) -> &'static [PassId] {
-            &[]
-        }
-
-        fn mask(&self) -> MemberMask {
-            MemberMask(0)
-        }
-    }
-
-    impl NodePass<(i32, i32)> for AddPass1 {
-        fn pass(&self, node: &mut (i32, i32), _: &SendAnyMap) -> bool {
-            node.0 += 1;
-            true
-        }
-    }
-
-    struct AddPass2;
-    impl Pass for AddPass2 {
-        fn pass_id(&self) -> PassId {
-            PassId(1)
-        }
-
-        fn dependancies(&self) -> &'static [PassId] {
-            &[]
-        }
-
-        fn dependants(&self) -> &'static [PassId] {
-            &[]
-        }
-
-        fn mask(&self) -> MemberMask {
-            MemberMask(1)
-        }
-    }
-
-    impl NodePass<(i32, i32)> for AddPass2 {
-        fn pass(&self, node: &mut (i32, i32), _: &SendAnyMap) -> bool {
-            node.1 += 1;
-            true
-        }
-    }
-
-    let add_pass1 = AnyPass::Node(&AddPass1);
-    let add_pass2 = AnyPass::Node(&AddPass2);
-    let passes = vec![&add_pass1, &add_pass2];
-    let dirty_nodes: DirtyNodeStates = DirtyNodeStates::default();
-    dirty_nodes.insert(PassId(0), tree.root());
-    dirty_nodes.insert(PassId(1), tree.root());
-    resolve_passes(&mut tree, dirty_nodes, passes, SendAnyMap::new());
-
-    assert_eq!(tree.get(tree.root()).unwrap(), &(1, 1));
-}
-
-#[test]
-fn down_pass() {
-    use crate::tree::{Tree, TreeLike};
-    let mut tree = Tree::new(1);
-    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);
-
-    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 DownwardPass<i32> for AddPass {
-        fn pass(&self, node: &mut i32, parent: Option<&mut i32>, _: &SendAnyMap) -> PassReturn {
-            if let Some(parent) = parent {
-                *node += *parent;
-            }
-            PassReturn {
-                progress: true,
-                mark_dirty: true,
-            }
-        }
-    }
-
-    let add_pass = AnyPass::Downward(&AddPass);
-    let passes = vec![&add_pass];
-    let dirty_nodes: DirtyNodeStates = DirtyNodeStates::default();
-    dirty_nodes.insert(PassId(0), tree.root());
-    resolve_passes(&mut tree, dirty_nodes, passes, SendAnyMap::new());
-
-    assert_eq!(tree.get(tree.root()).unwrap(), &1);
-    assert_eq!(tree.get(child1).unwrap(), &2);
-    assert_eq!(tree.get(grandchild1).unwrap(), &3);
-    assert_eq!(tree.get(child2).unwrap(), &2);
-    assert_eq!(tree.get(grandchild2).unwrap(), &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);
-}
+// #[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>(&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>(&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>(&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>(&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>(&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>(&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>(&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>(&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);
+// }

+ 336 - 126
packages/native-core/src/real_dom.rs

@@ -1,26 +1,17 @@
 use dioxus_core::{ElementId, Mutations, TemplateNode};
 use rustc_hash::{FxHashMap, FxHashSet};
+use std::any::TypeId;
 use std::fmt::Debug;
-use std::ops::{Deref, DerefMut, Index, IndexMut};
+use std::ops::{Index, IndexMut};
 
-use crate::node::{Node, NodeType, OwnedAttributeDiscription, OwnedAttributeValue};
+use crate::node::{
+    ElementNode, Node, NodeData, NodeType, OwnedAttributeDiscription, OwnedAttributeValue,
+};
 use crate::node_ref::{AttributeMask, NodeMask};
 use crate::passes::{resolve_passes, DirtyNodeStates, TypeErasedPass};
 use crate::state::State;
-use crate::tree::{NodeId, Tree, TreeLike, TreeView};
-use crate::{FxDashSet, RealNodeId, SendAnyMap};
-
-fn mark_dirty(
-    node_id: NodeId,
-    mask: NodeMask,
-    nodes_updated: &mut FxHashMap<RealNodeId, NodeMask>,
-) {
-    if let Some(node) = nodes_updated.get_mut(&node_id) {
-        *node = node.union(&mask);
-    } else {
-        nodes_updated.insert(node_id, mask);
-    }
-}
+use crate::tree::{NodeId, Tree, TreeLike, TreeView, TreeViewMut};
+use crate::{FxDashSet, SendAnyMap};
 
 /// A Dom that can sync with the VirtualDom mutations intended for use in lazy renderers.
 /// The render state passes from parent to children and or accumulates state from children to parents.
@@ -28,12 +19,15 @@ fn mark_dirty(
 pub struct RealDom<S: State + Send> {
     pub tree: Tree<Node<S>>,
     /// a map from element id to real node id
-    node_id_mapping: Vec<Option<RealNodeId>>,
-    nodes_listening: FxHashMap<String, FxHashSet<RealNodeId>>,
-    stack: Vec<RealNodeId>,
-    templates: FxHashMap<String, Vec<RealNodeId>>,
-    root_initialized: bool,
+    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<S>]>,
+    pub(crate) nodes_updated: FxHashMap<NodeId, NodeMask>,
+    passes_updated: FxHashMap<NodeId, FxHashSet<TypeId>>,
+    parent_changed_nodes: FxHashSet<NodeId>,
+    child_changed_nodes: FxHashSet<NodeId>,
 }
 
 impl<S: State + Send + Debug> Debug for RealDom<S> {
@@ -44,7 +38,6 @@ impl<S: State + Send + Debug> Debug for RealDom<S> {
             .field("nodes_listening", &self.nodes_listening)
             .field("stack", &self.stack)
             .field("templates", &self.templates)
-            .field("root_initialized", &self.root_initialized)
             .finish()
     }
 }
@@ -57,18 +50,34 @@ impl<S: State + Send> Default for RealDom<S> {
 
 impl<S: State + Send> RealDom<S> {
     pub fn new() -> RealDom<S> {
-        let mut root = Node::new(NodeType::Element {
+        let mut root = Node::new(NodeType::Element(ElementNode {
             tag: "Root".to_string(),
             namespace: Some("Root".to_string()),
             attributes: FxHashMap::default(),
             listeners: FxHashSet::default(),
-        });
+        }));
         root.node_data.element_id = Some(ElementId(0));
         let mut tree = Tree::new(root);
         let root_id = tree.root();
         tree.get_mut(root_id).unwrap().node_data.node_id = root_id;
 
-        let passes = S::create_passes();
+        let mut passes = S::create_passes();
+
+        // resolve dependants for each pass
+        for i in 1..passes.len() {
+            let (before, after) = passes.split_at_mut(i);
+            let (current, before) = before.split_last_mut().unwrap();
+            for pass in before.iter_mut().chain(after.iter_mut()) {
+                for dependancy in &current.combined_dependancy_type_ids {
+                    if pass.this_type_id == *dependancy {
+                        pass.dependants.insert(current.this_type_id);
+                    }
+                }
+            }
+        }
+        let mut nodes_updated = FxHashMap::default();
+        let root_id = NodeId(0);
+        nodes_updated.insert(root_id, NodeMask::ALL);
 
         RealDom {
             tree,
@@ -76,12 +85,31 @@ impl<S: State + Send> RealDom<S> {
             nodes_listening: FxHashMap::default(),
             stack: vec![root_id],
             templates: FxHashMap::default(),
-            root_initialized: false,
             passes,
+            nodes_updated,
+            passes_updated: FxHashMap::default(),
+            parent_changed_nodes: FxHashSet::default(),
+            child_changed_nodes: FxHashSet::default(),
+        }
+    }
+
+    fn mark_dirty(&mut self, node_id: NodeId, mask: NodeMask) {
+        if let Some(node) = self.nodes_updated.get_mut(&node_id) {
+            *node = node.union(&mask);
+        } else {
+            self.nodes_updated.insert(node_id, mask);
         }
     }
 
-    pub fn element_to_node_id(&self, element_id: ElementId) -> RealNodeId {
+    fn mark_parent_added_or_removed(&mut self, node_id: NodeId) {
+        self.parent_changed_nodes.insert(node_id);
+    }
+
+    fn mark_child_changed(&mut self, node_id: NodeId) {
+        self.child_changed_nodes.insert(node_id);
+    }
+
+    pub fn element_to_node_id(&self, element_id: ElementId) -> NodeId {
         self.node_id_mapping.get(element_id.0).unwrap().unwrap()
     }
 
@@ -99,7 +127,7 @@ impl<S: State + Send> RealDom<S> {
         self.node_id_mapping[element_id.0] = Some(node_id);
     }
 
-    fn load_child(&self, path: &[u8]) -> RealNodeId {
+    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];
@@ -107,18 +135,21 @@ impl<S: State + Send> RealDom<S> {
         current
     }
 
-    fn create_node(&mut self, node: Node<S>) -> RealNodeId {
+    fn create_node(&mut self, node: Node<S>, mark_dirty: bool) -> NodeId {
         let node_id = self.tree.create_node(node);
         let node = self.tree.get_mut(node_id).unwrap();
         node.node_data.node_id = node_id;
+        if mark_dirty {
+            self.nodes_updated.insert(node_id, NodeMask::ALL);
+        }
         node_id
     }
 
-    fn add_child(&mut self, node_id: RealNodeId, child_id: RealNodeId) {
+    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) -> RealNodeId {
+    fn create_template_node(&mut self, node: &TemplateNode) -> NodeId {
         match node {
             TemplateNode::Element {
                 tag,
@@ -126,7 +157,7 @@ impl<S: State + Send> RealDom<S> {
                 attrs,
                 children,
             } => {
-                let node = Node::new(NodeType::Element {
+                let node = Node::new(NodeType::Element(ElementNode {
                     tag: tag.to_string(),
                     namespace: namespace.map(|s| s.to_string()),
                     attributes: attrs
@@ -148,30 +179,28 @@ impl<S: State + Send> RealDom<S> {
                         })
                         .collect(),
                     listeners: FxHashSet::default(),
-                });
-                let node_id = self.create_node(node);
+                }));
+                let node_id = self.create_node(node, true);
                 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(Node::new(NodeType::Text {
-                text: text.to_string(),
-            })),
-            TemplateNode::Dynamic { .. } => self.create_node(Node::new(NodeType::Placeholder)),
-            TemplateNode::DynamicText { .. } => self.create_node(Node::new(NodeType::Text {
-                text: String::new(),
-            })),
+            TemplateNode::Text { text } => {
+                self.create_node(Node::new(NodeType::Text(text.to_string())), true)
+            }
+            TemplateNode::Dynamic { .. } => {
+                self.create_node(Node::new(NodeType::Placeholder), true)
+            }
+            TemplateNode::DynamicText { .. } => {
+                self.create_node(Node::new(NodeType::Text(String::new())), true)
+            }
         }
     }
 
     /// 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,
-    ) -> (DirtyNodeStates, FxHashMap<RealNodeId, NodeMask>) {
-        let mut nodes_updated: FxHashMap<RealNodeId, NodeMask> = FxHashMap::default();
+    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 {
@@ -181,11 +210,7 @@ impl<S: State + Send> RealDom<S> {
             self.templates
                 .insert(template.name.to_string(), template_root_ids);
         }
-        if !self.root_initialized {
-            self.root_initialized = true;
-            let root_id = self.tree.root();
-            nodes_updated.insert(root_id, NodeMask::ALL);
-        }
+
         for e in mutations.edits {
             use dioxus_core::Mutation::*;
             match e {
@@ -194,7 +219,6 @@ impl<S: State + Send> RealDom<S> {
                     let parent = self.element_to_node_id(id);
                     for child in children {
                         self.add_child(parent, child);
-                        mark_dirty(child, NodeMask::ALL, &mut nodes_updated);
                     }
                 }
                 AssignId { path, id } => {
@@ -202,38 +226,32 @@ impl<S: State + Send> RealDom<S> {
                 }
                 CreatePlaceholder { id } => {
                     let node = Node::new(NodeType::Placeholder);
-                    let node_id = self.create_node(node);
+                    let node_id = self.create_node(node, true);
                     self.set_element_id(node_id, id);
                     self.stack.push(node_id);
-                    mark_dirty(node_id, NodeMask::ALL, &mut nodes_updated);
                 }
                 CreateTextNode { value, id } => {
-                    let node = Node::new(NodeType::Text {
-                        text: value.to_string(),
-                    });
-                    let node_id = self.create_node(node);
+                    let node = Node::new(NodeType::Text(value.to_string()));
+                    let node_id = self.create_node(node, true);
                     let node = self.tree.get_mut(node_id).unwrap();
                     node.node_data.element_id = Some(id);
                     self.stack.push(node_id);
-                    mark_dirty(node_id, NodeMask::new().with_text(), &mut nodes_updated);
                 }
                 HydrateText { path, value, id } => {
                     let node_id = self.load_child(path);
                     self.set_element_id(node_id, id);
                     let node = self.tree.get_mut(node_id).unwrap();
-                    if let NodeType::Text { text } = &mut node.node_data.node_type {
+                    if let NodeType::Text(text) = &mut node.node_data.node_type {
                         *text = value.to_string();
                     } else {
-                        node.node_data.node_type = NodeType::Text {
-                            text: value.to_string(),
-                        };
+                        node.node_data.node_type = NodeType::Text(value.to_string());
                     }
 
-                    mark_dirty(node_id, NodeMask::new().with_text(), &mut nodes_updated);
+                    self.mark_dirty(node_id, NodeMask::new().with_text());
                 }
                 LoadTemplate { name, index, id } => {
                     let template_id = self.templates[name][index];
-                    let clone_id = self.clone_node(template_id, &mut nodes_updated);
+                    let clone_id = self.clone_node(template_id);
                     self.set_element_id(clone_id, id);
                     self.stack.push(clone_id);
                 }
@@ -242,7 +260,6 @@ impl<S: State + Send> RealDom<S> {
                     let old_node_id = self.element_to_node_id(id);
                     for new in new_nodes {
                         self.tree.insert_before(old_node_id, new);
-                        mark_dirty(new, NodeMask::ALL, &mut nodes_updated);
                     }
                     self.tree.remove(old_node_id);
                 }
@@ -251,7 +268,6 @@ impl<S: State + Send> RealDom<S> {
                     let old_node_id = self.load_child(path);
                     for new in new_nodes {
                         self.tree.insert_before(old_node_id, new);
-                        mark_dirty(new, NodeMask::ALL, &mut nodes_updated);
                     }
                     self.tree.remove(old_node_id);
                 }
@@ -260,7 +276,6 @@ impl<S: State + Send> RealDom<S> {
                     let old_node_id = self.element_to_node_id(id);
                     for new in new_nodes.into_iter().rev() {
                         self.tree.insert_after(old_node_id, new);
-                        mark_dirty(new, NodeMask::ALL, &mut nodes_updated);
                     }
                 }
                 InsertBefore { id, m } => {
@@ -268,7 +283,6 @@ impl<S: State + Send> RealDom<S> {
                     let old_node_id = self.element_to_node_id(id);
                     for new in new_nodes {
                         self.tree.insert_before(old_node_id, new);
-                        mark_dirty(new, NodeMask::ALL, &mut nodes_updated);
                     }
                 }
                 SetAttribute {
@@ -278,9 +292,9 @@ impl<S: State + Send> RealDom<S> {
                     ns,
                 } => {
                     let node_id = self.element_to_node_id(id);
-                    let node = self.tree.get_mut(node_id).unwrap();
-                    if let NodeType::Element { attributes, .. } = &mut node.node_data.node_type {
-                        attributes.insert(
+                    let mut node = self.get_mut(node_id).unwrap();
+                    if let NodeTypeMut::Element(mut element) = node.node_type_mut() {
+                        element.set_attribute(
                             OwnedAttributeDiscription {
                                 name: name.to_string(),
                                 namespace: ns.map(|s| s.to_string()),
@@ -288,18 +302,13 @@ impl<S: State + Send> RealDom<S> {
                             },
                             crate::node::OwnedAttributeValue::Text(value.to_string()),
                         );
-                        mark_dirty(
-                            node_id,
-                            NodeMask::new_with_attrs(AttributeMask::single(name)),
-                            &mut nodes_updated,
-                        );
                     }
                 }
                 SetBoolAttribute { name, value, id } => {
                     let node_id = self.element_to_node_id(id);
-                    let node = self.tree.get_mut(node_id).unwrap();
-                    if let NodeType::Element { attributes, .. } = &mut node.node_data.node_type {
-                        attributes.insert(
+                    let mut node = self.get_mut(node_id).unwrap();
+                    if let NodeTypeMut::Element(mut element) = node.node_type_mut() {
+                        element.set_attribute(
                             OwnedAttributeDiscription {
                                 name: name.to_string(),
                                 namespace: None,
@@ -307,25 +316,21 @@ impl<S: State + Send> RealDom<S> {
                             },
                             crate::node::OwnedAttributeValue::Bool(value),
                         );
-                        mark_dirty(
-                            node_id,
-                            NodeMask::new_with_attrs(AttributeMask::single(name)),
-                            &mut nodes_updated,
-                        );
                     }
                 }
                 SetText { value, id } => {
                     let node_id = self.element_to_node_id(id);
-                    let node = self.tree.get_mut(node_id).unwrap();
-                    if let NodeType::Text { text } = &mut node.node_data.node_type {
+                    let mut node = self.get_mut(node_id).unwrap();
+                    if let NodeTypeMut::Text(text) = node.node_type_mut() {
                         *text = value.to_string();
                     }
-                    mark_dirty(node_id, NodeMask::new().with_text(), &mut nodes_updated);
                 }
                 NewEventListener { name, id } => {
                     let node_id = self.element_to_node_id(id);
-                    let node = self.tree.get_mut(node_id).unwrap();
-                    if let NodeType::Element { listeners, .. } = &mut node.node_data.node_type {
+                    let mut node = self.get_mut(node_id).unwrap();
+                    if let NodeTypeMut::Element(mut element) = node.node_type_mut() {
+                        element.listeners_mut().insert(name.to_string());
+                        drop(node);
                         match self.nodes_listening.get_mut(name) {
                             Some(hs) => {
                                 hs.insert(node_id);
@@ -336,14 +341,15 @@ impl<S: State + Send> RealDom<S> {
                                 self.nodes_listening.insert(name.to_string(), hs);
                             }
                         }
-                        listeners.insert(name.to_string());
                     }
                 }
                 RemoveEventListener { id, name } => {
                     let node_id = self.element_to_node_id(id);
-                    let node = self.tree.get_mut(node_id).unwrap();
-                    if let NodeType::Element { listeners, .. } = &mut node.node_data.node_type {
-                        listeners.remove(name);
+                    {
+                        let mut node = self.get_mut(node_id).unwrap();
+                        if let NodeTypeMut::Element(mut element) = node.node_type_mut() {
+                            element.listeners_mut().remove(name);
+                        }
                     }
                     self.nodes_listening.get_mut(name).unwrap().remove(&node_id);
                 }
@@ -357,8 +363,17 @@ impl<S: State + Send> RealDom<S> {
                 }
             }
         }
+    }
 
+    /// Update the state of the dom, after appling some mutations. This will keep the nodes in the dom up to date with their VNode counterparts.
+    pub fn update_state(
+        &mut self,
+        ctx: SendAnyMap,
+    ) -> (FxDashSet<NodeId>, FxHashMap<NodeId, NodeMask>) {
+        let tree = &mut self.tree;
+        let passes = &self.passes;
         let dirty_nodes = DirtyNodeStates::default();
+        let nodes_updated = std::mem::take(&mut self.nodes_updated);
         for (&n, mask) in &nodes_updated {
             // remove any nodes that were created and then removed in the same mutations from the dirty nodes list
             if self.tree.contains(n) {
@@ -370,18 +385,11 @@ impl<S: State + Send> RealDom<S> {
             }
         }
 
-        (dirty_nodes, nodes_updated)
-    }
-
-    /// Update the state of the dom, after appling some mutations. This will keep the nodes in the dom up to date with their VNode counterparts.
-    pub fn update_state(
-        &mut self,
-        nodes_updated: DirtyNodeStates,
-        ctx: SendAnyMap,
-    ) -> FxDashSet<RealNodeId> {
-        let tree = &mut self.tree;
-        let passes = &self.passes;
-        resolve_passes(tree, nodes_updated, passes, ctx)
+        todo!("incorporate other update members");
+        (
+            resolve_passes(tree, dirty_nodes, passes, ctx),
+            nodes_updated,
+        )
     }
 
     /// Find all nodes that are listening for an event, sorted by there height in the dom progressing starting at the bottom and progressing up.
@@ -411,39 +419,135 @@ impl<S: State + Send> RealDom<S> {
         self.tree.root()
     }
 
-    fn clone_node(
-        &mut self,
-        node_id: NodeId,
-        nodes_updated: &mut FxHashMap<RealNodeId, NodeMask>,
-    ) -> RealNodeId {
+    fn clone_node(&mut self, node_id: NodeId) -> NodeId {
         let node = self.tree.get(node_id).unwrap();
-        let new_node = node.clone();
-        let new_id = self.create_node(new_node);
-        mark_dirty(new_id, NodeMask::ALL, nodes_updated);
+        let new_node = Node {
+            state: node.state.clone_or_default(),
+            node_data: node.node_data.clone(),
+        };
+        let new_id = self.create_node(new_node, false);
+        if let Some(passes) = S::non_clone_nodes() {
+            for pass_id in &*passes {
+                self.passes_updated
+                    .entry(node_id)
+                    .or_default()
+                    .insert(*pass_id);
+            }
+        }
+
         let self_ptr = self as *mut Self;
         for child in self.tree.children_ids(node_id).unwrap() {
             unsafe {
                 // this is safe because no node has itself as a child
                 let self_mut = &mut *self_ptr;
-                let child_id = self_mut.clone_node(*child, nodes_updated);
+                let child_id = self_mut.clone_node(*child);
                 self_mut.add_child(new_id, child_id);
             }
         }
         new_id
     }
+
+    pub fn get_mut(&mut self, id: NodeId) -> Option<NodeMut<'_>> {
+        self.tree.get_mut(id).map(|node| NodeMut {
+            node: &mut node.node_data,
+            dirty: NodeMask::new(),
+            nodes_updated: &mut self.nodes_updated,
+        })
+    }
+
+    /// WARNING: This escapes the reactive system that the real dom uses. Any changes made with this method will not trigger updates in states when [RealDom::update_state] is called.
+    pub fn get_mut_raw(&mut self, id: NodeId) -> Option<&mut Node<S>> {
+        self.tree.get_mut(id)
+    }
 }
 
-impl<S: State + Send> Deref for RealDom<S> {
-    type Target = Tree<Node<S>>;
+impl<S: State + Send> TreeView<Node<S>> for RealDom<S> {
+    type Iterator<'a> = <Tree<Node<S>> as TreeView<Node<S>>>::Iterator<'a>;
+
+    fn root(&self) -> NodeId {
+        self.tree.root()
+    }
+
+    fn get(&self, id: NodeId) -> Option<&Node<S>> {
+        self.tree.get(id)
+    }
+
+    fn children(&self, id: NodeId) -> Option<Self::Iterator<'_>> {
+        self.tree.children(id)
+    }
+
+    fn children_ids(&self, id: NodeId) -> Option<&[NodeId]> {
+        self.tree.children_ids(id)
+    }
+
+    fn parent(&self, id: NodeId) -> Option<&Node<S>> {
+        self.tree.parent(id)
+    }
+
+    fn parent_id(&self, id: NodeId) -> Option<NodeId> {
+        self.tree.parent_id(id)
+    }
+
+    fn height(&self, id: NodeId) -> Option<u16> {
+        self.tree.height(id)
+    }
 
-    fn deref(&self) -> &Self::Target {
-        &self.tree
+    fn size(&self) -> usize {
+        self.tree.size()
     }
 }
 
-impl<S: State + Send> DerefMut for RealDom<S> {
-    fn deref_mut(&mut self) -> &mut Self::Target {
-        &mut self.tree
+impl<S: State + Send> TreeLike<Node<S>> for RealDom<S> {
+    fn create_node(&mut self, node: Node<S>) -> NodeId {
+        let mask = NodeMask::ALL;
+        let id = self.tree.create_node(node);
+        self.tree.get_mut(id).unwrap().node_data.node_id = id;
+        self.mark_dirty(id, mask);
+        id
+    }
+
+    fn add_child(&mut self, parent: NodeId, child: NodeId) {
+        // mark the parent's children changed
+        self.mark_child_changed(parent);
+        // mark the child's parent changed
+        self.mark_parent_added_or_removed(child);
+        self.tree.add_child(parent, child);
+    }
+
+    fn remove(&mut self, id: NodeId) -> Option<Node<S>> {
+        if let Some(parent_id) = self.tree.parent_id(id) {
+            self.mark_child_changed(parent_id);
+        }
+        self.tree.remove(id)
+    }
+
+    fn remove_all_children(&mut self, id: NodeId) -> Vec<Node<S>> {
+        self.mark_child_changed(id);
+        self.tree.remove_all_children(id)
+    }
+
+    fn replace(&mut self, old: NodeId, new: NodeId) {
+        if let Some(parent_id) = self.tree.parent_id(old) {
+            self.mark_child_changed(parent_id);
+            self.mark_parent_added_or_removed(new);
+        }
+        self.tree.replace(old, new);
+    }
+
+    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);
+    }
+
+    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);
     }
 }
 
@@ -455,10 +559,10 @@ impl<S: State + Send> Index<ElementId> for RealDom<S> {
     }
 }
 
-impl<S: State + Send> Index<RealNodeId> for RealDom<S> {
+impl<S: State + Send> Index<NodeId> for RealDom<S> {
     type Output = Node<S>;
 
-    fn index(&self, idx: RealNodeId) -> &Self::Output {
+    fn index(&self, idx: NodeId) -> &Self::Output {
         self.tree.get(idx).unwrap()
     }
 }
@@ -469,8 +573,114 @@ impl<S: State + Send> IndexMut<ElementId> for RealDom<S> {
     }
 }
 
-impl<S: State + Send> IndexMut<RealNodeId> for RealDom<S> {
-    fn index_mut(&mut self, idx: RealNodeId) -> &mut Self::Output {
+impl<S: State + Send> IndexMut<NodeId> for RealDom<S> {
+    fn index_mut(&mut self, idx: NodeId) -> &mut Self::Output {
         self.tree.get_mut(idx).unwrap()
     }
 }
+
+pub struct NodeMut<'a> {
+    node: &'a mut NodeData,
+    dirty: NodeMask,
+    nodes_updated: &'a mut FxHashMap<NodeId, NodeMask>,
+}
+
+impl<'a> NodeMut<'a> {
+    pub fn node_type(&self) -> &NodeType {
+        &self.node.node_type
+    }
+
+    pub fn node_type_mut(&mut self) -> NodeTypeMut<'_> {
+        match &mut self.node.node_type {
+            NodeType::Element(element) => NodeTypeMut::Element(ElementNodeMut {
+                element,
+                dirty: &mut self.dirty,
+            }),
+            NodeType::Text(text) => {
+                self.dirty.set_text();
+                NodeTypeMut::Text(text)
+            }
+            NodeType::Placeholder => NodeTypeMut::Placeholder,
+        }
+    }
+}
+
+impl Drop for NodeMut<'_> {
+    fn drop(&mut self) {
+        let node_id = self.node.node_id;
+        let mask = std::mem::take(&mut self.dirty);
+        if let Some(node) = self.nodes_updated.get_mut(&node_id) {
+            *node = node.union(&mask);
+        } else {
+            self.nodes_updated.insert(node_id, mask);
+        }
+    }
+}
+
+pub enum NodeTypeMut<'a> {
+    Element(ElementNodeMut<'a>),
+    Text(&'a mut String),
+    Placeholder,
+}
+
+pub struct ElementNodeMut<'a> {
+    element: &'a mut ElementNode,
+    dirty: &'a mut NodeMask,
+}
+
+impl ElementNodeMut<'_> {
+    pub fn tag(&self) -> &str {
+        &self.element.tag
+    }
+
+    pub fn tag_mut(&mut self) -> &mut String {
+        self.dirty.set_tag();
+        &mut self.element.tag
+    }
+
+    pub fn namespace(&self) -> Option<&str> {
+        self.element.namespace.as_deref()
+    }
+
+    pub fn namespace_mut(&mut self) -> &mut Option<String> {
+        self.dirty.set_namespace();
+        &mut self.element.namespace
+    }
+
+    pub fn attributes(&self) -> &FxHashMap<OwnedAttributeDiscription, OwnedAttributeValue> {
+        &self.element.attributes
+    }
+
+    pub fn attributes_mut(
+        &mut self,
+    ) -> &mut FxHashMap<OwnedAttributeDiscription, OwnedAttributeValue> {
+        self.dirty.add_attributes(AttributeMask::All);
+        &mut self.element.attributes
+    }
+
+    pub fn set_attribute(
+        &mut self,
+        name: OwnedAttributeDiscription,
+        value: OwnedAttributeValue,
+    ) -> Option<OwnedAttributeValue> {
+        self.dirty.add_attributes(AttributeMask::single(&name.name));
+        self.element.attributes.insert(name, value)
+    }
+
+    pub fn get_attribute_mut(
+        &mut self,
+        name: &OwnedAttributeDiscription,
+    ) -> Option<&mut OwnedAttributeValue> {
+        self.dirty.add_attributes(AttributeMask::single(&name.name));
+        self.element.attributes.get_mut(name)
+    }
+
+    pub fn listeners(&self) -> &FxHashSet<String> {
+        &self.element.listeners
+    }
+
+    pub fn listeners_mut(&mut self) -> &mut FxHashSet<String> {
+        self.dirty.set_listeners();
+        &mut self.element.listeners
+    }
+}

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

@@ -1,10 +1,7 @@
-use std::cmp::Ordering;
-
-use crate::node::Node;
 use crate::node_ref::{NodeMask, NodeView};
-use crate::passes::{resolve_passes, AnyMapLike, DirtyNodeStates, Pass, TypeErasedPass};
-use crate::tree::{Tree, TreeView};
-use crate::{FxDashSet, RealNodeId, SendAnyMap};
+use crate::passes::{AnyMapLike, TypeErasedPass};
+use std::any::TypeId;
+use std::cmp::Ordering;
 
 /// Join two sorted iterators
 pub(crate) fn union_ordered_iter<'a>(
@@ -213,6 +210,16 @@ pub trait NodeDepState {
 pub trait State: Default + Clone + AnyMapLike + 'static {
     #[doc(hidden)]
     fn create_passes() -> Box<[TypeErasedPass<Self>]>;
+
+    #[doc(hidden)]
+    fn clone_or_default(&self) -> Self {
+        self.clone()
+    }
+
+    #[doc(hidden)]
+    fn non_clone_nodes() -> Option<Box<[TypeId]>> {
+        None
+    }
 }
 
 impl ChildDepState for () {

+ 131 - 414
packages/native-core/src/tree.rs

@@ -25,6 +25,17 @@ pub struct Tree<T> {
 }
 
 impl<T> Tree<T> {
+    pub fn new(root: T) -> Self {
+        let mut nodes = Slab::default();
+        let root = NodeId(nodes.insert(Node {
+            value: root,
+            parent: None,
+            children: Vec::new(),
+            height: 0,
+        }));
+        Self { nodes, root }
+    }
+
     fn try_remove(&mut self, id: NodeId) -> Option<Node<T>> {
         self.nodes.try_remove(id.0).map(|node| {
             if let Some(parent) = node.parent {
@@ -63,10 +74,6 @@ impl<T> Tree<T> {
 
 pub trait TreeView<T>: Sized {
     type Iterator<'a>: Iterator<Item = &'a T>
-    where
-        T: 'a,
-        Self: 'a;
-    type IteratorMut<'a>: Iterator<Item = &'a mut T>
     where
         T: 'a,
         Self: 'a;
@@ -83,69 +90,16 @@ pub trait TreeView<T>: Sized {
         unsafe { self.get(id).unwrap_unchecked() }
     }
 
-    fn get_mut(&mut self, id: NodeId) -> Option<&mut T>;
-
-    fn get_mut_unchecked(&mut self, id: NodeId) -> &mut T {
-        unsafe { self.get_mut(id).unwrap_unchecked() }
-    }
-
     fn children(&self, id: NodeId) -> Option<Self::Iterator<'_>>;
 
-    fn children_mut(&mut self, id: NodeId) -> Option<Self::IteratorMut<'_>>;
-
-    fn parent_child_mut(&mut self, id: NodeId) -> Option<(&mut T, Self::IteratorMut<'_>)> {
-        let mut_ptr: *mut Self = self;
-        unsafe {
-            // Safety: No node has itself as a child.
-            (*mut_ptr).get_mut(id).and_then(|parent| {
-                (*mut_ptr)
-                    .children_mut(id)
-                    .map(|children| (parent, children))
-            })
-        }
-    }
-
     fn children_ids(&self, id: NodeId) -> Option<&[NodeId]>;
 
     fn parent(&self, id: NodeId) -> Option<&T>;
 
-    fn parent_mut(&mut self, id: NodeId) -> Option<&mut T>;
-
-    fn node_parent_mut(&mut self, id: NodeId) -> Option<(&mut T, Option<&mut T>)> {
-        let mut_ptr: *mut Self = self;
-        unsafe {
-            // Safety: No node has itself as a parent.
-            (*mut_ptr)
-                .get_mut(id)
-                .map(|node| (node, (*mut_ptr).parent_mut(id)))
-        }
-    }
-
-    fn node_parent_children_mut(
-        &mut self,
-        id: NodeId,
-    ) -> Option<(&mut T, Option<&mut T>, Option<Self::IteratorMut<'_>>)> {
-        let mut_ptr: *mut Self = self;
-        unsafe {
-            // Safety: No node has itself as a parent or child.
-            (*mut_ptr)
-                .get_mut(id)
-                .map(|node| (node, (*mut_ptr).parent_mut(id), (*mut_ptr).children_mut(id)))
-        }
-    }
-
     fn parent_id(&self, id: NodeId) -> Option<NodeId>;
 
     fn height(&self, id: NodeId) -> Option<u16>;
 
-    fn map<T2, F: Fn(&T) -> &T2, FMut: Fn(&mut T) -> &mut T2>(
-        &mut self,
-        map: F,
-        map_mut: FMut,
-    ) -> TreeMap<T, T2, Self, F, FMut> {
-        TreeMap::new(self, map, map_mut)
-    }
-
     fn size(&self) -> usize;
 
     fn traverse_depth_first(&self, mut f: impl FnMut(&T)) {
@@ -160,18 +114,6 @@ pub trait TreeView<T>: Sized {
         }
     }
 
-    fn traverse_depth_first_mut(&mut self, mut f: impl FnMut(&mut T)) {
-        let mut stack = vec![self.root()];
-        while let Some(id) = stack.pop() {
-            if let Some(node) = self.get_mut(id) {
-                f(node);
-                if let Some(children) = self.children_ids(id) {
-                    stack.extend(children.iter().copied().rev());
-                }
-            }
-        }
-    }
-
     fn traverse_breadth_first(&self, mut f: impl FnMut(&T)) {
         let mut queue = VecDeque::new();
         queue.push_back(self.root());
@@ -186,6 +128,61 @@ pub trait TreeView<T>: Sized {
             }
         }
     }
+}
+
+pub trait TreeViewMut<T>: Sized + TreeView<T> {
+    type IteratorMut<'a>: Iterator<Item = &'a mut T>
+    where
+        T: 'a,
+        Self: 'a;
+
+    fn get_mut(&mut self, id: NodeId) -> Option<&mut T>;
+
+    fn get_mut_unchecked(&mut self, id: NodeId) -> &mut T {
+        unsafe { self.get_mut(id).unwrap_unchecked() }
+    }
+
+    fn children_mut(&mut self, id: NodeId) -> Option<<Self as TreeViewMut<T>>::IteratorMut<'_>>;
+
+    fn parent_child_mut(
+        &mut self,
+        id: NodeId,
+    ) -> Option<(&mut T, <Self as TreeViewMut<T>>::IteratorMut<'_>)> {
+        let mut_ptr: *mut Self = self;
+        unsafe {
+            // Safety: No node has itself as a child.
+            (*mut_ptr).get_mut(id).and_then(|parent| {
+                (*mut_ptr)
+                    .children_mut(id)
+                    .map(|children| (parent, children))
+            })
+        }
+    }
+
+    fn parent_mut(&mut self, id: NodeId) -> Option<&mut T>;
+
+    fn node_parent_mut(&mut self, id: NodeId) -> Option<(&mut T, Option<&mut T>)>;
+
+    fn node_parent_children_mut(
+        &mut self,
+        id: NodeId,
+    ) -> Option<(
+        &mut T,
+        Option<&mut T>,
+        Option<<Self as TreeViewMut<T>>::IteratorMut<'_>>,
+    )>;
+
+    fn traverse_depth_first_mut(&mut self, mut f: impl FnMut(&mut T)) {
+        let mut stack = vec![self.root()];
+        while let Some(id) = stack.pop() {
+            if let Some(node) = self.get_mut(id) {
+                f(node);
+                if let Some(children) = self.children_ids(id) {
+                    stack.extend(children.iter().copied().rev());
+                }
+            }
+        }
+    }
 
     fn traverse_breadth_first_mut(&mut self, mut f: impl FnMut(&mut T)) {
         let mut queue = VecDeque::new();
@@ -203,9 +200,7 @@ pub trait TreeView<T>: Sized {
     }
 }
 
-pub trait TreeLike<T>: TreeView<T> {
-    fn new(root: T) -> Self;
-
+pub trait TreeLike<T> {
     fn create_node(&mut self, value: T) -> NodeId;
 
     fn add_child(&mut self, parent: NodeId, child: NodeId);
@@ -239,22 +234,22 @@ impl<'a, T: 'a, Tr: TreeView<T>> Iterator for ChildNodeIterator<'a, T, Tr> {
     }
 }
 
-pub struct ChildNodeIteratorMut<'a, T, Tr: TreeView<T> + 'a> {
+pub struct ChildNodeIteratorMut<'a, T, Tr: TreeViewMut<T> + 'a> {
     tree: *mut Tr,
     children_ids: &'a [NodeId],
     index: usize,
     node_type: PhantomData<T>,
 }
 
-unsafe impl<'a, T, Tr: TreeView<T> + 'a> Sync for ChildNodeIteratorMut<'a, T, Tr> {}
+unsafe impl<'a, T, Tr: TreeViewMut<T> + 'a> Sync for ChildNodeIteratorMut<'a, T, Tr> {}
 
-impl<'a, T, Tr: TreeView<T>> ChildNodeIteratorMut<'a, T, Tr> {
+impl<'a, T, Tr: TreeViewMut<T>> ChildNodeIteratorMut<'a, T, Tr> {
     fn tree_mut(&mut self) -> &'a mut Tr {
         unsafe { &mut *self.tree }
     }
 }
 
-impl<'a, T: 'a, Tr: TreeView<T>> Iterator for ChildNodeIteratorMut<'a, T, Tr> {
+impl<'a, T: 'a, Tr: TreeViewMut<T>> Iterator for ChildNodeIteratorMut<'a, T, Tr> {
     type Item = &'a mut T;
 
     fn next(&mut self) -> Option<Self::Item> {
@@ -272,7 +267,6 @@ impl<'a, T: 'a, Tr: TreeView<T>> Iterator for ChildNodeIteratorMut<'a, T, Tr> {
 
 impl<T> TreeView<T> for Tree<T> {
     type Iterator<'a> = ChildNodeIterator<'a, T, Tree<T>> where T: 'a;
-    type IteratorMut<'a> = ChildNodeIteratorMut<'a, T, Tree<T>> where T: 'a;
 
     fn root(&self) -> NodeId {
         self.root
@@ -282,10 +276,6 @@ impl<T> TreeView<T> for Tree<T> {
         self.nodes.get(id.0).map(|node| &node.value)
     }
 
-    fn get_mut(&mut self, id: NodeId) -> Option<&mut T> {
-        self.nodes.get_mut(id.0).map(|node| &mut node.value)
-    }
-
     fn children(&self, id: NodeId) -> Option<Self::Iterator<'_>> {
         self.children_ids(id).map(|children_ids| ChildNodeIterator {
             tree: self,
@@ -295,20 +285,6 @@ impl<T> TreeView<T> for Tree<T> {
         })
     }
 
-    fn children_mut(&mut self, id: NodeId) -> Option<Self::IteratorMut<'_>> {
-        let raw_ptr = self as *mut Self;
-        unsafe {
-            // Safety: No node will appear as a child twice
-            self.children_ids(id)
-                .map(|children_ids| ChildNodeIteratorMut {
-                    tree: &mut *raw_ptr,
-                    children_ids,
-                    index: 0,
-                    node_type: PhantomData,
-                })
-        }
-    }
-
     fn children_ids(&self, id: NodeId) -> Option<&[NodeId]> {
         self.nodes.get(id.0).map(|node| node.children.as_slice())
     }
@@ -320,6 +296,30 @@ impl<T> TreeView<T> for Tree<T> {
             .map(|node| &node.value)
     }
 
+    fn parent_id(&self, id: NodeId) -> Option<NodeId> {
+        self.nodes.get(id.0).and_then(|node| node.parent)
+    }
+
+    fn height(&self, id: NodeId) -> Option<u16> {
+        self.nodes.get(id.0).map(|n| n.height)
+    }
+
+    fn get_unchecked(&self, id: NodeId) -> &T {
+        unsafe { &self.nodes.get_unchecked(id.0).value }
+    }
+
+    fn size(&self) -> usize {
+        self.nodes.len()
+    }
+}
+
+impl<T> TreeViewMut<T> for Tree<T> {
+    type IteratorMut<'a> = ChildNodeIteratorMut<'a, T, Tree<T>> where T: 'a;
+
+    fn get_mut(&mut self, id: NodeId) -> Option<&mut T> {
+        self.nodes.get_mut(id.0).map(|node| &mut node.value)
+    }
+
     fn parent_mut(&mut self, id: NodeId) -> Option<&mut T> {
         let self_ptr = self as *mut Self;
         unsafe {
@@ -334,39 +334,52 @@ impl<T> TreeView<T> for Tree<T> {
         }
     }
 
-    fn parent_id(&self, id: NodeId) -> Option<NodeId> {
-        self.nodes.get(id.0).and_then(|node| node.parent)
-    }
-
-    fn height(&self, id: NodeId) -> Option<u16> {
-        self.nodes.get(id.0).map(|n| n.height)
-    }
-
-    fn get_unchecked(&self, id: NodeId) -> &T {
-        unsafe { &self.nodes.get_unchecked(id.0).value }
+    fn children_mut(&mut self, id: NodeId) -> Option<Self::IteratorMut<'_>> {
+        let raw_ptr = self as *mut Self;
+        unsafe {
+            // Safety: No node will appear as a child twice
+            self.children_ids(id)
+                .map(|children_ids| ChildNodeIteratorMut {
+                    tree: &mut *raw_ptr,
+                    children_ids,
+                    index: 0,
+                    node_type: PhantomData,
+                })
+        }
     }
 
     fn get_mut_unchecked(&mut self, id: NodeId) -> &mut T {
         unsafe { &mut self.nodes.get_unchecked_mut(id.0).value }
     }
 
-    fn size(&self) -> usize {
-        self.nodes.len()
+    fn node_parent_mut(&mut self, id: NodeId) -> Option<(&mut T, Option<&mut T>)> {
+        if let Some(parent_id) = self.parent_id(id) {
+            self.nodes
+                .get2_mut(id.0, parent_id.0)
+                .map(|(node, parent)| (&mut node.value, Some(&mut parent.value)))
+        } else {
+            self.nodes.get_mut(id.0).map(|node| (&mut node.value, None))
+        }
     }
-}
 
-impl<T> TreeLike<T> for Tree<T> {
-    fn new(root: T) -> Self {
-        let mut nodes = Slab::default();
-        let root = NodeId(nodes.insert(Node {
-            value: root,
-            parent: None,
-            children: Vec::new(),
-            height: 0,
-        }));
-        Self { nodes, root }
+    fn node_parent_children_mut(
+        &mut self,
+        id: NodeId,
+    ) -> Option<(
+        &mut T,
+        Option<&mut T>,
+        Option<<Self as TreeViewMut<T>>::IteratorMut<'_>>,
+    )> {
+        // Safety: No node has itself as a parent.
+        let unbounded_self = unsafe { &mut *(self as *mut Self) };
+        self.node_parent_mut(id).map(move |(node, parent)| {
+            let children = unbounded_self.children_mut(id);
+            (node, parent, children)
+        })
     }
+}
 
+impl<T> TreeLike<T> for Tree<T> {
     fn create_node(&mut self, value: T) -> NodeId {
         NodeId(self.nodes.insert(Node {
             value,
@@ -448,248 +461,6 @@ impl<T> TreeLike<T> for Tree<T> {
         self.set_height(new, height);
     }
 }
-
-pub struct TreeMap<'a, T1, T2, Tr, F, FMut>
-where
-    Tr: TreeView<T1>,
-    F: Fn(&T1) -> &T2,
-    FMut: Fn(&mut T1) -> &mut T2,
-{
-    tree: &'a mut Tr,
-    map: F,
-    map_mut: FMut,
-    in_node_type: PhantomData<T1>,
-    out_node_type: PhantomData<T2>,
-}
-
-impl<'a, T1, T2, Tr, F, FMut> TreeMap<'a, T1, T2, Tr, F, FMut>
-where
-    Tr: TreeView<T1>,
-    F: Fn(&T1) -> &T2,
-    FMut: Fn(&mut T1) -> &mut T2,
-{
-    pub fn new(tree: &'a mut Tr, map: F, map_mut: FMut) -> Self {
-        TreeMap {
-            tree,
-            map,
-            map_mut,
-            in_node_type: PhantomData,
-            out_node_type: PhantomData,
-        }
-    }
-}
-
-impl<'a, T1, T2, Tr, F, FMut> TreeView<T2> for TreeMap<'a, T1, T2, Tr, F, FMut>
-where
-    Tr: TreeView<T1>,
-    F: Fn(&T1) -> &T2,
-    FMut: Fn(&mut T1) -> &mut T2,
-{
-    type Iterator<'b> = ChildNodeIterator<'b, T2, TreeMap<'a, T1, T2, Tr, F, FMut>>
-    where
-        T2: 'b,
-        Self:'b;
-    type IteratorMut<'b> = ChildNodeIteratorMut<'b, T2, TreeMap<'a, T1, T2, Tr, F, FMut>>
-    where
-        T2: 'b,
-        Self:'b;
-
-    fn root(&self) -> NodeId {
-        self.tree.root()
-    }
-
-    fn get(&self, id: NodeId) -> Option<&T2> {
-        self.tree.get(id).map(|node| (self.map)(node))
-    }
-
-    fn get_mut(&mut self, id: NodeId) -> Option<&mut T2> {
-        self.tree.get_mut(id).map(|node| (self.map_mut)(node))
-    }
-
-    fn children(&self, id: NodeId) -> Option<Self::Iterator<'_>> {
-        self.children_ids(id).map(|children_ids| ChildNodeIterator {
-            tree: self,
-            children_ids,
-            index: 0,
-            node_type: PhantomData,
-        })
-    }
-
-    fn children_mut(&mut self, id: NodeId) -> Option<Self::IteratorMut<'_>> {
-        let raw_ptr = self as *mut Self;
-        unsafe {
-            // Safety: No node can be a child twice.
-            self.children_ids(id)
-                .map(|children_ids| ChildNodeIteratorMut {
-                    tree: &mut *raw_ptr,
-                    children_ids,
-                    index: 0,
-                    node_type: PhantomData,
-                })
-        }
-    }
-
-    fn children_ids(&self, id: NodeId) -> Option<&[NodeId]> {
-        self.tree.children_ids(id)
-    }
-
-    fn parent(&self, id: NodeId) -> Option<&T2> {
-        self.tree.parent(id).map(|node| (self.map)(node))
-    }
-
-    fn parent_mut(&mut self, id: NodeId) -> Option<&mut T2> {
-        self.tree.parent_mut(id).map(|node| (self.map_mut)(node))
-    }
-
-    fn parent_id(&self, id: NodeId) -> Option<NodeId> {
-        self.tree.parent_id(id)
-    }
-
-    fn height(&self, id: NodeId) -> Option<u16> {
-        self.tree.height(id)
-    }
-
-    fn get_unchecked(&self, id: NodeId) -> &T2 {
-        (self.map)(self.tree.get_unchecked(id))
-    }
-
-    fn get_mut_unchecked(&mut self, id: NodeId) -> &mut T2 {
-        (self.map_mut)(self.tree.get_mut_unchecked(id))
-    }
-
-    fn size(&self) -> usize {
-        self.tree.size()
-    }
-}
-
-/// A view into a tree that can be shared between multiple threads. Nodes are locked invividually.
-pub struct SharedView<'a, T, Tr: TreeView<T>> {
-    tree: Arc<UnsafeCell<&'a mut Tr>>,
-    node_locks: Arc<RwLock<Vec<RawMutex>>>,
-    node_type: PhantomData<T>,
-}
-
-impl<'a, T, Tr: TreeView<T>> SharedView<'a, T, Tr> {
-    /// Checks if a node is currently locked. Returns None if the node does not exist.
-    pub fn check_lock(&self, id: NodeId) -> Option<bool> {
-        let locks = self.node_locks.read();
-        locks.get(id.0).map(|lock| lock.is_locked())
-    }
-}
-
-unsafe impl<'a, T, Tr: TreeView<T>> Send for SharedView<'a, T, Tr> {}
-unsafe impl<'a, T, Tr: TreeView<T>> Sync for SharedView<'a, T, Tr> {}
-impl<'a, T, Tr: TreeView<T>> Clone for SharedView<'a, T, Tr> {
-    fn clone(&self) -> Self {
-        Self {
-            tree: self.tree.clone(),
-            node_locks: self.node_locks.clone(),
-            node_type: PhantomData,
-        }
-    }
-}
-
-impl<'a, T, Tr: TreeView<T>> SharedView<'a, T, Tr> {
-    pub fn new(tree: &'a mut Tr) -> Self {
-        let tree = Arc::new(UnsafeCell::new(tree));
-        let mut node_locks = Vec::new();
-        for _ in 0..unsafe { (*tree.get()).size() } {
-            node_locks.push(RawMutex::INIT);
-        }
-        Self {
-            tree,
-            node_locks: Arc::new(RwLock::new(node_locks)),
-            node_type: PhantomData,
-        }
-    }
-
-    fn lock_node(&self, node: NodeId) {
-        let read = self.node_locks.read();
-        let lock = read.get(node.0);
-        match lock {
-            Some(lock) => lock.lock(),
-            None => {
-                drop(read);
-                let mut write = self.node_locks.write();
-                write.resize_with(node.0 + 1, || RawMutex::INIT);
-                unsafe { write.get_unchecked(node.0).lock() }
-            }
-        }
-    }
-
-    fn unlock_node(&self, node: NodeId) {
-        let read = self.node_locks.read();
-        let lock = read.get(node.0);
-        match lock {
-            Some(lock) => unsafe { lock.unlock() },
-            None => {
-                panic!("unlocking node that was not locked")
-            }
-        }
-    }
-
-    fn with_node<R>(&self, node_id: NodeId, f: impl FnOnce(&'a mut Tr) -> R) -> R {
-        self.lock_node(node_id);
-        let tree = unsafe { &mut *self.tree.get() };
-        let r = f(tree);
-        self.unlock_node(node_id);
-        r
-    }
-}
-
-impl<'a, T, Tr: TreeView<T>> TreeView<T> for SharedView<'a, T, Tr> {
-    type Iterator<'b> = Tr::Iterator<'b> where T: 'b, Self: 'b;
-
-    type IteratorMut<'b>=Tr::IteratorMut<'b>
-    where
-        T: 'b,
-        Self: 'b;
-
-    fn root(&self) -> NodeId {
-        unsafe { (*self.tree.get()).root() }
-    }
-
-    fn get(&self, id: NodeId) -> Option<&T> {
-        self.with_node(id, |t| t.get(id))
-    }
-
-    fn get_mut(&mut self, id: NodeId) -> Option<&mut T> {
-        self.with_node(id, |t| t.get_mut(id))
-    }
-
-    fn children(&self, id: NodeId) -> Option<Self::Iterator<'_>> {
-        self.with_node(id, |t| t.children(id))
-    }
-
-    fn children_mut(&mut self, id: NodeId) -> Option<Self::IteratorMut<'_>> {
-        self.with_node(id, |t| t.children_mut(id))
-    }
-
-    fn children_ids(&self, id: NodeId) -> Option<&[NodeId]> {
-        self.with_node(id, |t| t.children_ids(id))
-    }
-
-    fn parent(&self, id: NodeId) -> Option<&T> {
-        self.with_node(id, |t| t.get(id))
-    }
-
-    fn parent_mut(&mut self, id: NodeId) -> Option<&mut T> {
-        self.with_node(id, |t| t.parent_mut(id))
-    }
-
-    fn parent_id(&self, id: NodeId) -> Option<NodeId> {
-        self.with_node(id, |t| t.parent_id(id))
-    }
-
-    fn height(&self, id: NodeId) -> Option<u16> {
-        unsafe { (*self.tree.get()).height(id) }
-    }
-
-    fn size(&self) -> usize {
-        unsafe { (*self.tree.get()).size() }
-    }
-}
-
 #[test]
 fn creation() {
     let mut tree = Tree::new(1);
@@ -798,60 +569,6 @@ fn deletion() {
     assert_eq!(tree.children_ids(parent).unwrap(), &[]);
 }
 
-#[test]
-fn shared_view() {
-    use std::thread;
-    let mut tree = Tree::new(1);
-    let parent = tree.root();
-    let child = tree.create_node(0);
-    tree.add_child(parent, child);
-
-    let shared = SharedView::new(&mut tree);
-
-    thread::scope(|s| {
-        let (mut shared1, mut shared2, mut shared3) =
-            (shared.clone(), shared.clone(), shared.clone());
-        s.spawn(move || {
-            assert_eq!(*shared1.get_mut(parent).unwrap(), 1);
-            assert_eq!(*shared1.get_mut(child).unwrap(), 0);
-        });
-        s.spawn(move || {
-            assert_eq!(*shared2.get_mut(child).unwrap(), 0);
-            assert_eq!(*shared2.get_mut(parent).unwrap(), 1);
-        });
-        s.spawn(move || {
-            assert_eq!(*shared3.get_mut(parent).unwrap(), 1);
-            assert_eq!(*shared3.get_mut(child).unwrap(), 0);
-        });
-    });
-}
-
-#[test]
-fn map() {
-    #[derive(Debug, PartialEq)]
-    struct Value {
-        value: i32,
-    }
-    impl Value {
-        fn new(value: i32) -> Self {
-            Self { value }
-        }
-    }
-
-    let mut tree = Tree::new(Value::new(1));
-    let parent = tree.root();
-    let child = tree.create_node(Value::new(0));
-    tree.add_child(parent, child);
-
-    let mut mapped = tree.map(|x| &x.value, |x| &mut x.value);
-
-    *mapped.get_mut(child).unwrap() = 1;
-    *mapped.get_mut(parent).unwrap() = 2;
-
-    assert_eq!(*tree.get(parent).unwrap(), Value::new(2));
-    assert_eq!(*tree.get(child).unwrap(), Value::new(1));
-}
-
 #[test]
 fn traverse_depth_first() {
     let mut tree = Tree::new(0);

+ 35 - 34
packages/native-core/src/utils/persistant_iterator.rs

@@ -1,10 +1,10 @@
 use crate::{
-    node::NodeType,
+    node::{ElementNode, NodeType},
     passes::{AnyMapLike, TypeErasedPass},
     real_dom::RealDom,
     state::State,
     tree::TreeView,
-    NodeId, RealNodeId,
+    NodeId,
 };
 use dioxus_core::{Mutation, Mutations};
 use std::fmt::Debug;
@@ -12,12 +12,12 @@ use std::fmt::Debug;
 #[derive(Debug)]
 pub enum ElementProduced {
     /// The iterator produced an element by progressing to the next node in a depth first order.
-    Progressed(RealNodeId),
+    Progressed(NodeId),
     /// The iterator reached the end of the tree and looped back to the root
-    Looped(RealNodeId),
+    Looped(NodeId),
 }
 impl ElementProduced {
-    pub fn id(&self) -> RealNodeId {
+    pub fn id(&self) -> NodeId {
         match self {
             ElementProduced::Progressed(id) => *id,
             ElementProduced::Looped(id) => *id,
@@ -56,7 +56,7 @@ impl NodePosition {
 /// The iterator loops around when it reaches the end or the beginning.
 pub struct PersistantElementIter {
     // stack of elements and fragments
-    stack: smallvec::SmallVec<[(RealNodeId, NodePosition); 5]>,
+    stack: smallvec::SmallVec<[(NodeId, NodePosition); 5]>,
 }
 
 impl Default for PersistantElementIter {
@@ -141,7 +141,7 @@ impl PersistantElementIter {
             let (last, old_child_idx) = self.stack.last_mut().unwrap();
             let node = &rdom[*last];
             match &node.node_data.node_type {
-                NodeType::Element { .. } => {
+                NodeType::Element(ElementNode { .. }) => {
                     let children = rdom.tree.children_ids(*last).unwrap();
                     *old_child_idx = old_child_idx.map(|i| i + 1);
                     // if we have children, go to the next child
@@ -151,7 +151,8 @@ impl PersistantElementIter {
                         self.next(rdom)
                     } else {
                         let id = children[child_idx];
-                        if let NodeType::Element { .. } = &rdom[id].node_data.node_type {
+                        if let NodeType::Element(ElementNode { .. }) = &rdom[id].node_data.node_type
+                        {
                             self.stack.push((id, NodePosition::AtNode));
                         }
                         ElementProduced::Progressed(id)
@@ -170,12 +171,12 @@ impl PersistantElementIter {
     pub fn prev<S: State + Send>(&mut self, rdom: &RealDom<S>) -> ElementProduced {
         // recursively add the last child element to the stack
         fn push_back<S: State + Send>(
-            stack: &mut smallvec::SmallVec<[(RealNodeId, NodePosition); 5]>,
-            new_node: RealNodeId,
+            stack: &mut smallvec::SmallVec<[(NodeId, NodePosition); 5]>,
+            new_node: NodeId,
             rdom: &RealDom<S>,
-        ) -> RealNodeId {
+        ) -> NodeId {
             match &rdom[new_node].node_data.node_type {
-                NodeType::Element { .. } => {
+                NodeType::Element(ElementNode { .. }) => {
                     let children = rdom.tree.children_ids(new_node).unwrap();
                     if children.is_empty() {
                         new_node
@@ -194,7 +195,7 @@ impl PersistantElementIter {
             let (last, old_child_idx) = self.stack.last_mut().unwrap();
             let node = &rdom[*last];
             match &node.node_data.node_type {
-                NodeType::Element { .. } => {
+                NodeType::Element(ElementNode { .. }) => {
                     let children = rdom.tree.children_ids(*last).unwrap();
                     // if we have children, go to the next child
                     if let NodePosition::InChild(0) = old_child_idx {
@@ -228,7 +229,7 @@ impl PersistantElementIter {
         }
     }
 
-    fn pop(&mut self) -> RealNodeId {
+    fn pop(&mut self) -> NodeId {
         self.stack.pop().unwrap().0
     }
 }
@@ -280,68 +281,68 @@ fn traverse() {
     let div_tag = "div".to_string();
     assert!(matches!(
         &rdom[iter.next(&rdom).id()].node_data.node_type,
-        NodeType::Element { tag: div_tag, .. }
+        NodeType::Element(ElementNode { tag: div_tag, .. })
     ));
     assert!(matches!(
         &rdom[iter.next(&rdom).id()].node_data.node_type,
-        NodeType::Element { tag: div_tag, .. }
+        NodeType::Element(ElementNode { tag: div_tag, .. })
     ));
     let text1 = "hello".to_string();
     assert!(matches!(
         &rdom[iter.next(&rdom).id()].node_data.node_type,
-        NodeType::Text { text: text1, .. }
+        NodeType::Text(text1)
     ));
     let p_tag = "p".to_string();
     assert!(matches!(
         &rdom[iter.next(&rdom).id()].node_data.node_type,
-        NodeType::Element { tag: p_tag, .. }
+        NodeType::Element(ElementNode { tag: p_tag, .. })
     ));
     let text2 = "world".to_string();
     assert!(matches!(
         &rdom[iter.next(&rdom).id()].node_data.node_type,
-        NodeType::Text { text: text2, .. }
+        NodeType::Text(text2)
     ));
     let text3 = "hello world".to_string();
     assert!(matches!(
         &rdom[iter.next(&rdom).id()].node_data.node_type,
-        NodeType::Text { text: text3, .. }
+        NodeType::Text(text3)
     ));
     assert!(matches!(
         &rdom[iter.next(&rdom).id()].node_data.node_type,
-        NodeType::Element { tag: div_tag, .. }
+        NodeType::Element(ElementNode { tag: div_tag, .. })
     ));
 
     assert!(matches!(
         &rdom[iter.prev(&rdom).id()].node_data.node_type,
-        NodeType::Text { text: text3, .. }
+        NodeType::Text(text3)
     ));
     assert!(matches!(
         &rdom[iter.prev(&rdom).id()].node_data.node_type,
-        NodeType::Text { text: text2, .. }
+        NodeType::Text(text2)
     ));
     assert!(matches!(
         &rdom[iter.prev(&rdom).id()].node_data.node_type,
-        NodeType::Element { tag: p_tag, .. }
+        NodeType::Element(ElementNode { tag: p_tag, .. })
     ));
     assert!(matches!(
         &rdom[iter.prev(&rdom).id()].node_data.node_type,
-        NodeType::Text { text: text1, .. }
+        NodeType::Text(text1)
     ));
     assert!(matches!(
         &rdom[iter.prev(&rdom).id()].node_data.node_type,
-        NodeType::Element { tag: div_tag, .. }
+        NodeType::Element(ElementNode { tag: div_tag, .. })
     ));
     assert!(matches!(
         &rdom[iter.prev(&rdom).id()].node_data.node_type,
-        NodeType::Element { tag: div_tag, .. }
+        NodeType::Element(ElementNode { tag: div_tag, .. })
     ));
     assert!(matches!(
         &rdom[iter.prev(&rdom).id()].node_data.node_type,
-        NodeType::Element { tag: div_tag, .. }
+        NodeType::Element(ElementNode { tag: div_tag, .. })
     ));
     assert!(matches!(
         &rdom[iter.prev(&rdom).id()].node_data.node_type,
-        NodeType::Text { text: text3, .. }
+        NodeType::Text(text3)
     ));
 }
 
@@ -416,14 +417,14 @@ fn persist_removes() {
     dbg!(&rdom[idx].node_data.node_type);
     assert!(matches!(
         &rdom[idx].node_data.node_type,
-        NodeType::Element { tag: root_tag, .. }
+        NodeType::Element(ElementNode { tag: root_tag, .. })
     ));
 
     let idx = iter2.next(&rdom).id();
     dbg!(&rdom[idx].node_data.node_type);
     assert!(matches!(
         &rdom[idx].node_data.node_type,
-        NodeType::Element { tag: root_tag, .. }
+        NodeType::Element(ElementNode { tag: root_tag, .. })
     ));
 }
 
@@ -479,7 +480,7 @@ fn persist_instertions_before() {
     let idx = iter.next(&rdom).id();
     assert!(matches!(
         &rdom[idx].node_data.node_type,
-        NodeType::Element { tag: p_tag, .. }
+        NodeType::Element(ElementNode { tag: p_tag, .. })
     ));
 }
 
@@ -534,12 +535,12 @@ fn persist_instertions_after() {
     let idx = iter.next(&rdom).id();
     assert!(matches!(
         &rdom[idx].node_data.node_type,
-        NodeType::Element { tag: p_tag, .. }
+        NodeType::Element(ElementNode { tag: p_tag, .. })
     ));
     let text = "hello world".to_string();
     let idx = iter.next(&rdom).id();
     assert!(matches!(
         &rdom[idx].node_data.node_type,
-        NodeType::Text { text, .. }
+        NodeType::Text(text)
     ));
 }

+ 4 - 8
packages/tui/src/focus.rs

@@ -3,7 +3,7 @@ use crate::{node::PreventDefault, TuiDom};
 use dioxus_native_core::{
     tree::TreeView,
     utils::{ElementProduced, PersistantElementIter},
-    RealNodeId,
+    NodeId,
 };
 use dioxus_native_core_macro::sorted_str_slice;
 
@@ -120,7 +120,7 @@ const FOCUS_ATTRIBUTES: &[&str] = &sorted_str_slice!(["tabindex"]);
 #[derive(Default)]
 pub(crate) struct FocusState {
     pub(crate) focus_iter: PersistantElementIter,
-    pub(crate) last_focused_id: Option<RealNodeId>,
+    pub(crate) last_focused_id: Option<NodeId>,
     pub(crate) focus_level: FocusLevel,
     pub(crate) dirty: bool,
 }
@@ -236,11 +236,7 @@ impl FocusState {
     }
 
     pub(crate) fn prune(&mut self, mutations: &dioxus_core::Mutations, rdom: &TuiDom) {
-        fn remove_children(
-            to_prune: &mut [&mut Option<RealNodeId>],
-            rdom: &TuiDom,
-            removed: RealNodeId,
-        ) {
+        fn remove_children(to_prune: &mut [&mut Option<NodeId>], rdom: &TuiDom, removed: NodeId) {
             for opt in to_prune.iter_mut() {
                 if let Some(id) = opt {
                     if *id == removed {
@@ -274,7 +270,7 @@ impl FocusState {
         }
     }
 
-    pub(crate) fn set_focus(&mut self, rdom: &mut TuiDom, id: RealNodeId) {
+    pub(crate) fn set_focus(&mut self, rdom: &mut TuiDom, id: NodeId) {
         if let Some(old) = self.last_focused_id.replace(id) {
             rdom[old].state.focused = false;
         }