diff --git a/packages/native-core/src/passes.rs b/packages/native-core/src/passes.rs index b6a173b2b..fc464b722 100644 --- a/packages/native-core/src/passes.rs +++ b/packages/native-core/src/passes.rs @@ -9,7 +9,7 @@ use std::sync::Arc; use crate::node::{FromAnyValue, NodeData}; use crate::node_ref::NodeView; use crate::real_dom::RealDom; -use crate::tree::{Node, TreeStateView}; +use crate::tree::{self, Node, TreeStateView}; use crate::{FxDashMap, FxDashSet, SendAnyMap}; use crate::{NodeId, NodeMask}; @@ -374,6 +374,7 @@ pub fn resolve_passes( let mut currently_in_use = FxHashSet::::default(); std::thread::scope(|s| { let mut i = 0; + let dynamically_borrowed_tree = tree.tree.dynamically_borrowed(); while i < pass_indexes_remaining.len() { let passes_idx = pass_indexes_remaining[i]; let pass = &passes[passes_idx]; @@ -385,16 +386,18 @@ pub fn resolve_passes( pass_indexes_remaining.remove(i); resolving.push(pass_id); currently_in_use.insert(pass.this_type_id); - let tree_view = tree.tree.state_views( - [pass.this_type_id], + dynamically_borrowed_tree.with_view( pass.combined_dependancy_type_ids.iter().copied(), + [pass.this_type_id], + |tree_view| { + let dirty_nodes = dirty_nodes.clone(); + let nodes_updated = nodes_updated.clone(); + let ctx = ctx.clone(); + // s.spawn(move || { + pass.resolve(tree_view, &dirty_nodes, &nodes_updated, &ctx); + // }); + }, ); - let dirty_nodes = dirty_nodes.clone(); - let nodes_updated = nodes_updated.clone(); - let ctx = ctx.clone(); - s.spawn(move || { - pass.resolve(tree_view, &dirty_nodes, &nodes_updated, &ctx); - }); } else { i += 1; } diff --git a/packages/native-core/src/real_dom.rs b/packages/native-core/src/real_dom.rs index 4574d23c6..3a8d9adff 100644 --- a/packages/native-core/src/real_dom.rs +++ b/packages/native-core/src/real_dom.rs @@ -35,9 +35,9 @@ pub struct RealDom { impl RealDom { pub fn new(mut passes: Box<[TypeErasedPass]>) -> RealDom { - let tree = Tree::new(); + let mut tree = Tree::new(); let root_id = tree.root(); - let root = tree.get_node(root_id); + let mut root = tree.get_node(root_id); let mut root_node: NodeData = NodeData::new(NodeType::Element(ElementNode { tag: "Root".to_string(), namespace: Some("Root".to_string()), diff --git a/packages/native-core/src/tree.rs b/packages/native-core/src/tree.rs index a6ad60a9a..86a03d93d 100644 --- a/packages/native-core/src/tree.rs +++ b/packages/native-core/src/tree.rs @@ -1,12 +1,13 @@ use parking_lot::{ MappedRwLockReadGuard, MappedRwLockWriteGuard, RwLock, RwLockReadGuard, RwLockWriteGuard, }; -use rustc_hash::FxHasher; +use rustc_hash::{FxHashMap, FxHasher}; use std::any::{Any, TypeId}; use std::collections::VecDeque; use std::fmt::Debug; use std::hash::BuildHasherDefault; +use crate::node::NodeData; use crate::{AnyMapLike, Dependancy}; #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Debug, Hash)] @@ -20,12 +21,12 @@ pub(crate) struct Node { } pub(crate) struct NodeView<'a> { - tree: &'a Tree, + tree: &'a mut Tree, id: NodeId, } impl NodeView<'_> { - pub fn insert(&self, data: T) + pub fn insert(&mut self, data: T) where T: Any, { @@ -39,7 +40,7 @@ impl NodeView<'_> { self.tree.nodes.read_slab::().get(self.id).unwrap() } - pub fn get_mut(&self) -> &mut T + pub fn get_mut(&mut self) -> &mut T where T: Any, { @@ -90,11 +91,11 @@ impl Tree { self.node_slab().get(id).unwrap() } - fn node_slab_mut(&self) -> &mut SlabStorage { + fn node_slab_mut(&mut self) -> &mut SlabStorage { self.nodes.write_slab() } - pub fn get_node_data_mut(&self, id: NodeId) -> &mut Node { + pub fn get_node_data_mut(&mut self, id: NodeId) -> &mut Node { self.node_slab_mut().get_mut(id).unwrap() } @@ -118,7 +119,7 @@ impl Tree { recurse(self, id); } - fn set_height(&self, node: NodeId, height: u16) { + fn set_height(&mut self, node: NodeId, height: u16) { let children = { let mut node = self.get_node_data_mut(node); node.height = height; @@ -145,7 +146,6 @@ impl Tree { let parent = node_state.get_mut(parent).unwrap(); parent.children.push(new); let height = parent.height + 1; - drop(node_state); self.set_height(new, height); } @@ -162,7 +162,6 @@ impl Tree { } } let height = parent.height + 1; - drop(node_state); self.set_height(new_id, height); } } @@ -183,7 +182,6 @@ impl Tree { .unwrap(); parent.children.insert(index, new_id); let height = parent.height + 1; - drop(node_state); self.set_height(new_id, height); } @@ -200,7 +198,6 @@ impl Tree { .unwrap(); parent.children.insert(index + 1, new_id); let height = parent.height + 1; - drop(node_state); self.set_height(new_id, height); } @@ -212,22 +209,9 @@ impl Tree { self.nodes.len() } - pub fn state_views( - &self, - immutable: impl IntoIterator, - mutable: impl IntoIterator, - ) -> TreeStateView<'_> { - TreeStateView { - nodes_data: self.node_slab(), - nodes: immutable - .into_iter() - .map(|id| (id, MaybeRead::Read(self.nodes.data.get(&id).unwrap()))) - .chain( - mutable - .into_iter() - .map(|id| (id, MaybeRead::Write(self.nodes.data.get_mut(&id).unwrap()))), - ) - .collect(), + pub fn dynamically_borrowed(&mut self) -> DynamicallyBorrowedTree<'_> { + DynamicallyBorrowedTree { + nodes: self.nodes.dynamically_borrowed(), root: self.root, } } @@ -240,7 +224,7 @@ impl Tree { self.nodes.write_slab().get_mut(id) } - pub fn get_node(&self, id: NodeId) -> NodeView<'_> { + pub fn get_node(&mut self, id: NodeId) -> NodeView<'_> { NodeView { tree: self, id } } @@ -265,111 +249,34 @@ impl Tree { } } -pub(crate) trait NodeDataView { - fn root(&self) -> NodeId; - - fn parent_id(&self, id: NodeId) -> Option; - - fn children_ids(&self, id: NodeId) -> Option>; - - fn height(&self, id: NodeId) -> Option; +pub(crate) struct DynamicallyBorrowedTree<'a> { + nodes: DynamiclyBorrowedAnySlabView<'a>, + root: NodeId, } -trait TreeView: Sized + NodeDataView { - fn get(&self, id: NodeId) -> Option<&T>; - - fn get_unchecked(&self, id: NodeId) -> &T { - unsafe { self.get(id).unwrap_unchecked() } - } - - fn children(&self, id: NodeId) -> Option>; - - fn parent(&self, id: NodeId) -> Option<&T>; - - fn traverse_depth_first(&self, mut f: impl FnMut(&T)) { - let mut stack = vec![self.root()]; - while let Some(id) = stack.pop() { - if let Some(node) = self.get(id) { - f(node); - if let Some(children) = self.children_ids(id) { - stack.extend(children.iter().copied().rev()); - } - } +impl<'a> DynamicallyBorrowedTree<'a> { + pub fn with_view( + &self, + immutable: impl IntoIterator, + mutable: impl IntoIterator, + mut f: impl FnMut(TreeStateView), + ) { + let node_data = self.node_slab(); + let nodes = FxHashMap::default(); + { + let mut view = TreeStateView { + root: self.root, + nodes_data: &*node_data, + nodes, + }; + f(view) } } - fn traverse_breadth_first(&self, mut f: impl FnMut(&T)) { - let mut queue = VecDeque::new(); - queue.push_back(self.root()); - while let Some(id) = queue.pop_front() { - if let Some(node) = self.get(id) { - f(node); - if let Some(children) = self.children_ids(id) { - for id in children { - queue.push_back(id); - } - } - } - } - } -} - -trait TreeViewMut: Sized + TreeView { - fn get_mut(&mut self, id: NodeId) -> Option<&mut T>; - - unsafe fn get_mut_unchecked(&mut self, id: NodeId) -> &mut T { - unsafe { self.get_mut(id).unwrap_unchecked() } - } - - fn children_mut(&mut self, id: NodeId) -> Option>; - - fn parent_child_mut(&mut self, id: NodeId) -> Option<(&mut T, Vec<&mut T>)> { - let mut_ptr: *mut Self = self; - unsafe { - // Safety: No node has itself as a child. - (*mut_ptr).get_mut(id).and_then(|parent| { - (*mut_ptr) - .children_mut(id) - .map(|children| (parent, children)) - }) - } - } - - fn parent_mut(&mut self, id: NodeId) -> Option<&mut T>; - - fn node_parent_mut(&mut self, id: NodeId) -> Option<(&mut T, Option<&mut T>)>; - - #[allow(clippy::type_complexity)] - fn node_parent_children_mut( - &mut self, - id: NodeId, - ) -> Option<(&mut T, Option<&mut T>, Option>)>; - - fn traverse_depth_first_mut(&mut self, mut f: impl FnMut(&mut T)) { - let mut stack = vec![self.root()]; - while let Some(id) = stack.pop() { - if let Some(node) = self.get_mut(id) { - f(node); - if let Some(children) = self.children_ids(id) { - stack.extend(children.iter().copied().rev()); - } - } - } - } - - fn traverse_breadth_first_mut(&mut self, mut f: impl FnMut(&mut T)) { - let mut queue = VecDeque::new(); - queue.push_back(self.root()); - while let Some(id) = queue.pop_front() { - if let Some(node) = self.get_mut(id) { - f(node); - if let Some(children) = self.children_ids(id) { - for id in children { - queue.push_back(id); - } - } - } - } + fn node_slab(&self) -> MappedRwLockReadGuard<'_, SlabStorage> { + RwLockReadGuard::map(self.nodes.get_slab(TypeId::of::()).unwrap(), |slab| { + slab.as_any().downcast_ref().unwrap() + }) } } @@ -379,7 +286,7 @@ enum MaybeRead<'a> { } #[derive(Clone, Copy)] -struct TreeStateViewEntry<'a> { +pub struct TreeStateViewEntry<'a> { view: &'a TreeStateView<'a>, id: NodeId, } @@ -392,7 +299,7 @@ impl<'a> AnyMapLike<'a> for TreeStateViewEntry<'a> { pub struct TreeStateView<'a> { nodes_data: &'a SlabStorage, - nodes: hashbrown::HashMap, BuildHasherDefault>, + nodes: FxHashMap>, root: NodeId, } @@ -443,7 +350,7 @@ impl<'a> TreeStateView<'a> { self.get_slab_mut().and_then(|slab| slab.get_mut(id)) } - fn entry(&self, id: NodeId) -> TreeStateViewEntry<'_> { + pub fn entry(&self, id: NodeId) -> TreeStateViewEntry<'_> { TreeStateViewEntry { view: self, id } } @@ -459,6 +366,33 @@ impl<'a> TreeStateView<'a> { pub fn parent(&self, id: NodeId) -> Option> { T::borrow_elements_from(self.entry(id)) } + + fn traverse_depth_first(&self, mut f: impl FnMut(T::ElementBorrowed<'_>)) { + let mut stack = vec![self.root()]; + while let Some(id) = stack.pop() { + if let Some(node) = self.get::(id) { + f(node); + if let Some(children) = self.children_ids(id) { + stack.extend(children.iter().copied().rev()); + } + } + } + } + + fn traverse_breadth_first(&self, mut f: impl FnMut(T::ElementBorrowed<'_>)) { + let mut queue = VecDeque::new(); + queue.push_back(self.root()); + while let Some(id) = queue.pop_front() { + if let Some(node) = self.get::(id) { + f(node); + if let Some(children) = self.children_ids(id) { + for id in children { + queue.push_back(id); + } + } + } + } + } } #[test] @@ -479,9 +413,9 @@ fn creation() { assert_eq!(tree.parent_id(parent_id), None); assert_eq!(tree.parent_id(child_id).unwrap(), parent_id); assert_eq!(tree.children_ids(parent_id).unwrap(), &[child_id]); - let view = tree.state_view::(); - assert_eq!(*view.get(parent_id).unwrap(), 1); - assert_eq!(*view.get(child_id).unwrap(), 0); + + assert_eq!(*tree.read::(parent_id).unwrap(), 1); + assert_eq!(*tree.read::(child_id).unwrap(), 0); } #[test] @@ -512,11 +446,11 @@ fn insertion() { assert_eq!(tree.parent_id(child).unwrap(), parent); assert_eq!(tree.parent_id(after).unwrap(), parent); assert_eq!(tree.children_ids(parent).unwrap(), &[before, child, after]); - let view = tree.state_view::(); - assert_eq!(*view.get(parent).unwrap(), 0); - assert_eq!(*view.get(before).unwrap(), 1); - assert_eq!(*view.get(child).unwrap(), 2); - assert_eq!(*view.get(after).unwrap(), 3); + + assert_eq!(*tree.read::(parent).unwrap(), 0); + assert_eq!(*tree.read::(before).unwrap(), 1); + assert_eq!(*tree.read::(child).unwrap(), 2); + assert_eq!(*tree.read::(after).unwrap(), 3); } #[test] @@ -547,13 +481,11 @@ fn deletion() { assert_eq!(tree.parent_id(child).unwrap(), parent); assert_eq!(tree.parent_id(after).unwrap(), parent); assert_eq!(tree.children_ids(parent).unwrap(), &[before, child, after]); - { - let view = tree.state_view::(); - assert_eq!(*view.get(parent).unwrap(), 0); - assert_eq!(*view.get(before).unwrap(), 1); - assert_eq!(*view.get(child).unwrap(), 2); - assert_eq!(*view.get(after).unwrap(), 3); - } + + assert_eq!(*tree.read::(parent).unwrap(), 0); + assert_eq!(*tree.read::(before).unwrap(), 1); + assert_eq!(*tree.read::(child).unwrap(), 2); + assert_eq!(*tree.read::(after).unwrap(), 3); tree.remove(child); @@ -565,13 +497,11 @@ fn deletion() { assert_eq!(tree.parent_id(before).unwrap(), parent); assert_eq!(tree.parent_id(after).unwrap(), parent); assert_eq!(tree.children_ids(parent).unwrap(), &[before, after]); - { - let view = tree.state_view::(); - assert_eq!(*view.get(parent).unwrap(), 0); - assert_eq!(*view.get(before).unwrap(), 1); - assert_eq!(view.get(child), None); - assert_eq!(*view.get(after).unwrap(), 3); - } + + assert_eq!(*tree.read::(parent).unwrap(), 0); + assert_eq!(*tree.read::(before).unwrap(), 1); + assert_eq!(tree.read::(child), None); + assert_eq!(*tree.read::(after).unwrap(), 3); tree.remove(before); @@ -581,12 +511,10 @@ fn deletion() { assert_eq!(tree.height(after), Some(1)); assert_eq!(tree.parent_id(after).unwrap(), parent); assert_eq!(tree.children_ids(parent).unwrap(), &[after]); - { - let view = tree.state_view::(); - assert_eq!(*view.get(parent).unwrap(), 0); - assert_eq!(view.get(before), None); - assert_eq!(*view.get(after).unwrap(), 3); - } + + assert_eq!(*tree.read::(parent).unwrap(), 0); + assert_eq!(tree.read::(before), None); + assert_eq!(*tree.read::(after).unwrap(), 3); tree.remove(after); @@ -594,11 +522,9 @@ fn deletion() { assert_eq!(tree.size(), 1); assert_eq!(tree.height(parent), Some(0)); assert_eq!(tree.children_ids(parent).unwrap(), &[]); - { - let view = tree.state_view::(); - assert_eq!(*view.get(parent).unwrap(), 0); - assert_eq!(view.get(after), None); - } + + assert_eq!(*tree.read::(parent).unwrap(), 0); + assert_eq!(tree.read::(after), None); } #[test] @@ -752,6 +678,30 @@ impl AnySlabStorageImpl for SlabStorage { } } +pub(crate) struct DynamiclyBorrowedAnySlabView<'a> { + data: hashbrown::HashMap< + TypeId, + RwLock<&'a mut dyn AnySlabStorageImpl>, + BuildHasherDefault, + >, +} + +impl<'a> DynamiclyBorrowedAnySlabView<'a> { + fn get_slab( + &self, + type_id: TypeId, + ) -> Option> { + self.data.get(&type_id).map(|x| x.read()) + } + + fn get_slab_mut( + &self, + type_id: TypeId, + ) -> Option> { + self.data.get(&type_id).map(|x| x.write()) + } +} + pub(crate) struct AnySlab { data: hashbrown::HashMap, BuildHasherDefault>, filled: Vec, @@ -795,13 +745,13 @@ impl AnySlab { self.try_read_slab().unwrap() } - fn try_write_slab(&self) -> Option<&mut SlabStorage> { + fn try_write_slab(&mut self) -> Option<&mut SlabStorage> { self.data - .get(&TypeId::of::()) + .get_mut(&TypeId::of::()) .map(|x| x.as_any_mut().downcast_mut().unwrap()) } - fn write_slab(&self) -> &mut SlabStorage { + fn write_slab(&mut self) -> &mut SlabStorage { self.try_write_slab().unwrap() } @@ -855,6 +805,16 @@ impl AnySlab { fn contains(&self, id: NodeId) -> bool { self.filled.get(id.0).copied().unwrap_or_default() } + + fn dynamically_borrowed(&mut self) -> DynamiclyBorrowedAnySlabView<'_> { + DynamiclyBorrowedAnySlabView { + data: self + .data + .iter_mut() + .map(|(k, v)| (*k, RwLock::new(&mut **v))) + .collect(), + } + } } pub struct EntryBuilder<'a> { diff --git a/packages/native-core/tests/miri_native.rs b/packages/native-core/tests/miri_native.rs index 338f86915..674f69aa7 100644 --- a/packages/native-core/tests/miri_native.rs +++ b/packages/native-core/tests/miri_native.rs @@ -1,140 +1,140 @@ -use dioxus::prelude::*; -use dioxus_native_core::{ - node_ref::{AttributeMask, NodeView}, - real_dom::RealDom, - state::{ParentDepState, State}, - NodeMask, SendAnyMap, -}; -use dioxus_native_core_macro::{sorted_str_slice, State}; -use std::sync::{Arc, Mutex}; -use tokio::time::sleep; +// use dioxus::prelude::*; +// use dioxus_native_core::{ +// node_ref::{AttributeMask, NodeView}, +// real_dom::RealDom, +// state::{ParentDepState, State}, +// NodeMask, SendAnyMap, +// }; +// use dioxus_native_core_macro::{sorted_str_slice, State}; +// use std::sync::{Arc, Mutex}; +// use tokio::time::sleep; -#[derive(Debug, Clone, PartialEq, Eq, Default)] -pub struct BlablaState {} +// #[derive(Debug, Clone, PartialEq, Eq, Default)] +// pub struct BlablaState {} -/// Font style are inherited by default if not specified otherwise by some of the supported attributes. -impl ParentDepState for BlablaState { - type Ctx = (); - type DepState = (Self,); +// /// Font style are inherited by default if not specified otherwise by some of the supported attributes. +// impl ParentDepState for BlablaState { +// type Ctx = (); +// type DepState = (Self,); - const NODE_MASK: NodeMask = - NodeMask::new_with_attrs(AttributeMask::Static(&sorted_str_slice!(["blabla",]))); +// const NODE_MASK: NodeMask = +// NodeMask::new_with_attrs(AttributeMask::Static(&sorted_str_slice!(["blabla",]))); - fn reduce<'a>( - &mut self, - _node: NodeView, - _parent: Option<(&'a Self,)>, - _ctx: &Self::Ctx, - ) -> bool { - false - } -} +// fn reduce<'a>( +// &mut self, +// _node: NodeView, +// _parent: Option<(&'a Self,)>, +// _ctx: &Self::Ctx, +// ) -> bool { +// false +// } +// } -#[derive(Clone, State, Default, Debug)] -pub struct NodeState { - #[parent_dep_state(blabla)] - blabla: BlablaState, -} +// #[derive(Clone, State, Default, Debug)] +// pub struct NodeState { +// #[parent_dep_state(blabla)] +// blabla: BlablaState, +// } -mod dioxus_elements { - macro_rules! builder_constructors { - ( - $( - $(#[$attr:meta])* - $name:ident { - $( - $(#[$attr_method:meta])* - $fil:ident: $vil:ident, - )* - }; - )* - ) => { - $( - #[allow(non_camel_case_types)] - $(#[$attr])* - pub struct $name; +// mod dioxus_elements { +// macro_rules! builder_constructors { +// ( +// $( +// $(#[$attr:meta])* +// $name:ident { +// $( +// $(#[$attr_method:meta])* +// $fil:ident: $vil:ident, +// )* +// }; +// )* +// ) => { +// $( +// #[allow(non_camel_case_types)] +// $(#[$attr])* +// pub struct $name; - impl $name { - pub const TAG_NAME: &'static str = stringify!($name); - pub const NAME_SPACE: Option<&'static str> = None; +// impl $name { +// pub const TAG_NAME: &'static str = stringify!($name); +// pub const NAME_SPACE: Option<&'static str> = None; - $( - pub const $fil: (&'static str, Option<&'static str>, bool) = (stringify!($fil), None, false); - )* - } +// $( +// pub const $fil: (&'static str, Option<&'static str>, bool) = (stringify!($fil), None, false); +// )* +// } - impl GlobalAttributes for $name {} - )* - } - } +// impl GlobalAttributes for $name {} +// )* +// } +// } - pub trait GlobalAttributes {} +// pub trait GlobalAttributes {} - pub trait SvgAttributes {} +// pub trait SvgAttributes {} - builder_constructors! { - blabla { +// builder_constructors! { +// blabla { - }; - } -} +// }; +// } +// } -#[test] -fn native_core_is_okay() { - use std::time::Duration; +// #[test] +// fn native_core_is_okay() { +// use std::time::Duration; - fn app(cx: Scope) -> Element { - let colors = use_state(cx, || vec!["green", "blue", "red"]); - let padding = use_state(cx, || 10); +// fn app(cx: Scope) -> Element { +// let colors = use_state(cx, || vec!["green", "blue", "red"]); +// let padding = use_state(cx, || 10); - use_effect(cx, colors, |colors| async move { - sleep(Duration::from_millis(1000)).await; - colors.with_mut(|colors| colors.reverse()); - }); +// use_effect(cx, colors, |colors| async move { +// sleep(Duration::from_millis(1000)).await; +// colors.with_mut(|colors| colors.reverse()); +// }); - use_effect(cx, padding, |padding| async move { - sleep(Duration::from_millis(10)).await; - padding.with_mut(|padding| { - if *padding < 65 { - *padding += 1; - } else { - *padding = 5; - } - }); - }); +// use_effect(cx, padding, |padding| async move { +// sleep(Duration::from_millis(10)).await; +// padding.with_mut(|padding| { +// if *padding < 65 { +// *padding += 1; +// } else { +// *padding = 5; +// } +// }); +// }); - let _big = colors[0]; - let _mid = colors[1]; - let _small = colors[2]; +// let _big = colors[0]; +// let _mid = colors[1]; +// let _small = colors[2]; - cx.render(rsx! { - blabla {} - }) - } +// cx.render(rsx! { +// blabla {} +// }) +// } - let rt = tokio::runtime::Builder::new_current_thread() - .enable_time() - .build() - .unwrap(); +// let rt = tokio::runtime::Builder::new_current_thread() +// .enable_time() +// .build() +// .unwrap(); - rt.block_on(async { - let rdom = Arc::new(Mutex::new(RealDom::::new())); - let mut dom = VirtualDom::new(app); +// rt.block_on(async { +// let rdom = Arc::new(Mutex::new(RealDom::::new())); +// let mut dom = VirtualDom::new(app); - let muts = dom.rebuild(); - let (to_update, _diff) = rdom.lock().unwrap().apply_mutations(muts); +// let muts = dom.rebuild(); +// let (to_update, _diff) = rdom.lock().unwrap().apply_mutations(muts); - let ctx = SendAnyMap::new(); - rdom.lock().unwrap().update_state(to_update, ctx); +// let ctx = SendAnyMap::new(); +// rdom.lock().unwrap().update_state(to_update, ctx); - for _ in 0..10 { - dom.wait_for_work().await; +// for _ in 0..10 { +// dom.wait_for_work().await; - let mutations = dom.render_immediate(); - let (to_update, _diff) = rdom.lock().unwrap().apply_mutations(mutations); +// let mutations = dom.render_immediate(); +// let (to_update, _diff) = rdom.lock().unwrap().apply_mutations(mutations); - let ctx = SendAnyMap::new(); - rdom.lock().unwrap().update_state(to_update, ctx); - } - }); -} +// let ctx = SendAnyMap::new(); +// rdom.lock().unwrap().update_state(to_update, ctx); +// } +// }); +// }