Fix templates merging in debug mode in macros (#2828)
* Fix templates merging in debug mode in macros * Fix clippy * Fix web-sys scroll to deprecated warning
This commit is contained in:
1 parent
cab573eefd
commit
959ab67624
5 files changed
+259
-204
No files matched your search
Generated
+186
-173
File diff suppressed because it is too large.
Load diff
@@ -1,8 +1,8 @@
|
|||||||
#![cfg(not(miri))]
|
#![cfg(not(miri))]
|
||||||
|
|
||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
use dioxus_core::{AttributeValue, DynamicNode, NoOpMutations, VComponent, VNode, *};
|
use dioxus_core::{AttributeValue, DynamicNode, NoOpMutations, Template, VComponent, VNode, *};
|
||||||
use std::{any::Any, cfg, collections::HashSet, default::Default, rc::Rc};
|
use std::{any::Any, cell::RefCell, cfg, collections::HashSet, default::Default, rc::Rc};
|
||||||
|
|
||||||
fn random_ns() -> Option<&'static str> {
|
fn random_ns() -> Option<&'static str> {
|
||||||
let namespace = rand::random::<u8>() % 2;
|
let namespace = rand::random::<u8>() % 2;
|
||||||
@@ -127,13 +127,18 @@ enum DynamicNodeType {
|
|||||||
Other,
|
Other,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_random_template() -> (Template, Vec<DynamicNodeType>) {
|
fn create_random_template(depth: usize) -> (Template, Box<[DynamicNode]>) {
|
||||||
let mut dynamic_node_type = Vec::new();
|
let mut dynamic_node_types = Vec::new();
|
||||||
let mut template_idx = 0;
|
let mut template_idx = 0;
|
||||||
let mut attr_idx = 0;
|
let mut attr_idx = 0;
|
||||||
let roots = (0..(1 + rand::random::<usize>() % 5))
|
let roots = (0..(1 + rand::random::<usize>() % 5))
|
||||||
.map(|_| {
|
.map(|_| {
|
||||||
create_random_template_node(&mut dynamic_node_type, &mut template_idx, &mut attr_idx, 0)
|
create_random_template_node(
|
||||||
|
&mut dynamic_node_types,
|
||||||
|
&mut template_idx,
|
||||||
|
&mut attr_idx,
|
||||||
|
0,
|
||||||
|
)
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
assert!(!roots.is_empty());
|
assert!(!roots.is_empty());
|
||||||
@@ -157,10 +162,16 @@ fn create_random_template() -> (Template, Vec<DynamicNodeType>) {
|
|||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.into_boxed_slice(),
|
.into_boxed_slice(),
|
||||||
);
|
);
|
||||||
(
|
let dynamic_nodes = dynamic_node_types
|
||||||
Template { roots, node_paths, attr_paths },
|
.iter()
|
||||||
dynamic_node_type,
|
.map(|ty| match ty {
|
||||||
)
|
DynamicNodeType::Text => {
|
||||||
|
DynamicNode::Text(VText::new(format!("{}", rand::random::<usize>())))
|
||||||
|
}
|
||||||
|
DynamicNodeType::Other => create_random_dynamic_node(depth + 1),
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
(Template { roots, node_paths, attr_paths }, dynamic_nodes)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_random_dynamic_node(depth: usize) -> DynamicNode {
|
fn create_random_dynamic_node(depth: usize) -> DynamicNode {
|
||||||
@@ -223,31 +234,46 @@ struct DepthProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn create_random_element(cx: DepthProps) -> Element {
|
fn create_random_element(cx: DepthProps) -> Element {
|
||||||
|
let last_template = use_hook(|| Rc::new(RefCell::new(None)));
|
||||||
if rand::random::<usize>() % 10 == 0 {
|
if rand::random::<usize>() % 10 == 0 {
|
||||||
needs_update();
|
needs_update();
|
||||||
}
|
}
|
||||||
let range = if cx.root { 2 } else { 3 };
|
let range = if cx.root { 2 } else { 3 };
|
||||||
let node = match rand::random::<usize>() % range {
|
let node = match rand::random::<usize>() % range {
|
||||||
0 | 1 => {
|
// Change both the template and the dynamic nodes
|
||||||
let (template, dynamic_node_types) = create_random_template();
|
0 => {
|
||||||
let node = VNode::new(
|
let (template, dynamic_nodes) = create_random_template(cx.depth + 1);
|
||||||
|
last_template.replace(Some(template));
|
||||||
|
VNode::new(
|
||||||
None,
|
None,
|
||||||
template,
|
template,
|
||||||
dynamic_node_types
|
dynamic_nodes,
|
||||||
.iter()
|
|
||||||
.map(|ty| match ty {
|
|
||||||
DynamicNodeType::Text => {
|
|
||||||
DynamicNode::Text(VText::new(format!("{}", rand::random::<usize>())))
|
|
||||||
}
|
|
||||||
DynamicNodeType::Other => create_random_dynamic_node(cx.depth + 1),
|
|
||||||
})
|
|
||||||
.collect(),
|
|
||||||
(0..template.attr_paths.len())
|
(0..template.attr_paths.len())
|
||||||
.map(|_| Box::new([create_random_dynamic_attr()]) as Box<[Attribute]>)
|
.map(|_| Box::new([create_random_dynamic_attr()]) as Box<[Attribute]>)
|
||||||
.collect(),
|
.collect(),
|
||||||
);
|
)
|
||||||
node
|
|
||||||
}
|
}
|
||||||
|
// Change just the dynamic nodes
|
||||||
|
1 => {
|
||||||
|
let (template, dynamic_nodes) = match *last_template.borrow() {
|
||||||
|
Some(template) => (
|
||||||
|
template,
|
||||||
|
(0..template.node_paths.len())
|
||||||
|
.map(|_| create_random_dynamic_node(cx.depth + 1))
|
||||||
|
.collect(),
|
||||||
|
),
|
||||||
|
None => create_random_template(cx.depth + 1),
|
||||||
|
};
|
||||||
|
VNode::new(
|
||||||
|
None,
|
||||||
|
template,
|
||||||
|
dynamic_nodes,
|
||||||
|
(0..template.attr_paths.len())
|
||||||
|
.map(|_| Box::new([create_random_dynamic_attr()]) as Box<[Attribute]>)
|
||||||
|
.collect(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
// Remove the template
|
||||||
_ => VNode::default(),
|
_ => VNode::default(),
|
||||||
};
|
};
|
||||||
Element::Ok(node)
|
Element::Ok(node)
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ pub fn apply_changes(dom: &mut VirtualDom, msg: &HotReloadMsg) {
|
|||||||
let id = &template.location;
|
let id = &template.location;
|
||||||
let value = template.template.clone();
|
let value = template.template.clone();
|
||||||
if let Some(mut signal) = ctx.get_signal_with_key(id) {
|
if let Some(mut signal) = ctx.get_signal_with_key(id) {
|
||||||
signal.set(value);
|
signal.set(Some(value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -531,14 +531,16 @@ impl crate::RenderedElementBacking for web_sys::Element {
|
|||||||
&self,
|
&self,
|
||||||
behavior: crate::ScrollBehavior,
|
behavior: crate::ScrollBehavior,
|
||||||
) -> std::pin::Pin<Box<dyn std::future::Future<Output = crate::MountedResult<()>>>> {
|
) -> std::pin::Pin<Box<dyn std::future::Future<Output = crate::MountedResult<()>>>> {
|
||||||
|
let options = web_sys::ScrollIntoViewOptions::new();
|
||||||
match behavior {
|
match behavior {
|
||||||
crate::ScrollBehavior::Instant => self.scroll_into_view_with_scroll_into_view_options(
|
crate::ScrollBehavior::Instant => {
|
||||||
web_sys::ScrollIntoViewOptions::new().behavior(web_sys::ScrollBehavior::Instant),
|
options.set_behavior(web_sys::ScrollBehavior::Instant);
|
||||||
),
|
}
|
||||||
crate::ScrollBehavior::Smooth => self.scroll_into_view_with_scroll_into_view_options(
|
crate::ScrollBehavior::Smooth => {
|
||||||
web_sys::ScrollIntoViewOptions::new().behavior(web_sys::ScrollBehavior::Smooth),
|
options.set_behavior(web_sys::ScrollBehavior::Smooth);
|
||||||
),
|
}
|
||||||
}
|
}
|
||||||
|
self.scroll_into_view_with_scroll_into_view_options(&options);
|
||||||
|
|
||||||
Box::pin(async { Ok(()) })
|
Box::pin(async { Ok(()) })
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -149,10 +149,17 @@ impl ToTokens for TemplateBody {
|
|||||||
|
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
{
|
{
|
||||||
|
static __ORIGINAL_TEMPLATE: ::std::sync::OnceLock<dioxus_core::internal::HotReloadedTemplate> = ::std::sync::OnceLock::new();
|
||||||
|
fn __original_template() -> &'static dioxus_core::internal::HotReloadedTemplate {
|
||||||
|
if __ORIGINAL_TEMPLATE.get().is_none() {
|
||||||
|
_ = __ORIGINAL_TEMPLATE.set(#hot_reload_mapping);
|
||||||
|
}
|
||||||
|
__ORIGINAL_TEMPLATE.get().unwrap()
|
||||||
|
}
|
||||||
// The key is important here - we're creating a new GlobalSignal each call to this
|
// The key is important here - we're creating a new GlobalSignal each call to this
|
||||||
// But the key is what's keeping it stable
|
// But the key is what's keeping it stable
|
||||||
let __template = GlobalSignal::with_key(
|
let __template = GlobalSignal::with_key(
|
||||||
|| #hot_reload_mapping,
|
|| None::<dioxus_core::internal::HotReloadedTemplate>,
|
||||||
{
|
{
|
||||||
const PATH: &str = dioxus_core::const_format::str_replace!(file!(), "\\\\", "/");
|
const PATH: &str = dioxus_core::const_format::str_replace!(file!(), "\\\\", "/");
|
||||||
const NORMAL: &str = dioxus_core::const_format::str_replace!(PATH, '\\', "/");
|
const NORMAL: &str = dioxus_core::const_format::str_replace!(PATH, '\\', "/");
|
||||||
@@ -161,6 +168,13 @@ impl ToTokens for TemplateBody {
|
|||||||
);
|
);
|
||||||
|
|
||||||
__template.maybe_with_rt(|__template_read| {
|
__template.maybe_with_rt(|__template_read| {
|
||||||
|
// If the template has not been hot reloaded, we always use the original template
|
||||||
|
// Templates nested within macros may be merged because they have the same file-line-column-index
|
||||||
|
// They cannot be hot reloaded, so this prevents incorrect rendering
|
||||||
|
let __template_read = match __template_read.as_ref() {
|
||||||
|
Some(__template_read) => __template_read,
|
||||||
|
None => __original_template(),
|
||||||
|
};
|
||||||
let mut __dynamic_literal_pool = dioxus_core::internal::DynamicLiteralPool::new(
|
let mut __dynamic_literal_pool = dioxus_core::internal::DynamicLiteralPool::new(
|
||||||
vec![ #( #dynamic_text.to_string() ),* ],
|
vec![ #( #dynamic_text.to_string() ),* ],
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in new issue
Block a user