Diff
Modified: trunk/LayoutTests/ChangeLog (106149 => 106150)
--- trunk/LayoutTests/ChangeLog 2012-01-27 22:05:56 UTC (rev 106149)
+++ trunk/LayoutTests/ChangeLog 2012-01-27 22:26:13 UTC (rev 106150)
@@ -1,3 +1,22 @@
+2012-01-27 Ken Buchanan <ke...@chromium.org>
+
+ Crash in updateFirstLetter() from unnecessary anonymous block
+ https://bugs.webkit.org/show_bug.cgi?id=72675
+
+ Reviewed by David Hyatt.
+
+ Adding tests that cause a div to be removed from between a floating
+ first-letter block and its remaining text. If the anonymous block is
+ removed as an immediate consequence of the div removal, this shouldn't
+ crash.
+
+ * fast/css-generated-content/float-first-letter-siblings-convert-to-inline-expected.txt: Added
+ * fast/css-generated-content/float-first-letter-siblings-convert-to-inline.html: Added
+ * fast/css-generated-content/positioned-div-with-floating-after-content-crash-expected.txt: Added
+ * fast/css-generated-content/positioned-div-with-floating-after-content-crash.html: Added
+ * fast/css-generated-content/resources/positioned-div-with-floating-after-content-crash-frame1.html: Added
+ * fast/css-generated-content/resources/positioned-div-with-floating-after-content-crash-frame2.html: Added
+
2012-01-27 Levi Weintraub <le...@chromium.org>
Unreviewed gardening. Adding new windows image expectations for css3/flexbox/cross-axis-scrollbar.html
Added: trunk/LayoutTests/fast/css-generated-content/float-first-letter-siblings-convert-to-inline-expected.txt (0 => 106150)
--- trunk/LayoutTests/fast/css-generated-content/float-first-letter-siblings-convert-to-inline-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/css-generated-content/float-first-letter-siblings-convert-to-inline-expected.txt 2012-01-27 22:26:13 UTC (rev 106150)
@@ -0,0 +1 @@
+PASS if no crash or assert
Added: trunk/LayoutTests/fast/css-generated-content/float-first-letter-siblings-convert-to-inline.html (0 => 106150)
--- trunk/LayoutTests/fast/css-generated-content/float-first-letter-siblings-convert-to-inline.html (rev 0)
+++ trunk/LayoutTests/fast/css-generated-content/float-first-letter-siblings-convert-to-inline.html 2012-01-27 22:26:13 UTC (rev 106150)
@@ -0,0 +1,34 @@
+<style>
+.inlineFL::first-letter { overflow: visible; }
+.absolutePosition { position: absolute; }
+.floatFL:first-letter { float: right; }
+</style>
+<script>
+function recreateFirstLetterBlock() {
+ document.getElementById("parent").setAttribute('class', 'inlineFL');
+ if (window.layoutTestController)
+ layoutTestController.notifyDone();
+}
+function removeDiv() {
+ // This causes the parent to only have inline (and floating) children
+ document.getElementById("parent").removeChild(document.getElementById("child"));
+ setTimeout("recreateFirstLetterBlock();", 10);
+}
+
+function changeDivStyle() {
+ document.getElementById("child").setAttribute('class', 'inlineFL');
+ setTimeout("removeDiv();", 10);
+}
+function startTest() {
+ setTimeout("changeDivStyle();", 10);
+ if (window.layoutTestController) {
+ layoutTestController.waitUntilDone();
+ layoutTestController.dumpAsText();
+ }
+}
+window._onload_ = startTest;
+</script>
+<div id="parent" class="floatFL">
+ <div id="child" class="absolutePosition"></div>
+ PASS if no crash or assert
+</div>
Added: trunk/LayoutTests/fast/css-generated-content/positioned-div-with-floating-after-content-crash-expected.txt (0 => 106150)
--- trunk/LayoutTests/fast/css-generated-content/positioned-div-with-floating-after-content-crash-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/css-generated-content/positioned-div-with-floating-after-content-crash-expected.txt 2012-01-27 22:26:13 UTC (rev 106150)
@@ -0,0 +1,6 @@
+
+
+--------
+Frame: 'frame'
+--------
+PASS, if no exception or crash
Added: trunk/LayoutTests/fast/css-generated-content/positioned-div-with-floating-after-content-crash.html (0 => 106150)
--- trunk/LayoutTests/fast/css-generated-content/positioned-div-with-floating-after-content-crash.html (rev 0)
+++ trunk/LayoutTests/fast/css-generated-content/positioned-div-with-floating-after-content-crash.html 2012-01-27 22:26:13 UTC (rev 106150)
@@ -0,0 +1,11 @@
+<script>
+function runTest() {
+ if (window.layoutTestController) {
+ layoutTestController.waitUntilDone();
+ layoutTestController.dumpAsText();
+ layoutTestController.dumpChildFramesAsText();
+ }
+}
+window._onload_ = runTest;
+</script>
+<iframe id="frame" src=""
Added: trunk/LayoutTests/fast/css-generated-content/resources/positioned-div-with-floating-after-content-crash-frame1.html (0 => 106150)
--- trunk/LayoutTests/fast/css-generated-content/resources/positioned-div-with-floating-after-content-crash-frame1.html (rev 0)
+++ trunk/LayoutTests/fast/css-generated-content/resources/positioned-div-with-floating-after-content-crash-frame1.html 2012-01-27 22:26:13 UTC (rev 106150)
@@ -0,0 +1,31 @@
+<style>
+.c1 { display: table; }
+.c1::after { position: fixed; content: counter(section); }
+.c2 { display: table-caption; float: left; }
+</style>
+<script>
+var node = document.createElement('q');
+
+function changeQClass() {
+ node.setAttribute('class', 'c1');
+ setTimeout("appendQ();", 10);
+}
+
+function appendQ() {
+ document.getElementById('positionedDiv').appendChild(node);
+ setTimeout("navigateAway();");
+}
+
+function navigateAway() {
+ // Bug only manifests on document destruction
+ window.location="positioned-div-with-floating-after-content-crash-frame2.html";
+}
+
+function runTest() {
+ setTimeout("changeQClass();", 10);
+}
+window._onload_ = runTest;
+</script>
+<div class="c2"><textarea></textarea></div>
+<div id="positionedDiv" class="c1">FAIL</div>
+<div class="c2"></div>
Added: trunk/LayoutTests/fast/css-generated-content/resources/positioned-div-with-floating-after-content-crash-frame2.html (0 => 106150)
--- trunk/LayoutTests/fast/css-generated-content/resources/positioned-div-with-floating-after-content-crash-frame2.html (rev 0)
+++ trunk/LayoutTests/fast/css-generated-content/resources/positioned-div-with-floating-after-content-crash-frame2.html 2012-01-27 22:26:13 UTC (rev 106150)
@@ -0,0 +1,8 @@
+<script>
+function finishTest() {
+ if (window.layoutTestController)
+ layoutTestController.notifyDone();
+}
+window._onload_ = finishTest;
+</script>
+PASS, if no exception or crash
Modified: trunk/Source/WebCore/ChangeLog (106149 => 106150)
--- trunk/Source/WebCore/ChangeLog 2012-01-27 22:05:56 UTC (rev 106149)
+++ trunk/Source/WebCore/ChangeLog 2012-01-27 22:26:13 UTC (rev 106150)
@@ -1,3 +1,22 @@
+2012-01-27 Ken Buchanan <ke...@chromium.org>
+
+ Crash in updateFirstLetter() from unnecessary anonymous block
+ https://bugs.webkit.org/show_bug.cgi?id=72675
+
+ Reviewed by David Hyatt.
+
+ There was a problem with anonymous blocks not getting removed when
+ their only block flow siblings are removed if they also have non-block
+ flow first-letter siblings (i.e. floats). This patch modifies
+ RenderBlock::removeChild() to look for this situation and strip out
+ unnecessary anonymous container blocks if it occurs.
+
+ * rendering/RenderBlock.cpp:
+ (WebCore::RenderBlock::removeChild):
+ (WebCore::RenderBlock::collapseAnonymousBoxChild): Added
+ * rendering/RenderBlock.h:
+ (WebCore::RenderBlock::collapseAnonymousBoxChild): Added
+
2012-01-27 Fady Samuel <fsam...@chromium.org>
Rename shouldLayoutFixedElementsRelativeToFrame and make it a setting
Modified: trunk/Source/WebCore/rendering/RenderBlock.cpp (106149 => 106150)
--- trunk/Source/WebCore/rendering/RenderBlock.cpp 2012-01-27 22:05:56 UTC (rev 106149)
+++ trunk/Source/WebCore/rendering/RenderBlock.cpp 2012-01-27 22:26:13 UTC (rev 106150)
@@ -1025,6 +1025,18 @@
&& prev->isAnonymousColumnSpanBlock() == next->isAnonymousColumnSpanBlock();
}
+void RenderBlock::collapseAnonymousBoxChild(RenderBlock* parent, RenderObject* child)
+{
+ parent->setNeedsLayoutAndPrefWidthsRecalc();
+ parent->setChildrenInline(child->childrenInline());
+ RenderBlock* anonBlock = toRenderBlock(parent->children()->removeChildNode(parent, child, child->hasLayer()));
+ anonBlock->moveAllChildrenTo(parent, child->hasLayer());
+ // Delete the now-empty block's lines and nuke it.
+ if (!parent->documentBeingDestroyed())
+ anonBlock->deleteLineBoxTree();
+ anonBlock->destroy();
+}
+
void RenderBlock::removeChild(RenderObject* oldChild)
{
// If this child is a block, and if our previous and next siblings are
@@ -1081,13 +1093,17 @@
// The removal has knocked us down to containing only a single anonymous
// box. We can go ahead and pull the content right back up into our
// box.
- setNeedsLayoutAndPrefWidthsRecalc();
- setChildrenInline(child->childrenInline());
- RenderBlock* anonBlock = toRenderBlock(children()->removeChildNode(this, child, child->hasLayer()));
- anonBlock->moveAllChildrenTo(this, child->hasLayer());
- // Delete the now-empty block's lines and nuke it.
- anonBlock->deleteLineBoxTree();
- anonBlock->destroy();
+ collapseAnonymousBoxChild(this, child);
+ } else if ((prev && prev->isAnonymousBlock()) || (next && next->isAnonymousBlock())) {
+ // It's possible that the removal has knocked us down to a single anonymous
+ // block with pseudo-style element siblings (e.g. first-letter). If these
+ // are floating, then we need to pull the content up also.
+ RenderBlock* anonBlock = toRenderBlock((prev && prev->isAnonymousBlock()) ? prev : next);
+ if ((anonBlock->previousSibling() || anonBlock->nextSibling())
+ && (!anonBlock->previousSibling() || (anonBlock->previousSibling()->style()->styleType() != NOPSEUDO && anonBlock->previousSibling()->isFloating()))
+ && (!anonBlock->nextSibling() || (anonBlock->nextSibling()->style()->styleType() != NOPSEUDO && anonBlock->nextSibling()->isFloating()))) {
+ collapseAnonymousBoxChild(this, anonBlock);
+ }
}
if (!firstChild() && !documentBeingDestroyed()) {
Modified: trunk/Source/WebCore/rendering/RenderBlock.h (106149 => 106150)
--- trunk/Source/WebCore/rendering/RenderBlock.h 2012-01-27 22:05:56 UTC (rev 106149)
+++ trunk/Source/WebCore/rendering/RenderBlock.h 2012-01-27 22:26:13 UTC (rev 106150)
@@ -461,6 +461,8 @@
void makeChildrenNonInline(RenderObject* insertionPoint = 0);
virtual void removeLeftoverAnonymousBlock(RenderBlock* child);
+ static void collapseAnonymousBoxChild(RenderBlock* parent, RenderObject* child);
+
virtual void dirtyLinesFromChangedChild(RenderObject* child) { m_lineBoxes.dirtyLinesFromChangedChild(this, child); }
void addChildToContinuation(RenderObject* newChild, RenderObject* beforeChild);