DioxusLabs / DioxusLabs/blitz

Stale `paint_children` / hoisted children cause `hit_inner` panic after `remove_and_drop_node`

Open
#624 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
Rust
Stars
4.1k
Forks
203
Avg merge
8h 58m
Merged PRs (30d)
112

Description

# Stale `paint_children` / hoisted children cause `hit_inner` panic after `remove_and_drop_node`

## Problem

`DocumentMutator::remove_and_drop_node` updates `parent.children` (line 516: `retain`), but does not clean up the derived `paint_children` list or `stacking_context` hoisted children lists. These are only rebuilt during the next `resolve()` pass.

If a hit test runs between `remove_and_drop_node` and the next `resolve()`, `Node::hit_inner` iterates these stale lists and calls `self.with(stale_id)`, which does `tree().get(id).unwrap()` and panics.

## Affected call sites

Three places in `hit_inner` (`node.rs`):

| Line | List | Path |
|------|------|------|
| 1271 | `paint_children` | child traversal |
| 1260 | `pos_z_hoisted_children` | positive z-index hoisted children |
| 1283 | `neg_z_hoisted_children` | negative z-index hoisted children |

## Reproduction

Tests in `tests/blitz-tests/tests/hit_test_after_remove_node.rs`:

1. Build a DOM with child elements (with/without z-index)
2. `pump()` to build `paint_children` and hoisted children lists
3. `remove_and_drop_node` on a child (without pumping)
4. `hit()` in the area where the removed child used to be
5. Panic at `self.tree().get(id).unwrap()`

## Root cause

`paint_children` and hoisted children are **derived data** built during `resolve()`. `remove_and_drop_node` updates the DOM tree (`children` / `parent`) but not these derived lists. Between removal and the next `resolve()`, the lists contain stale NodeIds pointing to dropped nodes.

Contributor guide

Open the contributing guide

Research direction

Start with DocumentMutator::remove_and_drop_node and the three stale-list paths in node.rs::hit_inner. Run tests/blitz-tests/tests/hit_test_after_remove_node.rs and reproduce removal followed by hit() without pump(). Done means the affected hit tests no longer panic after removing children, including children with and without z-index.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
frontend, web-dev
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
72/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.