Commit de47d53b authored by robhogan@gmail.com's avatar robhogan@gmail.com

Strip anonymous blocks when change in style removes need for them

When a block element becomes a float or out of flow we should strip
any anonymous blocks wrapping its inline siblings.

BUG=331251

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

git-svn-id: svn://svn.chromium.org/blink/trunk@185200 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent c254287d
...@@ -608,6 +608,11 @@ crbug.com/344239 inspector-protocol/heap-profiler/heap-objects-tracking.html [ C ...@@ -608,6 +608,11 @@ crbug.com/344239 inspector-protocol/heap-profiler/heap-objects-tracking.html [ C
crbug.com/313846 http/tests/images/webp-partial-load.html [ ImageOnlyFailure Timeout Pass ] crbug.com/313846 http/tests/images/webp-partial-load.html [ ImageOnlyFailure Timeout Pass ]
crbug.com/331251 fast/block/float/float-not-removed-from-next-sibling2.html [ NeedsRebaseline ]
crbug.com/331251 fast/block/float/nestedAnonymousBlocks.html [ NeedsRebaseline ]
crbug.com/331251 fast/block/do-not-strip-anonymous-blocks-when-block-child-becomes-float-and-continuation-on-line.html [ NeedsRebaseline ]
crbug.com/331251 fast/block/do-not-strip-anonymous-blocks-when-block-child-becomes-float-and-other-block-on-line.html [ NeedsRebaseline ]
crbug.com/316730 canvas/synchronous-create-pattern.html [ ImageOnlyFailure Pass ] crbug.com/316730 canvas/synchronous-create-pattern.html [ ImageOnlyFailure Pass ]
crbug.com/320099 webaudio/oscillator-sawtooth.html [ NeedsManualRebaseline ] crbug.com/320099 webaudio/oscillator-sawtooth.html [ NeedsManualRebaseline ]
...@@ -1208,6 +1213,9 @@ crbug.com/396791 [ Debug ] virtual/threaded/printing/print-close-crash.html [ Pa ...@@ -1208,6 +1213,9 @@ crbug.com/396791 [ Debug ] virtual/threaded/printing/print-close-crash.html [ Pa
crbug.com/396851 [ Lion ] inspector/console/console-stack-overflow.html [ Timeout ] crbug.com/396851 [ Lion ] inspector/console/console-stack-overflow.html [ Timeout ]
crbug.com/331251 virtual/slimmingpaint/fast/block/do-not-strip-anonymous-blocks-when-block-child-becomes-float-and-continuation-on-line.html [ NeedsRebaseline ]
crbug.com/331251 virtual/slimmingpaint/fast/block/do-not-strip-anonymous-blocks-when-block-child-becomes-float-and-other-block-on-line.html [ NeedsRebaseline ]
# crbug.com/396936 [ Lion ] fast/writing-mode/broken-ideograph-small-caps.html [ Crash ] # crbug.com/396936 [ Lion ] fast/writing-mode/broken-ideograph-small-caps.html [ Crash ]
# crbug.com/396936 [ Lion ] fast/writing-mode/broken-ideographic-font.html [ Crash ] # crbug.com/396936 [ Lion ] fast/writing-mode/broken-ideographic-font.html [ Crash ]
# crbug.com/396936 [ Lion ] fast/writing-mode/japanese-rl-text-with-broken-font.html [ Crash ] # crbug.com/396936 [ Lion ] fast/writing-mode/japanese-rl-text-with-broken-font.html [ Crash ]
......
88
When a block element becomes positioned or float we should not strip anonymous blocks wrapping its siblings if any of their children are inline.
<!DOCTYPE html>
<style>
.fixed { position: fixed; }
.col { -webkit-column-span: all; }
.colcount:nth-child(2n) { -webkit-column-count: 1; }
.colcount { padding-left: 65536px; }
</style>
<script>
if (window.testRunner)
testRunner.dumpAsText();
function boom() {
var nav = document.createElement('nav');
nav.setAttribute('class', 'col');
div.appendChild(nav);
document.body.offsetTop;
dt.parentNode.removeChild(dt);
var p = document.createElement('p');
div.appendChild(p);
document.body.offsetTop;
var text = document.createTextNode('88');
div.appendChild(text);
p.setAttribute("class", "fixed");
var command = document.createElement('command');
command.setAttribute('class', 'colcount');
nav.appendChild(command);
}
window.onload = boom;
</script>
<p></p>
<dt id="dt"></dt>
<p></p>
<div class="colcount" id="div"></div>
<p> When a block element becomes positioned or float we should not strip anonymous blocks wrapping its siblings if any of their children are inline.</p>
<!DOCTYPE html>
<style>
body {
margin: 0;
padding: 0;
}
#container {
position: relative;
background: #ccc;
font: 20px Ahem;
}
#floater {
float: none;
}
</style>
<body>
<p> When a block element becomes a float we should not strip anonymous blocks wrapping its inline siblings if there are other blocks on the
line. In this test case, the block is wrapped in an anonymous block as part of a continuation.</p>
<div id="container">
<span>
<p>Text</p>
</span>
<dd id="floater"></dd>
</div>
<script>
document.body.offsetTop;
document.getElementById('floater').style.float = 'right';
</script>
</body>
<!DOCTYPE html>
<style>
body {
margin: 0;
padding: 0;
}
#container {
position: relative;
background: #ccc;
font: 20px Ahem;
}
#floater {
float: none;
}
</style>
<body>
<p> When a block element becomes a float we should not strip anonymous blocks wrapping its inline siblings if there are other blocks on the line.</p>
<div id="container">
<strong></strong>
<p></p>
<dd id="floater"></dd>
<br>
</div>
<script>
document.body.offsetTop;
document.getElementById('floater').style.float = 'right';
</script>
</body>
When a block element becomes a float we should strip any anonymous blocks wrapping its inline siblings.
Some
content
here. Should appear inside grey box.
PASS
<!DOCTYPE html>
<style>
body {
margin: 0;
padding: 0;
}
#container {
position: relative;
background: #ccc;
font: 20px Ahem;
}
#floater {
float: none;
}
</style>
<script src="../../resources/check-layout.js"></script>
<body>
<p> When a block element becomes a float we should strip any anonymous blocks wrapping its inline siblings.</p>
<div id="container">
<span id="content">
Some<br />
content<br />
here.
</span>
<div id="floater" data-offset-y=40>
Should appear inside grey box.
</div>
</div>
<script>
document.body.offsetTop;
document.getElementById('floater').style.float = 'right';
onload = function() { checkLayout('#container'); }
</script>
</body>
...@@ -28,6 +28,10 @@ div { ...@@ -28,6 +28,10 @@ div {
top: 20px; top: 20px;
background-color: blue; background-color: blue;
} }
#target0 {
left: 20px;
position: relative;
}
#target1 { #target1 {
left: 20px; left: 20px;
position: relative; position: relative;
...@@ -44,6 +48,8 @@ div { ...@@ -44,6 +48,8 @@ div {
} }
</style> </style>
There should be no invalildations on change of position without actual change of position and size. There should be no invalildations on change of position without actual change of position and size.
<!-- target0 ensures we don't strip anonymous wrappers (and trigger a layout) when the other elements change position. -->
<div id="target0"></div>
<div id="target1"></div> <div id="target1"></div>
<div id="target2"></div> <div id="target2"></div>
<div id="target3"></div> <div id="target3"></div>
layer at (0,0) size 800x600
RenderView at (0,0) size 800x600
layer at (0,0) size 800x116
RenderBlock {HTML} at (0,0) size 800x116
RenderBody {BODY} at (0,16) size 800x80
RenderBlock {P} at (0,0) size 800x40
RenderText {#text} at (0,0) size 792x39
text run at (0,0) width 792: "When a block element becomes a float we should not strip anonymous blocks wrapping its inline siblings if there are other blocks on"
text run at (0,20) width 22: "the "
text run at (22,20) width 549: "line. In this test case, the block is wrapped in an anonymous block as part of a continuation."
layer at (0,76) size 800x20
RenderBlock (relative positioned) {DIV} at (0,60) size 800x20 [bgcolor=#CCCCCC]
RenderBlock (anonymous) at (0,0) size 800x0
RenderInline {SPAN} at (0,0) size 0x0
RenderText {#text} at (0,0) size 0x0
RenderBlock (anonymous) at (0,0) size 800x20
RenderBlock {P} at (0,0) size 800x20
RenderText {#text} at (0,0) size 80x20
text run at (0,0) width 80: "Text"
RenderBlock (anonymous) at (0,40) size 800x0
RenderInline {SPAN} at (0,0) size 0x0
RenderText {#text} at (0,0) size 0x0
RenderBlock (floating) {DD} at (800,40) size 0x0
layer at (0,0) size 800x600
RenderView at (0,0) size 800x600
layer at (0,0) size 800x96
RenderBlock {HTML} at (0,0) size 800x96
RenderBody {BODY} at (0,16) size 800x80
RenderBlock {P} at (0,0) size 800x40
RenderText {#text} at (0,0) size 792x39
text run at (0,0) width 792: "When a block element becomes a float we should not strip anonymous blocks wrapping its inline siblings if there are other blocks on"
text run at (0,20) width 46: "the line."
layer at (0,76) size 800x20
RenderBlock (relative positioned) {DIV} at (0,60) size 800x20 [bgcolor=#CCCCCC]
RenderBlock (anonymous) at (0,0) size 800x0
RenderInline {STRONG} at (0,0) size 0x0
RenderText {#text} at (0,0) size 0x0
RenderBlock {P} at (0,0) size 800x0
RenderBlock (floating) {DD} at (800,0) size 0x0
RenderBlock (anonymous) at (0,0) size 800x20
RenderBR {BR} at (0,0) size 0x20
...@@ -345,6 +345,9 @@ void RenderBlock::styleDidChange(StyleDifference diff, const RenderStyle* oldSty ...@@ -345,6 +345,9 @@ void RenderBlock::styleDidChange(StyleDifference diff, const RenderStyle* oldSty
{ {
RenderBox::styleDidChange(diff, oldStyle); RenderBox::styleDidChange(diff, oldStyle);
if (isFloatingOrOutOfFlowPositioned() && oldStyle && !oldStyle->isFloating() && !oldStyle->hasOutOfFlowPosition() && parent() && parent()->isRenderBlockFlow())
toRenderBlock(parent())->removeAnonymousWrappersIfRequired();
RenderStyle* newStyle = style(); RenderStyle* newStyle = style();
if (!isAnonymousBlock()) { if (!isAnonymousBlock()) {
...@@ -1101,6 +1104,28 @@ static bool canMergeContiguousAnonymousBlocks(RenderObject* oldChild, RenderObje ...@@ -1101,6 +1104,28 @@ static bool canMergeContiguousAnonymousBlocks(RenderObject* oldChild, RenderObje
&& prev->isAnonymousColumnSpanBlock() == next->isAnonymousColumnSpanBlock(); && prev->isAnonymousColumnSpanBlock() == next->isAnonymousColumnSpanBlock();
} }
void RenderBlock::removeAnonymousWrappersIfRequired()
{
ASSERT(isRenderBlockFlow());
Vector<RenderBox*, 16> blocksToRemove;
for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
// There are still block children in the container, so any anonymous wrappers are still needed.
if (!child->isAnonymousBlock() && !child->isFloatingOrOutOfFlowPositioned())
return;
// We can't remove anonymous wrappers if they contain continuations as this means there are block children present.
if (child->isRenderBlock() && toRenderBlock(child)->continuation())
return;
// We are only interested in removing anonymous wrappers if there are inline siblings underneath them.
if (!child->childrenInline())
return;
if (child->isAnonymousBlock())
blocksToRemove.append(child);
}
for (size_t i = 0; i < blocksToRemove.size(); i++)
collapseAnonymousBlockChild(this, toRenderBlock(blocksToRemove[i]));
}
void RenderBlock::collapseAnonymousBlockChild(RenderBlock* parent, RenderBlock* child) void RenderBlock::collapseAnonymousBlockChild(RenderBlock* parent, RenderBlock* child)
{ {
// It's possible that this block's destruction may have been triggered by the // It's possible that this block's destruction may have been triggered by the
......
...@@ -357,6 +357,8 @@ private: ...@@ -357,6 +357,8 @@ private:
virtual bool isSelfCollapsingBlock() const override; virtual bool isSelfCollapsingBlock() const override;
void removeAnonymousWrappersIfRequired();
void insertIntoTrackedRendererMaps(RenderBox* descendant, TrackedDescendantsMap*&, TrackedContainerMap*&); void insertIntoTrackedRendererMaps(RenderBox* descendant, TrackedDescendantsMap*&, TrackedContainerMap*&);
static void removeFromTrackedRendererMaps(RenderBox* descendant, TrackedDescendantsMap*&, TrackedContainerMap*&); static void removeFromTrackedRendererMaps(RenderBox* descendant, TrackedDescendantsMap*&, TrackedContainerMap*&);
......
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