Backed out 4 changesets (bug 1865012) for causing mochitest failure on test_gencontent.html CLOSED TREE

Backed out changeset 95d920859b91 (bug 1865012)
Backed out changeset 26f6c2765cb5 (bug 1865012)
Backed out changeset 30a3c356ebc9 (bug 1865012)
Backed out changeset 4fb71ff990ae (bug 1865012)
This commit is contained in:
Norisz Fay 2024-01-23 02:17:49 +02:00
Родитель afbf63292f
Коммит 243c7ecbe4
11 изменённых файлов: 96 добавлений и 110 удалений

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

@ -8033,6 +8033,23 @@ nsIFrame* nsCSSFrameConstructor::CreateContinuingFrame(
// aFrame cannot be a dynamic reflow root because it has a continuation now.
aFrame->RemoveStateBits(NS_FRAME_DYNAMIC_REFLOW_ROOT);
// XXXalaskanemily: This avoids linear-time FirstContinuation lookups during
// paginated reflow, but there are a lot of smarter ways to manage this. We
// might also want to share the struct (refcount or some guarantee the struct
// will remain valid during reflow).
if (nsIFrame::PageValues* pageValues =
aFrame->GetProperty(nsIFrame::PageValuesProperty())) {
// It is possible that both values of a PageValues struct can be
// overwritten with null. If that's the case, then as a minor optimization
// we don't need to create a copy of the struct since this property being
// missing is equivalent to having null start/end values.
if (pageValues->mStartPageValue || pageValues->mEndPageValue) {
nsIFrame::PageValues* const newPageValues =
new nsIFrame::PageValues(*pageValues);
newFrame->SetProperty(nsIFrame::PageValuesProperty(), newPageValues);
}
}
MOZ_ASSERT(!newFrame->GetNextSibling(), "unexpected sibling");
return newFrame;
}

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

