Floating box is misplaced after content change.
authorzalan@apple.com <zalan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 26 Oct 2015 23:36:01 +0000 (23:36 +0000)
committerzalan@apple.com <zalan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 26 Oct 2015 23:36:01 +0000 (23:36 +0000)
https://bugs.webkit.org/show_bug.cgi?id=150271

Reviewed by David Hyatt.

Collapse anonymous block when as the result of a sibling removal only floating siblings are left.

Source/WebCore:

Test: fast/block/collapse-anon-block-with-float-siblings-only.html

* rendering/RenderBlock.cpp:
(WebCore::canCollapseAnonymousBlock):
(WebCore::canMergeContiguousAnonymousBlocks):
(WebCore::RenderBlock::collapseAnonymousBoxChild):
(WebCore::RenderBlock::removeChild):
(WebCore::canMergeAnonymousBlock): Deleted.
* rendering/RenderBlock.h:
* rendering/RenderElement.cpp:
(WebCore::RenderElement::removeAnonymousWrappersForInlinesIfNecessary):

LayoutTests:

* fast/block/collapse-anon-block-with-float-siblings-only-expected.html: Added.
* fast/block/collapse-anon-block-with-float-siblings-only.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@191610 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/fast/block/collapse-anon-block-with-float-siblings-only-expected.html [new file with mode: 0644]
LayoutTests/fast/block/collapse-anon-block-with-float-siblings-only.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/rendering/RenderBlock.cpp
Source/WebCore/rendering/RenderBlock.h
Source/WebCore/rendering/RenderBlockFlow.h
Source/WebCore/rendering/RenderDeprecatedFlexibleBox.h
Source/WebCore/rendering/RenderElement.cpp
Source/WebCore/rendering/RenderFlexibleBox.h
Source/WebCore/rendering/RenderGrid.h

index a2e0d71..2b996b0 100644 (file)
@@ -1,3 +1,15 @@
+2015-10-26  Zalan Bujtas  <zalan@apple.com>
+
+        Floating box is misplaced after content change.
+        https://bugs.webkit.org/show_bug.cgi?id=150271
+
+        Reviewed by David Hyatt.
+
+        Collapse anonymous block when as the result of a sibling removal only floating siblings are left.
+
+        * fast/block/collapse-anon-block-with-float-siblings-only-expected.html: Added.
+        * fast/block/collapse-anon-block-with-float-siblings-only.html: Added.
+
 2015-10-26  Jiewen Tan  <jiewen_tan@apple.com>
 
         Null dereference loading Blink layout test editing/execCommand/crash-replacing-list-by-list.html
diff --git a/LayoutTests/fast/block/collapse-anon-block-with-float-siblings-only-expected.html b/LayoutTests/fast/block/collapse-anon-block-with-float-siblings-only-expected.html
new file mode 100644 (file)
index 0000000..059071d
--- /dev/null
@@ -0,0 +1,8 @@
+<!DOCTYPE HTML>
+<head>
+<title>This tests that floating box is properly positioned after removing sibling block content.</title>
+</head>
+<body>
+should not wrap
+</body>
+</html>
diff --git a/LayoutTests/fast/block/collapse-anon-block-with-float-siblings-only.html b/LayoutTests/fast/block/collapse-anon-block-with-float-siblings-only.html
new file mode 100644 (file)
index 0000000..09ec8ef
--- /dev/null
@@ -0,0 +1,23 @@
+<!DOCTYPE HTML>
+<head>
+<title>This tests that floating box is properly positioned after removing sibling block content.</title>
+<style>
+       .floating {
+       float: left;
+       }
+</style>
+</head>
+<body>
+<span>wrap</span><div id=removeThis></div><div class="floating">should not&nbsp</div>
+<script>
+       if (window.testRunner)
+               testRunner.waitUntilDone();
+       setTimeout(function() { 
+               var ele = document.getElementById("removeThis"); 
+               ele.parentNode.removeChild(ele);
+               if (window.testRunner)
+                       testRunner.notifyDone(); 
+       }, 0);
+</script>
+</body>
+</html>
index 6c2c614..9f57ede 100644 (file)
@@ -1,3 +1,24 @@
+2015-10-26  Zalan Bujtas  <zalan@apple.com>
+
+        Floating box is misplaced after content change.
+        https://bugs.webkit.org/show_bug.cgi?id=150271
+
+        Reviewed by David Hyatt.
+
+        Collapse anonymous block when as the result of a sibling removal only floating siblings are left.
+
+        Test: fast/block/collapse-anon-block-with-float-siblings-only.html
+
+        * rendering/RenderBlock.cpp:
+        (WebCore::canCollapseAnonymousBlock):
+        (WebCore::canMergeContiguousAnonymousBlocks):
+        (WebCore::RenderBlock::collapseAnonymousBoxChild):
+        (WebCore::RenderBlock::removeChild):
+        (WebCore::canMergeAnonymousBlock): Deleted.
+        * rendering/RenderBlock.h:
+        * rendering/RenderElement.cpp:
+        (WebCore::RenderElement::removeAnonymousWrappersForInlinesIfNecessary):
+
 2015-10-26  Jiewen Tan  <jiewen_tan@apple.com>
 
         Null dereference loading Blink layout test editing/execCommand/crash-replacing-list-by-list.html
