From 2d541eca640d15bb56bccb4191b1dc0fe02dfc22 Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Mon, 23 Aug 2021 12:11:45 -0400 Subject: [PATCH] wip: structure coming together and tests --- packages/core/.vscode/settings.json | 2 +- packages/core/src/diff.rs | 93 ++++----- packages/core/src/diff_stack.rs | 28 ++- packages/core/src/{editor.rs => dom_edits.rs} | 9 +- packages/core/src/lib.rs | 10 +- packages/core/src/mutations.rs | 15 +- packages/core/src/virtual_dom.rs | 7 +- packages/core/tests/create_iterative.rs | 178 ++++++++++++++++-- packages/core/tests/diffing.rs | 22 +-- packages/core/tests/eventsystem.rs | 7 +- packages/core/tests/hooks.rs | 7 +- packages/core/tests/test_logging.rs | 7 +- packages/core/tests/work_sync.rs | 7 +- 13 files changed, 251 insertions(+), 141 deletions(-) rename packages/core/src/{editor.rs => dom_edits.rs} (93%) diff --git a/packages/core/.vscode/settings.json b/packages/core/.vscode/settings.json index 1c68f97cc..79505b018 100644 --- a/packages/core/.vscode/settings.json +++ b/packages/core/.vscode/settings.json @@ -1,3 +1,3 @@ { - "rust-analyzer.inlayHints.enable": true + "rust-analyzer.inlayHints.enable": false } diff --git a/packages/core/src/diff.rs b/packages/core/src/diff.rs index b9dffde21..4c4894161 100644 --- a/packages/core/src/diff.rs +++ b/packages/core/src/diff.rs @@ -167,8 +167,10 @@ impl<'bump> DiffMachine<'bump> { DiffInstruction::PopScope => { self.stack.pop_scope(); } + DiffInstruction::PopElement => { - self.mutations.pop(); + todo!(); + // self.mutations.pop(); } DiffInstruction::DiffNode { old, new, .. } => { @@ -179,20 +181,16 @@ impl<'bump> DiffMachine<'bump> { self.diff_children(old, new); } - DiffInstruction::Create { node, and } => { + DiffInstruction::Create { node } => { self.create_node(node); } DiffInstruction::Remove { child } => { - for child in RealChildIterator::new(child, self.vdom) { - self.mutations.remove(child.direct_id().as_u64()); - } + self.remove_nodes(Some(child)); } DiffInstruction::RemoveChildren { children } => { - for child in RealChildIterator::new_from_slice(children, self.vdom) { - self.mutations.remove(child.direct_id().as_u64()); - } + self.remove_nodes(children); } DiffInstruction::Mount { and } => { @@ -204,13 +202,13 @@ impl<'bump> DiffMachine<'bump> { Ok(()) } - fn mount(&mut self, and: MountType) { - let nodes_created = self.stack.nodes_created_stack.pop().unwrap(); + fn mount(&mut self, and: MountType<'bump>) { + let nodes_created = self.stack.pop_nodes_created(); match and { // add the nodes from this virtual list to the parent // used by fragments and components MountType::Absorb => { - *self.stack.nodes_created_stack.last_mut().unwrap() += nodes_created; + self.stack.add_child_count(nodes_created); } MountType::Append => { self.mutations.edits.push(AppendChildren { @@ -218,15 +216,21 @@ impl<'bump> DiffMachine<'bump> { }); } MountType::Replace { old } => { - todo!() - // self.mutations.replace_with(with as u32, many as u32); + let root = todo!(); + self.mutations.replace_with(root, nodes_created as u32); } + MountType::ReplaceByElementId { old } => { + self.mutations.replace_with(old, nodes_created as u32); + } + MountType::InsertAfter { other_node } => { - self.mutations.insert_after(nodes_created as u32); + let root = self.find_last_element(other_node).direct_id(); + self.mutations.insert_after(root, nodes_created as u32); } MountType::InsertBefore { other_node } => { - self.mutations.insert_before(nodes_created as u32); + let root = self.find_first_element(other_node).direct_id(); + self.mutations.insert_before(root, nodes_created as u32); } } } @@ -373,17 +377,19 @@ impl<'bump> DiffMachine<'bump> { match (old_node, new_node) { // Check the most common cases first (Text(old), Text(new)) => self.diff_text_nodes(old, new), - (Element(old), Element(new)) => self.diff_element_nodes(old, new), (Component(old), Component(new)) => self.diff_component_nodes(old, new), (Fragment(old), Fragment(new)) => self.diff_fragment_nodes(old, new), (Anchor(old), Anchor(new)) => new.dom_id.set(old.dom_id.get()), (Suspended(old), Suspended(new)) => new.node.set(old.node.get()), + (Element(old), Element(new)) => self.diff_element_nodes(old, new), // Anything else is just a basic replace and create ( Component(_) | Fragment(_) | Text(_) | Element(_) | Anchor(_) | Suspended(_), Component(_) | Fragment(_) | Text(_) | Element(_) | Anchor(_) | Suspended(_), - ) => self.replace_and_create_one_with_one(old_node, new_node), + ) => self + .stack + .create_node(new_node, MountType::Replace { old: old_node }), } } @@ -407,8 +413,8 @@ impl<'bump> DiffMachine<'bump> { // // This case is rather rare (typically only in non-keyed lists) if new.tag_name != old.tag_name || new.namespace != old.namespace { - todo!(); - // self.replace_node_with_node(root, old_node, new_node); + todo!("element changed"); + // self.replace_node_with_node(old, new); return; } @@ -779,21 +785,6 @@ impl<'bump> DiffMachine<'bump> { KeyedPrefixResult::MoreWorkToDo(shared_prefix_count) } - // Create the given children and append them to the parent node. - // - // The parent node must currently be on top of the change list stack: - // - // [... parent] - // - // When this function returns, the change list stack is in the same state. - fn create_and_append_children(&mut self, new: &'bump [VNode<'bump>]) { - for child in new { - todo!(); - // let meta = self.create_vnode(child); - // self.mutations.append_children(meta.added_to_stack); - } - } - // The most-general, expensive code path for keyed children diffing. // // We find the longest subsequence within `old` of children that are relatively @@ -957,12 +948,12 @@ impl<'bump> DiffMachine<'bump> { self.mutations.insert_before(1); } } else { - self.stack.push(DiffInstruction::Create { - node: next_new, - and: MountType::InsertBefore { - other_node: Some(new_anchor), + self.stack.create_node( + next_new, + MountType::InsertBefore { + other_node: new_anchor, }, - }); + ); } } } @@ -1081,7 +1072,7 @@ impl<'bump> DiffMachine<'bump> { self.stack.create_children( &new[old.len()..], MountType::InsertAfter { - other_node: old.last(), + other_node: old.last().unwrap(), }, ); } @@ -1098,6 +1089,10 @@ impl<'bump> DiffMachine<'bump> { } } + // ===================== + // Utilities + // ===================== + fn find_last_element(&mut self, vnode: &'bump VNode<'bump>) -> &'bump VNode<'bump> { let mut search_node = Some(vnode); @@ -1144,18 +1139,6 @@ impl<'bump> DiffMachine<'bump> { } } - // fn remove_child(&mut self, node: &'bump VNode<'bump>) { - // self.replace_and_create_many_with_many(Some(node), None); - // } - - fn replace_and_create_one_with_one( - &mut self, - old: &'bump VNode<'bump>, - new: &'bump VNode<'bump>, - ) { - self.stack.create_node(new, MountType::Replace { old }); - } - fn replace_many_with_many(&mut self, old: &'bump [VNode<'bump>], new: &'bump [VNode<'bump>]) { // } @@ -1316,10 +1299,8 @@ impl<'bump> DiffMachine<'bump> { old_node: &'bump VNode<'bump>, new_node: &'bump VNode<'bump>, ) { - self.stack.instructions.push(DiffInstruction::Create { - and: MountType::Replace { old: old_node }, - node: new_node, - }); + self.stack + .create_node(new_node, MountType::Replace { old: old_node }); } fn fix_listener<'a>(&mut self, listener: &'a Listener<'a>) { diff --git a/packages/core/src/diff_stack.rs b/packages/core/src/diff_stack.rs index 296bdd1d0..b82658e29 100644 --- a/packages/core/src/diff_stack.rs +++ b/packages/core/src/diff_stack.rs @@ -16,7 +16,6 @@ pub enum DiffInstruction<'a> { Create { node: &'a VNode<'a>, - and: MountType<'a>, }, Remove { @@ -41,13 +40,14 @@ pub enum MountType<'a> { Absorb, Append, Replace { old: &'a VNode<'a> }, - InsertAfter { other_node: Option<&'a VNode<'a>> }, - InsertBefore { other_node: Option<&'a VNode<'a>> }, + ReplaceByElementId { old: ElementId }, + InsertAfter { other_node: &'a VNode<'a> }, + InsertBefore { other_node: &'a VNode<'a> }, } pub struct DiffStack<'bump> { - pub instructions: Vec>, - pub nodes_created_stack: SmallVec<[usize; 10]>, + instructions: Vec>, + nodes_created_stack: SmallVec<[usize; 10]>, pub scope_stack: SmallVec<[ScopeId; 5]>, } @@ -77,24 +77,25 @@ impl<'bump> DiffStack<'bump> { self.instructions.push(DiffInstruction::Mount { and }); for child in children.into_iter().rev() { - self.instructions.push(DiffInstruction::Create { - and: MountType::Absorb, - node: child, - }); + self.instructions + .push(DiffInstruction::Create { node: child }); } } pub fn create_node(&mut self, node: &'bump VNode<'bump>, and: MountType<'bump>) { self.nodes_created_stack.push(0); self.instructions.push(DiffInstruction::Mount { and }); - self.instructions - .push(DiffInstruction::Create { and, node }); + self.instructions.push(DiffInstruction::Create { node }); } pub fn add_child_count(&mut self, count: usize) { *self.nodes_created_stack.last_mut().unwrap() += count; } + pub fn pop_nodes_created(&mut self) -> usize { + self.nodes_created_stack.pop().unwrap() + } + pub fn current_scope(&self) -> Option { self.scope_stack.last().map(|f| f.clone()) } @@ -107,9 +108,6 @@ impl<'bump> DiffStack<'bump> { // Run the creation algorithm with this scope on the stack // ?? I think we treat components as framgnets?? - self.instructions.push(DiffInstruction::Create { - node, - and: MountType::Absorb, - }); + self.instructions.push(DiffInstruction::Create { node }); } } diff --git a/packages/core/src/editor.rs b/packages/core/src/dom_edits.rs similarity index 93% rename from packages/core/src/editor.rs rename to packages/core/src/dom_edits.rs index 9aa887832..cbb70f248 100644 --- a/packages/core/src/editor.rs +++ b/packages/core/src/dom_edits.rs @@ -20,22 +20,29 @@ pub enum DomEdit<'bump> { id: u64, }, PopRoot, + AppendChildren { many: u32, }, + + // "Root" refers to the item direclty + // it's a waste of an instruction to push the root directly ReplaceWith { + root: u64, m: u32, }, InsertAfter { + root: u64, n: u32, }, InsertBefore { + root: u64, n: u32, }, - // remove roots directly Remove { root: u64, }, + RemoveAllChildren, CreateTextNode { text: &'bump str, diff --git a/packages/core/src/lib.rs b/packages/core/src/lib.rs index 34f8d3ce9..ed4e8ce9f 100644 --- a/packages/core/src/lib.rs +++ b/packages/core/src/lib.rs @@ -11,9 +11,9 @@ //! pub use crate::innerlude::{ - format_args_f, html, rsx, Context, DioxusElement, DomEdit, DomTree, ElementId, EventPriority, - EventTrigger, LazyNodes, Mutations, NodeFactory, Properties, ScopeId, SuspendedContext, VNode, - VirtualDom, VirtualEvent, FC, + format_args_f, html, rsx, Context, DiffInstruction, DioxusElement, DomEdit, DomTree, ElementId, + EventPriority, EventTrigger, LazyNodes, MountType, Mutations, NodeFactory, Properties, ScopeId, + SuspendedContext, VNode, VirtualDom, VirtualEvent, FC, }; pub mod prelude { @@ -35,7 +35,7 @@ pub(crate) mod innerlude { pub use crate::context::*; pub use crate::diff::*; pub use crate::diff_stack::*; - pub use crate::editor::*; + pub use crate::dom_edits::*; pub use crate::error::*; pub use crate::events::*; pub use crate::heuristics::*; @@ -67,7 +67,7 @@ pub mod component; pub mod context; pub mod diff; pub mod diff_stack; -pub mod editor; +pub mod dom_edits; pub mod error; pub mod events; pub mod heuristics; diff --git a/packages/core/src/mutations.rs b/packages/core/src/mutations.rs index d45a9bba4..afefc1cf0 100644 --- a/packages/core/src/mutations.rs +++ b/packages/core/src/mutations.rs @@ -31,16 +31,19 @@ impl<'a> Mutations<'a> { self.edits.push(PopRoot {}); } - pub(crate) fn replace_with(&mut self, m: u32) { - self.edits.push(ReplaceWith { m }); + pub(crate) fn replace_with(&mut self, root: ElementId, m: u32) { + let root = root.as_u64(); + self.edits.push(ReplaceWith { m, root }); } - pub(crate) fn insert_after(&mut self, n: u32) { - self.edits.push(InsertAfter { n }); + pub(crate) fn insert_after(&mut self, root: ElementId, n: u32) { + let root = root.as_u64(); + self.edits.push(InsertAfter { n, root }); } - pub(crate) fn insert_before(&mut self, n: u32) { - self.edits.push(InsertBefore { n }); + pub(crate) fn insert_before(&mut self, root: ElementId, n: u32) { + let root = root.as_u64(); + self.edits.push(InsertBefore { n, root }); } // Remove Nodesfrom the dom diff --git a/packages/core/src/virtual_dom.rs b/packages/core/src/virtual_dom.rs index 5a68e3008..2718aa222 100644 --- a/packages/core/src/virtual_dom.rs +++ b/packages/core/src/virtual_dom.rs @@ -173,10 +173,9 @@ impl VirtualDom { // // We run the component. If it succeeds, then we can diff it and add the changes to the dom. if cur_component.run_scope().is_ok() { - diff_machine.stack.push(DiffInstruction::Create { - node: cur_component.frames.fin_head(), - and: MountType::Append, - }); + diff_machine + .stack + .create_node(cur_component.frames.fin_head(), MountType::Append); diff_machine.work().await.unwrap(); } else { // todo: should this be a hard error? diff --git a/packages/core/tests/create_iterative.rs b/packages/core/tests/create_iterative.rs index e797fff05..519e97141 100644 --- a/packages/core/tests/create_iterative.rs +++ b/packages/core/tests/create_iterative.rs @@ -1,16 +1,11 @@ //! tests to prove that the iterative implementation works use anyhow::{Context, Result}; -use dioxus::{ - arena::SharedResources, - diff::{CreateMeta, DiffMachine}, - prelude::*, - scheduler::Mutations, - DomEdit, -}; +use dioxus::{arena::SharedResources, diff::DiffMachine, prelude::*, DomEdit, Mutations}; mod test_logging; use dioxus_core as dioxus; use dioxus_html as dioxus_elements; +use DomEdit::*; #[test] fn test_original_diff() { @@ -26,11 +21,24 @@ fn test_original_diff() { let mut dom = VirtualDom::new(App); let mutations = dom.rebuild().unwrap(); - dbg!(mutations); + assert_eq!( + mutations.edits, + [ + CreateElement { id: 0, tag: "div" }, + CreateElement { id: 1, tag: "div" }, + CreateTextNode { + id: 2, + text: "Hello, world!" + }, + AppendChildren { many: 1 }, + AppendChildren { many: 1 }, + AppendChildren { many: 1 }, + ] + ); } #[async_std::test] -async fn test_iterative_create() { +async fn create() { static App: FC<()> = |cx| { cx.render(rsx! { div { @@ -50,14 +58,38 @@ async fn test_iterative_create() { }; test_logging::set_up_logging(); - let mut dom = VirtualDom::new(App); let mutations = dom.rebuild_async().await.unwrap(); - dbg!(mutations); + assert_eq!( + mutations.edits, + [ + CreateElement { id: 0, tag: "div" }, + CreateElement { id: 1, tag: "div" }, + CreateTextNode { + id: 2, + text: "Hello, world!" + }, + CreateElement { id: 3, tag: "div" }, + CreateElement { id: 4, tag: "div" }, + CreateTextNode { + id: 5, + text: "hello" + }, + CreateTextNode { + id: 6, + text: "world" + }, + AppendChildren { many: 2 }, + AppendChildren { many: 1 }, + AppendChildren { many: 2 }, + AppendChildren { many: 1 }, + AppendChildren { many: 1 }, + ] + ); } #[async_std::test] -async fn test_iterative_create_list() { +async fn create_list() { static App: FC<()> = |cx| { cx.render(rsx! { {(0..3).map(|f| rsx!{ div { @@ -70,11 +102,36 @@ async fn test_iterative_create_list() { let mut dom = VirtualDom::new(App); let mutations = dom.rebuild_async().await.unwrap(); - dbg!(mutations); + + // copilot wrote this test :P + assert_eq!( + mutations.edits, + [ + CreateElement { id: 0, tag: "div" }, + CreateTextNode { + id: 1, + text: "hello" + }, + AppendChildren { many: 1 }, + CreateElement { id: 2, tag: "div" }, + CreateTextNode { + id: 3, + text: "hello" + }, + AppendChildren { many: 1 }, + CreateElement { id: 4, tag: "div" }, + CreateTextNode { + id: 5, + text: "hello" + }, + AppendChildren { many: 1 }, + AppendChildren { many: 3 }, + ] + ); } #[async_std::test] -async fn test_iterative_create_simple() { +async fn create_simple() { static App: FC<()> = |cx| { cx.render(rsx! { div {} @@ -88,11 +145,22 @@ async fn test_iterative_create_simple() { let mut dom = VirtualDom::new(App); let mutations = dom.rebuild_async().await.unwrap(); - dbg!(mutations); + + // copilot wrote this test :P + assert_eq!( + mutations.edits, + [ + CreateElement { id: 0, tag: "div" }, + CreateElement { id: 1, tag: "div" }, + CreateElement { id: 2, tag: "div" }, + CreateElement { id: 3, tag: "div" }, + AppendChildren { many: 4 }, + ] + ); } #[async_std::test] -async fn test_iterative_create_components() { +async fn create_components() { static App: FC<()> = |cx| { cx.render(rsx! { Child { "abc1" } @@ -113,5 +181,81 @@ async fn test_iterative_create_components() { let mut dom = VirtualDom::new(App); let mutations = dom.rebuild_async().await.unwrap(); - dbg!(mutations); + + assert_eq!( + mutations.edits, + [ + CreateElement { id: 0, tag: "h1" }, + CreateElement { id: 1, tag: "div" }, + CreateTextNode { + id: 2, + text: "abc1" + }, + AppendChildren { many: 1 }, + CreateElement { id: 3, tag: "p" }, + CreateElement { id: 4, tag: "h1" }, + CreateElement { id: 5, tag: "div" }, + CreateTextNode { + id: 6, + text: "abc2" + }, + AppendChildren { many: 1 }, + CreateElement { id: 7, tag: "p" }, + CreateElement { id: 8, tag: "h1" }, + CreateElement { id: 9, tag: "div" }, + CreateTextNode { + id: 10, + text: "abc3" + }, + AppendChildren { many: 1 }, + CreateElement { id: 11, tag: "p" }, + AppendChildren { many: 9 }, + ] + ); +} + +#[async_std::test] +async fn anchors() { + static App: FC<()> = |cx| { + cx.render(rsx! { + {true.then(|| rsx!{ div { "hello" } })} + {false.then(|| rsx!{ div { "goodbye" } })} + }) + }; + + test_logging::set_up_logging(); + + let mut dom = VirtualDom::new(App); + let mutations = dom.rebuild_async().await.unwrap(); + assert_eq!( + mutations.edits, + [ + CreateElement { id: 0, tag: "div" }, + CreateTextNode { + id: 1, + text: "hello" + }, + AppendChildren { many: 1 }, + CreatePlaceholder { id: 2 }, + AppendChildren { many: 2 }, + ] + ); +} + +#[async_std::test] +async fn suspended() { + static App: FC<()> = |cx| { + let val = use_suspense(cx, || async {}, |cx, _| cx.render(rsx! { "hi "})); + cx.render(rsx! { {val} }) + }; + + test_logging::set_up_logging(); + + let mut dom = VirtualDom::new(App); + let mutations = dom.rebuild_async().await.unwrap(); + + assert_eq!( + mutations.edits, + [CreatePlaceholder { id: 0 }, AppendChildren { many: 1 },] + ); } diff --git a/packages/core/tests/diffing.rs b/packages/core/tests/diffing.rs index 640aad610..a4ce42240 100644 --- a/packages/core/tests/diffing.rs +++ b/packages/core/tests/diffing.rs @@ -8,10 +8,7 @@ use bumpalo::Bump; use anyhow::{Context, Result}; use dioxus::{ - arena::SharedResources, - diff::{DiffInstruction, DiffMachine}, - prelude::*, - DomEdit, + arena::SharedResources, diff::DiffMachine, prelude::*, DiffInstruction, DomEdit, MountType, }; use dioxus_core as dioxus; use dioxus_html as dioxus_elements; @@ -43,9 +40,7 @@ impl TestDom { // let mut edits = Vec::new(); let mut machine = DiffMachine::new_headless(&self.resources); - machine - .stack - .push(dioxus::diff::DiffInstruction::DiffNode { new, old }); + machine.stack.push(DiffInstruction::DiffNode { new, old }); machine.mutations } @@ -58,10 +53,8 @@ impl TestDom { let mut machine = DiffMachine::new_headless(&self.resources); - machine.stack.push(dioxus::diff::DiffInstruction::Create { - node: old, - and: dioxus::diff::MountType::Append, - }); + machine.stack.create_node(old, MountType::Append); + work_sync(&mut machine); machine.mutations @@ -83,10 +76,9 @@ impl TestDom { // let mut create_edits = Vec::new(); let mut machine = DiffMachine::new_headless(&self.resources); - machine.stack.push(dioxus::diff::DiffInstruction::Create { - and: dioxus::diff::MountType::Append, - node: old, - }); + + machine.stack.create_node(old, MountType::Append); + work_sync(&mut machine); let create_edits = machine.mutations; diff --git a/packages/core/tests/eventsystem.rs b/packages/core/tests/eventsystem.rs index cb593dee7..919b0a447 100644 --- a/packages/core/tests/eventsystem.rs +++ b/packages/core/tests/eventsystem.rs @@ -1,12 +1,7 @@ use bumpalo::Bump; use anyhow::{Context, Result}; -use dioxus::{ - arena::SharedResources, - diff::{CreateMeta, DiffMachine}, - prelude::*, - DomEdit, -}; +use dioxus::{arena::SharedResources, diff::DiffMachine, prelude::*, DomEdit}; use dioxus_core as dioxus; use dioxus_html as dioxus_elements; diff --git a/packages/core/tests/hooks.rs b/packages/core/tests/hooks.rs index 2c434eabe..42f15db4b 100644 --- a/packages/core/tests/hooks.rs +++ b/packages/core/tests/hooks.rs @@ -1,10 +1,5 @@ use anyhow::{Context, Result}; -use dioxus::{ - arena::SharedResources, - diff::{CreateMeta, DiffMachine}, - prelude::*, - DomEdit, -}; +use dioxus::{arena::SharedResources, diff::DiffMachine, prelude::*, DomEdit}; use dioxus_core as dioxus; use dioxus_html as dioxus_elements; diff --git a/packages/core/tests/test_logging.rs b/packages/core/tests/test_logging.rs index 8783dd6d2..41498a9e9 100644 --- a/packages/core/tests/test_logging.rs +++ b/packages/core/tests/test_logging.rs @@ -17,7 +17,9 @@ pub fn set_up_logging() { // just clone `colors_line` and overwrite our changes let colors_level = colors_line.clone().info(Color::Green); // here we set up our fern Dispatch - fern::Dispatch::new() + + // when running tests in batch, the logger is re-used, so ignore the logger error + let _ = fern::Dispatch::new() .format(move |out, message, record| { out.finish(format_args!( "{color_line}[{level}{color_line}] {message}\x1B[0m", @@ -42,6 +44,5 @@ pub fn set_up_logging() { // .level_for("pretty_colored", log::LevelFilter::Trace) // output to stdout .chain(std::io::stdout()) - .apply() - .unwrap(); + .apply(); } diff --git a/packages/core/tests/work_sync.rs b/packages/core/tests/work_sync.rs index 187a4443b..ed9269bc7 100644 --- a/packages/core/tests/work_sync.rs +++ b/packages/core/tests/work_sync.rs @@ -3,12 +3,7 @@ //! This means you can actually call it synchronously if you want. use anyhow::{Context, Result}; -use dioxus::{ - arena::SharedResources, - diff::{CreateMeta, DiffInstruction, DiffMachine}, - prelude::*, - scope::Scope, -}; +use dioxus::{arena::SharedResources, diff::DiffMachine, prelude::*, scope::Scope}; use dioxus_core as dioxus; use dioxus_html as dioxus_elements; use futures_util::FutureExt;