Fix diffing Option<String> (#2746)
This commit is contained in:
1 parent
115cc0ad42
commit
33f3d40a49
3 files changed
+101
-3
No files matched your search
@@ -44,11 +44,20 @@ impl VirtualDom {
|
|||||||
) {
|
) {
|
||||||
let m = self.create_children(to.as_deref_mut(), r, parent);
|
let m = self.create_children(to.as_deref_mut(), r, parent);
|
||||||
if let Some(to) = to {
|
if let Some(to) = to {
|
||||||
to.replace_node_with(placeholder_id, m);
|
self.replace_placeholder_with_nodes_on_stack(to, placeholder_id, m)
|
||||||
self.reclaim(placeholder_id);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn replace_placeholder_with_nodes_on_stack(
|
||||||
|
&mut self,
|
||||||
|
to: &mut impl WriteMutations,
|
||||||
|
placeholder_id: ElementId,
|
||||||
|
m: usize,
|
||||||
|
) {
|
||||||
|
to.replace_node_with(placeholder_id, m);
|
||||||
|
self.reclaim(placeholder_id);
|
||||||
|
}
|
||||||
|
|
||||||
fn nodes_to_placeholder(
|
fn nodes_to_placeholder(
|
||||||
&mut self,
|
&mut self,
|
||||||
mut to: Option<&mut impl WriteMutations>,
|
mut to: Option<&mut impl WriteMutations>,
|
||||||
|
|||||||
@@ -84,6 +84,12 @@ impl VNode {
|
|||||||
self.diff_vtext(to, mount, idx, old, new)
|
self.diff_vtext(to, mount, idx, old, new)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
(Text(_), Placeholder(_)) => {
|
||||||
|
self.replace_text_with_placeholder(to, mount, idx, dom)
|
||||||
|
},
|
||||||
|
(Placeholder(_), Text(new)) => {
|
||||||
|
self.replace_placeholder_with_text(to, mount, idx, new, dom)
|
||||||
|
},
|
||||||
(Placeholder(_), Placeholder(_)) => {},
|
(Placeholder(_), Placeholder(_)) => {},
|
||||||
(Fragment(old), Fragment(new)) => dom.diff_non_empty_fragment(to, old, new, Some(self.reference_to_dynamic_node(mount, idx))),
|
(Fragment(old), Fragment(new)) => dom.diff_non_empty_fragment(to, old, new, Some(self.reference_to_dynamic_node(mount, idx))),
|
||||||
(Component(old), Component(new)) => {
|
(Component(old), Component(new)) => {
|
||||||
@@ -100,6 +106,42 @@ impl VNode {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Replace a text node with a placeholder node
|
||||||
|
pub(crate) fn replace_text_with_placeholder(
|
||||||
|
&self,
|
||||||
|
to: Option<&mut impl WriteMutations>,
|
||||||
|
mount: MountId,
|
||||||
|
idx: usize,
|
||||||
|
dom: &mut VirtualDom,
|
||||||
|
) {
|
||||||
|
if let Some(to) = to {
|
||||||
|
// Grab the text element id from the mount and replace it with a new placeholder
|
||||||
|
let text_id = ElementId(dom.mounts[mount.0].mounted_dynamic_nodes[idx]);
|
||||||
|
let (id, _) = self.create_dynamic_node_with_path(mount, idx, dom);
|
||||||
|
to.create_placeholder(id);
|
||||||
|
to.replace_node_with(text_id, 1);
|
||||||
|
dom.reclaim(text_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Replace a placeholder node with a text node
|
||||||
|
pub(crate) fn replace_placeholder_with_text(
|
||||||
|
&self,
|
||||||
|
to: Option<&mut impl WriteMutations>,
|
||||||
|
mount: MountId,
|
||||||
|
idx: usize,
|
||||||
|
new: &VText,
|
||||||
|
dom: &mut VirtualDom,
|
||||||
|
) {
|
||||||
|
if let Some(to) = to {
|
||||||
|
// Grab the placeholder id from the mount and replace it with a new text node
|
||||||
|
let placeholder_id = ElementId(dom.mounts[mount.0].mounted_dynamic_nodes[idx]);
|
||||||
|
let (new_id, _) = self.create_dynamic_node_with_path(mount, idx, dom);
|
||||||
|
to.create_text_node(&new.value, new_id);
|
||||||
|
dom.replace_placeholder_with_nodes_on_stack(to, placeholder_id, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Try to get the dynamic node and its index for a root node
|
/// Try to get the dynamic node and its index for a root node
|
||||||
pub(crate) fn get_dynamic_root_node_and_id(
|
pub(crate) fn get_dynamic_root_node_and_id(
|
||||||
&self,
|
&self,
|
||||||
@@ -880,7 +922,7 @@ impl VNode {
|
|||||||
) -> usize {
|
) -> usize {
|
||||||
let (id, path) = self.create_dynamic_node_with_path(mount, idx, dom);
|
let (id, path) = self.create_dynamic_node_with_path(mount, idx, dom);
|
||||||
|
|
||||||
// If this is a root node, the path is empty and we need to create a new text node
|
// If this is a root node, the path is empty and we need to create a new placeholder node
|
||||||
if path.is_empty() {
|
if path.is_empty() {
|
||||||
to.create_placeholder(id);
|
to.create_placeholder(id);
|
||||||
// We create one node on the stack
|
// We create one node on the stack
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
use dioxus::dioxus_core::{ElementId, Mutation::*};
|
||||||
|
use dioxus::prelude::*;
|
||||||
|
use pretty_assertions::assert_eq;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn toggle_option_text() {
|
||||||
|
let mut dom = VirtualDom::new(|| {
|
||||||
|
let gen = generation();
|
||||||
|
let text = if gen % 2 != 0 { Some("hello") } else { None };
|
||||||
|
|
||||||
|
rsx! {
|
||||||
|
div {
|
||||||
|
{text}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// load the div and then assign the None as a placeholder
|
||||||
|
assert_eq!(
|
||||||
|
dom.rebuild_to_vec().sanitize().edits,
|
||||||
|
[
|
||||||
|
LoadTemplate { name: "template", index: 0, id: ElementId(1,) },
|
||||||
|
AssignId { path: &[0], id: ElementId(2,) },
|
||||||
|
AppendChildren { id: ElementId(0), m: 1 },
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
// Rendering again should replace the placeholder with an text node
|
||||||
|
dom.mark_dirty(ScopeId::APP);
|
||||||
|
assert_eq!(
|
||||||
|
dom.render_immediate_to_vec().sanitize().edits,
|
||||||
|
[
|
||||||
|
CreateTextNode { value: "hello".to_string(), id: ElementId(3,) },
|
||||||
|
ReplaceWith { id: ElementId(2,), m: 1 },
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
// Rendering again should replace the placeholder with an text node
|
||||||
|
dom.mark_dirty(ScopeId::APP);
|
||||||
|
assert_eq!(
|
||||||
|
dom.render_immediate_to_vec().sanitize().edits,
|
||||||
|
[
|
||||||
|
CreatePlaceholder { id: ElementId(2,) },
|
||||||
|
ReplaceWith { id: ElementId(3,), m: 1 },
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in new issue
Block a user