Răsfoiți Sursa

feat: move over to push based mechanism

Jonathan Kelley 4 ani în urmă
părinte
comite
80e6c25

+ 1 - 2
packages/core/src/context.rs

@@ -305,8 +305,7 @@ Any function prefixed with "use" should not be called conditionally.
     ) -> (&TaskHandle, &mut Option<Out>)
     where
         Out: 'static,
-        Fut: Future<Output = Out>,
-        Fut: 'static,
+        Fut: Future<Output = Out> + 'static,
         Init: FnOnce() -> Fut + 'src,
     {
         struct TaskHook<T> {

+ 8 - 8
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) {

+ 12 - 12
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,
     },
 }

+ 10 - 8
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 const fn empty() -> Self {
-        Self(u64::MIN)
+    pub fn empty() -> Self {
+        let data = KeyData::from_ffi(u64::MIN);
+        let key: DefaultKey = data.into();
+        Self(key)
     }
-    pub const fn empty_cell() -> Cell<Self> {
+    pub fn empty_cell() -> Cell<Self> {
         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!()
     }
 

+ 2 - 3
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::<DogApi>().await
-        // String::from("Huzza!")
     });
 
     let dog_node = match g.as_ref().and_then(|f| f.as_ref().ok()) {

+ 62 - 36
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<DomEdit>) {
+        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::<Node>()
             .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();
+
+        // log::debug!("Called [`create_text_node`]: {}, {}", text, nid);
 
-        RealDomNode::new(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::<Element>() {
                 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::<web_sys::Element>() {
             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<EventTrigger> {
         .next()
         .and_then(|f| f.parse::<u64>().ok())
         .context("failed to parse gi id")?;
-    // let el_id = fields
-    //     .next()
-    //     .and_then(|f| f.parse::<usize>().ok())
-    //     .context("failed to parse el id")?;
+
     let real_id = fields
         .next()
-        .and_then(|f| f.parse::<u64>().ok().map(RealDomNode::new))
+        .and_then(|raw_id| {
+            raw_id
+                .parse::<u64>()
+                .ok()
+                .map(|value| KeyData::from_ffi(value))
+                .map(|f| RealDomNode(f.into()))
+        })
         .context("failed to parse real id")?;
 
     // Call the trigger

+ 1 - 1
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 });
     }