Bug 1856640: Ensure layout flush for as-of-yet reflowed frames when querying computed style of elements potentially matching container query. r=firefox-style-system-reviewers,emilio

Differential Revision: https://phabricator.services.mozilla.com/D202619
This commit is contained in:
David Shin
2024-02-27 17:48:07 +00:00
parent f6d6e7c52f
commit 2a4ef8f770
5 changed files with 42 additions and 82 deletions

View File

@@ -11562,6 +11562,26 @@ nsIFrame::PhysicalAxes nsIFrame::ShouldApplyOverflowClipping(
return clip ? PhysicalAxes::Both : PhysicalAxes::None;
}
bool nsIFrame::HasUnreflowedContainerQueryAncestor() const {
// If this frame has done the first reflow, its ancestors are guaranteed to
// have as well.
if (!HasAnyStateBits(NS_FRAME_FIRST_REFLOW) ||
!PresContext()->HasContainerQueryFrames()) {
return false;
}
for (nsIFrame* cur = GetInFlowParent(); cur; cur = cur->GetInFlowParent()) {
if (!cur->HasAnyStateBits(NS_FRAME_FIRST_REFLOW)) {
// Done first reflow from this ancestor up, including query containers.
return false;
}
if (cur->StyleDisplay()->IsQueryContainer()) {
return true;
}
}
// No query container from this frame up to root.
return false;
}
#ifdef DEBUG
static void GetTagName(nsIFrame* aFrame, nsIContent* aContent, int aResultSize,
char* aResult) {

View File

@@ -1380,6 +1380,8 @@ class nsIFrame : public nsQueryFrame {
return nullptr;
}
bool HasUnreflowedContainerQueryAncestor() const;
private:
// The value that the CSS page-name "auto" keyword resolves to for children
// of this frame.

View File

@@ -990,6 +990,19 @@ bool nsComputedDOMStyle::NeedsToFlushLayout(nsCSSPropertyID aPropID) const {
}
}
bool nsComputedDOMStyle::NeedsToFlushLayoutForContainerQuery() const {
const auto* outerFrame = GetOuterFrame();
if (!outerFrame) {
return false;
}
const auto* innerFrame = nsLayoutUtils::GetStyleFrame(outerFrame);
MOZ_ASSERT(innerFrame, "No valid inner frame?");
// It's possible that potential containers are styled but not yet reflowed,
// i.e. They don't have a correct size, which makes any container query
// evaluation against them invalid.
return innerFrame->HasUnreflowedContainerQueryAncestor();
}
void nsComputedDOMStyle::Flush(Document& aDocument, FlushType aFlushType) {
MOZ_ASSERT(mElement->IsInComposedDoc());
MOZ_ASSERT(mDocumentWeak == &aDocument);
@@ -1051,8 +1064,9 @@ void nsComputedDOMStyle::UpdateCurrentStyleSources(nsCSSPropertyID aPropID) {
Flush(*document, FlushType::Frames);
}
if (NeedsToFlushLayout(aPropID)) {
MOZ_ASSERT(MayNeedToFlushLayout(aPropID));
const bool needsToFlushLayoutForProp = NeedsToFlushLayout(aPropID);
if (needsToFlushLayoutForProp || NeedsToFlushLayoutForContainerQuery()) {
MOZ_ASSERT_IF(needsToFlushLayoutForProp, MayNeedToFlushLayout(aPropID));
didFlush = true;
Flush(*document, FlushType::Layout);
#ifdef DEBUG

View File

@@ -312,6 +312,10 @@ class nsComputedDOMStyle final : public nsDOMCSSDeclaration,
// Find out if we need to flush layout of the document, depending on the
// property that was requested.
bool NeedsToFlushLayout(nsCSSPropertyID) const;
// Find out if we need to flush layout of the document due to container
// query being made before relevant query containers are reflowed at least
// once.
bool NeedsToFlushLayoutForContainerQuery() const;
// Flushes the given document, which must be our document, and potentially the
// mElement's document.
void Flush(Document&, mozilla::FlushType);

View File

@@ -1,14 +1,4 @@
[font-relative-units.html]
[lh relative inline-size]
expected:
if (os == "linux") and not debug and not asan and not tsan: [FAIL, PASS]
if (os == "win") and debug and (processor == "x86"): PASS
if (os == "win") and not debug and (processor == "x86_64"): PASS
if (os == "win") and not debug and (processor == "x86"): PASS
if (os == "android") and debug: [FAIL, PASS]
if (os == "android") and not debug: [FAIL, PASS]
[PASS, FAIL]
[rex relative inline-size]
expected: FAIL
@@ -18,75 +8,5 @@
[ric relative inline-size]
expected: FAIL
[rlh relative inline-size]
expected:
if (os == "linux") and not debug and not asan and not tsan: [FAIL, PASS]
if (os == "win") and debug and (processor == "x86"): PASS
if (os == "win") and not debug and (processor == "x86_64"): PASS
if (os == "win") and not debug and (processor == "x86"): PASS
if (os == "android") and debug: [FAIL, PASS]
if (os == "android") and not debug: [FAIL, PASS]
[PASS, FAIL]
[em relative inline-size]
expected:
if (os == "linux") and not debug and not asan and not tsan: [FAIL, PASS]
if (os == "win") and debug and (processor == "x86"): PASS
if (os == "win") and not debug and (processor == "x86_64"): PASS
if (os == "win") and not debug and (processor == "x86"): PASS
if (os == "android") and debug: [FAIL, PASS]
if (os == "android") and not debug: [FAIL, PASS]
[PASS, FAIL]
[rem relative inline-size]
expected:
if (os == "linux") and not debug and not asan and not tsan: [FAIL, PASS]
if (os == "win") and debug and (processor == "x86"): PASS
if (os == "win") and not debug and (processor == "x86_64"): PASS
if (os == "win") and not debug and (processor == "x86"): PASS
if (os == "android") and debug: [FAIL, PASS]
if (os == "android") and not debug: [FAIL, PASS]
[PASS, FAIL]
[ex relative inline-size]
expected:
if (os == "linux") and not debug and not asan and not tsan: [FAIL, PASS]
if (os == "win") and debug and (processor == "x86"): PASS
if (os == "win") and not debug and (processor == "x86_64"): PASS
if (os == "win") and not debug and (processor == "x86"): PASS
if (os == "android") and debug: [FAIL, PASS]
if (os == "android") and not debug: [FAIL, PASS]
[PASS, FAIL]
[ch relative inline-size]
expected:
if (os == "linux") and not debug and not asan and not tsan: [FAIL, PASS]
if (os == "win") and debug and (processor == "x86"): PASS
if (os == "win") and not debug and (processor == "x86_64"): PASS
if (os == "win") and not debug and (processor == "x86"): PASS
if (os == "android") and debug: [FAIL, PASS]
if (os == "android") and not debug: [FAIL, PASS]
[PASS, FAIL]
[ic relative inline-size]
expected:
if (os == "linux") and not debug and not asan and not tsan: [FAIL, PASS]
if (os == "win") and debug and (processor == "x86"): PASS
if (os == "win") and not debug and (processor == "x86_64"): PASS
if (os == "win") and not debug and (processor == "x86"): PASS
if (os == "android") and debug: [FAIL, PASS]
if (os == "android") and not debug: [FAIL, PASS]
[PASS, FAIL]
[cap relative inline-size]
expected:
if (os == "linux") and not debug and not asan and not tsan: [FAIL, PASS]
if (os == "win") and debug and (processor == "x86"): PASS
if (os == "win") and not debug and (processor == "x86_64"): PASS
if (os == "win") and not debug and (processor == "x86"): PASS
if (os == "android") and debug: [FAIL, PASS]
if (os == "android") and not debug: [FAIL, PASS]
[PASS, FAIL]
[rcap relative inline-size]
expected: FAIL