Backed out 15 changesets (bug 1305957) for ASAN failures CLOSED TREE

Backed out changeset 4d5eb85d3155 (bug 1305957)
Backed out changeset 51c86d025ecb (bug 1305957)
Backed out changeset d8eef8f3e396 (bug 1305957)
Backed out changeset 950bf6ad1ef2 (bug 1305957)
Backed out changeset b4cb2cbebdb6 (bug 1305957)
Backed out changeset bfca5019a9cc (bug 1305957)
Backed out changeset e76b842c7b7f (bug 1305957)
Backed out changeset d9445a5f3458 (bug 1305957)
Backed out changeset d9052f7b34d9 (bug 1305957)
Backed out changeset e7124fecb721 (bug 1305957)
Backed out changeset bdb766faa867 (bug 1305957)
Backed out changeset 3033401ef320 (bug 1305957)
Backed out changeset 6b96050386f6 (bug 1305957)
Backed out changeset c66c00f73296 (bug 1305957)
Backed out changeset 6bd0bdab93cb (bug 1305957)
This commit is contained in:
Bogdan Tara 2019-01-10 18:49:22 +02:00
Родитель ba7c4014b7
Коммит 6d78d1e2c9
65 изменённых файлов: 121 добавлений и 1062 удалений

Просмотреть файл

