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/1787406503-taffy-oof-hoisting
branch
from
August 26, 2026 11:01
55127ef to
cf47ec8
Compare
staging-devin-ai-integration
Bot
force-pushed
the
devin/1787709349-incremental-paint-attach
branch
from
August 26, 2026 11:03
d2a2fd2 to
7555327
Compare
staging-devin-ai-integration
Bot
force-pushed
the
devin/1787406503-taffy-oof-hoisting
branch
from
August 26, 2026 11:21
cf47ec8 to
8860581
Compare
staging-devin-ai-integration
Bot
force-pushed
the
devin/1787709349-incremental-paint-attach
branch
from
August 26, 2026 11:23
7555327 to
c435a98
Compare
staging-devin-ai-integration
Bot
force-pushed
the
devin/1787709349-incremental-paint-attach
branch
from
September 2, 2026 19:30
c435a98 to
84db66d
Compare
staging-devin-ai-integration
Bot
changed the base branch from
devin/1787406503-taffy-oof-hoisting
to
devin/1787748926-taffy-oof-hoisting-latebound
September 2, 2026 19:30
staging-devin-ai-integration
Bot
force-pushed
the
devin/1787748926-taffy-oof-hoisting-latebound
branch
from
September 12, 2026 22:23
eca059a to
07c2ec6
Compare
staging-devin-ai-integration
Bot
force-pushed
the
devin/1787709349-incremental-paint-attach
branch
from
September 17, 2026 14:30
84db66d to
bf3afe0
Compare
staging-devin-ai-integration
Bot
force-pushed
the
devin/1787748926-taffy-oof-hoisting-latebound
branch
from
September 17, 2026 14:51
06b66c6 to
7367a75
Compare
staging-devin-ai-integration
Bot
force-pushed
the
devin/1787709349-incremental-paint-attach
branch
14 times, most recently
from
September 17, 2026 17:43
7c63dd6 to
47dea7c
Compare
staging-devin-ai-integration
Bot
force-pushed
the
devin/1787748926-taffy-oof-hoisting-latebound
branch
from
September 17, 2026 18:38
64991d8 to
dc19e19
Compare
…n; bump taffy pin to bc1776fc
staging-devin-ai-integration
Bot
force-pushed
the
devin/1787748926-taffy-oof-hoisting-latebound
branch
from
September 17, 2026 19:25
57ae385 to
7e28382
Compare
staging-devin-ai-integration
Bot
force-pushed
the
devin/1787709349-incremental-paint-attach
branch
from
September 17, 2026 19:26
e8f2315 to
402e100
Compare
Taffy's add/clear_hoisted_children callbacks now record the containing block in a dedicated Node::containing_block cell instead of repointing layout_parent, which stays the layout-tree parent. Coordinate accumulation (absolute_position, offsetParent, debug overlay, stacking context offsets) follows position_parent() = containing_block or layout_parent.
staging-devin-ai-integration
Bot
force-pushed
the
devin/1787709349-incremental-paint-attach
branch
from
September 17, 2026 19:36
402e100 to
8ae93ea
Compare
getComputedStyle for top/right/bottom/left on absolute/fixed boxes must measure against the containing block the box's Layout.location is relative to, which is no longer layout_parent since hoisting stopped mutating it.
staging-devin-ai-integration
Bot
force-pushed
the
devin/1787709349-incremental-paint-attach
branch
from
September 17, 2026 19:43
8ae93ea to
4da2cb7
Compare
HoistedPaintChild no longer stores a position offset. The offset of a hoisted child relative to the node that paints it is derived from the layout_parent chain when painting/hit-testing (Node::hoisted_child_position), so it cannot go stale when layout or scroll offsets change elsewhere. This removes the main reason attach_hoisted_children had to re-run over the whole tree every frame.
Taffy's out-of-flow callbacks (set_hoisted_children/add_hoisted_children) maintain a registry of containing blocks that own hoisted boxes, and attach_hoisted_children iterates that registry (with lazy pruning of removed/emptied entries) rather than every node in the document.
In incremental mode, subtrees with no damage (damage propagation bubbles descendant damage into each ancestor's stored damage) are skipped by the style flush: their taffy styles, layout/paint child lists and stacking contexts are unchanged from the previous flush. The HoistedPaintChild entries a skipped subtree contributed to an ancestor stacking context are replayed from a per-node cache captured when the subtree was last visited, so a rebuilt ancestor stacking context keeps entries from clean subtrees. This makes the per-frame style flush O(damaged nodes) rather than O(tree).
staging-devin-ai-integration
Bot
force-pushed
the
devin/1787709349-incremental-paint-attach
branch
from
September 17, 2026 19:49
4da2cb7 to
8f73948
Compare
staging-devin-ai-integration
Bot
changed the base branch from
devin/1787748926-taffy-oof-hoisting-latebound
to
main
September 17, 2026 20:04
This branch has not been deployed
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
Stacked on #805 (this PR's branch includes #805's commits; the diff reduces to the three commits below once #805 merges). Removes the avoidable O(tree) per-frame work from the paint-placement side of the OOF hoisting branch, with no behavior change. Three independent commits:
1. Hoisted paint-child positions are derived at use-time, not baked.
pub struct HoistedPaintChild { pub node_id: NodeId, pub z_index: i32, - pub position: taffy::Point<f32>, }Paint, hit-testing, and
compute_content_sizenow compute the offset viaNode::hoisted_child_position(child_id), which accumulateslocation - scroll_offsetalong the child'scontaining_block()chain (the OOF containing block for hoisted boxes, otherwiselayout_parent) up to the owning node (with a negated walk for the effect-ancestor case where the owner is below the containing block). Since nothing baked can go stale, layout/scroll changes elsewhere no longer require re-baking every hoisted entry.2.
attach_hoisted_childrenno longer scans the whole node slab.BaseDocumentgainsoof_containing_blocks: HashSet<NodeId>, maintained by Taffy's OOF callbacks (add_hoisted_childreninserts,clear_hoisted_childrenremoves). Attach iterates only these registered containing blocks (sorted for determinism, lazily pruning removed/emptied ones), so its cost is bounded by the number of OOF boxes, not document size.3.
flush_styles_to_layoutskips clean subtrees (incremental mode).Damage propagation already bubbles descendant damage into each ancestor's stored damage, so
damage.is_empty() && !has_damaged_descendants() && !is_anonymous()proves the whole subtree is unchanged: its taffy styles,layout_childrenorder-sort,paint_children, and stacking contexts are all still valid, and the flush returns early. The one piece a skipped subtree still owes its surroundings — theHoistedPaintChildentries it contributed to the nearest ancestor stacking context — is replayed from a per-nodesc_contribution_cachecaptured on the last flush that visited it, so a damaged ancestor SC that rebuilds its list keeps entries from clean descendant subtrees. This makes the flush's per-frame cost O(damaged nodes).Not addressed (intentionally): the tree-order splice and
is_before_in_tree_orderare unchanged (same ordering semantics as the base branch), Appendix E step-8 interleaving remains approximate (grid-items-relative-positioned-containing-block-003still fails), and attach still visits every registered CB each frame — it can't be safely damage-gated because a rebuilt ancestor stacking context needs clean CBs' z-indexed entries re-pushed.Testing
css/css-position,css/CSS2/positioning,css/CSS2/zindex,css/css-grid/grid-items,css/css-grid/abspos,css/css-flexbox: zero status differences.2cbce9b0):cargo test --workspace,cargo clippy --workspace,cargo fmtall clean.Link to Devin session: https://dioxus.staging.devinenterprise.com/sessions/2641a1705e2547a0b385ec07a70a3abb
Open in Devin Desktop: https://dioxus.staging.devinenterprise.com/desktop/session/2641a1705e2547a0b385ec07a70a3abb?variant=devin-insiders
Requested by: @nicoburns