mirror of
https://github.com/DioxusLabs/dioxus
synced 2024-11-10 06:34:20 +00:00
wip: basic support for scheduled rendering
This commit is contained in:
parent
80e6c25698
commit
c52af221f7
8 changed files with 93 additions and 80 deletions
|
@ -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"] }
|
||||
|
|
|
@ -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 {
|
||||
//
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
});
|
||||
|
|
|
@ -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());
|
||||
|
||||
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 {
|
||||
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
|
||||
.progress_with_event(&mut websys_dom)
|
||||
.await?;
|
||||
// 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 {
|
||||
// }
|
||||
|
||||
|
|
|
@ -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());
|
||||
|
||||
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 = 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 {
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue