Commit c579aa1f authored by robhogan's avatar robhogan Committed by Commit bot

Re-land 'Fold out-of-flow objects into anonymous blocks when removing children'

Another attempt at https://codereview.chromium.org/1406163003.

Sometimes when we remove a child we end up with a float or out-of-flow object beside
an anonymous block. When that happens, fold the float/out-of-flow object into the
anonymous box as that is where it would have lived if they were siblings in the
first place.

BUG=322039

Review URL: https://codereview.chromium.org/1543283002

Cr-Commit-Position: refs/heads/master@{#367074}
parent cbcf8a48
......@@ -244,6 +244,8 @@ crbug.com/524859 transforms/2d/hindi-rotated.html [ NeedsManualRebaseline ]
crbug.com/569139 fast/js/string-replace-2.html [ NeedsManualRebaseline ]
crbug.com/569139 fast/js/regexp-caching.html [ NeedsManualRebaseline ]
crbug.com/322039 fast/block/float/remove-div-after-float-and-before-anonymous-block-container.html [ NeedsRebaseline ]
crbug.com/498539 http/tests/inspector/elements/styles/selector-line.html [ Pass Timeout ]
crbug.com/498539 http/tests/inspector/network/network-datareceived.html [ Pass Timeout ]
crbug.com/498539 [ Win ] inspector/tracing/decode-resize.html [ Failure Timeout ]
......
crbug.com/322039: Don't attempt to fold a float into an anonymous block if it is being destroyed. The test should not crash.
<!DOCTYPE html>
<style>
.float { float: right; }
.span { content: ""; }
</style>
<body>
<p>crbug.com/322039: Don't attempt to fold a float into an anonymous block if it is being destroyed. The test should not crash.</p>
<span id="span" class="span"><div></div></span>
<div id="div"></div>
<div class="float"></div>
</body>
<script>
if (window.testRunner)
testRunner.dumpAsText();
document.body.offsetTop;
span.setAttribute('class', '');
div.setAttribute('class', 'float');
</script>
<!DOCTYPE html>
<style>
.block {
width: 50px;
height: 50px;
background-color: green;
}
</style>
<p>crbug.com/322039: There should be a green <em>square</em> below.</p>
<div>
<br>
<div id="first" class="block"></div>
</div>
<!DOCTYPE html>
<style>
.block {
width: 25px;
height: 50px;
background-color: green;
}
.float {
width: 25px;
height: 50px;
background-color: green;
float: left;
}
</style>
<p>crbug.com/322039: There should be a green <em>square</em> below.</p>
<div>
<div></div>
<br>
<div id="first" class="block"></div>
<div class="float"></div>
</div>
<script>
document.body.offsetTop;
document.getElementById("first").style.display = "inline-block";
</script>
layer at (0,0) size 800x600
LayoutView at (0,0) size 800x600
layer at (0,0) size 800x105
LayoutBlockFlow {HTML} at (0,0) size 800x105
LayoutBlockFlow {BODY} at (8,16) size 784x81
LayoutBlockFlow {P} at (0,0) size 784x20
LayoutText {#text} at (0,0) size 272x19
text run at (0,0) width 272: "crbug.com/322039: There should be a green "
LayoutInline {EM} at (0,0) size 43x19
LayoutText {#text} at (272,0) size 43x19
text run at (272,0) width 43: "square"
LayoutText {#text} at (314,0) size 438x19
text run at (314,0) width 438: " below. In the layout tree the float should be inside the anonymous block."
LayoutBlockFlow {DIV} at (0,36) size 150x45
LayoutBlockFlow {DIV} at (0,0) size 50x25 [bgcolor=#008000]
LayoutBlockFlow (anonymous) at (0,25) size 150x20
LayoutBlockFlow (floating) {DIV} at (0,0) size 50x25 [bgcolor=#008000]
LayoutText {#text} at (50,0) size 30x19
text run at (50,0) width 30: "Text."
<!DOCTYPE html>
<style>
.block {
width: 50px;
height: 25px;
background-color: green;
}
.float {
width: 50px;
height: 25px;
background-color: green;
float: left;
}
</style>
<p>crbug.com/322039: There should be a green <em>square</em> below. In the layout tree the float should be inside the anonymous block.</p>
<div style="width: 150px;">
<div class="block"></div>
<div class="float"></div>
<div id="div"></div>
Text.
</div>
<script>
document.body.offsetTop;
var div = document.getElementById("div");
div.parentNode.removeChild(div);
</script>
......@@ -374,6 +374,32 @@ void LayoutBlock::invalidateDisplayItemClients(const LayoutBoxModelObject& paint
invalidateDisplayItemClientForStartOfContinuationsIfNeeded(*this);
}
static void addNextFloatingOrOutOfFlowSiblingsToBlock(LayoutBlock* block, LayoutBlock* container)
{
if (block->beingDestroyed())
return;
LayoutObject* child = block->nextSibling();
while (child && child->isFloatingOrOutOfFlowPositioned()) {
LayoutObject* sibling = child->nextSibling();
container->moveChildTo(block, child, nullptr, false);
child = sibling;
}
}
static void addPreviousFloatingOrOutOfFlowSiblingsToBlock(LayoutBlock* block, LayoutBlock* container)
{
if (block->beingDestroyed())
return;
LayoutObject* child = block->previousSibling();
while (child && child->isFloatingOrOutOfFlowPositioned()) {
LayoutObject* sibling = child->previousSibling();
container->moveChildTo(block, child, block->firstChild(), false);
child = sibling;
}
}
void LayoutBlock::addChildIgnoringContinuation(LayoutObject* newChild, LayoutObject* beforeChild)
{
if (beforeChild && beforeChild->parent() != this) {
......@@ -448,19 +474,9 @@ void LayoutBlock::addChildIgnoringContinuation(LayoutObject* newChild, LayoutObj
LayoutBlock* newBox = createAnonymousBlock();
LayoutBox::addChild(newBox, beforeChild);
// Reparent adjacent floating or out-of-flow siblings to the new box.
LayoutObject* child = newBox->previousSibling();
while (child && child->isFloatingOrOutOfFlowPositioned()) {
LayoutObject* sibling = child->previousSibling();
moveChildTo(newBox, child, newBox->firstChild(), false);
child = sibling;
}
addPreviousFloatingOrOutOfFlowSiblingsToBlock(newBox, this);
newBox->addChild(newChild);
child = newBox->nextSibling();
while (child && child->isFloatingOrOutOfFlowPositioned()) {
LayoutObject* sibling = child->nextSibling();
moveChildTo(newBox, child, nullptr, false);
child = sibling;
}
addNextFloatingOrOutOfFlowSiblingsToBlock(newBox, this);
return;
}
}
......@@ -738,6 +754,13 @@ void LayoutBlock::removeChild(LayoutObject* oldChild)
&& (!anonymousBlock->previousSibling() || (anonymousBlock->previousSibling()->style()->styleType() != NOPSEUDO && anonymousBlock->previousSibling()->isFloating() && !anonymousBlock->previousSibling()->previousSibling()))
&& (!anonymousBlock->nextSibling() || (anonymousBlock->nextSibling()->style()->styleType() != NOPSEUDO && anonymousBlock->nextSibling()->isFloating() && !anonymousBlock->nextSibling()->nextSibling()))) {
collapseAnonymousBlockChild(this, anonymousBlock);
} else {
// If we have floating or out-of-flow siblings now adjacent to an anonymous block, fold them
// into it.
if (prev && prev->isAnonymousBlock())
addNextFloatingOrOutOfFlowSiblingsToBlock(toLayoutBlock(prev), this);
else if (next && next->isAnonymousBlock())
addPreviousFloatingOrOutOfFlowSiblingsToBlock(toLayoutBlock(next), this);
}
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment