Skip to content

Build the paint tree in a single post-layout pass - #910

Open
nicoburns wants to merge 2 commits into
devin/1787709349-incremental-paint-attachfrom
devin/1789678486-single-paint-tree-pass
Open

nicoburns wants to merge 2 commits into
devin/1787709349-incremental-paint-attachfrom
devin/1789678486-single-paint-tree-pass

Conversation

@nicoburns

@nicoburns nicoburns commented Sep 17, 2026

Copy link
Copy Markdown
Member

Summary

Stacked on #803 (targets its branch; the diff is the two commits on top). Implements the "single post-layout paint-tree pass" from the #803 review: paint-list construction moves out of flush_styles_to_layout (which now only clears Taffy caches / sorts flex+grid layout_children by order) into one damage-gated build_paint_tree that runs after resolve_layout + resolve_transforms, when Taffy has recorded every hoisted box's oof_containing_block. This replaces the two-writer model (flush builds paint_children/stacking contexts before layout, attach_hoisted_children patches them after) and deletes attach_hoisted_children, innermost_paint_effect_ancestor, is_before_in_tree_order, the oof_containing_blocks registry and Node::containing_block_claims.

Ownership rule (browser-style: paint owner follows DOM stacking-context ancestry, geometry follows the containing-block chain via the existing use-time hoisted_child_position):

