tor-browser

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

commit e3c22d4741ec8f00e34fcd70abb8edfc7d4fe64d
parent f2dc24047786f81c4a1eb8505fde769baae8df70
Author: Keith Cirkel <keithamus@users.noreply.github.com>
Date:   Mon, 27 Oct 2025 16:09:08 +0000

Bug 1924090 - Apply resolved position-area influenced self-alignment properties during alignment for abspos with cb r=emilio,layout-reviewers,dshin,firefox-style-system-reviewers

Differential Revision: https://phabricator.services.mozilla.com/D268152

Diffstat:
Mlayout/base/AnchorPositioningUtils.cpp | 4+++-
Mlayout/base/AnchorPositioningUtils.h | 2+-
Mlayout/generic/AbsoluteContainingBlock.cpp | 33++++++++++++++++++++-------------
Mlayout/generic/AbsoluteContainingBlock.h | 10+++++-----
Mlayout/generic/ReflowInput.h | 9++++++---
Mlayout/generic/WritingModes.h | 11+++++++++++
Mlayout/generic/nsContainerFrame.cpp | 44+++++++++++++++++++++++++++++++++++++++++++-
Mlayout/generic/nsContainerFrame.h | 5++++-
Mlayout/style/nsStyleStruct.h | 37++++++++++++++++++++++++++++++++++++-
Mservo/components/style/values/specified/position.rs | 24++++++++++++++++++++++++
Mservo/ports/geckolib/glue.rs | 21++++++++++++++++++++-
Mtesting/web-platform/meta/css/css-anchor-position/anchor-scroll-position-try-013.html.ini | 6------
Dtesting/web-platform/meta/css/css-anchor-position/last-successful-change-fallbacks-position-area.html.ini | 3---
Dtesting/web-platform/meta/css/css-anchor-position/popover-implicit-anchor.html.ini | 3---
Mtesting/web-platform/meta/css/css-anchor-position/position-area-align-justify-wm-dir.html.ini | 64++--------------------------------------------------------------
Mtesting/web-platform/meta/css/css-anchor-position/position-area-align-justify.html.ini | 36------------------------------------
Atesting/web-platform/meta/css/css-anchor-position/position-area-in-position-try.html.ini | 6++++++
Mtesting/web-platform/meta/css/css-anchor-position/position-area-scrolling-002.tentative.html.ini | 9---------
Dtesting/web-platform/meta/css/css-anchor-position/position-area-scrolling-004.tentative.html.ini | 2--
Mtesting/web-platform/meta/css/css-anchor-position/position-area-scrolling-005.html.ini | 9---------
Mtesting/web-platform/meta/css/css-anchor-position/position-area-scrolling-006.html.ini | 3---
Atesting/web-platform/meta/css/css-anchor-position/position-try-fallbacks-004.html.ini | 2++
Mtesting/web-platform/meta/css/css-anchor-position/position-try-switch-to-fixed-anchor.html.ini | 2+-
Atesting/web-platform/meta/css/css-anchor-position/position-visibility-no-overflow-scroll-002.html.ini | 2++
Atesting/web-platform/tests/css/css-anchor-position/position-area-inset-one-side-auto.tentative.html | 46++++++++++++++++++++++++++++++++++++++++++++++
Atesting/web-platform/tests/css/css-anchor-position/reference/position-area-inset-one-side-auto.html | 28++++++++++++++++++++++++++++
26 files changed, 260 insertions(+), 161 deletions(-)

