mirror of
https://github.com/DioxusLabs/dioxus
synced 2024-11-25 13:40:19 +00:00
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:
parent
cab573eefd
commit
959ab67624
5 changed files with 259 additions and 204 deletions
359
Cargo.lock
generated
359
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -1,8 +1,8 @@
|
|||
#![cfg(not(miri))]
|
||||
|
||||
use dioxus::prelude::*;
|
||||
use dioxus_core::{AttributeValue, DynamicNode, NoOpMutations, VComponent, VNode, *};
|
||||
use std::{any::Any, cfg, collections::HashSet, default::Default, rc::Rc};
|
||||
use dioxus_core::{AttributeValue, DynamicNode, NoOpMutations, Template, VComponent, VNode, *};
|
||||
use std::{any::Any, cell::RefCell, cfg, collections::HashSet, default::Default, rc::Rc};
|
||||
|
||||
fn random_ns() -> Option<&'static str> {
|
||||
let namespace = rand::random::<u8>() % 2;
|
||||
|
@ -127,13 +127,18 @@ enum DynamicNodeType {
|
|||
Other,
|
||||
}
|
||||
|
||||
fn create_random_template() -> (Template, Vec<DynamicNodeType>) {
|
||||
let mut dynamic_node_type = Vec::new();
|
||||
fn create_random_template(depth: usize) -> (Template, Box<[DynamicNode]>) {
|
||||
let mut dynamic_node_types = Vec::new();
|
||||
let mut template_idx = 0;
|
||||
let mut attr_idx = 0;
|
||||
let roots = (0..(1 + rand::random::<usize>() % 5))
|
||||
.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<_>>();
|
||||
assert!(!roots.is_empty());
|
||||
|
@ -157,10 +162,16 @@ fn create_random_template() -> (Template, Vec<DynamicNodeType>) {
|
|||
.collect::<Vec<_>>()
|
||||
.into_boxed_slice(),
|
||||
);
|
||||
(
|
||||
Template { roots, node_paths, attr_paths },
|
||||
dynamic_node_type,
|
||||
)
|
||||
let dynamic_nodes = dynamic_node_types
|
||||
.iter()
|
||||
.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 {
|
||||
|
@ -223,31 +234,46 @@ struct DepthProps {
|
|||
}
|
||||
|
||||
fn create_random_element(cx: DepthProps) -> Element {
|
||||
let last_template = use_hook(|| Rc::new(RefCell::new(None)));
|
||||
if rand::random::<usize>() % 10 == 0 {
|
||||
needs_update();
|
||||
}
|
||||
let range = if cx.root { 2 } else { 3 };
|
||||
let node = match rand::random::<usize>() % range {
|
||||
0 | 1 => {
|
||||
let (template, dynamic_node_types) = create_random_template();
|
||||
let node = VNode::new(
|
||||
// Change both the template and the dynamic nodes
|
||||
0 => {
|
||||
let (template, dynamic_nodes) = create_random_template(cx.depth + 1);
|
||||
last_template.replace(Some(template));
|
||||
VNode::new(
|
||||
None,
|
||||
template,
|
||||
dynamic_node_types
|
||||
.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(),
|
||||
dynamic_nodes,
|
||||
(0..template.attr_paths.len())
|
||||
.map(|_| Box::new([create_random_dynamic_attr()]) as Box<[Attribute]>)
|
||||
.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(),
|
||||
};
|
||||
Element::Ok(node)
|
||||
|
|
|
@ -13,7 +13,7 @@ pub fn apply_changes(dom: &mut VirtualDom, msg: &HotReloadMsg) {
|
|||
let id = &template.location;
|
||||
let value = template.template.clone();
|
||||
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,
|
||||
behavior: crate::ScrollBehavior,
|
||||
) -> std::pin::Pin<Box<dyn std::future::Future<Output = crate::MountedResult<()>>>> {
|
||||
let options = web_sys::ScrollIntoViewOptions::new();
|
||||
match behavior {
|
||||
crate::ScrollBehavior::Instant => self.scroll_into_view_with_scroll_into_view_options(
|
||||
web_sys::ScrollIntoViewOptions::new().behavior(web_sys::ScrollBehavior::Instant),
|
||||
),
|
||||
crate::ScrollBehavior::Smooth => self.scroll_into_view_with_scroll_into_view_options(
|
||||
web_sys::ScrollIntoViewOptions::new().behavior(web_sys::ScrollBehavior::Smooth),
|
||||
),
|
||||
crate::ScrollBehavior::Instant => {
|
||||
options.set_behavior(web_sys::ScrollBehavior::Instant);
|
||||
}
|
||||
crate::ScrollBehavior::Smooth => {
|
||||
options.set_behavior(web_sys::ScrollBehavior::Smooth);
|
||||
}
|
||||
}
|
||||
self.scroll_into_view_with_scroll_into_view_options(&options);
|
||||
|
||||
Box::pin(async { Ok(()) })
|
||||
}
|
||||
|
|
|
@ -149,10 +149,17 @@ impl ToTokens for TemplateBody {
|
|||
|
||||
#[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
|
||||
// But the key is what's keeping it stable
|
||||
let __template = GlobalSignal::with_key(
|
||||
|| #hot_reload_mapping,
|
||||
|| None::<dioxus_core::internal::HotReloadedTemplate>,
|
||||
{
|
||||
const PATH: &str = dioxus_core::const_format::str_replace!(file!(), "\\\\", "/");
|
||||
const NORMAL: &str = dioxus_core::const_format::str_replace!(PATH, '\\', "/");
|
||||
|
@ -161,6 +168,13 @@ impl ToTokens for TemplateBody {
|
|||
);
|
||||
|
||||
__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(
|
||||
vec![ #( #dynamic_text.to_string() ),* ],
|
||||
);
|
||||
|
|
Loading…
Reference in a new issue