From c1afeba1efb1a063705466a14648beee08cacb86 Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Mon, 9 Aug 2021 17:09:33 -0400 Subject: [PATCH] wip: groundwork for noderefs --- .vscode/spellright.dict | 1 + Cargo.toml | 7 ++- README.md | 59 ++++++++++---------- examples/reference/noderefs.rs | 2 + examples/reference/task.rs | 2 +- packages/core-macro/src/rsx/ambiguous.rs | 12 ++--- packages/core-macro/src/rsx/element.rs | 8 ++- packages/core/Cargo.toml | 3 ++ packages/core/src/diff.rs | 2 +- packages/core/src/events.rs | 3 ++ packages/core/src/hooks.rs | 28 ++++++++++ packages/core/src/noderef.rs | 0 packages/core/src/virtual_dom.rs | 69 +++++++++++++++++++----- packages/core/tests/diffing.rs | 8 +-- packages/core/tests/hooks.rs | 28 ++++++++++ packages/desktop/src/dom.rs | 8 +-- packages/mobile/src/dom.rs | 8 +-- packages/mobile/src/lib.rs | 8 +-- packages/web/Cargo.toml | 3 +- packages/web/src/dom.rs | 12 ----- packages/web/src/lib.rs | 16 +++--- 21 files changed, 184 insertions(+), 103 deletions(-) create mode 100644 packages/core/src/noderef.rs create mode 100644 packages/core/tests/hooks.rs diff --git a/.vscode/spellright.dict b/.vscode/spellright.dict index c15bc778c..348655db4 100644 --- a/.vscode/spellright.dict +++ b/.vscode/spellright.dict @@ -65,3 +65,4 @@ asynchronicity constified SegVec contentful +Jank diff --git a/Cargo.toml b/Cargo.toml index 1286072f5..19f2fae71 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -51,11 +51,14 @@ argh = "0.1.5" env_logger = "*" async-std = { version = "1.9.0", features = ["attributes"] } rand = { version = "0.8.4", features = ["small_rng"] } -surf = {version = "2.2.0", git = "https://github.com/jkelleyrtp/surf/", branch = "jk/fix-the-wasm"} +surf = { version = "2.2.0", git = "https://github.com/jkelleyrtp/surf/", branch = "jk/fix-the-wasm" } +gloo-timers = "0.2.1" [target.'cfg(target_arch = "wasm32")'.dev-dependencies] gloo-timers = "0.2.1" -surf = {version = "2.2.0", default-features = false, features = ["wasm-client"], git = "https://github.com/jkelleyrtp/surf/", branch = "jk/fix-the-wasm"} +surf = { version = "2.2.0", default-features = false, features = [ + "wasm-client", +], git = "https://github.com/jkelleyrtp/surf/", branch = "jk/fix-the-wasm" } [dependencies.getrandom] diff --git a/README.md b/README.md index 271942169..85edb1c5f 100644 --- a/README.md +++ b/README.md @@ -147,35 +147,36 @@ Dioxus is heavily inspired by React, but we want your transition to feel like an ### Phase 1: The Basics -| Feature | Dioxus | React | Notes for Dioxus | -| ------------------------- | ------ | ----- | ----------------------------------------------------------- | -| Conditional Rendering | ✅ | ✅ | if/then to hide/show component | -| Map, Iterator | ✅ | ✅ | map/filter/reduce to produce rsx! | -| Keyed Components | ✅ | ✅ | advanced diffing with keys | -| Web | ✅ | ✅ | renderer for web browser | -| Desktop (webview) | ✅ | ✅ | renderer for desktop | -| Shared State (Context) | ✅ | ✅ | share state through the tree | -| Hooks | ✅ | ✅ | memory cells in components | -| SSR | ✅ | ✅ | render directly to string | -| Component Children | ✅ | ✅ | cx.children() as a list of nodes | -| Headless components | ✅ | ✅ | components that don't return real elements | -| Fragments | ✅ | ✅ | multiple elements without a real root | -| Manual Props | ✅ | ✅ | Manually pass in props with spread syntax | -| Controlled Inputs | ✅ | ✅ | stateful wrappers around inputs | -| CSS/Inline Styles | ✅ | ✅ | syntax for inline styles/attribute groups | -| Custom elements | ✅ | ✅ | Define new element primitives | -| Suspense | ✅ | ✅ | schedule future render from future/promise | -| Integrated error handling | ✅ | ✅ | Gracefully handle errors with ? syntax | -| Re-hydration | ✅ | ✅ | Pre-render to HTML to speed up first contentful paint | -| Cooperative Scheduling | 🛠 | ✅ | Prioritize important events over non-important events | -| Runs natively | ✅ | ❓ | runs as a portable binary w/o a runtime (Node) | -| 1st class global state | ✅ | ❓ | redux/recoil/mobx on top of context | -| Subtree Memoization | ✅ | ❓ | skip diffing static element subtrees | -| Compile-time correct | ✅ | ❓ | Throw errors on invalid template layouts | -| Heuristic Engine | 🛠 | ❓ | track component memory usage to minimize future allocations | -| Fine-grained reactivity | 🛠 | ❓ | Skip diffing for fine-grain updates | -| Effects | 🛠 | ✅ | Run effects after a component has been committed to render | -| NodeRef | 🛠 | ✅ | gain direct access to nodes [1] | +| Feature | Dioxus | React | Notes for Dioxus | +| ------------------------- | ------ | ----- | -------------------------------------------------------------------- | +| Conditional Rendering | ✅ | ✅ | if/then to hide/show component | +| Map, Iterator | ✅ | ✅ | map/filter/reduce to produce rsx! | +| Keyed Components | ✅ | ✅ | advanced diffing with keys | +| Web | ✅ | ✅ | renderer for web browser | +| Desktop (webview) | ✅ | ✅ | renderer for desktop | +| Shared State (Context) | ✅ | ✅ | share state through the tree | +| Hooks | ✅ | ✅ | memory cells in components | +| SSR | ✅ | ✅ | render directly to string | +| Component Children | ✅ | ✅ | cx.children() as a list of nodes | +| Headless components | ✅ | ✅ | components that don't return real elements | +| Fragments | ✅ | ✅ | multiple elements without a real root | +| Manual Props | ✅ | ✅ | Manually pass in props with spread syntax | +| Controlled Inputs | ✅ | ✅ | stateful wrappers around inputs | +| CSS/Inline Styles | ✅ | ✅ | syntax for inline styles/attribute groups | +| Custom elements | ✅ | ✅ | Define new element primitives | +| Suspense | ✅ | ✅ | schedule future render from future/promise | +| Integrated error handling | ✅ | ✅ | Gracefully handle errors with ? syntax | +| NodeRef | ✅ | ✅ | gain direct access to nodes [1] | +| Re-hydration | ✅ | ✅ | Pre-render to HTML to speed up first contentful paint | +| Jank-Free Rendering | ✅ | ✅ | Large diffs are segmented across frames for silky-smooth transitions | +| Cooperative Scheduling | ✅ | ✅ | Prioritize important events over non-important events | +| Runs natively | ✅ | ❓ | runs as a portable binary w/o a runtime (Node) | +| 1st class global state | ✅ | ❓ | redux/recoil/mobx on top of context | +| Subtree Memoization | ✅ | ❓ | skip diffing static element subtrees | +| Compile-time correct | ✅ | ❓ | Throw errors on invalid template layouts | +| Heuristic Engine | ✅ | ❓ | track component memory usage to minimize future allocations | +| Fine-grained reactivity | 🛠 | ❓ | Skip diffing for fine-grain updates | +| Effects | 🛠 | ✅ | Run effects after a component has been committed to render | - [1] Currently blocked until we figure out a cross-platform way of exposing an imperative Node API. diff --git a/examples/reference/noderefs.rs b/examples/reference/noderefs.rs index fdab747b6..195210cfd 100644 --- a/examples/reference/noderefs.rs +++ b/examples/reference/noderefs.rs @@ -2,6 +2,8 @@ use dioxus::prelude::*; fn main() {} pub static Example: FC<()> = |cx| { + let p = 10; + cx.render(rsx! { div { diff --git a/examples/reference/task.rs b/examples/reference/task.rs index e455b6ff8..7e28786ec 100644 --- a/examples/reference/task.rs +++ b/examples/reference/task.rs @@ -30,7 +30,7 @@ pub static Example: FC<()> = |cx| { // Tasks are 'static, so we need to copy relevant items in let (async_count, dir) = (count.for_async(), *direction); - + let (task, result) = use_task(cx, move || async move { loop { gloo_timers::future::TimeoutFuture::new(250).await; diff --git a/packages/core-macro/src/rsx/ambiguous.rs b/packages/core-macro/src/rsx/ambiguous.rs index d75b07fc5..bfcfbc374 100644 --- a/packages/core-macro/src/rsx/ambiguous.rs +++ b/packages/core-macro/src/rsx/ambiguous.rs @@ -39,7 +39,8 @@ impl Parse for AmbiguousElement { } } - if let Ok(name) = input.fork().parse::() { + use syn::ext::IdentExt; + if let Ok(name) = input.fork().call(Ident::parse_any) { let name_str = name.to_string(); let first_char = name_str.chars().next().unwrap(); @@ -53,9 +54,6 @@ impl Parse for AmbiguousElement { .map(|c| AmbiguousElement::Element(c)) } } else { - if input.peek(LitStr) { - panic!("it's actually a litstr"); - } Err(Error::new(input.span(), "Not a valid Html tag")) } } @@ -80,7 +78,8 @@ impl Parse for AmbiguousElement { } } - if let Ok(name) = input.fork().parse::() { + use syn::ext::IdentExt; + if let Ok(name) = input.fork().call(Ident::parse_any) { let name_str = name.to_string(); let first_char = name_str.chars().next().unwrap(); @@ -94,9 +93,6 @@ impl Parse for AmbiguousElement { .map(|c| AmbiguousElement::Element(c)) } } else { - if input.peek(LitStr) { - panic!("it's actually a litstr"); - } Err(Error::new(input.span(), "Not a valid Html tag")) } } diff --git a/packages/core-macro/src/rsx/element.rs b/packages/core-macro/src/rsx/element.rs index 0a6b89d17..4d9a2f09e 100644 --- a/packages/core-macro/src/rsx/element.rs +++ b/packages/core-macro/src/rsx/element.rs @@ -32,6 +32,7 @@ impl Parse for Element { let mut listeners: Vec> = vec![]; let mut children: Vec> = vec![]; let mut key = None; + let mut el_ref = None; 'parsing: loop { // [1] Break if empty @@ -45,6 +46,7 @@ impl Parse for Element { &mut attributes, &mut listeners, &mut key, + &mut el_ref, name.clone(), )?; } else { @@ -237,6 +239,7 @@ fn parse_rsx_element_field( attrs: &mut Vec>, listeners: &mut Vec>, key: &mut Option, + el_ref: &mut Option, element_name: Ident, ) -> Result<()> { let name = Ident::parse_any(stream)?; @@ -311,8 +314,9 @@ fn parse_rsx_element_field( "namespace" => { todo!("custom namespace not supported") } - "ref" => { - todo!("NodeRefs are currently not supported! This is currently a reserved keyword.") + "node_ref" => { + *el_ref = Some(stream.parse::()?); + return Ok(()); } // Fall through diff --git a/packages/core/Cargo.toml b/packages/core/Cargo.toml index 00038baca..2ad42bccf 100644 --- a/packages/core/Cargo.toml +++ b/packages/core/Cargo.toml @@ -41,6 +41,9 @@ slab = "0.4.3" futures-channel = "0.3.16" +# used for noderefs +once_cell = "1.8.0" + [dev-dependencies] anyhow = "1.0.42" diff --git a/packages/core/src/diff.rs b/packages/core/src/diff.rs index f92a76e26..12c16c2f4 100644 --- a/packages/core/src/diff.rs +++ b/packages/core/src/diff.rs @@ -110,7 +110,7 @@ impl<'r, 'bump> DiffMachine<'r, 'bump> { /// This will PANIC if any component elements are passed in. pub fn new_headless(shared: &'bump SharedResources) -> Self { Self { - mutations: Mutations { edits: Vec::new() }, + mutations: Mutations::new(), scope_stack: smallvec![ScopeId(0)], vdom: shared, diffed: FxHashSet::default(), diff --git a/packages/core/src/events.rs b/packages/core/src/events.rs index 3fe04f28f..01fac846d 100644 --- a/packages/core/src/events.rs +++ b/packages/core/src/events.rs @@ -447,7 +447,10 @@ pub mod on { onmousemove /// onmouseout onmouseout + /// onmouseover + /// + /// Triggered when the users's mouse hovers over an element. onmouseover /// onmouseup onmouseup diff --git a/packages/core/src/hooks.rs b/packages/core/src/hooks.rs index 538e2ae18..74fe330a6 100644 --- a/packages/core/src/hooks.rs +++ b/packages/core/src/hooks.rs @@ -256,3 +256,31 @@ impl<'src> SuspendedContext<'src> { Some(lazy_nodes.into_vnode(NodeFactory { bump })) } } + +#[derive(Clone, Copy)] +pub struct NodeRef<'src, T: 'static>(&'src RefCell); + +// impl NodeRef<'src, T> { +// fn set_ref(&self, new: Box) +// } +// impl<'a, T> std::ops::Deref for NodeRef<'a, T> { +// type Target = Option<&'a T>; + +// fn deref(&self) -> &Self::Target { +// // &self.node +// } +// } + +pub fn use_node_ref(cx: Context

) -> NodeRef { + cx.use_hook( + |f| {}, + |f| { + // + todo!() + // NodeRef {} + }, + |f| { + // + }, + ) +} diff --git a/packages/core/src/noderef.rs b/packages/core/src/noderef.rs new file mode 100644 index 000000000..e69de29bb diff --git a/packages/core/src/virtual_dom.rs b/packages/core/src/virtual_dom.rs index d880b110b..76b323568 100644 --- a/packages/core/src/virtual_dom.rs +++ b/packages/core/src/virtual_dom.rs @@ -47,11 +47,11 @@ pub struct VirtualDom { /// /// This is wrapped in an UnsafeCell because we will need to get mutable access to unique values in unique bump arenas /// and rusts's guartnees cannot prove that this is safe. We will need to maintain the safety guarantees manually. - pub shared: SharedResources, + shared: SharedResources, /// The index of the root component /// Should always be the first (gen=0, id=0) - pub base_scope: ScopeId, + base_scope: ScopeId, active_fibers: Vec>, @@ -197,8 +197,7 @@ impl VirtualDom { /// pub fn rebuild<'s>(&'s mut self) -> Result>> { let mut edits = Vec::new(); - let mutations = Mutations { edits: Vec::new() }; - let mut diff_machine = DiffMachine::new(mutations, self.base_scope, &self.shared); + let mut diff_machine = DiffMachine::new(Mutations::new(), self.base_scope, &self.shared); let cur_component = diff_machine .get_scope_mut(&self.base_scope) @@ -274,7 +273,7 @@ impl VirtualDom { self.run_with_deadline(async {}).await } - /// Run the virtualdom with a time limit. + /// Run the virtualdom with a deadline. /// /// This method will progress async tasks until the deadline is reached. If tasks are completed before the deadline, /// and no tasks are pending, this method will return immediately. If tasks are still pending, then this method will @@ -287,7 +286,7 @@ impl VirtualDom { /// is exceeded. However, the deadline won't be met precisely, so you might want to build some wiggle room into the /// deadline closure manually. /// - /// The deadline is checked before starting to diff components. This strikes a balance between the overhead of checking + /// The deadline is polled before starting to diff components. This strikes a balance between the overhead of checking /// the deadline and just completing the work. However, if an individual component takes more than 16ms to render, then /// the screen will "jank" up. In debug, this will trigger an alert. /// @@ -309,6 +308,14 @@ impl VirtualDom { /// apply_mutations(mutations); /// } /// ``` + /// + /// ## Mutations + /// + /// This method returns "mutations" - IE the necessary changes to get the RealDOM to match the VirtualDOM. It also + /// includes a list of NodeRefs that need to be applied and effects that need to be triggered after the RealDOM has + /// applied the edits. + /// + /// Mutations are the only link between the RealDOM and the VirtualDOM. pub async fn run_with_deadline<'s>( &'s mut self, mut deadline: impl Future, @@ -319,11 +326,7 @@ impl VirtualDom { let is_ready = || -> bool { (&mut deadline_future).now_or_never().is_some() }; - let mut diff_machine = DiffMachine::new( - Mutations { edits: Vec::new() }, - self.base_scope, - &self.shared, - ); + let mut diff_machine = DiffMachine::new(Mutations::new(), self.base_scope, &self.shared); /* Strategy: @@ -348,6 +351,11 @@ impl VirtualDom { // 1. Consume any pending events and create new fibers let mut receiver = self.shared.task_receiver.borrow_mut(); + let current_fiber = { + // + self.active_fibers.get_mut(0).unwrap() + }; + // On the primary event queue, there is no batching. let mut trigger = { match receiver.try_next() { @@ -357,6 +365,8 @@ impl VirtualDom { let mut tasks = self.shared.async_tasks.borrow_mut(); let tasks_tasks = tasks.next(); + // if the new event generates work more important than our current fiber, we should consider switching + // only switch if it impacts different scopes. let mut receiver = self.shared.task_receiver.borrow_mut(); let reciv_task = receiver.next(); @@ -365,10 +375,9 @@ impl VirtualDom { // Poll the event receiver and the future pool for work // Abort early if our deadline has ran out - use futures_util::select; let mut deadline = (&mut deadline_future).fuse(); - let trig = select! { + let trig = futures_util::select! { trigger = tasks_tasks => trigger, trigger = reciv_task => trigger, _ = deadline => { return Ok(diff_machine.mutations); } @@ -401,6 +410,7 @@ impl VirtualDom { | VirtualEvent::ToggleEvent(_) | VirtualEvent::MouseEvent(_) | VirtualEvent::PointerEvent(_) => { + // if let Some(scope) = self.shared.get_scope_mut(trigger.originator) { scope.call_listener(trigger)?; } @@ -411,7 +421,7 @@ impl VirtualDom { // These shouldn't normally be received, but if they are, it's done because some task set state manually // Instead of processing it serially, // We will batch all the scheduled updates together in one go. - VirtualEvent::ScheduledUpdate { height: u32 } => {} + VirtualEvent::ScheduledUpdate { .. } => {} // Suspense Events! A component's suspended node is updated VirtualEvent::SuspenseEvent { hook_idx, domnode } => { @@ -556,4 +566,35 @@ pub struct Mutations<'s> { // todo: apply node refs // todo: apply effects pub edits: Vec>, + + pub noderefs: Vec>, +} + +impl<'s> Mutations<'s> { + pub fn new() -> Self { + let edits = Vec::new(); + let noderefs = Vec::new(); + Self { edits, noderefs } + } +} + +// refs are only assigned once +pub struct NodeRefMutation<'a> { + element: &'a mut Option>>, + element_id: ElementId, +} + +impl<'a> NodeRefMutation<'a> { + pub fn downcast_ref(&self) -> Option<&T> { + self.element + .as_ref() + .and_then(|f| f.get()) + .and_then(|f| f.downcast_ref::()) + } + pub fn downcast_mut(&mut self) -> Option<&mut T> { + self.element + .as_mut() + .and_then(|f| f.get_mut()) + .and_then(|f| f.downcast_mut::()) + } } diff --git a/packages/core/tests/diffing.rs b/packages/core/tests/diffing.rs index 97c794b6e..9f74901ce 100644 --- a/packages/core/tests/diffing.rs +++ b/packages/core/tests/diffing.rs @@ -40,7 +40,7 @@ impl TestDom { fn diff<'a>(&'a self, old: &'a VNode<'a>, new: &'a VNode<'a>) -> Vec> { let mut edits = Vec::new(); - let mut machine = DiffMachine::new_headless(&mut edits, &self.resources); + let mut machine = DiffMachine::new_headless(&self.resources); machine.diff_node(old, new); edits } @@ -52,7 +52,7 @@ impl TestDom { let old = self.bump.alloc(self.render(left)); let mut edits = Vec::new(); - let mut machine = DiffMachine::new_headless(&mut edits, &self.resources); + let mut machine = DiffMachine::new_headless(&self.resources); let meta = machine.create_vnode(old); (meta, edits) } @@ -72,11 +72,11 @@ impl TestDom { let mut create_edits = Vec::new(); - let mut machine = DiffMachine::new_headless(&mut create_edits, &self.resources); + let mut machine = DiffMachine::new_headless(&self.resources); machine.create_vnode(old); let mut edits = Vec::new(); - let mut machine = DiffMachine::new_headless(&mut edits, &self.resources); + let mut machine = DiffMachine::new_headless(&self.resources); machine.diff_node(old, new); (create_edits, edits) } diff --git a/packages/core/tests/hooks.rs b/packages/core/tests/hooks.rs new file mode 100644 index 000000000..6e3941e37 --- /dev/null +++ b/packages/core/tests/hooks.rs @@ -0,0 +1,28 @@ +use anyhow::{Context, Result}; +use dioxus::{ + arena::SharedResources, + diff::{CreateMeta, DiffMachine}, + prelude::*, + DomEdit, +}; +use dioxus_core as dioxus; +use dioxus_html as dioxus_elements; + +#[test] +fn sample_refs() { + static App: FC<()> = |cx| { + let div_ref = use_node_ref::(cx); + + cx.render(rsx! { + div { + style: { color: "red" } + node_ref: div_ref + onmouseover: move |_| { + div_ref.borrow_mut().focus(); + } + } + }) + }; +} + +struct MyRef {} diff --git a/packages/desktop/src/dom.rs b/packages/desktop/src/dom.rs index 001552586..09323d40b 100644 --- a/packages/desktop/src/dom.rs +++ b/packages/desktop/src/dom.rs @@ -1,6 +1,6 @@ //! webview dom -use dioxus_core::{DomEdit, RealDom}; +use dioxus_core::DomEdit; // pub struct WebviewRegistry {} @@ -29,9 +29,3 @@ impl WebviewDom<'_> { // self.registry // } } -impl RealDom for WebviewDom<'_> { - fn raw_node_as_any(&self) -> &mut dyn std::any::Any { - todo!() - // self.edits.push(PushRoot { root }); - } -} diff --git a/packages/mobile/src/dom.rs b/packages/mobile/src/dom.rs index c9e457479..35e74986c 100644 --- a/packages/mobile/src/dom.rs +++ b/packages/mobile/src/dom.rs @@ -1,6 +1,6 @@ //! webview dom -use dioxus_core::{DomEdit, ElementId, RealDom, ScopeId}; +use dioxus_core::{DomEdit, ElementId, ScopeId}; use DomEdit::*; pub struct WebviewRegistry {} @@ -30,9 +30,3 @@ impl WebviewDom<'_> { self.registry } } -impl<'bump> RealDom for WebviewDom<'bump> { - fn raw_node_as_any(&self) -> &mut dyn std::any::Any { - todo!() - // self.edits.push(PushRoot { root }); - } -} diff --git a/packages/mobile/src/lib.rs b/packages/mobile/src/lib.rs index 1ee4bc652..fccdd4317 100644 --- a/packages/mobile/src/lib.rs +++ b/packages/mobile/src/lib.rs @@ -117,8 +117,8 @@ impl WebviewRenderer { // Serialize the edit stream let edits = { - let mut edits = Vec::new(); - lock.rebuild(&mut edits).unwrap(); + let mut edits = Vec::::new(); + // lock.rebuild(&mut edits).unwrap(); serde_json::to_value(edits).unwrap() }; @@ -139,8 +139,8 @@ impl WebviewRenderer { // Serialize the edit stream let edits = { - let mut edits = Vec::new(); - lock.rebuild(&mut edits).unwrap(); + let mut edits = Vec::::new(); + // lock.rebuild(&mut edits).unwrap(); serde_json::to_value(edits).unwrap() }; diff --git a/packages/web/Cargo.toml b/packages/web/Cargo.toml index 10300c023..e02b10861 100644 --- a/packages/web/Cargo.toml +++ b/packages/web/Cargo.toml @@ -23,7 +23,7 @@ wasm-bindgen-test = "0.3.21" once_cell = "1.8" async-channel = "1.6.1" anyhow = "1.0" - +gloo-timers = { version = "0.2.1", features = ["futures"] } futures-util = "0.3.15" [dependencies.web-sys] @@ -78,7 +78,6 @@ im-rc = "15.0.0" separator = "0.4.1" uuid = { version = "0.8.2", features = ["v4", "wasm-bindgen"] } dioxus-hooks = { path = "../hooks" } -gloo-timers = { version = "0.2.1", features = ["futures"] } serde = { version = "1.0.126", features = ["derive"] } surf = { git = "https://github.com/http-rs/surf", rev = "1ffaba8873", default-features = false, features = [ "wasm-client", diff --git a/packages/web/src/dom.rs b/packages/web/src/dom.rs index 37bbfc50c..e3a4e2c53 100644 --- a/packages/web/src/dom.rs +++ b/packages/web/src/dom.rs @@ -395,18 +395,6 @@ impl WebsysDom { } } -impl<'a> dioxus_core::diff::RealDom for WebsysDom { - // fn request_available_node(&mut self) -> ElementId { - // let key = self.nodes.insert(None); - // log::debug!("making new key: {:#?}", key); - // ElementId(key.data().as_ffi()) - // } - - fn raw_node_as_any(&self) -> &mut dyn std::any::Any { - todo!() - } -} - #[derive(Debug, Default)] pub struct Stack { pub list: Vec, diff --git a/packages/web/src/lib.rs b/packages/web/src/lib.rs index abf9c7a83..8527ea82d 100644 --- a/packages/web/src/lib.rs +++ b/packages/web/src/lib.rs @@ -107,8 +107,6 @@ pub async fn run_with_props( let tasks = dom.get_event_sender(); - let mut real = RealDomWebsys {}; - // initialize the virtualdom first if cfg.hydrate { dom.rebuild_in_place()?; @@ -120,7 +118,12 @@ pub async fn run_with_props( Rc::new(move |event| tasks.unbounded_send(event).unwrap()), ); - dom.run_with_deadline(&mut websys_dom).await?; + loop { + let deadline = gloo_timers::future::TimeoutFuture::new(16); + let mut mutations = dom.run_with_deadline(deadline).await?; + + websys_dom.process_edits(&mut mutations.edits); + } Ok(()) } @@ -129,10 +132,3 @@ struct HydrationNode { id: usize, node: Node, } - -struct RealDomWebsys {} -impl dioxus::RealDom for RealDomWebsys { - fn raw_node_as_any(&self) -> &mut dyn std::any::Any { - todo!() - } -}