@ -806,7 +806,6 @@ a.learn-more-link.webconsole-learn-more-link {
.webconsole-output {
direction: ltr;
overflow: auto;
overflow-anchor: none;
-moz-user-select: text;
position: relative;
}

Просмотреть файл

@ -107,7 +107,6 @@ exports.ANIMATION_TYPE_FOR_LONGHANDS = [
"-moz-orient",
"-moz-osx-font-smoothing",
"outline-style",
"overflow-anchor",
"overflow-clip-box-block",
"overflow-clip-box-inline",
"overflow-wrap",

Просмотреть файл

@ -2917,7 +2917,6 @@ exports.CSS_PROPERTIES = {
"overflow-clip-box-block",
"overflow-x",
"overflow-y",
"overflow-anchor",
"transition-duration",
"transition-timing-function",
"transition-property",
@ -7644,20 +7643,6 @@ exports.CSS_PROPERTIES = {
"visible"
]
},
"overflow-anchor": {
"isInherited": false,
"subproperties": [
"overflow-anchor"
],
"supports": [],
"values": [
"auto",
"inherit",
"initial",
"none",
"unset"
]
},
"overflow-wrap": {
"isInherited": true,
"subproperties": [
@ -9391,10 +9376,6 @@ exports.PREFERENCES = [
"-moz-osx-font-smoothing",
"layout.css.osx-font-smoothing.enabled"
],
[
"overflow-anchor",
"layout.css.scroll-anchoring.enabled"
],
[
"scrollbar-width",
"layout.css.scrollbar-width.enabled"

Просмотреть файл

@ -178,7 +178,6 @@
#include "mozilla/layers/FocusTarget.h"
#include "mozilla/layers/WebRenderLayerManager.h"
#include "mozilla/layers/WebRenderUserData.h"
#include "mozilla/layout/ScrollAnchorContainer.h"
#include "mozilla/ServoBindings.h"
#include "mozilla/ServoStyleSet.h"
#include "mozilla/StyleSheet.h"
@ -1312,7 +1311,6 @@ void PresShell::Destroy() {
}
mFramesToDirty.Clear();
mDirtyScrollAnchorContainers.Clear();
if (mViewManager) {
// Clear the view manager's weak pointer back to |this| in case it
@ -2140,11 +2138,6 @@ void PresShell::NotifyDestroyingFrame(nsIFrame* aFrame) {
}
mFramesToDirty.RemoveEntry(aFrame);
nsIScrollableFrame* scrollableFrame = do_QueryFrame(aFrame);
if (scrollableFrame) {
mDirtyScrollAnchorContainers.RemoveEntry(scrollableFrame);
}
}
}
@ -2564,19 +2557,6 @@ void PresShell::VerifyHasDirtyRootAncestor(nsIFrame* aFrame) {
}
#endif
void PresShell::PostDirtyScrollAnchorContainer(nsIScrollableFrame* aFrame) {
mDirtyScrollAnchorContainers.PutEntry(aFrame);
}
void PresShell::FlushDirtyScrollAnchorContainers() {
for (auto iter = mDirtyScrollAnchorContainers.Iter(); !iter.Done();
iter.Next()) {
nsIScrollableFrame* scroll = iter.Get()->GetKey();
scroll->GetAnchor()->SelectAnchor();
}
mDirtyScrollAnchorContainers.Clear();
}
void PresShell::FrameNeedsReflow(nsIFrame* aFrame,
IntrinsicDirty aIntrinsicDirty,
nsFrameState aBitToAdd,
@ -8496,8 +8476,6 @@ bool PresShell::DoReflow(nsIFrame* target, bool aInterruptible,
mReflowCause = nullptr;
#endif
FlushDirtyScrollAnchorContainers();
if (mReflowContinueTimer) {
mReflowContinueTimer->Cancel();
mReflowContinueTimer = nullptr;
@ -8617,10 +8595,6 @@ bool PresShell::DoReflow(nsIFrame* target, bool aInterruptible,
nsContainerFrame::SET_ASYNC);
target->DidReflow(mPresContext, nullptr);
if (target->IsInScrollAnchorChain()) {
ScrollAnchorContainer* container = ScrollAnchorContainer::FindFor(target);
container->ApplyAdjustments();
}
if (isRoot && size.BSize(wm) == NS_UNCONSTRAINEDSIZE) {
mPresContext->SetVisibleArea(boundsRelativeToTarget);
}
@ -10031,8 +10005,7 @@ void PresShell::AddSizeOfIncludingThis(nsWindowSizes& aSizes) const {
}
aSizes.mLayoutPresShellSize +=
mApproximatelyVisibleFrames.ShallowSizeOfExcludingThis(mallocSizeOf) +
mFramesToDirty.ShallowSizeOfExcludingThis(mallocSizeOf) +
mDirtyScrollAnchorContainers.ShallowSizeOfExcludingThis(mallocSizeOf);
mFramesToDirty.ShallowSizeOfExcludingThis(mallocSizeOf);
StyleSet()->AddSizeOfIncludingThis(aSizes);

Просмотреть файл

@ -113,9 +113,6 @@ class PresShell final : public nsIPresShell,
nsIPageSequenceFrame* GetPageSequenceFrame() const override;
nsCanvasFrame* GetCanvasFrame() const override;
void PostDirtyScrollAnchorContainer(nsIScrollableFrame* aFrame) override;
void FlushDirtyScrollAnchorContainers() override;
void FrameNeedsReflow(
nsIFrame* aFrame, IntrinsicDirty aIntrinsicDirty, nsFrameState aBitToAdd,
ReflowRootHandling aRootHandling = eInferFromBitToAdd) override;
@ -747,7 +744,6 @@ class PresShell final : public nsIPresShell,
// Set of frames that we should mark with NS_FRAME_HAS_DIRTY_CHILDREN after
// we finish reflowing mCurrentReflowRoot.
nsTHashtable<nsPtrHashKey<nsIFrame>> mFramesToDirty;
nsTHashtable<nsPtrHashKey<nsIScrollableFrame>> mDirtyScrollAnchorContainers;
nsTArray<UniquePtr<DelayedEvent>> mDelayedEvents;

Просмотреть файл

@ -14,7 +14,6 @@
#include "mozilla/GeckoBindings.h"
#include "mozilla/LayerAnimationInfo.h"
#include "mozilla/layers/AnimationInfo.h"
#include "mozilla/layout/ScrollAnchorContainer.h"
#include "mozilla/ServoBindings.h"
#include "mozilla/ServoStyleSetInlines.h"
#include "mozilla/Unused.h"
@ -774,10 +773,6 @@ static bool RecomputePosition(nsIFrame* aFrame) {
}
}
if (aFrame->IsInScrollAnchorChain()) {
ScrollAnchorContainer* container = ScrollAnchorContainer::FindFor(aFrame);
container->ApplyAdjustments();
}
return true;
}
@ -883,10 +878,6 @@ static bool RecomputePosition(nsIFrame* aFrame) {
reflowInput.ComputedPhysicalMargin().top);
aFrame->SetPosition(pos);
if (aFrame->IsInScrollAnchorChain()) {
ScrollAnchorContainer* container = ScrollAnchorContainer::FindFor(aFrame);
container->ApplyAdjustments();
}
return true;
}
@ -1499,16 +1490,6 @@ void RestyleManager::ProcessRestyledFrames(nsStyleChangeList& aChangeList) {
}
if (hint & nsChangeHint_ReconstructFrame) {
// Record whether this frame was absolutely positioned before and after
// frame construction, to detect changes for scroll anchor adjustment
// suppression.
bool wasAbsPosStyle = false;
ScrollAnchorContainer* previousAnchorContainer = nullptr;
if (frame) {
wasAbsPosStyle = frame->StyleDisplay()->IsAbsolutelyPositionedStyle();
previousAnchorContainer = ScrollAnchorContainer::FindFor(frame);
}
// If we ever start passing true here, be careful of restyles
// that involve a reframe and animations. In particular, if the
// restyle we're processing here is an animation restyle, but
@ -1520,34 +1501,6 @@ void RestyleManager::ProcessRestyledFrames(nsStyleChangeList& aChangeList) {
// the reconstruction happening synchronously.
frameConstructor->RecreateFramesForContent(
content, nsCSSFrameConstructor::InsertionKind::Sync);
frame = content->GetPrimaryFrame();
// See the check above for absolutely positioned style.
bool isAbsPosStyle = false;
ScrollAnchorContainer* newAnchorContainer = nullptr;
if (frame) {
isAbsPosStyle = frame->StyleDisplay()->IsAbsolutelyPositionedStyle();
newAnchorContainer = ScrollAnchorContainer::FindFor(frame);
}
// If this frame construction was due to a change in absolute
// positioning, then suppress scroll anchor adjustments in the scroll
// anchor container the frame was in, and the one it moved into.
//
// This isn't entirely accurate to the specification, which requires us
// to do this for all frames that change being absolutely positioned. It's
// possible for multiple style changes to cause frame reconstruction and
// coalesce, which could cause a suppression trigger to be missed. It's
// unclear whether this will be an issue as suppression triggers are just
// heuristics.
if (wasAbsPosStyle != isAbsPosStyle) {
if (previousAnchorContainer) {
previousAnchorContainer->SuppressAdjustments();
}
if (newAnchorContainer) {
newAnchorContainer->SuppressAdjustments();
}
}
} else {
NS_ASSERTION(frame, "This shouldn't happen");
@ -2962,11 +2915,6 @@ void RestyleManager::DoProcessPendingRestyles(ServoTraversalFlags aFlags) {
return;
}
// Select scroll anchors for frames that have been scrolled. Do this
// before restyling so that anchor nodes are correctly marked for
// scroll anchor update suppressions.
presContext->PresShell()->FlushDirtyScrollAnchorContainers();
// Create a AnimationsWithDestroyedFrame during restyling process to
// stop animations and transitions on elements that have no frame at the end
// of the restyling process.

Просмотреть файл

@ -454,9 +454,6 @@ class nsIPresShell : public nsStubDocumentObserver {
*/
virtual nsCanvasFrame* GetCanvasFrame() const = 0;
virtual void PostDirtyScrollAnchorContainer(nsIScrollableFrame* aFrame) = 0;
virtual void FlushDirtyScrollAnchorContainers() = 0;
/**
* Tell the pres shell that a frame needs to be marked dirty and needs
* Reflow. It's OK if this is an ancestor of the frame needing reflow as

Просмотреть файл

@ -1490,11 +1490,11 @@ bool nsLayoutUtils::IsAncestorFrameCrossDoc(const nsIFrame* aAncestorFrame,
}
// static
bool nsLayoutUtils::IsProperAncestorFrame(const nsIFrame* aAncestorFrame,
const nsIFrame* aFrame,
const nsIFrame* aCommonAncestor) {
bool nsLayoutUtils::IsProperAncestorFrame(nsIFrame* aAncestorFrame,
nsIFrame* aFrame,
nsIFrame* aCommonAncestor) {
if (aFrame == aAncestorFrame) return false;
for (const nsIFrame* f = aFrame; f != aCommonAncestor; f = f->GetParent()) {
for (nsIFrame* f = aFrame; f != aCommonAncestor; f = f->GetParent()) {
if (f == aAncestorFrame) return true;
}
return aCommonAncestor == aAncestorFrame;

Просмотреть файл

@ -528,9 +528,8 @@ class nsLayoutUtils {
* aAncestorFrame. If non-null, this can bound the search and speed up
* the function
*/
static bool IsProperAncestorFrame(const nsIFrame* aAncestorFrame,
const nsIFrame* aFrame,
const nsIFrame* aCommonAncestor = nullptr);
static bool IsProperAncestorFrame(nsIFrame* aAncestorFrame, nsIFrame* aFrame,
nsIFrame* aCommonAncestor = nullptr);
/**
* Like IsProperAncestorFrame, but looks across document boundaries.

Просмотреть файл

@ -1,514 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "ScrollAnchorContainer.h"
#include "mozilla/StaticPrefs.h"
#include "nsGfxScrollFrame.h"
#include "nsLayoutUtils.h"
#define ANCHOR_LOG(...)
// #define ANCHOR_LOG(...) printf_stderr("ANCHOR: " __VA_ARGS__)
namespace mozilla {
namespace layout {
ScrollAnchorContainer::ScrollAnchorContainer(ScrollFrameHelper* aScrollFrame)
: mScrollFrame(aScrollFrame),
mAnchorNode(nullptr),
mLastAnchorPos(0, 0),
mAnchorNodeIsDirty(true),
mApplyingAnchorAdjustment(false),
mSuppressAnchorAdjustment(false) {}
ScrollAnchorContainer::~ScrollAnchorContainer() {}
ScrollAnchorContainer* ScrollAnchorContainer::FindFor(nsIFrame* aFrame) {
aFrame = aFrame->GetParent();
if (!aFrame) {
return nullptr;
}
nsIScrollableFrame* nearest = nsLayoutUtils::GetNearestScrollableFrame(
aFrame, nsLayoutUtils::SCROLLABLE_SAME_DOC |
nsLayoutUtils::SCROLLABLE_INCLUDE_HIDDEN);
if (nearest) {
return nearest->GetAnchor();
}
return nullptr;
}
nsIFrame* ScrollAnchorContainer::Frame() const { return mScrollFrame->mOuter; }
nsIScrollableFrame* ScrollAnchorContainer::ScrollableFrame() const {
return Frame()->GetScrollTargetFrame();
}
/**
* Set the appropriate frame flags for a frame that has become or is no longer
* an anchor node.
*/
static void SetAnchorFlags(const nsIFrame* aScrolledFrame,
nsIFrame* aAnchorNode, bool aInScrollAnchorChain) {
nsIFrame* frame = aAnchorNode;
while (frame && frame != aScrolledFrame) {
MOZ_ASSERT(
frame == aAnchorNode || !frame->IsScrollFrame(),
"We shouldn't select an anchor node inside a nested scroll frame.");
frame->SetInScrollAnchorChain(aInScrollAnchorChain);
frame = frame->GetParent();
}
MOZ_ASSERT(frame,
"The anchor node should be a descendant of the scroll frame");
// If needed, invalidate the frame so that we start/stop highlighting the
// anchor
if (StaticPrefs::layout_css_scroll_anchoring_highlight()) {
for (nsIFrame* frame = aAnchorNode->FirstContinuation(); !!frame;
frame = frame->GetNextContinuation()) {
frame->InvalidateFrame();
}
}
}
/**
* Compute the scrollable overflow rect [1] of aCandidate relative to
* aScrollFrame with all transforms applied. The specification is also
* ambiguous about what can be selected as a scroll anchor, which makes
* the scroll anchoring bounding rect partially undefined [2]. This code
* attempts to match the implementation in Blink.
*
* [1]
* https://drafts.csswg.org/css-scroll-anchoring-1/#scroll-anchoring-bounding-rect
* [2] https://github.com/w3c/csswg-drafts/issues/3478
*/
static nsRect FindScrollAnchoringBoundingRect(const nsIFrame* aScrollFrame,
nsIFrame* aCandidate) {
MOZ_ASSERT(nsLayoutUtils::IsProperAncestorFrame(aScrollFrame, aCandidate));
if (aCandidate->GetContent()->IsText()) {
nsRect bounding;
for (nsIFrame* continuation = aCandidate->FirstContinuation(); continuation;
continuation = continuation->GetNextContinuation()) {
nsRect localRect =
continuation->GetScrollableOverflowRectRelativeToSelf();
nsRect transformed = nsLayoutUtils::TransformFrameRectToAncestor(
continuation, localRect, aScrollFrame);
bounding = bounding.Union(transformed);
}
return bounding;
}
nsRect localRect = aCandidate->GetScrollableOverflowRectRelativeToSelf();
nsRect transformed = nsLayoutUtils::TransformFrameRectToAncestor(
aCandidate, localRect, aScrollFrame);
return transformed;
}
void ScrollAnchorContainer::SelectAnchor() {
MOZ_ASSERT(mScrollFrame->mScrolledFrame);
MOZ_ASSERT(mAnchorNodeIsDirty);
if (!StaticPrefs::layout_css_scroll_anchoring_enabled()) {
return;
}
ANCHOR_LOG("Selecting anchor for %p with scroll-port [%d %d x %d %d].\n",
this, mScrollFrame->mScrollPort.x, mScrollFrame->mScrollPort.y,
mScrollFrame->mScrollPort.width, mScrollFrame->mScrollPort.height);
const nsStyleDisplay* disp = Frame()->StyleDisplay();
// Don't select a scroll anchor if the scroll frame has `overflow-anchor:
// none`.
bool overflowAnchor =
disp->mOverflowAnchor == mozilla::StyleOverflowAnchor::Auto;
// Or if the scroll frame has not been scrolled from the logical origin. This
// is not in the specification [1], but Blink does this.
//
// [1] https://github.com/w3c/csswg-drafts/issues/3319
bool isScrolled = mScrollFrame->GetLogicalScrollPosition() != nsPoint();
// Or if there is perspective that could affect the scrollable overflow rect
// for descendant frames. This is not in the specification as Blink doesn't
// share this behavior with perspective [1].
//
// [1] https://github.com/w3c/csswg-drafts/issues/3322
bool hasPerspective = Frame()->ChildrenHavePerspective();
// Select a new scroll anchor
nsIFrame* oldAnchor = mAnchorNode;
if (overflowAnchor && isScrolled && !hasPerspective) {
ANCHOR_LOG("Beginning candidate selection.\n");
mAnchorNode = FindAnchorIn(mScrollFrame->mScrolledFrame);
} else {
if (!overflowAnchor) {
ANCHOR_LOG("Skipping candidate selection for `overflow-anchor: none`\n");
}
if (!isScrolled) {
ANCHOR_LOG("Skipping candidate selection for not being scrolled\n");
}
if (hasPerspective) {
ANCHOR_LOG(
"Skipping candidate selection for scroll frame with perspective\n");
}
mAnchorNode = nullptr;
}
// Update the anchor flags if needed
if (oldAnchor != mAnchorNode) {
ANCHOR_LOG("Anchor node has changed from (%p) to (%p).\n", oldAnchor,
mAnchorNode);
// Unset all flags for the old scroll anchor
if (oldAnchor) {
SetAnchorFlags(mScrollFrame->mScrolledFrame, oldAnchor, false);
}
// Set all flags for the new scroll anchor
if (mAnchorNode) {
// Anchor selection will never select a descendant of a different scroll
// frame, so we can set flags without conflicting with other scroll
// anchor containers.
SetAnchorFlags(mScrollFrame->mScrolledFrame, mAnchorNode, true);
}
} else {
ANCHOR_LOG("Anchor node has remained (%p).\n", mAnchorNode);
}
// Calculate the position to use for scroll adjustments
if (mAnchorNode) {
mLastAnchorPos =
FindScrollAnchoringBoundingRect(Frame(), mAnchorNode).TopLeft();
ANCHOR_LOG("Using last anchor position = [%d, %d].\n", mLastAnchorPos.x,
mLastAnchorPos.y);
} else {
mLastAnchorPos = nsPoint();
}
mAnchorNodeIsDirty = false;
}
void ScrollAnchorContainer::UserScrolled() {
if (mApplyingAnchorAdjustment) {
return;
}
InvalidateAnchor();
}
void ScrollAnchorContainer::SuppressAdjustments() {
ANCHOR_LOG("Received a scroll anchor suppression for %p.\n", this);
mSuppressAnchorAdjustment = true;
}
void ScrollAnchorContainer::InvalidateAnchor() {
if (!StaticPrefs::layout_css_scroll_anchoring_enabled()) {
return;
}
ANCHOR_LOG("Invalidating scroll anchor %p for %p.\n", mAnchorNode, this);
if (mAnchorNode) {
SetAnchorFlags(mScrollFrame->mScrolledFrame, mAnchorNode, false);
}
mAnchorNode = nullptr;
mAnchorNodeIsDirty = true;
mLastAnchorPos = nsPoint();
Frame()->PresShell()->PostDirtyScrollAnchorContainer(ScrollableFrame());
}
void ScrollAnchorContainer::Destroy() {
if (mAnchorNode) {
SetAnchorFlags(mScrollFrame->mScrolledFrame, mAnchorNode, false);
}
mAnchorNode = nullptr;
mAnchorNodeIsDirty = false;
mLastAnchorPos = nsPoint();
}
void ScrollAnchorContainer::ApplyAdjustments() {
if (!mAnchorNode || mAnchorNodeIsDirty) {
mSuppressAnchorAdjustment = false;
ANCHOR_LOG("Ignoring post-reflow (anchor=%p, dirty=%d, container=%p).\n",
mAnchorNode, mAnchorNodeIsDirty, this);
return;
}
nsPoint current =
FindScrollAnchoringBoundingRect(Frame(), mAnchorNode).TopLeft();
nsPoint adjustment = current - mLastAnchorPos;
nsIntPoint adjustmentDevicePixels =
adjustment.ToNearestPixels(Frame()->PresContext()->AppUnitsPerDevPixel());
ANCHOR_LOG("Anchor has moved from [%d, %d] to [%d, %d].\n", mLastAnchorPos.x,
mLastAnchorPos.y, current.x, current.y);
WritingMode writingMode = Frame()->GetWritingMode();
// The specification only allows for anchor adjustments in the block
// dimension, so remove the other component.
if (writingMode.IsVertical()) {
adjustmentDevicePixels.y = 0;
} else {
adjustmentDevicePixels.x = 0;
}
if (adjustmentDevicePixels == nsIntPoint()) {
ANCHOR_LOG("Ignoring zero delta anchor adjustment for %p.\n", this);
mSuppressAnchorAdjustment = false;
return;
}
if (mSuppressAnchorAdjustment) {
ANCHOR_LOG("Applying anchor adjustment suppression for %p.\n", this);
mSuppressAnchorAdjustment = false;
InvalidateAnchor();
return;
}
ANCHOR_LOG("Applying anchor adjustment of (%d %d) for %p and anchor %p.\n",
adjustment.x, adjustment.y, this, mAnchorNode);
MOZ_ASSERT(!mApplyingAnchorAdjustment);
// We should use AutoRestore here, but that doesn't work with bitfields
mApplyingAnchorAdjustment = true;
mScrollFrame->ScrollBy(
adjustmentDevicePixels, nsIScrollableFrame::DEVICE_PIXELS,
nsIScrollableFrame::INSTANT, nullptr, nsGkAtoms::relative);
mApplyingAnchorAdjustment = false;
// The anchor position may not be in the same relative position after
// adjustment. Update ourselves so we have consistent state.
mLastAnchorPos =
FindScrollAnchoringBoundingRect(Frame(), mAnchorNode).TopLeft();
}
ScrollAnchorContainer::ExamineResult
ScrollAnchorContainer::ExamineAnchorCandidate(nsIFrame* aFrame) const {
#ifdef DEBUG_FRAME_DUMP
nsCString tag = aFrame->ListTag();
ANCHOR_LOG("\tVisiting frame=%s (%p).\n", tag.get(), aFrame);
#else
ANCHOR_LOG("\t\tVisiting frame=%p.\n", aFrame);
#endif
// Check if the author has opted out of scroll anchoring for this frame
// and its descendants.
const nsStyleDisplay* disp = aFrame->StyleDisplay();
if (disp->mOverflowAnchor == mozilla::StyleOverflowAnchor::None) {
ANCHOR_LOG("\t\tExcluding `overflow-anchor: none`.\n");
return ExamineResult::Exclude;
}
// Sticky positioned elements can move with the scroll frame, making them
// unsuitable scroll anchors. This isn't in the specification yet [1], but
// matches Blink's implementation.
//
// [1] https://github.com/w3c/csswg-drafts/issues/3319
if (aFrame->IsStickyPositioned()) {
ANCHOR_LOG("\t\tExcluding `position: sticky`.\n");
return ExamineResult::Exclude;
}
// The frame for a <br> element has a non-zero area, but Blink treats them
// as if they have no area, so exclude them specially.
if (aFrame->IsBrFrame()) {
ANCHOR_LOG("\t\tExcluding <br>.\n");
return ExamineResult::Exclude;
}
// Exclude frames that aren't accessible to content.
bool isChrome =
aFrame->GetContent() && aFrame->GetContent()->ChromeOnlyAccess();
bool isPseudo = aFrame->Style()->IsPseudoElement();
if (isChrome && !isPseudo) {
ANCHOR_LOG("\t\tExcluding chrome only content.\n");
return ExamineResult::Exclude;
}
// See if this frame could have its own anchor node. We could check
// IsScrollFrame(), but that would miss nsListControlFrame which is not a
// scroll frame, but still inherits from nsHTMLScrollFrame.
nsIScrollableFrame* scrollable = do_QueryFrame(aFrame);
// We don't allow scroll anchors to be selected inside of scrollable frames as
// it's not clear how an anchor adjustment should apply to multiple scrollable
// frames. Blink allows this to happen, but they're not sure why [1].
//
// We also don't allow scroll anchors to be selected inside of SVG as it uses
// a different layout model than CSS, and the specification doesn't say it
// should apply.
//
// [1] https://github.com/w3c/csswg-drafts/issues/3477
bool canDescend = !scrollable && !aFrame->IsSVGOuterSVGFrame();
// Check what kind of frame this is
bool isBlockOutside = aFrame->IsBlockOutside();
bool isText = aFrame->GetContent()->IsText();
bool isAnonBox = aFrame->Style()->IsAnonBox() && !isText;
bool isInlineOutside = aFrame->IsInlineOutside() && !isText;
bool isContinuation = !!aFrame->GetPrevContinuation();
// If the frame is anonymous or inline-outside, search its descendants for a
// scroll anchor.
if ((isAnonBox || isInlineOutside) && canDescend) {
ANCHOR_LOG(
"\t\tSearching descendants of anon or inline box (a=%d, i=%d).\n",
isAnonBox, isInlineOutside);
return ExamineResult::PassThrough;
}
// If the frame is not block-outside or a text node then exclude it.
if (!isBlockOutside && !isText) {
ANCHOR_LOG("\t\tExcluding non block-outside or text node (b=%d, t=%d).\n",
isBlockOutside, isText);
return ExamineResult::Exclude;
}
// Find the scroll anchoring bounding rect.
nsRect rect = FindScrollAnchoringBoundingRect(Frame(), aFrame);
ANCHOR_LOG("\t\trect = [%d %d x %d %d].\n", rect.x, rect.y, rect.width,
rect.height);
// Check if this frame is visible in the scroll port. This will exclude rects
// with zero sized area. The specification is ambiguous about this [1], but
// this matches Blink's implementation.
//
// [1] https://github.com/w3c/csswg-drafts/issues/3483
nsRect visibleRect;
if (!visibleRect.IntersectRect(rect, mScrollFrame->mScrollPort)) {
return ExamineResult::Exclude;
}
// At this point, if canDescend is true, we should only have visible
// non-anonymous frames that are either:
// 1. block-outside
// 2. text nodes
//
// It's not clear what the scroll anchoring bounding rect of elements that are
// block-outside should be when they are fragmented. For text nodes that are
// fragmented, it's specified that we need to consider the union of its line
// boxes.
//
// So for text nodes we handle them by including the union of line boxes in
// the bounding rect of the primary frame, and not selecting any
// continuations.
//
// For block-outside elements we choose to consider the bounding rect of each
// frame individually, allowing ourselves to descend into any frame, but only
// selecting a frame if it's not a continuation.
if (canDescend && isContinuation) {
ANCHOR_LOG("\t\tSearching descendants of a continuation.\n");
return ExamineResult::PassThrough;
}
// If this frame is fully visible, then select it as the scroll anchor.
if (visibleRect.IsEqualEdges(rect)) {
ANCHOR_LOG("\t\tFully visible, taking.\n");
return ExamineResult::Accept;
}
// If we can't descend into this frame, then select it as the scroll anchor.
if (!canDescend) {
ANCHOR_LOG("\t\tIntersects a frame that we can't descend into, taking.\n");
return ExamineResult::Accept;
}
// It must be partially visible and we can descend into this frame. Examine
// its children for a better scroll anchor or fall back to this one.
ANCHOR_LOG("\t\tIntersects valid candidate, checking descendants.\n");
return ExamineResult::Traverse;
}
nsIFrame* ScrollAnchorContainer::FindAnchorIn(nsIFrame* aFrame) const {
// Visit the child lists of this frame
for (nsIFrame::ChildListIterator lists(aFrame); !lists.IsDone();
lists.Next()) {
// Skip child lists that contain out-of-flow frames, we'll visit them by
// following placeholders in the in-flow lists so that we visit these
// frames in DOM order.
// XXX do we actually need to exclude kOverflowOutOfFlowList too?
if (lists.CurrentID() == FrameChildListID::kAbsoluteList ||
lists.CurrentID() == FrameChildListID::kFixedList ||
lists.CurrentID() == FrameChildListID::kFloatList ||
lists.CurrentID() == FrameChildListID::kOverflowOutOfFlowList) {
continue;
}
// Search the child list, and return if we selected an anchor
if (nsIFrame* anchor = FindAnchorInList(lists.CurrentList())) {
return anchor;
}
}
// The spec requires us to do an extra pass to visit absolutely positioned
// frames a second time after all the children of their containing block have
// been visited.
//
// It's not clear why this is needed [1], but it matches Blink's
// implementation, and is needed for a WPT test.
//
// [1] https://github.com/w3c/csswg-drafts/issues/3465
const nsFrameList& absPosList =
aFrame->GetChildList(FrameChildListID::kAbsoluteList);
if (nsIFrame* anchor = FindAnchorInList(absPosList)) {
return anchor;
}
return nullptr;
}
nsIFrame* ScrollAnchorContainer::FindAnchorInList(
const nsFrameList& aFrameList) const {
for (nsIFrame* child : aFrameList) {
// If this is a placeholder, try to follow it to the out of flow frame.
nsIFrame* realFrame = nsPlaceholderFrame::GetRealFrameFor(child);
if (child != realFrame) {
// If the out of flow frame is not a descendant of our scroll frame,
// then it must have a different containing block and cannot be an
// anchor node.
if (!nsLayoutUtils::IsProperAncestorFrame(Frame(), realFrame)) {
ANCHOR_LOG(
"\t\tSkipping out of flow frame that is not a descendant of the "
"scroll frame.\n");
continue;
}
ANCHOR_LOG("\t\tFollowing placeholder to out of flow frame.\n");
child = realFrame;
}
// Perform the candidate examination algorithm
ExamineResult examine = ExamineAnchorCandidate(child);
// See the comment before the definition of `ExamineResult` in
// `ScrollAnchorContainer.h` for an explanation of this behavior.
switch (examine) {
case ExamineResult::Exclude: {
continue;
}
case ExamineResult::PassThrough: {
nsIFrame* candidate = FindAnchorIn(child);
if (!candidate) {
continue;
}
return candidate;
}
case ExamineResult::Traverse: {
nsIFrame* candidate = FindAnchorIn(child);
if (!candidate) {
return child;
}
return candidate;
}
case ExamineResult::Accept: {
return child;
}
}
}
return nullptr;
}
} // namespace layout
} // namespace mozilla

Просмотреть файл

@ -1,151 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_layout_ScrollAnchorContainer_h_
#define mozilla_layout_ScrollAnchorContainer_h_
#include "nsPoint.h"
class nsIFrame;
namespace mozilla {
class ScrollFrameHelper;
} // namespace mozilla
namespace mozilla {
namespace layout {
/**
* A scroll anchor container finds a descendent element of a scrollable frame
* to be an anchor node. After every reflow, the scroll anchor will apply
* scroll adjustments to keep the anchor node in the same relative position.
*
* See: https://drafts.csswg.org/css-scroll-anchoring/
*/
class ScrollAnchorContainer final {
public:
explicit ScrollAnchorContainer(ScrollFrameHelper* aScrollFrame);
~ScrollAnchorContainer();
/**
* Returns the nearest scroll anchor container that could select aFrame as an
* anchor node.
*/
static ScrollAnchorContainer* FindFor(nsIFrame* aFrame);
/**
* Returns the frame that is the selected anchor node or null if no anchor
* is selected.
*/
nsIFrame* AnchorNode() const { return mAnchorNode; }
/**
* Returns the frame that owns this scroll anchor container. This is always
* non-null.
*/
nsIFrame* Frame() const;
/**
* Returns the frame that owns this scroll anchor container as a scrollable
* frame. This is always non-null.
*/
nsIScrollableFrame* ScrollableFrame() const;
/**
* Find a suitable anchor node among the descendants of the scrollable frame.
* This should only be called after the scroll anchor has been invalidated.
*/
void SelectAnchor();
/**
* Notify the scroll anchor container that its scroll frame has been
* scrolled by a user and should invalidate itself.
*/
void UserScrolled();
/**
* Notify the scroll anchor container that a reflow has happened and it
* should query its anchor to see if a scroll adjustment needs to occur.
*/
void ApplyAdjustments();
/**
* Notify the scroll anchor container that it should suppress any scroll
* adjustment that may happen after the next layout flush.
*/
void SuppressAdjustments();
/**
* Notify this scroll anchor container that its anchor node should be
* invalidated and recomputed at the next available opportunity.
*/
void InvalidateAnchor();
/**
* Notify this scroll anchor container that it will be destroyed along with
* its parent frame.
*/
void Destroy();
private:
// Represents an assessment of a frame's suitability as a scroll anchor,
// from the scroll-anchoring spec's "candidate examination algorithm":
// https://drafts.csswg.org/css-scroll-anchoring-1/#candidate-examination
enum class ExamineResult {
// The frame is an excluded subtree or fully clipped and should be ignored.
// This corresponds with step 1 in the algorithm.
Exclude,
// This frame is an anonymous or inline box and its descendants should be
// searched to find an anchor node. If none are found, then continue
// searching. This is implied by the prologue of the algorithm, and
// should be made explicit in the spec [1].
//
// [1] https://github.com/w3c/csswg-drafts/issues/3489
PassThrough,
// The frame is partially visible and its descendants should be searched to
// find an anchor node. If none are found then this frame should be
// selected. This corresponds with step 3 in the algorithm.
Traverse,
// The frame is fully visible and should be selected as an anchor node. This
// corresponds with step 2 in the algorithm.
Accept,
};
ExamineResult ExamineAnchorCandidate(nsIFrame* aPrimaryFrame) const;
// Search a frame's children to find an anchor node. Returns the frame for a
// valid anchor node, if one was found in the frames descendants, or null
// otherwise.
nsIFrame* FindAnchorIn(nsIFrame* aFrame) const;
// Search a child list to find an anchor node. Returns the frame for a valid
// anchor node, if one was found in this child list, or null otherwise.
nsIFrame* FindAnchorInList(const nsFrameList& aFrameList) const;
// The owner of this scroll anchor container
ScrollFrameHelper* mScrollFrame;
// The anchor node that we will scroll to keep in the same relative position
// after reflows. This may be null if we were not able to select a valid
// scroll anchor
nsIFrame* mAnchorNode;
// The last position of the scroll anchor node relative to the scrollable
// frame. This is used for calculating the distance to scroll to keep the
// anchor node in the same relative position
nsPoint mLastAnchorPos;
// True if we should recalculate our anchor node at the next chance
bool mAnchorNodeIsDirty : 1;
// True if we are applying a scroll anchor adjustment
bool mApplyingAnchorAdjustment : 1;
// True if we should suppress anchor adjustments
bool mSuppressAnchorAdjustment : 1;
};
} // namespace layout
} // namespace mozilla
#endif // mozilla_layout_ScrollAnchorContainer_h_

Просмотреть файл

@ -145,7 +145,6 @@ EXPORTS.mozilla += [
EXPORTS.mozilla.layout += [
'FrameChildList.h',
'ScrollAnchorContainer.h',
]
UNIFIED_SOURCES += [
@ -203,7 +202,6 @@ UNIFIED_SOURCES += [
'ReflowInput.cpp',
'ReflowOutput.cpp',
'RubyUtils.cpp',
'ScrollAnchorContainer.cpp',
'ScrollAnimationBezierPhysics.cpp',
'ScrollAnimationMSDPhysics.cpp',
'ScrollbarActivity.cpp',

Просмотреть файл

@ -22,7 +22,6 @@
#include "mozilla/gfx/gfxVars.h"
#include "mozilla/gfx/PathHelpers.h"
#include "mozilla/Sprintf.h"
#include "mozilla/StaticPrefs.h"
#include "nsCOMPtr.h"
#include "nsFlexContainerFrame.h"
@ -112,7 +111,6 @@
#include "mozilla/dom/TouchEvent.h"
#include "mozilla/gfx/Tools.h"
#include "mozilla/layers/WebRenderUserData.h"
#include "mozilla/layout/ScrollAnchorContainer.h"
#include "nsPrintfCString.h"
#include "ActiveLayerTracker.h"
@ -729,11 +727,6 @@ void nsFrame::DestroyFrom(nsIFrame* aDestructRoot,
ActiveLayerTracker::TransferActivityToContent(this, mContent);
}
ScrollAnchorContainer* anchor = nullptr;
if (IsScrollAnchor(&anchor)) {
anchor->InvalidateAnchor();
}
if (HasCSSAnimations() || HasCSSTransitions() ||
EffectSet::GetEffectSet(this)) {
// If no new frame for this element is created by the end of the
@ -1054,11 +1047,6 @@ void nsIFrame::MarkNeedsDisplayItemRebuild() {
AddAndRemoveImageAssociations(this, oldLayers, newLayers);
if (aOldComputedStyle) {
// Detect style changes that should trigger a scroll anchor adjustment
// suppression.
// https://drafts.csswg.org/css-scroll-anchoring/#suppression-triggers
bool needAnchorSuppression = false;
// If we detect a change on margin, padding or border, we store the old
// values on the frame itself between now and reflow, so if someone
// calls GetUsed(Margin|Border|Padding)() before the next reflow, we
@ -1068,21 +1056,17 @@ void nsIFrame::MarkNeedsDisplayItemRebuild() {
nsMargin newValue(0, 0, 0, 0);
const nsStyleMargin* oldMargin = aOldComputedStyle->PeekStyleMargin();
if (oldMargin && oldMargin->GetMargin(oldValue)) {
if (!StyleMargin()->GetMargin(newValue) || oldValue != newValue) {
if (!HasProperty(UsedMarginProperty())) {
AddProperty(UsedMarginProperty(), new nsMargin(oldValue));
}
needAnchorSuppression = true;
if ((!StyleMargin()->GetMargin(newValue) || oldValue != newValue) &&
!HasProperty(UsedMarginProperty())) {
AddProperty(UsedMarginProperty(), new nsMargin(oldValue));
}
}
const nsStylePadding* oldPadding = aOldComputedStyle->PeekStylePadding();
if (oldPadding && oldPadding->GetPadding(oldValue)) {
if (!StylePadding()->GetPadding(newValue) || oldValue != newValue) {
if (!HasProperty(UsedPaddingProperty())) {
AddProperty(UsedPaddingProperty(), new nsMargin(oldValue));
}
needAnchorSuppression = true;
if ((!StylePadding()->GetPadding(newValue) || oldValue != newValue) &&
!HasProperty(UsedPaddingProperty())) {
AddProperty(UsedPaddingProperty(), new nsMargin(oldValue));
}
}
@ -1094,31 +1078,6 @@ void nsIFrame::MarkNeedsDisplayItemRebuild() {
AddProperty(UsedBorderProperty(), new nsMargin(oldValue));
}
}
if (mInScrollAnchorChain) {
const nsStylePosition* oldPosition =
aOldComputedStyle->PeekStylePosition();
if (oldPosition &&
(oldPosition->mOffset != StylePosition()->mOffset ||
oldPosition->mWidth != StylePosition()->mWidth ||
oldPosition->mMinWidth != StylePosition()->mMinWidth ||
oldPosition->mMaxWidth != StylePosition()->mMaxWidth ||
oldPosition->mHeight != StylePosition()->mHeight ||
oldPosition->mMinHeight != StylePosition()->mMinHeight ||
oldPosition->mMaxHeight != StylePosition()->mMaxHeight)) {
needAnchorSuppression = true;
}
const nsStyleDisplay* oldDisp = aOldComputedStyle->PeekStyleDisplay();
if (oldDisp && (oldDisp->mPosition != StyleDisplay()->mPosition ||
oldDisp->TransformChanged(*StyleDisplay()))) {
needAnchorSuppression = true;
}
}
if (mInScrollAnchorChain && needAnchorSuppression) {
ScrollAnchorContainer::FindFor(this)->SuppressAdjustments();
}
}
ImageLoader* imageLoader = PresContext()->Document()->StyleImageLoader();
@ -3518,17 +3477,6 @@ void nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
// Animations may change the stacking context state.
!(child->MayHaveTransformAnimation() || child->MayHaveOpacityAnimation());
if (StaticPrefs::layout_css_scroll_anchoring_highlight()) {
if (child->FirstContinuation()->IsScrollAnchor()) {
nsRect bounds = child->GetContentRectRelativeToSelf() +
aBuilder->ToReferenceFrame(child);
nsDisplaySolidColor* color = MakeDisplayItem<nsDisplaySolidColor>(
aBuilder, child, bounds, NS_RGBA(255, 0, 255, 64));
color->SetOverrideZIndex(INT32_MAX);
aLists.PositionedDescendants()->AppendToTop(color);
}
}
if (doingShortcut) {
BuildDisplayListForSimpleChild(aBuilder, child, aLists);
return;
@ -9195,28 +9143,6 @@ void nsIFrame::ComputePreserve3DChildrenOverflow(
}
}
bool nsIFrame::IsScrollAnchor(ScrollAnchorContainer** aOutContainer) {
if (!mInScrollAnchorChain) {
return false;
}
ScrollAnchorContainer* container = ScrollAnchorContainer::FindFor(this);
if (container->AnchorNode() != this) {
return false;
}
if (aOutContainer) {
*aOutContainer = container;
}
return true;
}
bool nsIFrame::IsInScrollAnchorChain() const { return mInScrollAnchorChain; }
void nsIFrame::SetInScrollAnchorChain(bool aInChain) {
mInScrollAnchorChain = aInChain;
}
uint32_t nsIFrame::GetDepthInFrameTree() const {
uint32_t result = 0;
for (nsContainerFrame* ancestor = GetParent(); ancestor;

Просмотреть файл

@ -1121,12 +1121,6 @@ void nsHTMLScrollFrame::Reflow(nsPresContext* aPresContext,
mHelper.PostOverflowEvent();
}
void nsHTMLScrollFrame::DidReflow(nsPresContext* aPresContext,
const ReflowInput* aReflowInput) {
nsContainerFrame::DidReflow(aPresContext, aReflowInput);
mHelper.mAnchor.ApplyAdjustments();
}
////////////////////////////////////////////////////////////////////////////////
#ifdef DEBUG_FRAME_DUMP
@ -1966,7 +1960,6 @@ ScrollFrameHelper::ScrollFrameHelper(nsContainerFrame* aOuter, bool aIsRoot)
mLastUpdateFramesPos(-1, -1),
mDisplayPortAtLastFrameUpdate(),
mScrollParentID(mozilla::layers::ScrollableLayerGuid::NULL_SCROLL_ID),
mAnchor(this),
mAllowScrollOriginDowngrade(false),
mHadDisplayPortAtLastFrameUpdate(false),
mNeverHasVerticalScrollbar(false),
@ -2747,7 +2740,6 @@ void ScrollFrameHelper::ScrollToImpl(nsPoint aPt, const nsRect& aRange,
}
ScrollVisual();
mAnchor.UserScrolled();
bool schedulePaint = true;
if (nsLayoutUtils::AsyncPanZoomEnabled(mOuter) &&
@ -4718,8 +4710,6 @@ void ScrollFrameHelper::AppendAnonymousContentTo(
}
void ScrollFrameHelper::Destroy(PostDestroyData& aPostDestroyData) {
mAnchor.Destroy();
if (mScrollbarActivity) {
mScrollbarActivity->Destroy();
mScrollbarActivity = nullptr;

Просмотреть файл

@ -25,7 +25,6 @@
#include "TextOverflow.h"
#include "ScrollVelocityQueue.h"
#include "mozilla/PresState.h"
#include "mozilla/layout/ScrollAnchorContainer.h"
class nsPresContext;
class nsIPresShell;
@ -53,7 +52,6 @@ class ScrollFrameHelper : public nsIReflowCallback {
typedef mozilla::layers::ScrollSnapInfo ScrollSnapInfo;
typedef mozilla::layers::Layer Layer;
typedef mozilla::layers::LayerManager LayerManager;
typedef mozilla::layout::ScrollAnchorContainer ScrollAnchorContainer;
class AsyncScroll;
class AsyncSmoothMSDScroll;
@ -568,8 +566,6 @@ class ScrollFrameHelper : public nsIReflowCallback {
// Timer to remove the displayport some time after scrolling has stopped
nsCOMPtr<nsITimer> mDisplayPortExpiryTimer;
ScrollAnchorContainer mAnchor;
bool mAllowScrollOriginDowngrade : 1;
bool mHadDisplayPortAtLastFrameUpdate : 1;
bool mNeverHasVerticalScrollbar : 1;
@ -727,7 +723,6 @@ class nsHTMLScrollFrame : public nsContainerFrame,
typedef mozilla::ScrollFrameHelper ScrollFrameHelper;
typedef mozilla::CSSIntPoint CSSIntPoint;
typedef mozilla::ScrollReflowInput ScrollReflowInput;
typedef mozilla::layout::ScrollAnchorContainer ScrollAnchorContainer;
friend nsHTMLScrollFrame* NS_NewHTMLScrollFrame(nsIPresShell* aPresShell,
ComputedStyle* aStyle,
bool aIsRoot);
@ -765,8 +760,6 @@ class nsHTMLScrollFrame : public nsContainerFrame,
virtual void Reflow(nsPresContext* aPresContext, ReflowOutput& aDesiredSize,
const ReflowInput& aReflowInput,
nsReflowStatus& aStatus) override;
virtual void DidReflow(nsPresContext* aPresContext,
const ReflowInput* aReflowInput) override;
virtual bool ComputeCustomOverflow(nsOverflowAreas& aOverflowAreas) override {
return mHelper.ComputeCustomOverflow(aOverflowAreas);
@ -1119,14 +1112,6 @@ class nsHTMLScrollFrame : public nsContainerFrame,
return mHelper.IsRootScrollFrameOfDocument();
}
virtual const ScrollAnchorContainer* GetAnchor() const override {
return &mHelper.mAnchor;
}
virtual ScrollAnchorContainer* GetAnchor() override {
return &mHelper.mAnchor;
}
// Return the scrolled frame.
void AppendDirectlyOwnedAnonBoxes(nsTArray<OwnedAnonBox>& aResult) override {
aResult.AppendElement(OwnedAnonBox(mHelper.GetScrolledFrame()));
@ -1189,7 +1174,6 @@ class nsXULScrollFrame final : public nsBoxFrame,
public:
typedef mozilla::ScrollFrameHelper ScrollFrameHelper;
typedef mozilla::CSSIntPoint CSSIntPoint;
typedef mozilla::layout::ScrollAnchorContainer ScrollAnchorContainer;
NS_DECL_QUERYFRAME
NS_DECL_FRAMEARENA_HELPERS(nsXULScrollFrame)
@ -1593,14 +1577,6 @@ class nsXULScrollFrame final : public nsBoxFrame,
return mHelper.IsRootScrollFrameOfDocument();
}
virtual const ScrollAnchorContainer* GetAnchor() const override {
return &mHelper.mAnchor;
}
virtual ScrollAnchorContainer* GetAnchor() override {
return &mHelper.mAnchor;
}
// Return the scrolled frame.
void AppendDirectlyOwnedAnonBoxes(nsTArray<OwnedAnonBox>& aResult) override {
aResult.AppendElement(OwnedAnonBox(mHelper.GetScrolledFrame()));

Просмотреть файл

@ -115,10 +115,6 @@ class Layer;
class LayerManager;
} // namespace layers
namespace layout {
class ScrollAnchorContainer;
} // namespace layout
namespace dom {
class Selection;
} // namespace dom
@ -570,8 +566,7 @@ class nsIFrame : public nsQueryFrame {
mIsPrimaryFrame(false),
mMayHaveTransformAnimation(false),
mMayHaveOpacityAnimation(false),
mAllDescendantsAreInvisible(false),
mInScrollAnchorChain(false) {
mAllDescendantsAreInvisible(false) {
mozilla::PodZero(&mOverflow);
}
@ -1851,24 +1846,6 @@ class nsIFrame : public nsQueryFrame {
void RecomputePerspectiveChildrenOverflow(const nsIFrame* aStartFrame);
/**
* Returns whether this frame is the anchor of some ancestor scroll frame. As
* this frame is moved, the scroll frame will apply adjustments to keep this
* scroll frame in the same relative position.
*
* aOutContainer will optionally be set to the scroll anchor container for
* this frame if this frame is an anchor.
*/
bool IsScrollAnchor(
mozilla::layout::ScrollAnchorContainer** aOutContainer = nullptr);
/**
* Returns whether this frame is the anchor of some ancestor scroll frame, or
* has a descendant which is the scroll anchor.
*/
bool IsInScrollAnchorChain() const;
void SetInScrollAnchorChain(bool aInChain);
/**
* Returns the number of ancestors between this and the root of our frame tree
*/
@ -3871,7 +3848,6 @@ class nsIFrame : public nsQueryFrame {
inline bool IsAbsPosContainingBlock() const;
inline bool IsFixedPosContainingBlock() const;
inline bool IsRelativelyPositioned() const;
inline bool IsStickyPositioned() const;
inline bool IsAbsolutelyPositioned(
const nsStyleDisplay* aStyleDisplay = nullptr) const;
@ -4316,12 +4292,9 @@ class nsIFrame : public nsQueryFrame {
*/
bool mAllDescendantsAreInvisible : 1;
/**
* True if we are or contain the scroll anchor for a scrollable frame.
*/
bool mInScrollAnchorChain : 1;
protected:
// There is a 1-bit gap left here.
// Helpers
/**
* Can we stop inside this frame when we're skipping non-rendered whitespace?

Просмотреть файл

@ -47,10 +47,6 @@ bool nsIFrame::IsRelativelyPositioned() const {
return StyleDisplay()->IsRelativelyPositioned(this);
}
bool nsIFrame::IsStickyPositioned() const {
return StyleDisplay()->IsStickyPositioned(this);
}
bool nsIFrame::IsAbsolutelyPositioned(
const nsStyleDisplay* aStyleDisplay) const {
const nsStyleDisplay* disp = StyleDisplayWithOptionalParam(aStyleDisplay);

Просмотреть файл

@ -39,9 +39,6 @@ struct ScrollMetadata;
class Layer;
class LayerManager;
} // namespace layers
namespace layout {
class ScrollAnchorContainer;
} // namespace layout
} // namespace mozilla
/**
@ -54,7 +51,6 @@ class nsIScrollableFrame : public nsIScrollbarMediator {
typedef mozilla::CSSIntPoint CSSIntPoint;
typedef mozilla::ContainerLayerParameters ContainerLayerParameters;
typedef mozilla::layers::ScrollSnapInfo ScrollSnapInfo;
typedef mozilla::layout::ScrollAnchorContainer ScrollAnchorContainer;
NS_DECL_QUERYFRAME_TARGET(nsIScrollableFrame)
@ -552,12 +548,6 @@ class nsIScrollableFrame : public nsIScrollbarMediator {
* all (ie XUL documents) even though they may contain other scroll frames.
*/
virtual bool IsRootScrollFrameOfDocument() const = 0;
/**
* Returns the scroll anchor associated with this scrollable frame.
*/
virtual const ScrollAnchorContainer* GetAnchor() const = 0;
virtual ScrollAnchorContainer* GetAnchor() = 0;
};
#endif

Просмотреть файл

@ -132,7 +132,6 @@ rusty-enums = [
"mozilla::StyleRuleInclusion",
"mozilla::StyleGridTrackBreadth",
"mozilla::StyleOverscrollBehavior",
"mozilla::StyleOverflowAnchor",
"mozilla::StyleScrollbarWidth",
"mozilla::StyleWhiteSpace",
"mozilla::StyleTextRendering",
@ -411,7 +410,6 @@ cbindgen-types = [
{ gecko = "StyleOverscrollBehavior", servo = "values::computed::OverscrollBehavior" },
{ gecko = "StyleTextAlign", servo = "values::computed::TextAlign" },
{ gecko = "StyleOverflow", servo = "values::computed::Overflow" },
{ gecko = "StyleOverflowAnchor", servo = "values::computed::OverflowAnchor" },
]
mapped-generic-types = [

Просмотреть файл

@ -131,7 +131,6 @@ SERIALIZED_PREDEFINED_TYPES = [
"url::ImageUrlOrNone",
"Appearance",
"OverscrollBehavior",
"OverflowAnchor",
"OverflowClipBox",
"ScrollSnapType",
"Float",

Просмотреть файл

@ -2990,7 +2990,6 @@ nsStyleDisplay::nsStyleDisplay(const nsPresContext* aContext)
mScrollBehavior(NS_STYLE_SCROLL_BEHAVIOR_AUTO),
mOverscrollBehaviorX(StyleOverscrollBehavior::Auto),
mOverscrollBehaviorY(StyleOverscrollBehavior::Auto),
mOverflowAnchor(StyleOverflowAnchor::Auto),
mScrollSnapTypeX(StyleScrollSnapType::None),
mScrollSnapTypeY(StyleScrollSnapType::None),
mScrollSnapPointsX(eStyleUnit_None),
@ -3147,12 +3146,6 @@ void nsStyleDisplay::FinishStyle(nsPresContext* aPresContext,
GenerateCombinedIndividualTransform();
}
static inline bool TransformListChanged(
const RefPtr<nsCSSValueSharedList>& aList,
const RefPtr<nsCSSValueSharedList>& aNewList) {
return !aList != !aNewList || (aList && *aList != *aNewList);
}
static inline nsChangeHint CompareTransformValues(
const RefPtr<nsCSSValueSharedList>& aList,
const RefPtr<nsCSSValueSharedList>& aNewList) {
@ -3431,11 +3424,6 @@ nsChangeHint nsStyleDisplay::CalcDifference(
return hint;
}
bool nsStyleDisplay::TransformChanged(const nsStyleDisplay& aNewData) const {
return TransformListChanged(mSpecifiedTransform,
aNewData.mSpecifiedTransform);
}
void nsStyleDisplay::GenerateCombinedIndividualTransform() {
// FIXME(emilio): This should probably be called from somewhere like what we
// do for image layers, instead of FinishStyle.

Просмотреть файл

@ -1881,8 +1881,6 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleDisplay {
nsChangeHint CalcDifference(const nsStyleDisplay& aNewData) const;
bool TransformChanged(const nsStyleDisplay& aNewData) const;
// We guarantee that if mBinding is non-null, so are mBinding->GetURI() and
// mBinding->mOriginPrincipal.
RefPtr<mozilla::css::URLValue> mBinding;
@ -1924,7 +1922,6 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleDisplay {
uint8_t mScrollBehavior; // NS_STYLE_SCROLL_BEHAVIOR_*
mozilla::StyleOverscrollBehavior mOverscrollBehaviorX;
mozilla::StyleOverscrollBehavior mOverscrollBehaviorY;
mozilla::StyleOverflowAnchor mOverflowAnchor;
mozilla::StyleScrollSnapType mScrollSnapTypeX;
mozilla::StyleScrollSnapType mScrollSnapTypeY;
nsStyleCoord mScrollSnapPointsX;
@ -2111,9 +2108,6 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleDisplay {
return NS_STYLE_POSITION_RELATIVE == mPosition ||
NS_STYLE_POSITION_STICKY == mPosition;
}
bool IsStickyPositionedStyle() const {
return NS_STYLE_POSITION_STICKY == mPosition;
}
bool IsPositionForcingStackingContext() const {
return NS_STYLE_POSITION_STICKY == mPosition ||
NS_STYLE_POSITION_FIXED == mPosition;
@ -2235,7 +2229,6 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleDisplay {
inline mozilla::StyleDisplay GetDisplay(const nsIFrame* aContextFrame) const;
inline bool IsFloating(const nsIFrame* aContextFrame) const;
inline bool IsRelativelyPositioned(const nsIFrame* aContextFrame) const;
inline bool IsStickyPositioned(const nsIFrame* aContextFrame) const;
inline bool IsAbsolutelyPositioned(const nsIFrame* aContextFrame) const;
// These methods are defined in nsStyleStructInlines.h.

Просмотреть файл

@ -211,13 +211,6 @@ bool nsStyleDisplay::IsRelativelyPositioned(
!nsSVGUtils::IsInSVGTextSubtree(aContextFrame);
}
bool nsStyleDisplay::IsStickyPositioned(const nsIFrame* aContextFrame) const {
NS_ASSERTION(aContextFrame->StyleDisplay() == this,
"unexpected aContextFrame");
return IsStickyPositionedStyle() &&
!nsSVGUtils::IsInSVGTextSubtree(aContextFrame);
}
bool nsStyleDisplay::IsAbsolutelyPositioned(
const nsIFrame* aContextFrame) const {
NS_ASSERTION(aContextFrame->StyleDisplay() == this,

Просмотреть файл

@ -7268,17 +7268,6 @@ if (IsCSSPropertyPrefEnabled("layout.css.osx-font-smoothing.enabled")) {
};
}
if (IsCSSPropertyPrefEnabled("layout.css.scroll-anchoring.enabled")) {
gCSSProperties["overflow-anchor"] = {
domProp: "overflowAnchor",
inherited: false,
type: CSS_TYPE_LONGHAND,
initial_values: [ "auto" ],
other_values: [ "none" ],
invalid_values: []
};
}
if (IsCSSPropertyPrefEnabled("layout.css.overflow-clip-box.enabled")) {
gCSSProperties["overflow-clip-box-block"] = {
domProp: "overflowClipBoxBlock",

Просмотреть файл

@ -883,25 +883,6 @@ VARCACHE_PREF(
bool, true
)
// Pref to control enabling scroll anchoring.
#ifdef NIGHTLY_BUILD
#define PREF_VALUE true
#else
#define PREF_VALUE false
#endif
VARCACHE_PREF(
"layout.css.scroll-anchoring.enabled",
layout_css_scroll_anchoring_enabled,
bool, PREF_VALUE
)
#undef PREF_VALUE
VARCACHE_PREF(
"layout.css.scroll-anchoring.highlight",
layout_css_scroll_anchoring_highlight,
bool, false
)
//---------------------------------------------------------------------------
// JavaScript prefs
//---------------------------------------------------------------------------

Просмотреть файл

@ -63,7 +63,6 @@ include = [
"Float",
"OverscrollBehavior",
"ScrollSnapType",
"OverflowAnchor",
"OverflowClipBox",
"Resize",
"Overflow",

Просмотреть файл

@ -326,7 +326,6 @@ class Longhand(object):
"Opacity",
"OutlineStyle",
"Overflow",
"OverflowAnchor",
"OverflowClipBox",
"OverflowWrap",
"OverscrollBehavior",

Просмотреть файл

@ -1419,7 +1419,6 @@ impl Clone for ${style_struct.gecko_struct_name} {
"Number": impl_simple,
"Opacity": impl_simple,
"OverflowWrap": impl_simple,
"OverflowAnchor": impl_simple,
"Perspective": impl_style_coord,
"Position": impl_position,
"RGBAColor": impl_rgba_color,

Просмотреть файл

@ -125,18 +125,6 @@ ${helpers.predefined_type(
servo_restyle_damage = "reflow",
)}
${helpers.predefined_type(
"overflow-anchor",
"OverflowAnchor",
"computed::OverflowAnchor::Auto",
initial_specified_value="specified::OverflowAnchor::Auto",
products="gecko",
needs_context=False,
gecko_pref="layout.css.scroll-anchoring.enabled",
spec="https://drafts.csswg.org/css-scroll-anchoring/#exclusion-api",
animation_value_type="discrete",
)}
<% transition_extra_prefixes = "moz:layout.css.prefixes.transitions webkit" %>
${helpers.predefined_type(

Просмотреть файл

@ -13,7 +13,7 @@ use crate::values::specified::box_ as specified;
pub use crate::values::specified::box_::{AnimationName, Appearance, BreakBetween, BreakWithin};
pub use crate::values::specified::box_::{Clear as SpecifiedClear, Float as SpecifiedFloat};
pub use crate::values::specified::box_::{Contain, Display, Overflow, OverflowAnchor, OverflowClipBox};
pub use crate::values::specified::box_::{Contain, Display, Overflow, OverflowClipBox};
pub use crate::values::specified::box_::{OverscrollBehavior, ScrollSnapType};
pub use crate::values::specified::box_::{TouchAction, TransitionProperty, WillChange};

Просмотреть файл

@ -43,7 +43,7 @@ pub use self::border::{BorderImageRepeat, BorderImageSideWidth};
pub use self::border::{BorderImageSlice, BorderImageWidth};
pub use self::box_::{AnimationIterationCount, AnimationName, Contain};
pub use self::box_::{Appearance, BreakBetween, BreakWithin, Clear, Float};
pub use self::box_::{Display, Overflow, OverflowAnchor, TransitionProperty};
pub use self::box_::{Display, Overflow, TransitionProperty};
pub use self::box_::{OverflowClipBox, OverscrollBehavior, Perspective, Resize};
pub use self::box_::{ScrollSnapType, TouchAction, VerticalAlign, WillChange};
pub use self::color::{Color, ColorPropertyValue, RGBAColor};

Просмотреть файл

@ -413,26 +413,6 @@ pub enum OverscrollBehavior {
None,
}
#[allow(missing_docs)]
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
#[derive(
Clone,
Copy,
Debug,
Eq,
MallocSizeOf,
Parse,
PartialEq,
SpecifiedValueInfo,
ToComputedValue,
ToCss,
)]
#[repr(u8)]
pub enum OverflowAnchor {
Auto,
None,
}
#[allow(missing_docs)]
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
#[derive(

Просмотреть файл

@ -36,7 +36,7 @@ pub use self::border::{BorderCornerRadius, BorderImageSlice, BorderImageWidth};
pub use self::border::{BorderImageRepeat, BorderImageSideWidth};
pub use self::border::{BorderRadius, BorderSideWidth, BorderSpacing, BorderStyle};
pub use self::box_::{AnimationIterationCount, AnimationName, Contain, Display};
pub use self::box_::{Appearance, BreakBetween, BreakWithin, Clear, Float, Overflow, OverflowAnchor};
pub use self::box_::{Appearance, BreakBetween, BreakWithin, Clear, Float, Overflow};
pub use self::box_::{OverflowClipBox, OverscrollBehavior, Perspective, Resize};
pub use self::box_::{ScrollSnapType, TouchAction, TransitionProperty, VerticalAlign, WillChange};
pub use self::color::{Color, ColorPropertyValue, RGBAColor};

Просмотреть файл

@ -1 +0,0 @@
prefs: [layout.css.scroll-anchoring.enabled:true]

Просмотреть файл

@ -0,0 +1,4 @@
[abspos-containing-block-outside-scroller.html]
[Abs-pos descendant with containing block outside the scroller.]
expected: FAIL

Просмотреть файл

@ -0,0 +1,4 @@
[abspos-contributes-to-static-parent-bounds.html]
[Abs-pos with zero-height static parent.]
expected: FAIL

Просмотреть файл

@ -0,0 +1,7 @@
[ancestor-change-heuristic.html]
[Ancestor changes in document scroller.]
expected: FAIL
[Ancestor changes in scrollable <div>.]
expected: FAIL

Просмотреть файл

@ -0,0 +1,4 @@
[anchor-updates-after-explicit-scroll.html]
[Anchor node recomputed after an explicit scroll occurs.]
expected: FAIL

Просмотреть файл

@ -0,0 +1,4 @@
[anchoring-with-bounds-clamping-div.html]
[Anchoring combined with scroll bounds clamping in a <div>.]
expected: FAIL

Просмотреть файл

@ -0,0 +1,4 @@
[anchoring-with-bounds-clamping.html]
[Anchoring combined with scroll bounds clamping in the document.]
expected: FAIL

Просмотреть файл

@ -0,0 +1,4 @@
[anonymous-block-box.html]
[Anchor selection descent into anonymous block boxes.]
expected: FAIL

Просмотреть файл

@ -0,0 +1,4 @@
[basic.html]
[Minimal scroll anchoring example.]
expected: FAIL

Просмотреть файл

@ -0,0 +1,4 @@
[clipped-scrollers-skipped.html]
[Anchor selection with nested scrollers.]
expected: FAIL

Просмотреть файл

@ -0,0 +1,4 @@
[descend-into-container-with-float.html]
[Zero-height container with float.]
expected: FAIL

Просмотреть файл

@ -0,0 +1,4 @@
[descend-into-container-with-overflow.html]
[Zero-height container with visible overflow.]
expected: FAIL

Просмотреть файл

@ -0,0 +1,4 @@
[exclude-fixed-position.html]
[Fixed-position header.]
expected: FAIL

Просмотреть файл

@ -0,0 +1,4 @@
[inline-block.html]
[Anchor selection descent into inline blocks.]
expected: FAIL

Просмотреть файл

@ -1,5 +1,4 @@
[negative-layout-overflow.html]
[Anchor selection accounts for negative positioning.]
expected: FAIL
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1517287

Просмотреть файл

@ -0,0 +1,7 @@
[opt-out.html]
[Disabled on document, enabled on div.]
expected: FAIL
[Enabled on document, disabled on div.]
expected: FAIL

Просмотреть файл

@ -0,0 +1,7 @@
[position-change-heuristic.html]
[Position changes in document scroller.]
expected: FAIL
[Position changes in scrollable <div>.]
expected: FAIL

Просмотреть файл

@ -1,11 +1,19 @@
[start-edge-in-block-layout-direction.html]
[Horizontal LTR.]
expected: FAIL
[Horizontal RTL.]
expected: FAIL
[Vertical-LR LTR.]
expected: FAIL
[Vertical-LR RTL.]
expected: FAIL
[Vertical-RL LTR.]
expected: FAIL
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1447743
issue: https://github.com/w3c/csswg-drafts/issues/2704
[Vertical-RL RTL.]
expected: FAIL
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1447743
issue: https://github.com/w3c/csswg-drafts/issues/2704

Просмотреть файл

@ -0,0 +1,4 @@
[subtree-exclusion.html]
[Subtree exclusion with overflow-anchor.]
expected: FAIL

Просмотреть файл

@ -1,6 +1,4 @@
[text-anchor-in-vertical-rl.html]
[Line at edge of scrollport shouldn't jump visually when content is inserted before]
expected: FAIL
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1447743
issue: https://github.com/w3c/csswg-drafts/issues/2704

Просмотреть файл

@ -0,0 +1,4 @@
[wrapped-text.html]
[Anchoring with text wrapping changes.]
expected: FAIL

Просмотреть файл

@ -3,7 +3,7 @@
<script src="/resources/testharnessreport.js"></script>
<style>
#space { height: 4000px; }
#space { height: 1000px; }
#ancestor { position: relative; }
#before, #anchor { height: 100px; }
#anchor { background-color: green; }

Просмотреть файл

@ -6,7 +6,7 @@
#changer { height: 1500px; }
#anchor {
width: 150px;
height: 4000px;
height: 1000px;
background-color: pink;
}

Просмотреть файл

@ -3,7 +3,7 @@
<script src="/resources/testharnessreport.js"></script>
<style>
body { height: 4000px; }
body { height: 1000px; }
div { height: 100px; }
</style>

Просмотреть файл

@ -3,7 +3,7 @@
<script src="/resources/testharnessreport.js"></script>
<style>
body { height: 4000px; }
body { height: 1000px; }
#outer { width: 300px; }
#outer:after { content: " "; clear:both; display: table; }
#float {

Просмотреть файл

@ -3,7 +3,7 @@
<script src="/resources/testharnessreport.js"></script>
<style>
body { height: 4000px; }
body { height: 1000px; }
#outer { width: 300px; }
#zeroheight { height: 0px; }
#changer { height: 100px; background-color: red; }

Просмотреть файл

@ -3,7 +3,7 @@
<script src="/resources/testharnessreport.js"></script>
<style>
body { height: 4000px; margin: 0; }
body { height: 1000px; margin: 0; }
#fixed, #content { width: 200px; height: 100px; }
#fixed { position: fixed; left: 100px; top: 50px; }
#before { height: 50px; }

Просмотреть файл

@ -3,7 +3,7 @@
<script src="/resources/testharnessreport.js"></script>
<style>
body { height: 4000px }
body { height: 1000px }
#outer { line-height: 100px }
#ib1, #ib2 { display: inline-block }

Просмотреть файл

@ -4,7 +4,7 @@
<style>
#space {
height: 4000px;
height: 1000px;
}
#header {
background-color: #F5B335;

Просмотреть файл

@ -32,11 +32,9 @@ html.vrl { writing-mode: vertical-rl; }
.vpush { height: 80px !important; }
.hpush { width: 70px !important; }
#anchor-container {
display: inline-block;
}
#anchor {
position: relative;
display: inline-block;
background-color: #8e8;
min-width: 100px;
min-height: 100px;
@ -51,10 +49,8 @@ html.vrl { writing-mode: vertical-rl; }
</style>
<div id="container">
<div id="block_pusher"></div><br>
<div id="inline_pusher"></div><div id="anchor-container">
<div id="anchor">
<div id="grower"></div>
</div>
<div id="inline_pusher"></div><div id="anchor">
<div id="grower"></div>
</div>
</div>
<script>

Просмотреть файл

@ -3,7 +3,7 @@
<script src="/resources/testharnessreport.js"></script>
<style>
body { height: 4000px }
body { height: 1000px }
#A, #B { width: 100px; background-color: #afa; }
#B { height: 100px; }
#inner { width: 100px; height: 100px; background-color: pink; }

Просмотреть файл

@ -7,7 +7,7 @@ body {
position: absolute;
font-size: 100px;
width: 200px;
height: 4000px;
height: 1000px;
line-height: 100px;
}