wip: enable more diffing

This commit is contained in:
Jonathan Kelley committed 2021-07-05 01:11:49 -04:00
1 parent b5e5ef171a
commit e8f29a8f8a
26 files changed
+1326 -367

No files matched your search

+294 -44
View File
@@ -77,49 +77,6 @@ impl WebsysRenderer {
.progress_with_event(&mut websys_dom, trigger)?;
}
// let edits = self.internal_dom.rebuild()?;
// log::debug!("Received edits: {:#?}", edits);
// edits.iter().for_each(|edit| {
// log::debug!("patching with {:?}", edit);
// patch_machine.handle_edit(edit);
// });
// patch_machine.reset();
// let root_node = body_element.first_child().unwrap();
// patch_machine.stack.push(root_node.clone());
// log::debug!("patch stack size {:?}", patch_machine.stack);
// Event loop waits for the receiver to finish up
// TODO! Connect the sender to the virtual dom's suspense system
// Suspense is basically an external event that can force renders to specific nodes
// while let Ok(event) = receiver.recv().await {
// log::debug!("Stack before entrance {:#?}", patch_machine.stack.top());
// log::debug!("patch stack size before {:#?}", patch_machine.stack);
// patch_machine.reset();
// patch_machine.stack.push(root_node.clone());
// self.internal_dom
// .progress_with_event(&mut websys_dom, event)?;
// let edits = self.internal_dom.progress_with_event(event)?;
// log::debug!("Received edits: {:#?}", edits);
// for edit in &edits {
// // log::debug!("edit stream {:?}", edit);
// // log::debug!("Stream stack {:#?}", patch_machine.stack.top());
// patch_machine.handle_edit(edit);
// }
// log::debug!("patch stack size after {:#?}", patch_machine.stack);
// patch_machine.reset();
// our root node reference gets invalidated
// not sure why
// for now, just select the first child again.
// eventually, we'll just make our own root element instead of using body
// or just use body directly IDEK
// let root_node = body_element.first_child().unwrap();
// patch_machine.stack.push(root_node.clone());
// }
Ok(()) // should actually never return from this, should be an error, rustc just cant see it
}
}
@@ -135,7 +92,7 @@ fn prepare_websys_dom() -> Element {
// Build a dummy div
let container: &Element = body.as_ref();
container.set_inner_html("");
// container.set_inner_html("");
container
.append_child(
document
@@ -164,6 +121,299 @@ fn prepare_websys_dom() -> Element {
// };
// }
/// Wasm-bindgen has a performance option to intern commonly used phrases
/// This saves the decoding cost, making the interaction of Rust<->JS more performant.
/// We intern all the HTML tags and attributes, making most operations much faster.
///
/// Interning takes about 1ms at the start of the app, but saves a *ton* of time later on.
pub fn intern_cache() {
let cached_words = [
// All the HTML Tags
"a",
"abbr",
"address",
"area",
"article",
"aside",
"audio",
"b",
"base",
"bdi",
"bdo",
"big",
"blockquote",
"body",
"br",
"button",
"canvas",
"caption",
"cite",
"code",
"col",
"colgroup",
"command",
"data",
"datalist",
"dd",
"del",
"details",
"dfn",
"dialog",
"div",
"dl",
"dt",
"em",
"embed",
"fieldset",
"figcaption",
"figure",
"footer",
"form",
"h1",
"h2",
"h3",
"h4",
"h5",
"h6",
"head",
"header",
"hr",
"html",
"i",
"iframe",
"img",
"input",
"ins",
"kbd",
"keygen",
"label",
"legend",
"li",
"link",
"main",
"map",
"mark",
"menu",
"menuitem",
"meta",
"meter",
"nav",
"noscript",
"object",
"ol",
"optgroup",
"option",
"output",
"p",
"param",
"picture",
"pre",
"progress",
"q",
"rp",
"rt",
"ruby",
"s",
"samp",
"script",
"section",
"select",
"small",
"source",
"span",
"strong",
"style",
"sub",
"summary",
"sup",
"table",
"tbody",
"td",
"textarea",
"tfoot",
"th",
"thead",
"time",
"title",
"tr",
"track",
"u",
"ul",
"var",
"video",
"wbr",
// All the event handlers
"Attribute",
"accept",
"accept-charset",
"accesskey",
"action",
"alt",
"async",
"autocomplete",
"autofocus",
"autoplay",
"charset",
"checked",
"cite",
"class",
"cols",
"colspan",
"content",
"contenteditable",
"controls",
"coords",
"data",
"data-*",
"datetime",
"default",
"defer",
"dir",
"dirname",
"disabled",
"download",
"draggable",
"enctype",
"for",
"form",
"formaction",
"headers",
"height",
"hidden",
"high",
"href",
"hreflang",
"http-equiv",
"id",
"ismap",
"kind",
"label",
"lang",
"list",
"loop",
"low",
"max",
"maxlength",
"media",
"method",
"min",
"multiple",
"muted",
"name",
"novalidate",
"onabort",
"onafterprint",
"onbeforeprint",
"onbeforeunload",
"onblur",
"oncanplay",
"oncanplaythrough",
"onchange",
"onclick",
"oncontextmenu",
"oncopy",
"oncuechange",
"oncut",
"ondblclick",
"ondrag",
"ondragend",
"ondragenter",
"ondragleave",
"ondragover",
"ondragstart",
"ondrop",
"ondurationchange",
"onemptied",
"onended",
"onerror",
"onfocus",
"onhashchange",
"oninput",
"oninvalid",
"onkeydown",
"onkeypress",
"onkeyup",
"onload",
"onloadeddata",
"onloadedmetadata",
"onloadstart",
"onmousedown",
"onmousemove",
"onmouseout",
"onmouseover",
"onmouseup",
"onmousewheel",
"onoffline",
"ononline",
"<body>",
"onpageshow",
"onpaste",
"onpause",
"onplay",
"onplaying",
"<body>",
"onprogress",
"onratechange",
"onreset",
"onresize",
"onscroll",
"onsearch",
"onseeked",
"onseeking",
"onselect",
"onstalled",
"<body>",
"onsubmit",
"onsuspend",
"ontimeupdate",
"ontoggle",
"onunload",
"onvolumechange",
"onwaiting",
"onwheel",
"open",
"optimum",
"pattern",
"placeholder",
"poster",
"preload",
"readonly",
"rel",
"required",
"reversed",
"rows",
"rowspan",
"sandbox",
"scope",
"selected",
"shape",
"size",
"sizes",
"span",
"spellcheck",
"src",
"srcdoc",
"srclang",
"srcset",
"start",
"step",
"style",
"tabindex",
"target",
"title",
"translate",
"type",
"usemap",
"value",
"width",
"wrap",
];
for s in cached_words {
wasm_bindgen::intern(s);
}
}
#[cfg(test)]
mod tests {
use std::env;
+24 -7
View File
@@ -171,6 +171,7 @@ impl<'a> dioxus_core::diff::RealDom<'a> for WebsysDom {
tag: &str,
ns: Option<&'static str>,
) -> dioxus_core::virtual_dom::RealDomNode {
let tag = wasm_bindgen::intern(tag);
let el = match ns {
Some(ns) => self
.document
@@ -200,6 +201,7 @@ impl<'a> dioxus_core::diff::RealDom<'a> for WebsysDom {
el_id: usize,
real_id: RealDomNode,
) {
let event = wasm_bindgen::intern(event);
log::debug!(
"Called [`new_event_listener`]: {}, {:?}, {}, {:?}",
event,
@@ -237,7 +239,7 @@ impl<'a> dioxus_core::diff::RealDom<'a> for WebsysDom {
// Instead, we just build and immediately execute a closure that returns result
match decode_trigger(event) {
Ok(synthetic_event) => trigger.as_ref()(synthetic_event),
Err(_) => log::error!("Error decoding Dioxus event attribute."),
Err(e) => log::error!("Error decoding Dioxus event attribute. {:#?}", e),
};
}) as Box<dyn FnMut(&Event)>);
@@ -407,7 +409,7 @@ fn virtual_event_from_websys_event(event: &web_sys::Event) -> VirtualEvent {
#[derive(Debug)]
pub struct CustomMouseEvent(web_sys::MouseEvent);
impl dioxus_core::events::on::MouseEvent for CustomMouseEvent {
impl dioxus_core::events::on::MouseEventInner for CustomMouseEvent {
fn alt_key(&self) -> bool {
self.0.alt_key()
}
@@ -451,7 +453,7 @@ fn virtual_event_from_websys_event(event: &web_sys::Event) -> VirtualEvent {
self.0.get_modifier_state(key_code)
}
}
VirtualEvent::MouseEvent(Rc::new(CustomMouseEvent(evt)))
VirtualEvent::MouseEvent(MouseEvent(Rc::new(CustomMouseEvent(evt))))
// MouseEvent(Box::new(RawMouseEvent {
// alt_key: evt.alt_key(),
// button: evt.button() as i32,
@@ -547,25 +549,36 @@ fn decode_trigger(event: &web_sys::Event) -> anyhow::Result<EventTrigger> {
use anyhow::Context;
// for attr in {
let attrs = target.attributes();
for x in 0..attrs.length() {
let attr = attrs.item(x).unwrap();
log::debug!("attrs include: {:#?}", attr);
}
// }
// for attr in target.attributes() {
// log::debug!("attrs include: {:#?}", attr);
// }
// The error handling here is not very descriptive and needs to be replaced with a zero-cost error system
let val: String = target
.get_attribute(&format!("dioxus-event-{}", typ))
.context("")?;
.context(format!("wrong format - received {:#?}", typ))?;
let mut fields = val.splitn(3, ".");
let gi_id = fields
.next()
.and_then(|f| f.parse::<u64>().ok())
.context("")?;
.context("failed to parse gi id")?;
let el_id = fields
.next()
.and_then(|f| f.parse::<usize>().ok())
.context("")?;
.context("failed to parse el id")?;
let real_id = fields
.next()
.and_then(|f| f.parse::<u64>().ok().map(RealDomNode::new))
.context("")?;
.context("failed to parse real id")?;
// Call the trigger
log::debug!("decoded gi_id: {}, li_idx: {}", gi_id, el_id);
@@ -575,6 +588,7 @@ fn decode_trigger(event: &web_sys::Event) -> anyhow::Result<EventTrigger> {
virtual_event_from_websys_event(event),
triggered_scope,
real_id,
dioxus_core::events::EventPriority::High,
))
}
@@ -584,3 +598,6 @@ impl ListenerMap {
false
}
}
struct JsStringCache {}
impl JsStringCache {}