wip: bottom up dropping
This commit is contained in:
1 parent
687cda1b6d
commit
f2334c17be
21 files changed
+682
-679
No files matched your search
+10
-1
@@ -1,9 +1,13 @@
|
||||
pub struct WebConfig {
|
||||
pub(crate) hydrate: bool,
|
||||
pub(crate) rootname: String,
|
||||
}
|
||||
impl Default for WebConfig {
|
||||
fn default() -> Self {
|
||||
Self { hydrate: false }
|
||||
Self {
|
||||
hydrate: false,
|
||||
rootname: "dioxusroot".to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl WebConfig {
|
||||
@@ -18,4 +22,9 @@ impl WebConfig {
|
||||
self.hydrate = f;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn rootname(mut self, name: impl Into<String>) -> Self {
|
||||
self.rootname = name.into();
|
||||
self
|
||||
}
|
||||
}
|
||||
+20
-43
@@ -7,8 +7,8 @@ use dioxus_core::{
|
||||
use fxhash::FxHashMap;
|
||||
use wasm_bindgen::{closure::Closure, JsCast};
|
||||
use web_sys::{
|
||||
window, Document, Element, Event, HtmlElement, HtmlInputElement, HtmlOptionElement, Node,
|
||||
NodeList,
|
||||
window, CssStyleDeclaration, Document, Element, Event, HtmlElement, HtmlInputElement,
|
||||
HtmlOptionElement, Node, NodeList,
|
||||
};
|
||||
|
||||
use crate::{nodeslab::NodeSlab, WebConfig};
|
||||
@@ -23,9 +23,7 @@ pub struct WebsysDom {
|
||||
|
||||
root: Element,
|
||||
|
||||
event_receiver: async_channel::Receiver<EventTrigger>,
|
||||
|
||||
trigger: Arc<dyn Fn(EventTrigger)>,
|
||||
sender_callback: Rc<dyn Fn(EventTrigger)>,
|
||||
|
||||
// map of listener types to number of those listeners
|
||||
// This is roughly a delegater
|
||||
@@ -40,19 +38,9 @@ pub struct WebsysDom {
|
||||
last_node_was_text: bool,
|
||||
}
|
||||
impl WebsysDom {
|
||||
pub fn new(root: Element, cfg: WebConfig) -> Self {
|
||||
pub fn new(root: Element, cfg: WebConfig, sender_callback: Rc<dyn Fn(EventTrigger)>) -> Self {
|
||||
let document = load_document();
|
||||
|
||||
let (sender, receiver) = async_channel::unbounded::<EventTrigger>();
|
||||
|
||||
let sender_callback = Arc::new(move |ev| {
|
||||
let c = sender.clone();
|
||||
wasm_bindgen_futures::spawn_local(async move {
|
||||
log::debug!("sending event through channel");
|
||||
c.send(ev).await.unwrap();
|
||||
});
|
||||
});
|
||||
|
||||
let mut nodes = NodeSlab::new(2000);
|
||||
let mut listeners = FxHashMap::default();
|
||||
|
||||
@@ -67,12 +55,11 @@ impl WebsysDom {
|
||||
let el: &Element = node.dyn_ref::<Element>().unwrap();
|
||||
let id: String = el.get_attribute("dio_el").unwrap();
|
||||
let id = id.parse::<usize>().unwrap();
|
||||
|
||||
// this autoresizes the vector if needed
|
||||
nodes[id] = Some(node);
|
||||
}
|
||||
|
||||
// Load all the event listeners into our listener register
|
||||
// TODO
|
||||
}
|
||||
|
||||
let mut stack = Stack::with_capacity(10);
|
||||
@@ -84,18 +71,12 @@ impl WebsysDom {
|
||||
nodes,
|
||||
listeners,
|
||||
document,
|
||||
event_receiver: receiver,
|
||||
trigger: sender_callback,
|
||||
sender_callback,
|
||||
root,
|
||||
last_node_was_text: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn wait_for_event(&mut self) -> Option<EventTrigger> {
|
||||
let v = self.event_receiver.recv().await.unwrap();
|
||||
Some(v)
|
||||
}
|
||||
|
||||
pub fn process_edits(&mut self, edits: &mut Vec<DomEdit>) {
|
||||
for edit in edits.drain(..) {
|
||||
log::info!("Handling edit: {:#?}", edit);
|
||||
@@ -310,7 +291,7 @@ impl WebsysDom {
|
||||
if let Some(entry) = self.listeners.get_mut(event) {
|
||||
entry.0 += 1;
|
||||
} else {
|
||||
let trigger = self.trigger.clone();
|
||||
let trigger = self.sender_callback.clone();
|
||||
|
||||
let handler = Closure::wrap(Box::new(move |event: &web_sys::Event| {
|
||||
// "Result" cannot be received from JS
|
||||
@@ -339,25 +320,21 @@ impl WebsysDom {
|
||||
}
|
||||
|
||||
fn set_attribute(&mut self, name: &str, value: &str, ns: Option<&str>) {
|
||||
if name == "class" {
|
||||
if let Some(el) = self.stack.top().dyn_ref::<Element>() {
|
||||
match ns {
|
||||
Some("http://www.w3.org/2000/svg") => {
|
||||
//
|
||||
if let Some(el) = self.stack.top().dyn_ref::<web_sys::SvgElement>() {
|
||||
let r: web_sys::SvgAnimatedString = el.class_name();
|
||||
r.set_base_val(value);
|
||||
// el.set_class_name(value);
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
if let Some(el) = self.stack.top().dyn_ref::<Element>() {
|
||||
el.set_class_name(value);
|
||||
}
|
||||
// inline style support
|
||||
Some("style") => {
|
||||
let el = el.dyn_ref::<HtmlElement>().unwrap();
|
||||
let style_dc: CssStyleDeclaration = el.style();
|
||||
style_dc.set_property(name, value).unwrap();
|
||||
}
|
||||
_ => el.set_attribute(name, value).unwrap(),
|
||||
}
|
||||
} else {
|
||||
if let Some(el) = self.stack.top().dyn_ref::<Element>() {
|
||||
el.set_attribute(name, value).unwrap();
|
||||
match name {
|
||||
"value" => {}
|
||||
"checked" => {}
|
||||
"selected" => {}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -418,7 +395,7 @@ impl WebsysDom {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> dioxus_core::diff::RealDom<'a> for WebsysDom {
|
||||
impl<'a> dioxus_core::diff::RealDom for WebsysDom {
|
||||
// fn request_available_node(&mut self) -> ElementId {
|
||||
// let key = self.nodes.insert(None);
|
||||
// log::debug!("making new key: {:#?}", key);
|
||||
|
||||
+23
-39
@@ -2,6 +2,8 @@
|
||||
//! --------------
|
||||
//! This crate implements a renderer of the Dioxus Virtual DOM for the web browser using Websys.
|
||||
|
||||
use std::rc::Rc;
|
||||
|
||||
pub use crate::cfg::WebConfig;
|
||||
use crate::dom::load_document;
|
||||
use dioxus::prelude::{Context, Properties, VNode};
|
||||
@@ -77,50 +79,25 @@ pub async fn run_with_props<T: Properties + 'static>(
|
||||
) -> Result<()> {
|
||||
let mut dom = VirtualDom::new_with_props(root, root_props);
|
||||
|
||||
// let tasks = dom.shared.tasks.clone();
|
||||
let root_el = load_document().get_element_by_id(&cfg.rootname).unwrap();
|
||||
|
||||
let root_el = load_document().get_element_by_id("dioxusroot").unwrap();
|
||||
let mut websys_dom = dom::WebsysDom::new(root_el, cfg);
|
||||
let tasks = dom.get_event_sender();
|
||||
|
||||
let mut edits = Vec::new();
|
||||
dom.rebuild(&mut websys_dom, &mut edits)?;
|
||||
websys_dom.process_edits(&mut edits);
|
||||
let mut real = RealDomWebsys {};
|
||||
|
||||
log::info!("Going into event loop");
|
||||
|
||||
// #[allow(unreachable_code)]
|
||||
loop {
|
||||
let trigger = {
|
||||
let real_queue = websys_dom.wait_for_event();
|
||||
if dom.any_pending_events() {
|
||||
log::info!("tasks is not empty, waiting for either tasks or event system");
|
||||
let mut task = dom.wait_for_event();
|
||||
|
||||
pin_mut!(real_queue);
|
||||
pin_mut!(task);
|
||||
|
||||
match futures_util::future::select(real_queue, task).await {
|
||||
futures_util::future::Either::Left((trigger, _)) => trigger,
|
||||
futures_util::future::Either::Right((trigger, _)) => trigger,
|
||||
}
|
||||
} else {
|
||||
log::info!("tasks is empty, waiting for dom event to trigger soemthing");
|
||||
real_queue.await
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(real_trigger) = trigger {
|
||||
log::info!("event received");
|
||||
|
||||
dom.queue_event(real_trigger);
|
||||
|
||||
let mut edits = Vec::new();
|
||||
dom.progress_with_event(&mut websys_dom, &mut edits).await?;
|
||||
websys_dom.process_edits(&mut edits);
|
||||
}
|
||||
// initialize the virtualdom first
|
||||
if cfg.hydrate {
|
||||
dom.rebuild_in_place()?;
|
||||
}
|
||||
|
||||
// should actually never return from this, should be an error, rustc just cant see it
|
||||
let mut websys_dom = dom::WebsysDom::new(
|
||||
root_el,
|
||||
cfg,
|
||||
Rc::new(move |event| tasks.unbounded_send(event).unwrap()),
|
||||
);
|
||||
|
||||
dom.run(&mut websys_dom).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -128,3 +105,10 @@ struct HydrationNode {
|
||||
id: usize,
|
||||
node: Node,
|
||||
}
|
||||
|
||||
struct RealDomWebsys {}
|
||||
impl dioxus::RealDom for RealDomWebsys {
|
||||
fn raw_node_as_any(&self) -> &mut dyn std::any::Any {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user