diff --git a/layout/forms/nsFieldSetFrame.cpp b/layout/forms/nsFieldSetFrame.cpp index e23921eca05f..dc75294e3b43 100644 --- a/layout/forms/nsFieldSetFrame.cpp +++ b/layout/forms/nsFieldSetFrame.cpp @@ -914,12 +914,10 @@ void nsFieldSetFrame::EnsureChildContinuation(nsIFrame* aChild, } } if (aStatus.IsOverflowIncomplete()) { - if (nsFrameList* eoc = - GetPropTableFrames(ExcessOverflowContainersProperty())) { + if (nsFrameList* eoc = GetExcessOverflowContainers()) { eoc->AppendFrames(nullptr, nifs); } else { - SetPropTableFrames(new (PresShell()) nsFrameList(nifs), - ExcessOverflowContainersProperty()); + SetExcessOverflowContainers(std::move(nifs)); } } else { if (nsFrameList* oc = GetOverflowFrames()) { diff --git a/layout/generic/nsBlockFrame.cpp b/layout/generic/nsBlockFrame.cpp index f784353174d8..d1b4a36141b3 100644 --- a/layout/generic/nsBlockFrame.cpp +++ b/layout/generic/nsBlockFrame.cpp @@ -5169,8 +5169,7 @@ bool nsBlockFrame::DrainOverflowLines() { // prev-in-flow. We'll append these to mFrames to ensure the continuations // are ordered. auto HasOverflowContainers = [this]() -> bool { - return GetOverflowContainers() || - GetPropTableFrames(ExcessOverflowContainersProperty()); + return GetOverflowContainers() || GetExcessOverflowContainers(); }; nsFrameList ocContinuations; if (HasOverflowContainers()) { diff --git a/layout/generic/nsContainerFrame.cpp b/layout/generic/nsContainerFrame.cpp index 8469491db5c6..00dac1d26ac5 100644 --- a/layout/generic/nsContainerFrame.cpp +++ b/layout/generic/nsContainerFrame.cpp @@ -305,8 +305,7 @@ const nsFrameList& nsContainerFrame::GetChildList(ChildListID aListID) const { return list ? *list : nsFrameList::EmptyList(); } case kExcessOverflowContainersList: { - nsFrameList* list = - GetPropTableFrames(ExcessOverflowContainersProperty()); + nsFrameList* list = GetExcessOverflowContainers(); return list ? *list : nsFrameList::EmptyList(); } case kBackdropList: { @@ -1441,7 +1440,7 @@ nsresult nsContainerFrame::StealFrame(nsIFrame* aChild) { if (!list || !list->ContainsFrame(aChild)) { list = GetOverflowContainers(); if (!list || !list->ContainsFrame(aChild)) { - list = GetProperty(ExcessOverflowContainersProperty()); + list = GetExcessOverflowContainers(); MOZ_ASSERT(list && list->ContainsFrame(aChild), "aChild isn't our child" " or on a frame list not supported by StealFrame"); @@ -2053,12 +2052,10 @@ void nsContainerFrame::MergeSortedExcessOverflowContainers(nsFrameList& aList) { aList.FirstChild()->HasAnyStateBits(NS_FRAME_IS_OVERFLOW_CONTAINER), "this is the wrong list to put this child frame"); MOZ_ASSERT(aList.FirstChild()->GetParent() == this); - nsFrameList* eoc = GetPropTableFrames(ExcessOverflowContainersProperty()); - if (eoc) { + if (nsFrameList* eoc = GetExcessOverflowContainers()) { MergeSortedFrameLists(*eoc, aList, GetContent()); } else { - SetPropTableFrames(new (PresShell()) nsFrameList(aList), - ExcessOverflowContainersProperty()); + SetExcessOverflowContainers(std::move(aList)); } } @@ -2248,7 +2245,7 @@ nsFrameList* nsContainerFrame::DrainExcessOverflowContainersList( NS_ASSERTION(!(overflowContainers && GetPrevInFlow() && static_cast(GetPrevInFlow()) - ->GetPropTableFrames(ExcessOverflowContainersProperty())), + ->GetExcessOverflowContainers()), "conflicting overflow containers lists"); if (!overflowContainers) { @@ -2940,8 +2937,7 @@ void nsOverflowContinuationTracker::SetupOverflowContList() { } } if (!mOverflowContList) { - mOverflowContList = mParent->GetPropTableFrames( - nsContainerFrame::ExcessOverflowContainersProperty()); + mOverflowContList = mParent->GetExcessOverflowContainers(); if (mOverflowContList) { SetUpListWalker(); } @@ -3044,10 +3040,14 @@ nsresult nsOverflowContinuationTracker::Insert(nsIFrame* aOverflowCont, aOverflowCont->AddStateBits(NS_FRAME_IS_OVERFLOW_CONTAINER); } if (!mOverflowContList) { + // Note: We don't use SetExcessOverflowContainers() since it requires + // setting a non-empty list. It's OK to manually set an empty list to + // ExcessOverflowContainersProperty() because we are going to insert + // aOverflowCont to mOverflowContList below, which guarantees an nonempty + // list in ExcessOverflowContainersProperty(). mOverflowContList = new (presContext->PresShell()) nsFrameList(); - mParent->SetPropTableFrames( - mOverflowContList, - nsContainerFrame::ExcessOverflowContainersProperty()); + mParent->SetProperty(nsContainerFrame::ExcessOverflowContainersProperty(), + mOverflowContList); SetUpListWalker(); } if (aOverflowCont->GetParent() != mParent) { @@ -3137,8 +3137,7 @@ void nsOverflowContinuationTracker::EndFinish(nsIFrame* aChild) { return; } // Forget mOverflowContList if it was deleted. - nsFrameList* eoc = mParent->GetProperty( - nsContainerFrame::ExcessOverflowContainersProperty()); + nsFrameList* eoc = mParent->GetExcessOverflowContainers(); if (eoc != mOverflowContList) { nsFrameList* oc = mParent->GetOverflowContainers(); if (oc != mOverflowContList) { @@ -3200,10 +3199,8 @@ void nsContainerFrame::SanityCheckChildListsBeforeReflow() const { const auto* pif = static_cast(GetPrevInFlow()); if (pif) { const nsFrameList* oc = GetOverflowContainers(); - const nsFrameList* eoc = - GetPropTableFrames(ExcessOverflowContainersProperty()); - const nsFrameList* pifEOC = - pif->GetPropTableFrames(ExcessOverflowContainersProperty()); + const nsFrameList* eoc = GetExcessOverflowContainers(); + const nsFrameList* pifEOC = pif->GetExcessOverflowContainers(); for (const nsIFrame* child : pif->GetChildList(kPrincipalList)) { const nsIFrame* childNIF = child->GetNextInFlow(); MOZ_ASSERT(!childNIF || mFrames.ContainsFrame(childNIF) || diff --git a/layout/generic/nsContainerFrame.h b/layout/generic/nsContainerFrame.h index d445f2f68edb..686f6c88f080 100644 --- a/layout/generic/nsContainerFrame.h +++ b/layout/generic/nsContainerFrame.h @@ -536,10 +536,12 @@ class nsContainerFrame : public nsSplittableFrame { */ /** - * Get the frames on the overflow list. Can return null if there are no - * overflow frames. The caller does NOT take ownership of the list; it's - * still owned by this frame. A non-null return value indicates that the - * list is nonempty. + * Get the frames on the overflow list, overflow containers list, or excess + * overflow containers list. Can return null if there are no frames in the + * list. + * + * The caller does NOT take ownership of the list; it's still owned by this + * frame. A non-null return value indicates that the list is non-empty. */ [[nodiscard]] nsFrameList* GetOverflowFrames() const { nsFrameList* list = GetProperty(OverflowProperty()); @@ -552,14 +554,22 @@ class nsContainerFrame : public nsSplittableFrame { "Unexpected empty overflow containers list"); return list; } + [[nodiscard]] nsFrameList* GetExcessOverflowContainers() const { + nsFrameList* list = GetProperty(ExcessOverflowContainersProperty()); + NS_ASSERTION(!list || !list->IsEmpty(), + "Unexpected empty overflow containers list"); + return list; + } /** - * As GetOverflowFrames, but removes the overflow frames property. The - * caller is responsible for deleting nsFrameList and either passing - * ownership of the frames to someone else or destroying the frames. - * A non-null return value indicates that the list is nonempty. The - * recommended way to use this function it to assign its return value - * into an AutoFrameListPtr. + * Same as the Get methods above, but also remove and the property from this + * frame. + * + * The caller is responsible for deleting nsFrameList and either passing + * ownership of the frames to someone else or destroying the frames. A + * non-null return value indicates that the list is non-empty. The recommended + * way to use this function it to assign its return value into an + * AutoFrameListPtr. */ [[nodiscard]] nsFrameList* StealOverflowFrames() { nsFrameList* list = TakeProperty(OverflowProperty()); @@ -571,9 +581,17 @@ class nsContainerFrame : public nsSplittableFrame { NS_ASSERTION(!list || !list->IsEmpty(), "Unexpected empty overflow list"); return list; } + [[nodiscard]] nsFrameList* StealExcessOverflowContainers() { + nsFrameList* list = TakeProperty(ExcessOverflowContainersProperty()); + NS_ASSERTION(!list || !list->IsEmpty(), "Unexpected empty overflow list"); + return list; + } /** - * Set the overflow list. aOverflowFrames must not be an empty list. + * Set the overflow list, overflow containers list, or excess overflow + * containers list. The argument must be a *non-empty* list. + * + * After this operation, the argument becomes an empty list. */ void SetOverflowFrames(nsFrameList&& aOverflowFrames) { MOZ_ASSERT(aOverflowFrames.NotEmpty(), "Shouldn't be called"); @@ -589,9 +607,25 @@ class nsContainerFrame : public nsSplittableFrame { SetProperty(OverflowContainersProperty(), new (PresShell()) nsFrameList(std::move(aOverflowContainers))); } + void SetExcessOverflowContainers(nsFrameList&& aExcessOverflowContainers) { + MOZ_ASSERT(aExcessOverflowContainers.NotEmpty(), + "Shouldn't set an empty list!"); + MOZ_ASSERT(!GetProperty(ExcessOverflowContainersProperty()), + "Shouldn't override existing list!"); + MOZ_ASSERT(IsFrameOfType(nsIFrame::eCanContainOverflowContainers), + "This type of frame can't have overflow containers!"); + SetProperty(ExcessOverflowContainersProperty(), + new (PresShell()) + nsFrameList(std::move(aExcessOverflowContainers))); + } /** - * Destroy the overflow list, which must be empty. + * Destroy the overflow list, overflow containers list, or excess overflow + * containers list. + * + * The list to be destroyed must be empty. That is, the caller is responsible + * for either passing ownership of the frames to someone else or destroying + * the frames before calling these methods. */ void DestroyOverflowList() { nsFrameList* list = RemovePropTableFrames(OverflowProperty()); @@ -603,6 +637,11 @@ class nsContainerFrame : public nsSplittableFrame { MOZ_ASSERT(list && list->IsEmpty()); list->Delete(PresShell()); } + void DestroyExcessOverflowContainers() { + nsFrameList* list = TakeProperty(ExcessOverflowContainersProperty()); + MOZ_ASSERT(list && list->IsEmpty()); + list->Delete(PresShell()); + } /** * Moves any frames on both the prev-in-flow's overflow list and the