@ -36,10 +36,10 @@ void nsFrameList::Delete(mozilla::PresShell* aPresShell) {
}
void nsFrameList::DestroyFrames(FrameDestroyContext& aContext) {
while (nsIFrame* frame = RemoveLastChild()) {
while (nsIFrame* frame = RemoveFirstChild()) {
frame->Destroy(aContext);
}
MOZ_ASSERT(!mFirstChild && !mLastChild, "We should've destroyed all frames!");
mLastChild = nullptr;
}
void nsFrameList::RemoveFrame(nsIFrame* aFrame) {
@ -95,15 +95,6 @@ nsIFrame* nsFrameList::RemoveFirstChild() {
return nullptr;
}
nsIFrame* nsFrameList::RemoveLastChild() {
if (mLastChild) {
nsIFrame* lastChild = mLastChild;
RemoveFrame(mLastChild);
return lastChild;
}
return nullptr;
}
void nsFrameList::DestroyFrame(FrameDestroyContext& aContext,
nsIFrame* aFrame) {
MOZ_ASSERT(aFrame, "null ptr");

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

@ -176,11 +176,10 @@ class nsFrameList {
[[nodiscard]] nsFrameList TakeFramesAfter(nsIFrame* aFrame);
/**
* Take the first (or last) child (if any) out of the frame list.
* @return the first (or last) child, or nullptr if the list is empty
* Take the first frame (if any) out of the frame list.
* @return the first child, or nullptr if the list is empty
*/
nsIFrame* RemoveFirstChild();
nsIFrame* RemoveLastChild();
/**
* The following two functions are intended to be used in concert for

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

@ -1345,16 +1345,14 @@ class nsIFrame : public nsQueryFrame {
NS_DECLARE_FRAME_PROPERTY_DELETABLE(PageValuesProperty, PageValues)
const nsAtom* GetStartPageValue() const {
if (const PageValues* const values =
FirstInFlow()->GetProperty(PageValuesProperty())) {
if (const PageValues* const values = GetProperty(PageValuesProperty())) {
return values->mStartPageValue;
}
return nullptr;
}
const nsAtom* GetEndPageValue() const {
if (const PageValues* const values =
FirstInFlow()->GetProperty(PageValuesProperty())) {
if (const PageValues* const values = GetProperty(PageValuesProperty())) {
return values->mEndPageValue;
}
return nullptr;

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

@ -359,8 +359,10 @@ void nsLineBox::DeleteLineList(nsPresContext* aPresContext, nsLineList& aLines,
line->SwitchToCounter(); // Avoid expensive has table removals.
}
while (line->GetChildCount() > 0) {
nsIFrame* child = aFrames->RemoveLastChild();
nsIFrame* child = aFrames->RemoveFirstChild();
MOZ_DIAGNOSTIC_ASSERT(child->PresContext() == aPresContext);
MOZ_DIAGNOSTIC_ASSERT(child == line->mFirstChild, "Lines out of sync");
line->mFirstChild = aFrames->FirstChild();
line->NoteFrameRemoved(child);
child->Destroy(aContext);
}

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

@ -421,6 +421,21 @@ void nsPageContentFrame::EnsurePageName() {
SetComputedStyleWithoutNotification(pageContentPseudoStyle);
}
nsIFrame* nsPageContentFrame::FirstContinuation() const {
const nsContainerFrame* const parent = GetParent();
MOZ_ASSERT(parent && parent->IsPageFrame(),
"Parent of nsPageContentFrame should be nsPageFrame");
// static cast so the compiler has a chance to devirtualize the call.
const auto* const pageFrameParent = static_cast<const nsPageFrame*>(parent);
nsPageContentFrame* const pageContentFrame =
static_cast<const nsPageFrame*>(pageFrameParent->FirstContinuation())
->PageContentFrame();
MOZ_ASSERT(pageContentFrame && !pageContentFrame->GetPrevContinuation(),
"First descendent of nsPageSequenceFrame should not have a "
"previous continuation");
return pageContentFrame;
}
#ifdef DEBUG_FRAME_DUMP
nsresult nsPageContentFrame::GetFrameName(nsAString& aResult) const {
return MakeFrameName(u"PageContent"_ns, aResult);

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

@ -46,6 +46,13 @@ class nsPageContentFrame final : public mozilla::ViewportFrame {
void EnsurePageName();
// The default implementation of FirstContinuation in nsSplittableFrame is
// implemented in linear time, walking back through the linked list of
// continuations via mPrevContinuation.
// For nsPageContentFrames, we can find the first continuation through the
// frame tree structure in constant time.
nsIFrame* FirstContinuation() const final;
#ifdef DEBUG_FRAME_DUMP
// Debugging
nsresult GetFrameName(nsAString& aResult) const override;

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

@ -802,6 +802,35 @@ double nsPageFrame::GetPageOrientationRotation(nsSharedPageData* aPD) const {
return 0.0;
}
nsIFrame* nsPageFrame::FirstContinuation() const {
// Walk up to our grandparent, and then to down the grandparent's first
// child, and then that frame's first child.
// At every step we assert the frames are the type we expect them to be.
const nsContainerFrame* const parent = GetParent();
MOZ_ASSERT(parent && parent->IsPrintedSheetFrame(),
"Parent of nsPageFrame should be PrintedSheetFrame");
const nsContainerFrame* const pageSequenceFrame = parent->GetParent();
MOZ_ASSERT(pageSequenceFrame && pageSequenceFrame->IsPageSequenceFrame(),
"Parent of PrintedSheetFrame should be nsPageSequenceFrame");
const nsIFrame* const firstPrintedSheetFrame =
pageSequenceFrame->PrincipalChildList().FirstChild();
MOZ_ASSERT(
firstPrintedSheetFrame && firstPrintedSheetFrame->IsPrintedSheetFrame(),
"Should have at least one child in nsPageSequenceFrame, and all "
"children of nsPageSequenceFrame should be PrintedSheetFrames");
nsIFrame* const firstPageFrame =
static_cast<const nsContainerFrame*>(firstPrintedSheetFrame)
->PrincipalChildList()
.FirstChild();
MOZ_ASSERT(firstPageFrame && firstPageFrame->IsPageFrame(),
"Should have at least one child in PrintedSheetFrame, and all "
"children of PrintedSheetFrame should be nsPageFrames");
MOZ_ASSERT(!firstPageFrame->GetPrevContinuation(),
"First descendent of nsPageSequenceFrame should not have a "
"previous continuation");
return firstPageFrame;
}
void nsPageFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsDisplayListSet& aLists) {
nsDisplayList content(aBuilder);

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

@ -85,6 +85,13 @@ class nsPageFrame final : public nsContainerFrame {
// the sheet (i.e. only print preview and save-to-PDF are supported).
double GetPageOrientationRotation(nsSharedPageData* aPD) const;
// The default implementation of FirstContinuation in nsSplittableFrame is
// implemented in linear time, walking back through the linked list of
// continuations via mPrevContinuation.
// For nsPageFrames, we can find the first continuation through the frame
// tree structure in constant time.
nsIFrame* FirstContinuation() const final;
protected:
explicit nsPageFrame(ComputedStyle* aStyle, nsPresContext* aPresContext);
virtual ~nsPageFrame();

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

@ -20,12 +20,6 @@ NS_QUERYFRAME_HEAD(nsSplittableFrame)
NS_QUERYFRAME_ENTRY(nsSplittableFrame)
NS_QUERYFRAME_TAIL_INHERITING(nsIFrame)
// These frame properties cache the first-continuation and first-in-flow frame
// pointers. All nsSplittableFrames other than the first one in the continuation
// chain will have these properties set.
NS_DECLARE_FRAME_PROPERTY_WITHOUT_DTOR(FirstContinuationProperty, nsIFrame);
NS_DECLARE_FRAME_PROPERTY_WITHOUT_DTOR(FirstInFlowProperty, nsIFrame);
void nsSplittableFrame::Init(nsIContent* aContent, nsContainerFrame* aParent,
nsIFrame* aPrevInFlow) {
if (aPrevInFlow) {
@ -57,7 +51,6 @@ void nsSplittableFrame::SetPrevContinuation(nsIFrame* aFrame) {
"creating a loop in continuation chain!");
mPrevContinuation = aFrame;
RemoveStateBits(NS_FRAME_IS_FLUID_CONTINUATION);
UpdateFirstContinuationAndFirstInFlowCache();
}
nsIFrame* nsSplittableFrame::GetNextContinuation() const {
@ -76,19 +69,12 @@ void nsSplittableFrame::SetNextContinuation(nsIFrame* aFrame) {
}
nsIFrame* nsSplittableFrame::FirstContinuation() const {
if (!GetPrevContinuation()) {
MOZ_ASSERT(
!HasProperty(FirstContinuationProperty()),
"The property shouldn't be present on first-continuation itself!");
return const_cast<nsSplittableFrame*>(this);
nsSplittableFrame* firstContinuation = const_cast<nsSplittableFrame*>(this);
while (firstContinuation->mPrevContinuation) {
firstContinuation =
static_cast<nsSplittableFrame*>(firstContinuation->mPrevContinuation);
}
nsIFrame* firstContinuation = GetProperty(FirstContinuationProperty());
MOZ_ASSERT(firstContinuation,
"The property should be set and non-null on all continuations "
"after the first!");
MOZ_ASSERT(!firstContinuation->GetPrevContinuation(),
"First continuation shouldn't have a prev continuation!");
MOZ_ASSERT(firstContinuation, "post-condition failed");
return firstContinuation;
}
@ -140,7 +126,6 @@ void nsSplittableFrame::SetPrevInFlow(nsIFrame* aFrame) {
"creating a loop in continuation chain!");
mPrevContinuation = aFrame;
AddStateBits(NS_FRAME_IS_FLUID_CONTINUATION);
UpdateFirstContinuationAndFirstInFlowCache();
}
nsIFrame* nsSplittableFrame::GetNextInFlow() const {
@ -162,18 +147,11 @@ void nsSplittableFrame::SetNextInFlow(nsIFrame* aFrame) {
}
nsIFrame* nsSplittableFrame::FirstInFlow() const {
if (!GetPrevInFlow()) {
MOZ_ASSERT(!HasProperty(FirstInFlowProperty()),
"The property shouldn't be present on first-in-flow itself!");
return const_cast<nsSplittableFrame*>(this);
nsSplittableFrame* firstInFlow = const_cast<nsSplittableFrame*>(this);
while (nsIFrame* prev = firstInFlow->GetPrevInFlow()) {
firstInFlow = static_cast<nsSplittableFrame*>(prev);
}
nsIFrame* firstInFlow = GetProperty(FirstInFlowProperty());
MOZ_ASSERT(firstInFlow,
"The property should be set and non-null on all in-flows after "
"the first!");
MOZ_ASSERT(!firstInFlow->GetPrevInFlow(),
"First-in-flow shouldn't have a prev-in-flow!");
MOZ_ASSERT(firstInFlow, "post-condition failed");
return firstInFlow;
}
@ -217,45 +195,6 @@ void nsSplittableFrame::RemoveFromFlow(nsIFrame* aFrame) {
aFrame->SetPrevInFlow(nullptr);
}
void nsSplittableFrame::UpdateFirstContinuationAndFirstInFlowCache() {
nsIFrame* oldCachedFirstContinuation =
GetProperty(FirstContinuationProperty());
nsIFrame* newFirstContinuation;
if (nsIFrame* prevContinuation = GetPrevContinuation()) {
newFirstContinuation = prevContinuation->FirstContinuation();
SetProperty(FirstContinuationProperty(), newFirstContinuation);
} else {
newFirstContinuation = this;
RemoveProperty(FirstContinuationProperty());
}
if (oldCachedFirstContinuation != newFirstContinuation) {
// Update the first-continuation cache for our next-continuations in the
// chain.
for (nsIFrame* next = GetNextContinuation(); next;
next = next->GetNextContinuation()) {
next->SetProperty(FirstContinuationProperty(), newFirstContinuation);
}
}
nsIFrame* oldCachedFirstInFlow = GetProperty(FirstInFlowProperty());
nsIFrame* newFirstInFlow;
if (nsIFrame* prevInFlow = GetPrevInFlow()) {
newFirstInFlow = prevInFlow->FirstInFlow();
SetProperty(FirstInFlowProperty(), newFirstInFlow);
} else {
newFirstInFlow = this;
RemoveProperty(FirstInFlowProperty());
}
if (oldCachedFirstInFlow != newFirstInFlow) {
// Update the first-in-flow cache for our next-in-flows in the chain.
for (nsIFrame* next = GetNextInFlow(); next; next = next->GetNextInFlow()) {
next->SetProperty(FirstInFlowProperty(), newFirstInFlow);
}
}
}
NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(ConsumedBSizeProperty, nscoord);
nscoord nsSplittableFrame::CalcAndCacheConsumedBSize() {

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

@ -46,17 +46,12 @@ class nsSplittableFrame : public nsIFrame {
nsIFrame* GetPrevContinuation() const final;
nsIFrame* GetNextContinuation() const final;
// Set a previous non-fluid continuation.
// Set a previous/next non-fluid continuation.
void SetPrevContinuation(nsIFrame*) final;
// Set a next non-fluid continuation.
//
// WARNING: this method updates caches for next-continuations, so it has O(n)
// time complexity over the length of next-continuations in the chain.
void SetNextContinuation(nsIFrame*) final;
// Get the first/last continuation for this frame.
nsIFrame* FirstContinuation() const final;
nsIFrame* FirstContinuation() const override;
nsIFrame* LastContinuation() const final;
#ifdef DEBUG
@ -69,13 +64,8 @@ class nsSplittableFrame : public nsIFrame {
nsIFrame* GetPrevInFlow() const final;
nsIFrame* GetNextInFlow() const final;
// Set a previous fluid continuation.
// Set a previous/next fluid continuation.
void SetPrevInFlow(nsIFrame*) final;
// Set a next fluid continuation.
//
// WARNING: this method updates caches for next-continuations, so it has O(n)
// time complexity over the length of next-continuations in the chain.
void SetNextInFlow(nsIFrame*) final;
// Get the first/last frame in the current flow.
@ -92,14 +82,6 @@ class nsSplittableFrame : public nsIFrame {
ClassID aID)
: nsIFrame(aStyle, aPresContext, aID) {}
// Update the first-continuation and first-in-flow cache for this frame and
// the next-continuations in the chain.
//
// Note: this function assumes that the first-continuation and first-in-flow
// caches are already up-to-date on this frame's
// prev-continuation/prev-in-flow frame (if there is such a frame).
void UpdateFirstContinuationAndFirstInFlowCache();
/**
* Return the sum of the block-axis content size of our previous
* continuations.