tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 9fc44ce3cd0ae46d38344a9201b2c40d38fd283a
parent 7f1600615e462565231800ac0df06569962d1caf
Author: agoloman <agoloman@mozilla.com>
Date:   Thu, 18 Dec 2025 19:05:46 +0200

Revert "Bug 2006402: Properly resolve auto inset/margin in nsComputedDOMStyle with anchor positioning. r=layout-anchor-positioning-reviewers,firefox-style-system-reviewers,emilio" for causing build bustages @nsStyleStruct.cpp.

This reverts commit 6e861d0db3e83e4c7c0aa74dc422b02d7514bbbf.

Revert "Bug 2006402: Use physical axes for flagging anchor-center use. r=layout-anchor-positioning-reviewers,firefox-style-system-reviewers,emilio"

This reverts commit 56907edbced39dadadc4779d62eb9dee4bedb755.

Revert "Bug 2006402: Remove anchor-center flags in reflowinput. r=layout-anchor-positioning-reviewers,layout-reviewers,emilio"

This reverts commit 3d67a1059f6f1b8b698a45fcea4f513bc4917b40.

Revert "Bug 2006402: Ensure that we override auto insets/margins only when there's position-area/anchor-center + valid default anchor. r=layout-anchor-positioning-reviewers,firefox-style-system-reviewers,layout-reviewers,emilio"

This reverts commit 8e1950452fbb5138d50c252ae3189de14b088a47.

Diffstat:
Mlayout/generic/AbsoluteContainingBlock.cpp | 30+++++++++++++++++-------------
Mlayout/generic/ReflowInput.cpp | 87++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------
Mlayout/generic/ReflowInput.h | 12++++++++++++
Mlayout/generic/nsIFrame.cpp | 2+-
Mlayout/generic/nsIFrame.h | 13+++++++++++--
Mlayout/style/nsComputedDOMStyle.h | 4++--
Mlayout/style/nsStyleStruct.cpp | 92+++++++++++++++++--------------------------------------------------------------
Mlayout/style/nsStyleStruct.h | 80+++++++++++++++++++++++++++++++++----------------------------------------------
Mservo/ports/geckolib/glue.rs | 4+++-
Atesting/web-platform/meta/css/css-anchor-position/position-area-basic.html.ini | 3+++
Dtesting/web-platform/tests/css/css-anchor-position/auto-inset-margin-getComputedStyle.html | 120-------------------------------------------------------------------------------
11 files changed, 179 insertions(+), 268 deletions(-)

