Skip to content

blitz-dom: a box that turns inline leaves its layout children pointing elsewhere

Generated from repros/blitz-dom-inline-keeps-layout-children/README.md when the site was built at 7aa23e2.

A radio group’s control takes the place of its radio buttons’ area (crates/niso-core/src/controls.rs, area and RadioGroups). When that area is inline labels, niso sizes the anonymous block holding them instead of making the first label a block: undoing that edit would restyle the label back to inline, which hits this bug.

An element with children that a restyle turns from block, inline-block or flow-root to inline keeps a layout_children list of its own while those children are now laid out in the inline root’s flow, whose layout_parent they point at. Debug builds then panic in assert_layout_parents_consistent (resolve.rs:341) on the next resolve, which propagate_damage_flags relies on to reach anonymous boxes. Going the other way, and to or from display: none, is fine.

  • Expected: every layout child points back at the box listing it, no panic.
  • Actual:
a label with children restyled from display: block to inline:
expected: every layout child points back at its box, no panic
actual: debug assertion panicked; NodeId(9v1) is a layout child of NodeId(8v1) but its layout_parent is Some(NodeId(14v3))

(the same for inline-block and flow-root).

Terminal window
CARGO_TARGET_DIR=~/.capy/work/repro-target cargo run

Exit status 1 while the bug reproduces, 0 once fixed. The check walks the layout tree itself, so it reports the inconsistency in release builds too, where the assertion is compiled out.

Not checked. Tested at the pinned be60597f67b3cece0456d26e8d7ff5a88600bbc5; main was at b6ace6a0c33e17b654e8e6d0b14a7e04e83756fe on 2026-11-09.

None searched.

Title: Restyling a box with children to display: inline leaves stale layout_children (debug assertion in resolve)

Body:

let mut doc = HtmlDocument::from_html(r#"<div><p>x</p><label id="l" style="display: block"><input type="radio"> A</label> <label>B</label></div>"#, DocumentConfig::default());
doc.resolve(0.0);
let label = doc.get_element_by_id("l").unwrap();
doc.mutate().set_attribute(label, QualName::new(None, ns!(), LocalName::from("style")), "display: inline");
doc.resolve(0.0); // debug: "layout_parent of NodeId(9v1) does not point at its layout container NodeId(8v1)"

The label is reconstructed with its own layout_children (the radio input), while the inline root that now flows the label’s content lists the input too and sets its layout_parent. An inline box’s content belongs to its inline root, so the label’s list should be cleared when it becomes inline. Tested at be60597.