Backed out changeset 5a4a5749f8dc (bug 1767262) for causing wpt failures.

This commit is contained in:
Butkovits Atila
2022-08-23 18:33:04 +03:00
parent e50fa41df7
commit 22dc8215a9
13 changed files with 8 additions and 334 deletions

View File

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

View File

@@ -11821,37 +11821,3 @@ void PresShell::PingPerTickTelemetry(FlushType aFlushType) {
bool PresShell::GetZoomableByAPZ() const { bool PresShell::GetZoomableByAPZ() const {
return mZoomConstraintsClient && mZoomConstraintsClient->GetAllowZoom(); 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; 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: private:
~PresShell(); ~PresShell();
@@ -3010,8 +2998,6 @@ class PresShell final : public nsStubDocumentObserver,
nsTHashSet<nsIScrollableFrame*> mPendingScrollAnchorAdjustment; nsTHashSet<nsIScrollableFrame*> mPendingScrollAnchorAdjustment;
nsTHashSet<nsIScrollableFrame*> mPendingScrollResnap; nsTHashSet<nsIScrollableFrame*> mPendingScrollResnap;
nsTHashSet<nsIContent*> mHiddenContentInForcedLayout;
nsCallbackEventRequest* mFirstCallbackEventRequest = nullptr; nsCallbackEventRequest* mFirstCallbackEventRequest = nullptr;
nsCallbackEventRequest* mLastCallbackEventRequest = nullptr; nsCallbackEventRequest* mLastCallbackEventRequest = nullptr;

View File

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

View File

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

View File

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

View File

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

View File

@@ -3150,13 +3150,6 @@ class nsIFrame : public nsQueryFrame {
*/ */
bool IsContentHidden() const; 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` * Returns true if this frame is entirely hidden due the `content-visibility`
* property on an ancestor. * property on an ancestor.

View File

@@ -1 +1,2 @@
prefs: [layout.css.content-visibility.enabled:true] 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

@@ -5,7 +5,6 @@
<link rel="author" title="Vladimir Levin" href="mailto:vmpstr@chromium.org"> <link rel="author" title="Vladimir Levin" href="mailto:vmpstr@chromium.org">
<link rel="help" href="https://drafts.csswg.org/css-contain/#content-visibility"> <link rel="help" href="https://drafts.csswg.org/css-contain/#content-visibility">
<meta name="assert" content="if an scroller is hidden via content-visibility and then shown again, its scroll offset should be restored"> <meta name="assert" content="if an scroller is hidden via content-visibility and then shown again, its scroll offset should be restored">
<meta name="viewport" content="width=device-width">
<script src="/resources/testharness.js"></script> <script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script> <script src="/resources/testharnessreport.js"></script>

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>