custom element test passing

This commit is contained in:
Evan Almloff 2023-04-12 11:35:57 -05:00
parent 43372c7609
commit 4e582d0374
10 changed files with 155 additions and 57 deletions

View file

@ -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.

View file

@ -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();

View file

@ -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();

View file

@ -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();

View file

@ -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();

View file

@ -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 &Dependant {
for id in tree.children_ids(id) { type_id,
dirty.insert(*dependant, id, height + 1); 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 { for &Dependant {
if let Some(id) = tree.parent_id(id) { type_id,
dirty.insert(*dependant, id, height - 1); 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>,
} }

View file

@ -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) { if !dependants.parent.contains(&current_dependant) {
dependants.parent.push(current.this_type_id); dependants.parent.push(current_dependant);
} }
} }
PassDirection::ParentToChild => { PassDirection::ParentToChild => {
if !dependants.child.contains(&current.this_type_id) { if !dependants.child.contains(&current_dependant) {
dependants.child.push(current.this_type_id); 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);

View file

@ -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
} }
} }

View file

@ -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);
)* )*

View file

@ -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 { if let Some(size) = view
self.color = parent.color; .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));
}
}
_ => {}
}
}); });
} }
}); });