commit 8317428fcdec9ee058e150675ec9c7015602ecac parent 629ba9fbd736e50ece755fcda4212db11650f80c Author: Cristina Horotan <chorotan@mozilla.com> Date: Sun, 23 Nov 2025 07:30:08 +0200 Revert "Bug 1994083 - Add WPTs for abspos fragmentation in vertical-rl writing-mode. r=dholbert" for causing Wr failures nsFrameList::ContinueRemoveFrame related This reverts commit 0bb89a9e15868449c22bf50db0addaa0110ea02b. Revert "Bug 1994083 - Adjust existing WPT expectations. r=dholbert" This reverts commit a716c30e8f170cee00ca806e3b258f06526b2a5e. Revert "Bug 1994083 - Generate display items for frames in absolute child list. r=dholbert,layout-reviewers" This reverts commit 1da35cc35d48f8552e80a045109f99840ef6e292. Revert "Bug 1994083 - Allow AbsoluteContainingBlock to reflow all abspos continuations. r=dholbert,layout-reviewers" This reverts commit 643eec99211ba30e588908baaf8e73c52caba369. Diffstat:
21 files changed, 89 insertions(+), 415 deletions(-)
diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp @@ -867,14 +867,7 @@ void nsFrameConstructorState::PushAbsoluteContainingBlock( }(); if (aNewAbsoluteContainingBlock) { - if (!aNewAbsoluteContainingBlock->GetPrevContinuation()) { - aNewAbsoluteContainingBlock->MarkAsAbsoluteContainingBlock(); - } else { - MOZ_ASSERT( - aNewAbsoluteContainingBlock->GetAbsoluteContainingBlock(), - "nsIFrame::Init() should've constructed AbsoluteContainingBlock in " - "this case, since the frame is a continuation!"); - } + aNewAbsoluteContainingBlock->MarkAsAbsoluteContainingBlock(); } } @@ -2986,20 +2979,12 @@ nsContainerFrame* nsCSSFrameConstructor::ConstructPageFrame( if (!prevPageContentFrame) { // The canvas is an inheriting anon box, so needs to be "owned" by the page // content. - pageContentFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES | - NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN); - // Make it an absolute container for fixed-pos elements - pageContentFrame->MarkAsAbsoluteContainingBlock(); - } else { - MOZ_ASSERT( - pageContentFrame->HasAllStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN), - "This bit should've been carried over from the previous continuation " - "in nsIFrame::Init()."); - MOZ_ASSERT(pageContentFrame->GetAbsoluteContainingBlock(), - "nsIFrame::Init() should've constructed AbsoluteContainingBlock " - "for continuations!"); + pageContentFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES); } SetInitialSingleChild(pageFrame, pageContentFrame); + // Make it an absolute container for fixed-pos elements + pageContentFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN); + pageContentFrame->MarkAsAbsoluteContainingBlock(); RefPtr<ComputedStyle> canvasPseudoStyle = styleSet->ResolveInheritingAnonymousBoxStyle(PseudoStyleType::canvas, diff --git a/layout/base/nsPresContext.cpp b/layout/base/nsPresContext.cpp @@ -333,7 +333,6 @@ static const char* gExactCallbackPrefs[] = { "dom.meta-viewport.enabled", "image.animation_mode", "intl.accept_languages", - "layout.abspos.fragmentainer-aware-positioning.enabled", "layout.css.devPixelsPerPx", "layout.css.dpi", "layout.css.letter-spacing.model", @@ -608,11 +607,6 @@ void nsPresContext::PreferenceChanged(const char* aPrefName) { changeHint |= NS_STYLE_HINT_REFLOW; } - if (prefName.EqualsLiteral( - "layout.abspos.fragmentainer-aware-positioning.enabled")) { - changeHint |= nsChangeHint_ReconstructFrame; - } - // Same, this just frees a bunch of memory. StaticPresData::Get()->InvalidateFontPrefs(); Document()->SetMayNeedFontPrefsUpdate(); diff --git a/layout/forms/nsFieldSetFrame.cpp b/layout/forms/nsFieldSetFrame.cpp @@ -229,7 +229,6 @@ void nsFieldSetFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, if (GetPrevInFlow()) { DisplayOverflowContainers(aBuilder, aLists); - DisplayAbsoluteContinuations(aBuilder, aLists); } nsDisplayListCollection contentDisplayItems(aBuilder); diff --git a/layout/generic/AbsoluteContainingBlock.cpp b/layout/generic/AbsoluteContainingBlock.cpp @@ -14,7 +14,6 @@ #include "AnchorPositioningUtils.h" #include "fmt/format.h" #include "mozilla/CSSAlignUtils.h" -#include "mozilla/DebugOnly.h" #include "mozilla/PresShell.h" #include "mozilla/ReflowInput.h" #include "mozilla/ViewportFrame.h" @@ -88,77 +87,10 @@ void AbsoluteContainingBlock::RemoveFrame(FrameDestroyContext& aContext, FrameChildListID aListID, nsIFrame* aOldFrame) { NS_ASSERTION(mChildListID == aListID, "unexpected child list"); - - if (!StaticPrefs::layout_abspos_fragmentainer_aware_positioning_enabled()) { - if (nsIFrame* nif = aOldFrame->GetNextInFlow()) { - nif->GetParent()->DeleteNextInFlowChild(aContext, nif, false); - } - mAbsoluteFrames.DestroyFrame(aContext, aOldFrame); - return; - } - - AutoTArray<nsIFrame*, 8> delFrames; - for (nsIFrame* f = aOldFrame; f; f = f->GetNextInFlow()) { - delFrames.AppendElement(f); + if (nsIFrame* nif = aOldFrame->GetNextInFlow()) { + nif->GetParent()->DeleteNextInFlowChild(aContext, nif, false); } - for (nsIFrame* delFrame : Reversed(delFrames)) { - delFrame->GetParent()->GetAbsoluteContainingBlock()->StealFrame(delFrame); - delFrame->Destroy(aContext); - } -} - -nsFrameList AbsoluteContainingBlock::StealPushedChildList() { - return std::move(mPushedAbsoluteFrames); -} - -bool AbsoluteContainingBlock::PrepareAbsoluteFrames( - nsContainerFrame* aDelegatingFrame) { - if (!StaticPrefs::layout_abspos_fragmentainer_aware_positioning_enabled()) { - return HasAbsoluteFrames(); - } - - if (const nsIFrame* prevInFlow = aDelegatingFrame->GetPrevInFlow()) { - AbsoluteContainingBlock* prevAbsCB = - prevInFlow->GetAbsoluteContainingBlock(); - MOZ_ASSERT(prevAbsCB, - "If this delegating frame has an absCB, its prev-in-flow must " - "have one, too!"); - - // Prepend the pushed absolute frames from the previous absCB to our - // absolute child list. - nsFrameList pushedFrames = prevAbsCB->StealPushedChildList(); - if (pushedFrames.NotEmpty()) { - mAbsoluteFrames.InsertFrames(aDelegatingFrame, nullptr, - std::move(pushedFrames)); - } - } - - // Our pushed absolute child list might be non-empty if our next-in-flow - // hasn't reflowed yet. Move any child in that list that is a first-in-flow, - // or whose prev-in-flow is not in our absolute child list, into our absolute - // child list. - nsIFrame* child = mPushedAbsoluteFrames.FirstChild(); - while (child) { - nsIFrame* next = child->GetNextInFlow(); - if (!child->GetPrevInFlow() || - child->GetPrevInFlow()->GetParent() != aDelegatingFrame) { - mPushedAbsoluteFrames.RemoveFrame(child); - mAbsoluteFrames.AppendFrame(nullptr, child); - } - child = next; - } - - // TODO (Bug 1994346 or Bug 1997696): Consider stealing absolute frames from - // our next-in-flow's absolute child list. - - return HasAbsoluteFrames(); -} - -void AbsoluteContainingBlock::StealFrame(nsIFrame* aFrame) { - const DebugOnly<bool> frameRemoved = - mAbsoluteFrames.StartRemoveFrame(aFrame) || - mPushedAbsoluteFrames.ContinueRemoveFrame(aFrame); - MOZ_ASSERT(frameRemoved, "Failed to find aFrame from our child lists!"); + mAbsoluteFrames.DestroyFrame(aContext, aOldFrame); } static void MaybeMarkAncestorsAsHavingDescendantDependentOnItsStaticPos( @@ -326,59 +258,29 @@ void AbsoluteContainingBlock::Reflow(nsContainerFrame* aDelegatingFrame, MOZ_ASSERT(!kidStatus.IsInlineBreakBefore(), "ShouldAvoidBreakInside should prevent this from happening"); nsIFrame* nextFrame = kidFrame->GetNextInFlow(); - if (StaticPrefs:: - layout_abspos_fragmentainer_aware_positioning_enabled()) { - if (!kidStatus.IsFullyComplete()) { - if (!nextFrame) { - nextFrame = aPresContext->PresShell() - ->FrameConstructor() - ->CreateContinuingFrame(kidFrame, aDelegatingFrame); - mPushedAbsoluteFrames.AppendFrame(nullptr, nextFrame); - } else if (nextFrame->GetParent() != - aDelegatingFrame->GetNextInFlow()) { - nextFrame->GetParent()->GetAbsoluteContainingBlock()->StealFrame( - nextFrame); - mPushedAbsoluteFrames.AppendFrame(nullptr, nextFrame); - } - reflowStatus.MergeCompletionStatusFrom(kidStatus); - } else if (nextFrame) { - // kidFrame is fully-complete. Delete all its next-in-flows. - FrameDestroyContext context(aPresContext->PresShell()); - nextFrame->GetParent()->GetAbsoluteContainingBlock()->RemoveFrame( - context, FrameChildListID::Absolute, nextFrame); - } - } else { - if (!kidStatus.IsFullyComplete() && - aDelegatingFrame->CanContainOverflowContainers()) { - // Need a continuation - if (!nextFrame) { - nextFrame = aPresContext->PresShell() - ->FrameConstructor() - ->CreateContinuingFrame(kidFrame, aDelegatingFrame); - } - // Add it as an overflow container. - // XXXfr This is a hack to fix some of our printing dataloss. - // See bug 154892. Not sure how to do it "right" yet; probably want - // to keep continuations within an AbsoluteContainingBlock eventually. - // - // NOTE(TYLin): we're now trying to conditionally do this "right" in - // the other branch here, inside of the StaticPrefs pref-check. - tracker.Insert(nextFrame, kidStatus); - reflowStatus.MergeCompletionStatusFrom(kidStatus); - } else if (nextFrame) { - // Delete any continuations - nsOverflowContinuationTracker::AutoFinish fini(&tracker, kidFrame); - FrameDestroyContext context(aPresContext->PresShell()); - nextFrame->GetParent()->DeleteNextInFlowChild(context, nextFrame, - true); + if (!kidStatus.IsFullyComplete() && + aDelegatingFrame->CanContainOverflowContainers()) { + // Need a continuation + if (!nextFrame) { + nextFrame = aPresContext->PresShell() + ->FrameConstructor() + ->CreateContinuingFrame(kidFrame, aDelegatingFrame); } + // Add it as an overflow container. + // XXXfr This is a hack to fix some of our printing dataloss. + // See bug 154892. Not sure how to do it "right" yet; probably want + // to keep continuations within an AbsoluteContainingBlock eventually. + tracker.Insert(nextFrame, kidStatus); + reflowStatus.MergeCompletionStatusFrom(kidStatus); + } else if (nextFrame) { + // Delete any continuations + nsOverflowContinuationTracker::AutoFinish fini(&tracker, kidFrame); + FrameDestroyContext context(aPresContext->PresShell()); + nextFrame->GetParent()->DeleteNextInFlowChild(context, nextFrame, true); } } else { + tracker.Skip(kidFrame, reflowStatus); if (aOverflowAreas) { - if (!StaticPrefs:: - layout_abspos_fragmentainer_aware_positioning_enabled()) { - tracker.Skip(kidFrame, reflowStatus); - } aDelegatingFrame->ConsiderChildOverflow(*aOverflowAreas, kidFrame); } } @@ -558,7 +460,6 @@ bool AbsoluteContainingBlock::FrameDependsOnContainer( void AbsoluteContainingBlock::DestroyFrames(DestroyContext& aContext) { mAbsoluteFrames.DestroyFrames(aContext); - mPushedAbsoluteFrames.DestroyFrames(aContext); } void AbsoluteContainingBlock::MarkSizeDependentFramesDirty() { @@ -1302,74 +1203,43 @@ void AbsoluteContainingBlock::ReflowAbsoluteFrame( // Don't split things below the fold. (Ideally we shouldn't *have* // anything totally below the fold, but we can't position frames - // across next-in-flow breaks yet. (Bug 1994346) + // across next-in-flow breaks yet. (aKidFrame->GetLogicalRect(cb.mRect.Size()).BStart(wm) <= aReflowInput.AvailableBSize()); // Get the border values const LogicalMargin border = - aDelegatingFrame->GetLogicalUsedBorder(outerWM).ApplySkipSides( - aDelegatingFrame->PreReflowBlockLevelLogicalSkipSides()); - - const nsIFrame* kidPrevInFlow = aKidFrame->GetPrevInFlow(); - nscoord availBSize; - if (kidFrameMaySplit) { - availBSize = aReflowInput.AvailableBSize(); - // If aKidFrame is a first-in-flow, we subtract our containing block's - // border-block-start, to consider the available space as starting at the - // containing block's padding-edge. - // - // If aKidFrame is *not* a first-in-flow, then we don't need to subtract - // the containing block's border. Instead, we consider this whole fragment - // as our available space, i.e., we allow abspos continuations to overlap - // any border that their containing block parent might have (including - // borders generated by 'box-decoration-break:clone'). - if (!kidPrevInFlow) { - availBSize -= border.BStart(outerWM); - } - } else { - availBSize = NS_UNCONSTRAINEDSIZE; - } - const LogicalSize availSize(outerWM, cbSize.ISize(outerWM), availBSize); + aDelegatingFrame->GetLogicalUsedBorder(outerWM); + const LogicalSize availSize( + outerWM, cbSize.ISize(outerWM), + kidFrameMaySplit + ? aReflowInput.AvailableBSize() - border.BStart(outerWM) + : NS_UNCONSTRAINEDSIZE); + ReflowInput kidReflowInput(aPresContext, aReflowInput, aKidFrame, availSize.ConvertTo(wm, outerWM), Some(cbSize.ConvertTo(wm, outerWM)), initFlags, {}, {}, aAnchorPosResolutionCache); - // ReflowInput's constructor may change the available block-size to - // unconstrained, e.g. in orthogonal reflow, so we retrieve it again and - // account for kid's constraints in its own writing-mode if needed. - if (!kidPrevInFlow) { - nscoord kidAvailBSize = kidReflowInput.AvailableBSize(); - if (kidAvailBSize != NS_UNCONSTRAINEDSIZE) { - kidAvailBSize -= kidReflowInput.ComputedLogicalMargin(wm).BStart(wm); - const nscoord kidOffsetBStart = - kidReflowInput.ComputedLogicalOffsets(wm).BStart(wm); - if (kidOffsetBStart != NS_AUTOOFFSET) { - kidAvailBSize -= kidOffsetBStart; - } - kidReflowInput.SetAvailableBSize(kidAvailBSize); + if (nscoord kidAvailBSize = kidReflowInput.AvailableBSize(); + kidAvailBSize != NS_UNCONSTRAINEDSIZE) { + // Shrink available block-size if it's constrained. + kidAvailBSize -= kidReflowInput.ComputedLogicalMargin(wm).BStart(wm); + const nscoord kidOffsetBStart = + kidReflowInput.ComputedLogicalOffsets(wm).BStart(wm); + if (NS_AUTOOFFSET != kidOffsetBStart) { + kidAvailBSize -= kidOffsetBStart; } + kidReflowInput.SetAvailableBSize(kidAvailBSize); } // Do the reflow ReflowOutput kidDesiredSize(kidReflowInput); aKidFrame->Reflow(aPresContext, kidDesiredSize, kidReflowInput, aStatus); - if (aKidFrame->IsMenuPopupFrame()) { - // Do nothing. Popup frame will handle its own positioning. - } else if (kidPrevInFlow) { - // aKidFrame is a next-in-flow. Place it at the block-edge start of its - // containing block, with the same inline-position as its prev-in-flow. - const nsSize cbBorderBoxSize = - (cbSize + border.Size(outerWM)).GetPhysicalSize(outerWM); - const LogicalPoint kidPos( - outerWM, kidPrevInFlow->IStart(outerWM, cbBorderBoxSize), 0); - const LogicalSize kidSize = kidDesiredSize.Size(outerWM); - const LogicalRect kidRect(outerWM, kidPos, kidSize); - aKidFrame->SetRect(outerWM, kidRect, cbBorderBoxSize); - } else { - // Position the child relative to our padding edge. + // Position the child relative to our padding edge. Don't do this for + // popups, which handle their own positioning. + if (!aKidFrame->IsMenuPopupFrame()) { const LogicalSize kidSize = kidDesiredSize.Size(outerWM); LogicalMargin offsets = kidReflowInput.ComputedLogicalOffsets(outerWM); diff --git a/layout/generic/AbsoluteContainingBlock.h b/layout/generic/AbsoluteContainingBlock.h @@ -57,9 +57,6 @@ class AbsoluteContainingBlock { } const nsFrameList& GetChildList() const { return mAbsoluteFrames; } - const nsFrameList& GetPushedChildList() const { - return mPushedAbsoluteFrames; - } void SetInitialChildList(nsIFrame* aDelegatingFrame, FrameChildListID aListID, nsFrameList&& aChildList); @@ -70,30 +67,6 @@ class AbsoluteContainingBlock { void RemoveFrame(FrameDestroyContext&, FrameChildListID, nsIFrame*); /** - * Return the pushed absolute frames. The caller is responsible for passing - * the ownership of the frames to someone else, or destroying them. - */ - [[nodiscard]] nsFrameList StealPushedChildList(); - - /** - * Prepare our absolute child list so that it is ready to reflow by moving all - * the pushed absolute frames in aDelegatingFrame's prev-in-flow's absCB, and - * some in our own pushed absolute child list, to our absolute child list. - * - * @return true if we have absolute frames after we return. - */ - bool PrepareAbsoluteFrames(nsContainerFrame* aDelegatingFrame); - - /** - * Return true if we have absolute frames. - * - * Note: During reflow, consider calling PrepareAbsoluteFrames() rather than - * this method; it moves absolute frames from other lists to mAbsoluteFrames, - * which may be needed to get the correct result. - */ - bool HasAbsoluteFrames() const { return mAbsoluteFrames.NotEmpty(); } - - /** * Called by the delegating frame after it has done its reflow first. This * function will reflow any absolutely positioned child frames that need to * be reflowed, e.g., because the absolutely positioned child frame has @@ -118,6 +91,8 @@ class AbsoluteContainingBlock { using DestroyContext = nsIFrame::DestroyContext; void DestroyFrames(DestroyContext&); + bool HasAbsoluteFrames() const { return mAbsoluteFrames.NotEmpty(); } + /** * Mark our size-dependent absolute frames with NS_FRAME_HAS_DIRTY_CHILDREN * so that we'll make sure to reflow them. @@ -188,18 +163,8 @@ class AbsoluteContainingBlock { */ void DoMarkFramesDirty(bool aMarkAllDirty); - /** - * Remove aFrame from one of our frame lists without destroying it. - */ - void StealFrame(nsIFrame* aFrame); - - // Stores the abspos frames that have been placed in this containing block. - nsFrameList mAbsoluteFrames; - - // A temporary frame list used during reflow, storing abspos frames that need - // to be reflowed by the delegating frame's next-in-flow after transferring - // them to its own AbsoluteContainingBlock. - nsFrameList mPushedAbsoluteFrames; + protected: + nsFrameList mAbsoluteFrames; // additional named child list #ifdef DEBUG // FrameChildListID::Fixed or FrameChildListID::Absolute diff --git a/layout/generic/ReflowInput.cpp b/layout/generic/ReflowInput.cpp @@ -2106,6 +2106,15 @@ static nscoord CalcQuirkContainingBlockHeight( LogicalSize ReflowInput::ComputeContainingBlockRectangle( nsPresContext* aPresContext, const ReflowInput* aContainingBlockRI) const { + MOZ_ASSERT(!mFrame->IsAbsolutelyPositioned(mStyleDisplay) || + // XXX: We have a hack putting abspos continuations in overflow + // container lists (bug 154892), so they are not reflowed by + // AbsoluteContainingBlock until we revisit the abspos + // continuations handling. + mFrame->GetPrevInFlow(), + "AbsoluteContainingBlock always provides a containing-block size " + "when creating ReflowInput for its children!"); + LogicalSize cbSize = aContainingBlockRI->ComputedSize(); WritingMode wm = aContainingBlockRI->GetWritingMode(); @@ -2188,20 +2197,6 @@ void ReflowInput::InitConstraints( // If we weren't given a containing block size, then compute one. if (aContainingBlockSize.isNothing()) { cbSize = ComputeContainingBlockRectangle(aPresContext, cbri); - } else if (StaticPrefs:: - layout_abspos_fragmentainer_aware_positioning_enabled() && - mFrame->IsAbsolutelyPositioned(mStyleDisplay) && - mFrame->GetPrevInFlow()) { - // AbsoluteContainingBlock always provides a containing-block size to - // ReflowInput. However, if the delegating frame is a continuation or an - // overflow container (i.e. it has zero block-size), we'll need a - // containing-block size (padding-box size) suitable for resolving the - // abspos continuation's percentage block-size. - // - // Bug 1998818 is to fix the containing-block size for resolving - // percentage block-size for abspos's first-in-flow. - cbSize = ComputeContainingBlockRectangle(aPresContext, cbri) + - cbri->ComputedLogicalPadding(wm).Size(wm); } // See if the containing block height is based on the size of its @@ -2365,8 +2360,8 @@ void ReflowInput::InitConstraints( mComputedMaxSize.SizeTo(mWritingMode, NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE); } else if (mFrame->IsAbsolutelyPositioned(mStyleDisplay) && - // The absolute constraints are needed only for abspos - // first-in-flow, not continuations. + // XXXfr hack for making frames behave properly when in overflow + // container lists, see bug 154892; need to revisit later !mFrame->GetPrevInFlow()) { InitAbsoluteConstraints(cbri, cbSize.ConvertTo(cbri->GetWritingMode(), wm)); diff --git a/layout/generic/nsBlockFrame.cpp b/layout/generic/nsBlockFrame.cpp @@ -1646,9 +1646,8 @@ void nsBlockFrame::Reflow(nsPresContext* aPresContext, ReflowOutput& aMetrics, // resetting the size. Because of this, we must not reflow our abs-pos // children in that situation --- what we think is our "new size" will not be // our real new size. This also happens to be more efficient. - AbsoluteContainingBlock* absoluteContainer = - IsAbsoluteContainer() ? GetAbsoluteContainingBlock() : nullptr; - if (absoluteContainer && absoluteContainer->PrepareAbsoluteFrames(this)) { + if (HasAbsolutelyPositionedChildren()) { + AbsoluteContainingBlock* absoluteContainer = GetAbsoluteContainingBlock(); bool haveInterrupt = aPresContext->HasPendingInterrupt(); if (aReflowInput.WillReflowAgainForClearance() || haveInterrupt) { // Make sure that when we reflow again we'll actually reflow all the abs @@ -1695,6 +1694,11 @@ void nsBlockFrame::Reflow(nsPresContext* aPresContext, ReflowOutput& aMetrics, !(isRoot && NS_UNCONSTRAINEDSIZE == aReflowInput.ComputedHeight()) && aMetrics.Height() != oldSize.height; + const LogicalRect containingBlock = [&]() { + LogicalRect rect(wm, LogicalPoint(wm), aMetrics.Size(wm)); + rect.Deflate(wm, aReflowInput.ComputedLogicalBorder(wm)); + return rect; + }(); AbsPosReflowFlags flags{AbsPosReflowFlag::AllowFragmentation}; if (cbWidthChanged) { flags += AbsPosReflowFlag::CBWidthChanged; @@ -1706,13 +1710,9 @@ void nsBlockFrame::Reflow(nsPresContext* aPresContext, ReflowOutput& aMetrics, // calculating hypothetical position of absolutely-positioned // frames. SetupLineCursorForQuery(); - - LogicalRect cbRect(wm, LogicalPoint(wm), aMetrics.Size(wm)); - cbRect.Deflate(wm, aReflowInput.ComputedLogicalBorder(wm).ApplySkipSides( - PreReflowBlockLevelLogicalSkipSides())); absoluteContainer->Reflow( this, aPresContext, aReflowInput, reflowStatus, - cbRect.GetPhysicalRect(wm, aMetrics.PhysicalSize()), flags, + containingBlock.GetPhysicalRect(wm, aMetrics.PhysicalSize()), flags, &aMetrics.mOverflowAreas); } } @@ -7764,7 +7764,6 @@ void nsBlockFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, if (GetPrevInFlow()) { DisplayOverflowContainers(aBuilder, aLists); - DisplayAbsoluteContinuations(aBuilder, aLists); for (nsIFrame* f : GetChildList(FrameChildListID::Float)) { if (f->HasAnyStateBits(NS_FRAME_IS_PUSHED_FLOAT)) { BuildDisplayListForChild(aBuilder, f, aLists); diff --git a/layout/generic/nsCanvasFrame.cpp b/layout/generic/nsCanvasFrame.cpp @@ -219,7 +219,6 @@ void nsCanvasFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, "::-moz-{scrolled-,}canvas doesn't have native appearance"); if (GetPrevInFlow()) { DisplayOverflowContainers(aBuilder, aLists); - DisplayAbsoluteContinuations(aBuilder, aLists); } // Force a background to be shown. We may have a background propagated to us, diff --git a/layout/generic/nsContainerFrame.cpp b/layout/generic/nsContainerFrame.cpp @@ -846,23 +846,21 @@ void nsContainerFrame::ReflowAbsoluteFrames(nsPresContext* aPresContext, ReflowOutput& aDesiredSize, const ReflowInput& aReflowInput, nsReflowStatus& aStatus) { - AbsoluteContainingBlock* absoluteContainer = - IsAbsoluteContainer() ? GetAbsoluteContainingBlock() : nullptr; - if (absoluteContainer && absoluteContainer->PrepareAbsoluteFrames(this)) { + if (HasAbsolutelyPositionedChildren()) { + AbsoluteContainingBlock* absoluteContainer = GetAbsoluteContainingBlock(); + // The containing block for the abs pos kids is formed by our padding edge. - const auto wm = GetWritingMode(); - LogicalRect cbRect(wm, LogicalPoint(wm), aDesiredSize.Size(wm)); - cbRect.Deflate(wm, GetLogicalUsedBorder(wm).ApplySkipSides( - PreReflowBlockLevelLogicalSkipSides())); + nsMargin usedBorder = GetUsedBorder(); + nsRect containingBlock(nsPoint{}, aDesiredSize.PhysicalSize()); + containingBlock.Deflate(usedBorder); // XXX: To optimize the performance, set the flags only when the CB width or // height actually changes. AbsPosReflowFlags flags{AbsPosReflowFlag::AllowFragmentation, AbsPosReflowFlag::CBWidthChanged, AbsPosReflowFlag::CBHeightChanged}; - absoluteContainer->Reflow( - this, aPresContext, aReflowInput, aStatus, - cbRect.GetPhysicalRect(wm, aDesiredSize.PhysicalSize()), flags, - &aDesiredSize.mOverflowAreas); + absoluteContainer->Reflow(this, aPresContext, aReflowInput, aStatus, + containingBlock, flags, + &aDesiredSize.mOverflowAreas); } } @@ -1018,15 +1016,6 @@ void nsContainerFrame::DisplayOverflowContainers( } } -void nsContainerFrame::DisplayAbsoluteContinuations( - nsDisplayListBuilder* aBuilder, const nsDisplayListSet& aLists) { - for (nsIFrame* frame : GetChildList(FrameChildListID::Absolute)) { - if (frame->GetPrevInFlow()) { - BuildDisplayListForChild(aBuilder, frame, aLists); - } - } -} - bool nsContainerFrame::TryRemoveFrame(FrameListPropertyDescriptor aProp, nsIFrame* aChildToRemove) { nsFrameList* list = GetProperty(aProp); @@ -2838,10 +2827,9 @@ void nsContainerFrame::SanityCheckChildListsBeforeReflow() const { const auto didPushItemsBit = IsFlexContainerFrame() ? NS_STATE_FLEX_DID_PUSH_ITEMS : NS_STATE_GRID_DID_PUSH_ITEMS; - ChildListIDs absLists = { - FrameChildListID::Absolute, FrameChildListID::PushedAbsolute, - FrameChildListID::Fixed, FrameChildListID::OverflowContainers, - FrameChildListID::ExcessOverflowContainers}; + ChildListIDs absLists = {FrameChildListID::Absolute, FrameChildListID::Fixed, + FrameChildListID::OverflowContainers, + FrameChildListID::ExcessOverflowContainers}; ChildListIDs itemLists = {FrameChildListID::Principal, FrameChildListID::Overflow}; for (const nsIFrame* f = this; f; f = f->GetNextInFlow()) { diff --git a/layout/generic/nsContainerFrame.h b/layout/generic/nsContainerFrame.h @@ -437,15 +437,6 @@ class nsContainerFrame : public nsSplittableFrame { const nsDisplayListSet& aLists); /** - * Add absolute frame continuations to the display list. - * - * Note: for absolute frame's first-in-flow, it will be painted through its - * placeholder frame. - */ - void DisplayAbsoluteContinuations(nsDisplayListBuilder* aBuilder, - const nsDisplayListSet& aLists); - - /** * Builds display lists for the children. The background * of each child is placed in the Content() list (suitable for inline * children and other elements that behave like inlines, diff --git a/layout/generic/nsFlexContainerFrame.cpp b/layout/generic/nsFlexContainerFrame.cpp @@ -2987,7 +2987,6 @@ void nsFlexContainerFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, if (GetPrevInFlow()) { DisplayOverflowContainers(aBuilder, tempLists); - DisplayAbsoluteContinuations(aBuilder, tempLists); } // Our children are all block-level, so their borders/backgrounds all go on diff --git a/layout/generic/nsFrameList.cpp b/layout/generic/nsFrameList.cpp @@ -459,8 +459,6 @@ const char* ChildListName(FrameChildListID aListID) { return "ColGroupList"; case FrameChildListID::Absolute: return "AbsoluteList"; - case FrameChildListID::PushedAbsolute: - return "PushedAbsoluteList"; case FrameChildListID::Fixed: return "FixedList"; case FrameChildListID::Overflow: diff --git a/layout/generic/nsFrameList.h b/layout/generic/nsFrameList.h @@ -36,7 +36,6 @@ enum class FrameChildListID { Principal, ColGroup, Absolute, - PushedAbsolute, Fixed, Overflow, OverflowContainers, diff --git a/layout/generic/nsGridContainerFrame.cpp b/layout/generic/nsGridContainerFrame.cpp @@ -3276,11 +3276,6 @@ struct MOZ_STACK_CLASS nsGridContainerFrame::GridReflowInput { MOZ_ASSERT(mGridItems.Length() == len + 1, "can't find GridItemInfo"); } - if (aGridContainerFrame->IsAbsoluteContainer()) { - // Prepare absolute frames before constructing GridItemInfo. - aGridContainerFrame->GetAbsoluteContainingBlock()->PrepareAbsoluteFrames( - aGridContainerFrame); - } // XXX NOTE: This is O(n^2) in the number of abs.pos. items. (bug 1252186) const nsFrameList& absPosChildren = aGridContainerFrame->GetChildList( aGridContainerFrame->GetAbsoluteListID()); @@ -9306,7 +9301,6 @@ nscoord nsGridContainerFrame::ReflowChildren(GridReflowInput& aGridRI, AbsoluteContainingBlock* absoluteContainer = IsAbsoluteContainer() ? GetAbsoluteContainingBlock() : nullptr; - // We have prepared the absolute frames when initializing GridReflowInput. if (absoluteContainer && absoluteContainer->HasAbsoluteFrames()) { // 'gridOrigin' is the origin of the grid (the start of the first track), // with respect to the grid container's padding-box (CB). @@ -10272,7 +10266,6 @@ void nsGridContainerFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, if (GetPrevInFlow()) { DisplayOverflowContainers(aBuilder, aLists); - DisplayAbsoluteContinuations(aBuilder, aLists); } // Our children are all grid-level boxes, which behave the same as diff --git a/layout/generic/nsIFrame.cpp b/layout/generic/nsIFrame.cpp @@ -644,13 +644,6 @@ void nsIFrame::Init(nsIContent* aContent, nsContainerFrame* aParent, // Copy other bits in nsIFrame from prev-in-flow. mHasColumnSpanSiblings = aPrevInFlow->HasColumnSpanSiblings(); - - // If our prev-in-flow is an absolute containing block, we must be one, too. - if (aPrevInFlow->IsAbsoluteContainer()) { - MOZ_ASSERT(HasAnyStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN), - "We should've carried this bit from our prev-in-flow!"); - MarkAsAbsoluteContainingBlock(); - } } else { PresContext()->ConstructedFrame(); } @@ -2028,24 +2021,18 @@ nscoord nsIFrame::GetLogicalBaseline( } const nsFrameList& nsIFrame::GetChildList(ChildListID aListID) const { - if (IsAbsoluteContainer()) { - if (aListID == GetAbsoluteListID()) { - return GetAbsoluteContainingBlock()->GetChildList(); - } else if (aListID == FrameChildListID::PushedAbsolute) { - return GetAbsoluteContainingBlock()->GetPushedChildList(); - } + if (IsAbsoluteContainer() && aListID == GetAbsoluteListID()) { + return GetAbsoluteContainingBlock()->GetChildList(); + } else { + return nsFrameList::EmptyList(); } - return nsFrameList::EmptyList(); } void nsIFrame::GetChildLists(nsTArray<ChildList>* aLists) const { if (IsAbsoluteContainer()) { - const auto* absCB = GetAbsoluteContainingBlock(); - const nsFrameList& absoluteList = absCB->GetChildList(); + const nsFrameList& absoluteList = + GetAbsoluteContainingBlock()->GetChildList(); absoluteList.AppendIfNonempty(aLists, GetAbsoluteListID()); - const nsFrameList& pushedAbsoluteList = absCB->GetPushedChildList(); - pushedAbsoluteList.AppendIfNonempty(aLists, - FrameChildListID::PushedAbsolute); } } diff --git a/modules/libpref/init/StaticPrefList.yaml b/modules/libpref/init/StaticPrefList.yaml @@ -11080,13 +11080,6 @@ #endif mirror: always -# Enable the support to position absoluetly positioned frames properly across -# fragmentainers (Bug 1994316). -- name: layout.abspos.fragmentainer-aware-positioning.enabled - type: bool - value: false - mirror: always - #--------------------------------------------------------------------------- # Prefs starting with "logging." #--------------------------------------------------------------------------- diff --git a/testing/web-platform/meta/css/css-anchor-position/anchor-position-multicol-012.html.ini b/testing/web-platform/meta/css/css-anchor-position/anchor-position-multicol-012.html.ini @@ -1,2 +1,2 @@ [anchor-position-multicol-012.html] - prefs: [layout.abspos.fragmentainer-aware-positioning.enabled: true] + expected: FAIL diff --git a/testing/web-platform/meta/css/css-break/out-of-flow-in-multicolumn-118.html.ini b/testing/web-platform/meta/css/css-break/out-of-flow-in-multicolumn-118.html.ini @@ -1,2 +0,0 @@ -[out-of-flow-in-multicolumn-118.html] - prefs: [layout.abspos.fragmentainer-aware-positioning.enabled: true] diff --git a/testing/web-platform/meta/css/css-break/out-of-flow-in-multicolumn-119.html.ini b/testing/web-platform/meta/css/css-break/out-of-flow-in-multicolumn-119.html.ini @@ -1,3 +0,0 @@ -[out-of-flow-in-multicolumn-119.html] - expected: FAIL - bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1999862 diff --git a/testing/web-platform/tests/css/css-break/out-of-flow-in-multicolumn-118.html b/testing/web-platform/tests/css/css-break/out-of-flow-in-multicolumn-118.html @@ -1,37 +0,0 @@ -<!DOCTYPE html> -<title>CSS Break Test: Fragmentation of abspos element in a vertical-rl multicol container</title> -<link rel="author" title="Ting-Yu Lin" href="mailto:tlin@mozilla.com"> -<link rel="author" title="Mozilla" href="https://www.mozilla.org/"> -<link rel="help" href="https://drafts.csswg.org/css-position-3/#abspos-breaking"> -<link rel="match" href="../reference/ref-filled-green-100px-square.xht"> - -<style> -.multicol { - writing-mode: vertical-rl; - block-size: 100px; - inline-size: 100px; - column-count: 2; - column-fill: auto; - column-gap: 0; - background: red; -} -.container { - position: relative; - border-block: 20px solid green; - block-size: 160px; -} - -.abspos { - position: absolute; - inline-size: 100%; - block-size: 160px; - background: green; -} -</style> - -<p>Test passes if there is a filled green square and <strong>no red</strong>.</p> -<div class="multicol"> - <div class="container"> - <div class="abspos"></div> - </div> -</div> diff --git a/testing/web-platform/tests/css/css-break/out-of-flow-in-multicolumn-119.html b/testing/web-platform/tests/css/css-break/out-of-flow-in-multicolumn-119.html @@ -1,38 +0,0 @@ -<!DOCTYPE html> -<title>CSS Break Test: Fragmentation of abspos element in a vertical-rl multicol container</title> -<link rel="author" title="Ting-Yu Lin" href="mailto:tlin@mozilla.com"> -<link rel="author" title="Mozilla" href="https://www.mozilla.org/"> -<link rel="help" href="https://drafts.csswg.org/css-position-3/#abspos-breaking"> -<link rel="match" href="../reference/ref-filled-green-100px-square.xht"> - -<style> -.multicol { - writing-mode: vertical-rl; - block-size: 100px; - inline-size: 100px; - column-count: 2; - column-fill: auto; - column-gap: 0; - background: red; -} -.container { - display: flex; - position: relative; - border-block: 20px solid green; - block-size: 160px; -} - -.abspos { - position: absolute; - inline-size: 100%; - block-size: 160px; - background: green; -} -</style> - -<p>Test passes if there is a filled green square and <strong>no red</strong>.</p> -<div class="multicol"> - <div class="container"> - <div class="abspos"></div> - </div> -</div>