fix(render): give flattened inline wrappers real DOM geometry - #727
Open
Vrejf wants to merge 1 commit into
Open
Conversation
A plain inline wrapper whose run holds a replaced element fails try_build_run, so build_mixed_block takes the mixed-run path and is_flattenable_inline splices the wrapper's children into the parent's taffy children. The wrapper owns no box and nothing records a rect for it, so getBoundingClientRect returned 0x0 and a coordinate click had no target. Synthesize the rect after layout from the wrapper's rendered descendants, grouped per line. Out-of-flow and floated descendants are excluded, and positioned inlines keep their own box because they are a containing block for absolute descendants. A padded inline now keeps a real box instead of being flattened, matching the existing treatment of a bordered inline. An inline wrapping a block child still reports one client rect where Chromium reports one per fragment; the bounding box matches. Fixes h4ckf0r0day#722.
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.
Fixes #722.
A plain inline wrapper whose run holds a replaced element (
<label>x</label><input>,<span>x</span><img>) failstry_build_run, sobuild_mixed_blocktakes the mixed-run path andis_flattenable_inlinesplices the wrapper's children into the parent's taffy children. The wrapper owns no box, nothing records a rect for it, andgetBoundingClientRect()returned0x0, so Puppeteer/Playwrighthandle.click()failed with "not clickable".The rect is now synthesized after layout from the wrapper's rendered descendants, grouped per line. Out-of-flow and floated descendants are excluded, since they are not part of the inline box; without that an absolutely positioned child at
left:900pxturned a 28px span into a 918px one. Positioned inlines keep their own box because they are a containing block for absolute descendants. A padded inline now keeps a real box instead of being flattened, matching how a bordered inline is already handled.The walk is iterative and bounded by a node budget rather than by depth, and wrappers are resolved deepest-first so each subtree is visited once and a nested wrapper contributes its own line fragments rather than a collapsed union.
Verification
Measured against headless Chrome 145 unless stated.
<div><label>toggle</label><input></div>getClientRects()cargo nextest run --release --features render --no-fail-fast: 1488 run, 1486 passed. The two failures areintersection_observer_*tests that fail on unmodifiedmainas well, at 2/10 and 3/10 over ten runs each on both trees.observer-intersectionidentically onmain.render-reprosfixtures produce metrics byte-identical to the pre-change build, so nothing repaints differently.No
render-reprosfixture is included: the change is DOM geometry and produces no pixel difference, so a screenshot fixture would assert nothing. Coverage is inlayout_test.rs.Known limitations
0x0where Chromium reports0x<line height>, and an inline wrapping only a replaced element gets that element's height rather than the line box's. Both need the inline strut thatsynthesize_ordinary_inline_fragmentsderives from the text engine.