Switch to a pool of dynamic values for hot reloading (#2705)

* create the dynamic value pool

* assign ids to dynamic formatted segments

* separate the rendering and literal pools

* rsx output compiles again

* more examples compiling with new rsx expansion

* update template body explanation

* all workspace examples compile

* fix formatted segments in keys

* start hot reload diffing

* fix component literal hot reloading

* start integrate new hot reloading with the CLI

* simple hot reloads working

* Fix hot reloading blocks with components

* implement hot reloading for if chains

* Fix hot reloading after a template requires a full rebuild

* Fix hot reloading any attribute values

* remove unsafe from hot reload utils

* Fix hot reloading empty rsx

* add more hot reloading tests

* reorganize hot reload module

* fix web hydration

* fix empty rsx nodes in autoformatting

* fix tests

* remove path sorting logic from core

* make template names more consistent in debug mode

* fix quote_as_hot_reload_literal for explicitly typed literals

* fix can_be_shorthand for string literals

* fix formatted single dynamic expression

* Fix usize component properties and playwright tests

* remove default implementation for TemplateBody

* add a bunch more comments for diffing, scoring and why this scoring system is optimal
This commit is contained in:
Evan Almloff authored and GitHub committed 2024-07-30 17:16:27 +00:00
1 parent f3ca1484a1
commit 34bdcd15cf
40 files changed
+2288 -1897

No files matched your search

+5 -33
View File
@@ -4,7 +4,7 @@
//! Currently the additional tooling doesn't do much.
use proc_macro2::TokenStream as TokenStream2;
use quote::{quote, ToTokens};
use quote::ToTokens;
use std::{cell::Cell, fmt::Debug};
use syn::{
parse::{Parse, ParseStream},
@@ -25,7 +25,6 @@ use crate::{BodyNode, TemplateBody};
#[derive(Debug, Clone)]
pub struct CallBody {
pub body: TemplateBody,
pub ifmt_idx: Cell<usize>,
pub template_idx: Cell<usize>,
}
@@ -38,10 +37,7 @@ impl Parse for CallBody {
impl ToTokens for CallBody {
fn to_tokens(&self, out: &mut TokenStream2) {
match self.body.is_empty() {
true => quote! { dioxus_core::VNode::empty() }.to_tokens(out),
false => self.body.to_tokens(out),
}
self.body.to_tokens(out)
}
}
@@ -52,7 +48,6 @@ impl CallBody {
pub fn new(body: TemplateBody) -> Self {
let body = CallBody {
body,
ifmt_idx: Cell::new(0),
template_idx: Cell::new(0),
};
@@ -91,36 +86,17 @@ impl CallBody {
///
/// Lots of wiring!
///
/// However, here, we only need to wire up ifmt and template IDs since TemplateBody will handle the rest.
/// However, here, we only need to wire up template IDs since TemplateBody will handle the rest.
///
/// This is better though since we can save the relevant data on the structures themselves.
fn cascade_hotreload_info(&self, nodes: &[BodyNode]) {
for node in nodes.iter() {
match node {
BodyNode::RawExpr(_) => { /* one day maybe provide hr here?*/ }
BodyNode::Text(text) => {
// one day we could also provide HR here to allow dynamic parts on the fly
if !text.is_static() {
text.hr_idx.set(self.next_ifmt_idx());
}
}
BodyNode::Element(el) => {
// Walk the attributes looking for hotreload opportunities
for attr in &el.merged_attributes {
attr.with_literal(|lit| lit.hr_idx.set(self.next_ifmt_idx()));
}
self.cascade_hotreload_info(&el.children);
}
BodyNode::Component(comp) => {
// walk the props looking for hotreload opportunities
for prop in comp.fields.iter() {
prop.with_literal(|lit| lit.hr_idx.set(self.next_ifmt_idx()));
}
comp.children.template_idx.set(self.next_template_idx());
self.cascade_hotreload_info(&comp.children.roots);
}
@@ -134,16 +110,12 @@ impl CallBody {
body.template_idx.set(self.next_template_idx());
self.cascade_hotreload_info(&body.roots)
}),
_ => {}
}
}
}
fn next_ifmt_idx(&self) -> usize {
let idx = self.ifmt_idx.get();
self.ifmt_idx.set(idx + 1);
idx
}
fn next_template_idx(&self) -> usize {
let idx = self.template_idx.get();
self.template_idx.set(idx + 1);