wip: bottom up dropping

This commit is contained in:
Jonathan Kelley committed 2021-08-05 22:23:41 -04:00
1 parent 687cda1b6d
commit f2334c17be
21 files changed
+682 -679

No files matched your search

+10 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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!()
}
}