index d5c8ab2..84b1fca 100644 (file)
@@ -637,7 +637,7 @@ void RenderBlock::removeLeftoverAnonymousBlock(RenderBlock* child)
     child->destroy();
 }
 
-static bool canMergeAnonymousBlock(RenderBlock& anonymousBlock)
+static bool canDropAnonymousBlock(const RenderBlock& anonymousBlock)
 {
     if (anonymousBlock.beingDestroyed() || anonymousBlock.continuation())
         return false;
@@ -655,33 +655,32 @@ static bool canMergeContiguousAnonymousBlocks(RenderObject& oldChild, RenderObje
         if (!previous->isAnonymousBlock())
             return false;
         RenderBlock& previousAnonymousBlock = downcast<RenderBlock>(*previous);
-        if (!canMergeAnonymousBlock(previousAnonymousBlock))
+        if (!canDropAnonymousBlock(previousAnonymousBlock))
             return false;
     }
     if (next) {
         if (!next->isAnonymousBlock())
             return false;
         RenderBlock& nextAnonymousBlock = downcast<RenderBlock>(*next);
-        if (!canMergeAnonymousBlock(nextAnonymousBlock))
+        if (!canDropAnonymousBlock(nextAnonymousBlock))
             return false;
     }
     return true;
 }
 
-void RenderBlock::collapseAnonymousBoxChild(RenderBlock& parent, RenderBlock* child)
+void RenderBlock::dropAnonymousBoxChild(RenderBlock& parent, RenderBlock& child)
 {
     parent.setNeedsLayoutAndPrefWidthsRecalc();
-    parent.setChildrenInline(child->childrenInline());
-    RenderObject* nextSibling = child->nextSibling();
+    parent.setChildrenInline(child.childrenInline());
+    if (auto* childFlowThread = child.flowThreadContainingBlock())
+        childFlowThread->removeFlowChildInfo(&child);
 
-    if (auto* childFlowThread = child->flowThreadContainingBlock())
-        childFlowThread->removeFlowChildInfo(child);
-
-    parent.removeChildInternal(*child, child->hasLayer() ? NotifyChildren : DontNotifyChildren);
-    child->moveAllChildrenTo(&parent, nextSibling, child->hasLayer());
+    RenderObject* nextSibling = child.nextSibling();
+    parent.removeChildInternal(child, child.hasLayer() ? NotifyChildren : DontNotifyChildren);
+    child.moveAllChildrenTo(&parent, nextSibling, child.hasLayer());
     // Delete the now-empty block's lines and nuke it.
-    child->deleteLines();
-    child->destroy();
+    child.deleteLines();
+    child.destroy();
 }
 
 void RenderBlock::removeChild(RenderObject& oldChild)
@@ -746,19 +745,26 @@ void RenderBlock::removeChild(RenderObject& oldChild)
     RenderBox::removeChild(oldChild);
 
     RenderObject* child = prev ? prev : next;
-    if (canMergeAnonymousBlocks && child && !child->previousSibling() && !child->nextSibling() && canCollapseAnonymousBlockChild()) {
+    if (canMergeAnonymousBlocks && child && !child->previousSibling() && !child->nextSibling() && canDropAnonymousBlockChild()) {
         // The removal has knocked us down to containing only a single anonymous
         // box. We can pull the content right back up into our box.
-        collapseAnonymousBoxChild(*this, downcast<RenderBlock>(child));
-    } else if (((prev && prev->isAnonymousBlock()) || (next && next->isAnonymousBlock())) && canCollapseAnonymousBlockChild()) {
+        dropAnonymousBoxChild(*this, downcast<RenderBlock>(*child));
+    } else if (((prev && prev->isAnonymousBlock()) || (next && next->isAnonymousBlock())) && canDropAnonymousBlockChild()) {
         // 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 = downcast<RenderBlock>((prev && prev->isAnonymousBlock()) ? prev : next);
-        if ((anonBlock->previousSibling() || anonBlock->nextSibling())
-            && (!anonBlock->previousSibling() || (anonBlock->previousSibling()->style().styleType() != NOPSEUDO && anonBlock->previousSibling()->isFloating() && !anonBlock->previousSibling()->previousSibling()))
-            && (!anonBlock->nextSibling() || (anonBlock->nextSibling()->style().styleType() != NOPSEUDO && anonBlock->nextSibling()->isFloating() && !anonBlock->nextSibling()->nextSibling()))) {
-            collapseAnonymousBoxChild(*this, anonBlock);
+        // block with floating siblings.
+        RenderBlock& anonBlock = downcast<RenderBlock>((prev && prev->isAnonymousBlock()) ? *prev : *next);
+        if (canDropAnonymousBlock(anonBlock)) {
+            bool dropAnonymousBlock = true;
+            for (auto& sibling : childrenOfType<RenderObject>(*this)) {
+                if (&sibling == &anonBlock)
+                    continue;
+                if (!sibling.isFloating()) {
+                    dropAnonymousBlock = false;
+                    break;
+                }
+            }
+            if (dropAnonymousBlock)
+                dropAnonymousBoxChild(*this, anonBlock);
         }
     }
 
index f3d5a10..5bd2e2d 100644 (file)
@@ -195,7 +195,7 @@ public:
 
     static RenderBlock* createAnonymousWithParentRendererAndDisplay(const RenderObject*, EDisplay = BLOCK);
     RenderBlock* createAnonymousBlock(EDisplay display = BLOCK) const { return createAnonymousWithParentRendererAndDisplay(this, display); }
-    static void collapseAnonymousBoxChild(RenderBlock& parent, RenderBlock* child);
+    static void dropAnonymousBoxChild(RenderBlock& parent, RenderBlock& child);
 
     virtual RenderBox* createAnonymousBoxWithSameTypeAs(const RenderObject* parent) const override;
 
@@ -300,7 +300,7 @@ public:
     virtual void updateHitTestResult(HitTestResult&, const LayoutPoint&) override;
 
     virtual bool canHaveChildren() const override { return true; }
-    virtual bool canCollapseAnonymousBlockChild() const { return true; }
+    virtual bool canDropAnonymousBlockChild() const { return true; }
 
     RenderFlowThread* cachedFlowThreadContainingBlock() const;
     void setCachedFlowThreadContainingBlockNeedsUpdate();
index aa0658a..4099e38 100644 (file)
@@ -277,7 +277,7 @@ public:
     }
     void layoutLineGridBox();
 
-    virtual bool canCollapseAnonymousBlockChild() const override { return !renderNamedFlowFragment(); }
+    virtual bool canDropAnonymousBlockChild() const override { return !renderNamedFlowFragment(); }
     RenderNamedFlowFragment* renderNamedFlowFragment() const { return hasRareBlockFlowData() ? rareBlockFlowData()->m_renderNamedFlowFragment : nullptr; }
     void setRenderNamedFlowFragment(RenderNamedFlowFragment*);
 
index 2dd01f7..daac92e 100644 (file)
@@ -47,7 +47,7 @@ public:
     bool isStretchingChildren() const { return m_stretchingChildren; }
 
     virtual bool avoidsFloats() const override { return true; }
-    virtual bool canCollapseAnonymousBlockChild() const override { return false; }
+    virtual bool canDropAnonymousBlockChild() const override { return false; }
 
     void placeChild(RenderBox* child, const LayoutPoint& location, LayoutSize* childLayoutDelta = nullptr);
 
index 95817f0..e70038e 100644 (file)
@@ -953,7 +953,7 @@ void RenderElement::handleDynamicFloatPositionChange()
 void RenderElement::removeAnonymousWrappersForInlinesIfNecessary()
 {
     RenderBlock& parentBlock = downcast<RenderBlock>(*parent());
-    if (!parentBlock.canCollapseAnonymousBlockChild())
+    if (!parentBlock.canDropAnonymousBlockChild())
         return;
 
     // We have changed to floated or out-of-flow positioning so maybe all our parent's
@@ -972,7 +972,7 @@ void RenderElement::removeAnonymousWrappersForInlinesIfNecessary()
     for (current = parent()->firstChild(); current; current = next) {
         next = current->nextSibling();
         if (current->isAnonymousBlock())
-            parentBlock.collapseAnonymousBoxChild(parentBlock, downcast<RenderBlock>(current));
+            parentBlock.dropAnonymousBoxChild(parentBlock, downcast<RenderBlock>(*current));
     }
 }
 
index 364fb8c..9bae316 100644 (file)
@@ -45,7 +45,7 @@ public:
     virtual const char* renderName() const override;
 
     virtual bool avoidsFloats() const override final { return true; }
-    virtual bool canCollapseAnonymousBlockChild() const override final { return false; }
+    virtual bool canDropAnonymousBlockChild() const override final { return false; }
     virtual void layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalHeight = 0) override final;
 
     virtual int baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const override;
index 4b1d1a2..0c40e07 100644 (file)
@@ -55,7 +55,7 @@ public:
     virtual void layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalHeight = 0) override;
 
     virtual bool avoidsFloats() const override { return true; }
-    virtual bool canCollapseAnonymousBlockChild() const override { return false; }
+    virtual bool canDropAnonymousBlockChild() const override { return false; }
 
     const Vector<LayoutUnit>& columnPositions() const { return m_columnPositions; }
     const Vector<LayoutUnit>& rowPositions() const { return m_rowPositions; }