for child in node.layout_children (DFS, tree order):
  z-indexed (positioned, or any flex/grid item) ─▶ nearest DOM ancestor stacking context   (unchanged; now also for OOF boxes)
  in-flow / OOF with containing_block == node   ─▶ node.paint_children
  OOF z:auto with containing_block above node   ─▶ bubbles up; claimed by the first of:
        • its containing block  → spliced into that node's paint_children right after the
                                  child it bubbled out of (stable (level, order) sort keeps tree order)
        • a stacking-context root → z:0 entry of that SC (negated-walk offset, as #803's effect_attached)

Incremental mode skips clean subtrees exactly as #803's flush did, replaying sc_contribution_cache plus a new Node::oof_bubble_cache (the boxes that bubbled out of the subtree; their CB is re-read live from oof_containing_block, so a CB change above the clean subtree is picked up without invalidating it). Both the DOM parent and the CB of a hoisted box are DOM ancestors of it, so any change to where it hoists dirties every node whose lists it can appear in.

Behaviour changes vs #803 (all verified against Chrome with pixel probes, now committed as tests/blitz-tests/tests/oof_paint_ownership.rs):

  • position:fixed inside a z-index ancestor paints inside that ancestor's stacking context instead of escaping to the root (was a regression vs main).
  • z-indexed abspos/fixed inside opacity (or any SC) stays in that SC instead of escaping to the CB's SC.
  • z-indexed position:fixed no longer scrolls with the document: stacking-context entries now get the same viewport-scroll compensation as paint_children (Node::fixed_child_scroll_compensation, threaded through hit_inner too). The compensation is applied only when the CB is the root: a fixed box inside a transformed scroller scrolls with it (matches Chrome; previously pinned).
  • Opacity/filter layers extend effect_layer_clip by the SC's content_area, so hoisted entries outside the border box are painted (previously clipped away in both main and Make paint-placement maintenance incremental (O(damage), not O(tree)) #803).
  • build_paint_tree runs after resolve_transforms, so a transform gained this frame makes the node an SC root this frame rather than next.
  • (2nd commit) Hoisted stacking-context entries are drawn outside the node's overflow clip layer, and the clip is pushed around each entry only when the node is on its containing-block chain (Node::clips_hoisted_child). A box captured by an SC root below its CB (e.g. fixed inside a position:fixed; overflow:auto scroller) is therefore no longer clipped/scrolled by that root. Clip-only layers are cheap in vello; this adds at most one per hoisted entry of a clipping SC root. Side effect: negative-z entries now paint before the node's own inline content/images (Appendix E step 3 before 4), previously after.
  • (2nd commit) Node::order() returns 0 for out-of-flow children: order only applies to flex/grid items, and sorting layout_children by it changed the paint order of abspos children of a flex container.

Not changed (pre-existing, out of scope): Appendix E step‑8 interleaving of z:auto positioned descendants across nesting levels, z-indexed descendants escaping a non-SC overflow:hidden ancestor, and general per-item clip chains (only the owning SC root's clip is skipped here, not clips of intermediate non-CB ancestors).

Testing

WPT results

Subtests: 1982 newly passing, 42 newly failing (net +1940). Timeouts: +1.

Full diff (243 changed tests)
+ FAIL => PASS         [1/1]    +1  css/CSS2/abspos/adjacent-to-relpos-inline-in-inline-that-had-block.html
+ FAIL => PASS         [1/1]    +1  css/CSS2/abspos/adjacent-to-relpos-inline-that-had-block.html
+ FAIL => PASS         [1/1]    +1  css/CSS2/abspos/static-inside-inline-002.html
+ FAIL => PASS         [1/1]    +1  css/CSS2/backgrounds/background-bg-pos-204.xht
- PASS => FAIL         [0/1]    -1  css/CSS2/backgrounds/background-position-002.xht
+ FAIL => PASS         [1/1]    +1  css/CSS2/backgrounds/background-root-023.xht
+ FAIL => PASS         [1/1]    +1  css/CSS2/box-display/containing-block-007.xht
+ FAIL => PASS         [1/1]    +1  css/CSS2/box-display/containing-block-008.xht
+ FAIL => PASS         [1/1]    +1  css/CSS2/box-display/containing-block-009.xht
+ FAIL => PASS         [1/1]    +1  css/CSS2/box-display/containing-block-010.xht
+ FAIL => PASS         [1/1]    +1  css/CSS2/floats-clear/clear-applies-to-012.xht
+ FAIL => PASS         [1/1]    +1  css/CSS2/floats-clear/clear-applies-to-014.xht
+ FAIL => PASS         [1/1]    +1  css/CSS2/floats-clear/clear-clearance-calculation-004.xht
+ FAIL => PASS         [1/1]    +1  css/CSS2/floats-clear/clear-clearance-calculation-005.xht
+ FAIL => PASS         [1/1]    +1  css/CSS2/floats-clear/floats-019.xht
+ FAIL => PASS         [1/1]    +1  css/CSS2/generated-content/before-after-positioned-002.html
+ FAIL => PASS         [1/1]    +1  css/CSS2/generated-content/before-after-positioned-003.html
+ FAIL => PASS         [1/1]    +1  css/CSS2/generated-content/content-white-space-003.xht
+ FAIL => PASS         [1/1]    +1  css/CSS2/generated-content/content-white-space-004.xht
+ FAIL => PASS         [1/1]    +1  css/CSS2/margin-padding-clear/margin-collapse-037.xht
+ FAIL => PASS         [1/1]    +1  css/CSS2/margin-padding-clear/padding-percentage-inherit-001.xht
+ FAIL => PASS         [1/1]    +1  css/CSS2/positioning/absolute-non-replaced-width-026.xht
+ FAIL => PASS         [1/1]    +1  css/CSS2/positioning/abspos-015.xht
+ FAIL => PASS         [1/1]    +1  css/CSS2/positioning/abspos-017.xht
+ FAIL => PASS         [1/1]    +1  css/CSS2/positioning/abspos-026.xht
+ FAIL => PASS         [1/1]    +1  css/CSS2/positioning/abspos-containing-block-005.xht
+ FAIL => PASS         [1/1]    +1  css/CSS2/positioning/abspos-containing-block-006.xht
+ FAIL => PASS         [1/1]    +1  css/CSS2/positioning/abspos-overflow-001.xht
+ FAIL => PASS         [1/1]    +1  css/CSS2/positioning/abspos-overflow-002.xht
+ FAIL => PASS         [1/1]    +1  css/CSS2/positioning/abspos-overflow-003.xht
+ FAIL => PASS         [1/1]    +1  css/CSS2/positioning/abspos-overflow-004.xht
+ FAIL => PASS         [1/1]    +1  css/CSS2/positioning/abspos-overflow-005.xht
+ FAIL => PASS         [1/1]    +1  css/CSS2/positioning/abspos-overflow-006.xht
+ FAIL => PASS         [1/1]    +1  css/CSS2/positioning/abspos-overflow-007.xht
+ FAIL => PASS         [1/1]    +1  css/CSS2/positioning/abspos-overflow-008.xht
+ FAIL => PASS         [1/1]    +1  css/CSS2/positioning/abspos-overflow-009.xht
+ FAIL => PASS         [1/1]    +1  css/CSS2/positioning/abspos-overflow-012.xht
+ FAIL => PASS         [1/1]    +1  css/CSS2/positioning/dynamic-top-change-002.xht
+ FAIL => PASS         [1/1]    +1  css/CSS2/positioning/dynamic-top-change-003.xht
+ FAIL => PASS         [1/1]    +1  css/CSS2/positioning/dynamic-top-change-004.xht
+ FAIL => PASS         [1/1]    +1  css/CSS2/positioning/left-applies-to-009.xht
+ FAIL => PASS         [1/1]    +1  css/CSS2/positioning/left-applies-to-012.xht
+ FAIL => PASS         [1/1]    +1  css/CSS2/positioning/left-applies-to-013.xht
+ FAIL => PASS         [1/1]    +1  css/CSS2/positioning/left-applies-to-014.xht
+ FAIL => PASS         [1/1]    +1  css/CSS2/positioning/position-fixed-007.xht
- PASS => FAIL         [0/1]    -1  css/CSS2/positioning/position-relative-016.xht
+ FAIL => PASS         [1/1]    +1  css/CSS2/positioning/right-applies-to-009.xht
+ FAIL => PASS         [1/1]    +1  css/CSS2/positioning/right-applies-to-012.xht
+ FAIL => PASS         [1/1]    +1  css/CSS2/positioning/right-applies-to-013.xht
+ FAIL => PASS         [1/1]    +1  css/CSS2/positioning/right-applies-to-014.xht
+ FAIL => PASS         [1/1]    +1  css/CSS2/positioning/top-applies-to-009.xht
+ FAIL => PASS         [1/1]    +1  css/CSS2/positioning/top-applies-to-012.xht
+ FAIL => PASS         [1/1]    +1  css/CSS2/positioning/top-applies-to-013.xht
+ FAIL => PASS         [1/1]    +1  css/CSS2/positioning/top-applies-to-014.xht
+ FAIL => PASS         [1/1]    +1  css/CSS2/tables/separated-border-model-007.xht
+ FAIL => PASS         [1/1]    +1  css/CSS2/tables/separated-border-model-008.xht
+ FAIL => PASS         [1/1]    +1  css/CSS2/tables/separated-border-model-009.xht
+ FAIL => PASS         [1/1]    +1  css/CSS2/visuren/anonymous-boxes-001b.xht
+ FAIL => PASS         [1/1]    +1  css/CSS2/visuren/position-absolute-percentage-inherit-001.xht
+ FAIL => PASS         [1/1]    +1  css/css-align/abspos/align-self-with-flex-grid-parent.html
- PASS => FAIL         [0/1]    -1  css/css-anchor-position/anchor-abspos-to-fixedpos-002.html
- PASS => FAIL         [0/1]    -1  css/css-anchor-position/anchor-abspos-to-fixedpos-003.html
+ FAIL => FAIL       [33/39]   +32  css/css-anchor-position/anchor-invalid-fallback.html
- PASS => FAIL         [0/1]    -1  css/css-anchor-position/anchor-position-dynamic-005.html
+ FAIL => FAIL         [3/5]    +3  css/css-anchor-position/anchor-scope-shadow-names.html
- PASS => FAIL         [0/1]    -1  css/css-anchor-position/anchor-scroll-fixedpos-003.html
! FAIL => TIMEOUT      [0/1]    +0  css/css-anchor-position/anchor-transition-focus.html
- PASS => FAIL         [0/1]    -1  css/css-anchor-position/position-visibility-anchor-visible.html
- PASS => FAIL         [0/1]    -1  css/css-anchor-position/position-visibility-anchors-visible-in-overflow.html
- PASS => FAIL         [0/1]    -1  css/css-anchor-position/position-visibility-anchors-visible-position-fixed.html
- PASS => FAIL         [0/1]    -1  css/css-anchor-position/position-visibility-anchors-visible.html
- PASS => FAIL         [0/1]    -1  css/css-anchor-position/position-visibility-initial.html
+ FAIL => PASS         [1/1]    +1  css/css-anchor-position/sticky-anchor-position-invalid.html
+ FAIL => PASS         [1/1]    +1  css/css-animations/translation-animation-subpixel-offset.html
+ FAIL => PASS         [1/1]    +1  css/css-backgrounds/background-origin-006.html
+ FAIL => PASS         [1/1]    +1  css/css-backgrounds/background-rounded-image-clip-001.html
+ FAIL => PASS         [1/1]    +1  css/css-backgrounds/background-size-percentage-root.html
+ FAIL => PASS         [1/1]    +1  css/css-backgrounds/box-shadow/slice-inline-fragmentation-002.html
+ FAIL => PASS         [1/1]    +1  css/css-break/abspos-in-opacity-000.html
- PASS => FAIL         [0/1]    -1  css/css-break/grid/grid-item-oof-012.html
+ FAIL => PASS         [1/1]    +1  css/css-break/out-of-flow-in-multicolumn-091.html
+ FAIL => PASS         [1/1]    +1  css/css-break/out-of-flow-in-multicolumn-092.html
+ FAIL => PASS         [1/1]    +1  css/css-color/t422-rgba-values-meaning-b.xht
+ FAIL => PASS         [1/1]    +1  css/css-conditional/container-queries/no-layout-containment-abspos.html
+ FAIL => PASS         [1/1]    +1  css/css-conditional/container-queries/no-layout-containment-fixedpos.html
- PASS => FAIL         [0/1]    -1  css/css-contain/contain-layout-020.html
- PASS => FAIL         [0/1]    -1  css/css-contain/contain-layout-021.html
+ FAIL => FAIL         [2/4]    +2  css/css-contain/contain-layout-dynamic-001.html
- PASS => FAIL         [0/1]    -1  css/css-contain/contain-layout-ignored-cases-ib-split-001.html
+ FAIL => PASS         [4/4]    +2  css/css-contain/contain-paint-dynamic-001.html
- PASS => FAIL         [0/1]    -1  css/css-contain/contain-paint-ignored-cases-ib-split-001.html
- PASS => FAIL         [0/1]    -1  css/css-contain/content-visibility/content-visibility-092.html
- PASS => FAIL         [0/1]    -1  css/css-contain/content-visibility/content-visibility-093.html
- PASS => FAIL         [0/1]    -1  css/css-contain/content-visibility/content-visibility-095.html
- PASS => FAIL         [0/1]    -1  css/css-contain/content-visibility/content-visibility-hidden-boundingbox-query.html
- FAIL => FAIL         [3/8]    -2  css/css-contain/content-visibility/content-visibility-layout-paint-containment-001.html
+ FAIL => PASS       [18/18]    +2  css/css-flexbox/abspos/position-absolute-002.html
+ FAIL => PASS         [1/1]    +1  css/css-flexbox/flexbox_margin-left-ex.html
+ FAIL => PASS         [1/1]    +1  css/css-flexbox/order/order-abs-children-painting-order.html
- PASS => FAIL         [0/1]    -1  css/css-flexbox/table-as-item-large-intrinsic-size.html
+ FAIL => PASS       [10/10]    +2  css/css-grid/abspos/absolute-positioning-grid-container-containing-block-001.html
+ FAIL => PASS       [12/12]    +6  css/css-grid/abspos/absolute-positioning-grid-container-parent-001.html
+ FAIL => PASS         [1/1]    +1  css/css-grid/abspos/grid-abspos-staticpos-align-items-center-large-border-padding.html
+ FAIL => PASS         [1/1]    +1  css/css-grid/abspos/grid-abspos-staticpos-align-items-end-large-border-padding.html
+ FAIL => PASS         [1/1]    +1  css/css-grid/abspos/grid-abspos-staticpos-align-items-flex-end-large-border-padding.html
+ FAIL => PASS         [1/1]    +1  css/css-grid/abspos/grid-abspos-staticpos-align-items-self-end-large-border-padding.html
+ FAIL => PASS         [1/1]    +1  css/css-grid/abspos/grid-abspos-staticpos-align-self-002.html
+ FAIL => PASS         [1/1]    +1  css/css-grid/abspos/grid-abspos-staticpos-align-self-center-large-border-padding.html
+ FAIL => PASS         [1/1]    +1  css/css-grid/abspos/grid-abspos-staticpos-align-self-end-large-border-padding.html
+ FAIL => PASS         [1/1]    +1  css/css-grid/abspos/grid-abspos-staticpos-align-self-flex-end-large-border-padding.html
+ FAIL => PASS         [1/1]    +1  css/css-grid/abspos/grid-abspos-staticpos-align-self-last-baseline-002.html
+ FAIL => PASS         [1/1]    +1  css/css-grid/abspos/grid-abspos-staticpos-align-self-rtl-003.html
+ FAIL => PASS         [1/1]    +1  css/css-grid/abspos/grid-abspos-staticpos-align-self-rtl-004.html
+ FAIL => PASS         [1/1]    +1  css/css-grid/abspos/grid-abspos-staticpos-align-self-rtl-last-baseline-003.html
+ FAIL => PASS         [1/1]    +1  css/css-grid/abspos/grid-abspos-staticpos-align-self-rtl-last-baseline-004.html
- PASS => FAIL         [0/1]    -1  css/css-grid/abspos/grid-abspos-staticpos-align-self-safe-outer-cb-003.tentative.html
+ FAIL => PASS         [1/1]    +1  css/css-grid/abspos/grid-abspos-staticpos-align-self-self-end-large-border-padding.html
+ FAIL => PASS         [1/1]    +1  css/css-grid/abspos/grid-abspos-staticpos-justify-self-002.html
+ FAIL => PASS         [1/1]    +1  css/css-grid/abspos/grid-abspos-staticpos-justify-self-img-last-baseline-002.html
+ FAIL => PASS         [1/1]    +1  css/css-grid/abspos/grid-abspos-staticpos-justify-self-last-baseline-002.html
+ FAIL => PASS         [1/1]    +1  css/css-grid/abspos/grid-abspos-staticpos-justify-self-rtl-003.html
+ FAIL => PASS         [1/1]    +1  css/css-grid/abspos/grid-abspos-staticpos-justify-self-rtl-last-baseline-003.html
+ FAIL => PASS         [1/1]    +1  css/css-grid/abspos/grid-abspos-staticpos-justify-self-rtl-last-baseline-004.html
+ FAIL => PASS         [1/1]    +1  css/css-grid/abspos/grid-fixedpos-static-position-not-containing-block.html
+ FAIL => PASS         [1/1]    +1  css/css-grid/abspos/grid-positioned-item-dynamic-change-002.html
+ FAIL => PASS     [100/100]  +100  css/css-grid/abspos/orthogonal-positioned-grid-descendants-016.html
+ FAIL => PASS         [1/1]    +1  css/css-grid/abspos/positioned-grid-descendant-containing-block-004.html
+ FAIL => PASS         [1/1]    +1  css/css-grid/abspos/positioned-grid-descendant-containing-block-006.html
+ FAIL => PASS         [1/1]    +1  css/css-grid/abspos/positioned-grid-descendant-containing-block-007.html
+ FAIL => PASS         [1/1]    +1  css/css-grid/abspos/positioned-grid-descendant-containing-block-008.html
+ FAIL => PASS         [1/1]    +1  css/css-grid/abspos/positioned-grid-descendant-containing-block-012.html
+ FAIL => PASS         [1/1]    +1  css/css-grid/abspos/positioned-grid-descendant-containing-block-014.html
+ FAIL => PASS         [1/1]    +1  css/css-grid/abspos/positioned-grid-descendant-containing-block-015.html
+ FAIL => PASS         [1/1]    +1  css/css-grid/abspos/positioned-grid-descendant-containing-block-016.html
+ FAIL => PASS     [100/100]  +100  css/css-grid/abspos/positioned-grid-descendants-002.html
+ FAIL => PASS     [100/100]  +100  css/css-grid/abspos/positioned-grid-descendants-004.html
+ FAIL => PASS     [100/100]  +100  css/css-grid/abspos/positioned-grid-descendants-006.html
+ FAIL => PASS     [100/100]  +100  css/css-grid/abspos/positioned-grid-descendants-007.html
+ FAIL => PASS     [100/100]  +100  css/css-grid/abspos/positioned-grid-descendants-008.html
+ FAIL => PASS     [100/100]  +100  css/css-grid/abspos/positioned-grid-descendants-009.html
+ FAIL => PASS     [100/100]  +100  css/css-grid/abspos/positioned-grid-descendants-011.html
+ FAIL => PASS     [100/100]  +100  css/css-grid/abspos/positioned-grid-descendants-012.html
+ FAIL => PASS     [100/100]  +100  css/css-grid/abspos/positioned-grid-descendants-013.html
+ FAIL => PASS     [100/100]  +100  css/css-grid/abspos/positioned-grid-descendants-014.html
+ FAIL => PASS     [100/100]  +100  css/css-grid/abspos/positioned-grid-descendants-015.html
+ FAIL => PASS     [100/100]  +100  css/css-grid/abspos/positioned-grid-descendants-016.html
+ FAIL => PASS         [1/1]    +1  css/css-grid/abspos/positioned-grid-descendants-017.html
+ FAIL => PASS         [1/1]    +1  css/css-grid/abspos/positioned-grid-items-019.html
+ FAIL => PASS         [1/1]    +1  css/css-grid/abspos/positioned-grid-items-024.html
+ FAIL => PASS       [12/12]    +4  css/css-grid/abspos/positioned-grid-items-should-not-take-up-space-001.html
+ FAIL => FAIL         [2/4]    +2  css/css-grid/alignment/grid-self-alignment-non-static-positioned-items-002.html
+ FAIL => FAIL         [2/4]    +2  css/css-grid/alignment/grid-self-alignment-positioned-items-with-margin-border-padding-001.html
+ FAIL => FAIL         [2/4]    +2  css/css-grid/alignment/grid-self-alignment-positioned-items-with-margin-border-padding-012.html
+ FAIL => PASS         [1/1]    +1  css/css-grid/grid-items/grid-items-percentage-paddings-015.html
- PASS => FAIL         [0/1]    -1  css/css-grid/grid-items/grid-items-relative-positioned-containing-block-003.html
+ FAIL => PASS         [1/1]    +1  css/css-grid/grid-lanes/subgrid/grid-subgridded-to-grid-lanes/column-subgrid-abs-pos-001.html
+ FAIL => PASS         [1/1]    +1  css/css-grid/subgrid/abs-pos-001.html
- PASS => FAIL         [0/1]    -1  css/css-images/image-orientation/image-orientation-img-object-fit.html
- PASS => FAIL         [0/1]    -1  css/css-inline/empty-span-scroll.html
- PASS => FAIL         [0/1]    -1  css/css-masking/clip/clip-fixed-pos-transform-descendant-001.html
+ FAIL => PASS         [1/1]    +1  css/css-multicol/multicol-contained-absolute.html
+ FAIL => PASS         [1/1]    +1  css/css-multicol/multicol-oof-inline-cb-001.html
+ FAIL => PASS         [1/1]    +1  css/css-multicol/multicol-span-all-fieldset-001.html
+ FAIL => PASS         [1/1]    +1  css/css-multicol/multicol-span-all-fieldset-002.html
+ FAIL => PASS         [1/1]    +1  css/css-multicol/multicol-span-all-fieldset-003.html
- PASS => FAIL         [0/1]    -1  css/css-overflow/overflow-outside-padding.html
- PASS => FAIL         [0/1]    -1  css/css-overflow/scroll-markers/scroll-target-group-012.html
+ FAIL => PASS         [1/1]    +1  css/css-overflow/scrollable-overflow-fixed-positioned-initial-containing-block.html
+ FAIL => PASS         [6/6]    +1  css/css-overflow/scrollable-overflow-from-grid-container-contents.html
+ FAIL => PASS         [1/1]    +1  css/css-page/fixedpos-005-print.html
+ FAIL => PASS         [1/1]    +1  css/css-page/fixedpos-007-print.html
+ FAIL => PASS         [1/1]    +1  css/css-page/fixedpos-008-print.html
+ FAIL => PASS         [1/1]    +1  css/css-position/absolute-pos-box-inside-fixed-pos-box-with-changing-height.html
+ FAIL => PASS         [1/1]    +1  css/css-position/hypothetical-box-scroll-parent.html
+ FAIL => PASS         [1/1]    +1  css/css-position/hypothetical-dynamic-change-003.html
- PASS => FAIL         [0/1]    -1  css/css-position/nested-inline-abspos-child-with-siblings.html
- PASS => FAIL         [0/1]    -1  css/css-position/nested-inline-abspos-child.html
+ FAIL => PASS         [1/1]    +1  css/css-position/overlay/author-overlay-top-layer-removal.html
+ FAIL => PASS         [1/1]    +1  css/css-position/position-absolute-center-003.html
+ FAIL => PASS         [1/1]    +1  css/css-position/position-absolute-center-004.html
+ FAIL => PASS         [8/8]    +8  css/css-position/position-absolute-dynamic-containing-block.html
+ FAIL => PASS         [1/1]    +1  css/css-position/position-fixed-dynamic-transformed-sibling.html
+ FAIL => PASS         [1/1]    +1  css/css-position/position-fixed-overflow-print.html
+ FAIL => PASS         [1/1]    +1  css/css-position/sticky/position-sticky-escape-scroller-001.html
+ FAIL => PASS         [1/1]    +1  css/css-position/sticky/position-sticky-escape-scroller-003.html
- PASS => FAIL         [0/1]    -1  css/css-position/sticky/position-sticky-escape-scroller-004.html
- FAIL => FAIL         [0/3]    -1  css/css-position/sticky/position-sticky-get-bounding-client-rect.html
+ FAIL => PASS         [1/1]    +1  css/css-position/sticky/position-sticky-left-004.html
+ FAIL => PASS         [1/1]    +1  css/css-position/sticky/position-sticky-left-005.html
+ FAIL => PASS         [1/1]    +1  css/css-position/sticky/position-sticky-left-006.html
+ FAIL => FAIL         [1/3]    +1  css/css-position/sticky/position-sticky-margins.html
+ FAIL => FAIL         [2/5]    +2  css/css-position/sticky/position-sticky-nested-bottom.html
+ FAIL => FAIL         [1/5]    +1  css/css-position/sticky/position-sticky-nested-left.html
+ FAIL => FAIL         [2/5]    +2  css/css-position/sticky/position-sticky-nested-right.html
+ FAIL => FAIL         [1/5]    +1  css/css-position/sticky/position-sticky-nested-top.html
+ FAIL => FAIL         [2/3]    +1  css/css-position/sticky/position-sticky-overflow-padding.html
+ FAIL => FAIL         [1/3]    +1  css/css-position/sticky/position-sticky-right.html
+ FAIL => PASS         [1/1]    +1  css/css-position/sticky/position-sticky-scroll-reposition.html
- PASS => FAIL         [0/1]    -1  css/css-position/sticky/position-sticky-stacking-context-002.html
+ FAIL => PASS         [1/1]    +1  css/css-position/sticky/position-sticky-stacking-context.html
+ FAIL => PASS         [1/1]    +1  css/css-position/sticky/position-sticky-top-004.html
+ FAIL => PASS         [1/1]    +1  css/css-position/sticky/position-sticky-top-005.html
+ FAIL => PASS         [1/1]    +1  css/css-position/sticky/position-sticky-top-006.html
- PASS => FAIL         [0/1]    -1  css/css-pseudo/first-letter-width-2.html
+ FAIL => FAIL       [36/46]    +8  css/css-sizing/stretch/stretch-alias-block-size-001.tentative.html
+ FAIL => FAIL       [36/46]    +8  css/css-sizing/stretch/stretch-alias-inline-size-001.tentative.html
+ FAIL => FAIL       [36/46]    +8  css/css-sizing/stretch/stretch-block-size-001.html
+ FAIL => FAIL        [4/36]    +4  css/css-sizing/stretch/stretch-block-size-002.html
+ FAIL => FAIL       [36/46]    +8  css/css-sizing/stretch/stretch-inline-size-001.html
+ FAIL => FAIL        [4/36]    +4  css/css-sizing/stretch/stretch-inline-size-002.html
+ FAIL => PASS         [1/1]    +1  css/css-tables/absolute-tables-010.tentative.html
+ FAIL => PASS         [1/1]    +1  css/css-text-decor/text-shadow/text-shadow-emoji-transparent.html
+ FAIL => FAIL        [5/20]    +5  css/css-transforms/3d-point-mapping-preserve-3d.html
- PASS => FAIL         [0/1]    -1  css/css-transforms/backface-visibility-hidden-animated-001.html
- PASS => FAIL         [0/1]    -1  css/css-transforms/backface-visibility-hidden-animated-002.html
+ FAIL => PASS         [1/1]    +1  css/css-transforms/perspective-containing-block-dynamic-1a.html
+ FAIL => PASS         [1/1]    +1  css/css-transforms/preserve-3d-flat-grouping-properties-containing-block-inline.tentative.html
+ FAIL => PASS         [1/1]    +1  css/css-transforms/transform-containing-block-dynamic-1a.html
+ FAIL => PASS         [1/1]    +1  css/css-transforms/ttwf-transform-translatex-001.html
+ FAIL => PASS         [1/1]    +1  css/css-transforms/ttwf-transform-translatey-001.html
- PASS => FAIL         [0/1]    -1  css/css-viewport/zoom/animation-range.html
+ FAIL => PASS         [1/1]    +1  css/css-will-change/will-change-fixedpos-cb-003.html
+ FAIL => PASS         [1/1]    +1  css/css-will-change/will-change-fixedpos-cb-006.html
+ FAIL => PASS         [1/1]    +1  css/css-will-change/will-change-fixpos-cb-height-1.html
+ FAIL => PASS         [1/1]    +1  css/css-will-change/will-change-fixpos-cb-position-1.html
+ FAIL => PASS         [1/1]    +1  css/css-writing-modes/dynamic-offset-rtl-001.html
+ FAIL => PASS         [1/1]    +1  css/css-writing-modes/dynamic-offset-rtl-002.html
+ FAIL => PASS         [1/1]    +1  css/css-writing-modes/dynamic-offset-vrl-001.html
+ FAIL => PASS         [1/1]    +1  css/css-writing-modes/dynamic-offset-vrl-rtl-001.html
+ FAIL => PASS         [1/1]    +1  css/css-writing-modes/float-rgt-orthog-htb-in-vrl-003.xht
+ FAIL => PASS         [2/2]    +1  css/cssom-view/CaretPosition-001.html
+ FAIL => FAIL       [15/16]    +5  css/cssom-view/elementFromPosition.html
+ FAIL => FAIL         [4/6]    +2  css/cssom-view/getBoundingClientRect-scroll.html
+ FAIL => PASS         [1/1]    +1  css/cssom-view/getClientRects-inline.html
+ FAIL => FAIL     [306/324]  +198  css/cssom/getComputedStyle-insets-absolute.html
+ FAIL => FAIL     [306/324]  +198  css/cssom/getComputedStyle-insets-fixed.html
- PASS => FAIL         [0/1]    -1  css/filter-effects/backdrop-filter-clip-rect-zoom.html
- PASS => FAIL         [0/1]    -1  css/filter-effects/backdrop-filter-plus-mask-large.html
+ FAIL => PASS         [1/1]    +1  css/filter-effects/filter-cb-dynamic-1a.html
- PASS => FAIL         [0/1]    -1  css/filter-effects/filtered-inline-is-container.html
+ FAIL => PASS         [1/1]    +1  svg/painting/subpixel-clip-path-transform.html
+ FAIL => PASS         [1/1]    +1  svg/painting/text-clip-path-transform.html
+ FAIL => PASS         [1/1]    +1  svg/painting/text-mask-transform.html

Generated by the WPT workflow.

Link to Devin session: https://dioxus.staging.devinenterprise.com/sessions/42a17ab185fd42b8bb6c11ce389518f5
Open in Devin Desktop: https://dioxus.staging.devinenterprise.com/desktop/session/42a17ab185fd42b8bb6c11ce389518f5?variant=devin-insiders
Requested by: @nicoburns

Paint-tree construction (paint_children + stacking contexts) moves out of
flush_styles_to_layout into build_paint_tree, which runs after layout and
transforms when Taffy has recorded every hoisted box's containing block.
This replaces the two-writer model (flush builds, attach_hoisted_children
patches) with one damage-gated pass.

Paint ownership now follows DOM stacking-context ancestry, with geometry
still derived from the containing-block chain at use-time:
- z-indexed boxes (in-flow or out-of-flow) go to the nearest DOM ancestor
  stacking context;
- z-index:auto out-of-flow boxes bubble up from their DOM parent and are
  claimed either by their containing block (spliced into its paint_children
  in tree order) or by an intervening stacking context root (as a z:0 entry
  with a compensating offset).

Clean subtrees are skipped in incremental mode: their stacking-context
contributions (sc_contribution_cache) and the boxes bubbling out of them
(new oof_bubble_cache) are replayed.

Removes attach_hoisted_children, innermost_paint_effect_ancestor,
is_before_in_tree_order, oof_containing_blocks and containing_block_claims.

Also:
- fixed-position entries of a stacking context get the same viewport-scroll
  compensation as fixed paint_children (they previously scrolled with the
  document), and the compensation is now only applied when the containing
  block is the root (a fixed box inside a transformed scroller scrolls with
  it, matching browsers);
- opacity/filter layers extend their clip to the stacking context's
  content_area so hoisted entries outside the border box are not lost.
@staging-devin-ai-integration

Copy link
Copy Markdown
Contributor

I'll fix CI failures and address comments from users with write access that start with 'DevinAI' or '@devin'.

  • Disable automatic comment, CI, and merge conflict monitoring

A stacking context root that paints a box whose containing block lies
above it must not clip it with its own overflow clip: draw hoisted
entries outside the clip layer and push the clip around each entry only
when the node is on its containing-block chain. Also stop applying flex
`order` to out-of-flow children (they are not items), which changed
their paint order.

Fixes WPT css/css-position/position-fixed-scroll-nested-fixed and
css/css-flexbox/flexbox-paint-ordering-003.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant