Backed out changeset 7538d23ee88e (bug 1767262) for causing failures at content-visibility-081.html. CLOSED TREE

This commit is contained in:
Butkovits Atila
2022-08-15 20:37:49 +03:00
parent 2a066d4f3a
commit 7925e56c67
12 changed files with 8 additions and 333 deletions

View File

@@ -253,17 +253,7 @@ nsIFrame* nsIContent::GetPrimaryFrame(mozilla::FlushType aType) {
doc->FlushPendingNotifications(aType);
}
auto* frame = GetPrimaryFrame();
if (!frame) {
return nullptr;
}
if (aType == mozilla::FlushType::Layout) {
frame->PresShell()->EnsureReflowIfFrameHasHiddenContent(frame);
frame = GetPrimaryFrame();
}
return frame;
return GetPrimaryFrame();
}
namespace mozilla::dom {

View File

@@ -11821,37 +11821,3 @@ void PresShell::PingPerTickTelemetry(FlushType aFlushType) {
bool PresShell::GetZoomableByAPZ() const {
return mZoomConstraintsClient && mZoomConstraintsClient->GetAllowZoom();
}
void PresShell::EnsureReflowIfFrameHasHiddenContent(nsIFrame* aFrame) {
if (!aFrame || !aFrame->IsSubtreeDirty() ||
!StaticPrefs::layout_css_content_visibility_enabled()) {
return;
}
MOZ_ASSERT(mHiddenContentInForcedLayout.IsEmpty());
nsIFrame* topmostFrameWithContentHidden = nullptr;
for (nsIFrame* cur = aFrame->GetInFlowParent(); cur;
cur = cur->GetInFlowParent()) {
if (cur->IsContentHidden()) {
topmostFrameWithContentHidden = cur;
mHiddenContentInForcedLayout.Insert(cur->GetContent());
}
}
if (mHiddenContentInForcedLayout.IsEmpty()) {
return;
}
// Queue and immediately flush a reflow for this node.
MOZ_ASSERT(topmostFrameWithContentHidden);
FrameNeedsReflow(topmostFrameWithContentHidden, IntrinsicDirty::Resize,
NS_FRAME_IS_DIRTY);
aFrame->PresContext()->Document()->FlushPendingNotifications(
FlushType::Layout);
mHiddenContentInForcedLayout.Clear();
}
bool PresShell::IsForcingLayoutForHiddenContent(const nsIFrame* aFrame) const {
return mHiddenContentInForcedLayout.Contains(aFrame->GetContent());
}

View File

@@ -1739,18 +1739,6 @@ class PresShell final : public nsStubDocumentObserver,
bool GetZoomableByAPZ() const;
/**
* If this frame has content hidden via `content-visibilty` that has a pending
* reflow, force the content to reflow immediately.
*/
void EnsureReflowIfFrameHasHiddenContent(nsIFrame*);
/**
* Whether or not this presshell is is forcing a reflow of hidden content in
* this frame via EnsureReflowIfFrameHasHiddenContent().
*/
bool IsForcingLayoutForHiddenContent(const nsIFrame*) const;
private:
~PresShell();
@@ -3010,8 +2998,6 @@ class PresShell final : public nsStubDocumentObserver,
nsTHashSet<nsIScrollableFrame*> mPendingScrollAnchorAdjustment;
nsTHashSet<nsIScrollableFrame*> mPendingScrollResnap;
nsTHashSet<nsIContent*> mHiddenContentInForcedLayout;
nsCallbackEventRequest* mFirstCallbackEventRequest = nullptr;
nsCallbackEventRequest* mLastCallbackEventRequest = nullptr;

View File

@@ -1262,11 +1262,6 @@ static bool IsLineClampItem(const ReflowInput& aReflowInput) {
void nsBlockFrame::Reflow(nsPresContext* aPresContext, ReflowOutput& aMetrics,
const ReflowInput& aReflowInput,
nsReflowStatus& aStatus) {
if (GetInFlowParent() && GetInFlowParent()->IsContentHiddenForLayout()) {
FinishAndStoreOverflow(&aMetrics, aReflowInput.mStyleDisplay);
return;
}
MarkInReflow();
DO_GLOBAL_REFLOW_COUNT("nsBlockFrame");
DISPLAY_REFLOW(aPresContext, this, aReflowInput, aMetrics, aStatus);
@@ -2536,10 +2531,6 @@ static bool LinesAreEmpty(const nsLineList& aList) {
}
void nsBlockFrame::ReflowDirtyLines(BlockReflowState& aState) {
if (IsContentHiddenForLayout()) {
return;
}
bool keepGoing = true;
bool repositionViews = false; // should we really need this?
bool foundAnyClears = aState.mFloatBreakType != StyleClear::None;

View File

@@ -4546,10 +4546,6 @@ void nsFlexContainerFrame::Reflow(nsPresContext* aPresContext,
ReflowOutput& aReflowOutput,
const ReflowInput& aReflowInput,
nsReflowStatus& aStatus) {
if (GetInFlowParent() && GetInFlowParent()->IsContentHiddenForLayout()) {
return;
}
MarkInReflow();
DO_GLOBAL_REFLOW_COUNT("nsFlexContainerFrame");
DISPLAY_REFLOW(aPresContext, this, aReflowInput, aReflowOutput, aStatus);
@@ -5294,10 +5290,6 @@ std::tuple<nscoord, bool> nsFlexContainerFrame::ReflowChildren(
const nscoord aSumOfPrevInFlowsChildrenBlockSize,
const FlexboxAxisTracker& aAxisTracker, bool aHasLineClampEllipsis,
FlexLayoutResult& aFlr) {
if (IsContentHiddenForLayout()) {
return {0, false};
}
// Before giving each child a final reflow, calculate the origin of the
// flex container's content box (with respect to its border-box), so that
// we can compute our flex item's final positions.
@@ -5516,11 +5508,11 @@ void nsFlexContainerFrame::PopulateReflowOutput(
if (aFlexContainerAscent == nscoord_MIN) {
// Still don't have our baseline set -- this happens if we have no
// children, if our children are huge enough that they have nscoord_MIN
// as their baseline, or our content is hidden in which case, we'll use the
// wrong baseline (but no big deal).
// children (or if our children are huge enough that they have nscoord_MIN
// as their baseline... in which case, we'll use the wrong baseline, but no
// big deal)
NS_WARNING_ASSERTION(
IsContentHidden() || aLines[0].IsEmpty(),
aLines[0].IsEmpty(),
"Have flex items but didn't get an ascent - that's odd (or there are "
"just gigantic sizes involved)");
// Per spec, synthesize baseline from the flex container's content box

View File

@@ -8433,12 +8433,6 @@ nscoord nsGridContainerFrame::ReflowChildren(GridReflowInput& aState,
const nsSize& aContainerSize,
ReflowOutput& aDesiredSize,
nsReflowStatus& aStatus) {
WritingMode wm = aState.mReflowInput->GetWritingMode();
nscoord bSize = aContentArea.BSize(wm);
if (IsContentHiddenForLayout()) {
return bSize;
}
MOZ_ASSERT(aState.mReflowInput);
MOZ_ASSERT(aStatus.IsEmpty(), "Caller should pass a fresh reflow status!");
@@ -8450,6 +8444,8 @@ nscoord nsGridContainerFrame::ReflowChildren(GridReflowInput& aState,
ocStatus, MergeSortedFrameListsFor);
}
WritingMode wm = aState.mReflowInput->GetWritingMode();
nscoord bSize = aContentArea.BSize(wm);
Maybe<Fragmentainer> fragmentainer = GetNearestFragmentainer(aState);
// MasonryLayout() can only handle fragmentation in the masonry-axis,
// so we let ReflowInFragmentainer() deal with grid-axis fragmentation
@@ -8543,10 +8539,6 @@ void nsGridContainerFrame::Reflow(nsPresContext* aPresContext,
ReflowOutput& aDesiredSize,
const ReflowInput& aReflowInput,
nsReflowStatus& aStatus) {
if (GetInFlowParent() && GetInFlowParent()->IsContentHiddenForLayout()) {
return;
}
MarkInReflow();
DO_GLOBAL_REFLOW_COUNT("nsGridContainerFrame");
DISPLAY_REFLOW(aPresContext, this, aReflowInput, aDesiredSize, aStatus);

View File

@@ -6715,10 +6715,6 @@ void nsIFrame::DidReflow(nsPresContext* aPresContext,
const ReflowInput* aReflowInput) {
NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS, ("nsIFrame::DidReflow"));
if (GetInFlowParent() && GetInFlowParent()->IsContentHiddenForLayout()) {
return;
}
SVGObserverUtils::InvalidateDirectRenderingObservers(
this, SVGObserverUtils::INVALIDATE_REFLOW);
@@ -6831,11 +6827,6 @@ bool nsIFrame::IsContentHidden() const {
return IsFrameOfType(nsIFrame::eReplaced) || !StyleDisplay()->IsInlineFlow();
}
bool nsIFrame::IsContentHiddenForLayout() const {
return IsContentHidden() &&
!PresShell()->IsForcingLayoutForHiddenContent(this);
}
bool nsIFrame::AncestorHidesContent() const {
if (!StaticPrefs::layout_css_content_visibility_enabled()) {
return false;

View File

@@ -3150,13 +3150,6 @@ class nsIFrame : public nsQueryFrame {
*/
bool IsContentHidden() const;
/**
* Whether the content is hidden via the `content-visibilty` property for
* layout. Hidden content might not be hidden for layout when forcing layout
* for size queries.
*/
bool IsContentHiddenForLayout() const;
/**
* Returns true if this frame is entirely hidden due the `content-visibility`
* property on an ancestor.

View File

@@ -1 +1,2 @@
prefs: [layout.css.content-visibility.enabled:true]
leak-threshold: [rdd:51200]

View File

@@ -1,2 +0,0 @@
prefs: [layout.css.content-visibility.enabled:true]
leak-threshold: [rdd:51200]

View File

@@ -1,120 +0,0 @@
<!DOCTYPE html>
<html>
<meta charset="utf-8">
<title>CSS Contain: Test content-visibility:hidden reflow counts</title>
<link rel="author" title="Ting-Yu Lin" href="mailto:tlin@mozilla.com">
<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1746098">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<style>
.container {
content-visibility: visible;
contain: strict;
}
.flex {
display: flex;
}
.grid {
display: grid;
grid: repeat(2, 60px) / auto-flow 80px;
}
</style>
<div id="test"></div>
<script>
let gUtils = SpecialPowers.getDOMWindowUtils(window);
let gTestContainer = document.getElementById("test");
function setupContainerWithStrictContainment() {
const container = document.createElement("div");
container.classList.add("container");
gTestContainer.innerHTML = "";
gTestContainer.appendChild(container);
return container;
}
function flushLayout() {
document.documentElement.offsetHeight;
}
function getReflowCount() {
flushLayout();
return gUtils.framesReflowed;
}
function runTestFunctionAndCountReflows(testFunction, container) {
const beforeCount = getReflowCount();
testFunction(container);
const afterCount = getReflowCount();
return afterCount - beforeCount;
}
function assertContentVisibilityHiddenHasFewerReflows(testSetup, testFunction) {
let container = setupContainerWithStrictContainment();
testSetup(container);
flushLayout();
const visibleReflows = runTestFunctionAndCountReflows(testFunction, container);
container = setupContainerWithStrictContainment();
testSetup(container);
container.style.contentVisibility = "hidden";
flushLayout();
const hiddenReflows = runTestFunctionAndCountReflows(testFunction, container);
assert_less_than(hiddenReflows, visibleReflows,
"Style / layout changes in hidden content resulted in fewer reflows than visible content.");
}
test(() => {
assertContentVisibilityHiddenHasFewerReflows(
(container) => {
const div = document.createElement("div");
div.innerText = "Test Content";
container.appendChild(div);
},
(container) => {
container.children[0].style.width = "100px";
container.children[0].style.height = "100px";
});
}, `Avoiding layout while modifying a simple div's style.`);
test(() => {
assertContentVisibilityHiddenHasFewerReflows(
(container) => {
container.classList.add("flex");
const flexContainer = document.createElement("div");
flexContainer.classList.add("flex");
container.appendChild(flexContainer);
container.appendChild(document.createElement("div"));
},
(container) => {
container.children[0].style.flexDirection = "row-reverse";
}
);
}, `Avoiding layout while modifying a div with flex display mode.`);
test(() => {
assertContentVisibilityHiddenHasFewerReflows(
(container) => {
container.classList.add("grid");
const gridChild = document.createElement("div");
gridChild.style.display = "grid";
container.appendChild(gridChild);
container.appendChild(document.createElement("div"));
},
(container) => {
container.children[0].style.rowGap = "30px";
},
);
}, `Avoiding layout while modifying a div with grid display mode.`);
</script>
</html>

View File

@@ -1,105 +0,0 @@
<!doctype HTML>
<html>
<meta charset="utf8">
<title>Content Visibility: nested forced layouts</title>
<link rel="author" title="Vladimir Levin" href="mailto:vmpstr@chromium.org">
<link rel="help" href="https://drafts.csswg.org/css-contain/#content-visibility">
<meta name="assert" content="nested content-visibility items are all processed when layout is forced">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<style>
body, html {
padding: 0;
margin: 0;
}
.spacer {
height: 3000px;
}
.target {
width: 12px;
height: 34px;
position: relative;
left: 5px;
top: 7px;
}
.hidden {
content-visibility: hidden;
}
.will-hide {
contain: style;
contain: size;
contain: layout;
contain: paint;
}
</style>
<div class=spacer></div>
<div class="will-hide">
<div id=one>A line of a certain length...</div>
</div>
<div class="will-hide">
<div class=target id=two></div>
</div>
<div class="will-hide">
<div class=target id=three></div>
</div>
<div class="will-hide">
<div class="will-hide">
<div class=target id=four></div>
</div>
</div>
<div class="will-hide">
<div class="will-hide">
<div class="will-hide">
<div class="will-hide">
<div class="will-hide">
<div class=target id=five></div>
</div>
</div>
</div>
</div>
</div>
<script>
function hideContent() {
document
.querySelectorAll('.will-hide')
.forEach(content => content.classList.add("hidden"));
}
function showContent() {
document
.querySelectorAll('.will-hide')
.forEach(content => content.classList.remove("hidden"));
}
const ids = ["one", "two", "three", "four", "five"];
for (let i = 0; i < ids.length; ++i) {
test(() => {
const expectedRect = document.getElementById(ids[i]).getClientRects()[0];
const expectedBoundingRect = document.getElementById(ids[i]).getBoundingClientRect();
hideContent();
const rect = document.getElementById(ids[i]).getClientRects()[0];
assert_equals(rect.width, expectedRect.width, `width for "${ids[i]}"`);
assert_equals(rect.height, expectedRect.height, `height for "${ids[i]}`);
const boundingRect = document.getElementById(ids[i]).getClientRects()[0];
assert_equals(boundingRect.width, expectedBoundingRect.width, `width for "${ids[i]}"`);
assert_equals(boundingRect.height, expectedBoundingRect.height, `height for "${ids[i]}`);
showContent();
}, `${ids[i]}.getBoundingClientRect(): `);
}
</script>
</html>