Chromium Code Reviews| Index: third_party/WebKit/Source/core/layout/LayoutObject.cpp |
| diff --git a/third_party/WebKit/Source/core/layout/LayoutObject.cpp b/third_party/WebKit/Source/core/layout/LayoutObject.cpp |
| index 87e07f5bf1700c7a5f5cc85c95d46bc1edcbe15b..937fb114b98b2ee56154021be5dc9c5abc7356bc 100644 |
| --- a/third_party/WebKit/Source/core/layout/LayoutObject.cpp |
| +++ b/third_party/WebKit/Source/core/layout/LayoutObject.cpp |
| @@ -42,6 +42,7 @@ |
| #include "core/frame/LocalFrame.h" |
| #include "core/frame/Settings.h" |
| #include "core/html/HTMLElement.h" |
| +#include "core/html/HTMLFrameOwnerElement.h" |
| #include "core/html/HTMLHtmlElement.h" |
| #include "core/html/HTMLTableCellElement.h" |
| #include "core/html/HTMLTableElement.h" |
| @@ -2577,39 +2578,65 @@ void LayoutObject::insertedIntoTree() { |
| flowThread->flowThreadDescendantWasInserted(this); |
| } |
| -enum FindReferencingScrollAnchorsBehavior { DontClear, Clear }; |
| - |
| -static bool findReferencingScrollAnchors( |
| - LayoutObject* layoutObject, |
| - FindReferencingScrollAnchorsBehavior behavior) { |
| +enum FindScrollAnchorsBehavior { FindReferencing, ClearReferencing, ClearAll }; |
| + |
| +// Returns true if scroller has layoutObject as its anchor. |
| +static bool clearScrollAnchorForScroller(ScrollableArea* scroller, |
|
ymalik
2016/10/06 19:51:13
@skobes, a note to make reviewing easier.
This fu
|
| + LayoutObject* layoutObject, |
| + FindScrollAnchorsBehavior behavior) { |
| + DCHECK(scroller); |
| + ScrollAnchor* anchor = scroller->scrollAnchor(); |
| + DCHECK(anchor); |
| + bool refersTo = false; |
| + if (anchor->refersTo(layoutObject)) { |
| + refersTo = true; |
| + if (behavior == FindReferencing) |
| + return refersTo; |
| + layoutObject->setIsScrollAnchorObject(false); |
| + anchor->releaseAnchor(); |
| + } else if (behavior == ClearAll && anchor->anchorObject()) { |
| + anchor->anchorObject()->setIsScrollAnchorObject(false); |
| + anchor->releaseAnchor(); |
| + } |
| + return refersTo; |
| +} |
| + |
| +// Returns true if any of scroller in the parent chain of layoutObject has |
| +// layoutObject as its anchor. If FindScrollAnchorsBehavior is ClearAll, all |
| +// the scrollers in the parent chain of layoutObject will have their scroll |
| +// anchor cleared. If FindScrollAnchorsBehavior is ClearReferencing, all the |
| +// scrollers in the parent chain of layoutObject that have layoutObject as their |
| +// anchor will have their scroll anchor cleared. |
| +static bool findScrollAnchors(LayoutObject* layoutObject, |
| + FindScrollAnchorsBehavior behavior) { |
| PaintLayer* layer = nullptr; |
| if (LayoutObject* parent = layoutObject->parent()) |
| layer = parent->enclosingLayer(); |
| bool found = false; |
| - // Walk up the layer tree to clear any scroll anchors that reference us. |
| + // Walk up the layer tree to clear scroll anchors if required. |
| while (layer) { |
| - if (PaintLayerScrollableArea* scrollableArea = layer->getScrollableArea()) { |
| - ScrollAnchor* anchor = scrollableArea->scrollAnchor(); |
| - DCHECK(anchor); |
| - if (anchor->refersTo(layoutObject)) { |
| - found = true; |
| - if (behavior == Clear) |
| - anchor->notifyRemoved(layoutObject); |
| - else |
| - return true; |
| - } |
| + if (PaintLayerScrollableArea* scroller = layer->getScrollableArea()) { |
| + found = clearScrollAnchorForScroller(scroller, layoutObject, behavior) || |
| + found; |
| + if (found && behavior == FindReferencing) |
| + return found; |
| } |
| layer = layer->parent(); |
| } |
| + |
| if (FrameView* view = layoutObject->frameView()) { |
| - ScrollAnchor* anchor = view->scrollAnchor(); |
| - DCHECK(anchor); |
| - if (anchor->refersTo(layoutObject)) { |
| - found = true; |
| - if (behavior == Clear) |
| - anchor->notifyRemoved(layoutObject); |
| - } |
| + found = clearScrollAnchorForScroller(view, layoutObject, behavior) || found; |
| + if (found && behavior == FindReferencing) |
| + return found; |
| + } |
| + |
| + // Continue walk past frame boundary. |
| + if (layoutObject->document().localOwner()) { |
| + found = |
| + findScrollAnchors(layoutObject->document().localOwner()->layoutObject(), |
| + behavior) || |
| + found; |
| } |
| return found; |
| } |
| @@ -2643,17 +2670,19 @@ void LayoutObject::willBeRemovedFromTree() { |
| parent()->setNeedsBoundariesUpdate(); |
| if (RuntimeEnabledFeatures::scrollAnchoringEnabled() && |
| - m_bitfields.isScrollAnchorObject()) { |
| - // Clear the bit first so that anchor.clear() doesn't recurse into findReferencingScrollAnchors. |
| - m_bitfields.setIsScrollAnchorObject(false); |
| - findReferencingScrollAnchors(this, Clear); |
| - } |
| + m_bitfields.isScrollAnchorObject()) |
| + findScrollAnchors(this, ClearReferencing); |
| } |
| void LayoutObject::maybeClearIsScrollAnchorObject() { |
| - if (m_bitfields.isScrollAnchorObject()) |
| + if (m_bitfields.isScrollAnchorObject()) { |
| m_bitfields.setIsScrollAnchorObject( |
| - findReferencingScrollAnchors(this, DontClear)); |
| + findScrollAnchors(this, FindReferencing)); |
| + } |
| +} |
| + |
| +void LayoutObject::clearScrollAnchors() { |
| + findScrollAnchors(this, ClearAll); |
| } |
| void LayoutObject::removeFromLayoutFlowThread() { |