commit 6572b7509a9036d73e396cee6b4b1e1f3c58623b
parent 45879990e9f1aa6481a9c973491bf8c418cbb21d
Author: Emilio Cobos Álvarez <emilio@crisal.io>
Date: Wed, 17 Dec 2025 19:42:35 +0000
Bug 2006499 - Consider exposing active fallback style in getComputedStyle(). r=jwatt
This has bit us consistently, and I guess it's not that hard to do if we
want.
Differential Revision: https://phabricator.services.mozilla.com/D276757
Diffstat:
6 files changed, 48 insertions(+), 34 deletions(-)
diff --git a/layout/base/AnchorPositioningUtils.h b/layout/base/AnchorPositioningUtils.h
@@ -163,6 +163,7 @@ class AnchorPosReferenceData {
};
struct LastSuccessfulPositionData {
+ RefPtr<const ComputedStyle> mStyle;
uint32_t mIndex = 0;
bool mTriedAllFallbacks = false;
};
diff --git a/layout/generic/AbsoluteContainingBlock.cpp b/layout/generic/AbsoluteContainingBlock.cpp
@@ -1193,17 +1193,13 @@ void AbsoluteContainingBlock::ReflowAbsoluteFrame(
Maybe<uint32_t> firstTryIndex;
Maybe<nsPoint> firstTryNormalPosition;
- // TODO(emilio): Right now fallback only applies to position-area, which only
- // makes a difference with a default anchor... Generalize it?
- if (aAnchorPosResolutionCache) {
- const auto* lastSuccessfulPosition =
- aKidFrame->GetProperty(nsIFrame::LastSuccessfulPositionFallback());
- if (lastSuccessfulPosition) {
- if (!SeekFallbackTo(lastSuccessfulPosition->mIndex)) {
- aKidFrame->RemoveProperty(nsIFrame::LastSuccessfulPositionFallback());
- } else {
- firstTryIndex = Some(lastSuccessfulPosition->mIndex);
- }
+ const auto* lastSuccessfulPosition =
+ aKidFrame->GetProperty(nsIFrame::LastSuccessfulPositionFallback());
+ if (lastSuccessfulPosition) {
+ if (!SeekFallbackTo(lastSuccessfulPosition->mIndex)) {
+ aKidFrame->RemoveProperty(nsIFrame::LastSuccessfulPositionFallback());
+ } else {
+ firstTryIndex = Some(lastSuccessfulPosition->mIndex);
}
}
@@ -1607,8 +1603,9 @@ void AbsoluteContainingBlock::ReflowAbsoluteFrame(
if (currentFallbackIndex) {
aKidFrame->SetOrUpdateDeletableProperty(
- nsIFrame::LastSuccessfulPositionFallback(), *currentFallbackIndex,
- isOverflowingCB);
+ nsIFrame::LastSuccessfulPositionFallback(),
+ LastSuccessfulPositionData{currentFallbackStyle, *currentFallbackIndex,
+ isOverflowingCB});
}
#ifdef DEBUG
diff --git a/layout/style/nsComputedDOMStyle.cpp b/layout/style/nsComputedDOMStyle.cpp
@@ -10,6 +10,7 @@
#include <algorithm>
+#include "AnchorPositioningUtils.h"
#include "mozilla/AppUnits.h"
#include "mozilla/ComputedStyle.h"
#include "mozilla/ComputedStyleInlines.h"
@@ -758,26 +759,30 @@ void nsComputedDOMStyle::ClearComputedStyle() {
}
void nsComputedDOMStyle::SetResolvedComputedStyle(
- RefPtr<const ComputedStyle>&& aContext, uint64_t aGeneration) {
+ RefPtr<const ComputedStyle> aStyle, uint64_t aGeneration) {
if (!mResolvedComputedStyle) {
mResolvedComputedStyle = true;
mElement->AddMutationObserver(this);
}
- mComputedStyle = aContext;
+ mComputedStyle = std::move(aStyle);
mComputedStyleGeneration = aGeneration;
mPresShellId = mPresShell->GetPresShellId();
}
-void nsComputedDOMStyle::SetFrameComputedStyle(mozilla::ComputedStyle* aStyle,
- uint64_t aGeneration) {
+void nsComputedDOMStyle::SetFrameComputedStyle(
+ RefPtr<const ComputedStyle> aStyle, uint64_t aGeneration) {
ClearComputedStyle();
- mComputedStyle = aStyle;
+ mComputedStyle = std::move(aStyle);
mComputedStyleGeneration = aGeneration;
mPresShellId = mPresShell->GetPresShellId();
}
static bool MayNeedToFlushLayout(NonCustomCSSPropertyId aPropId) {
switch (aPropId) {
+ case eCSSProperty_max_width:
+ case eCSSProperty_max_height:
+ case eCSSProperty_min_width:
+ case eCSSProperty_min_height:
case eCSSProperty_width:
case eCSSProperty_height:
case eCSSProperty_block_size:
@@ -882,6 +887,11 @@ static bool PaddingNeedsUsedValue(const LengthPercentage& aValue,
return !aValue.ConvertsToLength() || aStyle.StyleDisplay()->HasAppearance();
}
+static bool HasPositionFallbacks(nsIFrame* aFrame) {
+ return aFrame->HasAnyStateBits(NS_FRAME_OUT_OF_FLOW) &&
+ !aFrame->StylePosition()->mPositionTryFallbacks._0.IsEmpty();
+}
+
bool nsComputedDOMStyle::NeedsToFlushLayout(
NonCustomCSSPropertyId aPropId) const {
MOZ_ASSERT(aPropId != eCSSProperty_UNKNOWN);
@@ -899,6 +909,18 @@ bool nsComputedDOMStyle::NeedsToFlushLayout(
}
switch (aPropId) {
+ case eCSSProperty_max_width:
+ return HasPositionFallbacks(frame) ||
+ frame->StylePosition()->mMaxWidth.HasAnchorPositioningFunction();
+ case eCSSProperty_max_height:
+ return HasPositionFallbacks(frame) ||
+ frame->StylePosition()->mMaxHeight.HasAnchorPositioningFunction();
+ case eCSSProperty_min_width:
+ return HasPositionFallbacks(frame) ||
+ frame->StylePosition()->mMinWidth.HasAnchorPositioningFunction();
+ case eCSSProperty_min_height:
+ return HasPositionFallbacks(frame) ||
+ frame->StylePosition()->mMinHeight.HasAnchorPositioningFunction();
case eCSSProperty_width:
case eCSSProperty_height:
return !IsNonReplacedInline(frame);
@@ -941,7 +963,8 @@ bool nsComputedDOMStyle::NeedsToFlushLayout(
// NOTE(dshin): Raw margin value access since we want to flush
// anchor-dependent values here.
Side side = SideForPaddingOrMarginOrInsetProperty(aPropId);
- return !style->StyleMargin()->mMargin.Get(side).ConvertsToLength();
+ return !style->StyleMargin()->mMargin.Get(side).ConvertsToLength() ||
+ HasPositionFallbacks(frame);
}
default:
return false;
@@ -1057,7 +1080,12 @@ void nsComputedDOMStyle::UpdateCurrentStyleSources(
mInnerFrame = mOuterFrame;
if (mOuterFrame) {
mInnerFrame = nsLayoutUtils::GetStyleFrame(mOuterFrame);
- SetFrameComputedStyle(mInnerFrame->Style(), currentGeneration);
+ const auto* style = mInnerFrame->Style();
+ if (auto* data = mInnerFrame->GetProperty(
+ nsIFrame::LastSuccessfulPositionFallback())) {
+ style = data->mStyle.get();
+ }
+ SetFrameComputedStyle(std::move(style), currentGeneration);
NS_ASSERTION(mComputedStyle, "Frame without style?");
}
}
diff --git a/layout/style/nsComputedDOMStyle.h b/layout/style/nsComputedDOMStyle.h
@@ -167,9 +167,9 @@ class nsComputedDOMStyle final : public nsDOMCSSDeclaration,
// Helper functions called by UpdateCurrentStyleSources.
void ClearComputedStyle();
- void SetResolvedComputedStyle(RefPtr<const ComputedStyle>&& aContext,
+ void SetResolvedComputedStyle(RefPtr<const ComputedStyle>,
uint64_t aGeneration);
- void SetFrameComputedStyle(ComputedStyle* aStyle, uint64_t aGeneration);
+ void SetFrameComputedStyle(RefPtr<const ComputedStyle>, uint64_t aGeneration);
static already_AddRefed<const ComputedStyle> DoGetComputedStyleNoFlush(
const Element*, const PseudoStyleRequest&, mozilla::PresShell*,
diff --git a/testing/web-platform/meta/css/css-anchor-position/position-try-backdrop.html.ini b/testing/web-platform/meta/css/css-anchor-position/position-try-backdrop.html.ini
@@ -1,3 +0,0 @@
-[position-try-backdrop.html]
- [::backdrop can use position-try-fallbacks]
- expected: FAIL
diff --git a/testing/web-platform/meta/css/css-anchor-position/try-tactic-sizing.html.ini b/testing/web-platform/meta/css/css-anchor-position/try-tactic-sizing.html.ini
@@ -1,9 +0,0 @@
-[try-tactic-sizing.html]
- [flip-block does not affect sizing]
- expected: FAIL
-
- [flip-inline does not affect sizing]
- expected: FAIL
-
- [flip-start affects sizing]
- expected: FAIL