瀏覽代碼

create a way to create states

Evan Almloff 2 年之前
父節點
當前提交
0058c7ed32

+ 49 - 17
packages/native-core/src/passes.rs

@@ -9,7 +9,7 @@ use std::sync::Arc;
 use crate::node::{FromAnyValue, NodeData};
 use crate::node_ref::{NodeMaskBuilder, NodeView};
 use crate::real_dom::RealDom;
-use crate::tree::TreeStateView;
+use crate::tree::{SlabEntry, Tree, TreeStateView};
 use crate::{FxDashMap, FxDashSet, SendAnyMap};
 use crate::{NodeId, NodeMask};
 
@@ -76,12 +76,16 @@ impl DirtyNodeStates {
         let (&height, values) = dirty_read
             .iter()
             .find(|(_, values)| values.contains_key(&pass_id))?;
-        let mut dirty = values.get_mut(&pass_id)?;
-        let node_id = dirty.pop()?;
-        if dirty.is_empty() {
-            values.remove(&pass_id);
-        }
+        let node_id = {
+            let mut dirty = values.get_mut(&pass_id)?;
+            let node_id = dirty.pop()?;
+            if dirty.is_empty() {
+                values.remove(&pass_id);
+            }
+            node_id
+        };
         if values.is_empty() {
+            drop(dirty_read);
             let mut dirty_write = self.dirty.write();
             dirty_write.remove(&height);
         }
@@ -127,6 +131,14 @@ pub trait Pass<V: FromAnyValue + Send + Sync = ()>: Any + Send + Sync {
         context: &SendAnyMap,
     ) -> bool;
 
+    fn create<'a>(
+        node_view: NodeView<V>,
+        node: <Self::NodeDependencies as Dependancy>::ElementBorrowed<'a>,
+        parent: Option<<Self::ParentDependencies as Dependancy>::ElementBorrowed<'a>>,
+        children: Option<Vec<<Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>>,
+        context: &SendAnyMap,
+    ) -> Self;
+
     fn validate() {
         // no type can be a child and parent dependency
         for type_id in Self::parent_type_ids().iter().copied() {
@@ -172,24 +184,38 @@ pub trait Pass<V: FromAnyValue + Send + Sync = ()>: Any + Send + Sync {
                     debug_assert!(!Self::NodeDependencies::type_ids()
                         .iter()
                         .any(|id| *id == TypeId::of::<Self>()));
+                    println!("passing: {node_id:?}");
                     // get all of the states from the tree view
                     // Safety: No node has itself as a parent or child.
-                    let node_raw = tree.get_mut::<Self>(node_id).unwrap() as *mut Self;
+                    let myself: SlabEntry<'static, Self> = unsafe {
+                        std::mem::transmute(tree.get_slab_mut::<Self>().unwrap().entry(node_id))
+                    };
                     let node_data = tree.get_single::<NodeData<V>>(node_id).unwrap();
                     let node = tree.get::<Self::NodeDependencies>(node_id).unwrap();
                     let children = tree.children::<Self::ChildDependencies>(node_id);
                     let parent = tree.parent::<Self::ParentDependencies>(node_id);
-                    let myself = unsafe { &mut *node_raw };
-
-                    myself.pass(
-                        NodeView::new(node_data, Self::NODE_MASK.build()),
-                        node,
-                        parent,
-                        children,
-                        context,
-                    )
+
+                    if myself.value.is_none() {
+                        *myself.value = Some(Self::create(
+                            NodeView::new(node_data, Self::NODE_MASK.build()),
+                            node,
+                            parent,
+                            children,
+                            context,
+                        ));
+                        true
+                    } else {
+                        myself.value.as_mut().unwrap().pass(
+                            NodeView::new(node_data, Self::NODE_MASK.build()),
+                            node,
+                            parent,
+                            children,
+                            context,
+                        )
+                    }
                 },
             ) as PassCallback,
