wip: basic support for scheduled rendering

This commit is contained in:
Jonathan Kelley committed 2021-07-14 18:19:51 -04:00
1 parent 80e6c25698
commit c52af221f7
8 files changed
+93 -80

No files matched your search

-1
View File
@@ -13,7 +13,6 @@ proc-macro = true
[dependencies] [dependencies]
once_cell = "1.7.2" once_cell = "1.7.2"
proc-macro-hack = "0.5.19"
proc-macro2 = { version = "1.0.6" } proc-macro2 = { version = "1.0.6" }
quote = "1.0" quote = "1.0"
syn = { version = "1.0.11", features = ["full", "extra-traits"] } syn = { version = "1.0.11", features = ["full", "extra-traits"] }
+7 -1
View File
@@ -66,6 +66,11 @@ impl RealDomNode {
let key: DefaultKey = data.into(); let key: DefaultKey = data.into();
Self(key) 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> { pub fn empty_cell() -> Cell<Self> {
Cell::new(Self::empty()) Cell::new(Self::empty())
} }
@@ -102,7 +107,8 @@ impl<'a> RealDom<'a> for DebugDom {
async fn launch_demo(app: FC<()>) { async fn launch_demo(app: FC<()>) {
let mut dom = VirtualDom::new(app); let mut dom = VirtualDom::new(app);
let mut real_dom = DebugDom::new(); 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 { while let Some(evt) = dom.tasks.next().await {
// //
+13 -10
View File
@@ -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. /// 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<()> { pub fn rebuild_in_place(&mut self) -> Result<()> {
let mut realdom = DebugDom::new(); 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 /// 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 /// 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 /// 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<()> { pub fn rebuild<'s, Dom: RealDom<'s>>(
let mut edits = Vec::new(); &'s mut self,
realdom: &mut Dom,
edits: &mut Vec<DomEdit<'s>>,
) -> Result<()> {
let mut diff_machine = DiffMachine::new( let mut diff_machine = DiffMachine::new(
&mut edits, edits,
realdom, realdom,
&self.components, &self.components,
self.base_scope, self.base_scope,
@@ -211,7 +215,6 @@ impl VirtualDom {
); );
let cur_component = self.components.try_get_mut(self.base_scope).unwrap(); let cur_component = self.components.try_get_mut(self.base_scope).unwrap();
cur_component.run_scope()?; cur_component.run_scope()?;
let meta = diff_machine.create(cur_component.next_frame()); 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>>( pub async fn progress_with_event<'s, Dom: RealDom<'s>>(
&'s mut self, &'s mut self,
realdom: &'_ mut Dom, realdom: &'_ mut Dom,
edits: &mut Vec<DomEdit<'s>>,
) -> Result<()> { ) -> Result<()> {
let trigger = self.triggers.borrow_mut().pop().expect("failed"); let trigger = self.triggers.borrow_mut().pop().expect("failed");
let mut edits = Vec::new();
let mut diff_machine = DiffMachine::new( let mut diff_machine = DiffMachine::new(
&mut edits, edits,
realdom, realdom,
&self.components, &self.components,
trigger.originator, trigger.originator,
@@ -295,9 +298,9 @@ impl VirtualDom {
VirtualEvent::OtherEvent => todo!(), VirtualEvent::OtherEvent => todo!(),
// Fiber events // Fiber events
VirtualEvent::FiberEvent => { // VirtualEvent::FiberEvent => {
// // //
} // }
// This is the "meat" of our cooperative scheduler // 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 // As updates flow in, we re-evalute the event queue and decide if we should be switching the type of work
+1 -12
View File
@@ -17,7 +17,7 @@ use dioxus_web::*;
fn main() { fn main() {
// Setup logging // 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(); console_error_panic_hook::set_once();
// Run the app // Run the app
@@ -37,17 +37,6 @@ static App: FC<()> = |cx| {
let set_val = state.setter(); let set_val = state.setter();
let (tas, g) = cx.use_task(|| async move { 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); set_val(10);
surf::get(ENDPOINT).recv_json::<DogApi>().await surf::get(ENDPOINT).recv_json::<DogApi>().await
}); });
+43 -39
View File
@@ -72,53 +72,57 @@ impl WebsysRenderer {
websys_dom.stack.push(root_node.clone()); websys_dom.stack.push(root_node.clone());
websys_dom.stack.push(root_node); 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"); log::info!("Going into event loop");
// loop { loop {
let trigger = { let trigger = {
let real_queue = websys_dom.wait_for_event(); let real_queue = websys_dom.wait_for_event();
if self.internal_dom.tasks.is_empty() { if self.internal_dom.tasks.is_empty() {
log::info!("tasks is empty, waiting for dom event to trigger soemthing"); log::info!("tasks is empty, waiting for dom event to trigger soemthing");
real_queue.await real_queue.await
} else { } else {
log::info!("tasks is not empty, waiting for either tasks or event system"); log::info!("tasks is not empty, waiting for either tasks or event system");
let task_queue = (&mut self.internal_dom.tasks).next(); let task_queue = (&mut self.internal_dom.tasks).next();
pin_mut!(real_queue); pin_mut!(real_queue);
pin_mut!(task_queue); pin_mut!(task_queue);
match futures_util::future::select(real_queue, task_queue).await { match futures_util::future::select(real_queue, task_queue).await {
futures_util::future::Either::Left((trigger, _)) => trigger, futures_util::future::Either::Left((trigger, _)) => trigger,
futures_util::future::Either::Right((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());
self.internal_dom.queue_event(real_trigger)?;
let mut edits = Vec::new();
self.internal_dom
.progress_with_event(&mut websys_dom, &mut edits)
.await?;
websys_dom.process_edits(&mut edits);
} }
};
if let Some(real_trigger) = trigger { // let t2 = self.internal_dom.tasks.next();
log::info!("event received"); // futures::select! {
// let root_node = body_element.first_child().unwrap(); // trigger = t1 => {
// websys_dom.stack.push(root_node.clone()); // log::info!("event received");
// let root_node = body_element.first_child().unwrap();
self.internal_dom.queue_event(real_trigger)?; // websys_dom.stack.push(root_node.clone());
// self.internal_dom
self.internal_dom // .progress_with_event(&mut websys_dom, trigger)?;
.progress_with_event(&mut websys_dom) // },
.await?; // () = 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 { // while let Some(trigger) = websys_dom.wait_for_event().await {
// } // }
+21 -12
View File
@@ -13,7 +13,7 @@ use web_sys::{
pub struct WebsysDom { pub struct WebsysDom {
pub stack: Stack, pub stack: Stack,
nodes: slotmap::SlotMap<DefaultKey, Node>, nodes: slotmap::SlotMap<DefaultKey, Option<Node>>,
document: Document, document: Document,
root: Element, root: Element,
@@ -51,7 +51,7 @@ impl WebsysDom {
let mut nodes = slotmap::SlotMap::with_capacity(1000); 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 { Self {
stack: Stack::with_capacity(10), stack: Stack::with_capacity(10),
@@ -72,6 +72,7 @@ impl WebsysDom {
pub fn process_edits(&mut self, edits: &mut Vec<DomEdit>) { pub fn process_edits(&mut self, edits: &mut Vec<DomEdit>) {
for edit in edits.drain(..) { for edit in edits.drain(..) {
log::info!("Handling edit: {:#?}", edit);
match edit { match edit {
DomEdit::PushRoot { root } => self.push(root), DomEdit::PushRoot { root } => self.push(root),
DomEdit::PopRoot => self.pop(), DomEdit::PopRoot => self.pop(),
@@ -90,18 +91,19 @@ impl WebsysDom {
idx, idx,
} => self.new_event_listener(event, scope, idx, node), } => self.new_event_listener(event, scope, idx, node),
DomEdit::RemoveEventListener { event } => todo!(), DomEdit::RemoveEventListener { event } => todo!(),
DomEdit::SetText { text } => todo!(), DomEdit::SetText { text } => self.set_text(text),
DomEdit::SetAttribute { field, value, ns } => todo!(), DomEdit::SetAttribute { field, value, ns } => self.set_attribute(field, value, ns),
DomEdit::RemoveAttribute { name } => todo!(), DomEdit::RemoveAttribute { name } => self.remove_attribute(name),
} }
} }
} }
fn push(&mut self, root: RealDomNode) { fn push(&mut self, root: RealDomNode) {
let key = root.0; let key = root.0;
let domnode = self let domnode = self.nodes.get_mut(key);
.nodes
.get(key) let domnode = domnode.unwrap().as_mut().unwrap();
.expect(&format!("Failed to pop know root: {:#?}", key)); // .expect(&format!("Failed to pop know root: {:#?}", key))
// .unwrap();
self.stack.push(domnode.clone()); self.stack.push(domnode.clone());
} }
@@ -189,14 +191,17 @@ impl WebsysDom {
} }
fn create_text_node(&mut self, text: &str, id: RealDomNode) { fn create_text_node(&mut self, text: &str, id: RealDomNode) {
// let nid = self.node_counter.next(); // let nid = self.node_counter.next();
let textnode = self let textnode = self
.document .document
.create_text_node(text) .create_text_node(text)
.dyn_into::<Node>() .dyn_into::<Node>()
.unwrap(); .unwrap();
self.stack.push(textnode.clone());
todo!(); self.stack.push(textnode.clone());
let mut slot = self.nodes.get_mut(id.0).unwrap();
*slot = Some(textnode);
// let nid = self.nodes.insert(textnode); // let nid = self.nodes.insert(textnode);
// let nid = nid.data().as_ffi(); // let nid = nid.data().as_ffi();
@@ -223,6 +228,8 @@ impl WebsysDom {
}; };
self.stack.push(el.clone()); 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.node_counter.?next();
// let nid = self.nodes.insert(el).data().as_ffi(); // let nid = self.nodes.insert(el).data().as_ffi();
// log::debug!("Called [`create_element`]: {}, {:?}", tag, nid); // log::debug!("Called [`create_element`]: {}, {:?}", tag, nid);
@@ -331,7 +338,9 @@ impl WebsysDom {
impl<'a> dioxus_core::diff::RealDom<'a> for WebsysDom { impl<'a> dioxus_core::diff::RealDom<'a> for WebsysDom {
fn request_available_node(&mut self) -> RealDomNode { 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 { fn raw_node_as_any(&self) -> &mut dyn std::any::Any {
+2 -1
View File
@@ -37,6 +37,7 @@ impl<'bump> RealDom<'bump> for WebviewDom<'bump> {
} }
fn request_available_node(&mut self) -> RealDomNode { fn request_available_node(&mut self) -> RealDomNode {
todo!() self.node_counter += 1;
RealDomNode::from_u64(self.node_counter)
} }
} }
+6 -4
View File
@@ -87,8 +87,9 @@ impl<T: Properties + 'static> WebviewRenderer<T> {
// Serialize the edit stream // Serialize the edit stream
let edits = { let edits = {
lock.rebuild(&mut real).unwrap(); let mut edits = Vec::new();
serde_json::to_value(&real.edits).unwrap() lock.rebuild(&mut real, &mut edits).unwrap();
serde_json::to_value(edits).unwrap()
}; };
// Give back the registry into its slot // Give back the registry into its slot
@@ -108,8 +109,9 @@ impl<T: Properties + 'static> WebviewRenderer<T> {
// Serialize the edit stream // Serialize the edit stream
let edits = { let edits = {
lock.rebuild(&mut real).unwrap(); let mut edits = Vec::new();
serde_json::to_value(&real.edits).unwrap() lock.rebuild(&mut real, &mut edits).unwrap();
serde_json::to_value(edits).unwrap()
}; };
// Give back the registry into its slot // Give back the registry into its slot