diff --git a/packages/native-core/Cargo.toml b/packages/native-core/Cargo.toml index ee2a3b912..2e748563c 100644 --- a/packages/native-core/Cargo.toml +++ b/packages/native-core/Cargo.toml @@ -36,5 +36,5 @@ tokio = { version = "*", features = ["full"] } dioxus-native-core = { path = ".", features = ["dioxus"] } [features] -default = ["dioxus"] +default = [] dioxus = ["dioxus-core"] \ No newline at end of file diff --git a/packages/native-core/src/dioxus.rs b/packages/native-core/src/dioxus.rs index 6170be0d2..8d67d9e2c 100644 --- a/packages/native-core/src/dioxus.rs +++ b/packages/native-core/src/dioxus.rs @@ -15,7 +15,7 @@ pub struct DioxusState { } impl DioxusState { - pub fn new(rdom: &mut RealDom) -> Self { + pub fn create(rdom: &mut RealDom) -> Self { rdom.insert_slab::(); let root_id = rdom.root_id(); let mut root = rdom.get_mut(root_id).unwrap(); diff --git a/packages/native-core/src/node_ref.rs b/packages/native-core/src/node_ref.rs index d8fc309be..99b4c53e2 100644 --- a/packages/native-core/src/node_ref.rs +++ b/packages/native-core/src/node_ref.rs @@ -203,12 +203,12 @@ impl NodeMask { } #[derive(PartialEq, Eq, Clone, Debug)] -pub enum AttributeMaskBuilder { +pub enum AttributeMaskBuilder<'a> { All, - Some(&'static [&'static str]), + Some(&'a [&'a str]), } -impl Default for AttributeMaskBuilder { +impl Default for AttributeMaskBuilder<'_> { fn default() -> Self { AttributeMaskBuilder::Some(&[]) } @@ -216,15 +216,15 @@ impl Default for AttributeMaskBuilder { /// A mask that limits what parts of a node a dependency can see. #[derive(Default, PartialEq, Eq, Clone, Debug)] -pub struct NodeMaskBuilder { - attritutes: AttributeMaskBuilder, +pub struct NodeMaskBuilder<'a> { + attritutes: AttributeMaskBuilder<'a>, tag: bool, namespace: bool, text: bool, listeners: bool, } -impl NodeMaskBuilder { +impl<'a> NodeMaskBuilder<'a> { /// A node mask with no parts visible. pub const NONE: Self = Self::new(); /// A node mask with every part visible. @@ -246,7 +246,7 @@ impl NodeMaskBuilder { } /// Allow the mask to view the given attributes - pub const fn with_attrs(mut self, attritutes: AttributeMaskBuilder) -> Self { + pub const fn with_attrs(mut self, attritutes: AttributeMaskBuilder<'a>) -> Self { self.attritutes = attritutes; self } diff --git a/packages/native-core/src/passes.rs b/packages/native-core/src/passes.rs index f5a66aaad..86059508a 100644 --- a/packages/native-core/src/passes.rs +++ b/packages/native-core/src/passes.rs @@ -64,14 +64,15 @@ impl DirtyNodeStates { } pub fn insert(&self, pass_id: TypeId, node_id: NodeId, height: u16) { - let btree = self.dirty.get(&pass_id).unwrap(); - let mut write = btree.write(); - if let Some(entry) = write.get_mut(&height) { - entry.add_node(node_id); - } else { - let mut entry = DirtyNodes::default(); - entry.add_node(node_id); - write.insert(height, entry); + if let Some(btree) = self.dirty.get(&pass_id) { + let mut write = btree.write(); + if let Some(entry) = write.get_mut(&height) { + entry.add_node(node_id); + } else { + let mut entry = DirtyNodes::default(); + entry.add_node(node_id); + write.insert(height, entry); + } } } @@ -109,7 +110,7 @@ pub trait Pass: Any + Send + Sync { type ChildDependencies: Dependancy; /// This is a tuple of (T: Any, ..) type NodeDependencies: Dependancy; - const NODE_MASK: NodeMaskBuilder; + const NODE_MASK: NodeMaskBuilder<'static>; fn pass<'a>( &mut self, @@ -137,12 +138,12 @@ pub trait Pass: Any + Send + Sync { } // this type cannot be both a parent and child dependency assert!( - Self::parent_type_ids() + !(Self::parent_type_ids() .iter() - .any(|type_id| *type_id != TypeId::of::()) + .any(|type_id| *type_id == TypeId::of::()) && Self::child_type_ids() .iter() - .any(|type_id| *type_id != TypeId::of::()), + .any(|type_id| *type_id == TypeId::of::())), "The current type cannot be a parent and child dependency" ); // no states have the same type id diff --git a/packages/native-core/src/real_dom.rs b/packages/native-core/src/real_dom.rs index bb7d1ec99..8cc4d29de 100644 --- a/packages/native-core/src/real_dom.rs +++ b/packages/native-core/src/real_dom.rs @@ -1,15 +1,57 @@ use rustc_hash::{FxHashMap, FxHashSet}; use std::any::{Any, TypeId}; use std::collections::VecDeque; +use std::rc::Rc; use crate::node::{ ElementNode, FromAnyValue, NodeType, OwnedAttributeDiscription, OwnedAttributeValue, }; -use crate::node_ref::{AttributeMask, NodeMask, NodeMaskBuilder}; +use crate::node_ref::{NodeMask, NodeMaskBuilder}; use crate::passes::{resolve_passes, DirtyNodeStates, TypeErasedPass}; +use crate::prelude::AttributeMaskBuilder; use crate::tree::{NodeId, Tree}; use crate::{FxDashSet, SendAnyMap}; +struct NodesDirty { + passes_updated: FxHashMap>, + nodes_updated: FxHashMap, + passes: Rc]>>, +} + +impl NodesDirty { + 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) { + 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) { + 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); + } + } + } +} + /// 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. /// To get started implement [crate::state::ParentDepState], [crate::state::NodeDepState], or [crate::state::ChildDepState] and call [RealDom::apply_mutations] to update the dom and [RealDom::update_state] to update the state of the nodes. @@ -19,9 +61,8 @@ use crate::{FxDashSet, SendAnyMap}; pub struct RealDom { pub(crate) tree: Tree, nodes_listening: FxHashMap>, - pub(crate) passes: Box<[TypeErasedPass]>, - passes_updated: FxHashMap>, - nodes_updated: FxHashMap, + pub(crate) passes: Rc]>>, + dirty_nodes: NodesDirty, phantom: std::marker::PhantomData, } @@ -53,6 +94,7 @@ impl RealDom { } } } + let passes = Rc::new(passes); let mut passes_updated = FxHashMap::default(); let mut nodes_updated = FxHashMap::default(); @@ -64,50 +106,22 @@ impl RealDom { RealDom { tree, nodes_listening: FxHashMap::default(), - passes, - passes_updated, - nodes_updated, + passes: passes.clone(), + dirty_nodes: NodesDirty { + passes_updated, + nodes_updated, + passes, + }, 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) { - 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) { - 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 create_node(&mut self, node: NodeType, mark_dirty: bool) -> NodeMut<'_, V> { let mut node_entry = self.tree.create_node(); let id = node_entry.id(); if mark_dirty { - self.passes_updated + self.dirty_nodes + .passes_updated .entry(id) .or_default() .extend(self.passes.iter().map(|x| x.this_type_id)); @@ -186,8 +200,8 @@ impl RealDom { ctx: SendAnyMap, parallel: bool, ) -> (FxDashSet, FxHashMap) { - let passes = std::mem::take(&mut self.passes_updated); - let nodes_updated = std::mem::take(&mut self.nodes_updated); + let passes = std::mem::take(&mut self.dirty_nodes.passes_updated); + let nodes_updated = std::mem::take(&mut self.dirty_nodes.nodes_updated); let dirty_nodes = DirtyNodeStates::with_passes(self.passes.iter().map(|p| p.this_type_id)); for (node_id, passes) in passes { // remove any nodes that were created and then removed in the same mutations from the dirty nodes list @@ -206,15 +220,15 @@ impl RealDom { pub fn remove(&mut self, id: NodeId) { if let Some(parent_id) = self.tree.parent_id(id) { - self.mark_child_changed(parent_id); + self.dirty_nodes.mark_child_changed(parent_id); } self.tree.remove(id) } pub fn replace(&mut self, old: NodeId, new: NodeId) { if let Some(parent_id) = self.tree.parent_id(old) { - self.mark_child_changed(parent_id); - self.mark_parent_added_or_removed(new); + self.dirty_nodes.mark_child_changed(parent_id); + self.dirty_nodes.mark_parent_added_or_removed(new); } self.tree.replace(old, new); } @@ -376,16 +390,11 @@ impl<'a, V: FromAnyValue + Send + Sync> NodeImmutable for NodeRef<'a, V> { pub struct NodeMut<'a, V: FromAnyValue + Send + Sync = ()> { id: NodeId, dom: &'a mut RealDom, - dirty: NodeMask, } impl<'a, V: FromAnyValue + Send + Sync> NodeMut<'a, V> { pub fn new(id: NodeId, dom: &'a mut RealDom) -> Self { - Self { - id, - dom, - dirty: NodeMask::default(), - } + Self { id, dom } } } @@ -407,6 +416,7 @@ impl<'a, V: FromAnyValue + Send + Sync> NodeMutable for NodeMut<'a, V> { fn get_mut(&mut self) -> Option<&mut T> { // mark the node state as dirty self.dom + .dirty_nodes .passes_updated .entry(self.id) .or_default() @@ -417,6 +427,7 @@ impl<'a, V: FromAnyValue + Send + Sync> NodeMutable for NodeMut<'a, V> { fn insert(&mut self, value: T) { // mark the node state as dirty self.dom + .dirty_nodes .passes_updated .entry(self.id) .or_default() @@ -427,8 +438,8 @@ impl<'a, V: FromAnyValue + Send + Sync> NodeMutable for NodeMut<'a, V> { fn insert_after(&mut self, old: NodeId) { let id = self.id(); if let Some(parent_id) = self.dom.tree.parent_id(old) { - self.dom.mark_child_changed(parent_id); - self.dom.mark_parent_added_or_removed(id); + self.dom.dirty_nodes.mark_child_changed(parent_id); + self.dom.dirty_nodes.mark_parent_added_or_removed(id); } self.dom.tree.insert_after(old, id); } @@ -436,16 +447,20 @@ impl<'a, V: FromAnyValue + Send + Sync> NodeMutable for NodeMut<'a, V> { fn insert_before(&mut self, old: NodeId) { let id = self.id(); if let Some(parent_id) = self.dom.tree.parent_id(old) { - self.dom.mark_child_changed(parent_id); - self.dom.mark_parent_added_or_removed(id); + self.dom.dirty_nodes.mark_child_changed(parent_id); + self.dom.dirty_nodes.mark_parent_added_or_removed(id); } self.dom.tree.insert_before(old, id); } fn add_event_listener(&mut self, event: &str) { let id = self.id(); - if let NodeTypeMut::Element(mut element) = self.node_type_mut() { - element.listeners_mut().insert(event.to_string()); + let node_type: &mut NodeType = self.dom.tree.get_mut(self.id).unwrap(); + if let NodeType::Element(ElementNode { listeners, .. }) = node_type { + self.dom + .dirty_nodes + .mark_dirty(self.id, NodeMaskBuilder::new().with_listeners().build()); + listeners.insert(event.to_string()); match self.dom.nodes_listening.get_mut(event) { Some(hs) => { hs.insert(id); @@ -461,21 +476,33 @@ impl<'a, V: FromAnyValue + Send + Sync> NodeMutable for NodeMut<'a, V> { fn remove_event_listener(&mut self, event: &str) { let id = self.id(); - if let NodeTypeMut::Element(mut element) = self.node_type_mut() { - element.listeners_mut().remove(event); + let node_type: &mut NodeType = self.dom.tree.get_mut(self.id).unwrap(); + if let NodeType::Element(ElementNode { listeners, .. }) = node_type { + self.dom + .dirty_nodes + .mark_dirty(self.id, NodeMaskBuilder::new().with_listeners().build()); + listeners.remove(event); + + self.dom.nodes_listening.get_mut(event).unwrap().remove(&id); } - self.dom.nodes_listening.get_mut(event).unwrap().remove(&id); } } impl<'a, V: FromAnyValue + Send + Sync> NodeMut<'a, V> { pub fn node_type_mut(&mut self) -> NodeTypeMut<'_, V> { - let Self { id, dom, dirty } = self; - let node_type = dom.tree.get_mut::>(*id).unwrap(); + let Self { id, dom } = self; + let RealDom { + dirty_nodes, tree, .. + } = dom; + let node_type = tree.get_mut(*id).unwrap(); match node_type { - NodeType::Element(element) => NodeTypeMut::Element(ElementNodeMut { element, dirty }), + NodeType::Element(element) => NodeTypeMut::Element(ElementNodeMut { + id: *id, + element, + dirty_nodes, + }), NodeType::Text(text) => { - dirty.set_text(); + dirty_nodes.mark_dirty(self.id, NodeMaskBuilder::new().with_text().build()); NodeTypeMut::Text(text) } NodeType::Placeholder => NodeTypeMut::Placeholder, @@ -484,35 +511,32 @@ impl<'a, V: FromAnyValue + Send + Sync> NodeMut<'a, V> { pub fn set_type(&mut self, new: NodeType) { *self.dom.tree.get_mut::>(self.id).unwrap() = new; - self.dirty = NodeMaskBuilder::ALL.build(); + self.dom + .dirty_nodes + .mark_dirty(self.id, NodeMaskBuilder::ALL.build()) } } -impl Drop for NodeMut<'_, V> { - fn drop(&mut self) { - let mask = std::mem::take(&mut self.dirty); - self.dom.mark_dirty(self.id, mask); - } -} - -pub enum NodeTypeMut<'a, V: FromAnyValue = ()> { +pub enum NodeTypeMut<'a, V: FromAnyValue + Send + Sync = ()> { Element(ElementNodeMut<'a, V>), Text(&'a mut String), Placeholder, } -pub struct ElementNodeMut<'a, V: FromAnyValue = ()> { +pub struct ElementNodeMut<'a, V: FromAnyValue + Send + Sync = ()> { + id: NodeId, element: &'a mut ElementNode, - dirty: &'a mut NodeMask, + dirty_nodes: &'a mut NodesDirty, } -impl ElementNodeMut<'_, V> { +impl ElementNodeMut<'_, V> { pub fn tag(&self) -> &str { &self.element.tag } pub fn tag_mut(&mut self) -> &mut String { - self.dirty.set_tag(); + self.dirty_nodes + .mark_dirty(self.id, NodeMaskBuilder::new().with_tag().build()); &mut self.element.tag } @@ -521,7 +545,8 @@ impl ElementNodeMut<'_, V> { } pub fn namespace_mut(&mut self) -> &mut Option { - self.dirty.set_namespace(); + self.dirty_nodes + .mark_dirty(self.id, NodeMaskBuilder::new().with_namespace().build()); &mut self.element.namespace } @@ -532,7 +557,12 @@ impl ElementNodeMut<'_, V> { pub fn attributes_mut( &mut self, ) -> &mut FxHashMap> { - self.dirty.add_attributes(AttributeMask::All); + self.dirty_nodes.mark_dirty( + self.id, + NodeMaskBuilder::new() + .with_attrs(AttributeMaskBuilder::All) + .build(), + ); &mut self.element.attributes } @@ -541,7 +571,12 @@ impl ElementNodeMut<'_, V> { name: OwnedAttributeDiscription, value: OwnedAttributeValue, ) -> Option> { - self.dirty.add_attributes(AttributeMask::single(&name.name)); + self.dirty_nodes.mark_dirty( + self.id, + NodeMaskBuilder::new() + .with_attrs(AttributeMaskBuilder::Some(&[&name.name])) + .build(), + ); self.element.attributes.insert(name, value) } @@ -549,7 +584,12 @@ impl ElementNodeMut<'_, V> { &mut self, name: &OwnedAttributeDiscription, ) -> Option> { - self.dirty.add_attributes(AttributeMask::single(&name.name)); + self.dirty_nodes.mark_dirty( + self.id, + NodeMaskBuilder::new() + .with_attrs(AttributeMaskBuilder::Some(&[&name.name])) + .build(), + ); self.element.attributes.remove(name) } @@ -557,18 +597,18 @@ impl ElementNodeMut<'_, V> { &mut self, name: &OwnedAttributeDiscription, ) -> Option<&mut OwnedAttributeValue> { - self.dirty.add_attributes(AttributeMask::single(&name.name)); + self.dirty_nodes.mark_dirty( + self.id, + NodeMaskBuilder::new() + .with_attrs(AttributeMaskBuilder::Some(&[&name.name])) + .build(), + ); self.element.attributes.get_mut(name) } pub fn listeners(&self) -> &FxHashSet { &self.element.listeners } - - pub fn listeners_mut(&mut self) -> &mut FxHashSet { - self.dirty.set_listeners(); - &mut self.element.listeners - } } pub struct NodeMutRaw<'a, V: FromAnyValue + Send + Sync = ()> { diff --git a/packages/native-core/src/tree.rs b/packages/native-core/src/tree.rs index cbb59dab8..390ac42b2 100644 --- a/packages/native-core/src/tree.rs +++ b/packages/native-core/src/tree.rs @@ -249,7 +249,13 @@ pub struct TreeStateViewEntry<'a, 'b> { impl<'a, 'b> AnyMapLike<'a> for TreeStateViewEntry<'a, 'b> { fn get(self) -> Option<&'a T> { - self.view.get_slab().and_then(|slab| slab.get(self.id)) + let slab = self.view.get_slab(); + dbg!(slab.is_some()); + slab.and_then(|slab| { + let r = slab.get(self.id); + dbg!(r.is_some()); + r + }) } } @@ -315,7 +321,7 @@ impl<'a, 'b> TreeStateView<'a, 'b> { } pub fn parent(&self, id: NodeId) -> Option> { - T::borrow_elements_from(self.entry(id)) + T::borrow_elements_from(self.entry(self.parent_id(id)?)) } } diff --git a/packages/native-core/tests/fuzzing.rs b/packages/native-core/tests/fuzzing.rs index a32fb849f..49e9656a8 100644 --- a/packages/native-core/tests/fuzzing.rs +++ b/packages/native-core/tests/fuzzing.rs @@ -1,6 +1,7 @@ use dioxus::prelude::Props; use dioxus_core::*; use dioxus_native_core::{ + dioxus::DioxusState, node_ref::{AttributeMaskBuilder, NodeMaskBuilder, NodeView}, real_dom::RealDom, Dependancy, Pass, SendAnyMap, @@ -302,7 +303,7 @@ impl Pass for BlablaState { type ChildDependencies = (); type NodeDependencies = (); - const NODE_MASK: NodeMaskBuilder = NodeMaskBuilder::new() + const NODE_MASK: NodeMaskBuilder<'static> = NodeMaskBuilder::new() .with_attrs(AttributeMaskBuilder::Some(&["blabla"])) .with_element(); @@ -348,7 +349,8 @@ fn create() { ); let mutations = vdom.rebuild(); let mut rdom: RealDom = RealDom::new(Box::new([BlablaState::to_type_erased()])); - rdom.apply_mutations(mutations); + let mut dioxus_state = DioxusState::create(&mut rdom); + dioxus_state.apply_mutations(&mut rdom, mutations); let ctx = SendAnyMap::new(); rdom.update_state(ctx, false); @@ -369,13 +371,14 @@ fn diff() { ); let mutations = vdom.rebuild(); let mut rdom: RealDom = RealDom::new(Box::new([BlablaState::to_type_erased()])); - rdom.apply_mutations(mutations); + let mut dioxus_state = DioxusState::create(&mut rdom); + dioxus_state.apply_mutations(&mut rdom, mutations); let ctx = SendAnyMap::new(); rdom.update_state(ctx, false); for _ in 0..10 { let mutations = vdom.render_immediate(); - rdom.apply_mutations(mutations); + dioxus_state.apply_mutations(&mut rdom, mutations); let ctx = SendAnyMap::new(); rdom.update_state(ctx, false); diff --git a/packages/native-core/tests/miri_native.rs b/packages/native-core/tests/miri_native.rs index 23ca8a0e7..ead73b84d 100644 --- a/packages/native-core/tests/miri_native.rs +++ b/packages/native-core/tests/miri_native.rs @@ -1,10 +1,14 @@ use dioxus::prelude::*; use dioxus_native_core::{ + dioxus::DioxusState, node_ref::{AttributeMaskBuilder, NodeMaskBuilder, NodeView}, real_dom::RealDom, Dependancy, Pass, SendAnyMap, }; -use std::sync::{Arc, Mutex}; +use std::{ + borrow::BorrowMut, + sync::{Arc, Mutex}, +}; use tokio::time::sleep; #[derive(Debug, Clone, PartialEq, Eq, Default)] @@ -17,7 +21,7 @@ impl Pass for BlablaState { type ChildDependencies = (); type NodeDependencies = (); - const NODE_MASK: NodeMaskBuilder = NodeMaskBuilder::new() + const NODE_MASK: NodeMaskBuilder<'static> = NodeMaskBuilder::new() .with_attrs(AttributeMaskBuilder::Some(&["blabla"])) .with_element(); @@ -135,10 +139,11 @@ fn native_core_is_okay() { let rdom = Arc::new(Mutex::new(RealDom::new(Box::new([ BlablaState::to_type_erased(), ])))); + let mut dioxus_state = DioxusState::create(&mut *rdom.lock().unwrap()); let mut dom = VirtualDom::new(app); - let muts = dom.rebuild(); - rdom.lock().unwrap().apply_mutations(muts); + let mutations = dom.rebuild(); + dioxus_state.apply_mutations(&mut *rdom.lock().unwrap(), mutations); let ctx = SendAnyMap::new(); rdom.lock().unwrap().update_state(ctx, false); @@ -147,7 +152,7 @@ fn native_core_is_okay() { dom.wait_for_work().await; let mutations = dom.render_immediate(); - rdom.lock().unwrap().apply_mutations(mutations); + dioxus_state.apply_mutations(&mut *rdom.lock().unwrap(), mutations); let ctx = SendAnyMap::new(); rdom.lock().unwrap().update_state(ctx, false); diff --git a/packages/native-core/tests/passes.rs b/packages/native-core/tests/passes.rs index c9d6b089f..ab104f5e5 100644 --- a/packages/native-core/tests/passes.rs +++ b/packages/native-core/tests/passes.rs @@ -1,6 +1,7 @@ use dioxus::prelude::*; use dioxus_native_core::node::NodeType; use dioxus_native_core::prelude::*; +use rustc_hash::{FxHashMap, FxHashSet}; use std::any::TypeId; use std::sync::{Arc, Mutex}; @@ -8,8 +9,8 @@ fn create_blank_element() -> NodeType { NodeType::Element(ElementNode { tag: "div".to_owned(), namespace: None, - attributes: HashMap::new(), - listeners: HashMap::new(), + attributes: FxHashMap::default(), + listeners: FxHashSet::default(), }) } @@ -22,7 +23,7 @@ fn node_pass() { type ChildDependencies = (); type NodeDependencies = (); type ParentDependencies = (); - const NODE_MASK: NodeMaskBuilder = NodeMaskBuilder::new(); + const NODE_MASK: NodeMaskBuilder<'static> = NodeMaskBuilder::new(); fn pass<'a>( &mut self, @@ -70,7 +71,7 @@ fn dependant_node_pass() { type ChildDependencies = (); type NodeDependencies = (SubtractNumber,); type ParentDependencies = (); - const NODE_MASK: NodeMaskBuilder = NodeMaskBuilder::new(); + const NODE_MASK: NodeMaskBuilder<'static> = NodeMaskBuilder::new(); fn pass<'a>( &mut self, @@ -104,7 +105,7 @@ fn dependant_node_pass() { type ChildDependencies = (); type NodeDependencies = (); type ParentDependencies = (); - const NODE_MASK: NodeMaskBuilder = NodeMaskBuilder::new(); + const NODE_MASK: NodeMaskBuilder<'static> = NodeMaskBuilder::new(); fn pass<'a>( &mut self, @@ -170,7 +171,7 @@ fn independant_node_pass() { type NodeDependencies = (); type ParentDependencies = (); - const NODE_MASK: NodeMaskBuilder = NodeMaskBuilder::new(); + const NODE_MASK: NodeMaskBuilder<'static> = NodeMaskBuilder::new(); fn pass<'a>( &mut self, @@ -205,7 +206,7 @@ fn independant_node_pass() { type NodeDependencies = (); type ParentDependencies = (); - const NODE_MASK: NodeMaskBuilder = NodeMaskBuilder::new(); + const NODE_MASK: NodeMaskBuilder<'static> = NodeMaskBuilder::new(); fn pass<'a>( &mut self, @@ -279,7 +280,7 @@ fn down_pass() { type NodeDependencies = (); type ParentDependencies = (AddNumber,); - const NODE_MASK: NodeMaskBuilder = NodeMaskBuilder::new(); + const NODE_MASK: NodeMaskBuilder<'static> = NodeMaskBuilder::new(); fn pass<'a>( &mut self, @@ -289,332 +290,144 @@ fn down_pass() { children: Option::ElementBorrowed<'a>>>, context: &SendAnyMap, ) -> bool { + dbg!(parent); + dbg!(node_view); if let Some((parent,)) = parent { - *self.0 += *parent.0; + self.0 += parent.0; } true } + + fn create<'a>( + node_view: NodeView<()>, + node: ::ElementBorrowed<'a>, + parent: Option<::ElementBorrowed<'a>>, + children: Option::ElementBorrowed<'a>>>, + context: &SendAnyMap, + ) -> Self { + let mut myself = Self::default(); + myself.pass(node_view, node, parent, children, context); + myself + } } let mut tree: RealDom = RealDom::new(Box::new([AddNumber::to_type_erased()])); - let parent = tree.root_id(); - let child1 = tree.create_node(create_blank_element(), true); - tree.add_child(parent, child1); - let grandchild1 = tree.create_node(create_blank_element(), true); - tree.add_child(child1, grandchild1); - let child2 = tree.create_node(create_blank_element(), true); - tree.add_child(parent, child2); - let grandchild2 = tree.create_node(create_blank_element(), true); - tree.add_child(child2, grandchild2); + let mut grandchild1 = tree.create_node(create_blank_element(), true); + let grandchild1 = grandchild1.id(); + let mut child1 = tree.create_node(create_blank_element(), true); + child1.add_child(grandchild1); + let child1 = child1.id(); + let mut grandchild2 = tree.create_node(create_blank_element(), true); + let grandchild2 = grandchild2.id(); + let mut child2 = tree.create_node(create_blank_element(), true); + child2.add_child(grandchild2); + let child2 = child2.id(); + let mut parent = tree.get_mut(tree.root_id()).unwrap(); + parent.add_child(child1); + parent.add_child(child2); - tree.dirty_nodes - .insert(TypeId::of::(), NodeId(0)); tree.update_state(SendAnyMap::new(), false); - assert_eq!(tree.get(tree.root_id()).unwrap().state.add_number.0, 1); - assert_eq!(tree.get(child1).unwrap().state.add_number.0, 2); - assert_eq!(tree.get(grandchild1).unwrap().state.add_number.0, 3); - assert_eq!(tree.get(child2).unwrap().state.add_number.0, 2); - assert_eq!(tree.get(grandchild2).unwrap().state.add_number.0, 3); + let root = tree.get(tree.root_id()).unwrap(); + dbg!(root.id()); + assert_eq!(root.get(), Some(&AddNumber(1))); + + let child1 = tree.get(child1).unwrap(); + dbg!(child1.id()); + dbg!(child1.parent().unwrap().get::()); + assert_eq!(child1.get(), Some(&AddNumber(2))); + + let grandchild1 = tree.get(grandchild1).unwrap(); + assert_eq!(grandchild1.get(), Some(&AddNumber(3))); + + let child2 = tree.get(child2).unwrap(); + assert_eq!(child2.get(), Some(&AddNumber(2))); + + let grandchild2 = tree.get(grandchild2).unwrap(); + assert_eq!(grandchild2.get(), Some(&AddNumber(3))); } -// #[test] -// fn dependant_down_pass() { -// // 0 -// let mut tree = Tree::new(1); -// let parent = tree.root_id(); -// // 1 -// let child1 = tree.create_node(1); -// tree.add_child(parent, child1); -// // 2 -// let grandchild1 = tree.create_node(1); -// tree.add_child(child1, grandchild1); -// // 3 -// let child2 = tree.create_node(1); -// tree.add_child(parent, child2); -// // 4 -// let grandchild2 = tree.create_node(1); -// tree.add_child(child2, grandchild2); +#[test] +fn up_pass() { + // Tree before: + // 1=\ + // 1=\ + // 1 + // 1=\ + // 1 + // Tree after: + // 4=\ + // 2=\ + // 1 + // 2=\ + // 1 -// struct AddPass; -// impl Pass for AddPass { -// fn pass_id(&self) -> PassId { -// PassId(0) -// } + #[derive(Debug, Clone, PartialEq)] + struct AddNumber(i32); -// fn dependancies(&self) -> &'static [PassId] { -// &[PassId(1)] -// } + impl Pass for AddNumber { + type ChildDependencies = (AddNumber,); + type NodeDependencies = (); + type ParentDependencies = (); -// fn dependants(&self) -> &'static [PassId] { -// &[] -// } + const NODE_MASK: NodeMaskBuilder<'static> = NodeMaskBuilder::new(); -// fn mask(&self) -> MemberMask { -// MemberMask(0) -// } -// } -// impl DownwardPass 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, -// } -// } -// } + fn pass<'a>( + &mut self, + node_view: NodeView, + node: ::ElementBorrowed<'a>, + parent: Option<::ElementBorrowed<'a>>, + children: Option::ElementBorrowed<'a>>>, + context: &SendAnyMap, + ) -> bool { + if let Some(children) = children { + self.0 += children.iter().map(|(i,)| i.0).sum::(); + } + true + } -// struct SubtractPass; -// impl Pass for SubtractPass { -// fn pass_id(&self) -> PassId { -// PassId(1) -// } + fn create<'a>( + node_view: NodeView<()>, + node: ::ElementBorrowed<'a>, + parent: Option<::ElementBorrowed<'a>>, + children: Option::ElementBorrowed<'a>>>, + context: &SendAnyMap, + ) -> Self { + let mut myself = Self(1); + myself.pass(node_view, node, parent, children, context); + myself + } + } -// fn dependancies(&self) -> &'static [PassId] { -// &[] -// } + let mut tree: RealDom = RealDom::new(Box::new([AddNumber::to_type_erased()])); + let mut grandchild1 = tree.create_node(create_blank_element(), true); + let grandchild1 = grandchild1.id(); + let mut child1 = tree.create_node(create_blank_element(), true); + child1.add_child(grandchild1); + let child1 = child1.id(); + let mut grandchild2 = tree.create_node(create_blank_element(), true); + let grandchild2 = grandchild2.id(); + let mut child2 = tree.create_node(create_blank_element(), true); + child2.add_child(grandchild2); + let child2 = child2.id(); + let mut parent = tree.get_mut(tree.root_id()).unwrap(); + parent.add_child(child1); + parent.add_child(child2); -// fn dependants(&self) -> &'static [PassId] { -// &[PassId(0)] -// } + tree.update_state(SendAnyMap::new(), false); -// fn mask(&self) -> MemberMask { -// MemberMask(0) -// } -// } -// impl DownwardPass 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 root = tree.get(tree.root_id()).unwrap(); + assert_eq!(root.get(), Some(&AddNumber(5))); -// let add_pass = AnyPass::Downward(&AddPass); -// let subtract_pass = AnyPass::Downward(&SubtractPass); -// let passes = vec![&add_pass, &subtract_pass]; -// let dirty_nodes: DirtyNodeStates = DirtyNodeStates::default(); -// dirty_nodes.insert(PassId(1), tree.root_id()); -// resolve_passes(&mut tree, dirty_nodes, passes, SendAnyMap::new()); + let child1 = tree.get(child1).unwrap(); + assert_eq!(child1.get(), Some(&AddNumber(2))); -// // Tree before: -// // 1=\ -// // 1=\ -// // 1 -// // 1=\ -// // 1 -// // Tree after subtract: -// // 1=\ -// // 0=\ -// // 1 -// // 0=\ -// // 1 -// // Tree after add: -// // 1=\ -// // 1=\ -// // 2 -// // 1=\ -// // 2 -// assert_eq!(tree.get(tree.root_id()).unwrap(), &1); -// assert_eq!(tree.get(child1).unwrap(), &1); -// assert_eq!(tree.get(grandchild1).unwrap(), &2); -// assert_eq!(tree.get(child2).unwrap(), &1); -// assert_eq!(tree.get(grandchild2).unwrap(), &2); -// } + let grandchild1 = tree.get(grandchild1).unwrap(); + assert_eq!(grandchild1.get(), Some(&AddNumber(1))); -// #[test] -// fn up_pass() { -// // Tree before: -// // 0=\ -// // 0=\ -// // 1 -// // 0=\ -// // 1 -// // Tree after: -// // 2=\ -// // 1=\ -// // 1 -// // 1=\ -// // 1 -// let mut tree = Tree::new(0); -// let parent = tree.root_id(); -// let child1 = tree.create_node(0); -// tree.add_child(parent, child1); -// let grandchild1 = tree.create_node(1); -// tree.add_child(child1, grandchild1); -// let child2 = tree.create_node(0); -// tree.add_child(parent, child2); -// let grandchild2 = tree.create_node(1); -// tree.add_child(child2, grandchild2); + let child2 = tree.get(child2).unwrap(); + assert_eq!(child2.get(), Some(&AddNumber(2))); -// 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 for AddPass { -// fn pass<'a>( -// &self, -// node: &mut i32, -// children: &mut dyn Iterator, -// _: &SendAnyMap, -// ) -> PassReturn { -// *node += children.map(|i| *i).sum::(); -// PassReturn { -// progress: true, -// mark_dirty: true, -// } -// } -// } - -// let add_pass = AnyPass::Upward(&AddPass); -// let passes = vec![&add_pass]; -// let dirty_nodes: DirtyNodeStates = DirtyNodeStates::default(); -// dirty_nodes.insert(PassId(0), grandchild1); -// dirty_nodes.insert(PassId(0), grandchild2); -// resolve_passes(&mut tree, dirty_nodes, passes, SendAnyMap::new()); - -// assert_eq!(tree.get(tree.root_id()).unwrap(), &2); -// assert_eq!(tree.get(child1).unwrap(), &1); -// assert_eq!(tree.get(grandchild1).unwrap(), &1); -// assert_eq!(tree.get(child2).unwrap(), &1); -// assert_eq!(tree.get(grandchild2).unwrap(), &1); -// } - -// #[test] -// fn dependant_up_pass() { -// // 0 -// let mut tree = Tree::new(0); -// let parent = tree.root_id(); -// // 1 -// let child1 = tree.create_node(0); -// tree.add_child(parent, child1); -// // 2 -// let grandchild1 = tree.create_node(1); -// tree.add_child(child1, grandchild1); -// // 3 -// let child2 = tree.create_node(0); -// tree.add_child(parent, child2); -// // 4 -// let grandchild2 = tree.create_node(1); -// tree.add_child(child2, grandchild2); - -// struct AddPass; -// impl Pass for AddPass { -// fn pass_id(&self) -> PassId { -// PassId(0) -// } - -// fn dependancies(&self) -> &'static [PassId] { -// &[PassId(1)] -// } - -// fn dependants(&self) -> &'static [PassId] { -// &[] -// } - -// fn mask(&self) -> MemberMask { -// MemberMask(0) -// } -// } -// impl UpwardPass for AddPass { -// fn pass<'a>( -// &self, -// node: &mut i32, -// children: &mut dyn Iterator, -// _: &SendAnyMap, -// ) -> PassReturn { -// *node += children.map(|i| *i).sum::(); -// 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 for SubtractPass { -// fn pass<'a>( -// &self, -// node: &mut i32, -// children: &mut dyn Iterator, -// _: &SendAnyMap, -// ) -> PassReturn { -// *node -= children.map(|i| *i).sum::(); -// PassReturn { -// progress: true, -// mark_dirty: true, -// } -// } -// } - -// let add_pass = AnyPass::Upward(&AddPass); -// let subtract_pass = AnyPass::Upward(&SubtractPass); -// let passes = vec![&add_pass, &subtract_pass]; -// let dirty_nodes: DirtyNodeStates = DirtyNodeStates::default(); -// dirty_nodes.insert(PassId(1), grandchild1); -// dirty_nodes.insert(PassId(1), grandchild2); -// resolve_passes(&mut tree, dirty_nodes, passes, SendAnyMap::new()); - -// // Tree before: -// // 0=\ -// // 0=\ -// // 1 -// // 0=\ -// // 1 -// // Tree after subtract: -// // 2=\ -// // -1=\ -// // 1 -// // -1=\ -// // 1 -// // Tree after add: -// // 2=\ -// // 0=\ -// // 1 -// // 0=\ -// // 1 -// assert_eq!(tree.get(tree.root_id()).unwrap(), &2); -// assert_eq!(tree.get(child1).unwrap(), &0); -// assert_eq!(tree.get(grandchild1).unwrap(), &1); -// assert_eq!(tree.get(child2).unwrap(), &0); -// assert_eq!(tree.get(grandchild2).unwrap(), &1); -// } + let grandchild2 = tree.get(grandchild2).unwrap(); + assert_eq!(grandchild2.get(), Some(&AddNumber(1))); +}