diff --git a/layout/base/AnchorPositioningUtils.cpp b/layout/base/AnchorPositioningUtils.cpp @@ -504,7 +504,8 @@ static StylePositionArea ToPhysicalPositionArea(StylePositionArea aPosArea, nsRect AnchorPositioningUtils::AdjustAbsoluteContainingBlockRectForPositionArea( const nsRect& aAnchorRect, const nsRect& aCBRect, WritingMode aPositionedWM, - WritingMode aCBWM, const StylePositionArea& aPosArea) { + WritingMode aCBWM, const StylePositionArea& aPosArea, + StylePositionArea* aOutResolvedArea) { // Get the boundaries of 3x3 grid in CB's frame space. The edges of the // default anchor box are clamped to the bounds of the CB, even if that // results in zero width/height cells. @@ -536,6 +537,7 @@ nsRect AnchorPositioningUtils::AdjustAbsoluteContainingBlockRectForPositionArea( // PositionArea, resolved to only contain Left/Right/Top/Bottom values. StylePositionArea posArea = ToPhysicalPositionArea(aPosArea, aCBWM, aPositionedWM); + *aOutResolvedArea = posArea; nscoord right = ltrEdges[3]; if (posArea.first == StylePositionAreaKeyword::Left) { diff --git a/layout/base/AnchorPositioningUtils.h b/layout/base/AnchorPositioningUtils.h @@ -114,7 +114,7 @@ struct AnchorPositioningUtils { static nsRect AdjustAbsoluteContainingBlockRectForPositionArea( const nsRect& aAnchorRect, const nsRect& aCBRect, WritingMode aPositionedWM, WritingMode aCBWM, - const StylePositionArea& aPosArea); + const StylePositionArea& aPosArea, StylePositionArea* aOutResolvedArea); /** * Gets the used anchor name for an anchor positioned frame. diff --git a/layout/generic/AbsoluteContainingBlock.cpp b/layout/generic/AbsoluteContainingBlock.cpp @@ -506,7 +506,8 @@ static nscoord OffsetToAlignedStaticPos( const ReflowInput& aKidReflowInput, const LogicalSize& aKidSizeInAbsPosCBWM, const LogicalSize& aAbsPosCBSize, const nsContainerFrame* aPlaceholderContainer, WritingMode aAbsPosCBWM, - LogicalAxis aAbsPosCBAxis, Maybe<NonAutoAlignParams> aNonAutoAlignParams) { + LogicalAxis aAbsPosCBAxis, Maybe<NonAutoAlignParams> aNonAutoAlignParams, + const StylePositionArea& aPositionArea) { if (!aPlaceholderContainer) { // (The placeholder container should be the thing that kicks this whole // process off, by setting PLACEHOLDER_STATICPOS_NEEDS_CSSALIGN. So it @@ -526,6 +527,7 @@ static nscoord OffsetToAlignedStaticPos( // WritingMode. For brevity, we use the abbreviation "pc" for "placeholder // container" in variables below. WritingMode pcWM = aPlaceholderContainer->GetWritingMode(); + LogicalSize absPosCBSizeInPCWM = aAbsPosCBSize.ConvertTo(pcWM, aAbsPosCBWM); // Find what axis aAbsPosCBAxis corresponds to, in placeholder's parent's // writing-mode. @@ -609,7 +611,7 @@ static nscoord OffsetToAlignedStaticPos( aNonAutoAlignParams ? aPlaceholderContainer ->CSSAlignmentForAbsPosChildWithinContainingBlock( - aKidReflowInput, pcAxis) + aKidReflowInput, pcAxis, aPositionArea, absPosCBSizeInPCWM) : aPlaceholderContainer->CSSAlignmentForAbsPosChild(aKidReflowInput, pcAxis); // If the safe bit in alignConst is set, set the safe flag in |flags|. @@ -710,7 +712,7 @@ static nscoord OffsetToAlignedStaticPos( void AbsoluteContainingBlock::ResolveSizeDependentOffsets( ReflowInput& aKidReflowInput, const LogicalSize& aLogicalCBSize, const LogicalSize& aKidSize, const LogicalMargin& aMargin, - LogicalMargin& aOffsets) { + const StylePositionArea& aResolvedPositionArea, LogicalMargin& aOffsets) { WritingMode wm = aKidReflowInput.GetWritingMode(); WritingMode outerWM = aKidReflowInput.mParentReflowInput->GetWritingMode(); @@ -745,7 +747,7 @@ void AbsoluteContainingBlock::ResolveSizeDependentOffsets( placeholderContainer = GetPlaceholderContainer(aKidReflowInput.mFrame); nscoord offset = OffsetToAlignedStaticPos( aKidReflowInput, aKidSize, logicalCBSizeOuterWM, placeholderContainer, - outerWM, LogicalAxis::Inline, Nothing{}); + outerWM, LogicalAxis::Inline, Nothing{}, aResolvedPositionArea); // Shift IStart from its current position (at start corner of the // alignment container) by the returned offset. And set IEnd to the // distance between the kid's end edge to containing block's end edge. @@ -765,7 +767,7 @@ void AbsoluteContainingBlock::ResolveSizeDependentOffsets( } nscoord offset = OffsetToAlignedStaticPos( aKidReflowInput, aKidSize, logicalCBSizeOuterWM, placeholderContainer, - outerWM, LogicalAxis::Block, Nothing{}); + outerWM, LogicalAxis::Block, Nothing{}, aResolvedPositionArea); // Shift BStart from its current position (at start corner of the // alignment container) by the returned offset. And set BEnd to the // distance between the kid's end edge to containing block's end edge. @@ -955,13 +957,14 @@ void AbsoluteContainingBlock::ReflowAbsoluteFrame( do { AutoFallbackStyleSetter fallback(aKidFrame, currentFallbackStyle); + auto positionArea = aKidFrame->StylePosition()->mPositionArea; + StylePositionArea resolvedPositionArea; const nsRect usedCb = [&] { if (isGrid) { // TODO(emilio): how does position-area interact with grid? return nsGridContainerFrame::GridItemCB(aKidFrame); } - auto positionArea = aKidFrame->StylePosition()->mPositionArea; if (currentFallback && currentFallback->IsPositionArea()) { MOZ_ASSERT(currentFallback->IsPositionArea()); positionArea = currentFallback->AsPositionArea(); @@ -975,7 +978,8 @@ void AbsoluteContainingBlock::ReflowAbsoluteFrame( AdjustAbsoluteContainingBlockRectForPositionArea( *defaultAnchorInfo.mRect, aOriginalContainingBlockRect, aKidFrame->GetWritingMode(), - aDelegatingFrame->GetWritingMode(), positionArea); + aDelegatingFrame->GetWritingMode(), positionArea, + &resolvedPositionArea); } } @@ -1096,7 +1100,7 @@ void AbsoluteContainingBlock::ReflowAbsoluteFrame( // If we're solving for start in either inline or block direction, // then compute it now that we know the dimensions. ResolveSizeDependentOffsets(kidReflowInput, logicalCBSize, kidSize, - margin, offsets); + margin, resolvedPositionArea, offsets); if (kidReflowInput.mFlags.mDeferAutoMarginComputation) { ResolveAutoMarginsAfterLayout(kidReflowInput, logicalCBSize, kidSize, @@ -1108,10 +1112,12 @@ void AbsoluteContainingBlock::ReflowAbsoluteFrame( // to align the child by its margin box: // https://drafts.csswg.org/css-position-3/#abspos-layout const auto* stylePos = aKidFrame->StylePosition(); + const LogicalSize logicalCBSizeOuterWM(outerWM, usedCb.Size()); const auto anchorResolutionParams = - AnchorPosOffsetResolutionParams::UseCBFrameSize( + AnchorPosOffsetResolutionParams::ExplicitCBFrameSize( AnchorPosResolutionParams::From(aKidFrame, - aAnchorPosReferenceData)); + aAnchorPosReferenceData), + &logicalCBSizeOuterWM); const bool iInsetAuto = stylePos ->GetAnchorResolvedInset(LogicalSide::IStart, outerWM, @@ -1130,7 +1136,6 @@ void AbsoluteContainingBlock::ReflowAbsoluteFrame( ->GetAnchorResolvedInset(LogicalSide::BEnd, outerWM, anchorResolutionParams) ->IsAuto(); - const LogicalSize logicalCBSizeOuterWM(outerWM, usedCb.Size()); const LogicalSize kidMarginBox{ outerWM, margin.IStartEnd(outerWM) + kidSize.ISize(outerWM), margin.BStartEnd(outerWM) + kidSize.BSize(outerWM)}; @@ -1148,7 +1153,8 @@ void AbsoluteContainingBlock::ReflowAbsoluteFrame( Some(NonAutoAlignParams{ offsets.IStart(outerWM), offsets.IEnd(outerWM), - })); + }), + resolvedPositionArea); offsets.IStart(outerWM) += alignOffset; offsets.IEnd(outerWM) = @@ -1165,7 +1171,8 @@ void AbsoluteContainingBlock::ReflowAbsoluteFrame( Some(NonAutoAlignParams{ offsets.BStart(outerWM), offsets.BEnd(outerWM), - })); + }), + resolvedPositionArea); offsets.BStart(outerWM) += alignOffset; offsets.BEnd(outerWM) = logicalCBSizeOuterWM.BSize(outerWM) - diff --git a/layout/generic/AbsoluteContainingBlock.h b/layout/generic/AbsoluteContainingBlock.h @@ -28,6 +28,7 @@ enum class AbsPosReflowFlag : uint8_t { IsGridContainerCB, }; using AbsPosReflowFlags = EnumSet<AbsPosReflowFlag>; +struct StylePositionArea; /** * This class contains the logic for being an absolute containing block. This @@ -122,11 +123,10 @@ class AbsoluteContainingBlock { * * aOffset is an outparam. */ - void ResolveSizeDependentOffsets(ReflowInput& aKidReflowInput, - const LogicalSize& aLogicalCBSize, - const LogicalSize& aKidSize, - const LogicalMargin& aMargin, - LogicalMargin& aOffsets); + void ResolveSizeDependentOffsets( + ReflowInput& aKidReflowInput, const LogicalSize& aLogicalCBSize, + const LogicalSize& aKidSize, const LogicalMargin& aMargin, + const StylePositionArea& aResolvedPositionArea, LogicalMargin& aOffsets); /** * For frames that have intrinsic block sizes, since we want to use the diff --git a/layout/generic/ReflowInput.h b/layout/generic/ReflowInput.h @@ -981,9 +981,12 @@ struct ReflowInput : public SizeComputationInput { } // namespace mozilla inline AnchorPosResolutionParams AnchorPosResolutionParams::From( - const mozilla::ReflowInput* aRI) { - return {aRI->mFrame, aRI->mStyleDisplay->mPosition, - aRI->mStylePosition->mPositionArea, aRI->mAnchorPosReferenceData}; + const mozilla::ReflowInput* aRI, bool aIgnorePositionArea) { + const mozilla::StylePositionArea posArea = + aIgnorePositionArea ? mozilla::StylePositionArea{} + : aRI->mStylePosition->mPositionArea; + return {aRI->mFrame, aRI->mStyleDisplay->mPosition, posArea, + aRI->mAnchorPosReferenceData}; } #endif // mozilla_ReflowInput_h diff --git a/layout/generic/WritingModes.h b/layout/generic/WritingModes.h @@ -2189,6 +2189,17 @@ inline AnchorResolvedInset nsStylePosition::GetAnchorResolvedInset( return GetAnchorResolvedInset(aWM.PhysicalSide(aSide), aParams); } +inline mozilla::Maybe<mozilla::Side> nsStylePosition::GetSingleAutoInsetInAxis( + LogicalAxis aAxis, WritingMode aWM, + const AnchorPosOffsetResolutionParams& aParams) const { + const bool isInlineAxis = (aAxis == LogicalAxis::Inline); + const mozilla::StylePhysicalAxis physicalAxis = + (isInlineAxis == aWM.IsVertical()) + ? mozilla::StylePhysicalAxis::Vertical + : mozilla::StylePhysicalAxis::Horizontal; + return GetSingleAutoInsetInAxis(physicalAxis, aParams); +} + inline AnchorResolvedSize nsStylePosition::ISize( WritingMode aWM, const AnchorPosResolutionParams& aParams) const { return aWM.IsVertical() ? GetHeight(aParams) : GetWidth(aParams); diff --git a/layout/generic/nsContainerFrame.cpp b/layout/generic/nsContainerFrame.cpp @@ -10,6 +10,7 @@ #include <algorithm> +#include "AnchorPositioningUtils.h" #include "mozilla/AbsoluteContainingBlock.h" #include "mozilla/AutoRestore.h" #include "mozilla/ComputedStyle.h" @@ -2624,7 +2625,9 @@ StyleAlignFlags nsContainerFrame::CSSAlignmentForAbsPosChild( StyleAlignFlags nsContainerFrame::CSSAlignmentForAbsPosChildWithinContainingBlock( - const ReflowInput& aChildRI, LogicalAxis aLogicalAxis) const { + const ReflowInput& aChildRI, LogicalAxis aLogicalAxis, + const StylePositionArea& aResolvedPositionArea, + const LogicalSize& aCBSize) const { MOZ_ASSERT(aChildRI.mFrame->IsAbsolutelyPositioned(), "This method should only be called for abspos children"); // When determining the position of absolutely-positioned boxes, @@ -2634,6 +2637,45 @@ nsContainerFrame::CSSAlignmentForAbsPosChildWithinContainingBlock( ? aChildRI.mStylePosition->UsedJustifySelf(nullptr)._0 : aChildRI.mStylePosition->UsedAlignSelf(nullptr)._0; + // Check if position-area is set - if so, it determines the default alignment + // https://drafts.csswg.org/css-anchor-position/#position-area-alignment + if (!aResolvedPositionArea.IsNone() && alignment == StyleAlignFlags::NORMAL) { + const WritingMode cbWM = GetWritingMode(); + const auto anchorResolutionParams = AnchorPosResolutionParams::From( + &aChildRI, /* aIgnorePositionArea = */ true); + const auto anchorOffsetResolutionParams = + AnchorPosOffsetResolutionParams::ExplicitCBFrameSize( + anchorResolutionParams, &aCBSize); + + // Check if we have exactly one auto inset in this axis (IMCB situation) + const auto singleAutoInset = + aChildRI.mStylePosition->GetSingleAutoInsetInAxis( + aLogicalAxis, cbWM, anchorOffsetResolutionParams); + + // Check if exactly one inset in the axis is auto + // https://drafts.csswg.org/css-anchor-position/#position-area-alignment + // "However, if only one inset property in the relevant axis is auto, the + // default alignment is instead towards the edge with the non-auto inset; + // and this is an unsafe alignment." + if (singleAutoInset.isSome()) { + const LogicalSide startSide = aLogicalAxis == LogicalAxis::Inline + ? LogicalSide::IStart + : LogicalSide::BStart; + const mozilla::Side autoSide = *singleAutoInset; + const mozilla::Side startPhysicalSide = cbWM.PhysicalSide(startSide); + // Exactly one inset is auto - align toward the non-auto edge, unsafely + alignment = (autoSide == startPhysicalSide) ? StyleAlignFlags::END + : StyleAlignFlags::START; + alignment |= StyleAlignFlags::UNSAFE; + } else { + auto keyword = aLogicalAxis == LogicalAxis::Inline + ? aResolvedPositionArea.first + : aResolvedPositionArea.second; + // Use normal position-area alignment + Servo_ResolvePositionAreaSelfAlignment(&keyword, &alignment); + } + } + return MapCSSAlignment(alignment, aChildRI, aLogicalAxis, GetWritingMode()); } diff --git a/layout/generic/nsContainerFrame.h b/layout/generic/nsContainerFrame.h @@ -21,6 +21,7 @@ class nsOverflowContinuationTracker; namespace mozilla { class PresShell; +struct StylePositionArea; } // namespace mozilla // Some macros for container classes to do sanity checking on @@ -492,7 +493,9 @@ class nsContainerFrame : public nsSplittableFrame { * on its type (By overriding `CSSAlignmentForAbsPosChild`). */ mozilla::StyleAlignFlags CSSAlignmentForAbsPosChildWithinContainingBlock( - const ReflowInput& aChildRI, mozilla::LogicalAxis aLogicalAxis) const; + const ReflowInput& aChildRI, mozilla::LogicalAxis aLogicalAxis, + const mozilla::StylePositionArea& aResolvedPositionArea, + const mozilla::LogicalSize& aContainingBlockSize) const; #define NS_DECLARE_FRAME_PROPERTY_FRAMELIST(prop) \ NS_DECLARE_FRAME_PROPERTY_WITH_DTOR_NEVER_CALLED(prop, nsFrameList) diff --git a/layout/style/nsStyleStruct.h b/layout/style/nsStyleStruct.h @@ -399,7 +399,8 @@ struct AnchorPosResolutionParams { static inline AnchorPosResolutionParams From( const nsIFrame* aFrame, mozilla::AnchorPosReferenceData* aAnchorPosReferenceData = nullptr); - static inline AnchorPosResolutionParams From(const mozilla::ReflowInput* aRI); + static inline AnchorPosResolutionParams From( + const mozilla::ReflowInput* aRI, bool aIgnorePositionArea = false); static inline AnchorPosResolutionParams From( const nsComputedDOMStyle* aComputedDOMStyle); }; @@ -1089,6 +1090,40 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStylePosition { mozilla::LogicalSide aSide, WritingMode aWM, const AnchorPosOffsetResolutionParams& aParams) const; + // Returns the side with an auto inset if exactly one inset in the given + // physical axis is auto. Otherwise returns Nothing(). + mozilla::Maybe<mozilla::Side> GetSingleAutoInsetInAxis( + mozilla::StylePhysicalAxis aAxis, + const AnchorPosOffsetResolutionParams& aParams) const { + const mozilla::Side startSide = + aAxis == mozilla::StylePhysicalAxis::Horizontal ? mozilla::eSideLeft + : mozilla::eSideTop; + const mozilla::Side endSide = + aAxis == mozilla::StylePhysicalAxis::Horizontal ? mozilla::eSideRight + : mozilla::eSideBottom; + + const bool startInsetIsAuto = + AnchorResolvedInsetHelper::FromUnresolved(mOffset.Get(startSide), + startSide, aParams) + ->IsAuto(); + const bool endInsetIsAuto = AnchorResolvedInsetHelper::FromUnresolved( + mOffset.Get(endSide), endSide, aParams) + ->IsAuto(); + + if (startInsetIsAuto && !endInsetIsAuto) { + return mozilla::Some(startSide); + } + if (!startInsetIsAuto && endInsetIsAuto) { + return mozilla::Some(endSide); + } + return mozilla::Nothing(); + } + + // Logical-axis version, defined in WritingModes.h + inline mozilla::Maybe<mozilla::Side> GetSingleAutoInsetInAxis( + LogicalAxis aAxis, WritingMode aWM, + const AnchorPosOffsetResolutionParams& aParams) const; + AnchorResolvedSize GetWidth(const AnchorPosResolutionParams& aParams) const { return AnchorResolvedSizeHelper::FromUnresolved( mWidth, mozilla::StylePhysicalAxis::Horizontal, aParams); diff --git a/servo/components/style/values/specified/position.rs b/servo/components/style/values/specified/position.rs @@ -21,6 +21,7 @@ use crate::values::generics::position::ZIndex as GenericZIndex; use crate::values::generics::position::{AspectRatio as GenericAspectRatio, GenericAnchorSide}; use crate::values::generics::position::{GenericAnchorFunction, GenericInset}; use crate::values::specified; +use crate::values::specified::align::AlignFlags; use crate::values::specified::{AllowQuirks, Integer, LengthPercentage, NonNegativeNumber}; use crate::values::DashedIdent; use crate::{Atom, Zero}; @@ -1184,6 +1185,29 @@ impl PositionAreaKeyword { let new_track = old_track.flip(); Self::from_u8((self as u8 & !TRACK_MASK) | new_track as u8).unwrap() } + + /// Returns a value for the self-alignment properties in order to resolve + /// `normal`. + /// + /// <https://drafts.csswg.org/css-anchor-position/#position-area-alignment> + pub fn to_self_alignment(self) -> Option<AlignFlags> { + let track = self.track()?; + Some(match track { + // "If the only the center track in an axis is selected, the default alignment in that axis is center." + PositionAreaTrack::Center => AlignFlags::CENTER, + // "If all three tracks are selected, the default alignment in that axis is anchor-center." + PositionAreaTrack::SpanAll => AlignFlags::ANCHOR_CENTER, + // "Otherwise, the default alignment in that axis is toward the non-specified side track: if it’s + // specifying the “start” track of its axis, the default alignment in that axis is end; etc." + _ => { + if track.start() { + AlignFlags::END + } else { + AlignFlags::START + } + }, + }) + } } #[derive( diff --git a/servo/ports/geckolib/glue.rs b/servo/ports/geckolib/glue.rs @@ -163,12 +163,15 @@ use style::values::computed::length_percentage::{ AllowAnchorPosResolutionInCalcPercentage, Unpacked, }; use style::values::computed::position::{AnchorFunction, PositionArea}; -use style::values::computed::{self, ContentVisibility, Context, ToComputedValue}; +use style::values::computed::{ + self, ContentVisibility, Context, PositionAreaKeyword, ToComputedValue, +}; use style::values::distance::{ComputeSquaredDistance, SquaredDistance}; use style::values::generics::color::ColorMixFlags; use style::values::generics::easing::BeforeFlag; use style::values::generics::length::GenericAnchorSizeFunction; use style::values::resolved; +use style::values::specified::align::AlignFlags; use style::values::specified::intersection_observer::IntersectionObserverMargin; use style::values::specified::position::DashedIdentAndOrTryTactic; use style::values::specified::source_size_list::SourceSizeList; @@ -10761,3 +10764,19 @@ pub extern "C" fn Servo_PhysicalizePositionArea( ) { *area = area.to_physical(*cb_wm, *self_wm); } + +#[no_mangle] +pub extern "C" fn Servo_ResolvePositionAreaSelfAlignment( + area: &PositionAreaKeyword, + out: &mut AlignFlags, +) { + let Some(align) = area.to_self_alignment() else { + debug_assert!( + false, + "ResolvePositionAreaSelfAlignment called on {:?}", + area + ); + return; + }; + *out = align; +} diff --git a/testing/web-platform/meta/css/css-anchor-position/anchor-scroll-position-try-013.html.ini b/testing/web-platform/meta/css/css-anchor-position/anchor-scroll-position-try-013.html.ini @@ -1,9 +1,3 @@ [anchor-scroll-position-try-013.html] - [anchor-scroll-position-try-013] - expected: FAIL - - [anchor-scroll-position-try-013 2] - expected: FAIL - [anchor-scroll-position-try-013 1] expected: FAIL diff --git a/testing/web-platform/meta/css/css-anchor-position/last-successful-change-fallbacks-position-area.html.ini b/testing/web-platform/meta/css/css-anchor-position/last-successful-change-fallbacks-position-area.html.ini @@ -1,3 +0,0 @@ -[last-successful-change-fallbacks-position-area.html] - [position-try-fallbacks is set to a different value, both base and fallback works, uses base because last successful position option is invalidated] - expected: FAIL diff --git a/testing/web-platform/meta/css/css-anchor-position/popover-implicit-anchor.html.ini b/testing/web-platform/meta/css/css-anchor-position/popover-implicit-anchor.html.ini @@ -1,3 +0,0 @@ -[popover-implicit-anchor.html] - [Popover invokers form an implicit anchor reference] - expected: FAIL diff --git a/testing/web-platform/meta/css/css-anchor-position/position-area-align-justify-wm-dir.html.ini b/testing/web-platform/meta/css/css-anchor-position/position-area-align-justify-wm-dir.html.ini @@ -11,18 +11,6 @@ [Offsets for: self-x-start self-y-start with writing-mode / direction: containing-block: horizontal-tb / rtl] expected: FAIL - [Offsets for: start start with writing-mode / direction: containing-block: vertical-lr / ltr] - expected: FAIL - - [Offsets for: self-start self-start with writing-mode / direction: containing-block: vertical-lr / ltr] - expected: FAIL - - [Offsets for: x-start y-start with writing-mode / direction: containing-block: vertical-lr / ltr] - expected: FAIL - - [Offsets for: self-x-start self-y-start with writing-mode / direction: containing-block: vertical-lr / ltr] - expected: FAIL - [Offsets for: start start with writing-mode / direction: containing-block: vertical-lr / rtl] expected: FAIL @@ -53,56 +41,8 @@ [Offsets for: x-start y-start with writing-mode / direction: containing-block: vertical-rl / rtl] expected: FAIL - [Offsets for: start start with writing-mode / direction: self: horizontal-tb / rtl] - expected: FAIL - - [Offsets for: self-start self-start with writing-mode / direction: self: horizontal-tb / rtl] - expected: FAIL - - [Offsets for: x-start y-start with writing-mode / direction: self: horizontal-tb / rtl] - expected: FAIL - - [Offsets for: self-x-start self-y-start with writing-mode / direction: self: horizontal-tb / rtl] - expected: FAIL - - [Offsets for: start start with writing-mode / direction: self: vertical-lr / ltr] - expected: FAIL - - [Offsets for: self-start self-start with writing-mode / direction: self: vertical-lr / ltr] - expected: FAIL - - [Offsets for: x-start y-start with writing-mode / direction: self: vertical-lr / ltr] - expected: FAIL - - [Offsets for: self-x-start self-y-start with writing-mode / direction: self: vertical-lr / ltr] - expected: FAIL - - [Offsets for: start start with writing-mode / direction: self: vertical-lr / rtl] - expected: FAIL - - [Offsets for: self-start self-start with writing-mode / direction: self: vertical-lr / rtl] - expected: FAIL - - [Offsets for: x-start y-start with writing-mode / direction: self: vertical-lr / rtl] - expected: FAIL - - [Offsets for: self-x-start self-y-start with writing-mode / direction: self: vertical-lr / rtl] - expected: FAIL - - [Offsets for: start start with writing-mode / direction: self: vertical-rl / ltr] - expected: FAIL - - [Offsets for: self-start self-start with writing-mode / direction: self: vertical-rl / ltr] - expected: FAIL - - [Offsets for: x-start y-start with writing-mode / direction: self: vertical-rl / ltr] - expected: FAIL - - [Offsets for: self-x-start self-y-start with writing-mode / direction: self: vertical-rl / ltr] - expected: FAIL - - [Offsets for: start start with writing-mode / direction: self: vertical-rl / rtl] + [Offsets for: self-start self-start with writing-mode / direction: containing-block: vertical-rl / rtl] expected: FAIL - [Offsets for: x-start y-start with writing-mode / direction: self: vertical-rl / rtl] + [Offsets for: self-x-start self-y-start with writing-mode / direction: containing-block: vertical-rl / rtl] expected: FAIL diff --git a/testing/web-platform/meta/css/css-anchor-position/position-area-align-justify.html.ini b/testing/web-platform/meta/css/css-anchor-position/position-area-align-justify.html.ini @@ -1,39 +1,3 @@ [position-area-align-justify.html] [Offsets for position-area: span-all] expected: FAIL - - [Offsets for position-area: top left] - expected: FAIL - - [Offsets for position-area: top center] - expected: FAIL - - [Offsets for position-area: top right] - expected: FAIL - - [Offsets for position-area: center left] - expected: FAIL - - [Offsets for position-area: center center] - expected: FAIL - - [Offsets for position-area: center right] - expected: FAIL - - [Offsets for position-area: bottom left] - expected: FAIL - - [Offsets for position-area: bottom center] - expected: FAIL - - [Offsets for position-area: top span-left] - expected: FAIL - - [Offsets for position-area: top span-right] - expected: FAIL - - [Offsets for position-area: span-top left] - expected: FAIL - - [Offsets for position-area: span-bottom left] - expected: FAIL diff --git a/testing/web-platform/meta/css/css-anchor-position/position-area-in-position-try.html.ini b/testing/web-platform/meta/css/css-anchor-position/position-area-in-position-try.html.ini @@ -0,0 +1,6 @@ +[position-area-in-position-try.html] + [Placement: --bottom, --right, --left, --top] + expected: FAIL + + [Placement: --bottom, --left, --top, --right] + expected: FAIL diff --git a/testing/web-platform/meta/css/css-anchor-position/position-area-scrolling-002.tentative.html.ini b/testing/web-platform/meta/css/css-anchor-position/position-area-scrolling-002.tentative.html.ini @@ -1,18 +1,9 @@ [position-area-scrolling-002.tentative.html] - [Initial scroll position] - expected: FAIL - [Scroll to 40,60] expected: FAIL [Reattach at 40,60] expected: FAIL - [Redisplay at 40,60] - expected: FAIL - [Scroll to 0,0 and relayout] expected: FAIL - - [Redisplay at 0,0] - expected: FAIL diff --git a/testing/web-platform/meta/css/css-anchor-position/position-area-scrolling-004.tentative.html.ini b/testing/web-platform/meta/css/css-anchor-position/position-area-scrolling-004.tentative.html.ini @@ -1,2 +0,0 @@ -[position-area-scrolling-004.tentative.html] - expected: FAIL diff --git a/testing/web-platform/meta/css/css-anchor-position/position-area-scrolling-005.html.ini b/testing/web-platform/meta/css/css-anchor-position/position-area-scrolling-005.html.ini @@ -1,7 +1,4 @@ [position-area-scrolling-005.html] - [Initial scroll position] - expected: FAIL - [Scroll to 40,60] expected: FAIL @@ -10,9 +7,3 @@ [Scroll to 0,0] expected: FAIL - - [Redisplay at 0,0] - expected: FAIL - - [Scroll to 750,100] - expected: FAIL diff --git a/testing/web-platform/meta/css/css-anchor-position/position-area-scrolling-006.html.ini b/testing/web-platform/meta/css/css-anchor-position/position-area-scrolling-006.html.ini @@ -1,7 +1,4 @@ [position-area-scrolling-006.html] - [Initial scroll position] - expected: FAIL - [Scroll to the bottom] expected: FAIL diff --git a/testing/web-platform/meta/css/css-anchor-position/position-try-fallbacks-004.html.ini b/testing/web-platform/meta/css/css-anchor-position/position-try-fallbacks-004.html.ini @@ -0,0 +1,2 @@ +[position-try-fallbacks-004.html] + expected: FAIL diff --git a/testing/web-platform/meta/css/css-anchor-position/position-try-switch-to-fixed-anchor.html.ini b/testing/web-platform/meta/css/css-anchor-position/position-try-switch-to-fixed-anchor.html.ini @@ -1,2 +1,2 @@ [position-try-switch-to-fixed-anchor.html] - expected: FAIL + expected: [PASS, FAIL] diff --git a/testing/web-platform/meta/css/css-anchor-position/position-visibility-no-overflow-scroll-002.html.ini b/testing/web-platform/meta/css/css-anchor-position/position-visibility-no-overflow-scroll-002.html.ini @@ -0,0 +1,2 @@ +[position-visibility-no-overflow-scroll-002.html] + expected: FAIL diff --git a/testing/web-platform/tests/css/css-anchor-position/position-area-inset-one-side-auto.tentative.html b/testing/web-platform/tests/css/css-anchor-position/position-area-inset-one-side-auto.tentative.html @@ -0,0 +1,46 @@ +<!DOCTYPE html> +<link rel="help" href="https://drafts.csswg.org/css-anchor-position-1/#position-area-alignment"> +<link rel="author" href="mailto:wpt@keithcirkel.co.uk"> +<link rel="match" href="reference/position-area-inset-one-side-auto.html"> +<meta name="assert" content="A positioned element with one inset on one axis and auto on author should position unsafely"> +<style> +.abs { + width: 200px; + height: 200px; + position: relative; + border: 1px solid; +} + +.anchor { + width: 100px; + height: 100px; + background: tomato; + anchor-name: --a; + margin: 100px 0 0 100px; +} + +.ref { + position: absolute; + inset: 100px auto auto 100px; + width: 50px; + height: 50px; + background: green; +} + +.positioned { + inset: 100% auto auto 100px; + width: 50px; + height: 50px; + position-area: top left; + background: skyblue; + position-anchor: --a; + position: absolute; + position-visibility: always; +} + +</style> +<div class=abs> + <div class=anchor></div> + <div class=ref></div> + <div class=positioned></div> +</div> diff --git a/testing/web-platform/tests/css/css-anchor-position/reference/position-area-inset-one-side-auto.html b/testing/web-platform/tests/css/css-anchor-position/reference/position-area-inset-one-side-auto.html @@ -0,0 +1,28 @@ +<!DOCTYPE html> +<style> +.abs { + width: 200px; + height: 200px; + position: relative; + border: 1px solid; +} + +.anchor { + width: 100px; + height: 100px; + background: tomato; + margin: 100px 0 0 100px; +} + +.ref { + position: absolute; + inset: 100px auto auto 100px; + width: 50px; + height: 50px; + background: skyblue; +} +</style> +<div class=abs> + <div class=anchor></div> + <div class=ref></div> +</div>