Skip to content

Commit 0effd07

Browse files
committed
Incorrectly positioned out-of-flow box when layout boundary is present
https://bugs.webkit.org/show_bug.cgi?id=254666 Reviewed by Antti Koivisto. Consider the following case: <containing-block> <layout-boundary> Inline-content <out-of-flow-box> </layout-boundary> </containing-block> e.g. <div style="overflow: hidden"> some text <div style="position: absolute"></div> </div> 1. "inline content" gets mutated and the associated renderers are marked dirty. During #1 we climb the ancestor chain and mark containing blocks dirty to ensure the subsequent layout has a correct entry point. We either (most of the time) stop at the ICB (RenderView) during this walk or at a layout-boundary. 2. Subsequent layout is initiated starting at layout-boundary. The geometry of the freshly laid out inline-content may affect the out-of-flow-box's static position. In inline layout code (both legacy and IFC) at this point we only set the "static" position assuming that layout eventually reaches the out-of-flow-box's containing block which would set the final top/left coords. However since this layout is bound to layout-boundary's subtree, we never get to the containing-block. While this is an invalidation bug where we fail to mark the containing-block dirty (by not stopping at layout-boundary), it's expensive to figure out if there's a descendent of the layout-boundary with an ancestor containing block (outside of layout-boundary's subtree). Instead set the out-of-flow-box's coordinates here at inline layout and let the containing block update it as part of the normal layout flow (when we actually get to the containing block). This is technically correct since this renderer's position is its static position until the containing block updates it as applicable (and the special "static position" handling could be considered as a render tree artifact). * LayoutTests/fast/block/positioning/static_out_of_flow_inside_layout_boundary-expected.html: Added. * LayoutTests/fast/block/positioning/static_out_of_flow_inside_layout_boundary.html: Added. * Source/WebCore/layout/integration/inline/LayoutIntegrationLineLayout.cpp: (WebCore::LayoutIntegration::LineLayout::updateRenderTreePositions): Canonical link: https://commits.webkit.org/262470@main
1 parent 4bfd15d commit 0effd07

File tree

4 files changed

+49
-1
lines changed

4 files changed

+49
-1
lines changed

LayoutTests/TestExpectations

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3671,6 +3671,7 @@ webkit.org/b/203451 imported/w3c/web-platform-tests/css/css-position/static-posi
36713671
webkit.org/b/203451 imported/w3c/web-platform-tests/css/css-position/static-position/vrl-rtl-rtl.html [ ImageOnlyFailure ]
36723672

36733673
webkit.org/b/254666 [ Debug ] imported/w3c/web-platform-tests/css/css-position/position-absolute-crash-chrome-005.html [ Skip ]
3674+
webkit.org/b/254666 [ Debug ] fast/block/positioning/static_out_of_flow_inside_layout_boundary.html [ Skip ]
36743675

36753676
webkit.org/b/203606 imported/w3c/web-platform-tests/css/css-display/display-change-object-iframe.html [ ImageOnlyFailure ]
36763677
webkit.org/b/203606 imported/w3c/web-platform-tests/css/css-display/display-flow-root-list-item-001.html [ ImageOnlyFailure ]
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<style>
2+
div {
3+
width: 100px;
4+
height: 50px;
5+
background-color: green;
6+
}
7+
</style>
8+
<div></div>
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<style>
2+
.container {
3+
width: 100px;
4+
height: 50px;
5+
background-color: red;
6+
overflow: hidden;
7+
}
8+
9+
.out_of_flow {
10+
display: inline;
11+
width: 100px;
12+
height: 50px;
13+
background-color: green;
14+
position: absolute;
15+
}
16+
17+
#remove_this {
18+
display: inline-block;
19+
width: 100px;
20+
height: 10px;
21+
background-color: blue;
22+
}
23+
</style>
24+
<div class=container>
25+
<div id=remove_this></div>
26+
<div class=out_of_flow></div>
27+
</div>
28+
<script>
29+
document.body.offsetHeight;
30+
remove_this.style.display = "none";
31+
</script>

Source/WebCore/layout/integration/inline/LayoutIntegrationLineLayout.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -666,19 +666,27 @@ void LineLayout::updateRenderTreePositions(const Vector<LineAdjustment>& lineAdj
666666

667667
renderer.setLocation(Layout::BoxGeometry::borderBoxRect(visualGeometry).topLeft());
668668
renderer.repaint();
669+
continue;
669670
}
670671

671672
if (layoutBox.isOutOfFlowPositioned()) {
672673
ASSERT(renderer.layer());
673674
auto& layer = *renderer.layer();
674675
auto logicalBorderBoxRect = LayoutRect { Layout::BoxGeometry::borderBoxRect(logicalGeometry) };
675676

676-
if (layoutBox.style().isOriginalDisplayInlineType())
677+
if (layoutBox.style().isOriginalDisplayInlineType()) {
678+
auto previousStaticPosition = LayoutPoint { layer.staticInlinePosition(), layer.staticBlockPosition() };
677679
blockFlow.setStaticInlinePositionForChild(renderer, logicalBorderBoxRect.y(), logicalBorderBoxRect.x());
678680

681+
auto delta = logicalBorderBoxRect.location() - previousStaticPosition;
682+
// A non-statically positioned out-of-flow box's layout will override the top/left values we are setting here.
683+
renderer.move(delta.width(), delta.height());
684+
}
685+
679686
layer.setStaticBlockPosition(logicalBorderBoxRect.y());
680687
layer.setStaticInlinePosition(logicalBorderBoxRect.x());
681688

689+
// FIXME: Figure out if this is really needed (see webkit.org/b/254666).
682690
if (layoutBox.style().hasStaticInlinePosition(renderer.isHorizontalWritingMode()))
683691
renderer.setChildNeedsLayout(MarkOnlyThis);
684692
continue;

0 commit comments

Comments
 (0)