diff --git a/packages/core/src/context.rs b/packages/core/src/context.rs index a8b8596a6..b0aeb8401 100644 --- a/packages/core/src/context.rs +++ b/packages/core/src/context.rs @@ -305,8 +305,7 @@ Any function prefixed with "use" should not be called conditionally. ) -> (&TaskHandle, &mut Option) where Out: 'static, - Fut: Future, - Fut: 'static, + Fut: Future + 'static, Init: FnOnce() -> Fut + 'src, { struct TaskHook { diff --git a/packages/core/src/diff.rs b/packages/core/src/diff.rs index d6dee1150..9733a6348 100644 --- a/packages/core/src/diff.rs +++ b/packages/core/src/diff.rs @@ -66,8 +66,8 @@ use std::any::Any; /// target-specific Node type as well as easily serializing the edits to be sent over a network or IPC connection. pub trait RealDom<'a> { fn request_available_node(&mut self) -> RealDomNode; - // node ref - fn raw_node_as_any_mut(&self) -> &mut dyn Any; + + fn raw_node_as_any(&self) -> &mut dyn Any; } pub struct DomEditor<'real, 'bump> { @@ -77,7 +77,7 @@ use DomEdit::*; impl<'real, 'bump> DomEditor<'real, 'bump> { // Navigation pub(crate) fn push(&mut self, root: RealDomNode) { - self.edits.push(PushRoot { root: root.0 }); + self.edits.push(PushRoot { root }); } pub(crate) fn pop(&mut self) { self.edits.push(PopRoot {}); @@ -105,7 +105,7 @@ impl<'real, 'bump> DomEditor<'real, 'bump> { // Create pub(crate) fn create_text_node(&mut self, text: &'bump str, id: RealDomNode) { - self.edits.push(CreateTextNode { text, id: id.0 }); + self.edits.push(CreateTextNode { text, id }); } pub(crate) fn create_element( &mut self, @@ -114,14 +114,14 @@ impl<'real, 'bump> DomEditor<'real, 'bump> { id: RealDomNode, ) { match ns { - Some(ns) => self.edits.push(CreateElementNs { id: id.0, ns, tag }), - None => self.edits.push(CreateElement { id: id.0, tag }), + Some(ns) => self.edits.push(CreateElementNs { id, ns, tag }), + None => self.edits.push(CreateElement { id, tag }), } } // placeholders are nodes that don't get rendered but still exist as an "anchor" in the real dom pub(crate) fn create_placeholder(&mut self, id: RealDomNode) { - self.edits.push(CreatePlaceholder { id: id.0 }); + self.edits.push(CreatePlaceholder { id }); } // events @@ -136,7 +136,7 @@ impl<'real, 'bump> DomEditor<'real, 'bump> { scope, event, idx: element_id, - node: realnode.0, + node: realnode, }); } pub(crate) fn remove_event_listener(&mut self, event: &'static str) { diff --git a/packages/core/src/serialize.rs b/packages/core/src/serialize.rs index 5233d1cb5..954e9be9d 100644 --- a/packages/core/src/serialize.rs +++ b/packages/core/src/serialize.rs @@ -7,7 +7,7 @@ //! //! -use crate::innerlude::ScopeIdx; +use crate::{innerlude::ScopeIdx, RealDomNode}; use serde::{Deserialize, Serialize}; /// A `DomEdit` represents a serialzied form of the VirtualDom's trait-based API. This allows streaming edits across the @@ -16,7 +16,7 @@ use serde::{Deserialize, Serialize}; #[serde(tag = "type")] pub enum DomEdit<'bump> { PushRoot { - root: u64, + root: RealDomNode, }, PopRoot, AppendChildren { @@ -29,38 +29,38 @@ pub enum DomEdit<'bump> { RemoveAllChildren, CreateTextNode { text: &'bump str, - id: u64, + id: RealDomNode, }, CreateElement { tag: &'bump str, - id: u64, + id: RealDomNode, }, CreateElementNs { tag: &'bump str, - id: u64, - ns: &'bump str, + id: RealDomNode, + ns: &'static str, }, CreatePlaceholder { - id: u64, + id: RealDomNode, }, NewEventListener { - event: &'bump str, + event: &'static str, scope: ScopeIdx, - node: u64, + node: RealDomNode, idx: usize, }, RemoveEventListener { - event: &'bump str, + event: &'static str, }, SetText { text: &'bump str, }, SetAttribute { - field: &'bump str, + field: &'static str, value: &'bump str, ns: Option<&'bump str>, }, RemoveAttribute { - name: &'bump str, + name: &'static str, }, } diff --git a/packages/core/src/util.rs b/packages/core/src/util.rs index 0b4bc9b7f..d229e5bbe 100644 --- a/packages/core/src/util.rs +++ b/packages/core/src/util.rs @@ -4,6 +4,7 @@ use std::{ }; use futures_util::StreamExt; +use slotmap::{DefaultKey, KeyData}; use crate::innerlude::*; @@ -55,16 +56,17 @@ impl PartialOrd for HeightMarker { /// "u64" was chosen for two reasons /// - 0 cost hashing /// - use with slotmap and other versioned slot arenas + +#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))] #[derive(Clone, Copy, Debug, PartialEq)] -pub struct RealDomNode(pub u64); +pub struct RealDomNode(pub DefaultKey); impl RealDomNode { - pub fn new(id: u64) -> Self { - Self(id) + pub fn empty() -> Self { + let data = KeyData::from_ffi(u64::MIN); + let key: DefaultKey = data.into(); + Self(key) } - pub const fn empty() -> Self { - Self(u64::MIN) - } - pub const fn empty_cell() -> Cell { + pub fn empty_cell() -> Cell { Cell::new(Self::empty()) } } @@ -88,7 +90,7 @@ impl DebugDom { } } impl<'a> RealDom<'a> for DebugDom { - fn raw_node_as_any_mut(&self) -> &mut dyn std::any::Any { + fn raw_node_as_any(&self) -> &mut dyn std::any::Any { todo!() } diff --git a/packages/web/examples/async_web.rs b/packages/web/examples/async_web.rs index 3228af704..345e897ee 100644 --- a/packages/web/examples/async_web.rs +++ b/packages/web/examples/async_web.rs @@ -36,7 +36,7 @@ static App: FC<()> = |cx| { let state = use_state(cx, || 0); let set_val = state.setter(); - let g = cx.use_task(|| async move { + let (tas, g) = cx.use_task(|| async move { let mut tick: i32 = 0; log::debug!("yeet!"); // loop { @@ -47,10 +47,9 @@ static App: FC<()> = |cx| { // break; // } // } - + // String::from("Huzza!") set_val(10); surf::get(ENDPOINT).recv_json::().await - // String::from("Huzza!") }); let dog_node = match g.as_ref().and_then(|f| f.as_ref().ok()) { diff --git a/packages/web/src/new.rs b/packages/web/src/new.rs index 64d7e4108..642c39a1d 100644 --- a/packages/web/src/new.rs +++ b/packages/web/src/new.rs @@ -2,7 +2,7 @@ use std::{collections::HashMap, rc::Rc, sync::Arc}; use dioxus_core::{ events::{EventTrigger, VirtualEvent}, - RealDomNode, ScopeIdx, + DomEdit, RealDomNode, ScopeIdx, }; use fxhash::FxHashMap; use slotmap::{DefaultKey, Key, KeyData}; @@ -69,12 +69,35 @@ impl WebsysDom { let v = self.event_receiver.recv().await.unwrap(); Some(v) } -} -impl<'a> dioxus_core::diff::RealDom<'a> for WebsysDom { + pub fn process_edits(&mut self, edits: &mut Vec) { + for edit in edits.drain(..) { + match edit { + DomEdit::PushRoot { root } => self.push(root), + DomEdit::PopRoot => self.pop(), + DomEdit::AppendChildren { many } => self.append_children(many), + DomEdit::ReplaceWith { many } => self.replace_with(many), + DomEdit::Remove => self.remove(), + DomEdit::RemoveAllChildren => self.remove_all_children(), + DomEdit::CreateTextNode { text, id } => self.create_text_node(text, id), + DomEdit::CreateElement { tag, id } => self.create_element(tag, None, id), + DomEdit::CreateElementNs { tag, id, ns } => self.create_element(tag, Some(ns), id), + DomEdit::CreatePlaceholder { id } => self.create_placeholder(id), + DomEdit::NewEventListener { + event, + scope, + node, + idx, + } => self.new_event_listener(event, scope, idx, node), + DomEdit::RemoveEventListener { event } => todo!(), + DomEdit::SetText { text } => todo!(), + DomEdit::SetAttribute { field, value, ns } => todo!(), + DomEdit::RemoveAttribute { name } => todo!(), + } + } + } fn push(&mut self, root: RealDomNode) { - log::debug!("Called [push_root] {:#?}", root); - let key: DefaultKey = KeyData::from_ffi(root.0).into(); + let key = root.0; let domnode = self .nodes .get(key) @@ -161,10 +184,10 @@ impl<'a> dioxus_core::diff::RealDom<'a> for WebsysDom { todo!() } - fn create_placeholder(&mut self) -> RealDomNode { - self.create_element("pre", None) + fn create_placeholder(&mut self, id: RealDomNode) { + self.create_element("pre", None, id) } - fn create_text_node(&mut self, text: &str) -> RealDomNode { + fn create_text_node(&mut self, text: &str, id: RealDomNode) { // let nid = self.node_counter.next(); let textnode = self .document @@ -172,15 +195,17 @@ impl<'a> dioxus_core::diff::RealDom<'a> for WebsysDom { .dyn_into::() .unwrap(); self.stack.push(textnode.clone()); - let nid = self.nodes.insert(textnode); - let nid = nid.data().as_ffi(); - log::debug!("Called [`create_text_node`]: {}, {}", text, nid); + todo!(); + // let nid = self.nodes.insert(textnode); + // let nid = nid.data().as_ffi(); - RealDomNode::new(nid) + // log::debug!("Called [`create_text_node`]: {}, {}", text, nid); + + // RealDomNode::new(nid) } - fn create_element(&mut self, tag: &str, ns: Option<&'static str>) -> RealDomNode { + fn create_element(&mut self, tag: &str, ns: Option<&'static str>, id: RealDomNode) { let tag = wasm_bindgen::intern(tag); let el = match ns { Some(ns) => self @@ -199,9 +224,9 @@ impl<'a> dioxus_core::diff::RealDom<'a> for WebsysDom { self.stack.push(el.clone()); // let nid = self.node_counter.?next(); - let nid = self.nodes.insert(el).data().as_ffi(); - log::debug!("Called [`create_element`]: {}, {:?}", tag, nid); - RealDomNode::new(nid) + // let nid = self.nodes.insert(el).data().as_ffi(); + // log::debug!("Called [`create_element`]: {}, {:?}", tag, nid); + // RealDomNode::new(nid) } fn new_event_listener( @@ -213,13 +238,7 @@ impl<'a> dioxus_core::diff::RealDom<'a> for WebsysDom { ) { let (_on, event) = event.split_at(2); let event = wasm_bindgen::intern(event); - log::debug!( - "Called [`new_event_listener`]: {}, {:?}, {}, {:?}", - event, - scope, - _element_id, - real_id - ); + // attach the correct attributes to the element // these will be used by accessing the event's target // This ensures we only ever have one handler attached to the root, but decide @@ -234,8 +253,7 @@ impl<'a> dioxus_core::diff::RealDom<'a> for WebsysDom { let scope_id = scope.data().as_ffi(); el.set_attribute( &format!("dioxus-event-{}", event), - &format!("{}.{}", scope_id, real_id.0), - // &format!("{}.{}.{}", gi_id, el_id, real_id.0), + &format!("{}.{}", scope_id, real_id.0.data().as_ffi()), ) .unwrap(); @@ -265,17 +283,14 @@ impl<'a> dioxus_core::diff::RealDom<'a> for WebsysDom { } fn remove_event_listener(&mut self, event: &str) { - log::debug!("Called [`remove_event_listener`]: {}", event); todo!() } fn set_text(&mut self, text: &str) { - log::debug!("Called [`set_text`]: {}", text); self.stack.top().set_text_content(Some(text)) } fn set_attribute(&mut self, name: &str, value: &str, ns: Option<&str>) { - log::debug!("Called [`set_attribute`]: {}, {}", name, value); if name == "class" { if let Some(el) = self.stack.top().dyn_ref::() { el.set_class_name(value); @@ -288,7 +303,6 @@ impl<'a> dioxus_core::diff::RealDom<'a> for WebsysDom { } fn remove_attribute(&mut self, name: &str) { - log::debug!("Called [`remove_attribute`]: {}", name); let node = self.stack.top(); if let Some(node) = node.dyn_ref::() { node.remove_attribute(name).unwrap(); @@ -310,8 +324,17 @@ impl<'a> dioxus_core::diff::RealDom<'a> for WebsysDom { } } - fn raw_node_as_any_mut(&self) -> &mut dyn std::any::Any { - log::debug!("Called [`raw_node_as_any_mut`]"); + fn raw_node_as_any(&self) -> &mut dyn std::any::Any { + todo!() + } +} + +impl<'a> dioxus_core::diff::RealDom<'a> for WebsysDom { + fn request_available_node(&mut self) -> RealDomNode { + todo!() + } + + fn raw_node_as_any(&self) -> &mut dyn std::any::Any { todo!() } } @@ -583,13 +606,16 @@ fn decode_trigger(event: &web_sys::Event) -> anyhow::Result { .next() .and_then(|f| f.parse::().ok()) .context("failed to parse gi id")?; - // let el_id = fields - // .next() - // .and_then(|f| f.parse::().ok()) - // .context("failed to parse el id")?; + let real_id = fields .next() - .and_then(|f| f.parse::().ok().map(RealDomNode::new)) + .and_then(|raw_id| { + raw_id + .parse::() + .ok() + .map(|value| KeyData::from_ffi(value)) + .map(|f| RealDomNode(f.into())) + }) .context("failed to parse real id")?; // Call the trigger diff --git a/packages/webview/src/dom.rs b/packages/webview/src/dom.rs index 8f4cf0f29..a3c3d8c04 100644 --- a/packages/webview/src/dom.rs +++ b/packages/webview/src/dom.rs @@ -31,7 +31,7 @@ impl WebviewDom<'_> { } } impl<'bump> RealDom<'bump> for WebviewDom<'bump> { - fn raw_node_as_any_mut(&self) -> &mut dyn std::any::Any { + fn raw_node_as_any(&self) -> &mut dyn std::any::Any { todo!() // self.edits.push(PushRoot { root }); }