diff --git a/layout/base/nsLayoutUtils.h b/layout/base/nsLayoutUtils.h index d05242b7a080..68334ed6aed4 100644 --- a/layout/base/nsLayoutUtils.h +++ b/layout/base/nsLayoutUtils.h @@ -1575,6 +1575,25 @@ class nsLayoutUtils { return std::max(0, result - aContentEdgeToBoxSizingBoxEdge); } + // Wrapper for ComputeBSizeValue that also handles 'stretch': + template + static nscoord ComputeBSizeValueHandlingStretch( + nscoord aContainingBlockBSize, nscoord aMargin, nscoord aBorderPadding, + nscoord aContentEdgeToBoxSizingBoxEdge, const SizeOrMaxSize& aSize) { + if (aSize.BehavesLikeStretchOnBlockAxis()) { + // Note: we don't need to worry about accounting for "box-sizing" when + // resolving 'stretch' here. This function unconditionally returns a + // content-box size, and the content-box size of a stretched element is + // the same regardless of whether whether the author is conceptually + // asking us to stretch the content box vs. the border-box. + return ComputeStretchContentBoxBSize(aContainingBlockBSize, aMargin, + aBorderPadding); + } + return ComputeBSizeValue(aContainingBlockBSize, + aContentEdgeToBoxSizingBoxEdge, + aSize.AsLengthPercentage()); + } + /** * Returns the size that an element's box should take on, in order for its * margin-box to exactly reach a particular larger size (e.g. to fill its @@ -1650,20 +1669,21 @@ class nsLayoutUtils { } /** - * The "extremum length" values (see ExtremumLength) were originally aimed at + * The "extremum length" values (see ExtremumLength) that return true from + * 'BehavesLikeInitialValueOnBlockAxis()' were originally aimed at * inline-size (or width, as it was before logicalization). For now, we return * true for those here, so that we don't call ComputeBSizeValue with value * types that it doesn't understand. (See bug 1113216.) - * - * FIXME (bug 567039, bug 527285) - * This isn't correct for the 'fill' value or for the 'min-*' or 'max-*' - * properties, which need to be handled differently by the callers of - * IsAutoBSize(). */ template static bool IsAutoBSize(const SizeOrMaxSize& aCoord, nscoord aCBBSize) { + // Note: percentages and 'stretch' both behave like 'auto' in the block + // axis *if and only if* they're resolved against an unconstrained + // block-size (on their containing block). That's what the second half of + // this condition is handling. return aCoord.BehavesLikeInitialValueOnBlockAxis() || - (aCBBSize == nscoord_MAX && aCoord.HasPercent()); + (aCBBSize == nscoord_MAX && + (aCoord.HasPercent() || aCoord.BehavesLikeStretchOnBlockAxis())); } static bool IsPaddingZero(const LengthPercentage& aLength) { diff --git a/layout/generic/ReflowInput.cpp b/layout/generic/ReflowInput.cpp index f9ad1f3ac61b..04df2979c5fb 100644 --- a/layout/generic/ReflowInput.cpp +++ b/layout/generic/ReflowInput.cpp @@ -285,6 +285,20 @@ nscoord SizeComputationInput::ComputeISizeValue( .mISize; } +template +nscoord SizeComputationInput::ComputeBSizeValueHandlingStretch( + nscoord aContainingBlockBSize, StyleBoxSizing aBoxSizing, + const SizeOrMaxSize& aSize) const { + if (aSize.BehavesLikeStretchOnBlockAxis()) { + WritingMode wm = GetWritingMode(); + return nsLayoutUtils::ComputeStretchContentBoxBSize( + aContainingBlockBSize, ComputedLogicalMargin(wm).Size(wm).BSize(wm), + ComputedLogicalBorderPadding(wm).Size(wm).BSize(wm)); + } + return ComputeBSizeValue(aContainingBlockBSize, aBoxSizing, + aSize.AsLengthPercentage()); +} + nscoord SizeComputationInput::ComputeBSizeValue( nscoord aContainingBlockBSize, StyleBoxSizing aBoxSizing, const LengthPercentage& aSize) const { @@ -1489,7 +1503,9 @@ void ReflowInput::CalculateHypotheticalPosition( nscoord boxBSize; const auto& styleBSize = mStylePosition->BSize(wm); - if (styleBSize.BehavesLikeInitialValueOnBlockAxis()) { + const bool isAutoBSize = + nsLayoutUtils::IsAutoBSize(styleBSize, blockContentSize.BSize(wm)); + if (isAutoBSize) { if (mFlags.mIsReplaced && intrinsicSize) { // It's a replaced element with an 'auto' block size so the box // block size is its intrinsic size plus any border/padding/margin @@ -1501,6 +1517,16 @@ void ReflowInput::CalculateHypotheticalPosition( // positioned frame?) boxBSize = 0; } + } else if (styleBSize.BehavesLikeStretchOnBlockAxis()) { + MOZ_ASSERT(blockContentSize.BSize(wm) != NS_UNCONSTRAINEDSIZE, + "If we're 'stretch' with unconstrained size, isAutoBSize " + "should be true which should make us skip this code"); + // TODO(dholbert) The 'insideBoxSizing' and 'outsideBoxSizing' usages + // here aren't quite right, because we're supposed to be passing margin + // and borderPadding specifically. The arithmetic seems to work out in + // testcases though. + boxBSize = nsLayoutUtils::ComputeStretchContentBoxBSize( + blockContentSize.BSize(wm), outsideBoxSizing, insideBoxSizing); } else { // We need to compute it. It's important we do this, because if it's // percentage-based this computed value may be different from the @@ -3013,9 +3039,8 @@ void ReflowInput::ComputeMinMaxValues(const LogicalSize& aCBSize) { if (BSizeBehavesAsInitialValue(minBSize)) { SetComputedMinBSize(0); } else { - SetComputedMinBSize(ComputeBSizeValue(bPercentageBasis, - mStylePosition->mBoxSizing, - minBSize.AsLengthPercentage())); + SetComputedMinBSize(ComputeBSizeValueHandlingStretch( + bPercentageBasis, mStylePosition->mBoxSizing, minBSize)); } if (mIsThemed) { @@ -3026,9 +3051,8 @@ void ReflowInput::ComputeMinMaxValues(const LogicalSize& aCBSize) { // Specified value of 'none' SetComputedMaxBSize(NS_UNCONSTRAINEDSIZE); } else { - SetComputedMaxBSize(ComputeBSizeValue(bPercentageBasis, - mStylePosition->mBoxSizing, - maxBSize.AsLengthPercentage())); + SetComputedMaxBSize(ComputeBSizeValueHandlingStretch( + bPercentageBasis, mStylePosition->mBoxSizing, maxBSize)); } // If the computed value of 'min-height' is greater than the value of diff --git a/layout/generic/ReflowInput.h b/layout/generic/ReflowInput.h index efc77cda8320..61231917a1e2 100644 --- a/layout/generic/ReflowInput.h +++ b/layout/generic/ReflowInput.h @@ -169,7 +169,7 @@ struct SizeComputationInput { const Maybe& aPadding, const nsStyleDisplay* aDisplay = nullptr); - /* + /** * Convert StyleSize or StyleMaxSize to nscoord when percentages depend on the * inline size of the containing block, and enumerated values are for inline * size, min-inline-size, or max-inline-size. Does not handle auto inline @@ -180,6 +180,20 @@ struct SizeComputationInput { StyleBoxSizing aBoxSizing, const SizeOrMaxSize&) const; + /** + * Wrapper for SizeComputationInput::ComputeBSizeValue (defined below, which + * itself is a wrapper for nsLayoutUtils::ComputeBSizeValue). This one just + * handles 'stretch' sizes first. + */ + template + inline nscoord ComputeBSizeValueHandlingStretch( + nscoord aContainingBlockBSize, StyleBoxSizing aBoxSizing, + const SizeOrMaxSize& aSize) const; + + /** + * Wrapper for nsLayoutUtils::ComputeBSizeValue, which automatically figures + * out the value to pass for its aContentEdgeToBoxSizingBoxEdge param. + */ nscoord ComputeBSizeValue(nscoord aContainingBlockBSize, StyleBoxSizing aBoxSizing, const LengthPercentage& aCoord) const; diff --git a/layout/generic/nsBlockFrame.cpp b/layout/generic/nsBlockFrame.cpp index 1eb8a413aaa8..6115d0222278 100644 --- a/layout/generic/nsBlockFrame.cpp +++ b/layout/generic/nsBlockFrame.cpp @@ -4029,17 +4029,20 @@ void nsBlockFrame::MoveChildFramesOfLine(nsLineBox* aLine, } static inline bool IsNonAutoNonZeroBSize(const StyleSize& aCoord) { - // The "extremum length" values (see ExtremumLength) were originally aimed at + // The "extremum length" values (see ExtremumLength) that return true from + // 'BehavesLikeInitialValueOnBlockAxis()' were originally aimed at // inline-size (or width, as it was before logicalization). For now, let them // return false here, so we treat them like 'auto' pending a real // implementation. (See bug 1126420.) - // - // FIXME (bug 567039, bug 527285) This isn't correct for the 'fill' value, - // which should more likely (but not necessarily, depending on the available - // space) be returning true. if (aCoord.BehavesLikeInitialValueOnBlockAxis()) { return false; } + if (aCoord.BehavesLikeStretchOnBlockAxis()) { + // We return true for "stretch" because it's essentially equivalent to + // "100%" for the purposes of this function (and this function returns true + // for nonzero percentage values, in the final return statement below). + return true; + } MOZ_ASSERT(aCoord.IsLengthPercentage()); // If we evaluate the length/percent/calc at a percentage basis of // both nscoord_MAX and 0, and it's zero both ways, then it's a zero diff --git a/layout/generic/nsContainerFrame.cpp b/layout/generic/nsContainerFrame.cpp index df784326b69f..fdbdc1318275 100644 --- a/layout/generic/nsContainerFrame.cpp +++ b/layout/generic/nsContainerFrame.cpp @@ -2207,6 +2207,9 @@ LogicalSize nsContainerFrame::ComputeSizeWithIntrinsicDimensions( const auto& styleISize = aSizeOverrides.mStyleISize ? *aSizeOverrides.mStyleISize : stylePos->ISize(aWM); + + // TODO(dholbert): if styleBSize is 'stretch' here, we should probably + // resolve it like we do in nsIFrame::ComputeSize. See bug 1937275. const auto& styleBSize = aSizeOverrides.mStyleBSize ? *aSizeOverrides.mStyleBSize : stylePos->BSize(aWM); @@ -2340,9 +2343,9 @@ LogicalSize nsContainerFrame::ComputeSizeWithIntrinsicDimensions( } if (!isAutoBSize) { - bSize = nsLayoutUtils::ComputeBSizeValue(aCBSize.BSize(aWM), - boxSizingAdjust.BSize(aWM), - styleBSize.AsLengthPercentage()); + bSize = nsLayoutUtils::ComputeBSizeValueHandlingStretch( + aCBSize.BSize(aWM), aMargin.BSize(aWM), aBorderPadding.BSize(aWM), + boxSizingAdjust.BSize(aWM), styleBSize); } else if (MOZ_UNLIKELY(isGridItem) && !parentFrame->IsMasonry(isOrthogonal ? LogicalAxis::Inline : LogicalAxis::Block)) { @@ -2377,9 +2380,9 @@ LogicalSize nsContainerFrame::ComputeSizeWithIntrinsicDimensions( const auto& maxBSizeCoord = stylePos->MaxBSize(aWM); if (!nsLayoutUtils::IsAutoBSize(maxBSizeCoord, aCBSize.BSize(aWM)) && !isFlexItemBlockAxisMainAxis) { - maxBSize = nsLayoutUtils::ComputeBSizeValue( - aCBSize.BSize(aWM), boxSizingAdjust.BSize(aWM), - maxBSizeCoord.AsLengthPercentage()); + maxBSize = nsLayoutUtils::ComputeBSizeValueHandlingStretch( + aCBSize.BSize(aWM), aMargin.BSize(aWM), aBorderPadding.BSize(aWM), + boxSizingAdjust.BSize(aWM), maxBSizeCoord); } else { maxBSize = nscoord_MAX; } @@ -2387,9 +2390,9 @@ LogicalSize nsContainerFrame::ComputeSizeWithIntrinsicDimensions( const auto& minBSizeCoord = stylePos->MinBSize(aWM); if (!nsLayoutUtils::IsAutoBSize(minBSizeCoord, aCBSize.BSize(aWM)) && !isFlexItemBlockAxisMainAxis) { - minBSize = nsLayoutUtils::ComputeBSizeValue( - aCBSize.BSize(aWM), boxSizingAdjust.BSize(aWM), - minBSizeCoord.AsLengthPercentage()); + minBSize = nsLayoutUtils::ComputeBSizeValueHandlingStretch( + aCBSize.BSize(aWM), aMargin.BSize(aWM), aBorderPadding.BSize(aWM), + boxSizingAdjust.BSize(aWM), minBSizeCoord); } else { minBSize = 0; } diff --git a/layout/generic/nsFlexContainerFrame.cpp b/layout/generic/nsFlexContainerFrame.cpp index 6a33dcc3f817..a3c0e02df2d5 100644 --- a/layout/generic/nsFlexContainerFrame.cpp +++ b/layout/generic/nsFlexContainerFrame.cpp @@ -1606,6 +1606,10 @@ nscoord nsFlexContainerFrame::PartiallyResolveAutoMinSize( nscoord specifiedSizeSuggestion = nscoord_MAX; if (aAxisTracker.IsRowOriented()) { + // TODO(dholbert): We need to handle 'stretch' (and its prefixed aliases) + // here; that's tracked in bug 1936942. (Note that we do handle 'stretch' + // in our column-oriented "else" clause below, via the call to + // ComputeBSizeValueHandlingStretch.) if (mainStyleSize.IsLengthPercentage()) { // NOTE: We ignore extremum inline-size. This is OK because the caller is // responsible for computing the min-content inline-size and min()'ing it @@ -1615,14 +1619,16 @@ nscoord nsFlexContainerFrame::PartiallyResolveAutoMinSize( mainStyleSize.AsLengthPercentage()); } } else { + // NOTE: We ignore specified block-sizes that behave as 'auto', as + // identified by IsAutoBSize(); that's OK because the caller is responsible + // for computing the content-based block-size and and min()'ing it with the + // value we return. const auto percentageBasisBSize = PercentageBasisForItem().BSize(cbWM); if (!nsLayoutUtils::IsAutoBSize(mainStyleSize, percentageBasisBSize)) { - // NOTE: We ignore auto and extremum block-size. This is OK because the - // caller is responsible for computing the min-content block-size and - // min()'ing it with the value we return. - specifiedSizeSuggestion = nsLayoutUtils::ComputeBSizeValue( - percentageBasisBSize, boxSizingAdjust.BSize(cbWM), - mainStyleSize.AsLengthPercentage()); + specifiedSizeSuggestion = nsLayoutUtils::ComputeBSizeValueHandlingStretch( + percentageBasisBSize, aFlexItem.MarginSizeInMainAxis(), + aFlexItem.BorderPaddingSizeInMainAxis(), boxSizingAdjust.BSize(cbWM), + mainStyleSize); } } @@ -2340,6 +2346,15 @@ bool FlexItem::IsMinSizeAutoResolutionNeeded() const { const auto& mainMinSize = Frame()->StylePosition()->MinSize(MainAxis(), ContainingBlockWM()); + // "min-{height,width}:stretch" never produces an automatic minimum size. You + // might think it would result in an automatic min-size if the containing + // block size is indefinite, but "stretch" is instead treated as 0px in that + // case rather than auto. This WPT requires this behavior: + // https://wpt.live/css/css-sizing/stretch/indefinite-4.html More details & + // discussion here: https://github.com/w3c/csswg-drafts/issues/11006 + if (mainMinSize.BehavesLikeStretchOnBlockAxis()) { + return false; + } return IsAutoOrEnumOnBSize(mainMinSize, IsInlineAxisMainAxis()) && !Frame()->StyleDisplay()->IsScrollableOverflow(); } diff --git a/layout/generic/nsIFrame.cpp b/layout/generic/nsIFrame.cpp index 3b1e21f1d466..46afec9dd03f 100644 --- a/layout/generic/nsIFrame.cpp +++ b/layout/generic/nsIFrame.cpp @@ -6394,15 +6394,30 @@ nsIFrame::SizeComputationResult nsIFrame::ComputeSize( aBorderPadding.ISize(aWM) - boxSizingAdjust.ISize(aWM); - const auto& styleISize = aSizeOverrides.mStyleISize - ? *aSizeOverrides.mStyleISize - : stylePos->ISize(aWM); - const auto& styleBSize = aSizeOverrides.mStyleBSize - ? *aSizeOverrides.mStyleBSize - : stylePos->BSize(aWM); const auto& aspectRatio = aSizeOverrides.mAspectRatio ? *aSizeOverrides.mAspectRatio : GetAspectRatio(); + const auto& styleISize = aSizeOverrides.mStyleISize + ? *aSizeOverrides.mStyleISize + : stylePos->ISize(aWM); + // For bsize, we consider overrides *and then* we resolve 'stretch' to a + // nscoord value, for convenience (so that we can assume that either + // isAutoBSize is true, or styleBSize is of type LengthPercentage()). + const auto& styleBSize = [&] { + const auto& styleBSizeConsideringOverrides = + (aSizeOverrides.mStyleBSize) ? *aSizeOverrides.mStyleBSize + : stylePos->BSize(aWM); + if (styleBSizeConsideringOverrides.BehavesLikeStretchOnBlockAxis() && + aCBSize.BSize(aWM) != NS_UNCONSTRAINEDSIZE) { + // We've got a 'stretch' BSize; resolve it to a length: + nscoord stretchBSize = nsLayoutUtils::ComputeStretchBSize( + aCBSize.BSize(aWM), aMargin.BSize(aWM), aBorderPadding.BSize(aWM), + stylePos->mBoxSizing); + return StyleSize::LengthPercentage( + LengthPercentage::FromAppUnits(stretchBSize)); + } + return styleBSizeConsideringOverrides; + }(); auto parentFrame = GetParent(); auto alignCB = parentFrame; @@ -6439,6 +6454,11 @@ nsIFrame::SizeComputationResult nsIFrame::ComputeSize( const bool isAutoBSize = nsLayoutUtils::IsAutoBSize(styleBSize, aCBSize.BSize(aWM)); + MOZ_ASSERT(isAutoBSize || styleBSize.IsLengthPercentage(), + "We should have resolved away any non-'auto'-like flavors " + "of styleBSize into a LengthPercentage. (If this fails, we " + "might run afoul of some AsLengthPercentage() call below.)"); + // Compute inline-axis size const bool isSubgriddedInInlineAxis = isSubgrid && static_cast(this)->IsColSubgrid(); @@ -6722,16 +6742,16 @@ nsIFrame::SizeComputationResult nsIFrame::ComputeSize( const bool shouldIgnoreMinMaxBSize = isFlexItemBlockAxisMainAxis || isSubgriddedInBlockAxis; if (!isAutoMaxBSize && !shouldIgnoreMinMaxBSize) { - nscoord maxBSize = nsLayoutUtils::ComputeBSizeValue( - aCBSize.BSize(aWM), boxSizingAdjust.BSize(aWM), - maxBSizeCoord.AsLengthPercentage()); + nscoord maxBSize = nsLayoutUtils::ComputeBSizeValueHandlingStretch( + aCBSize.BSize(aWM), aMargin.BSize(aWM), aBorderPadding.BSize(aWM), + boxSizingAdjust.BSize(aWM), maxBSizeCoord); result.BSize(aWM) = std::min(maxBSize, result.BSize(aWM)); } if (!isAutoMinBSize && !shouldIgnoreMinMaxBSize) { - nscoord minBSize = nsLayoutUtils::ComputeBSizeValue( - aCBSize.BSize(aWM), boxSizingAdjust.BSize(aWM), - minBSizeCoord.AsLengthPercentage()); + nscoord minBSize = nsLayoutUtils::ComputeBSizeValueHandlingStretch( + aCBSize.BSize(aWM), aMargin.BSize(aWM), aBorderPadding.BSize(aWM), + boxSizingAdjust.BSize(aWM), minBSizeCoord); result.BSize(aWM) = std::max(minBSize, result.BSize(aWM)); } } @@ -6770,20 +6790,32 @@ nscoord nsIFrame::ComputeBSizeValueAsPercentageBasis( return NS_UNCONSTRAINEDSIZE; } - const nscoord bSize = nsLayoutUtils::ComputeBSizeValue( - aCBBSize, aContentEdgeToBoxSizingBSize, aStyleBSize.AsLengthPercentage()); + // TODO(dholbert): This is a temporary hack, to be fixed up in bug 1933604. + // We don't know have aMargin or aBorderPadding args available, + // so we use these dummy zero-valued variables as placeholders in + // our call to ComputeBSizeValueHandlingStretch. (This might mean we + // end up resolving 'stretch' to something slighlty-too-large for the + // purposes of this call, if there's actually nonzero margin/border/padding). + const nscoord dummyMargin = 0; + const nscoord dummyBorderPadding = 0; - const nscoord minBSize = nsLayoutUtils::IsAutoBSize(aStyleMinBSize, aCBBSize) - ? 0 - : nsLayoutUtils::ComputeBSizeValue( - aCBBSize, aContentEdgeToBoxSizingBSize, - aStyleMinBSize.AsLengthPercentage()); + const nscoord bSize = nsLayoutUtils::ComputeBSizeValueHandlingStretch( + aCBBSize, dummyMargin, dummyBorderPadding, aContentEdgeToBoxSizingBSize, + aStyleBSize); - const nscoord maxBSize = nsLayoutUtils::IsAutoBSize(aStyleMaxBSize, aCBBSize) - ? NS_UNCONSTRAINEDSIZE - : nsLayoutUtils::ComputeBSizeValue( - aCBBSize, aContentEdgeToBoxSizingBSize, - aStyleMaxBSize.AsLengthPercentage()); + const nscoord minBSize = + nsLayoutUtils::IsAutoBSize(aStyleMinBSize, aCBBSize) + ? 0 + : nsLayoutUtils::ComputeBSizeValueHandlingStretch( + aCBBSize, dummyMargin, dummyBorderPadding, + aContentEdgeToBoxSizingBSize, aStyleMinBSize); + + const nscoord maxBSize = + nsLayoutUtils::IsAutoBSize(aStyleMaxBSize, aCBBSize) + ? NS_UNCONSTRAINEDSIZE + : nsLayoutUtils::ComputeBSizeValueHandlingStretch( + aCBBSize, dummyMargin, dummyBorderPadding, + aContentEdgeToBoxSizingBSize, aStyleMaxBSize); return CSSMinMax(bSize, minBSize, maxBSize); } diff --git a/layout/style/ServoStyleConstsInlines.h b/layout/style/ServoStyleConstsInlines.h index 0d836ab3107d..7a14ab29d3af 100644 --- a/layout/style/ServoStyleConstsInlines.h +++ b/layout/style/ServoStyleConstsInlines.h @@ -837,14 +837,20 @@ inline bool StyleFlexBasis::IsAuto() const { return IsSize() && AsSize().IsAuto(); } -#define IMPL_BEHAVES_LIKE_SIZE_METHODS(ty_, isInitialValMethod_) \ - template <> \ - inline bool ty_::BehavesLikeStretchOnInlineAxis() const { \ - return IsStretch() || IsMozAvailable() || IsWebkitFillAvailable(); \ - } \ - template <> \ - inline bool ty_::BehavesLikeInitialValueOnBlockAxis() const { \ - return isInitialValMethod_() || !IsLengthPercentage(); \ +#define IMPL_BEHAVES_LIKE_SIZE_METHODS(ty_, isInitialValMethod_) \ + template <> \ + inline bool ty_::BehavesLikeStretchOnInlineAxis() const { \ + return IsStretch() || IsMozAvailable() || IsWebkitFillAvailable(); \ + } \ + template <> \ + inline bool ty_::BehavesLikeStretchOnBlockAxis() const { \ + /* TODO(dholbert): Add "|| IsMozAvailable()" in bug 527285. */ \ + return IsStretch() || IsWebkitFillAvailable(); \ + } \ + template <> \ + inline bool ty_::BehavesLikeInitialValueOnBlockAxis() const { \ + return isInitialValMethod_() || \ + (!BehavesLikeStretchOnBlockAxis() && !IsLengthPercentage()); \ } IMPL_BEHAVES_LIKE_SIZE_METHODS(StyleSize, IsAuto) diff --git a/layout/style/nsStyleStruct.h b/layout/style/nsStyleStruct.h index 22a9e464933c..c29f74db97b5 100644 --- a/layout/style/nsStyleStruct.h +++ b/layout/style/nsStyleStruct.h @@ -921,8 +921,10 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStylePosition { template static bool BSizeCoordDependsOnContainer(const SizeOrMaxSize& aCoord) { - return aCoord.IsLengthPercentage() && - aCoord.AsLengthPercentage().HasPercent(); + if (aCoord.IsLengthPercentage()) { + return aCoord.AsLengthPercentage().HasPercent(); + } + return aCoord.BehavesLikeStretchOnBlockAxis(); } }; diff --git a/layout/style/test/test_value_computation.html b/layout/style/test/test_value_computation.html index 8c98ccdeed5a..ad84c6f0a13e 100644 --- a/layout/style/test/test_value_computation.html +++ b/layout/style/test/test_value_computation.html @@ -80,12 +80,14 @@ var gSwapInitialWhenHaveFrame = { // For the block axis ('height' by default): when there's a frame, these // keywords work out to the same as the initial value, i.e. `auto`, given - // the prerequisites of only 'display: block'. + // the prerequisites of only 'display: block'. (Notably, 'stretch' and + // its '-webkit-fill-available' alias *do not behave like auto* in the + // block axis, so they're not listed among the keywords here.) "height": [ "-moz-max-content", "-moz-min-content", "-moz-fit-content", - "-moz-available", "-webkit-fill-available", + "-moz-available", // TODO(dholbert): remove in bug 527285. "max-content", "min-content", "fit-content", "fit-content(100px)", "fit-content(10%)", - "fit-content(calc(3*25px + 50%))", "stretch" ], + "fit-content(calc(3*25px + 50%))" ], }; // Use the same lists for logical versions of width/height properties: gSwapInitialWhenHaveFrame["inline-size"] = gSwapInitialWhenHaveFrame.width; diff --git a/servo/ports/geckolib/cbindgen.toml b/servo/ports/geckolib/cbindgen.toml index adf2bf61b278..d16840e7cece 100644 --- a/servo/ports/geckolib/cbindgen.toml +++ b/servo/ports/geckolib/cbindgen.toml @@ -500,6 +500,7 @@ renaming_overrides_prefixing = true inline bool HasPercent() const; inline bool HasLengthAndPercentage() const; inline bool BehavesLikeStretchOnInlineAxis() const; + inline bool BehavesLikeStretchOnBlockAxis() const; inline bool BehavesLikeInitialValueOnBlockAxis() const; inline bool BehavesLikeInitialValue(LogicalAxis) const; """ @@ -516,6 +517,7 @@ renaming_overrides_prefixing = true inline bool HasPercent() const; inline bool HasLengthAndPercentage() const; inline bool BehavesLikeStretchOnInlineAxis() const; + inline bool BehavesLikeStretchOnBlockAxis() const; inline bool BehavesLikeInitialValueOnBlockAxis() const; inline bool BehavesLikeInitialValue(LogicalAxis) const; """