tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 37912600c566f976bfe8ee98ae362e241e5eaf0e
parent c8c8d52d0be3bef9fd739aae1748894c93b729db
Author: Ting-Yu Lin <tlin@mozilla.com>
Date:   Fri, 19 Dec 2025 19:35:20 +0000

Bug 2007058 Part 1 - Generalize NS_FRAME_IS_PUSHED_FLOAT bit to NS_FRAME_IS_PUSHED_OUT_OF_FLOW. r=layout-reviewers,emilio

We need a similar concept to mark an abspos frame that is pushed to a later
absolute-containing-block continuation. A frame is either a float or an abspos
and thus lives in a different frame child list, so the same bit can be used in
both scenarios without conflicts.

Differential Revision: https://phabricator.services.mozilla.com/D277137

Diffstat:
Mlayout/base/nsLayoutUtils.cpp | 2+-
Mlayout/generic/BlockReflowState.cpp | 10+++++-----
Mlayout/generic/BlockReflowState.h | 2+-
Mlayout/generic/nsBlockFrame.cpp | 32++++++++++++++++----------------
Mlayout/generic/nsBlockFrame.h | 2+-
Mlayout/generic/nsFrameStateBits.h | 19+++++++++----------
Mlayout/generic/nsIFrame.cpp | 6+++---
Mlayout/painting/nsDisplayList.cpp | 2+-
8 files changed, 37 insertions(+), 38 deletions(-)

diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp @@ -3934,7 +3934,7 @@ nsIFrame* nsLayoutUtils::GetParentOrPlaceholderForCrossDoc( } nsIFrame* nsLayoutUtils::GetDisplayListParent(nsIFrame* aFrame) { - if (aFrame->HasAnyStateBits(NS_FRAME_IS_PUSHED_FLOAT)) { + if (aFrame->HasAnyStateBits(NS_FRAME_IS_PUSHED_OUT_OF_FLOW)) { return aFrame->GetParent(); } return nsLayoutUtils::GetParentOrPlaceholderForCrossDoc(aFrame); diff --git a/layout/generic/BlockReflowState.cpp b/layout/generic/BlockReflowState.cpp @@ -408,7 +408,7 @@ void BlockReflowState::ReconstructMarginBefore(nsLineList::iterator aLine) { void BlockReflowState::AppendPushedFloatChain(nsIFrame* aFloatCont) { nsFrameList* pushedFloats = mBlock->EnsurePushedFloats(); while (true) { - aFloatCont->AddStateBits(NS_FRAME_IS_PUSHED_FLOAT); + aFloatCont->AddStateBits(NS_FRAME_IS_PUSHED_OUT_OF_FLOW); pushedFloats->AppendFrame(mBlock, aFloatCont); aFloatCont = aFloatCont->GetNextInFlow(); if (!aFloatCont || aFloatCont->GetParent() != mBlock) { @@ -511,12 +511,12 @@ bool BlockReflowState::AddFloat(nsLineLayout* aLineLayout, nsIFrame* aFloat, MOZ_ASSERT(aFloat->GetParent(), "float must have parent"); MOZ_ASSERT(aFloat->GetParent()->IsBlockFrameOrSubclass(), "float's parent must be block"); - if (aFloat->HasAnyStateBits(NS_FRAME_IS_PUSHED_FLOAT) || + if (aFloat->HasAnyStateBits(NS_FRAME_IS_PUSHED_OUT_OF_FLOW) || aFloat->GetParent() != mBlock) { - MOZ_ASSERT(aFloat->HasAnyStateBits(NS_FRAME_IS_PUSHED_FLOAT | + MOZ_ASSERT(aFloat->HasAnyStateBits(NS_FRAME_IS_PUSHED_OUT_OF_FLOW | NS_FRAME_FIRST_REFLOW), "float should be in this block unless it was marked as " - "pushed float, or just inserted"); + "pushed out-of-flow, or just inserted"); MOZ_ASSERT(aFloat->GetParent()->FirstContinuation() == mBlock->FirstContinuation()); // If, in a previous reflow, the float was pushed entirely to @@ -530,7 +530,7 @@ bool BlockReflowState::AddFloat(nsLineLayout* aLineLayout, nsIFrame* aFloat, auto* floatParent = static_cast<nsBlockFrame*>(aFloat->GetParent()); floatParent->StealFrame(aFloat); - aFloat->RemoveStateBits(NS_FRAME_IS_PUSHED_FLOAT); + aFloat->RemoveStateBits(NS_FRAME_IS_PUSHED_OUT_OF_FLOW); // Appending is fine, since if a float was pushed to the next // page/column, all later floats were also pushed. diff --git a/layout/generic/BlockReflowState.h b/layout/generic/BlockReflowState.h @@ -329,7 +329,7 @@ class BlockReflowState { * pushed floats list. aFloatCont should not be on any child list when making * this call. Its next-in-flows will be removed from mBlock using StealFrame() * before being added to mBlock's pushed floats list. All appended frames will - * be marked NS_FRAME_IS_PUSHED_FLOAT. + * be marked NS_FRAME_IS_PUSHED_OUT_OF_FLOW. */ void AppendPushedFloatChain(nsIFrame* aFloatCont); diff --git a/layout/generic/nsBlockFrame.cpp b/layout/generic/nsBlockFrame.cpp @@ -2903,7 +2903,7 @@ void nsBlockFrame::ReparentFloats(nsIFrame* aFirstFrame, aOldParent->CollectFloats(aFirstFrame, list, aReparentSiblings); if (list.NotEmpty()) { for (nsIFrame* f : list) { - MOZ_ASSERT(!f->HasAnyStateBits(NS_FRAME_IS_PUSHED_FLOAT), + MOZ_ASSERT(!f->HasAnyStateBits(NS_FRAME_IS_PUSHED_OUT_OF_FLOW), "CollectFloats should've removed that bit"); ReparentFrame(f, aOldParent, this); } @@ -2979,8 +2979,8 @@ bool nsBlockFrame::ReflowDirtyLines(BlockReflowState& aState) { bool needToRecoverState = false; // Float continuations were reflowed in ReflowPushedFloats bool reflowedFloat = - HasFloats() && - GetFloats()->FirstChild()->HasAnyStateBits(NS_FRAME_IS_PUSHED_FLOAT); + HasFloats() && GetFloats()->FirstChild()->HasAnyStateBits( + NS_FRAME_IS_PUSHED_OUT_OF_FLOW); bool lastLineMovedUp = false; // We save up information about BR-clearance here UsedClear inlineFloatClearType = aState.mTrailingClearFromPIF; @@ -5306,7 +5306,7 @@ static bool CheckPlaceholderInLine(nsIFrame* aBlock, nsLineBox* aLine, } NS_ASSERTION(!aFloat->GetPrevContinuation(), "float in a line should never be a continuation"); - NS_ASSERTION(!aFloat->HasAnyStateBits(NS_FRAME_IS_PUSHED_FLOAT), + NS_ASSERTION(!aFloat->HasAnyStateBits(NS_FRAME_IS_PUSHED_OUT_OF_FLOW), "float in a line should never be a pushed float"); nsIFrame* ph = aFloat->FirstInFlow()->GetPlaceholderFrame(); for (nsIFrame* f = ph; f; f = f->GetParent()) { @@ -5702,7 +5702,7 @@ void nsBlockFrame::PushLines(BlockReflowState& aState, if (floats.NotEmpty()) { #ifdef DEBUG for (nsIFrame* f : floats) { - MOZ_ASSERT(!f->HasAnyStateBits(NS_FRAME_IS_PUSHED_FLOAT), + MOZ_ASSERT(!f->HasAnyStateBits(NS_FRAME_IS_PUSHED_OUT_OF_FLOW), "CollectFloats should've removed that bit"); } #endif @@ -5831,7 +5831,7 @@ bool nsBlockFrame::DrainOverflowLines() { for (nsIFrame* f : oofs.mList) { nsIFrame* nif = f->GetNextInFlow(); for (; nif && nif->GetParent() == this; nif = nif->GetNextInFlow()) { - MOZ_ASSERT(nif->HasAnyStateBits(NS_FRAME_IS_PUSHED_FLOAT)); + MOZ_ASSERT(nif->HasAnyStateBits(NS_FRAME_IS_PUSHED_OUT_OF_FLOW)); RemoveFloat(nif); pushedFloats.AppendFrame(nullptr, nif); } @@ -5879,7 +5879,7 @@ bool nsBlockFrame::DrainSelfOverflowList() { if (oofs.mList.NotEmpty()) { #ifdef DEBUG for (nsIFrame* f : oofs.mList) { - MOZ_ASSERT(!f->HasAnyStateBits(NS_FRAME_IS_PUSHED_FLOAT), + MOZ_ASSERT(!f->HasAnyStateBits(NS_FRAME_IS_PUSHED_OUT_OF_FLOW), "CollectFloats should've removed that bit"); } #endif @@ -5943,7 +5943,7 @@ void nsBlockFrame::DrainSelfPushedFloats() { // FIXME: This isn't quite right! What if they're all pushed floats? nsIFrame* insertionPrevSibling = nullptr; /* beginning of list */ for (nsIFrame* f = floats ? floats->FirstChild() : nullptr; - f && f->HasAnyStateBits(NS_FRAME_IS_PUSHED_FLOAT); + f && f->HasAnyStateBits(NS_FRAME_IS_PUSHED_OUT_OF_FLOW); f = f->GetNextSibling()) { insertionPrevSibling = f; } @@ -7444,7 +7444,7 @@ void nsBlockFrame::ReflowPushedFloats(BlockReflowState& aState, nsFrameList* floats = GetFloats(); nsIFrame* f = floats ? floats->FirstChild() : nullptr; nsIFrame* prev = nullptr; - while (f && f->HasAnyStateBits(NS_FRAME_IS_PUSHED_FLOAT)) { + while (f && f->HasAnyStateBits(NS_FRAME_IS_PUSHED_OUT_OF_FLOW)) { MOZ_ASSERT(prev == f->GetPrevSibling()); // When we push a first-continuation float in a non-initial reflow, // it's possible that we end up with two continuations with the same @@ -7603,14 +7603,14 @@ bool nsBlockFrame::HasPushedFloatsFromPrevContinuation() const { if (const nsFrameList* floats = GetFloats()) { // If we have pushed floats, then they should be at the beginning of our // float list. - if (floats->FirstChild()->HasAnyStateBits(NS_FRAME_IS_PUSHED_FLOAT)) { + if (floats->FirstChild()->HasAnyStateBits(NS_FRAME_IS_PUSHED_OUT_OF_FLOW)) { return true; } #ifdef DEBUG // Double-check the above assertion that pushed floats should be at the // beginning of our floats list. for (nsIFrame* f : *floats) { - NS_ASSERTION(!f->HasAnyStateBits(NS_FRAME_IS_PUSHED_FLOAT), + NS_ASSERTION(!f->HasAnyStateBits(NS_FRAME_IS_PUSHED_OUT_OF_FLOW), "pushed floats must be at the beginning of the float list"); } #endif @@ -7761,7 +7761,7 @@ void nsBlockFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, DisplayOverflowContainers(aBuilder, aLists); DisplayAbsoluteContinuations(aBuilder, aLists); for (nsIFrame* f : GetChildList(FrameChildListID::Float)) { - if (f->HasAnyStateBits(NS_FRAME_IS_PUSHED_FLOAT)) { + if (f->HasAnyStateBits(NS_FRAME_IS_PUSHED_OUT_OF_FLOW)) { BuildDisplayListForChild(aBuilder, f, aLists); } } @@ -8308,9 +8308,9 @@ void nsBlockFrame::DoCollectFloats(nsIFrame* aFrame, nsFrameList& aList, : nullptr; while (outOfFlowFrame && outOfFlowFrame->GetParent() == this) { RemoveFloat(outOfFlowFrame); - // Remove the IS_PUSHED_FLOAT bit, in case |outOfFlowFrame| came from - // the PushedFloats list. - outOfFlowFrame->RemoveStateBits(NS_FRAME_IS_PUSHED_FLOAT); + // Remove the NS_FRAME_IS_PUSHED_OUT_OF_FLOW bit, in case + // |outOfFlowFrame| came from the PushedFloats list. + outOfFlowFrame->RemoveStateBits(NS_FRAME_IS_PUSHED_OUT_OF_FLOW); aList.AppendFrame(nullptr, outOfFlowFrame); outOfFlowFrame = outOfFlowFrame->GetNextInFlow(); // FIXME: By not pulling floats whose parent is one of our @@ -8354,7 +8354,7 @@ void nsBlockFrame::CheckFloats(BlockReflowState& aState) { bool hasHiddenFloats = false; uint32_t i = 0; for (nsIFrame* f : GetChildList(FrameChildListID::Float)) { - if (f->HasAnyStateBits(NS_FRAME_IS_PUSHED_FLOAT)) { + if (f->HasAnyStateBits(NS_FRAME_IS_PUSHED_OUT_OF_FLOW)) { continue; } // There are chances that the float children won't be added to lines, diff --git a/layout/generic/nsBlockFrame.h b/layout/generic/nsBlockFrame.h @@ -660,7 +660,7 @@ class nsBlockFrame : public nsContainerFrame { * Determine if we have any pushed floats from a previous continuation. * * @returns true, if any of the floats at the beginning of our floats list - * have the NS_FRAME_IS_PUSHED_FLOAT bit set; false otherwise. + * have the NS_FRAME_IS_PUSHED_OUT_OF_FLOW bit set; false otherwise. */ bool HasPushedFloatsFromPrevContinuation() const; diff --git a/layout/generic/nsFrameStateBits.h b/layout/generic/nsFrameStateBits.h @@ -174,15 +174,14 @@ FRAME_STATE_BIT(Generic, 19, NS_FRAME_REFLOW_ROOT) // NOTE: Bits 20-31 and 60-63 of the frame state are reserved for specific // frame classes. -// This bit is set on floats whose parent does not contain their -// placeholder. This can happen for two reasons: (1) the float was -// split, and this piece is the continuation, or (2) the entire float -// didn't fit on the page. -// Note that this bit is also shared by text frames for -// TEXT_IS_IN_TOKEN_MATHML. That's OK because we only check the -// NS_FRAME_IS_PUSHED_FLOAT bit on frames which we already know are -// out-of-flow. -FRAME_STATE_BIT(Generic, 32, NS_FRAME_IS_PUSHED_FLOAT) +// This bit is set on out-of-flow frames (e.g. floats or absolutely positioned +// elements) whose parent does not contain their placeholder. This can happen +// for two reasons: (1) the frame was split, and this piece is the continuation, +// or (2) the entire frame didn't fit on the fragmentainer (e.g. page/column). +// Note that this bit is also shared by text frames for TEXT_IS_IN_TOKEN_MATHML. +// That's OK because we only check the NS_FRAME_IS_PUSHED_OUT_OF_FLOW bit on +// frames which we already know are out-of-flow. +FRAME_STATE_BIT(Generic, 32, NS_FRAME_IS_PUSHED_OUT_OF_FLOW) // This bit acts as a loop flag for recursive paint server drawing. FRAME_STATE_BIT(Generic, 33, NS_FRAME_DRAWING_AS_PAINTSERVER) @@ -493,7 +492,7 @@ FRAME_STATE_BIT(Text, 31, TEXT_HAS_NONCOLLAPSED_CHARACTERS) // This state bit is set on children of token MathML elements. // NOTE: TEXT_IS_IN_TOKEN_MATHML has a global state bit value that is shared -// with NS_FRAME_IS_PUSHED_FLOAT. +// with NS_FRAME_IS_PUSHED_OUT_OF_FLOW. FRAME_STATE_BIT(Text, 32, TEXT_IS_IN_TOKEN_MATHML) // Set when this text frame is mentioned in the userdata for the diff --git a/layout/generic/nsIFrame.cpp b/layout/generic/nsIFrame.cpp @@ -4339,12 +4339,12 @@ void nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder, aBuilder->ClearWillChangeBudgetStatus(child); } - // If 'child' is a pushed float then it's owned by a block that's not an - // ancestor of the placeholder, and it will be painted by that block and + // If 'child' is a pushed out-of-flow then it's owned by a block that's not + // an ancestor of the placeholder, and it will be painted by that block and // should not be painted through the placeholder. Also recheck // NS_FRAME_TOO_DEEP_IN_FRAME_TREE and NS_FRAME_IS_NONDISPLAY. static const nsFrameState skipFlags = - (NS_FRAME_IS_PUSHED_FLOAT | NS_FRAME_TOO_DEEP_IN_FRAME_TREE | + (NS_FRAME_IS_PUSHED_OUT_OF_FLOW | NS_FRAME_TOO_DEEP_IN_FRAME_TREE | NS_FRAME_IS_NONDISPLAY); if (child->HasAnyStateBits(skipFlags) || nsLayoutUtils::IsPopup(child)) { return; diff --git a/layout/painting/nsDisplayList.cpp b/layout/painting/nsDisplayList.cpp @@ -8850,7 +8850,7 @@ PaintTelemetry::AutoRecordPaint::~AutoRecordPaint() { } static nsIFrame* GetSelfOrPlaceholderFor(nsIFrame* aFrame) { - if (aFrame->HasAnyStateBits(NS_FRAME_IS_PUSHED_FLOAT)) { + if (aFrame->HasAnyStateBits(NS_FRAME_IS_PUSHED_OUT_OF_FLOW)) { return aFrame; }