Bug 1794415 - Force reflow of fewer anonymous children of content-visibility: hidden r=emilio

Reflow fewer types of anonymous children (only anonymous blocks) of
`content-visibility: hidden` elements. This reduces the number of
reflows for skipped content. This also adjusts to the implementation of
IsHiddenByContentVisibilityOnAnyAncestor() to match the implementation of
IsHiddenByContentVisibilityOfInFlowParentForLayout() in only skipping
one layer of anonymous content.

Differential Revision: https://phabricator.services.mozilla.com/D158961
This commit is contained in:
Martin Robinson 2022-10-11 06:59:52 +00:00
parent f47fc4dad4
commit 683c8233a4
2 changed files with 54 additions and 9 deletions

View File

@ -6734,6 +6734,7 @@ void nsIFrame::DidReflow(nsPresContext* aPresContext,
NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS, ("nsIFrame::DidReflow"));
if (IsHiddenByContentVisibilityOfInFlowParentForLayout()) {
RemoveStateBits(NS_FRAME_IN_REFLOW | NS_FRAME_FIRST_REFLOW);
return;
}
@ -6855,7 +6856,8 @@ bool nsIFrame::HidesContentForLayout() const {
bool nsIFrame::IsHiddenByContentVisibilityOfInFlowParentForLayout() const {
const auto* parent = GetInFlowParent();
return parent && parent->HidesContentForLayout() && !Style()->IsAnonBox();
return parent && parent->HidesContentForLayout() &&
!(Style()->IsAnonBox() && !IsFrameOfType(nsIFrame::eLineParticipant));
}
bool nsIFrame::IsHiddenByContentVisibilityOnAnyAncestor() const {
@ -6863,18 +6865,17 @@ bool nsIFrame::IsHiddenByContentVisibilityOnAnyAncestor() const {
return false;
}
bool isAnonymousBox = Style()->IsAnonBox();
bool isAnonymousBlock =
Style()->IsAnonBox() && !IsFrameOfType(nsIFrame::eLineParticipant);
for (nsIFrame* cur = GetInFlowParent(); cur; cur = cur->GetInFlowParent()) {
if (!isAnonymousBlock && cur->HidesContent()) {
return true;
}
// Anonymous boxes are not hidden by the content-visibility of their first
// non-anonymous ancestor, but can be hidden by ancestors further up the
// tree.
if (isAnonymousBox && !cur->Style()->IsAnonBox()) {
isAnonymousBox = false;
}
if (!isAnonymousBox && cur->HidesContent()) {
return true;
}
isAnonymousBlock = false;
}
return false;

View File

@ -0,0 +1,44 @@
<!DOCTYPE html>
<html>
<meta charset="utf-8">
<title>CSS Contain: Test content-visibility:hidden reflow counts</title>
<link rel="author" title="Martin Robinson" href="mailto:mrobinson@igalia.com">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<body style="content-visibility: hidden;">
hello
</body>
<script>
let gUtils = SpecialPowers.getDOMWindowUtils(window);
let gTestContainer = document.getElementById("test");
function flushLayout() {
document.documentElement.offsetHeight;
}
function getReflowCount() {
flushLayout();
return gUtils.framesReflowed;
}
function runTestFunctionAndCountReflows(testFunction) {
const beforeCount = getReflowCount();
testFunction();
const afterCount = getReflowCount();
console.log(afterCount - beforeCount);
return afterCount - beforeCount;
}
test(() => {
flushLayout();
const reflows = runTestFunctionAndCountReflows(() => {
document.body.innerText = "something else";
});
assert_equals(reflows, 1, "Reflow only triggered on body.");
}, "Changing text of 'content-visibility: hidden' body only triggers a single reflow.");
</script>
</html>