Chromium Code Reviews| Index: third_party/WebKit/Source/core/frame/FrameView.cpp |
| diff --git a/third_party/WebKit/Source/core/frame/FrameView.cpp b/third_party/WebKit/Source/core/frame/FrameView.cpp |
| index 3fa8e63c185b071c4f343796b89e2d2f3ac3c1be..3a0f9d0278f3beff4054040ba44b831d931ae214 100644 |
| --- a/third_party/WebKit/Source/core/frame/FrameView.cpp |
| +++ b/third_party/WebKit/Source/core/frame/FrameView.cpp |
| @@ -170,7 +170,7 @@ FrameView::FrameView(LocalFrame* frame) |
| , m_suppressAdjustViewSize(false) |
| , m_allowsLayoutInvalidationAfterLayoutClean(true) |
| { |
| - ASSERT(m_frame); |
| + DCHECK(m_frame); |
| init(); |
| } |
| @@ -193,7 +193,9 @@ FrameView* FrameView::create(LocalFrame* frame, const IntSize& initialSize) |
| FrameView::~FrameView() |
| { |
| - ASSERT(m_hasBeenDisposed); |
| +#if ENABLE(ASSERT) |
| + DCHECK(m_hasBeenDisposed); |
| +#endif |
| } |
| DEFINE_TRACE(FrameView) |
| @@ -266,7 +268,7 @@ void FrameView::init() |
| void FrameView::dispose() |
| { |
| - RELEASE_ASSERT(!isInPerformLayout()); |
| + CHECK(!isInPerformLayout()); |
| if (ScrollAnimatorBase* scrollAnimator = existingScrollAnimator()) |
| scrollAnimator->cancelAnimation(); |
| @@ -538,7 +540,7 @@ void FrameView::adjustViewSize() |
| if (layoutViewItem.isNull()) |
| return; |
| - ASSERT(m_frame->view() == this); |
| + DCHECK(m_frame->view() == this); |
| const IntRect rect = layoutViewItem.documentRect(); |
| const IntSize& size = rect.size(); |
| @@ -637,7 +639,7 @@ void FrameView::updateAcceleratedCompositingSettings() |
| void FrameView::recalcOverflowAfterStyleChange() |
| { |
| LayoutViewItem layoutViewItem = this->layoutViewItem(); |
| - RELEASE_ASSERT(!layoutViewItem.isNull()); |
| + CHECK(!layoutViewItem.isNull()); |
| if (!layoutViewItem.needsOverflowRecalcAfterStyleChange()) |
| return; |
| @@ -685,7 +687,7 @@ bool FrameView::usesCompositedScrolling() const |
| LayoutViewItem layoutView = this->layoutViewItem(); |
| if (layoutView.isNull()) |
| return false; |
| - if (m_frame->settings() && m_frame->settings()->preferCompositingToLCDTextEnabled()) |
| + if (layoutView.layer()->needsCompositedScrolling()) |
|
chrishtr
2016/07/27 19:26:00
I don't think this will work, because the view is
Stephen Chennney
2016/07/28 13:55:38
Done.
|
| return layoutView.compositor()->inCompositingMode(); |
| return false; |
| } |
| @@ -778,7 +780,7 @@ inline void FrameView::forceLayoutParentViewIfNeeded() |
| ownerLayoutObject->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(LayoutInvalidationReason::Unknown); |
| // Synchronously enter layout, to layout the view containing the host object/embed/iframe. |
| - ASSERT(frameView); |
| + DCHECK(frameView); |
| frameView->layout(); |
| } |
| @@ -872,7 +874,7 @@ std::unique_ptr<TracedValue> FrameView::analyzerCounters() |
| void FrameView::performLayout(bool inSubtreeLayout) |
| { |
| - ASSERT(inSubtreeLayout || m_layoutSubtreeRootList.isEmpty()); |
| + DCHECK(inSubtreeLayout || m_layoutSubtreeRootList.isEmpty()); |
| TRACE_EVENT_BEGIN1(PERFORM_LAYOUT_TRACE_CATEGORIES, "FrameView::performLayout", |
| "contentsHeightBeforeLayout", layoutViewItem().documentRect().height()); |
| @@ -880,7 +882,7 @@ void FrameView::performLayout(bool inSubtreeLayout) |
| ScriptForbiddenScope forbidScript; |
| - ASSERT(!isInPerformLayout()); |
| + DCHECK(!isInPerformLayout()); |
| lifecycle().advanceTo(DocumentLifecycle::InPerformLayout); |
| // performLayout is the actual guts of layout(). |
| @@ -945,9 +947,9 @@ void FrameView::scheduleOrPerformPostLayoutTasks() |
| void FrameView::layout() |
| { |
| // We should never layout a Document which is not in a LocalFrame. |
| - ASSERT(m_frame); |
| - ASSERT(m_frame->view() == this); |
| - ASSERT(m_frame->page()); |
| + DCHECK(m_frame); |
| + DCHECK(m_frame->view() == this); |
| + DCHECK(m_frame->page()); |
| ScriptForbiddenScope forbidScript; |
| @@ -1061,7 +1063,7 @@ void FrameView::layout() |
| if (!inSubtreeLayout && !document->printing()) |
| adjustViewSizeAndLayout(); |
| - ASSERT(m_layoutSubtreeRootList.isEmpty()); |
| + DCHECK(m_layoutSubtreeRootList.isEmpty()); |
| } // Reset m_layoutSchedulingEnabled to its previous value. |
| checkDoesNotNeedLayout(); |
| @@ -1114,9 +1116,9 @@ void FrameView::invalidateTreeIfNeeded(const PaintInvalidationState& paintInvali |
| lifecycle().advanceTo(DocumentLifecycle::InPaintInvalidation); |
| - RELEASE_ASSERT(!layoutViewItem().isNull()); |
| + CHECK(!layoutViewItem().isNull()); |
| LayoutViewItem rootForPaintInvalidation = layoutViewItem(); |
| - ASSERT(!rootForPaintInvalidation.needsLayout()); |
| + DCHECK(!rootForPaintInvalidation.needsLayout()); |
| TRACE_EVENT1("blink", "FrameView::invalidateTree", "root", rootForPaintInvalidation.debugName().ascii()); |
| @@ -1132,7 +1134,7 @@ void FrameView::invalidateTreeIfNeeded(const PaintInvalidationState& paintInvali |
| void FrameView::invalidatePaintIfNeeded(const PaintInvalidationState& paintInvalidationState) |
| { |
| - RELEASE_ASSERT(!layoutViewItem().isNull()); |
| + CHECK(!layoutViewItem().isNull()); |
| if (!m_frame->settings() || !m_frame->settings()->rootLayerScrolls()) |
| invalidatePaintOfScrollControlsIfNeeded(paintInvalidationState); |
| @@ -1257,10 +1259,10 @@ void FrameView::updateWidgetGeometries() |
| void FrameView::addPartToUpdate(LayoutEmbeddedObject& object) |
| { |
| - ASSERT(isInPerformLayout()); |
| + DCHECK(isInPerformLayout()); |
| // Tell the DOM element that it needs a widget update. |
| Node* node = object.node(); |
| - ASSERT(node); |
| + DCHECK(node); |
| if (isHTMLObjectElement(*node) || isHTMLEmbedElement(*node)) |
| toHTMLPlugInElement(node)->setNeedsWidgetUpdate(true); |
| @@ -1280,7 +1282,7 @@ void FrameView::setDisplayMode(WebDisplayMode mode) |
| void FrameView::setMediaType(const AtomicString& mediaType) |
| { |
| - ASSERT(m_frame->document()); |
| + DCHECK(m_frame->document()); |
| m_frame->document()->mediaQueryAffectingValueChanged(); |
| m_mediaType = mediaType; |
| } |
| @@ -1314,7 +1316,7 @@ bool FrameView::contentsInCompositedLayer() const |
| void FrameView::addBackgroundAttachmentFixedObject(LayoutObject* object) |
| { |
| - ASSERT(!m_backgroundAttachmentFixedObjects.contains(object)); |
| + DCHECK(!m_backgroundAttachmentFixedObjects.contains(object)); |
| m_backgroundAttachmentFixedObjects.add(object); |
| if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) |
| @@ -1323,7 +1325,7 @@ void FrameView::addBackgroundAttachmentFixedObject(LayoutObject* object) |
| void FrameView::removeBackgroundAttachmentFixedObject(LayoutObject* object) |
| { |
| - ASSERT(m_backgroundAttachmentFixedObjects.contains(object)); |
| + DCHECK(m_backgroundAttachmentFixedObjects.contains(object)); |
| m_backgroundAttachmentFixedObjects.remove(object); |
| if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) |
| @@ -1420,8 +1422,8 @@ bool FrameView::invalidateViewportConstrainedObjects() |
| for (const auto& viewportConstrainedObject : *m_viewportConstrainedObjects) { |
| LayoutObject* layoutObject = viewportConstrainedObject; |
| LayoutItem layoutItem = LayoutItem(layoutObject); |
| - ASSERT(layoutItem.style()->hasViewportConstrainedPosition()); |
| - ASSERT(layoutItem.hasLayer()); |
| + DCHECK(layoutItem.style()->hasViewportConstrainedPosition()); |
| + DCHECK(layoutItem.hasLayer()); |
| PaintLayer* layer = LayoutBoxModel(layoutItem).layer(); |
| if (layer->isPaintInvalidationContainer()) |
| @@ -1473,7 +1475,7 @@ void FrameView::scrollContentsSlowPath(const IntRect& updateRect) |
| // We need full invalidation during slow scrolling. For slimming paint, full invalidation |
| // of the LayoutView is not enough. We also need to invalidate all of the objects. |
| // FIXME: Find out what are enough to invalidate in slow path scrolling. crbug.com/451090#9. |
| - ASSERT(!layoutViewItem().isNull()); |
| + DCHECK(!layoutViewItem().isNull()); |
| if (contentsInCompositedLayer()) |
| layoutViewItem().layer()->compositedLayerMapping()->setContentsNeedDisplay(); |
| else |
| @@ -1482,7 +1484,7 @@ void FrameView::scrollContentsSlowPath(const IntRect& updateRect) |
| if (contentsInCompositedLayer()) { |
| IntRect updateRect = visibleContentRect(); |
| - ASSERT(!layoutViewItem().isNull()); |
| + DCHECK(!layoutViewItem().isNull()); |
| // FIXME: We should not allow paint invalidation out of paint invalidation state. crbug.com/457415 |
| DisablePaintInvalidationStateAsserts disabler; |
| layoutViewItem().invalidatePaintRectangle(LayoutRect(updateRect)); |
| @@ -1530,7 +1532,7 @@ void FrameView::processUrlFragment(const KURL& url, UrlFragmentBehavior behavior |
| bool FrameView::processUrlFragmentHelper(const String& name, UrlFragmentBehavior behavior) |
| { |
| - ASSERT(m_frame->document()); |
| + DCHECK(m_frame->document()); |
| if (behavior == UrlFragmentScroll && !m_frame->document()->isRenderingReady()) { |
| m_frame->document()->setGotoAnchorNeededAfterStylesheetsLoad(true); |
| @@ -1578,7 +1580,7 @@ bool FrameView::processUrlFragmentHelper(const String& name, UrlFragmentBehavior |
| void FrameView::setFragmentAnchor(Node* anchorNode) |
| { |
| - ASSERT(anchorNode); |
| + DCHECK(anchorNode); |
| m_fragmentAnchor = anchorNode; |
| // We need to update the layout tree before scrolling. |
| @@ -1640,7 +1642,7 @@ IntSize FrameView::layoutSize(IncludeScrollbarsInRect scrollbarInclusion) const |
| void FrameView::setLayoutSize(const IntSize& size) |
| { |
| - ASSERT(!layoutSizeFixedToFrameSize()); |
| + DCHECK(!layoutSizeFixedToFrameSize()); |
| setLayoutSizeInternal(size); |
| } |
| @@ -1726,7 +1728,7 @@ void FrameView::updateCompositedSelectionIfNeeded() |
| TRACE_EVENT0("blink", "FrameView::updateCompositedSelectionIfNeeded"); |
| Page* page = frame().page(); |
| - ASSERT(page); |
| + DCHECK(page); |
| CompositedSelection selection; |
| LocalFrame* focusedFrame = page->focusController().focusedFrame(); |
| @@ -1824,7 +1826,7 @@ bool FrameView::hasOrthogonalWritingModeRoots() const |
| void FrameView::layoutOrthogonalWritingModeRoots() |
| { |
| for (auto& root : m_orthogonalWritingModeRootList.ordered()) { |
| - ASSERT(root->isBox() && toLayoutBox(*root).isOrthogonalWritingModeRoot()); |
| + DCHECK(root->isBox() && toLayoutBox(*root).isOrthogonalWritingModeRoot()); |
| if (!root->needsLayout() |
| || root->isOutOfFlowPositioned() |
| || root->isColumnSpanAll() |
| @@ -2034,7 +2036,7 @@ bool FrameView::updateWidgets() |
| { |
| // This is always called from updateWidgetsTimerFired. |
| // m_updateWidgetsTimer should only be scheduled if we have widgets to update. |
| - // Thus I believe we can stop checking isEmpty here, and just ASSERT isEmpty: |
| + // Thus I believe we can stop checking isEmpty here, and just DCHECK isEmpty: |
| // FIXME: This assert has been temporarily removed due to https://crbug.com/430344 |
| if (m_nestedLayoutCount > 1 || m_partUpdateSet.isEmpty()) |
| return true; |
| @@ -2070,7 +2072,7 @@ bool FrameView::updateWidgets() |
| void FrameView::updateWidgetsTimerFired(Timer<FrameView>*) |
| { |
| - ASSERT(!isInPerformLayout()); |
| + DCHECK(!isInPerformLayout()); |
| m_updateWidgetsTimer.stop(); |
| for (unsigned i = 0; i < maxUpdateWidgetsIterations; ++i) { |
| if (updateWidgets()) |
| @@ -2080,7 +2082,7 @@ void FrameView::updateWidgetsTimerFired(Timer<FrameView>*) |
| void FrameView::flushAnyPendingPostLayoutTasks() |
| { |
| - ASSERT(!isInPerformLayout()); |
| + DCHECK(!isInPerformLayout()); |
| if (m_postLayoutTasksTimer.isActive()) |
| performPostLayoutTasks(); |
| if (m_updateWidgetsTimer.isActive()) |
| @@ -2089,7 +2091,7 @@ void FrameView::flushAnyPendingPostLayoutTasks() |
| void FrameView::scheduleUpdateWidgetsIfNecessary() |
| { |
| - ASSERT(!isInPerformLayout()); |
| + DCHECK(!isInPerformLayout()); |
| if (m_updateWidgetsTimer.isActive() || m_partUpdateSet.isEmpty()) |
| return; |
| m_updateWidgetsTimer.startOneShot(0, BLINK_FROM_HERE); |
| @@ -2100,8 +2102,8 @@ void FrameView::performPostLayoutTasks() |
| // FIXME: We can reach here, even when the page is not active! |
| // http/tests/inspector/elements/html-link-import.html and many other |
| // tests hit that case. |
| - // We should ASSERT(isActive()); or at least return early if we can! |
| - ASSERT(!isInPerformLayout()); // Always before or after performLayout(), part of the highest-level layout() call. |
| + // We should DCHECK(isActive()); or at least return early if we can! |
| + DCHECK(!isInPerformLayout()); // Always before or after performLayout(), part of the highest-level layout() call. |
| TRACE_EVENT0("blink,benchmark", "FrameView::performPostLayoutTasks"); |
| m_postLayoutTasksTimer.stop(); |
| @@ -2109,7 +2111,7 @@ void FrameView::performPostLayoutTasks() |
| m_frame->selection().setCaretRectNeedsUpdate(); |
| m_frame->selection().updateAppearance(); |
| - ASSERT(m_frame->document()); |
| + DCHECK(m_frame->document()); |
| FontFaceSet::didLayout(*m_frame->document()); |
| // Cursor update scheduling is done by the local root, which is the main frame if there |
| @@ -2139,17 +2141,17 @@ void FrameView::performPostLayoutTasks() |
| bool FrameView::wasViewportResized() |
| { |
| - ASSERT(m_frame); |
| + DCHECK(m_frame); |
| LayoutViewItem layoutViewItem = this->layoutViewItem(); |
| if (layoutViewItem.isNull()) |
| return false; |
| - ASSERT(layoutViewItem.style()); |
| + DCHECK(layoutViewItem.style()); |
| return (layoutSize(IncludeScrollbars) != m_lastViewportSize || layoutViewItem.style()->zoom() != m_lastZoomFactor); |
| } |
| void FrameView::sendResizeEventIfNeeded() |
| { |
| - ASSERT(m_frame); |
| + DCHECK(m_frame); |
| LayoutViewItem layoutViewItem = this->layoutViewItem(); |
| if (layoutViewItem.isNull() || layoutViewItem.document().printing()) |
| @@ -2188,7 +2190,7 @@ void FrameView::updateCounters() |
| IntRect FrameView::windowClipRect(IncludeScrollbarsInRect scrollbarInclusion) const |
| { |
| - ASSERT(m_frame->view() == this); |
| + DCHECK(m_frame->view() == this); |
| LayoutRect clipRect(LayoutPoint(), LayoutSize(visibleContentSize(scrollbarInclusion))); |
| layoutViewItem().mapToVisualRectInAncestorSpace(&layoutView()->containerForPaintInvalidation(), clipRect); |
| @@ -2197,7 +2199,10 @@ IntRect FrameView::windowClipRect(IncludeScrollbarsInRect scrollbarInclusion) co |
| bool FrameView::shouldUseIntegerScrollOffset() const |
| { |
| - if (m_frame->settings() && !m_frame->settings()->preferCompositingToLCDTextEnabled()) |
| + LayoutViewItem layoutView = this->layoutViewItem(); |
|
chrishtr
2016/07/27 19:26:00
Ditto.
I think you should just write:
if (m_fra
Stephen Chennney
2016/07/28 13:55:38
We don't need anything at all. The logic works suc
|
| + if (layoutView.isNull()) |
| + return false; |
| + if (layoutView.layer()->needsCompositedScrolling()) |
| return true; |
| return ScrollableArea::shouldUseIntegerScrollOffset(); |
| @@ -2604,7 +2609,7 @@ void FrameView::updatePaintProperties() |
| { |
| TRACE_EVENT0("blink", "FrameView::updatePaintProperties"); |
| - ASSERT(RuntimeEnabledFeatures::slimmingPaintV2Enabled()); |
| + DCHECK(RuntimeEnabledFeatures::slimmingPaintV2Enabled()); |
| forAllNonThrottledFrameViews([](FrameView& frameView) { frameView.lifecycle().advanceTo(DocumentLifecycle::InPrePaint); }); |
| PrePaintTreeWalk().walk(*this); |
| @@ -2616,10 +2621,10 @@ void FrameView::synchronizedPaint() |
| TRACE_EVENT0("blink", "FrameView::synchronizedPaint"); |
| SCOPED_BLINK_UMA_HISTOGRAM_TIMER("Blink.Paint.UpdateTime"); |
| - ASSERT(frame() == page()->mainFrame() || (!frame().tree().parent()->isLocalFrame())); |
| + DCHECK(frame() == page()->mainFrame() || (!frame().tree().parent()->isLocalFrame())); |
| LayoutViewItem view = layoutViewItem(); |
| - ASSERT(!view.isNull()); |
| + DCHECK(!view.isNull()); |
| forAllNonThrottledFrameViews([](FrameView& frameView) { frameView.lifecycle().advanceTo(DocumentLifecycle::InPaint); }); |
| // A null graphics layer can occur for painting of SVG images that are not parented into the main frame tree, |
| @@ -2668,14 +2673,14 @@ void FrameView::pushPaintArtifactToCompositor() |
| { |
| TRACE_EVENT0("blink", "FrameView::pushPaintArtifactToCompositor"); |
| - ASSERT(RuntimeEnabledFeatures::slimmingPaintV2Enabled()); |
| + DCHECK(RuntimeEnabledFeatures::slimmingPaintV2Enabled()); |
| LayoutViewItem viewItem = layoutViewItem(); |
| - ASSERT(!viewItem.isNull()); |
| + DCHECK(!viewItem.isNull()); |
| // TODO(jbroman): Simplify the path to PaintController. |
| PaintLayer* layer = viewItem.layer(); |
| - ASSERT(layer); |
| + DCHECK(layer); |
| if (!layer->hasCompositedLayerMapping()) |
| return; |
| GraphicsLayer* rootGraphicsLayer = layer->compositedLayerMapping()->mainGraphicsLayer(); |
| @@ -2761,7 +2766,7 @@ void FrameView::updateStyleAndLayoutIfNeededRecursiveInternal() |
| // These asserts ensure that parent frames are clean, when child frames finished updating layout and style. |
| checkDoesNotNeedLayout(); |
| - ASSERT(!m_frame->document()->hasSVGFilterElementsRequiringLayerUpdate()); |
| + DCHECK(!m_frame->document()->hasSVGFilterElementsRequiringLayerUpdate()); |
| #if ENABLE(ASSERT) |
| m_frame->document()->layoutView()->assertLaidOut(); |
| #endif |
| @@ -3090,7 +3095,7 @@ void FrameView::removeResizerArea(LayoutBox& resizerBox) |
| void FrameView::addScrollableArea(ScrollableArea* scrollableArea) |
| { |
| - ASSERT(scrollableArea); |
| + DCHECK(scrollableArea); |
| if (!m_scrollableAreas) |
| m_scrollableAreas = new ScrollableAreaSet; |
| m_scrollableAreas->add(scrollableArea); |
| @@ -3111,7 +3116,7 @@ void FrameView::removeScrollableArea(ScrollableArea* scrollableArea) |
| void FrameView::addAnimatingScrollableArea(ScrollableArea* scrollableArea) |
| { |
| - ASSERT(scrollableArea); |
| + DCHECK(scrollableArea); |
| if (!m_animatingScrollableAreas) |
| m_animatingScrollableAreas = new ScrollableAreaSet; |
| m_animatingScrollableAreas->add(scrollableArea); |
| @@ -3143,7 +3148,7 @@ void FrameView::setParent(Widget* parentView) |
| void FrameView::removeChild(Widget* child) |
| { |
| - ASSERT(child->parent() == this); |
| + DCHECK(child->parent() == this); |
| if (child->isFrameView()) |
| removeScrollableArea(toFrameView(child)); |
| @@ -3214,7 +3219,7 @@ IntPoint FrameView::maximumScrollPosition() const |
| void FrameView::addChild(Widget* child) |
| { |
| - ASSERT(child != this && !child->parent()); |
| + DCHECK(child != this && !child->parent()); |
| child->setParent(this); |
| m_children.add(child); |
| } |
| @@ -3370,7 +3375,7 @@ void FrameView::setScrollOffset(const DoublePoint& offset, ScrollType scrollType |
| if (m_frame->settings() && m_frame->settings()->rootLayerScrolls()) { |
| // Don't scroll the FrameView! |
| - ASSERT_NOT_REACHED(); |
| + NOTREACHED(); |
| } |
| m_scrollPosition = newPosition; |
| @@ -3545,7 +3550,7 @@ IntRect FrameView::adjustScrollbarRectForResizer(const IntRect& rect, Scrollbar& |
| bool FrameView::adjustScrollbarExistence(ComputeScrollbarExistenceOption option) |
| { |
| - ASSERT(m_inUpdateScrollbars); |
| + DCHECK(m_inUpdateScrollbars); |
| // If we came in here with the view already needing a layout, then go ahead and do that |
| // first. (This will be the common case, e.g., when the page changes due to window resizing for example). |
| @@ -4146,7 +4151,7 @@ void FrameView::updateViewportIntersectionIfNeeded() |
| m_viewportIntersection = frameRect(); |
| return; |
| } |
| - ASSERT(!parent->m_needsUpdateViewportIntersection); |
| + DCHECK(!parent->m_needsUpdateViewportIntersection); |
| // If our parent is hidden, then we are too. |
| if (parent->m_viewportIntersection.isEmpty()) { |
| @@ -4159,7 +4164,7 @@ void FrameView::updateViewportIntersectionIfNeeded() |
| // parent is throttled, we'll use possible stale layout information and |
| // rely on the fact that another lifecycle update will be scheduled once |
| // our parent becomes unthrottled. |
| - ASSERT(parent->lifecycle().state() >= DocumentLifecycle::LayoutClean || parent->shouldThrottleRendering()); |
| + DCHECK(parent->lifecycle().state() >= DocumentLifecycle::LayoutClean || parent->shouldThrottleRendering()); |
| m_viewportIntersection = parent->contentsToRootFrame(frameRect()); |
| // TODO(skyostil): Expand the viewport to make it less likely to see stale content while scrolling. |