Fix stale node references in projection stack during SPA navigations#3527
Fix stale node references in projection stack during SPA navigations#3527mattgperry wants to merge 1 commit intomainfrom
Conversation
Code ReviewSummaryThis PR provides a minimal, elegant fix for stale DOM node references in the projection stack during SPA navigations. The solution is significantly simpler than the alternative approach in #3516 (15 lines vs 190+ lines) while effectively addressing the core issue. ✅ Strengths
|
cb7cbc6 to
e478c7f
Compare
When elements with layoutId are removed from DOM outside of animateLayout() (e.g. framework SPA navigation), their projection nodes remain in the NodeStack with disconnected instances. On the next animateLayout() call, registerSharedNode → promote() sets resumeFrom to these stale nodes. LayoutAnimationBuilder can't detect this because it only knows about elements present at the start and end of its own call — it has no visibility into removals that happened between calls. Fix by checking isConnected in NodeStack: 1. add(): filter disconnected members and clear stale lead/prevLead 2. promote(): only use prevLead if its instance is still connected https://claude.ai/code/session_019kNt63LG4sBKvk5m87JVUb
e478c7f to
68c0d72
Compare
Summary
This PR fixes issues with stale DOM node references remaining in the projection stack after single-page application (SPA) navigations. When DOM nodes are disconnected but still referenced in the stack, they can cause incorrect shared element transitions and memory leaks.
Closes: #3516
Key Changes
add(): Filter out members with disconnected DOM instances before adding new nodes to the stackprevLeadandleadpointers if they reference nodes that are no longer in the filtered members listprevLeadfor shared element transitions to prevent operations on disconnected DOM nodesImplementation Details
The fix leverages the DOM's
isConnectedproperty to detect when nodes have been removed from the document tree. This is particularly important in SPA scenarios where:The cleanup happens at the entry point (
add()) to ensure the stack remains consistent, and the transition guard prevents any operations on disconnected nodes during the render phase.https://claude.ai/code/session_019kNt63LG4sBKvk5m87JVUb