Integrate Taffy out-of-flow hoisting support - #805
Open
nicoburns wants to merge 8 commits into
Open
Conversation
Contributor
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
staging-devin-ai-integration
Bot
force-pushed
the
devin/1787748926-taffy-oof-hoisting-latebound
branch
3 times, most recently
from
August 26, 2026 13:43
9c79ae6 to
4f6fbef
Compare
…ize) passes Guard inline child taffy layout writes behind RunMode::PerformLayout, snapshot/restore the Parley layout around measure passes, and only run the out-of-flow positioning pass on PerformLayout passes.
Update the taffy pin to the current stack-top rev (grid-area edge-case fixes and cache-invalidation tests). Hoisted out-of-flow boxes were appended to the end of their containing block's paint_children, painting them above every in-flow sibling. Insert them at their (paint level, tree order) position instead, so z-index:auto positioned boxes paint in tree order among positioned siblings (CSS 2.1 Appendix E step 8). Fixes grid-items-relative-positioned-containing-block-004/005/006.
staging-devin-ai-integration
Bot
force-pushed
the
devin/1787748926-taffy-oof-hoisting-latebound
branch
from
August 29, 2026 13:24
4f6fbef to
89c20f9
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Summary
Integrates Taffy's browser-style out-of-flow (OOF) hoisting (dispatcher-owned pass) into Blitz. Depends on the Taffy PR stack (DioxusLabs/taffy stack #1173: DioxusLabs/taffy#1140 / DioxusLabs/taffy#1170 / DioxusLabs/taffy#1171 / DioxusLabs/taffy#1172) landing first — the
taffydependency is pinned torev = "4da30115"(stack top, includes the late-bound static-position representation, grid-area edge-case fixes and cache-invalidation tests).This PR replaces #763 (closed; branch preserved as
backup/taffy-oof-hoisting-prelatebound). The only change is the taffy pin bump to the late-bound stack: Blitz's inline emitter already usesStaticPosition::from_edge, which maps unchanged onto the new area+alignment representation.Key changes:
stylo_taffy::convert::position):static → Position::Static,fixed → Position::Fixed(previouslyRelative/Absolute).blitz-dom/layout/mod.rs): per-nodehoisted_childrenstorage viaset_hoisted_children/add_hoisted_children;RoundTree::{is_hoisted, hoisted_child_count, get_hoisted_child_id};LayoutContainingBlockimpl (get_oof_item_style,get_detailed_layout_info);compute_oof_layoutruns in thecompute_cached_layoutcache-miss closures (normal + block dispatch), onPerformLayoutpasses only; forwarded throughTableTreeWrapper.oof_claims: positioned elements claim absolute candidates; elements establishing a fixed containing block (transform/translate/rotate/scale/perspective,filter/backdrop-filter,will-change: transform/perspective+ fixpos bits,contain: layout/paint,container-type != normal) claim both (Node::establishes_fixed_containing_block).layout/inline.rs): the locallayout_abspos_childroutine is removed; inline layout now emitsOofCandidates (with hypothetical-box static positions, RTL-aware inline-level edges) and anOofPositioningArea, bubbling candidates from float/inline-block subtrees. Measure (ComputeSize) passes no longer mutate persistent state: child Taffy layouts are only written onPerformLayout, and the Parley layout is snapshotted/restored around measure passes (fixes a pre-existing cache-clobber bug where a hover restyle could leave measure-time line breaks in painted output — reproduced on GitHub's repo page; regression test intests/blitz-tests/tests/measure_clobber.rs).ElementData.detailed_grid_info: Option<Box<DetailedGridInfo>>→detailed_layout_info: DetailedLayoutInfo, needed for grid-area-based OOF positioning of non-direct grid descendants.Layout.locationis now relative to its containing block's border box, a post-layout pass (BaseDocument::attach_hoisted_children) repoints each hoisted box'slayout_parentat its CB (soabsolute_position,offsetLeft/Topetc. accumulate through the CB chain) and splices hoisted boxes into the CB'spaint_childrenat their (paint level, tree order) position per CSS 2.1 Appendix E step 8 (z-indexed hoisted boxes are instead pushed into the nearest ancestor stacking context, matching the existing z-index hoisting inflush_styles_to_layout; boxes with an intermediate atomic paint-effect ancestor — opacity/filter/clip-path/mask — are painted inside that ancestor's effect layers with a compensated offset). OOF boxes remain in their DOM parent's paint list when the parent is itself their CB (preserving in-tree paint order) and are skipped otherwise. Paint and hit-testing cancel the CB's scroll offset forposition: fixedchildren — using the viewport scroll when the CB is the root element (fixed boxes don't scroll with the document); scrollable-overflow resolution (resolve_transforms) accounts OOF boxes at their CB instead of their DOM parent.tests/blitz-tests/tests/oof_dynamic_cb.rs): toggling containing-block-establishing properties (transform/will-change/filter/contain/position, via style attributes and:hoverrestyles), DOM insertion/removal of fixed boxes,display:nonetoggles, and content changes inside hoisted subtrees, all under incremental layout.WPT results (before → after, tests fully passing)
Net across these suites: 55 newly passing, 8 regressed (+47 overall). The paint-order splice + taffy stack-top bump added a further net +3 on css/css-grid (
grid-items-relative-positioned-containing-block-004/005/006now pass) with no css-position regressions.Known regressions (grouped)
grid-items-relative-positioned-containing-block-003,position-relative-016,position-sticky-stacking-context-002,CSS2/backgrounds/background-position-002): the tree-order splice fixes ordering within one containing block's paint list, but a box hoisted to a distant CB (e.g. the ICB) still paints after the entire subtree containing a later positioned z-index:auto box, because Blitz paints hierarchically. A correct fix needs CSS 2.1 Appendix E step-8 semantics (collect all positioned z-index:auto descendants at the stacking-context level, painted after in-flow content in tree order) — deferred pending a design that doesn't hurt paint performance.nested-inline-abspos-child*): aposition:relativeinline span is not a Taffy node, so it cannot claim candidates; abspos boxes inside it now bubble past it. The old code positioned them relative to the inline root, which happened to pass these tests.anchor-scroll-fixedpos-003/004,anchor-scroll-nested,position-visibility-anchors-visible-in-overflow,filter-cb-abspos-inline-002/003): false passes on main (both test and ref mis-rendered); the branch now renders the refs correctly so they fail honestly. They needanchor()support (and inline CBs) to pass.Testing
cargo fmt --all,cargo clippy --workspace(clean),cargo check --workspace,cargo test --workspace(all pass).main, including focused reruns ofcss/css-grid/**andcss/css-position/**before/after the paint-order splice.Link to Devin session: https://dioxus.staging.devinenterprise.com/sessions/65c5463061c8403bade7888271d5eeb4
Open in Devin Desktop: https://dioxus.staging.devinenterprise.com/desktop/session/65c5463061c8403bade7888271d5eeb4?variant=devin-insiders
Requested by: @nicoburns
WPT results
151 newly passing, 37 newly failing (net +114), 15 other status changes.
Full diff (203 changed tests)
Generated by the WPT workflow.