+            create: Box::new(|tree: &mut Tree| tree.insert_slab::<Self>()) as CreatePassCallback,
             phantom: PhantomData,
         }
     }
@@ -238,6 +264,7 @@ pub struct TypeErasedPass<V: FromAnyValue + Send = ()> {
     pub(crate) dependants: FxHashSet<TypeId>,
     pub(crate) mask: NodeMask,
     pass: PassCallback,
+    pub(crate) create: CreatePassCallback,
     pub(crate) pass_direction: PassDirection,
     phantom: PhantomData<V>,
 }
@@ -297,6 +324,7 @@ pub enum PassDirection {
 }
 
 type PassCallback = Box<dyn Fn(NodeId, &mut TreeStateView, &SendAnyMap) -> bool + Send + Sync>;
+type CreatePassCallback = Box<dyn Fn(&mut Tree) + Send + Sync>;
 
 pub trait AnyMapLike<'a> {
     fn get<T: Any + Sync + Send>(self) -> Option<&'a T>;
@@ -388,7 +416,11 @@ pub fn resolve_passes<V: FromAnyValue + Send + Sync>(
                     resolving.push(pass_id);
                     currently_in_use.insert(pass.this_type_id);
                     let tree_view = dynamically_borrowed_tree.view(
-                        pass.combined_dependancy_type_ids.iter().copied(),
+                        pass.combined_dependancy_type_ids
+                            .iter()
+                            .filter(|id| **id != pass.this_type_id)
+                            .copied()
+                            .chain(std::iter::once(TypeId::of::<NodeData<V>>())),
                         [pass.this_type_id],
                     );
                     let dirty_nodes = dirty_nodes.clone();

+ 50 - 58
packages/native-core/src/real_dom.rs

@@ -1,7 +1,7 @@
 use dioxus_core::{BorrowedAttributeValue, ElementId, Mutations, TemplateNode};
 
 use rustc_hash::{FxHashMap, FxHashSet};
-use std::any::Any;
+use std::any::{Any, TypeId};
 use std::collections::VecDeque;
 
 use crate::node::{
@@ -26,11 +26,8 @@ pub struct RealDom<V: FromAnyValue + Send + Sync = ()> {
     stack: Vec<NodeId>,
     templates: FxHashMap<String, Vec<NodeId>>,
     pub(crate) passes: Box<[TypeErasedPass<V>]>,
-    pub(crate) nodes_updated: FxHashMap<NodeId, NodeMask>,
-    passes_updated: DirtyNodeStates,
-    parent_changed_nodes: FxHashSet<NodeId>,
-    child_changed_nodes: FxHashSet<NodeId>,
-    nodes_created: FxHashSet<NodeId>,
+    passes_updated: FxHashMap<NodeId, FxHashSet<TypeId>>,
+    nodes_updated: FxHashMap<NodeId, NodeMask>,
     phantom: std::marker::PhantomData<V>,
 }
 
@@ -38,8 +35,10 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
     pub fn new(mut passes: Box<[TypeErasedPass<V>]>) -> RealDom<V> {
         let mut tree = Tree::new();
         tree.insert_slab::<NodeData<V>>();
+        for pass in passes.iter() {
+            (pass.create)(&mut tree);
+        }
         let root_id = tree.root();
-        let root: &mut NodeData<V> = tree.get_mut(root_id).unwrap();
         let mut root_node: NodeData<V> = NodeData::new(NodeType::Element(ElementNode {
             tag: "Root".to_string(),
             namespace: Some("Root".to_string()),
@@ -48,7 +47,7 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
         }));
         root_node.element_id = Some(ElementId(0));
         root_node.node_id = root_id;
-        *root = root_node;
+        tree.insert(root_id, root_node);
 
         // resolve dependants for each pass
         for i in 1..passes.len() {
@@ -63,8 +62,11 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
             }
         }
 
+        let mut passes_updated = FxHashMap::default();
         let mut nodes_updated = FxHashMap::default();
+
         let root_id = NodeId(0);
+        passes_updated.insert(root_id, passes.iter().map(|x| x.this_type_id).collect());
         nodes_updated.insert(root_id, NodeMaskBuilder::ALL.build());
 
         RealDom {
@@ -74,21 +76,42 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
             stack: vec![root_id],
             templates: FxHashMap::default(),
             passes,
+            passes_updated,
             nodes_updated,
-            passes_updated: DirtyNodeStates::default(),
-            parent_changed_nodes: FxHashSet::default(),
-            child_changed_nodes: FxHashSet::default(),
-            nodes_created: FxHashSet::default(),
             phantom: std::marker::PhantomData,
         }
     }
 
+    fn mark_dirty(&mut self, node_id: NodeId, mask: NodeMask) {
+        self.passes_updated.entry(node_id).or_default().extend(
+            self.passes
+                .iter()
+                .filter_map(|x| x.mask.overlaps(&mask).then_some(x.this_type_id)),
+        );
+        let nodes_updated = &mut self.nodes_updated;
+        if let Some(node) = nodes_updated.get_mut(&node_id) {
+            *node = node.union(&mask);
+        } else {
+            nodes_updated.insert(node_id, mask);
+        }
+    }
+
     fn mark_parent_added_or_removed(&mut self, node_id: NodeId) {
-        self.parent_changed_nodes.insert(node_id);
+        let hm = self.passes_updated.entry(node_id).or_default();
+        for pass in &*self.passes {
+            if pass.parent_dependant {
+                hm.insert(pass.this_type_id);
+            }
+        }
     }
 
     fn mark_child_changed(&mut self, node_id: NodeId) {
-        self.child_changed_nodes.insert(node_id);
+        let hm = self.passes_updated.entry(node_id).or_default();
+        for pass in &*self.passes {
+            if pass.child_dependant {
+                hm.insert(pass.this_type_id);
+            }
+        }
     }
 
     pub fn element_to_node_id(&self, element_id: ElementId) -> NodeId {
@@ -121,12 +144,15 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
     ) -> EntryBuilder<'_> {
         let mut node_entry = self.tree.create_node();
         let node_id = node_entry.id();
+        if mark_dirty {
+            self.passes_updated
+                .entry(node_id)
+                .or_default()
+                .extend(self.passes.iter().map(|x| x.this_type_id));
+        }
         node.node_id = node_id;
         node.element_id = id;
         node_entry.insert(node);
-        if mark_dirty {
-            self.nodes_created.insert(node_id);
-        }
         node_entry
     }
 
@@ -414,43 +440,14 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
         &mut self,
         ctx: SendAnyMap,
     ) -> (FxDashSet<NodeId>, FxHashMap<NodeId, NodeMask>) {
-        let dirty_nodes = std::mem::take(&mut self.passes_updated);
+        let passes = std::mem::take(&mut self.passes_updated);
         let nodes_updated = std::mem::take(&mut self.nodes_updated);
-        for (&node, mask) in &nodes_updated {
-            // remove any nodes that were created and then removed in the same mutations from the dirty nodes list
-            if let Some(height) = self.tree.height(node) {
-                for pass in &*self.passes {
-                    if mask.overlaps(&pass.mask) {
-                        dirty_nodes.insert(pass.this_type_id, node, height);
-                    }
-                }
-            }
-        }
-        for node in std::mem::take(&mut self.child_changed_nodes) {
-            // remove any nodes that were created and then removed in the same mutations from the dirty nodes list
-            if let Some(height) = self.tree.height(node) {
-                for pass in &*self.passes {
-                    if pass.child_dependant {
-                        dirty_nodes.insert(pass.this_type_id, node, height);
-                    }
-                }
-            }
-        }
-        for node in std::mem::take(&mut self.parent_changed_nodes) {
+        let dirty_nodes = DirtyNodeStates::default();
+        for (node_id, passes) in passes {
             // remove any nodes that were created and then removed in the same mutations from the dirty nodes list
-            if let Some(height) = self.tree.height(node) {
-                for pass in &*self.passes {
-                    if pass.parent_dependant {
-                        dirty_nodes.insert(pass.this_type_id, node, height);
-                    }
-                }
-            }
-        }
-        for node in std::mem::take(&mut self.nodes_created) {
-            // remove any nodes that were created and then removed in the same mutations from the dirty nodes list
-            if let Some(height) = self.tree.height(node) {
-                for pass in &*self.passes {
-                    dirty_nodes.insert(pass.this_type_id, node, height);
+            if let Some(height) = self.tree.height(node_id) {
+                for pass in passes {
+                    dirty_nodes.insert(pass, node_id, height);
                 }
             }
         }
@@ -681,12 +678,7 @@ impl<V: FromAnyValue + Send + Sync> Drop for NodeMut<'_, V> {
     fn drop(&mut self) {
         let node_id = self.node_data().node_id;
         let mask = std::mem::take(&mut self.dirty);
-        let nodes_updated = &mut self.dom.nodes_updated;
-        if let Some(node) = nodes_updated.get_mut(&node_id) {
-            *node = node.union(&mask);
-        } else {
-            nodes_updated.insert(node_id, mask);
-        }
+        self.dom.mark_dirty(node_id, mask);
     }
 }
 

+ 40 - 3
packages/native-core/src/tree.rs

@@ -176,6 +176,10 @@ impl Tree {
         self.nodes.write_slab().get_mut(id)
     }
 
+    pub fn insert<T: Any + Sync + Send>(&mut self, id: NodeId, value: T) {
+        self.nodes.write_slab().insert(id, value);
+    }
+
     pub fn contains(&self, id: NodeId) -> bool {
         self.nodes.contains(id)
     }
@@ -210,9 +214,11 @@ impl<'a> DynamicallyBorrowedTree<'a> {
         let nodes_data = self.node_slab();
         let mut nodes = FxHashMap::default();
         for id in immutable {
+            println!("reading {id:?}");
             nodes.insert(id, MaybeRead::Read(self.nodes.get_slab(id).unwrap()));
         }
         for id in mutable {
+            println!("writing {id:?}");
             nodes.insert(id, MaybeRead::Write(self.nodes.get_slab_mut(id).unwrap()));
         }
 
@@ -249,7 +255,7 @@ pub struct TreeStateView<'a, 'b> {
 }
 
 impl<'a, 'b> TreeStateView<'a, 'b> {
-    fn get_slab<T: Any + Sync + Send>(&self) -> Option<&SlabStorage<T>> {
+    pub fn get_slab<T: Any + Sync + Send>(&self) -> Option<&SlabStorage<T>> {
         self.nodes
             .get(&TypeId::of::<T>())
             .and_then(|gaurd| match gaurd {
@@ -258,7 +264,7 @@ impl<'a, 'b> TreeStateView<'a, 'b> {
             })
     }
 
-    fn get_slab_mut<T: Any + Sync + Send>(&mut self) -> Option<&mut SlabStorage<T>> {
+    pub fn get_slab_mut<T: Any + Sync + Send>(&mut self) -> Option<&mut SlabStorage<T>> {
         self.nodes
             .get_mut(&TypeId::of::<T>())
             .and_then(|gaurd| match gaurd {
@@ -442,7 +448,7 @@ fn deletion() {
 }
 
 #[derive(Debug)]
-pub(crate) struct SlabStorage<T> {
+pub struct SlabStorage<T> {
     data: Vec<Option<T>>,
 }
 
@@ -467,6 +473,16 @@ impl<T> SlabStorage<T> {
         self.data.get_mut(id.0).and_then(|x| x.as_mut())
     }
 
+    pub fn entry(&mut self, id: NodeId) -> SlabEntry<'_, T> {
+        let idx = id.0;
+        if idx >= self.data.len() {
+            self.data.resize_with(idx + 1, || None);
+        }
+        SlabEntry {
+            value: &mut self.data[idx],
+        }
+    }
+
     fn insert(&mut self, id: NodeId, value: T) {
         let idx = id.0;
         if idx >= self.data.len() {
@@ -476,6 +492,27 @@ impl<T> SlabStorage<T> {
     }
 }
 
+pub struct SlabEntry<'a, T> {
+    pub value: &'a mut Option<T>,
+}
+
+impl<'a, T> SlabEntry<'a, T> {
+    pub fn or_insert_with<F: FnOnce() -> T>(self, f: F) -> &'a mut T {
+        self.value.get_or_insert_with(f)
+    }
+
+    pub fn or_insert(self, value: T) -> &'a mut T {
+        self.value.get_or_insert(value)
+    }
+
+    pub fn or_default(self) -> &'a mut T
+    where
+        T: Default,
+    {
+        self.value.get_or_insert_with(Default::default)
+    }
+}
+
 impl<T: 'static + Send + Sync> AnySlabStorageImpl for SlabStorage<T> {
     fn remove(&mut self, id: NodeId) {
         self.data[id.0].take();

+ 12 - 0
packages/tui/src/focus.rs

@@ -121,6 +121,18 @@ impl Pass for Focus {
             false
         }
     }
+
+    fn create<'a>(
+        node_view: NodeView<()>,
+        node: <Self::NodeDependencies as Dependancy>::ElementBorrowed<'a>,
+        parent: Option<<Self::ParentDependencies as Dependancy>::ElementBorrowed<'a>>,
+        children: Option<Vec<<Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>>,
+        context: &SendAnyMap,
+    ) -> Self {
+        let mut myself = Self::default();
+        myself.pass(node_view, node, parent, children, context);
+        myself
+    }
 }
 
 const FOCUS_EVENTS: &[&str] = &["keydown", "keypress", "keyup"];

+ 12 - 0
packages/tui/src/layout.rs

@@ -192,6 +192,18 @@ impl Pass for TaffyLayout {
         }
         changed
     }
+
+    fn create<'a>(
+        node_view: NodeView<()>,
+        node: <Self::NodeDependencies as Dependancy>::ElementBorrowed<'a>,
+        parent: Option<<Self::ParentDependencies as Dependancy>::ElementBorrowed<'a>>,
+        children: Option<Vec<<Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>>,
+        context: &SendAnyMap,
+    ) -> Self {
+        let mut myself = Self::default();
+        myself.pass(node_view, node, parent, children, context);
+        myself
+    }
 }
 
 // these are the attributes in layout_attiributes in native-core

+ 12 - 0
packages/tui/src/prevent_default.rs

@@ -73,4 +73,16 @@ impl Pass for PreventDefault {
             true
         }
     }
+
+    fn create<'a>(
+        node_view: NodeView<()>,
+        node: <Self::NodeDependencies as Dependancy>::ElementBorrowed<'a>,
+        parent: Option<<Self::ParentDependencies as Dependancy>::ElementBorrowed<'a>>,
+        children: Option<Vec<<Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>>,
+        context: &SendAnyMap,
+    ) -> Self {
+        let mut myself = Self::default();
+        myself.pass(node_view, node, parent, children, context);
+        myself
+    }
 }

+ 12 - 0
packages/tui/src/style_attributes.rs

@@ -112,6 +112,18 @@ impl Pass for StyleModifier {
             false
         }
     }
+
+    fn create<'a>(
+        node_view: NodeView<()>,
+        node: <Self::NodeDependencies as Dependancy>::ElementBorrowed<'a>,
+        parent: Option<<Self::ParentDependencies as Dependancy>::ElementBorrowed<'a>>,
+        children: Option<Vec<<Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>>,
+        context: &SendAnyMap,
+    ) -> Self {
+        let mut myself = Self::default();
+        myself.pass(node_view, node, parent, children, context);
+        myself
+    }
 }
 
 #[derive(Default, Clone, PartialEq, Debug)]