Fix stale node references after node removal #338
+194
−0
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Problem
When nodes are removed from the document via
remove_nodeorremove_and_drop_node, several pieces of internal state can retain references to the removed node IDs:hover_node_id- If a node is removed while it's being hovered,hover_node_idstill points to the deleted node IDsnapshots- If a snapshot was created for a node (e.g., during hover state change or attribute modification), the snapshot persists after the node is removedlayout_children- The parent's cached layout children list may still contain the removed node's IDThese stale references cause panics when later operations try to access the deleted nodes:
traversal.rs-node_layout_ancestors()panics with "invalid key" when accessingself.nodes[stale_id]selector_parser.rs- Stylo's style invalidation code panics when processing snapshots for deleted nodesWhen This Happens
This issue is triggered when:
resolve()call, either:set_hover_towhich callsmaybe_node_layout_ancestorswith the stalehover_node_id)resolve()is called (Stylo tries to process the stale snapshot)This is most likely to occur in applications that:
incrementalfeature enabled for style invalidationSolution
Clean up all internal references when nodes are removed. In
process_removed_subtree:layout_childrencache in removal functions:Changes
mutator.rs:remove_node()- Clear parent'slayout_childrencacheremove_and_drop_node()- Clear parent'slayout_childrencacheremove_and_drop_all_children()- Clear parent'slayout_childrencacheprocess_removed_subtree()- Clear hover state and remove snapshots for removed nodesdocument.rs:snapshot_node()- Use emptyVecinstead ofNonefor non-element node attrs (prevents panic in Stylo'sget_attr())Tests
Added three new tests:
removing_hovered_node_clears_hover_state- Verifies hover state is cleared when hovered node is removedremoving_node_clears_snapshot- Verifies snapshots are removed when node is removedstale_layout_children_do_not_panic- Verifies traversal handles stale layout_children gracefullyAll existing tests continue to pass.