diff --git a/layout/generic/AbsoluteContainingBlock.cpp b/layout/generic/AbsoluteContainingBlock.cpp @@ -971,7 +971,7 @@ void AbsoluteContainingBlock::ResolveAutoMarginsAfterLayout( const auto anchorResolutionParams = AnchorPosResolutionParams::From(&aKidReflowInput); - auto ResolveMarginsInAxis = [&](LogicalAxis aAxis) { + auto ResolveMarginsInAxis = [&](LogicalAxis aAxis, bool aAnchorCenter) { const auto startSide = MakeLogicalSide(aAxis, LogicalEdge::Start); const auto endSide = MakeLogicalSide(aAxis, LogicalEdge::End); @@ -1000,18 +1000,20 @@ void AbsoluteContainingBlock::ResolveAutoMarginsAfterLayout( ->IsAuto(); if (aAxis == LogicalAxis::Inline) { - ReflowInput::ComputeAbsPosInlineAutoMargin(availMarginSpace, outerWM, - startSideMarginIsAuto, - endSideMarginIsAuto, aMargin); + ReflowInput::ComputeAbsPosInlineAutoMargin( + availMarginSpace, outerWM, startSideMarginIsAuto, endSideMarginIsAuto, + aAnchorCenter, aMargin); } else { - ReflowInput::ComputeAbsPosBlockAutoMargin(availMarginSpace, outerWM, - startSideMarginIsAuto, - endSideMarginIsAuto, aMargin); + ReflowInput::ComputeAbsPosBlockAutoMargin( + availMarginSpace, outerWM, startSideMarginIsAuto, endSideMarginIsAuto, + aAnchorCenter, aMargin); } }; - ResolveMarginsInAxis(LogicalAxis::Inline); - ResolveMarginsInAxis(LogicalAxis::Block); + ResolveMarginsInAxis(LogicalAxis::Inline, + aKidReflowInput.mFlags.mIAnchorCenter); + ResolveMarginsInAxis(LogicalAxis::Block, + aKidReflowInput.mFlags.mBAnchorCenter); aKidReflowInput.SetComputedLogicalMargin(outerWM, aMargin); nsMargin* propValue = @@ -1462,9 +1464,10 @@ void AbsoluteContainingBlock::ReflowAbsoluteFrame( const auto* placeholderContainer = GetPlaceholderContainer(kidReflowInput.mFrame); - if (!iInsetAuto) { + if (!iInsetAuto || kidReflowInput.mFlags.mIAnchorCenter) { MOZ_ASSERT( - !kidReflowInput.mFlags.mIOffsetsNeedCSSAlign, + !kidReflowInput.mFlags.mIOffsetsNeedCSSAlign || + kidReflowInput.mFlags.mIAnchorCenter, "Non-auto inline inset but requires CSS alignment for static " "position?"); auto alignOffset = OffsetToAlignedStaticPos( @@ -1481,8 +1484,9 @@ void AbsoluteContainingBlock::ReflowAbsoluteFrame( cbSize.ISize(outerWM) - (offsets.IStart(outerWM) + kidMarginBox.ISize(outerWM)); } - if (!bInsetAuto) { - MOZ_ASSERT(!kidReflowInput.mFlags.mBOffsetsNeedCSSAlign, + if (!bInsetAuto || kidReflowInput.mFlags.mBAnchorCenter) { + MOZ_ASSERT(!kidReflowInput.mFlags.mBOffsetsNeedCSSAlign || + kidReflowInput.mFlags.mBAnchorCenter, "Non-auto block inset but requires CSS alignment for static " "position?"); auto alignOffset = OffsetToAlignedStaticPos( diff --git a/layout/generic/ReflowInput.cpp b/layout/generic/ReflowInput.cpp @@ -43,13 +43,23 @@ using namespace mozilla::layout; AnchorPosResolutionParams AnchorPosResolutionParams::From( const mozilla::SizeComputationInput* aSizingInput, bool aIgnorePositionArea) { - auto override = AutoResolutionOverrideParams{ - aSizingInput->mFrame, aSizingInput->mAnchorPosResolutionCache}; - if (aIgnorePositionArea) { - override.mPositionAreaInUse = false; - } - return {aSizingInput->mFrame, aSizingInput->mFrame->StyleDisplay()->mPosition, - aSizingInput->mAnchorPosResolutionCache, override}; + const mozilla::StylePositionArea posArea = + aIgnorePositionArea + ? mozilla::StylePositionArea{} + : aSizingInput->mFrame->StylePosition()->mPositionArea; + bool inlineUsesAnchorCenter = false; + bool blockUsesAnchorCenter = false; + + ComputeAnchorCenterUsage(aSizingInput->mFrame, + aSizingInput->mAnchorPosResolutionCache, + inlineUsesAnchorCenter, blockUsesAnchorCenter); + + return {aSizingInput->mFrame, + aSizingInput->mFrame->StyleDisplay()->mPosition, + posArea, + aSizingInput->mAnchorPosResolutionCache, + inlineUsesAnchorCenter, + blockUsesAnchorCenter}; } static bool CheckNextInFlowParenthood(nsIFrame* aFrame, nsIFrame* aParent) { @@ -58,6 +68,32 @@ static bool CheckNextInFlowParenthood(nsIFrame* aFrame, nsIFrame* aParent) { return frameNext && parentNext && frameNext->GetParent() == parentNext; } +void ComputeAnchorCenterUsage( + const nsIFrame* aFrame, + mozilla::AnchorPosResolutionCache* aAnchorPosResolutionCache, + bool& aInlineUsesAnchorCenter, bool& aBlockUsesAnchorCenter) { + aInlineUsesAnchorCenter = false; + aBlockUsesAnchorCenter = false; + nsIFrame* parent = aFrame->GetParent(); + if (!parent || !aFrame->HasAnyStateBits(NS_FRAME_OUT_OF_FLOW) || + !aAnchorPosResolutionCache || + !aAnchorPosResolutionCache->mDefaultAnchorCache.mAnchor) { + return; + } + + const auto* stylePos = aFrame->StylePosition(); + + auto checkAxis = [&](LogicalAxis aAxis) { + StyleAlignFlags alignment = + stylePos->UsedSelfAlignment(aAxis, parent->Style()); + return (alignment & ~StyleAlignFlags::FLAG_BITS) == + StyleAlignFlags::ANCHOR_CENTER; + }; + + aInlineUsesAnchorCenter = checkAxis(LogicalAxis::Inline); + aBlockUsesAnchorCenter = checkAxis(LogicalAxis::Block); +} + /** * Adjusts the margin for a list (ol, ul), if necessary, depending on * font inflation settings. Unfortunately, because bullets from a list are @@ -305,6 +341,7 @@ ReflowInput::ReflowInput(nsPresContext* aPresContext, mFlags.mDummyParentReflowInput = false; mFlags.mStaticPosIsCBOrigin = aFlags.contains(InitFlag::StaticPosIsCBOrigin); mFlags.mIOffsetsNeedCSSAlign = mFlags.mBOffsetsNeedCSSAlign = false; + mFlags.mIAnchorCenter = mFlags.mBAnchorCenter = false; // We don't want the mOrthogonalCellFinalReflow flag to be inherited; it's up // to the table row frame to set it for its direct children as needed. @@ -1144,7 +1181,18 @@ void ReflowInput::ComputeAbsPosInlineAutoMargin(nscoord aAvailMarginSpace, WritingMode aContainingBlockWM, bool aIsMarginIStartAuto, bool aIsMarginIEndAuto, + bool aIsIAnchorCenter, LogicalMargin& aMargin) { + if (aIsIAnchorCenter) { + // `anchor-center` sets any use of `auto` margin to 0. + if (aIsMarginIStartAuto) { + aMargin.IStart(aContainingBlockWM) = 0; + } + if (aIsMarginIEndAuto) { + aMargin.IEnd(aContainingBlockWM) = 0; + } + return; + } if (aIsMarginIStartAuto) { if (aIsMarginIEndAuto) { if (aAvailMarginSpace < 0) { @@ -1178,7 +1226,18 @@ void ReflowInput::ComputeAbsPosBlockAutoMargin(nscoord aAvailMarginSpace, WritingMode aContainingBlockWM, bool aIsMarginBStartAuto, bool aIsMarginBEndAuto, + bool aIsBAnchorCenter, LogicalMargin& aMargin) { + if (aIsBAnchorCenter) { + // `anchor-center` sets any use of `auto` margin to 0. + if (aIsMarginBStartAuto) { + aMargin.BStart(aContainingBlockWM) = 0; + } + if (aIsMarginBEndAuto) { + aMargin.BEnd(aContainingBlockWM) = 0; + } + return; + } if (aIsMarginBStartAuto) { if (aIsMarginBEndAuto) { // Both 'margin-top' and 'margin-bottom' are 'auto', so they get @@ -1696,6 +1755,16 @@ void ReflowInput::InitAbsoluteConstraints(const ReflowInput* aCBReflowInput, bool bStartIsAuto = bStartOffset->IsAuto(); bool bEndIsAuto = bEndOffset->IsAuto(); + mFlags.mIAnchorCenter = anchorResolutionParams.mBaseParams.mIAnchorCenter; + mFlags.mBAnchorCenter = anchorResolutionParams.mBaseParams.mBAnchorCenter; + + // For anchor-center with both insets auto, insets need to be kept as 0 + // so hypothetical position should be skipped. + const bool inlineBothInsetsAuto = + mFlags.mIAnchorCenter && iStartIsAuto && iEndIsAuto; + const bool blockBothInsetsAuto = + mFlags.mBAnchorCenter && bStartIsAuto && bEndIsAuto; + // If both 'inline-start' and 'inline-end' are 'auto' or both 'block-start' // and 'block-end' are 'auto', then compute the hypothetical box position // where the element would have if it were in the flow. @@ -1781,7 +1850,7 @@ void ReflowInput::InitAbsoluteConstraints(const ReflowInput* aCBReflowInput, nsLayoutUtils::ComputeCBDependentValue(aCBSize.ISize(cbwm), iEndOffset); } - if (iStartIsAuto && iEndIsAuto) { + if (iStartIsAuto && iEndIsAuto && !inlineBothInsetsAuto) { if (cbwm.IsInlineReversed() != hypotheticalPos.mWritingMode.IsInlineReversed()) { offsets.IEnd(cbwm) = hypotheticalPos.mIStart; @@ -1805,7 +1874,7 @@ void ReflowInput::InitAbsoluteConstraints(const ReflowInput* aCBReflowInput, nsLayoutUtils::ComputeCBDependentValue(aCBSize.BSize(cbwm), bEndOffset); } - if (bStartIsAuto && bEndIsAuto) { + if (bStartIsAuto && bEndIsAuto && !blockBothInsetsAuto) { // Treat 'top' like 'static-position' offsets.BStart(cbwm) = hypotheticalPos.mBStart; bStartIsAuto = false; diff --git a/layout/generic/ReflowInput.h b/layout/generic/ReflowInput.h @@ -512,6 +512,11 @@ struct ReflowInput : public SizeComputationInput { bool mIOffsetsNeedCSSAlign : 1; bool mBOffsetsNeedCSSAlign : 1; + // True when anchor-center is being used with a valid anchor and at least + // one inset is auto on this axis. Used to zero out margins. + bool mIAnchorCenter : 1; + bool mBAnchorCenter : 1; + // Is this frame or one of its ancestors being reflowed in a different // continuation than the one in which it was previously reflowed? In // other words, has it moved to a different column or page than it was in @@ -825,6 +830,7 @@ struct ReflowInput : public SizeComputationInput { WritingMode aContainingBlockWM, bool aIsMarginBStartAuto, bool aIsMarginBEndAuto, + bool aIsIAnchorCenter, LogicalMargin& aMargin); // Resolve any inline-axis 'auto' margins (if any) for an absolutely @@ -834,6 +840,7 @@ struct ReflowInput : public SizeComputationInput { WritingMode aContainingBlockWM, bool aIsMarginIStartAuto, bool aIsMarginIEndAuto, + bool aIsBAnchorCenter, LogicalMargin& aMargin); protected: @@ -975,4 +982,9 @@ struct ReflowInput : public SizeComputationInput { } // namespace mozilla +void ComputeAnchorCenterUsage( + const nsIFrame* aFrame, + mozilla::AnchorPosResolutionCache* aAnchorPosResolutionCache, + bool& aInlineUsesAnchorCenter, bool& aBlockUsesAnchorCenter); + #endif // mozilla_ReflowInput_h diff --git a/layout/generic/nsIFrame.cpp b/layout/generic/nsIFrame.cpp @@ -7229,7 +7229,7 @@ LogicalSize nsIFrame::ComputeAbsolutePosAutoSize( const auto* stylePos = StylePosition(); const auto anchorResolutionParams = AnchorPosOffsetResolutionParams::UseCBFrameSize( - AnchorPosResolutionParams::From(&aSizingInput)); + AnchorPosResolutionParams::From(this)); const auto& styleISize = aSizeOverrides.mStyleISize ? AnchorResolvedSizeHelper::Overridden(*aSizeOverrides.mStyleISize) diff --git a/layout/generic/nsIFrame.h b/layout/generic/nsIFrame.h @@ -5911,8 +5911,17 @@ inline nsIFrame* nsFrameList::BackwardFrameTraversal::Prev(nsIFrame* aFrame) { inline AnchorPosResolutionParams AnchorPosResolutionParams::From( const nsIFrame* aFrame, mozilla::AnchorPosResolutionCache* aAnchorPosResolutionCache) { - return {aFrame, aFrame->StyleDisplay()->mPosition, aAnchorPosResolutionCache, - AutoResolutionOverrideParams{aFrame, aAnchorPosResolutionCache}}; + bool inlineUsesAnchorCenter = false; + bool blockUsesAnchorCenter = false; + ComputeAnchorCenterUsage(aFrame, aAnchorPosResolutionCache, + inlineUsesAnchorCenter, blockUsesAnchorCenter); + + return {aFrame, + aFrame->StyleDisplay()->mPosition, + aFrame->StylePosition()->mPositionArea, + aAnchorPosResolutionCache, + inlineUsesAnchorCenter, + blockUsesAnchorCenter}; } #endif /* nsIFrame_h___ */ diff --git a/layout/style/nsComputedDOMStyle.h b/layout/style/nsComputedDOMStyle.h @@ -400,9 +400,9 @@ already_AddRefed<nsComputedDOMStyle> NS_NewComputedDOMStyle( inline AnchorPosResolutionParams AnchorPosResolutionParams::From( const nsComputedDOMStyle* aComputedDOMStyle) { - AutoResolutionOverrideParams overrides{aComputedDOMStyle->mOuterFrame}; return {aComputedDOMStyle->mOuterFrame, - aComputedDOMStyle->StyleDisplay()->mPosition, nullptr, overrides}; + aComputedDOMStyle->StyleDisplay()->mPosition, + aComputedDOMStyle->StylePosition()->mPositionArea}; } #endif /* nsComputedDOMStyle_h__ */ diff --git a/layout/style/nsStyleStruct.cpp b/layout/style/nsStyleStruct.cpp @@ -13,7 +13,6 @@ #include <algorithm> -#include "AnchorPositioningUtils.h" #include "CounterStyleManager.h" #include "ImageLoader.h" #include "imgIContainer.h" @@ -287,78 +286,6 @@ static StyleRect<T> StyleRectWithAllSides(const T& aSide) { return {aSide, aSide, aSide, aSide}; } -bool AnchorPosResolutionParams::AutoResolutionOverrideParams::OverriddenToZero( - StylePhysicalAxis aAxis) const { - if (mPositionAreaInUse) { - // If `position-area` is used "Any auto inset properties resolve to 0": - // https://drafts.csswg.org/css-anchor-position-1/#valdef-position-area-position-area - return true; - } - - // If `anchor-center` is used with a valid anchor, "auto inset - // properties resolve to 0" on that axis: - // https://drafts.csswg.org/css-anchor-position-1/#anchor-center - switch (aAxis) { - case StylePhysicalAxis::Vertical: - return mVAnchorCenter; - case StylePhysicalAxis::Horizontal: - return mHAnchorCenter; - } -} - -static AnchorPosResolutionParams::AutoResolutionOverrideParams -GetAutoResolutionOverrideParams(const nsIFrame* aFrame, - bool aDefaultAnchorValid) { - if (!aFrame) { - return {}; - } - nsIFrame* parent = aFrame->GetParent(); - if (!parent || !aFrame->HasAnyStateBits(NS_FRAME_OUT_OF_FLOW) || - !aDefaultAnchorValid) { - return {}; - } - - const auto* stylePos = aFrame->StylePosition(); - const auto cbwm = parent->GetWritingMode(); - - auto checkAxis = [&](LogicalAxis aAxis) { - StyleAlignFlags alignment = - stylePos->UsedSelfAlignment(aAxis, parent->Style()); - return (alignment & ~StyleAlignFlags::FLAG_BITS) == - StyleAlignFlags::ANCHOR_CENTER; - }; - - const auto horizontalLogicalAxis = - cbwm.IsVertical() ? LogicalAxis::Block : LogicalAxis::Inline; - AnchorPosResolutionParams::AutoResolutionOverrideParams result; - result.mHAnchorCenter = checkAxis(horizontalLogicalAxis); - result.mVAnchorCenter = checkAxis(GetOrthogonalAxis(horizontalLogicalAxis)); - result.mPositionAreaInUse = !stylePos->mPositionArea.IsNone(); - return result; -} - -AnchorPosResolutionParams::AutoResolutionOverrideParams:: - AutoResolutionOverrideParams( - const nsIFrame* aFrame, const mozilla::AnchorPosResolutionCache* aCache) - : AutoResolutionOverrideParams{GetAutoResolutionOverrideParams( - aFrame, aCache && aCache->mDefaultAnchorCache.mAnchor)} {} - -AnchorPosResolutionParams::AutoResolutionOverrideParams:: - AutoResolutionOverrideParams(const nsIFrame* aFrame) - : AutoResolutionOverrideParams{ - GetAutoResolutionOverrideParams(aFrame, [&]() { - if (!aFrame) { - return false; - } - const auto* references = - aFrame->GetProperty(nsIFrame::AnchorPosReferences()); - if (!references || !references->mDefaultAnchorName) { - // It is presumed that this is called on a reflowed frame. - return false; - } - return references->Lookup(references->mDefaultAnchorName)->isSome(); - }())} {} - AnchorResolvedMargin AnchorResolvedMarginHelper::ResolveAnchor( const StyleMargin& aValue, StylePhysicalAxis aAxis, const AnchorPosResolutionParams& aParams) { @@ -1401,6 +1328,25 @@ StyleSelfAlignment nsStylePosition::UsedJustifySelf( return {StyleAlignFlags::NORMAL}; } +bool AnchorResolvedInsetHelper::SideUsesAnchorCenter( + mozilla::Side aSide, const AnchorPosOffsetResolutionParams& aParams) { + const nsIFrame* frame = aParams.mBaseParams.mFrame; + if (!frame) { + return false; + } + const nsIFrame* parent = frame->GetParent(); + if (!parent) { + return false; + } + + WritingMode wm = parent->GetWritingMode(); + LogicalSide logicalSide = wm.LogicalSideForPhysicalSide(aSide); + LogicalAxis axis = GetAxis(logicalSide); + + return axis == LogicalAxis::Inline ? aParams.mBaseParams.mIAnchorCenter + : aParams.mBaseParams.mBAnchorCenter; +} + AnchorResolvedInset AnchorResolvedInsetHelper::ResolveAnchor( const mozilla::StyleInset& aValue, mozilla::StylePhysicalSide aSide, const AnchorPosOffsetResolutionParams& aParams) { diff --git a/layout/style/nsStyleStruct.h b/layout/style/nsStyleStruct.h @@ -42,7 +42,6 @@ class nsComputedDOMStyle; namespace mozilla { class ComputedStyle; struct AnchorPosResolutionCache; -class AnchorPosReferenceData; struct IntrinsicSize; struct SizeComputationInput; @@ -379,32 +378,21 @@ using AnchorResolvedMargin = // Base set of parameters required to resolve a reference to an anchor. struct AnchorPosResolutionParams { - struct AutoResolutionOverrideParams { - // Whether anchor-center is being used on the horizontal axis. - bool mHAnchorCenter = false; - // Whether anchor-center is being used on the vertical axis. - bool mVAnchorCenter = false; - // Whether position-area is being used. - bool mPositionAreaInUse = false; - - AutoResolutionOverrideParams() = default; - AutoResolutionOverrideParams( - const nsIFrame* aFrame, - const mozilla::AnchorPosResolutionCache* aCache); - explicit AutoResolutionOverrideParams(const nsIFrame* aFrame); - - bool OverriddenToZero(mozilla::StylePhysicalAxis aAxis) const; - }; // Frame of the anchor positioned element. // If nullptr, skips anchor lookup and returns invalid, resolving fallbacks. const nsIFrame* mFrame; // Position property of the element in question. mozilla::StylePositionProperty mPosition; + // position-area property of the element in question. + mozilla::StylePositionArea mPositionArea; // Cache data used for anchor resolution. mozilla::AnchorPosResolutionCache* const mCache; - // Set of parameters that override `auto` values to 0, if the default - // anchor is valid. - AutoResolutionOverrideParams mAutoResolutionOverrideParams; + // Whether anchor-center is being used with a valid anchor on the inline axis. + // When true, auto insets in the inline axis resolve to 0. + bool mIAnchorCenter = false; + // Whether anchor-center is being used with a valid anchor on the block axis. + // When true, auto insets in the block axis resolve to 0. + bool mBAnchorCenter = false; // Helper functions for creating anchor resolution parameters. // Defined in corresponding header files. @@ -428,17 +416,16 @@ struct AnchorResolvedMarginHelper { static AnchorResolvedMargin FromUnresolved( const mozilla::StyleMargin& aValue, mozilla::StylePhysicalAxis aAxis, const AnchorPosResolutionParams& aParams) { - auto resolved = [&]() { - if (aValue.HasAnchorPositioningFunction()) { - return ResolveAnchor(aValue, aAxis, aParams); - } - return AnchorResolvedMargin::NonOwning(&aValue); - }(); - if (resolved->IsAuto() && - aParams.mAutoResolutionOverrideParams.OverriddenToZero(aAxis)) { + if (aValue.HasAnchorPositioningFunction()) { + return ResolveAnchor(aValue, aAxis, aParams); + } + // For `position-area` values other than `none`, the used value of `auto` + // margin properties resolves to 0: + // <https://drafts.csswg.org/css-anchor-position-1/#valdef-position-area-position-area> + if (aValue.IsAuto() && !aParams.mPositionArea.IsNone()) { return Zero(); } - return resolved; + return AnchorResolvedMargin::NonOwning(&aValue); } private: @@ -793,28 +780,24 @@ struct AnchorResolvedInsetHelper { return value; } - static const mozilla::StyleInset& ZeroValue() { - static const auto value = mozilla::StyleInset::LengthPercentage( - mozilla::StyleLengthPercentage::Zero()); - return value; - } - static AnchorResolvedInset FromUnresolved( const mozilla::StyleInset& aValue, mozilla::Side aSide, const AnchorPosOffsetResolutionParams& aParams) { - auto resolved = [&]() { - if (aValue.HasAnchorPositioningFunction()) { - return ResolveAnchor(aValue, mozilla::ToStylePhysicalSide(aSide), - aParams); - } - return AnchorResolvedInset::NonOwning(&aValue); - }(); - if (resolved->IsAuto() && - aParams.mBaseParams.mAutoResolutionOverrideParams.OverriddenToZero( - mozilla::ToStylePhysicalAxis(aSide))) { - return AnchorResolvedInset::NonOwning(&ZeroValue()); + if (aValue.HasAnchorPositioningFunction()) { + return ResolveAnchor(aValue, mozilla::ToStylePhysicalSide(aSide), + aParams); + } + // If `position-area` is used "Any auto inset properties resolve to 0": + // https://drafts.csswg.org/css-anchor-position-1/#valdef-position-area-position-area + // If `anchor-center` is used with a valid anchor, "auto inset + // properties resolve to 0": + // https://drafts.csswg.org/css-anchor-position-1/#anchor-center + if (aValue.IsAuto() && (!aParams.mBaseParams.mPositionArea.IsNone() || + SideUsesAnchorCenter(aSide, aParams))) { + return AnchorResolvedInset::UniquelyOwning( + new mozilla::StyleInset(mozilla::LengthPercentage::Zero())); } - return resolved; + return AnchorResolvedInset::NonOwning(&aValue); } private: @@ -822,6 +805,9 @@ struct AnchorResolvedInsetHelper { return AnchorResolvedInset::NonOwning(&AutoValue()); } + static bool SideUsesAnchorCenter( + mozilla::Side aSide, const AnchorPosOffsetResolutionParams& aParams); + static AnchorResolvedInset ResolveAnchor( const mozilla::StyleInset& aValue, mozilla::StylePhysicalSide aSide, const AnchorPosOffsetResolutionParams& aParams); diff --git a/servo/ports/geckolib/glue.rs b/servo/ports/geckolib/glue.rs @@ -10799,8 +10799,10 @@ fn offset_params_from_base_params( mBaseParams: AnchorPosResolutionParams { mFrame: params.mFrame, mPosition: params.mPosition, + mPositionArea: params.mPositionArea, mCache: params.mCache, - mAutoResolutionOverrideParams: params.mAutoResolutionOverrideParams, + mIAnchorCenter: params.mIAnchorCenter, + mBAnchorCenter: params.mBAnchorCenter, }, } } diff --git a/testing/web-platform/meta/css/css-anchor-position/position-area-basic.html.ini b/testing/web-platform/meta/css/css-anchor-position/position-area-basic.html.ini @@ -0,0 +1,3 @@ +[position-area-basic.html] + [Offsets for: span-all top] + expected: FAIL diff --git a/testing/web-platform/tests/css/css-anchor-position/auto-inset-margin-getComputedStyle.html b/testing/web-platform/tests/css/css-anchor-position/auto-inset-margin-getComputedStyle.html @@ -1,120 +0,0 @@ -<!DOCTYPE html> -<meta charset="utf-8"> -<title>Tests that getComputedStyle() returns auto insets and margins 0 when position-area or anchor-center is used with valid default anchor</title> -<link rel="help" href="https://drafts.csswg.org/css-anchor-position-1/#position-area"> -<link rel="help" href="https://drafts.csswg.org/css-anchor-position-1/#anchor-pos"> -<link rel="author" name="David Shin" href="mailto:dshin@mozilla.com"> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<style> -.abs-cb { - width: 60px; - height: 60px; - border: 5px solid; - position: relative; - anchor-scope: all; - display: inline-block; - /* Nudge static position against padding box. */ - padding: 10px; -} - -.anchor { - anchor-name: --a; - position: absolute; - left: 20px; - top: 20px; - width: 20px; - height: 20px; - background: pink; -} - -.positioned { - position: absolute; - background: purple; - width: 20px; - height: 20px; -} - -.margin-auto > .positioned { - inset: 0; - margin: auto; -} - -.inset-auto > .positioned { - inset: auto; -} - -.pa { - position-area: bottom right; -} - -.jac { - justify-self: anchor-center; -} - -.aac { - align-self: anchor-center; -} - -.valid-anchor > .positioned { - position-anchor: --a; -} -</style> -<div id=insetValidAnchor class="abs-cb inset-auto valid-anchor"> - <div class=anchor></div> - <div class="positioned pa"></div> - <div class="positioned jac"></div> - <div class="positioned aac"></div> -</div -><div id=insetInvalidAnchor class="abs-cb inset-auto"> - <div class=anchor></div> - <div class="positioned pa"></div> - <div class="positioned jac"></div> - <div class="positioned aac"></div> -</div><br> -<div id=marginValidAnchor class="abs-cb margin-auto valid-anchor"> - <div class=anchor></div> - <div class="positioned pa"></div> - <div class="positioned jac"></div> - <div class="positioned aac"></div> -</div -><div id=marginInvalidAnchor class="abs-cb margin-auto"> - <div class=anchor></div> - <div class="positioned pa"></div> - <div class="positioned jac"></div> - <div class="positioned aac"></div> -</div> -<script> -function assert_zero(e, f, props, t) { - test(() => { - const s = getComputedStyle(e); - for (const prop of props) { - f(s.getPropertyValue(prop), "0px"); - } - }, t); -} - -const horizontalInsets = ['left', 'right']; -const verticalInsets = ['top', 'bottom']; -const allInsets = horizontalInsets.concat(verticalInsets); - -assert_zero(insetValidAnchor.querySelector('.pa'), assert_equals, allInsets, "position-area with valid anchor sets insets to zero"); -assert_zero(insetValidAnchor.querySelector('.jac'), assert_equals, horizontalInsets, "justify-self: anchor-center with valid anchor sets insets to zero"); -assert_zero(insetValidAnchor.querySelector('.aac'), assert_equals, verticalInsets, "align-self: anchor-center with valid anchor sets insets to zero"); - -assert_zero(insetInvalidAnchor.querySelector('.pa'), assert_not_equals, allInsets, "position-area with invalid anchor does not set insets to zero"); -assert_zero(insetInvalidAnchor.querySelector('.jac'), assert_not_equals, horizontalInsets, "justify-self: anchor-center with invalid anchor does not set insets to zero"); -assert_zero(insetInvalidAnchor.querySelector('.aac'), assert_not_equals, verticalInsets, "align-self: anchor-center with invalid anchor does not set insets to zero"); - -const horizontalMargins = ['margin-left', 'margin-right']; -const verticalMargins = ['margin-top', 'margin-bottom']; -const allMargins = horizontalMargins.concat(verticalMargins); - -assert_zero(marginValidAnchor.querySelector('.pa'), assert_equals, allMargins, "position-area with valid anchor sets margins to zero"); -assert_zero(marginValidAnchor.querySelector('.jac'), assert_equals, horizontalMargins, "justify-self: anchor-center with valid anchor sets margins to zero"); -assert_zero(marginValidAnchor.querySelector('.aac'), assert_equals, verticalMargins, "align-self: anchor-center with valid anchor sets margins to zero"); - -assert_zero(marginInvalidAnchor.querySelector('.pa'), assert_not_equals, allMargins, "position-area with invalid anchor does not set margins to zero"); -assert_zero(marginInvalidAnchor.querySelector('.jac'), assert_not_equals, horizontalMargins, "justify-self: anchor-center with invalid anchor does not set margins to zero"); -assert_zero(marginInvalidAnchor.querySelector('.aac'), assert_not_equals, verticalMargins, "align-self: anchor-center with invalid anchor does not set margins to zero"); -</script>