Fix suspense diffing (#2789)

* Fix suspense placeholders after creating a node
* add nested suspense client side core test
* fix resolve suspense
This commit is contained in:
Evan Almloff authored and GitHub committed 2024-08-06 13:54:58 -07:00
1 parent 0042430a36
commit 37ea8ab906
5 files changed
+605 -23

No files matched your search

+1 -1
View File
@@ -243,7 +243,7 @@ impl Runtime {
// If this is not a suspended scope, and we are under a frozen context, then we should
let scopes = self.scope_states.borrow();
let scope = &scopes[scope_id.0].as_ref().unwrap();
!matches!(scope.suspense_location(), SuspenseLocation::UnderSuspense(suspense) if suspense.has_suspended_tasks())
!matches!(scope.suspense_location(), SuspenseLocation::UnderSuspense(suspense) if suspense.is_suspended())
}
}
+7 -14
View File
@@ -421,7 +421,8 @@ impl SuspenseBoundaryProps {
let suspense_context =
SuspenseContext::downcast_suspense_boundary_from_scope(&dom.runtime, scope_id)
.unwrap();
let suspended = suspense_context.suspended_nodes();
// Take the suspended nodes out of the suspense boundary so the children know that the boundary is not suspended while diffing
let suspended = suspense_context.take_suspended_nodes();
if let Some(node) = suspended {
node.remove_node(&mut *dom, None::<&mut M>, None);
}
@@ -444,10 +445,6 @@ impl SuspenseBoundaryProps {
let props = Self::downcast_from_props(&mut *scope_state.props).unwrap();
props.children = children.clone().node;
scope_state.last_rendered_node = Some(children);
let suspense_context =
SuspenseContext::downcast_suspense_boundary_from_scope(&dom.runtime, scope_id)
.unwrap();
suspense_context.take_suspended_nodes();
})
}
@@ -555,8 +552,11 @@ impl SuspenseBoundaryProps {
suspense_context.set_suspended_nodes(new_children);
un_resolve_suspense(dom, scope_id);
} // We have suspended nodes, but we just got out of suspense. Move the suspended nodes to the foreground
(Some(old_suspended_nodes), false) => {
}
// We have suspended nodes, but we just got out of suspense. Move the suspended nodes to the foreground
(Some(_), false) => {
// Take the suspended nodes out of the suspense boundary so the children know that the boundary is not suspended while diffing
let old_suspended_nodes = suspense_context.take_suspended_nodes().unwrap();
let old_placeholder = last_rendered_node;
let new_children = RenderReturn { node: children };
@@ -579,13 +579,6 @@ impl SuspenseBoundaryProps {
// Set the last rendered node to the new children
dom.scopes[scope_id.0].last_rendered_node = Some(new_children);
let suspense_context = SuspenseContext::downcast_suspense_boundary_from_scope(
&dom.runtime,
scope_id,
)
.unwrap();
suspense_context.take_suspended_nodes();
mark_suspense_resolved(dom, scope_id);
}
}
+5
View File
@@ -148,6 +148,11 @@ impl SuspenseContext {
!self.inner.suspended_tasks.borrow().is_empty()
}
/// Check if the suspense boundary is currently rendered as suspended
pub fn is_suspended(&self) -> bool {
self.inner.suspended_nodes.borrow().is_some()
}
/// Add a suspended task
pub(crate) fn add_suspended_task(&self, task: SuspendedFuture) {
self.inner.suspended_tasks.borrow_mut().push(task);