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 eca6b082996a9c4e144924398fe522653d4adbd0..327710e04f05a609be40ae5442f99349c23f2105 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" |
| @@ -2575,39 +2576,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, |
| + 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. |
|
skobes
2016/10/10 21:34:35
Hmm, do we actually want this behavior? We don't
ymalik
2016/10/11 19:54:22
hmm you're right. I was under the impression that
|
| + if (layoutObject->document().localOwner()) { |
| + found = |
| + findScrollAnchors(layoutObject->document().localOwner()->layoutObject(), |
| + behavior) || |
| + found; |
| } |
| return found; |
| } |
| @@ -2641,17 +2668,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() { |