wip: basic support for scheduled rendering
This commit is contained in:
1 parent
80e6c25698
commit
c52af221f7
8 files changed
+93
-80
No files matched your search
@@ -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"] }
|
||||||
|
|||||||
@@ -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 {
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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 {
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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
|
||||||
|
|||||||
Reference in new issue
Block a user