Bug 1850834 - Don't reframe containing block on insertion when empty. r=jwatt

This is also actually needed to avoid the perf cliff in Perf-Dashboard.

Differential Revision: https://phabricator.services.mozilla.com/D212373
This commit is contained in:
Emilio Cobos Álvarez 2024-06-04 08:53:28 +00:00
parent cce3bdefa5
commit 8467fcc705
2 changed files with 31 additions and 5 deletions

View file

@ -7057,6 +7057,11 @@ void nsCSSFrameConstructor::ContentRangeInserted(nsIContent* aStartChild,
if (LayoutFrameType::Table == frameType ||
LayoutFrameType::TableWrapper == frameType) {
PullOutCaptionFrames(frameList, captionList);
if (prevSibling && prevSibling->IsTableCaption()) {
// This can happen, but only if the table is empty (otherwise
// SafeToInsertPseudoNeedingChildren bails).
prevSibling = nullptr;
}
}
}
@ -11156,6 +11161,25 @@ bool nsCSSFrameConstructor::WipeInsertionParent(nsContainerFrame* aFrame) {
#undef TRACE
}
static bool SafeToInsertPseudoNeedingChildren(nsIFrame* aFrame) {
for (auto& [list, listID] : aFrame->ChildLists()) {
if (list.IsEmpty()) {
continue;
}
// We have some existing frame, usually it would be unsafe to insert. But
// let's make an exception for the synthetic colgroup that tables have,
// since that gets created unconditionally.
if (listID == FrameChildListID::ColGroup) {
if (nsIFrame* f = list.OnlyChild();
f && static_cast<nsTableColGroupFrame*>(f)->IsSynthetic()) {
continue;
}
}
return false;
}
return true;
}
bool nsCSSFrameConstructor::WipeContainingBlock(
nsFrameConstructorState& aState, nsIFrame* aContainingBlock,
nsIFrame* aFrame, FrameConstructionItemList& aItems, bool aIsAppend,
@ -11419,7 +11443,10 @@ bool nsCSSFrameConstructor::WipeContainingBlock(
return false;
}
if (!aItems.AllWantParentType(parentType)) {
// If aFrame is empty, the insertion process will be able to take care of
// creating any needed pseudo-parents.
if (!aItems.AllWantParentType(parentType) &&
!SafeToInsertPseudoNeedingChildren(aFrame)) {
// Reframing aFrame->GetContent() is good enough, since the content of
// table pseudo-frames is the ancestor content.
TRACE("Pseudo-frames going wrong");

View file

@ -20,11 +20,10 @@
const frameCountBeforeReframe = utils.framesConstructed;
// We expect to construct one newly appended block, and reconstruct the
// display:table <body>, which consists of 8 frames including TableWrapper,
// Table, TableRowGroup, TableRow, TableColGroup, TableCol, TableCell, and
// We expect to construct one newly appended block, and the relevant pseudo
// parents: TableRowGroup, TableRow, TableColGroup, TableCol, TableCell, and
// TableCell's inner block.
const expectedFrameConstructionCount = 1 + 8;
const expectedFrameConstructionCount = 1 + 6;
let div = document.createElement("div");
document.body.appendChild(div);