Browse Source

custom element test passing

Evan Almloff 2 years ago
parent
commit
4e582d0374

+ 5 - 5
packages/native-core-macro/src/lib.rs

@@ -224,14 +224,14 @@ pub fn partial_derive_state(_: TokenStream, input: TokenStream) -> TokenStream {
     let get_parent_view = {
     let get_parent_view = {
         if parent_dependencies.is_empty() {
         if parent_dependencies.is_empty() {
             quote! {
             quote! {
-                let raw_parent = tree.parent_id(id).map(|_| ());
+                let raw_parent = tree.parent_id_advanced(id, Self::TRAVERSE_SHADOW_DOM).map(|_| ());
             }
             }
         } else {
         } else {
             let temps = (0..parent_dependencies.len())
             let temps = (0..parent_dependencies.len())
                 .map(|i| format_ident!("__temp{}", i))
                 .map(|i| format_ident!("__temp{}", i))
                 .collect::<Vec<_>>();
                 .collect::<Vec<_>>();
             quote! {
             quote! {
-                let raw_parent = tree.parent_id(id).and_then(|parent_id| {
+                let raw_parent = tree.parent_id_advanced(id, Self::TRAVERSE_SHADOW_DOM).and_then(|parent_id| {
                     let raw_parent: Option<(#(*const #parent_dependencies,)*)> = (#(&#parent_view,)*).get(parent_id).ok().map(|c| {
                     let raw_parent: Option<(#(*const #parent_dependencies,)*)> = (#(&#parent_view,)*).get(parent_id).ok().map(|c| {
                         let (#(#temps,)*) = c;
                         let (#(#temps,)*) = c;
                         (#(#temps as *const _,)*)
                         (#(#temps as *const _,)*)
@@ -261,14 +261,14 @@ pub fn partial_derive_state(_: TokenStream, input: TokenStream) -> TokenStream {
     let get_child_view = {
     let get_child_view = {
         if child_dependencies.is_empty() {
         if child_dependencies.is_empty() {
             quote! {
             quote! {
-                let raw_children: Vec<_> = tree.children_ids(id).into_iter().map(|_| ()).collect();
+                let raw_children: Vec<_> = tree.children_ids_advanced(id, Self::TRAVERSE_SHADOW_DOM).into_iter().map(|_| ()).collect();
             }
             }
         } else {
         } else {
             let temps = (0..child_dependencies.len())
             let temps = (0..child_dependencies.len())
                 .map(|i| format_ident!("__temp{}", i))
                 .map(|i| format_ident!("__temp{}", i))
                 .collect::<Vec<_>>();
                 .collect::<Vec<_>>();
             quote! {
             quote! {
-                let raw_children: Vec<_> = tree.children_ids(id).into_iter().filter_map(|id| {
+                let raw_children: Vec<_> = tree.children_ids_advanced(id, Self::TRAVERSE_SHADOW_DOM).into_iter().filter_map(|id| {
                     let raw_children: Option<(#(*const #child_dependencies,)*)> = (#(&#child_view,)*).get(id).ok().map(|c| {
                     let raw_children: Option<(#(*const #child_dependencies,)*)> = (#(&#child_view,)*).get(id).ok().map(|c| {
                         let (#(#temps,)*) = c;
                         let (#(#temps,)*) = c;
                         (#(#temps as *const _,)*)
                         (#(#temps as *const _,)*)
@@ -336,7 +336,7 @@ pub fn partial_derive_state(_: TokenStream, input: TokenStream) -> TokenStream {
                     let (#(#split_views,)*) = data;
                     let (#(#split_views,)*) = data;
                     let tree = run_view.tree.clone();
                     let tree = run_view.tree.clone();
                     let node_types = run_view.node_type.clone();
                     let node_types = run_view.node_type.clone();
-                    dioxus_native_core::prelude::run_pass(type_id, dependants.clone(), pass_direction, run_view, Self::TRAVERSE_SHADOW_DOM, |id, context| {
+                    dioxus_native_core::prelude::run_pass(type_id, dependants.clone(), pass_direction, run_view, |id, context| {
                         let node_data: &NodeType<_> = node_types.get(id).unwrap_or_else(|err| panic!("Failed to get node type {:?}", err));
                         let node_data: &NodeType<_> = node_types.get(id).unwrap_or_else(|err| panic!("Failed to get node type {:?}", err));
                         // get all of the states from the tree view
                         // get all of the states from the tree view
                         // Safety: No node has itself as a parent or child.
                         // Safety: No node has itself as a parent or child.

+ 1 - 1
packages/native-core/examples/custom_attr.rs

@@ -215,7 +215,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
                 let _to_rerender = rdom.update_state(ctx);
                 let _to_rerender = rdom.update_state(ctx);
 
 
                 // render...
                 // render...
-                rdom.traverse_depth_first(|node| {
+                rdom.traverse_depth_first(true, |node| {
                     let indent = " ".repeat(node.height() as usize);
                     let indent = " ".repeat(node.height() as usize);
                     let color = *node.get::<TextColor>().unwrap();
                     let color = *node.get::<TextColor>().unwrap();
                     let size = *node.get::<Size>().unwrap();
                     let size = *node.get::<Size>().unwrap();

+ 1 - 1
packages/native-core/examples/font_size.rs

@@ -160,7 +160,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
                 let _to_rerender = rdom.update_state(ctx);
                 let _to_rerender = rdom.update_state(ctx);
 
 
                 // render...
                 // render...
-                rdom.traverse_depth_first(|node| {
+                rdom.traverse_depth_first(true, |node| {
                     let indent = " ".repeat(node.height() as usize);
                     let indent = " ".repeat(node.height() as usize);
                     let font_size = *node.get::<FontSize>().unwrap();
                     let font_size = *node.get::<FontSize>().unwrap();
                     let size = *node.get::<Size>().unwrap();
                     let size = *node.get::<Size>().unwrap();

+ 1 - 1
packages/native-core/examples/simple.rs

@@ -206,7 +206,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
                 let _to_rerender = rdom.update_state(ctx);
                 let _to_rerender = rdom.update_state(ctx);
 
 
                 // render...
                 // render...
-                rdom.traverse_depth_first(|node| {
+                rdom.traverse_depth_first(true, |node| {
                     let indent = " ".repeat(node.height() as usize);
                     let indent = " ".repeat(node.height() as usize);
                     let color = *node.get::<TextColor>().unwrap();
                     let color = *node.get::<TextColor>().unwrap();
                     let size = *node.get::<Size>().unwrap();
                     let size = *node.get::<Size>().unwrap();

+ 1 - 1
packages/native-core/examples/simple_dioxus.rs

@@ -234,7 +234,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
                 let _to_rerender = rdom.update_state(ctx);
                 let _to_rerender = rdom.update_state(ctx);
 
 
                 // render...
                 // render...
-                rdom.traverse_depth_first(|node| {
+                rdom.traverse_depth_first(true, |node| {
                     let indent = " ".repeat(node.height() as usize);
                     let indent = " ".repeat(node.height() as usize);
                     let color = *node.get::<TextColor>().unwrap();
                     let color = *node.get::<TextColor>().unwrap();
                     let size = *node.get::<Size>().unwrap();
                     let size = *node.get::<Size>().unwrap();

+ 25 - 10
packages/native-core/src/passes.rs

@@ -153,6 +153,7 @@ pub trait State<V: FromAnyValue + Send + Sync = ()>: Any + Send + Sync {
             dependants: Default::default(),
             dependants: Default::default(),
             mask: node_mask,
             mask: node_mask,
             pass_direction: pass_direction::<V, Self>(),
             pass_direction: pass_direction::<V, Self>(),
+            enter_shadow_dom: Self::TRAVERSE_SHADOW_DOM,
             workload: Self::workload_system,
             workload: Self::workload_system,
             phantom: PhantomData,
             phantom: PhantomData,
         }
         }
@@ -193,7 +194,6 @@ pub fn run_pass<V: FromAnyValue + Send + Sync>(
     dependants: Arc<Dependants>,
     dependants: Arc<Dependants>,
     pass_direction: PassDirection,
     pass_direction: PassDirection,
     view: RunPassView<V>,
     view: RunPassView<V>,
-    enter_shadow_dom: bool,
     mut update_node: impl FnMut(NodeId, &SendAnyMap) -> bool,
     mut update_node: impl FnMut(NodeId, &SendAnyMap) -> bool,
 ) {
 ) {
     let RunPassView {
     let RunPassView {
@@ -232,28 +232,42 @@ pub fn run_pass<V: FromAnyValue + Send + Sync>(
     }
     }
 }
 }
 
 
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub(crate) struct Dependant {
+    pub(crate) type_id: TypeId,
+    pub(crate) enter_shadow_dom: bool,
+}
+
 /// The states that depend on this state
 /// The states that depend on this state
 #[derive(Default, Debug, Clone, PartialEq, Eq)]
 #[derive(Default, Debug, Clone, PartialEq, Eq)]
 pub struct Dependants {
 pub struct Dependants {
     /// The states in the parent direction that should be invalidated when this state is invalidated
     /// The states in the parent direction that should be invalidated when this state is invalidated
-    pub parent: Vec<TypeId>,
+    pub(crate) parent: Vec<Dependant>,
     /// The states in the child direction that should be invalidated when this state is invalidated
     /// The states in the child direction that should be invalidated when this state is invalidated
-    pub child: Vec<TypeId>,
+    pub(crate) child: Vec<Dependant>,
     /// The states in the node direction that should be invalidated when this state is invalidated
     /// The states in the node direction that should be invalidated when this state is invalidated
-    pub node: Vec<TypeId>,
+    pub(crate) node: Vec<TypeId>,
 }
 }
 
 
 impl Dependants {
 impl Dependants {
     fn mark_dirty(&self, dirty: &DirtyNodeStates, id: NodeId, tree: &impl TreeRef, height: u16) {
     fn mark_dirty(&self, dirty: &DirtyNodeStates, id: NodeId, tree: &impl TreeRef, height: u16) {
-        for dependant in &self.child {
-            for id in tree.children_ids(id) {
-                dirty.insert(*dependant, id, height + 1);
+        for &Dependant {
+            type_id,
+            enter_shadow_dom,
+        } in &self.child
+        {
+            for id in tree.children_ids_advanced(id, enter_shadow_dom) {
+                dirty.insert(type_id, id, height + 1);
             }
             }
         }
         }
 
 
-        for dependant in &self.parent {
-            if let Some(id) = tree.parent_id(id) {
-                dirty.insert(*dependant, id, height - 1);
+        for &Dependant {
+            type_id,
+            enter_shadow_dom,
+        } in &self.parent
+        {
+            if let Some(id) = tree.parent_id_advanced(id, enter_shadow_dom) {
+                dirty.insert(type_id, id, height - 1);
             }
             }
         }
         }
 
 
@@ -273,6 +287,7 @@ pub struct TypeErasedState<V: FromAnyValue + Send = ()> {
     pub(crate) mask: NodeMask,
     pub(crate) mask: NodeMask,
     pub(crate) workload: fn(TypeId, Arc<Dependants>, PassDirection) -> WorkloadSystem,
     pub(crate) workload: fn(TypeId, Arc<Dependants>, PassDirection) -> WorkloadSystem,
     pub(crate) pass_direction: PassDirection,
     pub(crate) pass_direction: PassDirection,
+    pub(crate) enter_shadow_dom: bool,
     phantom: PhantomData<V>,
     phantom: PhantomData<V>,
 }
 }
 
 

+ 35 - 17
packages/native-core/src/real_dom.rs

@@ -16,7 +16,7 @@ use crate::node::{
 };
 };
 use crate::node_ref::{NodeMask, NodeMaskBuilder};
 use crate::node_ref::{NodeMask, NodeMaskBuilder};
 use crate::node_watcher::{AttributeWatcher, NodeWatcher};
 use crate::node_watcher::{AttributeWatcher, NodeWatcher};
-use crate::passes::{DirtyNodeStates, PassDirection, TypeErasedState};
+use crate::passes::{Dependant, DirtyNodeStates, PassDirection, TypeErasedState};
 use crate::prelude::AttributeMaskBuilder;
 use crate::prelude::AttributeMaskBuilder;
 use crate::tree::{TreeMut, TreeMutView, TreeRef, TreeRefView};
 use crate::tree::{TreeMut, TreeMutView, TreeRef, TreeRefView};
 use crate::NodeId;
 use crate::NodeId;
@@ -128,19 +128,25 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
             let (current, before) = before.split_last_mut().unwrap();
             let (current, before) = before.split_last_mut().unwrap();
             for state in before.iter_mut().chain(after.iter_mut()) {
             for state in before.iter_mut().chain(after.iter_mut()) {
                 let dependants = Arc::get_mut(&mut state.dependants).unwrap();
                 let dependants = Arc::get_mut(&mut state.dependants).unwrap();
+
+                let current_dependant = Dependant {
+                    type_id: current.this_type_id,
+                    enter_shadow_dom: current.enter_shadow_dom,
+                };
+
                 // If this node depends on the other state as a parent, then the other state should update its children of the current type when it is invalidated
                 // If this node depends on the other state as a parent, then the other state should update its children of the current type when it is invalidated
                 if current
                 if current
                     .parent_dependancies_ids
                     .parent_dependancies_ids
                     .contains(&state.this_type_id)
                     .contains(&state.this_type_id)
-                    && !dependants.child.contains(&current.this_type_id)
+                    && !dependants.child.contains(&current_dependant)
                 {
                 {
-                    dependants.child.push(current.this_type_id);
+                    dependants.child.push(current_dependant);
                 }
                 }
                 // If this node depends on the other state as a child, then the other state should update its parent of the current type when it is invalidated
                 // If this node depends on the other state as a child, then the other state should update its parent of the current type when it is invalidated
                 if current.child_dependancies_ids.contains(&state.this_type_id)
                 if current.child_dependancies_ids.contains(&state.this_type_id)
-                    && !dependants.parent.contains(&current.this_type_id)
+                    && !dependants.parent.contains(&current_dependant)
                 {
                 {
-                    dependants.parent.push(current.this_type_id);
+                    dependants.parent.push(current_dependant);
                 }
                 }
                 // If this node depends on the other state as a sibling, then the other state should update its siblings of the current type when it is invalidated
                 // If this node depends on the other state as a sibling, then the other state should update its siblings of the current type when it is invalidated
                 if current.node_dependancies_ids.contains(&state.this_type_id)
                 if current.node_dependancies_ids.contains(&state.this_type_id)
@@ -151,15 +157,19 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
             }
             }
             // If the current state depends on itself, then it should update itself when it is invalidated
             // If the current state depends on itself, then it should update itself when it is invalidated
             let dependants = Arc::get_mut(&mut current.dependants).unwrap();
             let dependants = Arc::get_mut(&mut current.dependants).unwrap();
+            let current_dependant = Dependant {
+                type_id: current.this_type_id,
+                enter_shadow_dom: current.enter_shadow_dom,
+            };
             match current.pass_direction {
             match current.pass_direction {
                 PassDirection::ChildToParent => {
                 PassDirection::ChildToParent => {
-                    if !dependants.parent.contains(&current.this_type_id) {
-                        dependants.parent.push(current.this_type_id);
+                    if !dependants.parent.contains(&current_dependant) {
+                        dependants.parent.push(current_dependant);
                     }
                     }
                 }
                 }
                 PassDirection::ParentToChild => {
                 PassDirection::ParentToChild => {
-                    if !dependants.child.contains(&current.this_type_id) {
-                        dependants.child.push(current.this_type_id);
+                    if !dependants.child.contains(&current_dependant) {
+                        dependants.child.push(current_dependant);
                     }
                     }
                 }
                 }
                 _ => {}
                 _ => {}
@@ -371,27 +381,27 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
     }
     }
 
 
     /// Traverses the dom in a depth first manner, calling the provided function on each node.
     /// Traverses the dom in a depth first manner, calling the provided function on each node.
-    pub fn traverse_depth_first(&self, mut f: impl FnMut(NodeRef<V>)) {
+    pub fn traverse_depth_first(&self, enter_shadow_doms: bool, mut f: impl FnMut(NodeRef<V>)) {
         let mut stack = vec![self.root_id()];
         let mut stack = vec![self.root_id()];
         let tree = self.tree_ref();
         let tree = self.tree_ref();
         while let Some(id) = stack.pop() {
         while let Some(id) = stack.pop() {
             if let Some(node) = self.get(id) {
             if let Some(node) = self.get(id) {
                 f(node);
                 f(node);
-                let children = tree.children_ids(id);
+                let children = tree.children_ids_advanced(id, enter_shadow_doms);
                 stack.extend(children.iter().copied().rev());
                 stack.extend(children.iter().copied().rev());
             }
             }
         }
         }
     }
     }
 
 
     /// Traverses the dom in a breadth first manner, calling the provided function on each node.
     /// Traverses the dom in a breadth first manner, calling the provided function on each node.
-    pub fn traverse_breadth_first(&self, mut f: impl FnMut(NodeRef<V>)) {
+    pub fn traverse_breadth_first(&self, enter_shadow_doms: bool, mut f: impl FnMut(NodeRef<V>)) {
         let mut queue = VecDeque::new();
         let mut queue = VecDeque::new();
         queue.push_back(self.root_id());
         queue.push_back(self.root_id());
         let tree = self.tree_ref();
         let tree = self.tree_ref();
         while let Some(id) = queue.pop_front() {
         while let Some(id) = queue.pop_front() {
             if let Some(node) = self.get(id) {
             if let Some(node) = self.get(id) {
                 f(node);
                 f(node);
-                let children = tree.children_ids(id);
+                let children = tree.children_ids_advanced(id, enter_shadow_doms);
                 for id in children {
                 for id in children {
                     queue.push_back(id);
                     queue.push_back(id);
                 }
                 }
@@ -400,11 +410,15 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
     }
     }
 
 
     /// Traverses the dom in a depth first manner mutably, calling the provided function on each node.
     /// Traverses the dom in a depth first manner mutably, calling the provided function on each node.
-    pub fn traverse_depth_first_mut(&mut self, mut f: impl FnMut(NodeMut<V>)) {
+    pub fn traverse_depth_first_mut(
+        &mut self,
+        enter_shadow_doms: bool,
+        mut f: impl FnMut(NodeMut<V>),
+    ) {
         let mut stack = vec![self.root_id()];
         let mut stack = vec![self.root_id()];
         while let Some(id) = stack.pop() {
         while let Some(id) = stack.pop() {
             let tree = self.tree_ref();
             let tree = self.tree_ref();
-            let mut children = tree.children_ids(id);
+            let mut children = tree.children_ids_advanced(id, enter_shadow_doms);
             drop(tree);
             drop(tree);
             children.reverse();
             children.reverse();
             if let Some(node) = self.get_mut(id) {
             if let Some(node) = self.get_mut(id) {
@@ -416,12 +430,16 @@ impl<V: FromAnyValue + Send + Sync> RealDom<V> {
     }
     }
 
 
     /// Traverses the dom in a breadth first manner mutably, calling the provided function on each node.
     /// Traverses the dom in a breadth first manner mutably, calling the provided function on each node.
-    pub fn traverse_breadth_first_mut(&mut self, mut f: impl FnMut(NodeMut<V>)) {
+    pub fn traverse_breadth_first_mut(
+        &mut self,
+        enter_shadow_doms: bool,
+        mut f: impl FnMut(NodeMut<V>),
+    ) {
         let mut queue = VecDeque::new();
         let mut queue = VecDeque::new();
         queue.push_back(self.root_id());
         queue.push_back(self.root_id());
         while let Some(id) = queue.pop_front() {
         while let Some(id) = queue.pop_front() {
             let tree = self.tree_ref();
             let tree = self.tree_ref();
-            let children = tree.children_ids(id);
+            let children = tree.children_ids_advanced(id, enter_shadow_doms);
             drop(tree);
             drop(tree);
             if let Some(node) = self.get_mut(id) {
             if let Some(node) = self.get_mut(id) {
                 f(node);
                 f(node);

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

@@ -11,8 +11,6 @@ pub struct ShadowTree {
     pub shadow_roots: Vec<NodeId>,
     pub shadow_roots: Vec<NodeId>,
     /// The node that children of the super tree should be inserted under.
     /// The node that children of the super tree should be inserted under.
     pub slot: Option<NodeId>,
     pub slot: Option<NodeId>,
-    /// The node in the super tree that the shadow_tree is attached to.
-    pub super_tree_root: NodeId,
 }
 }
 
 
 /// A node in a tree.
 /// A node in a tree.
@@ -35,8 +33,43 @@ pub type TreeMutView<'a> = (EntitiesViewMut<'a>, ViewMut<'a, Node>);
 
 
 /// A immutable view of a tree.
 /// A immutable view of a tree.
 pub trait TreeRef {
 pub trait TreeRef {
+    /// Get the id of the parent of the current node, if enter_shadow_dom is true and the current node is a shadow root, the node the shadow root is attached to will be returned
+    #[inline]
+    fn parent_id_advanced(&self, id: NodeId, enter_shadow_dom: bool) -> Option<NodeId> {
+        // If this node is the root of a shadow_tree, return the node the shadow_tree is attached
+        let light_tree_root = self.light_tree_root(id);
+        match (light_tree_root, enter_shadow_dom) {
+            (Some(id), true) => Some(id),
+            _ => {
+                let parent_id = self.parent_id(id);
+                if enter_shadow_dom {
+                    // If this node is attached via a slot, return the slot as the parent instead of the light tree parent
+                    parent_id.map(|id| {
+                        self.shadow_tree(id)
+                            .and_then(|tree| tree.slot)
+                            .unwrap_or(id)
+                    })
+                } else {
+                    parent_id
+                }
+            }
+        }
+    }
     /// The parent id of the node.
     /// The parent id of the node.
     fn parent_id(&self, id: NodeId) -> Option<NodeId>;
     fn parent_id(&self, id: NodeId) -> Option<NodeId>;
+    /// Get the ids of the children of the current node, if enter_shadow_dom is true and the current node is a shadow slot, the ids of the nodes under the node the shadow slot is attached to will be returned
+    #[inline]
+    fn children_ids_advanced(&self, id: NodeId, enter_shadow_dom: bool) -> Vec<NodeId> {
+        let shadow_tree = self.shadow_tree(id);
+        let slot_of_light_tree = self.slot_for_light_tree(id);
+        match (shadow_tree, slot_of_light_tree, enter_shadow_dom) {
+            // If this node is a shadow root, return the shadow roots
+            (Some(tree), _, true) => tree.shadow_roots.clone(),
+            // If this node is a slot, return the children of the node the slot is attached to
+            (None, Some(id), true) => self.children_ids(id),
+            _ => self.children_ids(id),
+        }
+    }
     /// The children ids of the node.
     /// The children ids of the node.
     fn children_ids(&self, id: NodeId) -> Vec<NodeId>;
     fn children_ids(&self, id: NodeId) -> Vec<NodeId>;
     /// The shadow tree tree under the node.
     /// The shadow tree tree under the node.
@@ -229,7 +262,6 @@ impl<'a> TreeMut for TreeMutView<'a> {
         let light_root_height;
         let light_root_height;
         {
         {
             let shadow_tree = ShadowTree {
             let shadow_tree = ShadowTree {
-                super_tree_root: id,
                 shadow_roots: shadow_roots.clone(),
                 shadow_roots: shadow_roots.clone(),
                 slot,
                 slot,
             };
             };
@@ -251,6 +283,7 @@ impl<'a> TreeMut for TreeMutView<'a> {
 
 
         // Now that we have created the shadow_tree, we need to update the height of the shadow_tree roots
         // Now that we have created the shadow_tree, we need to update the height of the shadow_tree roots
         for root in shadow_roots {
         for root in shadow_roots {
+            (&mut self.1).get(root).unwrap().light_tree_root = Some(id);
             set_height(self, root, light_root_height + 1);
             set_height(self, root, light_root_height + 1);
         }
         }
     }
     }
@@ -319,7 +352,7 @@ fn set_height(tree: &mut TreeMutView<'_>, node: NodeId, height: u16) {
     if let Some(shadow_tree) = shadow_tree {
     if let Some(shadow_tree) = shadow_tree {
         // Set the height of the shadow_tree roots
         // Set the height of the shadow_tree roots
         for &shadow_root in &shadow_tree.shadow_roots {
         for &shadow_root in &shadow_tree.shadow_roots {
-            set_height(tree, shadow_root, height);
+            set_height(tree, shadow_root, height + 1);
         }
         }
     } else {
     } else {
         // Otherwise, we just set the height of the children to be one more than the height of the parent
         // Otherwise, we just set the height of the children to be one more than the height of the parent
@@ -362,17 +395,17 @@ impl<'a> TreeRef for TreeMutView<'a> {
 
 
     fn shadow_tree(&self, id: NodeId) -> Option<&ShadowTree> {
     fn shadow_tree(&self, id: NodeId) -> Option<&ShadowTree> {
         let node_data = &self.1;
         let node_data = &self.1;
-        node_data.get(id).unwrap().child_subtree.as_ref()
+        node_data.get(id).ok()?.child_subtree.as_ref()
     }
     }
 
 
     fn slot_for_light_tree(&self, id: NodeId) -> Option<NodeId> {
     fn slot_for_light_tree(&self, id: NodeId) -> Option<NodeId> {
         let node_data = &self.1;
         let node_data = &self.1;
-        node_data.get(id).unwrap().slot_for_light_tree
+        node_data.get(id).ok()?.slot_for_light_tree
     }
     }
 
 
     fn light_tree_root(&self, id: NodeId) -> Option<NodeId> {
     fn light_tree_root(&self, id: NodeId) -> Option<NodeId> {
         let node_data = &self.1;
         let node_data = &self.1;
-        node_data.get(id).unwrap().light_tree_root
+        node_data.get(id).ok()?.light_tree_root
     }
     }
 }
 }
 
 

+ 1 - 1
packages/native-core/tests/called_minimally_on_build.rs

@@ -146,7 +146,7 @@ macro_rules! test_state{
             dioxus_state.apply_mutations(&mut dom, mutations);
             dioxus_state.apply_mutations(&mut dom, mutations);
             dom.update_state(SendAnyMap::new());
             dom.update_state(SendAnyMap::new());
 
 
-            dom.traverse_depth_first(|n| {
+            dom.traverse_depth_first(false, |n| {
                 $(
                 $(
                     assert_eq!(n.get::<$state>().unwrap().0, 1);
                     assert_eq!(n.get::<$state>().unwrap().0, 1);
                 )*
                 )*

+ 45 - 13
packages/native-core/tests/custom_element.rs

@@ -23,14 +23,26 @@ impl State for ColorState {
 
 
     fn update<'a>(
     fn update<'a>(
         &mut self,
         &mut self,
-        _: NodeView,
+        view: NodeView,
         _: <Self::NodeDependencies as Dependancy>::ElementBorrowed<'a>,
         _: <Self::NodeDependencies as Dependancy>::ElementBorrowed<'a>,
         parent: Option<<Self::ParentDependencies as Dependancy>::ElementBorrowed<'a>>,
         parent: Option<<Self::ParentDependencies as Dependancy>::ElementBorrowed<'a>>,
         _: Vec<<Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>,
         _: Vec<<Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>,
         _: &SendAnyMap,
         _: &SendAnyMap,
     ) -> bool {
     ) -> bool {
-        if let Some((parent,)) = parent {
-            self.color = parent.color;
+        if let Some(size) = view
+            .attributes()
+            .into_iter()
+            .flatten()
+            .find(|attr| attr.attribute.name == "color")
+        {
+            self.color = size
+                .value
+                .as_float()
+                .or_else(|| size.value.as_int().map(|i| i as f64))
+                .or_else(|| size.value.as_text().and_then(|i| i.parse().ok()))
+                .unwrap_or(0.0) as usize;
+        } else if let Some((parent,)) = parent {
+            *self = *parent;
         }
         }
         true
         true
     }
     }
@@ -74,11 +86,6 @@ impl State for LayoutState {
         _: Vec<<Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>,
         _: Vec<<Self::ChildDependencies as Dependancy>::ElementBorrowed<'a>>,
         _: &SendAnyMap,
         _: &SendAnyMap,
     ) -> bool {
     ) -> bool {
-        println!(
-            "Updating layout state @{:?} {:?}",
-            parent.as_ref().map(|(p,)| p.size),
-            view.node_id()
-        );
         if let Some(size) = view
         if let Some(size) = view
             .attributes()
             .attributes()
             .into_iter()
             .into_iter()
@@ -93,7 +100,7 @@ impl State for LayoutState {
                 .unwrap_or(0.0) as usize;
                 .unwrap_or(0.0) as usize;
         } else if let Some((parent,)) = parent {
         } else if let Some((parent,)) = parent {
             if parent.size > 0 {
             if parent.size > 0 {
-                self.size -= 1;
+                self.size = parent.size - 1;
             }
             }
         }
         }
         true
         true
@@ -130,7 +137,7 @@ mod dioxus_elements {
                 $(#[$attr])*
                 $(#[$attr])*
                 pub struct $name;
                 pub struct $name;
 
 
-                #[allow(non_upper_case_globals)]
+                #[allow(non_upper_case_globals, unused)]
                 impl $name {
                 impl $name {
                     pub const TAG_NAME: &'static str = stringify!($name);
                     pub const TAG_NAME: &'static str = stringify!($name);
                     pub const NAME_SPACE: Option<&'static str> = None;
                     pub const NAME_SPACE: Option<&'static str> = None;
@@ -152,10 +159,14 @@ mod dioxus_elements {
     builder_constructors! {
     builder_constructors! {
         customelementslot {
         customelementslot {
             size: attr,
             size: attr,
+            color: attr,
         };
         };
         customelementnoslot {
         customelementnoslot {
+            size: attr,
+            color: attr,
         };
         };
         testing132 {
         testing132 {
+            color: attr,
         };
         };
     }
     }
 }
 }
@@ -253,6 +264,7 @@ fn custom_elements_work() {
         cx.render(rsx! {
         cx.render(rsx! {
             customelementslot {
             customelementslot {
                 size: "{count}",
                 size: "{count}",
+                color: "1",
                 customelementslot {
                 customelementslot {
                     testing132 {}
                     testing132 {}
                 }
                 }
@@ -277,7 +289,7 @@ fn custom_elements_work() {
         let ctx = SendAnyMap::new();
         let ctx = SendAnyMap::new();
         rdom.update_state(ctx);
         rdom.update_state(ctx);
 
 
-        for _ in 0..10 {
+        for i in 0..10usize {
             dom.wait_for_work().await;
             dom.wait_for_work().await;
 
 
             let mutations = dom.render_immediate();
             let mutations = dom.render_immediate();
@@ -287,13 +299,33 @@ fn custom_elements_work() {
             rdom.update_state(ctx);
             rdom.update_state(ctx);
 
 
             // render...
             // render...
-            rdom.traverse_depth_first(|node| {
+            rdom.traverse_depth_first(true, |node| {
                 let node_type = &*node.node_type();
                 let node_type = &*node.node_type();
-                let indent = " ".repeat(node.height() as usize);
+                let height = node.height() as usize;
+                let indent = " ".repeat(height);
                 let color = *node.get::<ColorState>().unwrap();
                 let color = *node.get::<ColorState>().unwrap();
                 let size = *node.get::<LayoutState>().unwrap();
                 let size = *node.get::<LayoutState>().unwrap();
                 let id = node.id();
                 let id = node.id();
                 println!("{indent}{id:?} {color:?} {size:?} {node_type:?}");
                 println!("{indent}{id:?} {color:?} {size:?} {node_type:?}");
+                match node_type {
+                    NodeType::Element(el) => {
+                        match el.tag.as_str() {
+                            // the color should bubble up from customelementslot
+                            "testing132" | "customelementslot" => {
+                                assert_eq!(color.color, 1);
+                            }
+                            // the color of the light dom should not effect the color of the shadow dom, so the color of divs in the shadow dom should be 0
+                            "div" => {
+                                assert_eq!(color.color, 0);
+                            }
+                            _ => {}
+                        }
+                        if el.tag != "Root" {
+                            assert_eq!(size.size, (i + 2).saturating_sub(height));
+                        }
+                    }
+                    _ => {}
+                }
             });
             });
         }
         }
     });
     });