Переглянути джерело

wip: basic support for scheduled rendering

Jonathan Kelley 4 роки тому
батько
коміт
c52af22

+ 0 - 1
packages/core-macro/Cargo.toml

@@ -13,7 +13,6 @@ proc-macro = true
 
 [dependencies]
 once_cell = "1.7.2"
-proc-macro-hack = "0.5.19"
 proc-macro2 = { version = "1.0.6" }
 quote = "1.0"
 syn = { version = "1.0.11", features = ["full", "extra-traits"] }

+ 7 - 1
packages/core/src/util.rs

@@ -66,6 +66,11 @@ impl RealDomNode {
         let key: DefaultKey = data.into();
         Self(key)
     }
+    pub fn from_u64(id: u64) -> Self {
+        let data = KeyData::from_ffi(id);
+        let key: DefaultKey = data.into();
+        Self(key)
+    }
     pub fn empty_cell() -> Cell<Self> {
         Cell::new(Self::empty())
     }
@@ -102,7 +107,8 @@ impl<'a> RealDom<'a> for DebugDom {
 async fn launch_demo(app: FC<()>) {
     let mut dom = VirtualDom::new(app);
     let mut real_dom = DebugDom::new();
-    dom.rebuild(&mut real_dom).unwrap();
+    let mut edits = Vec::new();
+    dom.rebuild(&mut real_dom, &mut edits).unwrap();
 
     while let Some(evt) = dom.tasks.next().await {
         //

+ 13 - 10
packages/core/src/virtual_dom.rs

@@ -191,7 +191,8 @@ impl VirtualDom {
     /// SSR takes advantage of this by using Dioxus itself as the source of truth, and rendering from the tree directly.
     pub fn rebuild_in_place(&mut self) -> Result<()> {
         let mut realdom = DebugDom::new();
-        self.rebuild(&mut realdom)
+        let mut edits = Vec::new();
+        self.rebuild(&mut realdom, &mut edits)
     }
 
     /// Performs a *full* rebuild of the virtual dom, returning every edit required to generate the actual dom rom scratch
@@ -199,10 +200,13 @@ impl VirtualDom {
     /// Currently this doesn't do what we want it to do
     ///
     /// The diff machine expects the RealDom's stack to be the root of the application
-    pub fn rebuild<'s, Dom: RealDom<'s>>(&'s mut self, realdom: &mut Dom) -> Result<()> {
-        let mut edits = Vec::new();
+    pub fn rebuild<'s, Dom: RealDom<'s>>(
+        &'s mut self,
+        realdom: &mut Dom,
+        edits: &mut Vec<DomEdit<'s>>,
+    ) -> Result<()> {
         let mut diff_machine = DiffMachine::new(
-            &mut edits,
+            edits,
             realdom,
             &self.components,
             self.base_scope,
@@ -211,7 +215,6 @@ impl VirtualDom {
         );
 
         let cur_component = self.components.try_get_mut(self.base_scope).unwrap();
-
         cur_component.run_scope()?;
 
         let meta = diff_machine.create(cur_component.next_frame());
@@ -278,12 +281,12 @@ impl VirtualDom {
     pub async fn progress_with_event<'s, Dom: RealDom<'s>>(
         &'s mut self,
         realdom: &'_ mut Dom,
+        edits: &mut Vec<DomEdit<'s>>,
     ) -> Result<()> {
         let trigger = self.triggers.borrow_mut().pop().expect("failed");
 
-        let mut edits = Vec::new();
         let mut diff_machine = DiffMachine::new(
-            &mut edits,
+            edits,
             realdom,
             &self.components,
             trigger.originator,
@@ -295,9 +298,9 @@ impl VirtualDom {
             VirtualEvent::OtherEvent => todo!(),
 
             // Fiber events
-            VirtualEvent::FiberEvent => {
-                //
-            }
+            // VirtualEvent::FiberEvent => {
+            //     //
+            // }
 
             // This is the "meat" of our cooperative scheduler
             // As updates flow in, we re-evalute the event queue and decide if we should be switching the type of work

+ 1 - 12
packages/web/examples/async_web.rs

@@ -17,7 +17,7 @@ use dioxus_web::*;
 
 fn main() {
     // Setup logging
-    // wasm_logger::init(wasm_logger::Config::new(log::Level::Debug));
+    wasm_logger::init(wasm_logger::Config::new(log::Level::Debug));
     console_error_panic_hook::set_once();
 
     // Run the app
@@ -37,17 +37,6 @@ static App: FC<()> = |cx| {
     let set_val = state.setter();
 
     let (tas, g) = cx.use_task(|| async move {
-        let mut tick: i32 = 0;
-        log::debug!("yeet!");
-        // loop {
-        //     gloo_timers::future::TimeoutFuture::new(250).await;
-        //     log::debug!("ticking forward... {}", tick);
-        //     tick += 1;
-        //     if tick > 10 {
-        //         break;
-        //     }
-        // }
-        // String::from("Huzza!")
         set_val(10);
         surf::get(ENDPOINT).recv_json::<DogApi>().await
     });

+ 42 - 38
packages/web/src/lib.rs

@@ -72,53 +72,57 @@ impl WebsysRenderer {
         websys_dom.stack.push(root_node.clone());
         websys_dom.stack.push(root_node);
 
-        self.internal_dom.rebuild(&mut websys_dom)?;
+        let mut edits = Vec::new();
+        self.internal_dom.rebuild(&mut websys_dom, &mut edits)?;
+        websys_dom.process_edits(&mut edits);
 
         log::info!("Going into event loop");
-        // loop {
-        let trigger = {
-            let real_queue = websys_dom.wait_for_event();
-            if self.internal_dom.tasks.is_empty() {
-                log::info!("tasks is empty, waiting for dom event to trigger soemthing");
-                real_queue.await
-            } else {
-                log::info!("tasks is not empty, waiting for either tasks or event system");
-                let task_queue = (&mut self.internal_dom.tasks).next();
+        loop {
+            let trigger = {
+                let real_queue = websys_dom.wait_for_event();
+                if self.internal_dom.tasks.is_empty() {
+                    log::info!("tasks is empty, waiting for dom event to trigger soemthing");
+                    real_queue.await
+                } else {
+                    log::info!("tasks is not empty, waiting for either tasks or event system");
+                    let task_queue = (&mut self.internal_dom.tasks).next();
 
-                pin_mut!(real_queue);
-                pin_mut!(task_queue);
+                    pin_mut!(real_queue);
+                    pin_mut!(task_queue);
 
-                match futures_util::future::select(real_queue, task_queue).await {
-                    futures_util::future::Either::Left((trigger, _)) => trigger,
-                    futures_util::future::Either::Right((trigger, _)) => trigger,
+                    match futures_util::future::select(real_queue, task_queue).await {
+                        futures_util::future::Either::Left((trigger, _)) => trigger,
+                        futures_util::future::Either::Right((trigger, _)) => trigger,
+                    }
                 }
-            }
-        };
+            };
 
-        if let Some(real_trigger) = trigger {
-            log::info!("event received");
-            // let root_node = body_element.first_child().unwrap();
-            // websys_dom.stack.push(root_node.clone());
+            if let Some(real_trigger) = trigger {
+                log::info!("event received");
+                // let root_node = body_element.first_child().unwrap();
+                // websys_dom.stack.push(root_node.clone());
 
-            self.internal_dom.queue_event(real_trigger)?;
+                self.internal_dom.queue_event(real_trigger)?;
 
-            self.internal_dom
-                .progress_with_event(&mut websys_dom)
-                .await?;
-        }
+                let mut edits = Vec::new();
+                self.internal_dom
+                    .progress_with_event(&mut websys_dom, &mut edits)
+                    .await?;
+                websys_dom.process_edits(&mut edits);
+            }
 
-        // let t2 = self.internal_dom.tasks.next();
-        // futures::select! {
-        //     trigger = t1 => {
-        //         log::info!("event received");
-        //         let root_node = body_element.first_child().unwrap();
-        //         websys_dom.stack.push(root_node.clone());
-        //         self.internal_dom
-        //             .progress_with_event(&mut websys_dom, trigger)?;
-        //     },
-        //     () = t2 => {}
-        // };
-        // }
+            // let t2 = self.internal_dom.tasks.next();
+            // futures::select! {
+            //     trigger = t1 => {
+            //         log::info!("event received");
+            //         let root_node = body_element.first_child().unwrap();
+            //         websys_dom.stack.push(root_node.clone());
+            //         self.internal_dom
+            //             .progress_with_event(&mut websys_dom, trigger)?;
+            //     },
+            //     () = t2 => {}
+            // };
+        }
         // while let Some(trigger) = websys_dom.wait_for_event().await {
         // }
 

+ 20 - 11
packages/web/src/new.rs

@@ -13,7 +13,7 @@ use web_sys::{
 
 pub struct WebsysDom {
     pub stack: Stack,
-    nodes: slotmap::SlotMap<DefaultKey, Node>,
+    nodes: slotmap::SlotMap<DefaultKey, Option<Node>>,
     document: Document,
     root: Element,
 
@@ -51,7 +51,7 @@ impl WebsysDom {
 
         let mut nodes = slotmap::SlotMap::with_capacity(1000);
 
-        let root_id = nodes.insert(root.clone().dyn_into::<Node>().unwrap());
+        let root_id = nodes.insert(Some(root.clone().dyn_into::<Node>().unwrap()));
 
         Self {
             stack: Stack::with_capacity(10),
@@ -72,6 +72,7 @@ impl WebsysDom {
 
     pub fn process_edits(&mut self, edits: &mut Vec<DomEdit>) {
         for edit in edits.drain(..) {
+            log::info!("Handling edit: {:#?}", edit);
             match edit {
                 DomEdit::PushRoot { root } => self.push(root),
                 DomEdit::PopRoot => self.pop(),
@@ -90,18 +91,19 @@ impl WebsysDom {
                     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!(),
+                DomEdit::SetText { text } => self.set_text(text),
+                DomEdit::SetAttribute { field, value, ns } => self.set_attribute(field, value, ns),
+                DomEdit::RemoveAttribute { name } => self.remove_attribute(name),
             }
         }
     }
     fn push(&mut self, root: RealDomNode) {
         let key = root.0;
-        let domnode = self
-            .nodes
-            .get(key)
-            .expect(&format!("Failed to pop know root: {:#?}", key));
+        let domnode = self.nodes.get_mut(key);
+
+        let domnode = domnode.unwrap().as_mut().unwrap();
+        // .expect(&format!("Failed to pop know root: {:#?}", key))
+        // .unwrap();
 
         self.stack.push(domnode.clone());
     }
@@ -189,14 +191,17 @@ impl WebsysDom {
     }
     fn create_text_node(&mut self, text: &str, id: RealDomNode) {
         // let nid = self.node_counter.next();
+
         let textnode = self
             .document
             .create_text_node(text)
             .dyn_into::<Node>()
             .unwrap();
+
         self.stack.push(textnode.clone());
+        let mut slot = self.nodes.get_mut(id.0).unwrap();
+        *slot = Some(textnode);
 
-        todo!();
         // let nid = self.nodes.insert(textnode);
         // let nid = nid.data().as_ffi();
 
@@ -223,6 +228,8 @@ impl WebsysDom {
         };
 
         self.stack.push(el.clone());
+        let mut slot = self.nodes.get_mut(id.0).unwrap();
+        *slot = Some(el);
         // let nid = self.node_counter.?next();
         // let nid = self.nodes.insert(el).data().as_ffi();
         // log::debug!("Called [`create_element`]: {}, {:?}", tag, nid);
@@ -331,7 +338,9 @@ impl WebsysDom {
 
 impl<'a> dioxus_core::diff::RealDom<'a> for WebsysDom {
     fn request_available_node(&mut self) -> RealDomNode {
-        todo!()
+        let key = self.nodes.insert(None);
+        log::debug!("making new key: {:#?}", key);
+        RealDomNode(key)
     }
 
     fn raw_node_as_any(&self) -> &mut dyn std::any::Any {

+ 2 - 1
packages/webview/src/dom.rs

@@ -37,6 +37,7 @@ impl<'bump> RealDom<'bump> for WebviewDom<'bump> {
     }
 
     fn request_available_node(&mut self) -> RealDomNode {
-        todo!()
+        self.node_counter += 1;
+        RealDomNode::from_u64(self.node_counter)
     }
 }

+ 6 - 4
packages/webview/src/lib.rs

@@ -87,8 +87,9 @@ impl<T: Properties + 'static> WebviewRenderer<T> {
 
                             // Serialize the edit stream
                             let edits = {
-                                lock.rebuild(&mut real).unwrap();
-                                serde_json::to_value(&real.edits).unwrap()
+                                let mut edits = Vec::new();
+                                lock.rebuild(&mut real, &mut edits).unwrap();
+                                serde_json::to_value(edits).unwrap()
                             };
 
                             // Give back the registry into its slot
@@ -108,8 +109,9 @@ impl<T: Properties + 'static> WebviewRenderer<T> {
 
                         // Serialize the edit stream
                         let edits = {
-                            lock.rebuild(&mut real).unwrap();
-                            serde_json::to_value(&real.edits).unwrap()
+                            let mut edits = Vec::new();
+                            lock.rebuild(&mut real, &mut edits).unwrap();
+                            serde_json::to_value(edits).unwrap()
                         };
 
                         // Give back the registry into its slot