Fix nested rsx expansion by not using template titles (#2799)

* Fix nested rsx expansion by not using template titles

* fix writers with nameless templates

* fix clippy

* dont commit vscode fix

* fix release mode, pull out __template_name

* fix axum_desktop

* Fix core tests

* Make most fields of HotReloadedTemplate public for testing

* wip: formatting, compare all diff cases

* slightly smarter diffing for dynamic nodes

* add a comment about generic node diffing

* clean up mutations a bit

* fix load template

* simplify maybe_rebuild

* Restore write mutations flag in web

* write_mutations -> skip_mutations

---------

Co-authored-by: Evan Almloff <evanalmloff@gmail.com>
This commit is contained in:
Jonathan KelleyandEvan Almloff authored and GitHub committed 2024-08-13 01:59:04 +00:00
1 parent a2180b92e9
commit 0de3bf7aeb
40 files changed
+597 -1038

No files matched your search

+5 -7
View File
@@ -6,7 +6,7 @@
//! - tests to ensure dyn_into works for various event types.
//! - Partial delegation?
use dioxus_core::ElementId;
use dioxus_core::{ElementId, Template};
use dioxus_html::PlatformEventData;
use dioxus_interpreter_js::unified_bindings::Interpreter;
use futures_channel::mpsc;
@@ -20,8 +20,7 @@ pub struct WebsysDom {
#[allow(dead_code)]
pub(crate) root: Element,
pub(crate) document: Document,
pub(crate) templates: FxHashMap<String, u16>,
pub(crate) max_template_id: u16,
pub(crate) templates: FxHashMap<Template, u16>,
pub(crate) interpreter: Interpreter,
#[cfg(feature = "mounted")]
@@ -41,10 +40,10 @@ pub struct WebsysDom {
// Instead we now store a flag to see if we should be writing templates at all if hydration is enabled.
// This has a small overhead, but it avoids dynamic dispatch and reduces the binary size
//
// NOTE: running the virtual dom with the `only_write_templates` flag set to true is different from running
// NOTE: running the virtual dom with the `write_mutations` flag set to true is different from running
// it with no mutation writer because it still assigns ids to nodes, but it doesn't write them to the dom
#[cfg(feature = "hydrate")]
pub(crate) only_write_templates: bool,
pub(crate) skip_mutations: bool,
#[cfg(feature = "hydrate")]
pub(crate) suspense_hydration_ids: crate::hydration::SuspenseHydrationIds,
@@ -145,13 +144,12 @@ impl WebsysDom {
root,
interpreter,
templates: FxHashMap::default(),
max_template_id: 0,
#[cfg(feature = "mounted")]
event_channel,
#[cfg(feature = "mounted")]
queued_mounted_events: Default::default(),
#[cfg(feature = "hydrate")]
only_write_templates: false,
skip_mutations: false,
#[cfg(feature = "hydrate")]
suspense_hydration_ids: Default::default(),
}
+2 -2
View File
@@ -151,11 +151,11 @@ impl WebsysDom {
self,
|to| {
// Switch to only writing templates
to.only_write_templates = true;
to.skip_mutations = true;
},
children.len(),
);
self.only_write_templates = false;
self.skip_mutations = false;
});
// Flush the mutations that will swap the placeholder nodes with the resolved nodes
+4 -3
View File
@@ -25,6 +25,7 @@ use std::{panic, rc::Rc};
pub use crate::cfg::Config;
use crate::hydration::SuspenseMessage;
use dioxus_core::VirtualDom;
use dom::WebsysDom;
use futures_util::{pin_mut, select, FutureExt, StreamExt};
mod cfg;
@@ -77,7 +78,7 @@ pub async fn run(virtual_dom: VirtualDom, web_config: Config) -> ! {
let should_hydrate = web_config.hydrate;
let mut websys_dom = dom::WebsysDom::new(web_config, tx);
let mut websys_dom = WebsysDom::new(web_config, tx);
let mut hydration_receiver: Option<futures_channel::mpsc::UnboundedReceiver<SuspenseMessage>> =
None;
@@ -85,7 +86,7 @@ pub async fn run(virtual_dom: VirtualDom, web_config: Config) -> ! {
if should_hydrate {
#[cfg(feature = "hydrate")]
{
websys_dom.only_write_templates = true;
websys_dom.skip_mutations = true;
// Get the initial hydration data from the client
#[wasm_bindgen::prelude::wasm_bindgen(inline_js = r#"
export function get_initial_hydration_data() {
@@ -105,7 +106,7 @@ pub async fn run(virtual_dom: VirtualDom, web_config: Config) -> ! {
with_server_data(server_data, || {
dom.rebuild(&mut websys_dom);
});
websys_dom.only_write_templates = false;
websys_dom.skip_mutations = false;
let rx = websys_dom.rehydrate(&dom).unwrap();
hydration_receiver = Some(rx);
+30 -42
View File
@@ -79,10 +79,10 @@ impl WebsysDom {
}
#[inline]
fn only_write_templates(&self) -> bool {
fn skip_mutations(&self) -> bool {
#[cfg(feature = "hydrate")]
{
self.only_write_templates
self.skip_mutations
}
#[cfg(not(feature = "hydrate"))]
{
@@ -92,28 +92,15 @@ impl WebsysDom {
}
impl WriteMutations for WebsysDom {
fn register_template(&mut self, template: Template) {
let mut roots = vec![];
for root in template.roots {
roots.push(self.create_template_node(root))
}
self.templates
.insert(template.name.to_owned(), self.max_template_id);
self.interpreter
.base()
.save_template(roots, self.max_template_id);
self.max_template_id += 1
}
fn append_children(&mut self, id: ElementId, m: usize) {
if self.only_write_templates() {
if self.skip_mutations() {
return;
}
self.interpreter.append_children(id.0 as u32, m as u16)
}
fn assign_node_id(&mut self, path: &'static [u8], id: ElementId) {
if self.only_write_templates() {
if self.skip_mutations() {
return;
}
self.interpreter
@@ -121,46 +108,47 @@ impl WriteMutations for WebsysDom {
}
fn create_placeholder(&mut self, id: ElementId) {
if self.only_write_templates() {
if self.skip_mutations() {
return;
}
self.interpreter.create_placeholder(id.0 as u32)
}
fn create_text_node(&mut self, value: &str, id: ElementId) {
if self.only_write_templates() {
if self.skip_mutations() {
return;
}
self.interpreter.create_text_node(value, id.0 as u32)
}
fn hydrate_text_node(&mut self, path: &'static [u8], value: &str, id: ElementId) {
if self.only_write_templates() {
fn load_template(&mut self, template: Template, index: usize, id: ElementId) {
if self.skip_mutations() {
return;
}
self.interpreter
.hydrate_text(path.as_ptr() as u32, path.len() as u8, value, id.0 as u32)
}
let tmpl_id = self.templates.get(&template).cloned().unwrap_or_else(|| {
let mut roots = vec![];
for root in template.roots {
roots.push(self.create_template_node(root))
}
let id = self.templates.len() as u16;
self.templates.insert(template, id);
self.interpreter.base().save_template(roots, id);
id
});
fn load_template(&mut self, name: &'static str, index: usize, id: ElementId) {
if self.only_write_templates() {
return;
}
if let Some(tmpl_id) = self.templates.get(name) {
self.interpreter
.load_template(*tmpl_id, index as u16, id.0 as u32)
}
self.interpreter
.load_template(tmpl_id, index as u16, id.0 as u32)
}
fn replace_node_with(&mut self, id: ElementId, m: usize) {
if self.only_write_templates() {
if self.skip_mutations() {
return;
}
self.interpreter.replace_with(id.0 as u32, m as u16)
}
fn replace_placeholder_with_nodes(&mut self, path: &'static [u8], m: usize) {
if self.only_write_templates() {
if self.skip_mutations() {
return;
}
self.interpreter
@@ -168,14 +156,14 @@ impl WriteMutations for WebsysDom {
}
fn insert_nodes_after(&mut self, id: ElementId, m: usize) {
if self.only_write_templates() {
if self.skip_mutations() {
return;
}
self.interpreter.insert_after(id.0 as u32, m as u16)
}
fn insert_nodes_before(&mut self, id: ElementId, m: usize) {
if self.only_write_templates() {
if self.skip_mutations() {
return;
}
self.interpreter.insert_before(id.0 as u32, m as u16)
@@ -188,7 +176,7 @@ impl WriteMutations for WebsysDom {
value: &AttributeValue,
id: ElementId,
) {
if self.only_write_templates() {
if self.skip_mutations() {
return;
}
match value {
@@ -223,14 +211,14 @@ impl WriteMutations for WebsysDom {
}
fn set_node_text(&mut self, value: &str, id: ElementId) {
if self.only_write_templates() {
if self.skip_mutations() {
return;
}
self.interpreter.set_text(id.0 as u32, value)
}
fn create_event_listener(&mut self, name: &'static str, id: ElementId) {
if self.only_write_templates() {
if self.skip_mutations() {
return;
}
// mounted events are fired immediately after the element is mounted.
@@ -245,7 +233,7 @@ impl WriteMutations for WebsysDom {
}
fn remove_event_listener(&mut self, name: &'static str, id: ElementId) {
if self.only_write_templates() {
if self.skip_mutations() {
return;
}
if name == "mounted" {
@@ -257,14 +245,14 @@ impl WriteMutations for WebsysDom {
}
fn remove_node(&mut self, id: ElementId) {
if self.only_write_templates() {
if self.skip_mutations() {
return;
}
self.interpreter.remove(id.0 as u32)
}
fn push_root(&mut self, id: ElementId) {
if self.only_write_templates() {
if self.skip_mutations() {
return;
}
self.interpreter.push_root(id.0 as u32)