Improve compile times by splitting out rsx-hotreload from rsx (#2971)
* fix imports, migrate over rsx-hotreload
This commit is contained in:
1 parent
b67122dd2a
commit
463e67cd12
41 files changed
+188
-190
No files matched your search
Generated
+18
-3
@@ -2510,9 +2510,11 @@ dependencies = [
|
|||||||
"dioxus-check",
|
"dioxus-check",
|
||||||
"dioxus-cli-config",
|
"dioxus-cli-config",
|
||||||
"dioxus-core",
|
"dioxus-core",
|
||||||
|
"dioxus-core-types",
|
||||||
"dioxus-hot-reload",
|
"dioxus-hot-reload",
|
||||||
"dioxus-html",
|
"dioxus-html",
|
||||||
"dioxus-rsx",
|
"dioxus-rsx",
|
||||||
|
"dioxus-rsx-hotreload",
|
||||||
"dioxus-rsx-rosetta",
|
"dioxus-rsx-rosetta",
|
||||||
"dirs",
|
"dirs",
|
||||||
"env_logger 0.11.5",
|
"env_logger 0.11.5",
|
||||||
@@ -2792,6 +2794,7 @@ dependencies = [
|
|||||||
"dioxus-core",
|
"dioxus-core",
|
||||||
"dioxus-html",
|
"dioxus-html",
|
||||||
"dioxus-rsx",
|
"dioxus-rsx",
|
||||||
|
"dioxus-rsx-hotreload",
|
||||||
"dioxus-signals",
|
"dioxus-signals",
|
||||||
"execute",
|
"execute",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
@@ -2815,6 +2818,7 @@ dependencies = [
|
|||||||
"dioxus",
|
"dioxus",
|
||||||
"dioxus-core",
|
"dioxus-core",
|
||||||
"dioxus-core-macro",
|
"dioxus-core-macro",
|
||||||
|
"dioxus-core-types",
|
||||||
"dioxus-hooks",
|
"dioxus-hooks",
|
||||||
"dioxus-html-internal-macro",
|
"dioxus-html-internal-macro",
|
||||||
"dioxus-rsx",
|
"dioxus-rsx",
|
||||||
@@ -3033,14 +3037,25 @@ dependencies = [
|
|||||||
name = "dioxus-rsx"
|
name = "dioxus-rsx"
|
||||||
version = "0.6.0-alpha.2"
|
version = "0.6.0-alpha.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dioxus-core",
|
|
||||||
"internment",
|
|
||||||
"prettier-please",
|
"prettier-please",
|
||||||
"prettyplease",
|
"prettyplease",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"proc-macro2-diagnostics",
|
"proc-macro2-diagnostics",
|
||||||
"quote",
|
"quote",
|
||||||
"serde",
|
"syn 2.0.77",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dioxus-rsx-hotreload"
|
||||||
|
version = "0.6.0-alpha.2"
|
||||||
|
dependencies = [
|
||||||
|
"dioxus-core",
|
||||||
|
"dioxus-core-types",
|
||||||
|
"dioxus-rsx",
|
||||||
|
"internment",
|
||||||
|
"proc-macro2",
|
||||||
|
"proc-macro2-diagnostics",
|
||||||
|
"quote",
|
||||||
"syn 2.0.77",
|
"syn 2.0.77",
|
||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ members = [
|
|||||||
"packages/autofmt",
|
"packages/autofmt",
|
||||||
"packages/check",
|
"packages/check",
|
||||||
"packages/rsx",
|
"packages/rsx",
|
||||||
|
"packages/rsx-hotreload",
|
||||||
"packages/rsx-rosetta",
|
"packages/rsx-rosetta",
|
||||||
"packages/generational-box",
|
"packages/generational-box",
|
||||||
"packages/signals",
|
"packages/signals",
|
||||||
@@ -87,6 +88,7 @@ dioxus-liveview = { path = "packages/liveview", version = "0.6.0-alpha.0" }
|
|||||||
dioxus-autofmt = { path = "packages/autofmt", version = "0.6.0-alpha.0" }
|
dioxus-autofmt = { path = "packages/autofmt", version = "0.6.0-alpha.0" }
|
||||||
dioxus-check = { path = "packages/check", version = "0.6.0-alpha.0" }
|
dioxus-check = { path = "packages/check", version = "0.6.0-alpha.0" }
|
||||||
dioxus-rsx = { path = "packages/rsx", version = "0.6.0-alpha.0" }
|
dioxus-rsx = { path = "packages/rsx", version = "0.6.0-alpha.0" }
|
||||||
|
dioxus-rsx-hotreload = { path = "packages/rsx-hotreload", version = "0.6.0-alpha.0" }
|
||||||
dioxus-rsx-rosetta = { path = "packages/rsx-rosetta", version = "0.6.0-alpha.0" }
|
dioxus-rsx-rosetta = { path = "packages/rsx-rosetta", version = "0.6.0-alpha.0" }
|
||||||
dioxus-signals = { path = "packages/signals", version = "0.6.0-alpha.0" }
|
dioxus-signals = { path = "packages/signals", version = "0.6.0-alpha.0" }
|
||||||
dioxus-cli-config = { path = "packages/cli-config", version = "0.6.0-alpha.0", default-features = false}
|
dioxus-cli-config = { path = "packages/cli-config", version = "0.6.0-alpha.0", default-features = false}
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ impl Files {
|
|||||||
|
|
||||||
fn enter_dir(&mut self, dir_id: usize) {
|
fn enter_dir(&mut self, dir_id: usize) {
|
||||||
let path = &self.path_names[dir_id];
|
let path = &self.path_names[dir_id];
|
||||||
self.current_path = path.clone();
|
self.current_path.clone_from(path);
|
||||||
self.reload_path_list();
|
self.reload_path_list();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -90,9 +90,11 @@ brotli = "6.0.0"
|
|||||||
dioxus-autofmt = { workspace = true }
|
dioxus-autofmt = { workspace = true }
|
||||||
dioxus-check = { workspace = true }
|
dioxus-check = { workspace = true }
|
||||||
dioxus-rsx-rosetta = { workspace = true }
|
dioxus-rsx-rosetta = { workspace = true }
|
||||||
dioxus-rsx = { workspace = true, features = ["serde"]}
|
dioxus-rsx = { workspace = true }
|
||||||
|
dioxus-rsx-hotreload = { workspace = true }
|
||||||
dioxus-html = { workspace = true, features = ["hot-reload-context"] }
|
dioxus-html = { workspace = true, features = ["hot-reload-context"] }
|
||||||
dioxus-core = { workspace = true, features = ["serialize"] }
|
dioxus-core = { workspace = true, features = ["serialize"] }
|
||||||
|
dioxus-core-types = { workspace = true }
|
||||||
dioxus-hot-reload = { workspace = true, features = ["serve"] }
|
dioxus-hot-reload = { workspace = true, features = ["serve"] }
|
||||||
ignore = "0.4.22"
|
ignore = "0.4.22"
|
||||||
env_logger = "0.11.3"
|
env_logger = "0.11.3"
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
use dioxus_core::internal::{HotReloadTemplateWithLocation, HotReloadedTemplate};
|
use dioxus_core::internal::{HotReloadTemplateWithLocation, HotReloadedTemplate};
|
||||||
use dioxus_rsx::{
|
use dioxus_core_types::HotReloadingContext;
|
||||||
hot_reload::{diff_rsx, ChangedRsx},
|
use dioxus_rsx::CallBody;
|
||||||
CallBody, HotReloadingContext,
|
use dioxus_rsx_hotreload::{diff_rsx, ChangedRsx};
|
||||||
};
|
|
||||||
use krates::cm::MetadataCommand;
|
use krates::cm::MetadataCommand;
|
||||||
use krates::Cmd;
|
use krates::Cmd;
|
||||||
pub use std::collections::HashMap;
|
pub use std::collections::HashMap;
|
||||||
@@ -155,7 +154,7 @@ impl FileMap {
|
|||||||
let template_location = template_location(old_start, file);
|
let template_location = template_location(old_start, file);
|
||||||
|
|
||||||
// Returns a list of templates that are hotreloadable
|
// Returns a list of templates that are hotreloadable
|
||||||
let hotreload_result = dioxus_rsx::hot_reload::HotReloadResult::new::<Ctx>(
|
let hotreload_result = dioxus_rsx_hotreload::HotReloadResult::new::<Ctx>(
|
||||||
&old_call_body.body,
|
&old_call_body.body,
|
||||||
&new_call_body.body,
|
&new_call_body.body,
|
||||||
template_location.clone(),
|
template_location.clone(),
|
||||||
|
|||||||
File renamed without changes.
@@ -1,3 +1,5 @@
|
|||||||
pub mod bubbles;
|
pub mod bubbles;
|
||||||
|
pub mod hr_context;
|
||||||
|
|
||||||
pub use bubbles::*;
|
pub use bubbles::*;
|
||||||
|
pub use hr_context::*;
|
||||||
@@ -10,7 +10,8 @@ description = "Hot reloading utilities for Dioxus"
|
|||||||
keywords = ["dom", "ui", "gui", "react", "hot-reloading"]
|
keywords = ["dom", "ui", "gui", "react", "hot-reloading"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
dioxus-rsx = { workspace = true, features = ["serde"] }
|
dioxus-rsx = { workspace = true }
|
||||||
|
dioxus-rsx-hotreload = { workspace = true }
|
||||||
dioxus-core = { workspace = true, features = ["serialize"] }
|
dioxus-core = { workspace = true, features = ["serialize"] }
|
||||||
dioxus-html = { workspace = true, optional = true }
|
dioxus-html = { workspace = true, optional = true }
|
||||||
dioxus-signals = { workspace = true, optional = true }
|
dioxus-signals = { workspace = true, optional = true }
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ keywords = ["dom", "ui", "gui", "react"]
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
dioxus-core = { workspace = true }
|
dioxus-core = { workspace = true }
|
||||||
dioxus-core-macro = { workspace = true }
|
dioxus-core-macro = { workspace = true }
|
||||||
|
dioxus-core-types = { workspace = true }
|
||||||
dioxus-rsx = { workspace = true, optional = true }
|
dioxus-rsx = { workspace = true, optional = true }
|
||||||
dioxus-html-internal-macro = { workspace = true }
|
dioxus-html-internal-macro = { workspace = true }
|
||||||
dioxus-hooks = { workspace = true }
|
dioxus-hooks = { workspace = true }
|
||||||
@@ -96,7 +97,7 @@ file-engine = [
|
|||||||
]
|
]
|
||||||
wasm-bind = ["dep:web-sys", "dep:wasm-bindgen", "dep:wasm-bindgen-futures"]
|
wasm-bind = ["dep:web-sys", "dep:wasm-bindgen", "dep:wasm-bindgen-futures"]
|
||||||
native-bind = ["dep:tokio", "file-engine"]
|
native-bind = ["dep:tokio", "file-engine"]
|
||||||
hot-reload-context = ["dep:dioxus-rsx", "dioxus-rsx/hot_reload_traits"]
|
hot-reload-context = ["dep:dioxus-rsx"]
|
||||||
html-to-rsx = []
|
html-to-rsx = []
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
|
|||||||
@@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
use dioxus_core::prelude::IntoAttributeValue;
|
use dioxus_core::prelude::IntoAttributeValue;
|
||||||
use dioxus_core::HasAttributes;
|
use dioxus_core::HasAttributes;
|
||||||
use dioxus_html_internal_macro::impl_extension_attributes;
|
|
||||||
#[cfg(feature = "hot-reload-context")]
|
#[cfg(feature = "hot-reload-context")]
|
||||||
use dioxus_rsx::HotReloadingContext;
|
use dioxus_core_types::HotReloadingContext;
|
||||||
|
use dioxus_html_internal_macro::impl_extension_attributes;
|
||||||
|
|
||||||
#[cfg(feature = "hot-reload-context")]
|
#[cfg(feature = "hot-reload-context")]
|
||||||
use crate::{map_global_attributes, map_svg_attributes};
|
use crate::{map_global_attributes, map_svg_attributes};
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
[package]
|
||||||
|
name = "dioxus-rsx-hotreload"
|
||||||
|
edition = "2021"
|
||||||
|
version.workspace = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
dioxus-rsx = { workspace = true }
|
||||||
|
internment = { workspace = true }
|
||||||
|
proc-macro2 = { workspace = true, features = ["span-locations"] }
|
||||||
|
proc-macro2-diagnostics = { workspace = true }
|
||||||
|
quote = { workspace = true }
|
||||||
|
syn = { workspace = true, features = ["full", "extra-traits", "visit", "visit-mut"] }
|
||||||
|
tracing = { workspace = true }
|
||||||
|
dioxus-core = { workspace = true }
|
||||||
|
dioxus-core-types = { workspace = true }
|
||||||
File renamed without changes.
@@ -63,14 +63,16 @@
|
|||||||
//! The subproblem is optimal because the alternative is leaving less dynamic items for the remaining templates to hot reload which just makes it
|
//! The subproblem is optimal because the alternative is leaving less dynamic items for the remaining templates to hot reload which just makes it
|
||||||
//! more difficult to match future templates.
|
//! more difficult to match future templates.
|
||||||
|
|
||||||
use crate::innerlude::*;
|
|
||||||
use crate::HotReloadingContext;
|
|
||||||
use dioxus_core::internal::{
|
use dioxus_core::internal::{
|
||||||
FmtedSegments, HotReloadAttributeValue, HotReloadDynamicAttribute, HotReloadDynamicNode,
|
FmtedSegments, HotReloadAttributeValue, HotReloadDynamicAttribute, HotReloadDynamicNode,
|
||||||
HotReloadLiteral, HotReloadedTemplate, NamedAttribute,
|
HotReloadLiteral, HotReloadedTemplate, NamedAttribute,
|
||||||
};
|
};
|
||||||
|
use dioxus_core_types::HotReloadingContext;
|
||||||
|
use dioxus_rsx::*;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use crate::extensions::{html_tag_and_namespace, intern, to_template_node};
|
||||||
|
|
||||||
use super::last_build_state::LastBuildState;
|
use super::last_build_state::LastBuildState;
|
||||||
|
|
||||||
/// A result of hot reloading
|
/// A result of hot reloading
|
||||||
@@ -193,7 +195,7 @@ impl HotReloadResult {
|
|||||||
let roots: Vec<_> = new
|
let roots: Vec<_> = new
|
||||||
.roots
|
.roots
|
||||||
.iter()
|
.iter()
|
||||||
.map(|node| node.to_template_node::<Ctx>())
|
.map(|node| to_template_node::<Ctx>(node))
|
||||||
.collect();
|
.collect();
|
||||||
let roots: &[dioxus_core::TemplateNode] = intern(&*roots);
|
let roots: &[dioxus_core::TemplateNode] = intern(&*roots);
|
||||||
|
|
||||||
@@ -589,7 +591,7 @@ impl HotReloadResult {
|
|||||||
&mut self,
|
&mut self,
|
||||||
attribute: &Attribute,
|
attribute: &Attribute,
|
||||||
) -> Option<()> {
|
) -> Option<()> {
|
||||||
let (tag, namespace) = attribute.html_tag_and_namespace::<Ctx>();
|
let (tag, namespace) = html_tag_and_namespace::<Ctx>(attribute);
|
||||||
|
|
||||||
// If the attribute is a spread, try to grab it from the last build
|
// If the attribute is a spread, try to grab it from the last build
|
||||||
// If it wasn't in the last build with the same name, we can't hot reload it
|
// If it wasn't in the last build with the same name, we can't hot reload it
|
||||||
@@ -0,0 +1,111 @@
|
|||||||
|
use dioxus_core::TemplateNode;
|
||||||
|
use dioxus_core_types::HotReloadingContext;
|
||||||
|
use dioxus_rsx::*;
|
||||||
|
use internment::Intern;
|
||||||
|
use std::hash::Hash;
|
||||||
|
|
||||||
|
// interns a object into a static object, reusing the value if it already exists
|
||||||
|
pub(crate) fn intern<T: Eq + Hash + Send + Sync + ?Sized + 'static>(
|
||||||
|
s: impl Into<Intern<T>>,
|
||||||
|
) -> &'static T {
|
||||||
|
s.into().as_ref()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn html_tag_and_namespace<Ctx: HotReloadingContext>(
|
||||||
|
attr: &Attribute,
|
||||||
|
) -> (&'static str, Option<&'static str>) {
|
||||||
|
let attribute_name_rust = attr.name.to_string();
|
||||||
|
let element_name = attr.el_name.as_ref().unwrap();
|
||||||
|
let rust_name = match element_name {
|
||||||
|
ElementName::Ident(i) => i.to_string(),
|
||||||
|
// If this is a web component, just use the name of the elements instead of mapping the attribute
|
||||||
|
// through the hot reloading context
|
||||||
|
ElementName::Custom(_) => return (intern(attribute_name_rust.as_str()), None),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ctx::map_attribute(&rust_name, &attribute_name_rust)
|
||||||
|
.unwrap_or((intern(attribute_name_rust.as_str()), None))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_template_attribute<Ctx: HotReloadingContext>(
|
||||||
|
attr: &Attribute,
|
||||||
|
) -> dioxus_core::TemplateAttribute {
|
||||||
|
use dioxus_core::TemplateAttribute;
|
||||||
|
|
||||||
|
// If it's a dynamic node, just return it
|
||||||
|
// For dynamic attributes, we need to check the mapping to see if that mapping exists
|
||||||
|
// todo: one day we could generate new dynamic attributes on the fly if they're a literal,
|
||||||
|
// or something sufficiently serializable
|
||||||
|
// (ie `checked`` being a bool and bools being interpretable)
|
||||||
|
//
|
||||||
|
// For now, just give up if that attribute doesn't exist in the mapping
|
||||||
|
if !attr.is_static_str_literal() {
|
||||||
|
let id = attr.dyn_idx.get();
|
||||||
|
return TemplateAttribute::Dynamic { id };
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise it's a static node and we can build it
|
||||||
|
let (_, value) = attr.as_static_str_literal().unwrap();
|
||||||
|
let (name, namespace) = html_tag_and_namespace::<Ctx>(attr);
|
||||||
|
|
||||||
|
TemplateAttribute::Static {
|
||||||
|
name,
|
||||||
|
namespace,
|
||||||
|
value: intern(value.to_static().unwrap().as_str()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert this BodyNode into a TemplateNode.
|
||||||
|
///
|
||||||
|
/// dioxus-core uses this to understand templates at compiletime
|
||||||
|
pub fn to_template_node<Ctx: HotReloadingContext>(node: &BodyNode) -> dioxus_core::TemplateNode {
|
||||||
|
use dioxus_core::TemplateNode;
|
||||||
|
match node {
|
||||||
|
BodyNode::Element(el) => {
|
||||||
|
let rust_name = el.name.to_string();
|
||||||
|
|
||||||
|
let (tag, namespace) =
|
||||||
|
Ctx::map_element(&rust_name).unwrap_or((intern(rust_name.as_str()), None));
|
||||||
|
|
||||||
|
TemplateNode::Element {
|
||||||
|
tag,
|
||||||
|
namespace,
|
||||||
|
children: intern(
|
||||||
|
el.children
|
||||||
|
.iter()
|
||||||
|
.map(|c| to_template_node::<Ctx>(c))
|
||||||
|
.collect::<Vec<_>>(),
|
||||||
|
),
|
||||||
|
attrs: intern(
|
||||||
|
el.merged_attributes
|
||||||
|
.iter()
|
||||||
|
.map(|attr| to_template_attribute::<Ctx>(attr))
|
||||||
|
.collect::<Vec<_>>(),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BodyNode::Text(text) => text_to_template_node(text),
|
||||||
|
BodyNode::RawExpr(exp) => TemplateNode::Dynamic {
|
||||||
|
id: exp.dyn_idx.get(),
|
||||||
|
},
|
||||||
|
BodyNode::Component(comp) => TemplateNode::Dynamic {
|
||||||
|
id: comp.dyn_idx.get(),
|
||||||
|
},
|
||||||
|
BodyNode::ForLoop(floop) => TemplateNode::Dynamic {
|
||||||
|
id: floop.dyn_idx.get(),
|
||||||
|
},
|
||||||
|
BodyNode::IfChain(chain) => TemplateNode::Dynamic {
|
||||||
|
id: chain.dyn_idx.get(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn text_to_template_node(node: &TextNode) -> TemplateNode {
|
||||||
|
match node.input.to_static() {
|
||||||
|
Some(text) => TemplateNode::Text {
|
||||||
|
text: intern(text.as_str()),
|
||||||
|
},
|
||||||
|
None => TemplateNode::Dynamic {
|
||||||
|
id: node.dyn_idx.get(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
use crate::innerlude::*;
|
|
||||||
use dioxus_core::internal::{FmtSegment, FmtedSegments, HotReloadLiteral};
|
use dioxus_core::internal::{FmtSegment, FmtedSegments, HotReloadLiteral};
|
||||||
|
use dioxus_rsx::*;
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
|
|
||||||
/// A pool of items we can grab from during hot reloading.
|
/// A pool of items we can grab from during hot reloading.
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
mod collect;
|
||||||
|
pub use collect::*;
|
||||||
|
|
||||||
|
mod diff;
|
||||||
|
pub use diff::*;
|
||||||
|
|
||||||
|
mod last_build_state;
|
||||||
|
|
||||||
|
mod extensions;
|
||||||
+3
-4
@@ -10,10 +10,9 @@ use dioxus_core::{
|
|||||||
prelude::{Template, TemplateNode},
|
prelude::{Template, TemplateNode},
|
||||||
TemplateAttribute, VNode,
|
TemplateAttribute, VNode,
|
||||||
};
|
};
|
||||||
use dioxus_rsx::{
|
use dioxus_core_types::HotReloadingContext;
|
||||||
hot_reload::{self, diff_rsx, ChangedRsx, HotReloadResult},
|
use dioxus_rsx::CallBody;
|
||||||
CallBody, HotReloadingContext,
|
use dioxus_rsx_hotreload::{self, diff_rsx, ChangedRsx, HotReloadResult};
|
||||||
};
|
|
||||||
use proc_macro2::TokenStream;
|
use proc_macro2::TokenStream;
|
||||||
use quote::{quote, ToTokens};
|
use quote::{quote, ToTokens};
|
||||||
use syn::{parse::Parse, spanned::Spanned, token::Token, File};
|
use syn::{parse::Parse, spanned::Spanned, token::Token, File};
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
use dioxus_rsx::hot_reload::diff_rsx;
|
use dioxus_rsx_hotreload::diff_rsx;
|
||||||
use syn::File;
|
use syn::File;
|
||||||
|
|
||||||
macro_rules! assert_rsx_changed {
|
macro_rules! assert_rsx_changed {
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+3
-10
@@ -13,20 +13,13 @@ keywords = ["dom", "ui", "gui", "react"]
|
|||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
quote = { workspace = true }
|
|
||||||
proc-macro2 = { workspace = true, features = ["span-locations"] }
|
proc-macro2 = { workspace = true, features = ["span-locations"] }
|
||||||
dioxus-core = { workspace = true, optional = true }
|
proc-macro2-diagnostics = { workspace = true }
|
||||||
|
quote = { workspace = true }
|
||||||
syn = { workspace = true, features = ["full", "extra-traits", "visit", "visit-mut"] }
|
syn = { workspace = true, features = ["full", "extra-traits", "visit", "visit-mut"] }
|
||||||
serde = { workspace = true, features = ["derive"], optional = true }
|
|
||||||
internment = { version = "0.7.0", optional = true }
|
|
||||||
tracing = { workspace = true }
|
|
||||||
proc-macro2-diagnostics = { version = "0.10", default-features = false }
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["hot_reload"]
|
default = []
|
||||||
hot_reload_traits = []
|
|
||||||
hot_reload = ["dep:internment", "dep:dioxus-core", "hot_reload_traits", "serde"]
|
|
||||||
serde = ["dep:serde", "dioxus-core/serialize"]
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
prettyplease = { workspace = true }
|
prettyplease = { workspace = true }
|
||||||
|
|||||||
@@ -166,52 +166,6 @@ impl Attribute {
|
|||||||
self.as_static_str_literal().is_some()
|
self.as_static_str_literal().is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "hot_reload")]
|
|
||||||
pub(crate) fn html_tag_and_namespace<Ctx: crate::HotReloadingContext>(
|
|
||||||
&self,
|
|
||||||
) -> (&'static str, Option<&'static str>) {
|
|
||||||
let attribute_name_rust = self.name.to_string();
|
|
||||||
let element_name = self.el_name.as_ref().unwrap();
|
|
||||||
let rust_name = match element_name {
|
|
||||||
ElementName::Ident(i) => i.to_string(),
|
|
||||||
// If this is a web component, just use the name of the elements instead of mapping the attribute
|
|
||||||
// through the hot reloading context
|
|
||||||
ElementName::Custom(_) => return (intern(attribute_name_rust.as_str()), None),
|
|
||||||
};
|
|
||||||
|
|
||||||
Ctx::map_attribute(&rust_name, &attribute_name_rust)
|
|
||||||
.unwrap_or((intern(attribute_name_rust.as_str()), None))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "hot_reload")]
|
|
||||||
pub fn to_template_attribute<Ctx: crate::HotReloadingContext>(
|
|
||||||
&self,
|
|
||||||
) -> dioxus_core::TemplateAttribute {
|
|
||||||
use dioxus_core::TemplateAttribute;
|
|
||||||
|
|
||||||
// If it's a dynamic node, just return it
|
|
||||||
// For dynamic attributes, we need to check the mapping to see if that mapping exists
|
|
||||||
// todo: one day we could generate new dynamic attributes on the fly if they're a literal,
|
|
||||||
// or something sufficiently serializable
|
|
||||||
// (ie `checked`` being a bool and bools being interpretable)
|
|
||||||
//
|
|
||||||
// For now, just give up if that attribute doesn't exist in the mapping
|
|
||||||
if !self.is_static_str_literal() {
|
|
||||||
let id = self.dyn_idx.get();
|
|
||||||
return TemplateAttribute::Dynamic { id };
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise it's a static node and we can build it
|
|
||||||
let (_, value) = self.as_static_str_literal().unwrap();
|
|
||||||
let (name, namespace) = self.html_tag_and_namespace::<Ctx>();
|
|
||||||
|
|
||||||
TemplateAttribute::Static {
|
|
||||||
name,
|
|
||||||
namespace,
|
|
||||||
value: intern(value.to_static().unwrap().as_str()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn rendered_as_dynamic_attr(&self) -> TokenStream2 {
|
pub fn rendered_as_dynamic_attr(&self) -> TokenStream2 {
|
||||||
// Shortcut out with spreads
|
// Shortcut out with spreads
|
||||||
if let AttributeName::Spread(_) = self.name {
|
if let AttributeName::Spread(_) = self.name {
|
||||||
|
|||||||
@@ -253,7 +253,7 @@ impl Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Iterate over the props of the component (without spreads, key, and custom attributes)
|
// Iterate over the props of the component (without spreads, key, and custom attributes)
|
||||||
pub(crate) fn component_props(&self) -> impl Iterator<Item = &Attribute> {
|
pub fn component_props(&self) -> impl Iterator<Item = &Attribute> {
|
||||||
self.fields
|
self.fields
|
||||||
.iter()
|
.iter()
|
||||||
.filter(move |attr| !attr.name.is_likely_key())
|
.filter(move |attr| !attr.name.is_likely_key())
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
#[cfg(feature = "hot_reload")]
|
|
||||||
mod collect;
|
|
||||||
#[cfg(feature = "hot_reload")]
|
|
||||||
pub use collect::*;
|
|
||||||
|
|
||||||
#[cfg(feature = "hot_reload_traits")]
|
|
||||||
mod context;
|
|
||||||
#[cfg(feature = "hot_reload_traits")]
|
|
||||||
pub use context::*;
|
|
||||||
|
|
||||||
#[cfg(feature = "hot_reload")]
|
|
||||||
mod diff;
|
|
||||||
#[cfg(feature = "hot_reload")]
|
|
||||||
pub use diff::*;
|
|
||||||
|
|
||||||
#[cfg(feature = "hot_reload")]
|
|
||||||
mod last_build_state;
|
|
||||||
@@ -78,11 +78,6 @@ pub use partial_closure::PartialClosure;
|
|||||||
pub use rsx_call::*;
|
pub use rsx_call::*;
|
||||||
pub use template_body::TemplateBody;
|
pub use template_body::TemplateBody;
|
||||||
|
|
||||||
pub mod hot_reload;
|
|
||||||
|
|
||||||
#[cfg(feature = "hot_reload_traits")]
|
|
||||||
pub use hot_reload::HotReloadingContext;
|
|
||||||
|
|
||||||
use quote::{quote, ToTokens, TokenStreamExt};
|
use quote::{quote, ToTokens, TokenStreamExt};
|
||||||
use syn::{
|
use syn::{
|
||||||
parse::{Parse, ParseStream},
|
parse::{Parse, ParseStream},
|
||||||
|
|||||||
@@ -126,52 +126,6 @@ impl ToTokens for BodyNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl BodyNode {
|
impl BodyNode {
|
||||||
/// Convert this BodyNode into a TemplateNode.
|
|
||||||
///
|
|
||||||
/// dioxus-core uses this to understand templates at compiletime
|
|
||||||
#[cfg(feature = "hot_reload")]
|
|
||||||
pub fn to_template_node<Ctx: crate::HotReloadingContext>(&self) -> dioxus_core::TemplateNode {
|
|
||||||
use dioxus_core::TemplateNode;
|
|
||||||
match self {
|
|
||||||
BodyNode::Element(el) => {
|
|
||||||
let rust_name = el.name.to_string();
|
|
||||||
|
|
||||||
let (tag, namespace) =
|
|
||||||
Ctx::map_element(&rust_name).unwrap_or((intern(rust_name.as_str()), None));
|
|
||||||
|
|
||||||
TemplateNode::Element {
|
|
||||||
tag,
|
|
||||||
namespace,
|
|
||||||
children: intern(
|
|
||||||
el.children
|
|
||||||
.iter()
|
|
||||||
.map(|c| c.to_template_node::<Ctx>())
|
|
||||||
.collect::<Vec<_>>(),
|
|
||||||
),
|
|
||||||
attrs: intern(
|
|
||||||
el.merged_attributes
|
|
||||||
.iter()
|
|
||||||
.map(|attr| attr.to_template_attribute::<Ctx>())
|
|
||||||
.collect::<Vec<_>>(),
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
BodyNode::Text(text) => text.to_template_node(),
|
|
||||||
BodyNode::RawExpr(exp) => TemplateNode::Dynamic {
|
|
||||||
id: exp.dyn_idx.get(),
|
|
||||||
},
|
|
||||||
BodyNode::Component(comp) => TemplateNode::Dynamic {
|
|
||||||
id: comp.dyn_idx.get(),
|
|
||||||
},
|
|
||||||
BodyNode::ForLoop(floop) => TemplateNode::Dynamic {
|
|
||||||
id: floop.dyn_idx.get(),
|
|
||||||
},
|
|
||||||
BodyNode::IfChain(chain) => TemplateNode::Dynamic {
|
|
||||||
id: chain.dyn_idx.get(),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_dyn_idx(&self) -> usize {
|
pub fn get_dyn_idx(&self) -> usize {
|
||||||
match self {
|
match self {
|
||||||
BodyNode::Text(text) => text.dyn_idx.get(),
|
BodyNode::Text(text) => text.dyn_idx.get(),
|
||||||
|
|||||||
@@ -238,7 +238,7 @@ impl TemplateBody {
|
|||||||
self.roots.is_empty()
|
self.roots.is_empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn implicit_key(&self) -> Option<&AttributeValue> {
|
pub fn implicit_key(&self) -> Option<&AttributeValue> {
|
||||||
match self.roots.first() {
|
match self.roots.first() {
|
||||||
Some(BodyNode::Element(el)) => el.key(),
|
Some(BodyNode::Element(el)) => el.key(),
|
||||||
Some(BodyNode::Component(comp)) => comp.get_key(),
|
Some(BodyNode::Component(comp)) => comp.get_key(),
|
||||||
@@ -310,7 +310,7 @@ impl TemplateBody {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Iterate through the literal component properties of this rsx call in depth-first order
|
/// Iterate through the literal component properties of this rsx call in depth-first order
|
||||||
pub(crate) fn literal_component_properties(&self) -> impl Iterator<Item = &HotLiteral> + '_ {
|
pub fn literal_component_properties(&self) -> impl Iterator<Item = &HotLiteral> + '_ {
|
||||||
self.dynamic_nodes()
|
self.dynamic_nodes()
|
||||||
.filter_map(|node| {
|
.filter_map(|node| {
|
||||||
if let BodyNode::Component(component) = node {
|
if let BodyNode::Component(component) = node {
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
#[cfg(feature = "hot_reload")]
|
|
||||||
use dioxus_core::TemplateNode;
|
|
||||||
|
|
||||||
use crate::{literal::HotLiteral, location::DynIdx, HotReloadFormattedSegment, IfmtInput};
|
use crate::{literal::HotLiteral, location::DynIdx, HotReloadFormattedSegment, IfmtInput};
|
||||||
use proc_macro2::{Span, TokenStream as TokenStream2};
|
use proc_macro2::{Span, TokenStream as TokenStream2};
|
||||||
use quote::ToTokens;
|
use quote::ToTokens;
|
||||||
@@ -62,19 +59,6 @@ impl TextNode {
|
|||||||
pub fn is_static(&self) -> bool {
|
pub fn is_static(&self) -> bool {
|
||||||
self.input.is_static()
|
self.input.is_static()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "hot_reload")]
|
|
||||||
pub fn to_template_node(&self) -> TemplateNode {
|
|
||||||
use crate::intern;
|
|
||||||
match self.input.to_static() {
|
|
||||||
Some(text) => TemplateNode::Text {
|
|
||||||
text: intern(text.as_str()),
|
|
||||||
},
|
|
||||||
None => TemplateNode::Dynamic {
|
|
||||||
id: self.dyn_idx.get(),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
#![allow(unused)]
|
#![allow(unused)]
|
||||||
|
|
||||||
#[cfg(feature = "hot_reload")]
|
|
||||||
use internment::Intern;
|
|
||||||
|
|
||||||
use proc_macro2::TokenStream as TokenStream2;
|
use proc_macro2::TokenStream as TokenStream2;
|
||||||
use std::{fmt::Debug, hash::Hash};
|
use std::{fmt::Debug, hash::Hash};
|
||||||
use syn::{
|
use syn::{
|
||||||
@@ -11,14 +8,6 @@ use syn::{
|
|||||||
Ident,
|
Ident,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// interns a object into a static object, reusing the value if it already exists
|
|
||||||
#[cfg(feature = "hot_reload")]
|
|
||||||
pub(crate) fn intern<T: Eq + Hash + Send + Sync + ?Sized + 'static>(
|
|
||||||
s: impl Into<Intern<T>>,
|
|
||||||
) -> &'static T {
|
|
||||||
s.into().as_ref()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Parse a raw ident and return a new ident with the r# prefix added
|
/// Parse a raw ident and return a new ident with the r# prefix added
|
||||||
pub fn parse_raw_ident(parse_buffer: &ParseBuffer) -> syn::Result<Ident> {
|
pub fn parse_raw_ident(parse_buffer: &ParseBuffer) -> syn::Result<Ident> {
|
||||||
// First try to parse as a normal ident
|
// First try to parse as a normal ident
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
dioxus_core :: TemplateNode :: Element { tag : dioxus_elements :: elements :: circle :: TAG_NAME , namespace : dioxus_elements :: elements :: circle :: NAME_SPACE , attrs : & [dioxus_core :: TemplateAttribute :: Dynamic { id : 0usize } , dioxus_core :: TemplateAttribute :: Dynamic { id : 1usize } , dioxus_core :: TemplateAttribute :: Dynamic { id : 2usize } , dioxus_core :: TemplateAttribute :: Static { name : dioxus_elements :: elements :: circle :: stroke . 0 , namespace : dioxus_elements :: elements :: circle :: stroke . 1 , value : "green" , } , dioxus_core :: TemplateAttribute :: Static { name : dioxus_elements :: elements :: circle :: fill . 0 , namespace : dioxus_elements :: elements :: circle :: fill . 1 , value : "yellow" , } ,] , children : & [] , }
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
|
|
||||||
rsx! {
|
|
||||||
circle {
|
|
||||||
cx: 50,
|
|
||||||
cy: 50,
|
|
||||||
r: 40,
|
|
||||||
stroke: "green",
|
|
||||||
fill: "yellow"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Reference in new issue
Block a user