Diff
Modified: trunk/LayoutTests/ChangeLog (174760 => 174761)
--- trunk/LayoutTests/ChangeLog 2014-10-16 06:45:53 UTC (rev 174760)
+++ trunk/LayoutTests/ChangeLog 2014-10-16 06:50:30 UTC (rev 174761)
@@ -1,3 +1,18 @@
+2014-10-15 Andrei Bucur <[email protected]>
+
+ ASSERTION FAILED in WebCore::RenderFlowThread::getRegionRangeForBox
+ https://bugs.webkit.org/show_bug.cgi?id=135563
+
+ Reviewed by David Hyatt.
+
+ A test verifying that positioned elements inside multi-column containers don't
+ cause assertions or crashes.
+
+ * fast/multicol/multicol-all-positioned-crash-expected.txt: Added.
+ * fast/multicol/multicol-all-positioned-crash.html: Added.
+ * fast/multicol/multicol-transform-containing-block-expected.txt: Added.
+ * fast/multicol/multicol-transform-containing-block.html: Added.
+
2014-10-15 Commit Queue <[email protected]>
Unreviewed, rolling out r174753.
Added: trunk/LayoutTests/fast/multicol/multicol-all-positioned-crash-expected.txt (0 => 174761)
--- trunk/LayoutTests/fast/multicol/multicol-all-positioned-crash-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/multicol/multicol-all-positioned-crash-expected.txt 2014-10-16 06:50:30 UTC (rev 174761)
@@ -0,0 +1 @@
+Test for the bug 135563. It should not crash or assert.
Added: trunk/LayoutTests/fast/multicol/multicol-all-positioned-crash.html (0 => 174761)
--- trunk/LayoutTests/fast/multicol/multicol-all-positioned-crash.html (rev 0)
+++ trunk/LayoutTests/fast/multicol/multicol-all-positioned-crash.html 2014-10-16 06:50:30 UTC (rev 174761)
@@ -0,0 +1,17 @@
+<html>
+<head>
+<style>
+* {
+ -webkit-columns: 2;
+ position: absolute;
+}
+</style>
+</head>
+<body>
+Test for <a href="" bug 135563</a>. It should not crash or assert.
+<script>
+if (window.testRunner)
+ window.testRunner.dumpAsText();
+</script>
+</body>
+</html>
Added: trunk/LayoutTests/fast/multicol/multicol-transform-containing-block-expected.txt (0 => 174761)
--- trunk/LayoutTests/fast/multicol/multicol-transform-containing-block-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/multicol/multicol-transform-containing-block-expected.txt 2014-10-16 06:50:30 UTC (rev 174761)
@@ -0,0 +1 @@
+Test for b135563. It should not crash or assert.
Added: trunk/LayoutTests/fast/multicol/multicol-transform-containing-block.html (0 => 174761)
--- trunk/LayoutTests/fast/multicol/multicol-transform-containing-block.html (rev 0)
+++ trunk/LayoutTests/fast/multicol/multicol-transform-containing-block.html 2014-10-16 06:50:30 UTC (rev 174761)
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<html>
+<style>
+ #pos {
+ position: absolute;
+ top: 10px;
+ left: 10px;
+ }
+
+ .multicol {
+ -webkit-column-count: 2;
+ height: 300px;
+ }
+
+ #transformed {
+ background: red;
+ width: 10px;
+ height: 10px;
+ }
+
+ .update {
+ -webkit-transform: rotate(-10deg);
+ }
+
+ .parent {
+ height: 400px;
+ }
+
+ .container {
+ padding: 50px;
+ margin: 20px;
+ }
+</style>
+<body>
+<div class="multicol parent">
+ <div id="change" class="container">
+ <div class="multicol">
+ <div>Static</div>
+ <div>Static</div>
+ <div>Static</div>
+ <div id="pos">Positioned</div>
+ <div>Static</div>
+ <div>Static</div>
+ </div>
+ </div>
+</div>
+<script type="text/_javascript_">
+ if (window.testRunner)
+ window.testRunner.dumpAsText();
+
+ document.body.offsetTop;
+ document.getElementById("change").className += " update";
+ document.body.offsetTop;
+ document.body.innerHTML = "Test for b135563. It should not crash or assert.";
+</script>
+</body>
+</html>
Modified: trunk/Source/WebCore/ChangeLog (174760 => 174761)
--- trunk/Source/WebCore/ChangeLog 2014-10-16 06:45:53 UTC (rev 174760)
+++ trunk/Source/WebCore/ChangeLog 2014-10-16 06:50:30 UTC (rev 174761)
@@ -1,3 +1,100 @@
+2014-10-15 Andrei Bucur <[email protected]>
+
+ ASSERTION FAILED in WebCore::RenderFlowThread::getRegionRangeForBox
+ https://bugs.webkit.org/show_bug.cgi?id=135563
+
+ Reviewed by David Hyatt.
+
+ The new multi-column code doesn't work correctly when the document contains nested fragmentation
+ contexts. The problem is the current flow thread concept that can store only one RenderFlowThread
+ at a time and use it during layout.
+
+ The stored flow thread is always correct for regions because named flow threads are absolutley positioned
+ so every child renderer is contained inside them (with the expcetion of fixed positioned elements which are
+ treated separately).
+
+ For multi-column elements this is no longer the case. An absolutely positioned element inside a static
+ multi-column element will be contained by a block outside the fragmentation context. It can even be
+ contained by a different multi-column element in the case of nested flow threads.
+
+ The patch below explores a solution that's not based on a current flow thread stored globally. The proposed
+ patch makes every block to store a pointer to its fragmentation context and a flag that states if this pointer
+ needs to be updated or not. If the renderer is not a block it will get its flow thread from the containing
+ block. Once the containing flow thread is requested for the block, the pointer is computed and cached until
+ invalidated:
+ - when a subtree is removed from a flow thread
+ - when the position property of an element inside a flow thread changes
+
+ The process is recursive and it doesn't affect elements that are not nested inside a flow thread. If a block
+ changes position from relative to static, any element that was contained by it can only be contained by an
+ ancestor of the block. This ancestor will still be outside of any flow thread. This ensures that non-fragmentation
+ code is not affected from a performance perspective.
+
+ The patch affects the results of the performance tests:
+ - the regions layout tests have a decreased performance raging from 2% to 5-6%
+ - the regions selection tests have an increased performance raging from 1-2% to 10%
+ - the multicolumn layout tests (now pending review in b137687) have an increased performance
+ raging from 1.8% to 5%
+
+ Tests: fast/multicol/multicol-all-positioned-crash.html
+ fast/multicol/multicol-transform-containing-block.html
+
+ * rendering/FlowThreadController.cpp:
+ (WebCore::FlowThreadController::FlowThreadController):
+ * rendering/FlowThreadController.h:
+ (WebCore::FlowThreadController::currentRenderFlowThread): Deleted.
+ (WebCore::FlowThreadController::setCurrentRenderFlowThread): Deleted.
+ * rendering/LayoutState.h:
+ (WebCore::LayoutState::currentRenderFlowThread):
+ (WebCore::LayoutState::setCurrentRenderFlowThread):
+ * rendering/RenderBlock.cpp:
+ (WebCore::RenderBlockRareData::RenderBlockRareData):
+ (WebCore::RenderBlock::styleWillChange):
+ (WebCore::RenderBlock::styleDidChange):
+ (WebCore::RenderBlock::collapseAnonymousBoxChild):
+ (WebCore::RenderBlock::cachedFlowThreadContainingBlock):
+ (WebCore::RenderBlock::cachedFlowThreadContainingBlockNeedsUpdate):
+ (WebCore::RenderBlock::setCachedFlowThreadContainingBlockNeedsUpdate):
+ (WebCore::RenderBlock::updateCachedFlowThreadContainingBlock):
+ (WebCore::RenderBlock::locateFlowThreadContainingBlock):
+ * rendering/RenderBlock.h:
+ * rendering/RenderBlockFlow.cpp:
+ (WebCore::RenderBlockFlow::styleWillChange):
+ * rendering/RenderBox.cpp:
+ (WebCore::RenderBox::borderBoxRectInRegion):
+ * rendering/RenderFlowThread.cpp:
+ (WebCore::RenderFlowThread::layout):
+ (WebCore::RenderFlowThread::updateAllLayerToRegionMappings):
+ (WebCore::RenderFlowThread::repaintRectangleInRegions):
+ (WebCore::CurrentRenderFlowThreadMaintainer::CurrentRenderFlowThreadMaintainer): Deleted.
+ (WebCore::CurrentRenderFlowThreadMaintainer::~CurrentRenderFlowThreadMaintainer): Deleted.
+ (WebCore::CurrentRenderFlowThreadDisabler::CurrentRenderFlowThreadDisabler): Deleted.
+ (WebCore::CurrentRenderFlowThreadDisabler::~CurrentRenderFlowThreadDisabler): Deleted.
+ * rendering/RenderFlowThread.h:
+ * rendering/RenderLayer.cpp:
+ (WebCore::RenderLayer::paintLayer):
+ (WebCore::RenderLayer::hitTestLayer):
+ (WebCore::RenderLayer::mapLayerClipRectsToFragmentationLayer):
+ (WebCore::RenderLayer::calculateClipRects):
+ * rendering/RenderObject.cpp:
+ (WebCore::RenderObject::showRegionsInformation):
+ (WebCore::RenderObject::insertedIntoTree):
+ (WebCore::RenderObject::removeFromRenderFlowThread):
+ (WebCore::RenderObject::removeFromRenderFlowThreadIncludingDescendants):
+ (WebCore::RenderObject::invalidateFlowThreadContainingBlockIncludingDescendants):
+ (WebCore::RenderObject::currentRenderNamedFlowFragment):
+ (WebCore::RenderObject::locateFlowThreadContainingBlock):
+ (WebCore::RenderObject::locateFlowThreadContainingBlockNoCache): Deleted.
+ (WebCore::RenderObject::removeFromRenderFlowThreadRecursive): Deleted.
+ * rendering/RenderObject.h:
+ (WebCore::RenderObject::flowThreadContainingBlock):
+ * rendering/RenderRegion.cpp:
+ (WebCore::RenderRegion::computeOverflowFromFlowThread):
+ * rendering/RenderView.cpp:
+ (WebCore::RenderView::pushLayoutStateForCurrentFlowThread):
+ (WebCore::RenderView::popLayoutStateForCurrentFlowThread):
+ * rendering/RenderView.h:
+
2014-10-15 Chris Dumez <[email protected]>
Use is<>() / downcast<>() for list-related render objects
Modified: trunk/Source/WebCore/rendering/FlowThreadController.cpp (174760 => 174761)
--- trunk/Source/WebCore/rendering/FlowThreadController.cpp 2014-10-16 06:45:53 UTC (rev 174760)
+++ trunk/Source/WebCore/rendering/FlowThreadController.cpp 2014-10-16 06:50:30 UTC (rev 174761)
@@ -42,7 +42,6 @@
FlowThreadController::FlowThreadController(RenderView* view)
: m_view(view)
- , m_currentRenderFlowThread(0)
, m_isRenderNamedFlowThreadOrderDirty(false)
, m_flowThreadsWithAutoLogicalHeightRegions(0)
{
Modified: trunk/Source/WebCore/rendering/FlowThreadController.h (174760 => 174761)
--- trunk/Source/WebCore/rendering/FlowThreadController.h 2014-10-16 06:45:53 UTC (rev 174760)
+++ trunk/Source/WebCore/rendering/FlowThreadController.h 2014-10-16 06:50:30 UTC (rev 174761)
@@ -48,9 +48,6 @@
explicit FlowThreadController(RenderView*);
~FlowThreadController();
- RenderFlowThread* currentRenderFlowThread() const { return m_currentRenderFlowThread; }
- void setCurrentRenderFlowThread(RenderFlowThread* flowThread) { m_currentRenderFlowThread = flowThread; }
-
bool isRenderNamedFlowThreadOrderDirty() const { return m_isRenderNamedFlowThreadOrderDirty; }
void setIsRenderNamedFlowThreadOrderDirty(bool dirty)
{
@@ -96,7 +93,6 @@
private:
RenderView* m_view;
- RenderFlowThread* m_currentRenderFlowThread;
bool m_isRenderNamedFlowThreadOrderDirty;
unsigned m_flowThreadsWithAutoLogicalHeightRegions;
std::unique_ptr<RenderNamedFlowThreadList> m_renderNamedFlowThreadList;
Modified: trunk/Source/WebCore/rendering/LayoutState.h (174760 => 174761)
--- trunk/Source/WebCore/rendering/LayoutState.h 2014-10-16 06:45:53 UTC (rev 174760)
+++ trunk/Source/WebCore/rendering/LayoutState.h 2014-10-16 06:50:30 UTC (rev 174761)
@@ -83,6 +83,10 @@
void setLineGridPaginationOrigin(const LayoutSize& origin) { m_lineGridPaginationOrigin = origin; }
bool needsBlockDirectionLocationSetBeforeLayout() const { return m_lineGrid || (m_isPaginated && m_pageLogicalHeight); }
+
+ RenderFlowThread* currentRenderFlowThread() const { return m_currentRenderFlowThread; }
+ void setCurrentRenderFlowThread(RenderFlowThread* flowThread) { m_currentRenderFlowThread = flowThread; }
+
private:
void propagateLineGridInfo(RenderBox*);
void establishLineGrid(RenderBlockFlow*);
@@ -122,6 +126,8 @@
LayoutSize m_lineGridOffset;
LayoutSize m_lineGridPaginationOrigin;
+ RenderFlowThread* m_currentRenderFlowThread { nullptr };
+
#ifndef NDEBUG
RenderObject* m_renderer;
#endif
Modified: trunk/Source/WebCore/rendering/RenderBlock.cpp (174760 => 174761)
--- trunk/Source/WebCore/rendering/RenderBlock.cpp 2014-10-16 06:45:53 UTC (rev 174760)
+++ trunk/Source/WebCore/rendering/RenderBlock.cpp 2014-10-16 06:50:30 UTC (rev 174761)
@@ -68,7 +68,9 @@
#include "ShadowRoot.h"
#include "TextBreakIterator.h"
#include "TransformState.h"
+
#include <wtf/NeverDestroyed.h>
+#include <wtf/Optional.h>
#include <wtf/StackStats.h>
#include <wtf/TemporaryChange.h>
@@ -94,7 +96,7 @@
static TrackedContainerMap* gPositionedContainerMap = 0;
static TrackedContainerMap* gPercentHeightContainerMap = 0;
-
+
typedef HashMap<RenderBlock*, std::unique_ptr<ListHashSet<RenderInline*>>> ContinuationOutlineTableMap;
struct UpdateScrollInfoAfterLayoutTransaction {
@@ -121,14 +123,17 @@
struct RenderBlockRareData {
WTF_MAKE_NONCOPYABLE(RenderBlockRareData); WTF_MAKE_FAST_ALLOCATED;
public:
- RenderBlockRareData()
+ RenderBlockRareData()
: m_paginationStrut(0)
, m_pageLogicalOffset(0)
- {
+ , m_flowThreadContainingBlock(Nullopt)
+ {
}
LayoutUnit m_paginationStrut;
LayoutUnit m_pageLogicalOffset;
+
+ Optional<RenderFlowThread*> m_flowThreadContainingBlock;
};
typedef HashMap<const RenderBlock*, std::unique_ptr<RenderBlockRareData>> RenderBlockRareDataMap;
@@ -266,7 +271,7 @@
const RenderStyle* oldStyle = hasInitializedStyle() ? &style() : nullptr;
setReplaced(newStyle.isDisplayInlineType());
-
+
if (oldStyle && parent() && diff == StyleDifferenceLayout && oldStyle->position() != newStyle.position()) {
if (newStyle.position() == StaticPosition)
// Clear our positioned objects list. Our absolutely positioned descendants will be
@@ -283,7 +288,7 @@
}
containingBlock = containingBlock->parent();
}
-
+
if (is<RenderBlock>(*containingBlock))
downcast<RenderBlock>(*containingBlock).removePositionedObjects(this, NewContainingBlock);
}
@@ -308,10 +313,20 @@
void RenderBlock::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
- RenderBox::styleDidChange(diff, oldStyle);
-
RenderStyle& newStyle = style();
+ bool hadTransform = hasTransform();
+ bool flowThreadContainingBlockInvalidated = false;
+ if (oldStyle && oldStyle->position() != newStyle.position()) {
+ invalidateFlowThreadContainingBlockIncludingDescendants();
+ flowThreadContainingBlockInvalidated = true;
+ }
+
+ RenderBox::styleDidChange(diff, oldStyle);
+
+ if (hadTransform != hasTransform() && !flowThreadContainingBlockInvalidated)
+ invalidateFlowThreadContainingBlockIncludingDescendants();
+
if (!isAnonymousBlock()) {
// Ensure that all of our continuation blocks pick up the new style.
for (RenderBlock* currCont = blockElementContinuation(); currCont; currCont = currCont->blockElementContinuation()) {
@@ -324,7 +339,7 @@
propagateStyleToAnonymousChildren(PropagateToBlockChildrenOnly);
m_lineHeight = -1;
-
+
// It's possible for our border/padding to change, but for the overall logical width of the block to
// end up being the same. We keep track of this change so in layoutBlock, we can know to set relayoutChildren=true.
m_hasBorderOrPaddingLogicalWidthChanged = oldStyle && diff == StyleDifferenceLayout && needsLayout() && borderOrPaddingLogicalWidthChanged(oldStyle, &newStyle);
@@ -690,7 +705,6 @@
RenderObject* nextSibling = child->nextSibling();
RenderFlowThread* childFlowThread = child->flowThreadContainingBlock();
- CurrentRenderFlowThreadMaintainer flowThreadMaintainer(childFlowThread);
if (childFlowThread && childFlowThread->isRenderNamedFlowThread())
toRenderNamedFlowThread(childFlowThread)->removeFlowChildInfo(child);
@@ -3254,6 +3268,50 @@
createFirstLetterRenderer(firstLetterContainer, downcast<RenderText>(firstLetterObj));
}
+RenderFlowThread* RenderBlock::cachedFlowThreadContainingBlock() const
+{
+ RenderBlockRareData* rareData = getRareData(this);
+
+ if (!rareData || !rareData->m_flowThreadContainingBlock)
+ return nullptr;
+
+ return rareData->m_flowThreadContainingBlock.value();
+}
+
+bool RenderBlock::cachedFlowThreadContainingBlockNeedsUpdate() const
+{
+ RenderBlockRareData* rareData = getRareData(this);
+
+ if (!rareData || !rareData->m_flowThreadContainingBlock)
+ return true;
+
+ return false;
+}
+
+void RenderBlock::setCachedFlowThreadContainingBlockNeedsUpdate()
+{
+ RenderBlockRareData& rareData = ensureRareData(this);
+ rareData.m_flowThreadContainingBlock = Nullopt;
+}
+
+RenderFlowThread* RenderBlock::updateCachedFlowThreadContainingBlock(RenderFlowThread* flowThread) const
+{
+ RenderBlockRareData& rareData = ensureRareData(this);
+ rareData.m_flowThreadContainingBlock = flowThread;
+
+ return flowThread;
+}
+
+RenderFlowThread* RenderBlock::locateFlowThreadContainingBlock() const
+{
+ RenderBlockRareData* rareData = getRareData(this);
+ if (!rareData || !rareData->m_flowThreadContainingBlock)
+ return updateCachedFlowThreadContainingBlock(RenderBox::locateFlowThreadContainingBlock());
+
+ ASSERT(rareData->m_flowThreadContainingBlock.value() == RenderBox::locateFlowThreadContainingBlock());
+ return rareData->m_flowThreadContainingBlock.value();
+}
+
LayoutUnit RenderBlock::paginationStrut() const
{
RenderBlockRareData* rareData = getRareData(this);
Modified: trunk/Source/WebCore/rendering/RenderBlock.h (174760 => 174761)
--- trunk/Source/WebCore/rendering/RenderBlock.h 2014-10-16 06:45:53 UTC (rev 174760)
+++ trunk/Source/WebCore/rendering/RenderBlock.h 2014-10-16 06:50:30 UTC (rev 174761)
@@ -312,7 +312,12 @@
virtual bool canHaveChildren() const override { return true; }
virtual bool canCollapseAnonymousBlockChild() const { return true; }
+ RenderFlowThread* cachedFlowThreadContainingBlock() const;
+ void setCachedFlowThreadContainingBlockNeedsUpdate();
+ virtual bool cachedFlowThreadContainingBlockNeedsUpdate() const;
+
protected:
+ virtual RenderFlowThread* locateFlowThreadContainingBlock() const override;
virtual void willBeDestroyed() override;
virtual void layout() override;
@@ -449,7 +454,7 @@
virtual LayoutRect rectWithOutlineForRepaint(const RenderLayerModelObject* repaintContainer, LayoutUnit outlineWidth) const override final;
virtual const RenderStyle& outlineStyleForRepaint() const override final;
-
+
virtual RenderElement* hoverAncestor() const override final;
virtual void updateDragState(bool dragOn) override final;
virtual void childBecameNonInline(RenderObject* child) override final;
@@ -489,6 +494,8 @@
RenderPtr<RenderBlock> clone() const;
RenderBlock* continuationBefore(RenderObject* beforeChild);
+ RenderFlowThread* updateCachedFlowThreadContainingBlock(RenderFlowThread*) const;
+
private:
bool hasRareData() const;
Modified: trunk/Source/WebCore/rendering/RenderBlockFlow.cpp (174760 => 174761)
--- trunk/Source/WebCore/rendering/RenderBlockFlow.cpp 2014-10-16 06:45:53 UTC (rev 174760)
+++ trunk/Source/WebCore/rendering/RenderBlockFlow.cpp 2014-10-16 06:50:30 UTC (rev 174761)
@@ -1985,18 +1985,10 @@
if (oldStyle) {
EPosition oldPosition = oldStyle->position();
EPosition newPosition = newStyle.position();
-
+
if (parent() && diff == StyleDifferenceLayout && oldPosition != newPosition) {
if (containsFloats() && !isFloating() && !isOutOfFlowPositioned() && newStyle.hasOutOfFlowPosition())
markAllDescendantsWithFloatsForLayout();
-
- // If this block is inside a multicol and is moving from in-flow positioning to out-of-flow positioning,
- // remove its info (such as lines-to-region mapping) from the flowthread because it won't be able to do it later.
- // The flowthread will no longer be in its containing block chain and, as such, flowThreadContainingBlock will return null.
- if (RenderFlowThread* flowThread = flowThreadContainingBlock(SkipFlowThreadCache)) {
- if (flowThread->isRenderMultiColumnFlowThread() && !isOutOfFlowPositioned() && (newPosition == AbsolutePosition || newPosition == FixedPosition))
- flowThread->removeFlowChildInfo(this);
- }
}
}
Modified: trunk/Source/WebCore/rendering/RenderBox.cpp (174760 => 174761)
--- trunk/Source/WebCore/rendering/RenderBox.cpp 2014-10-16 06:45:53 UTC (rev 174760)
+++ trunk/Source/WebCore/rendering/RenderBox.cpp 2014-10-16 06:50:30 UTC (rev 174761)
@@ -196,7 +196,7 @@
// FIXME: In a perfect world this condition should never happen.
return borderBoxRect();
}
-
+
ASSERT(flowThread->regionInRange(region, startRegion, endRegion));
// Compute the logical width and placement in this region.
@@ -207,21 +207,26 @@
// We have cached insets.
LayoutUnit logicalWidth = boxInfo->logicalWidth();
LayoutUnit logicalLeft = boxInfo->logicalLeft();
-
+
// Now apply the parent inset since it is cumulative whenever anything in the containing block chain shifts.
// FIXME: Doesn't work right with perpendicular writing modes.
const RenderBlock* currentBox = containingBlock();
- RenderBoxRegionInfo* currentBoxInfo = currentBox->renderBoxRegionInfo(region);
+ RenderBoxRegionInfo* currentBoxInfo = isRenderFlowThread() ? nullptr : currentBox->renderBoxRegionInfo(region);
while (currentBoxInfo && currentBoxInfo->isShifted()) {
if (currentBox->style().direction() == LTR)
logicalLeft += currentBoxInfo->logicalLeft();
else
logicalLeft -= (currentBox->logicalWidth() - currentBoxInfo->logicalWidth()) - currentBoxInfo->logicalLeft();
+
+ // Once we reach the fragmentation container we should stop.
+ if (currentBox->isRenderFlowThread())
+ break;
+
currentBox = currentBox->containingBlock();
region = currentBox->clampToStartAndEndRegions(region);
currentBoxInfo = currentBox->renderBoxRegionInfo(region);
}
-
+
if (cacheFlag == DoNotCacheRenderBoxRegionInfo)
delete boxInfo;
Modified: trunk/Source/WebCore/rendering/RenderFlowThread.cpp (174760 => 174761)
--- trunk/Source/WebCore/rendering/RenderFlowThread.cpp 2014-10-16 06:45:53 UTC (rev 174760)
+++ trunk/Source/WebCore/rendering/RenderFlowThread.cpp 2014-10-16 06:50:30 UTC (rev 174761)
@@ -197,7 +197,6 @@
validateRegions();
- CurrentRenderFlowThreadMaintainer currentFlowThreadSetter(this);
RenderBlockFlow::layout();
m_pageLogicalSizeChanged = false;
@@ -288,10 +287,6 @@
if (!collectsGraphicsLayersUnderRegions())
return false;
- // We can't use currentFlowThread as it is possible to have interleaved flow threads and the wrong one could be used.
- // Let each region figure out the proper enclosing flow thread.
- CurrentRenderFlowThreadDisabler disabler(&view());
-
// If the RenderFlowThread had a z-index layer update, then we need to update the composited layers too.
bool needsLayerUpdate = layer()->isDirtyRenderFlowThread() || m_layersToRegionMappingsDirty || !m_layerToRegionMap.get();
layer()->updateLayerListsIfNeeded();
@@ -388,10 +383,6 @@
LayoutStateDisabler layoutStateDisabler(&view()); // We can't use layout state to repaint, since the regions are somewhere else.
- // We can't use currentFlowThread as it is possible to have interleaved flow threads and the wrong one could be used.
- // Let each region figure out the proper enclosing flow thread.
- CurrentRenderFlowThreadDisabler disabler(&view());
-
for (auto& region : m_regionList)
region->repaintFlowThreadContent(repaintRect);
}
@@ -1522,42 +1513,5 @@
return *m_lineToRegionMap.get();
}
-CurrentRenderFlowThreadMaintainer::CurrentRenderFlowThreadMaintainer(RenderFlowThread* renderFlowThread)
- : m_renderFlowThread(renderFlowThread)
- , m_previousRenderFlowThread(0)
-{
- if (!m_renderFlowThread)
- return;
- FlowThreadController& controller = m_renderFlowThread->view().flowThreadController();
- m_previousRenderFlowThread = controller.currentRenderFlowThread();
- // Remove the assert so we can use this to change the flow thread context.
- // ASSERT(!m_previousRenderFlowThread || !renderFlowThread->isRenderNamedFlowThread());
- controller.setCurrentRenderFlowThread(m_renderFlowThread);
-}
-CurrentRenderFlowThreadMaintainer::~CurrentRenderFlowThreadMaintainer()
-{
- if (!m_renderFlowThread)
- return;
- FlowThreadController& controller = m_renderFlowThread->view().flowThreadController();
- ASSERT(controller.currentRenderFlowThread() == m_renderFlowThread);
- controller.setCurrentRenderFlowThread(m_previousRenderFlowThread);
-}
-
-CurrentRenderFlowThreadDisabler::CurrentRenderFlowThreadDisabler(RenderView* view)
- : m_view(view)
- , m_renderFlowThread(0)
-{
- m_renderFlowThread = m_view->flowThreadController().currentRenderFlowThread();
- if (m_renderFlowThread)
- view->flowThreadController().setCurrentRenderFlowThread(0);
-}
-
-CurrentRenderFlowThreadDisabler::~CurrentRenderFlowThreadDisabler()
-{
- if (m_renderFlowThread)
- m_view->flowThreadController().setCurrentRenderFlowThread(m_renderFlowThread);
-}
-
-
} // namespace WebCore
Modified: trunk/Source/WebCore/rendering/RenderFlowThread.h (174760 => 174761)
--- trunk/Source/WebCore/rendering/RenderFlowThread.h 2014-10-16 06:45:53 UTC (rev 174760)
+++ trunk/Source/WebCore/rendering/RenderFlowThread.h 2014-10-16 06:50:30 UTC (rev 174761)
@@ -231,6 +231,8 @@
ContainingRegionMap& containingRegionMap();
+ virtual bool cachedFlowThreadContainingBlockNeedsUpdate() const override { return false; }
+
// FIXME: Eventually as column and region flow threads start nesting, this may end up changing.
virtual bool shouldCheckColumnBreaks() const { return false; }
@@ -244,6 +246,8 @@
protected:
RenderFlowThread(Document&, PassRef<RenderStyle>);
+ virtual RenderFlowThread* locateFlowThreadContainingBlock() const override { return const_cast<RenderFlowThread*>(this); }
+
virtual const char* renderName() const = 0;
// Overridden by columns/pages to set up an initial logical width of the page width even when
@@ -374,26 +378,6 @@
RENDER_OBJECT_TYPE_CASTS(RenderFlowThread, isRenderFlowThread())
-class CurrentRenderFlowThreadMaintainer {
- WTF_MAKE_NONCOPYABLE(CurrentRenderFlowThreadMaintainer);
-public:
- CurrentRenderFlowThreadMaintainer(RenderFlowThread*);
- ~CurrentRenderFlowThreadMaintainer();
-private:
- RenderFlowThread* m_renderFlowThread;
- RenderFlowThread* m_previousRenderFlowThread;
-};
-
-class CurrentRenderFlowThreadDisabler {
- WTF_MAKE_NONCOPYABLE(CurrentRenderFlowThreadDisabler);
-public:
- CurrentRenderFlowThreadDisabler(RenderView*);
- ~CurrentRenderFlowThreadDisabler();
-private:
- RenderView* m_view;
- RenderFlowThread* m_renderFlowThread;
-};
-
// This structure is used by PODIntervalTree for debugging.
#ifndef NDEBUG
template <> struct ValueToString<RenderRegion*> {
Modified: trunk/Source/WebCore/rendering/RenderLayer.cpp (174760 => 174761)
--- trunk/Source/WebCore/rendering/RenderLayer.cpp 2014-10-16 06:45:53 UTC (rev 174760)
+++ trunk/Source/WebCore/rendering/RenderLayer.cpp 2014-10-16 06:50:30 UTC (rev 174761)
@@ -3771,12 +3771,6 @@
// Don't paint the layer if the renderer doesn't belong to this region.
// This is true as long as we clamp the range of a box to its containing block range.
-
- // Disable named flow region information for in flow threads such as multi-col.
- std::unique_ptr<CurrentRenderFlowThreadDisabler> flowThreadDisabler;
- if (enclosingPaginationLayer(ExcludeCompositedPaginatedLayers))
- flowThreadDisabler = std::make_unique<CurrentRenderFlowThreadDisabler>(&renderer().view());
-
RenderNamedFlowFragment* namedFlowFragment = currentRenderNamedFlowFragment();
if (namedFlowFragment) {
ASSERT(namedFlowFragment->isValid());
@@ -4821,11 +4815,6 @@
if (!isSelfPaintingLayer() && !hasSelfPaintingLayerDescendant())
return 0;
- // Disable named flow region information for in flow threads such as multi-col.
- std::unique_ptr<CurrentRenderFlowThreadDisabler> flowThreadDisabler;
- if (enclosingPaginationLayer(ExcludeCompositedPaginatedLayers))
- flowThreadDisabler = std::make_unique<CurrentRenderFlowThreadDisabler>(&renderer().view());
-
RenderNamedFlowFragment* namedFlowFragment = currentRenderNamedFlowFragment();
// Prevent hitting the fixed layers inside the flow thread when hitting through regions.
@@ -5232,8 +5221,7 @@
return false;
ASSERT(namedFlowFragment->parent() && namedFlowFragment->parent()->isRenderNamedFlowFragmentContainer());
-
- CurrentRenderFlowThreadDisabler flowThreadDisabler(&renderer().view());
+
ClipRectsContext targetClipRectsContext(&namedFlowFragment->fragmentContainerLayer(), TemporaryClipRects);
namedFlowFragment->fragmentContainerLayer().calculateClipRects(targetClipRectsContext, clipRects);
@@ -6710,7 +6698,6 @@
void RenderLayer::paintNamedFlowThreadInsideRegion(GraphicsContext* context, RenderNamedFlowFragment* region, LayoutRect paintDirtyRect, LayoutPoint paintOffset, PaintBehavior paintBehavior, PaintLayerFlags paintFlags)
{
LayoutRect regionContentBox = toRenderBox(region->layerOwner()).contentBoxRect();
- CurrentRenderFlowThreadMaintainer flowThreadMaintainer(toRenderFlowThread(&renderer()));
CurrentRenderRegionMaintainer regionMaintainer(*region);
region->setRegionObjectsRegionStyle();
@@ -6817,7 +6804,6 @@
hitTestRectInFlowThread.move(hitTestOffset);
hitTestRectInFlowThread.expand(LayoutSize(fabs((double)hitTestOffset.width()), fabs((double)hitTestOffset.height())));
- CurrentRenderFlowThreadMaintainer flowThreadMaintainer(flowThread);
CurrentRenderRegionMaintainer regionMaintainer(region);
HitTestResult tempResult(result.hitTestLocation());
Modified: trunk/Source/WebCore/rendering/RenderObject.cpp (174760 => 174761)
--- trunk/Source/WebCore/rendering/RenderObject.cpp 2014-10-16 06:45:53 UTC (rev 174760)
+++ trunk/Source/WebCore/rendering/RenderObject.cpp 2014-10-16 06:50:30 UTC (rev 174761)
@@ -522,38 +522,6 @@
return false;
}
-RenderFlowThread* RenderObject::locateFlowThreadContainingBlockNoCache() const
-{
- ASSERT(flowThreadState() != NotInsideFlowThread);
-
- RenderObject* curr = const_cast<RenderObject*>(this);
- while (curr) {
- if (curr->isRenderFlowThread())
- return toRenderFlowThread(curr);
- curr = curr->containingBlock();
- }
- return 0;
-}
-
-RenderFlowThread* RenderObject::locateFlowThreadContainingBlock() const
-{
- ASSERT(flowThreadState() != NotInsideFlowThread);
-
- // See if we have the thread cached because we're in the middle of layout.
- RenderFlowThread* flowThread = view().flowThreadController().currentRenderFlowThread();
- if (flowThread && (flowThreadState() == flowThread->flowThreadState())) {
- // Make sure the slow path would return the same result as our cache.
- // FIXME: For the moment, only apply this assertion to regions, as multicol
- // still has some issues and triggers this assert.
- // Created https://bugs.webkit.org/show_bug.cgi?id=132946 for this issue.
- ASSERT(!flowThread->isRenderNamedFlowThread() || flowThread == locateFlowThreadContainingBlockNoCache());
- return flowThread;
- }
-
- // Not in the middle of layout so have to find the thread the slow way.
- return locateFlowThreadContainingBlockNoCache();
-}
-
RenderBlock* RenderObject::firstLineBlock() const
{
return 0;
@@ -1438,8 +1406,6 @@
void RenderObject::showRegionsInformation() const
{
- CurrentRenderFlowThreadDisabler flowThreadDisabler(&view());
-
if (RenderFlowThread* flowThread = flowThreadContainingBlock()) {
const RenderBox* box = isBox() ? toRenderBox(this) : nullptr;
if (box) {
@@ -2048,17 +2014,9 @@
if (!isFloating() && parent()->childrenInline())
parent()->dirtyLinesFromChangedChild(*this);
-
- // We have to unset the current layout RenderFlowThread here, since insertedIntoTree() can happen in
- // the middle of layout but for objects inside a nested flow thread that is still being populated. This
- // will cause an accurate crawl to happen in order to ensure that the right flow thread is notified.
- RenderFlowThread* previousThread = view().flowThreadController().currentRenderFlowThread();
- view().flowThreadController().setCurrentRenderFlowThread(nullptr);
- if (parent()->isRenderFlowThread())
- toRenderFlowThread(parent())->flowThreadDescendantInserted(this);
- else if (RenderFlowThread* flowThread = parent()->flowThreadContainingBlock())
+
+ if (RenderFlowThread* flowThread = flowThreadContainingBlock())
flowThread->flowThreadDescendantInserted(this);
- view().flowThreadController().setCurrentRenderFlowThread(previousThread);
}
void RenderObject::willBeRemovedFromTree()
@@ -2075,27 +2033,56 @@
{
if (flowThreadState() == NotInsideFlowThread)
return;
-
+
// Sometimes we remove the element from the flow, but it's not destroyed at that time.
- // It's only until later when we actually destroy it and remove all the children from it.
+ // It's only until later when we actually destroy it and remove all the children from it.
// Currently, that happens for firstLetter elements and list markers.
// Pass in the flow thread so that we don't have to look it up for all the children.
- removeFromRenderFlowThreadRecursive(flowThreadContainingBlock());
+ removeFromRenderFlowThreadIncludingDescendants(true);
}
-void RenderObject::removeFromRenderFlowThreadRecursive(RenderFlowThread* renderFlowThread)
+void RenderObject::removeFromRenderFlowThreadIncludingDescendants(bool shouldUpdateState)
{
+ // Once we reach another flow thread we don't need to update the flow thread state
+ // but we have to continue cleanup the flow thread info.
+ if (isRenderFlowThread())
+ shouldUpdateState = false;
+
for (RenderObject* child = firstChildSlow(); child; child = child->nextSibling())
- child->removeFromRenderFlowThreadRecursive(renderFlowThread);
+ child->removeFromRenderFlowThreadIncludingDescendants(shouldUpdateState);
- RenderFlowThread* localFlowThread = renderFlowThread;
- if (flowThreadState() == InsideInFlowThread)
- localFlowThread = flowThreadContainingBlock(); // We have to ask. We can't just assume we are in the same flow thread.
- if (localFlowThread)
- localFlowThread->removeFlowChildInfo(this);
- setFlowThreadState(NotInsideFlowThread);
+ // We have to ask for our containing flow thread as it may be above the removed sub-tree.
+ RenderFlowThread* flowThreadContainingBlock = this->flowThreadContainingBlock();
+ if (flowThreadContainingBlock)
+ flowThreadContainingBlock->removeFlowChildInfo(this);
+ if (is<RenderBlock>(*this))
+ downcast<RenderBlock>(*this).setCachedFlowThreadContainingBlockNeedsUpdate();
+ if (shouldUpdateState)
+ setFlowThreadState(NotInsideFlowThread);
}
+void RenderObject::invalidateFlowThreadContainingBlockIncludingDescendants(RenderFlowThread* flowThread)
+{
+ if (flowThreadState() == NotInsideFlowThread)
+ return;
+
+ if (is<RenderBlock>(*this)) {
+ RenderBlock& block = downcast<RenderBlock>(*this);
+
+ if (block.cachedFlowThreadContainingBlockNeedsUpdate())
+ return;
+
+ flowThread = block.cachedFlowThreadContainingBlock();
+ block.setCachedFlowThreadContainingBlockNeedsUpdate();
+ }
+
+ if (flowThread)
+ flowThread->removeFlowChildInfo(this);
+
+ for (RenderObject* child = firstChildSlow(); child; child = child->nextSibling())
+ child->invalidateFlowThreadContainingBlockIncludingDescendants(flowThread);
+}
+
void RenderObject::destroyAndCleanupAnonymousWrappers()
{
// If the tree is destroyed, there is no need for a clean-up phase.
@@ -2597,24 +2584,24 @@
RenderNamedFlowFragment* RenderObject::currentRenderNamedFlowFragment() const
{
- if (flowThreadState() == NotInsideFlowThread)
+ RenderFlowThread* flowThread = flowThreadContainingBlock();
+ if (!flowThread || !flowThread->isRenderNamedFlowThread())
return nullptr;
- RenderFlowThread* flowThread = view().flowThreadController().currentRenderFlowThread();
- if (!flowThread)
- return nullptr;
-
- ASSERT(flowThread == flowThreadContainingBlock());
-
// FIXME: Once regions are fully integrated with the compositing system we should uncomment this assert.
// This assert needs to be disabled because it's possible to ask for the ancestor clipping rectangle of
// a layer without knowing the containing region in advance.
// ASSERT(flowThread->currentRegion() && flowThread->currentRegion()->isRenderNamedFlowFragment());
- RenderNamedFlowFragment* namedFlowFragment = toRenderNamedFlowFragment(flowThread->currentRegion());
- return namedFlowFragment;
+ return toRenderNamedFlowFragment(flowThread->currentRegion());
}
+RenderFlowThread* RenderObject::locateFlowThreadContainingBlock() const
+{
+ RenderBlock* containingBlock = this->containingBlock();
+ return containingBlock ? containingBlock->flowThreadContainingBlock() : nullptr;
+}
+
} // namespace WebCore
#ifndef NDEBUG
Modified: trunk/Source/WebCore/rendering/RenderObject.h (174760 => 174761)
--- trunk/Source/WebCore/rendering/RenderObject.h 2014-10-16 06:45:53 UTC (rev 174760)
+++ trunk/Source/WebCore/rendering/RenderObject.h 2014-10-16 06:50:30 UTC (rev 174761)
@@ -212,18 +212,14 @@
bool fixedPositionedWithNamedFlowContainingBlock() const;
- enum ShouldUseFlowThreadCache {
- UseFlowThreadCache,
- SkipFlowThreadCache
- };
-
// Function to return our enclosing flow thread if we are contained inside one. This
// function follows the containing block chain.
- RenderFlowThread* flowThreadContainingBlock(ShouldUseFlowThreadCache useCache = UseFlowThreadCache) const
+ RenderFlowThread* flowThreadContainingBlock() const
{
if (flowThreadState() == NotInsideFlowThread)
- return 0;
- return (useCache == SkipFlowThreadCache) ? locateFlowThreadContainingBlockNoCache() : locateFlowThreadContainingBlock();
+ return nullptr;
+
+ return locateFlowThreadContainingBlock();
}
RenderNamedFlowFragment* currentRenderNamedFlowFragment() const;
@@ -892,12 +888,12 @@
void setPosChildNeedsLayoutBit(bool b) { m_bitfields.setPosChildNeedsLayout(b); }
void setNeedsSimplifiedNormalFlowLayoutBit(bool b) { m_bitfields.setNeedsSimplifiedNormalFlowLayout(b); }
+ virtual RenderFlowThread* locateFlowThreadContainingBlock() const;
+ void invalidateFlowThreadContainingBlockIncludingDescendants(RenderFlowThread* = nullptr);
+
private:
- RenderFlowThread* locateFlowThreadContainingBlock() const;
- RenderFlowThread* locateFlowThreadContainingBlockNoCache() const;
-
void removeFromRenderFlowThread();
- void removeFromRenderFlowThreadRecursive(RenderFlowThread*);
+ void removeFromRenderFlowThreadIncludingDescendants(bool);
Color selectionColor(int colorProperty) const;
PassRefPtr<RenderStyle> selectionPseudoStyle() const;
Modified: trunk/Source/WebCore/rendering/RenderRegion.cpp (174760 => 174761)
--- trunk/Source/WebCore/rendering/RenderRegion.cpp 2014-10-16 06:45:53 UTC (rev 174760)
+++ trunk/Source/WebCore/rendering/RenderRegion.cpp 2014-10-16 06:50:30 UTC (rev 174761)
@@ -218,15 +218,8 @@
void RenderRegion::computeOverflowFromFlowThread()
{
ASSERT(isValid());
-
- LayoutRect layoutRect;
- {
- // When getting the overflow from the flow thread we need to temporarly reset the current flow thread because
- // we're changing flows.
- CurrentRenderFlowThreadMaintainer flowThreadMaintainer(m_flowThread);
- layoutRect = layoutOverflowRectForBox(m_flowThread);
- }
+ LayoutRect layoutRect = layoutOverflowRectForBox(m_flowThread);
layoutRect.setLocation(contentBoxRect().location() + (layoutRect.location() - m_flowThreadPortionRect.location()));
// FIXME: Correctly adjust the layout overflow for writing modes.
Modified: trunk/Source/WebCore/rendering/RenderView.cpp (174760 => 174761)
--- trunk/Source/WebCore/rendering/RenderView.cpp 2014-10-16 06:45:53 UTC (rev 174760)
+++ trunk/Source/WebCore/rendering/RenderView.cpp 2014-10-16 06:50:30 UTC (rev 174761)
@@ -1311,10 +1311,12 @@
if (!m_flowThreadController)
return;
- RenderFlowThread* currentFlowThread = m_flowThreadController->currentRenderFlowThread();
+ RenderFlowThread* currentFlowThread = object.flowThreadContainingBlock();
if (!currentFlowThread)
return;
+ m_layoutState->setCurrentRenderFlowThread(currentFlowThread);
+
currentFlowThread->pushFlowThreadLayoutState(object);
}
@@ -1323,7 +1325,7 @@
if (!m_flowThreadController)
return;
- RenderFlowThread* currentFlowThread = m_flowThreadController->currentRenderFlowThread();
+ RenderFlowThread* currentFlowThread = m_layoutState->currentRenderFlowThread();
if (!currentFlowThread)
return;
Modified: trunk/Source/WebCore/rendering/RenderView.h (174760 => 174761)
--- trunk/Source/WebCore/rendering/RenderView.h 2014-10-16 06:45:53 UTC (rev 174760)
+++ trunk/Source/WebCore/rendering/RenderView.h 2014-10-16 06:50:30 UTC (rev 174761)
@@ -295,7 +295,7 @@
void pushLayoutStateForCurrentFlowThread(const RenderObject&);
void popLayoutStateForCurrentFlowThread();
-
+
friend class LayoutStateMaintainer;
friend class LayoutStateDisabler;