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
+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
--- /dev/null
+<!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>
--- /dev/null
+<!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 </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>
+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
child->destroy();
}
-static bool canMergeAnonymousBlock(RenderBlock& anonymousBlock)
+static bool canDropAnonymousBlock(const RenderBlock& anonymousBlock)
{
if (anonymousBlock.beingDestroyed() || anonymousBlock.continuation())
return false;
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)
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);
}
}
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;
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();
}
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*);
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);
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
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));
}
}
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;
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; }