feat: static node infrastructure and ssr changes
This commit is contained in:
1 parent
975fa566f9
commit
9abb0470b7
34 files changed
+1022
-855
No files matched your search
Vendored
+1
-1
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"rust-analyzer.inlayHints.enable": false
|
||||
}
|
||||
}
|
||||
@@ -23,11 +23,12 @@ generational-arena = "0.2.8"
|
||||
wasm-bindgen-test = "0.3.21"
|
||||
once_cell = "1.7.2"
|
||||
atoms = { path="../atoms" }
|
||||
|
||||
async-channel = "1.6.1"
|
||||
anyhow = "1.0.41"
|
||||
slotmap = "1.0.3"
|
||||
|
||||
futures-util = "0.3.15"
|
||||
|
||||
[dependencies.web-sys]
|
||||
version = "0.3.50"
|
||||
features = [
|
||||
@@ -72,6 +73,9 @@ crate-type = ["cdylib", "rlib"]
|
||||
|
||||
[dev-dependencies]
|
||||
im-rc = "15.0.0"
|
||||
rand = { version="0.8.4", features=["small_rng"] }
|
||||
# rand = { version="0.8.4", features=["small_rng"] }
|
||||
separator = "0.4.1"
|
||||
uuid = { version="0.8.2", features=["v4", "wasm-bindgen"] }
|
||||
dioxus-hooks = { path="../hooks" }
|
||||
gloo-timers = { version="0.2.1", features=["futures"] }
|
||||
# wasm-timer = "0.2.5"
|
||||
@@ -0,0 +1,71 @@
|
||||
//! Basic example that renders a simple VNode to the browser.
|
||||
|
||||
use dioxus::events::on::MouseEvent;
|
||||
use dioxus_core as dioxus;
|
||||
use dioxus_core::prelude::*;
|
||||
use dioxus_hooks::*;
|
||||
use dioxus_html as dioxus_elements;
|
||||
// use wasm_timer;
|
||||
|
||||
use std::future::Future;
|
||||
|
||||
use std::{pin::Pin, time::Duration};
|
||||
|
||||
use dioxus::prelude::*;
|
||||
|
||||
use dioxus_web::*;
|
||||
|
||||
fn main() {
|
||||
// Setup logging
|
||||
wasm_logger::init(wasm_logger::Config::new(log::Level::Debug));
|
||||
console_error_panic_hook::set_once();
|
||||
|
||||
// Run the app
|
||||
wasm_bindgen_futures::spawn_local(WebsysRenderer::start(App));
|
||||
}
|
||||
|
||||
static App: FC<()> = |cx| {
|
||||
// let mut count = use_state(cx, || 0);
|
||||
let fut = cx.use_hook(
|
||||
move || {
|
||||
Box::pin(async {
|
||||
let mut tick: i32 = 0;
|
||||
log::debug!("yeet!");
|
||||
loop {
|
||||
gloo_timers::future::TimeoutFuture::new(250).await;
|
||||
log::debug!("ticking forward... {}", tick);
|
||||
tick += 1;
|
||||
}
|
||||
}) as Pin<Box<dyn Future<Output = ()> + 'static>>
|
||||
},
|
||||
|h| h,
|
||||
|_| {},
|
||||
);
|
||||
|
||||
cx.submit_task(fut);
|
||||
|
||||
let state = use_state(cx, || 0);
|
||||
cx.render(rsx! {
|
||||
div {
|
||||
section { class: "py-12 px-4 text-center"
|
||||
div { class: "w-full max-w-2xl mx-auto"
|
||||
span { class: "text-sm font-semibold"
|
||||
"count: {state}"
|
||||
}
|
||||
div {
|
||||
button {
|
||||
onclick: move |_| state.set(state + 1)
|
||||
"incr"
|
||||
}
|
||||
br {}
|
||||
br {}
|
||||
button {
|
||||
onclick: move |_| state.set(state - 1)
|
||||
"decr"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
};
|
||||
@@ -0,0 +1,52 @@
|
||||
//! Basic example that renders a simple VNode to the browser.
|
||||
|
||||
use dioxus::events::on::MouseEvent;
|
||||
use dioxus_core as dioxus;
|
||||
use dioxus_core::prelude::*;
|
||||
use dioxus_hooks::*;
|
||||
use dioxus_html as dioxus_elements;
|
||||
// use wasm_timer;
|
||||
|
||||
use std::future::Future;
|
||||
|
||||
use std::{pin::Pin, time::Duration};
|
||||
|
||||
use dioxus::prelude::*;
|
||||
|
||||
use dioxus_web::*;
|
||||
|
||||
fn main() {
|
||||
// Setup logging
|
||||
wasm_logger::init(wasm_logger::Config::new(log::Level::Debug));
|
||||
console_error_panic_hook::set_once();
|
||||
|
||||
// Run the app
|
||||
wasm_bindgen_futures::spawn_local(WebsysRenderer::start(App));
|
||||
}
|
||||
|
||||
static App: FC<()> = |cx| {
|
||||
let mut state = use_state(cx, || 0);
|
||||
cx.render(rsx! {
|
||||
div {
|
||||
section { class: "py-12 px-4 text-center"
|
||||
div { class: "w-full max-w-2xl mx-auto"
|
||||
span { class: "text-sm font-semibold"
|
||||
"static subtree"
|
||||
}
|
||||
}
|
||||
}
|
||||
section { class: "py-12 px-4 text-center"
|
||||
div { class: "w-full max-w-2xl mx-auto"
|
||||
span { class: "text-sm font-semibold"
|
||||
"dynamic subtree {state}"
|
||||
}
|
||||
div {
|
||||
button { onclick: move |_| state+=1, "incr" }
|
||||
br {}
|
||||
button { onclick: move |_| state-=1, "decr" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
};
|
||||
+33
-2
@@ -3,6 +3,8 @@
|
||||
//! This crate implements a renderer of the Dioxus Virtual DOM for the web browser using Websys.
|
||||
|
||||
use dioxus::prelude::{Context, Properties, VNode};
|
||||
use futures_util::{pin_mut, Stream, StreamExt};
|
||||
|
||||
use fxhash::FxHashMap;
|
||||
use web_sys::{window, Document, Element, Event, Node};
|
||||
// use futures::{channel::mpsc, SinkExt, StreamExt};
|
||||
@@ -70,12 +72,41 @@ impl WebsysRenderer {
|
||||
|
||||
self.internal_dom.rebuild(&mut websys_dom)?;
|
||||
|
||||
while let Some(trigger) = websys_dom.wait_for_event().await {
|
||||
log::info!("Going into event loop");
|
||||
loop {
|
||||
let trigger = {
|
||||
let real_queue = websys_dom.wait_for_event();
|
||||
let task_queue = (&mut self.internal_dom.tasks).next();
|
||||
|
||||
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,
|
||||
}
|
||||
};
|
||||
|
||||
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)?;
|
||||
.progress_with_event(&mut websys_dom, trigger.unwrap())?;
|
||||
|
||||
// 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 {
|
||||
// }
|
||||
|
||||
Ok(()) // should actually never return from this, should be an error, rustc just cant see it
|
||||
}
|
||||
|
||||
+14
-11
@@ -78,7 +78,7 @@ impl<'a> dioxus_core::diff::RealDom<'a> for WebsysDom {
|
||||
self.stack.push(domnode.clone());
|
||||
}
|
||||
|
||||
fn append_child(&mut self) {
|
||||
fn append_children(&mut self, many: u32) {
|
||||
log::debug!("Called [`append_child`]");
|
||||
let child = self.stack.pop();
|
||||
|
||||
@@ -99,7 +99,7 @@ impl<'a> dioxus_core::diff::RealDom<'a> for WebsysDom {
|
||||
self.stack.top().append_child(&child).unwrap();
|
||||
}
|
||||
|
||||
fn replace_with(&mut self) {
|
||||
fn replace_with(&mut self, many: u32) {
|
||||
log::debug!("Called [`replace_with`]");
|
||||
let new_node = self.stack.pop();
|
||||
let old_node = self.stack.pop();
|
||||
@@ -193,15 +193,16 @@ impl<'a> dioxus_core::diff::RealDom<'a> for WebsysDom {
|
||||
&mut self,
|
||||
event: &'static str,
|
||||
scope: dioxus_core::prelude::ScopeIdx,
|
||||
el_id: usize,
|
||||
_element_id: usize,
|
||||
real_id: RealDomNode,
|
||||
) {
|
||||
let (_on, event) = event.split_at(2);
|
||||
let event = wasm_bindgen::intern(event);
|
||||
log::debug!(
|
||||
"Called [`new_event_listener`]: {}, {:?}, {}, {:?}",
|
||||
event,
|
||||
scope,
|
||||
el_id,
|
||||
_element_id,
|
||||
real_id
|
||||
);
|
||||
// attach the correct attributes to the element
|
||||
@@ -215,10 +216,11 @@ impl<'a> dioxus_core::diff::RealDom<'a> for WebsysDom {
|
||||
.dyn_ref::<Element>()
|
||||
.expect(&format!("not an element: {:?}", el));
|
||||
|
||||
let gi_id = scope.data().as_ffi();
|
||||
let scope_id = scope.data().as_ffi();
|
||||
el.set_attribute(
|
||||
&format!("dioxus-event-{}", event),
|
||||
&format!("{}.{}.{}", gi_id, el_id, real_id.0),
|
||||
&format!("{}.{}", scope_id, real_id.0),
|
||||
// &format!("{}.{}.{}", gi_id, el_id, real_id.0),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
@@ -566,19 +568,20 @@ 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 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))
|
||||
.context("failed to parse real id")?;
|
||||
|
||||
// Call the trigger
|
||||
log::debug!("decoded gi_id: {}, li_idx: {}", gi_id, el_id);
|
||||
log::debug!("decoded scope_id: {}, node_id: {:#?}", gi_id, real_id);
|
||||
|
||||
let triggered_scope: ScopeIdx = KeyData::from_ffi(gi_id).into();
|
||||
log::debug!("Triggered scope is {:#?}", triggered_scope);
|
||||
Ok(EventTrigger::new(
|
||||
virtual_event_from_websys_event(event),
|
||||
triggered_scope,
|
||||
|
||||
Reference in new issue
Block a user