fix parents in placeholder diffing
This commit is contained in:
1 parent
b0733958f2
commit
c5ebdc9635
6 files changed
+50
-11
No files matched your search
@@ -85,7 +85,7 @@ fn app(cx: Scope) -> Element {
|
|||||||
};
|
};
|
||||||
// The VNode is a reference to the template with the dynamic parts of the rsx
|
// The VNode is a reference to the template with the dynamic parts of the rsx
|
||||||
::dioxus::core::VNode {
|
::dioxus::core::VNode {
|
||||||
parent: None,
|
parent: Default::default(),
|
||||||
key: None,
|
key: None,
|
||||||
// The static template this node will use. The template is stored in a Cell so it can be replaced with a new template when hot rsx reloading is enabled
|
// The static template this node will use. The template is stored in a Cell so it can be replaced with a new template when hot rsx reloading is enabled
|
||||||
template: std::cell::Cell::new(TEMPLATE),
|
template: std::cell::Cell::new(TEMPLATE),
|
||||||
|
|||||||
@@ -192,7 +192,15 @@ impl<'b> VirtualDom {
|
|||||||
};
|
};
|
||||||
self.create_dynamic_node(template_ref, node)
|
self.create_dynamic_node(template_ref, node)
|
||||||
}
|
}
|
||||||
Placeholder(VPlaceholder { id }) => {
|
Placeholder(VPlaceholder { id, parent }) => {
|
||||||
|
let template_ref = ElementRef {
|
||||||
|
path: ElementPath {
|
||||||
|
path: &template.template.get().node_paths[idx],
|
||||||
|
},
|
||||||
|
template: &template,
|
||||||
|
scope: self.runtime.current_scope_id().unwrap_or(ScopeId(0)),
|
||||||
|
};
|
||||||
|
parent.set(Some(self.next_element_ref(template_ref)));
|
||||||
let id = self.set_slot(id);
|
let id = self.set_slot(id);
|
||||||
self.mutations.push(CreatePlaceholder { id });
|
self.mutations.push(CreatePlaceholder { id });
|
||||||
1
|
1
|
||||||
@@ -510,6 +518,9 @@ impl<'b> VirtualDom {
|
|||||||
// Make sure the text node is assigned to the correct element
|
// Make sure the text node is assigned to the correct element
|
||||||
placeholder.id.set(Some(id));
|
placeholder.id.set(Some(id));
|
||||||
|
|
||||||
|
// Assign the placeholder's parent
|
||||||
|
placeholder.parent.set(Some(self.next_element_ref(parent)));
|
||||||
|
|
||||||
// Assign the ID to the existing node in the template
|
// Assign the ID to the existing node in the template
|
||||||
self.mutations.push(AssignId {
|
self.mutations.push(AssignId {
|
||||||
path: &parent.path.path[1..],
|
path: &parent.path.path[1..],
|
||||||
@@ -538,7 +549,7 @@ impl<'b> VirtualDom {
|
|||||||
self.assign_boundary_ref(parent, t);
|
self.assign_boundary_ref(parent, t);
|
||||||
self.create_scope(scope, t)
|
self.create_scope(scope, t)
|
||||||
}
|
}
|
||||||
Aborted(t) => self.mount_aborted(t),
|
Aborted(t) => self.mount_aborted(t, parent),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -554,10 +565,18 @@ impl<'b> VirtualDom {
|
|||||||
.unwrap_or_else(|| component.scope.get().unwrap())
|
.unwrap_or_else(|| component.scope.get().unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mount_aborted(&mut self, placeholder: &VPlaceholder) -> usize {
|
fn mount_aborted(
|
||||||
|
&mut self,
|
||||||
|
placeholder: &VPlaceholder,
|
||||||
|
parent: Option<ElementRef<'b>>,
|
||||||
|
) -> usize {
|
||||||
let id = self.next_element();
|
let id = self.next_element();
|
||||||
self.mutations.push(Mutation::CreatePlaceholder { id });
|
self.mutations.push(Mutation::CreatePlaceholder { id });
|
||||||
placeholder.id.set(Some(id));
|
placeholder.id.set(Some(id));
|
||||||
|
placeholder
|
||||||
|
.parent
|
||||||
|
.set(parent.map(|parent| self.next_element_ref(parent)));
|
||||||
|
|
||||||
1
|
1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -42,11 +42,18 @@ impl<'b> VirtualDom {
|
|||||||
(Ready(l), Aborted(p)) => self.diff_ok_to_err(l, p),
|
(Ready(l), Aborted(p)) => self.diff_ok_to_err(l, p),
|
||||||
|
|
||||||
// Just move over the placeholder
|
// Just move over the placeholder
|
||||||
(Aborted(l), Aborted(r)) => r.id.set(l.id.get()),
|
(Aborted(l), Aborted(r)) => {
|
||||||
|
r.id.set(l.id.get());
|
||||||
|
r.parent.set(l.parent.get())
|
||||||
|
}
|
||||||
|
|
||||||
// Placeholder becomes something
|
// Placeholder becomes something
|
||||||
// We should also clear the error now
|
// We should also clear the error now
|
||||||
(Aborted(l), Ready(r)) => self.replace_placeholder(l, [r], todo!()),
|
(Aborted(l), Ready(r)) => self.replace_placeholder(
|
||||||
|
l,
|
||||||
|
[r],
|
||||||
|
self.element_refs[l.parent.get().expect("root should not be none").0],
|
||||||
|
),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
self.runtime.scope_stack.borrow_mut().pop();
|
self.runtime.scope_stack.borrow_mut().pop();
|
||||||
@@ -55,6 +62,7 @@ impl<'b> VirtualDom {
|
|||||||
fn diff_ok_to_err(&mut self, l: &'b VNode<'b>, p: &'b VPlaceholder) {
|
fn diff_ok_to_err(&mut self, l: &'b VNode<'b>, p: &'b VPlaceholder) {
|
||||||
let id = self.next_element();
|
let id = self.next_element();
|
||||||
p.id.set(Some(id));
|
p.id.set(Some(id));
|
||||||
|
p.parent.set(l.parent.get());
|
||||||
self.mutations.push(Mutation::CreatePlaceholder { id });
|
self.mutations.push(Mutation::CreatePlaceholder { id });
|
||||||
|
|
||||||
let pre_edits = self.mutations.edits.len();
|
let pre_edits = self.mutations.edits.len();
|
||||||
@@ -164,10 +172,13 @@ impl<'b> VirtualDom {
|
|||||||
match (left_node, right_node) {
|
match (left_node, right_node) {
|
||||||
(Text(left), Text(right)) => self.diff_vtext(left, right),
|
(Text(left), Text(right)) => self.diff_vtext(left, right),
|
||||||
(Fragment(left), Fragment(right)) => self.diff_non_empty_fragment(left, right, parent),
|
(Fragment(left), Fragment(right)) => self.diff_non_empty_fragment(left, right, parent),
|
||||||
(Placeholder(left), Placeholder(right)) => right.id.set(left.id.get()),
|
(Placeholder(left), Placeholder(right)) => {
|
||||||
|
right.id.set(left.id.get());
|
||||||
|
right.parent.set(left.parent.get())
|
||||||
|
},
|
||||||
(Component(left), Component(right)) => self.diff_vcomponent(left, right, Some(parent)),
|
(Component(left), Component(right)) => self.diff_vcomponent(left, right, Some(parent)),
|
||||||
(Placeholder(left), Fragment(right)) => self.replace_placeholder(left, *right, parent),
|
(Placeholder(left), Fragment(right)) => self.replace_placeholder(left, *right, parent),
|
||||||
(Fragment(left), Placeholder(right)) => self.node_to_placeholder(left, right),
|
(Fragment(left), Placeholder(right)) => self.node_to_placeholder(left, right, parent),
|
||||||
_ => todo!("This is an usual custom case for dynamic nodes. We don't know how to handle it yet."),
|
_ => todo!("This is an usual custom case for dynamic nodes. We don't know how to handle it yet."),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -838,11 +849,17 @@ impl<'b> VirtualDom {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn node_to_placeholder(&mut self, l: &'b [VNode<'b>], r: &'b VPlaceholder) {
|
fn node_to_placeholder(
|
||||||
|
&mut self,
|
||||||
|
l: &'b [VNode<'b>],
|
||||||
|
r: &'b VPlaceholder,
|
||||||
|
parent: ElementRef<'b>,
|
||||||
|
) {
|
||||||
// Create the placeholder first, ensuring we get a dedicated ID for the placeholder
|
// Create the placeholder first, ensuring we get a dedicated ID for the placeholder
|
||||||
let placeholder = self.next_element();
|
let placeholder = self.next_element();
|
||||||
|
|
||||||
r.id.set(Some(placeholder));
|
r.id.set(Some(placeholder));
|
||||||
|
r.parent.set(Some(self.next_element_ref(parent)));
|
||||||
|
|
||||||
self.mutations
|
self.mutations
|
||||||
.push(Mutation::CreatePlaceholder { id: placeholder });
|
.push(Mutation::CreatePlaceholder { id: placeholder });
|
||||||
|
|||||||
@@ -373,6 +373,8 @@ impl<'a> VText<'a> {
|
|||||||
pub struct VPlaceholder {
|
pub struct VPlaceholder {
|
||||||
/// The ID of this node in the real DOM
|
/// The ID of this node in the real DOM
|
||||||
pub(crate) id: Cell<Option<ElementId>>,
|
pub(crate) id: Cell<Option<ElementId>>,
|
||||||
|
/// The parent of this node
|
||||||
|
pub(crate) parent: Cell<Option<BubbleId>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VPlaceholder {
|
impl VPlaceholder {
|
||||||
|
|||||||
@@ -12,9 +12,10 @@ use serde::{de::DeserializeOwned, Serialize};
|
|||||||
/// use dioxus_fullstack::prelude::*;
|
/// use dioxus_fullstack::prelude::*;
|
||||||
///
|
///
|
||||||
/// fn app(cx: Scope) -> Element {
|
/// fn app(cx: Scope) -> Element {
|
||||||
/// let state1 = use_state(cx, || from_server(|| {
|
/// let state1 = use_state(cx, || server_cached(|| {
|
||||||
/// 1234
|
/// 1234
|
||||||
/// }));
|
/// }));
|
||||||
|
/// todo!()
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn server_cached<O: 'static + Serialize + DeserializeOwned>(server_fn: impl Fn() -> O) -> O {
|
pub fn server_cached<O: 'static + Serialize + DeserializeOwned>(server_fn: impl Fn() -> O) -> O {
|
||||||
|
|||||||
@@ -255,7 +255,7 @@ fn create_random_element(cx: Scope<DepthProps>) -> Element {
|
|||||||
println!("{template:#?}");
|
println!("{template:#?}");
|
||||||
let node = VNode {
|
let node = VNode {
|
||||||
key: None,
|
key: None,
|
||||||
parent: None,
|
parent: Default::default(),
|
||||||
template: Cell::new(template),
|
template: Cell::new(template),
|
||||||
root_ids: dioxus::core::exports::bumpalo::collections::Vec::new_in(cx.bump())
|
root_ids: dioxus::core::exports::bumpalo::collections::Vec::new_in(cx.bump())
|
||||||
.into(),
|
.into(),
|
||||||
|
|||||||
Reference in new issue
Block a user