From 19650c6f8a55e1cfed6acd9bcf415409569f0945 Mon Sep 17 00:00:00 2001 From: FranklinDM Date: Sat, 13 May 2023 14:50:12 +0800 Subject: Issue #1765 - Part 1: Move ReduceNumberCalcOps struct up higher, rename IsCSSTokenCalcFunction to CSSParserImpl::IsCalcFunctionToken --- layout/style/nsCSSParser.cpp | 52 +++++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 25 deletions(-) (limited to 'layout') diff --git a/layout/style/nsCSSParser.cpp b/layout/style/nsCSSParser.cpp index 1483eb0a11..244abf36ae 100644 --- a/layout/style/nsCSSParser.cpp +++ b/layout/style/nsCSSParser.cpp @@ -137,6 +137,22 @@ struct CSSParserInputState { bool mHavePushBack; }; +struct ReduceNumberCalcOps : public mozilla::css::BasicFloatCalcOps, + public mozilla::css::CSSValueInputCalcOps +{ + result_type ComputeLeafValue(const nsCSSValue& aValue) + { + // FIXME: Restore this assertion once ParseColor no longer uses this class. + //MOZ_ASSERT(aValue.GetUnit() == eCSSUnit_Number, "unexpected unit"); + return aValue.GetFloatValue(); + } + + float ComputeNumber(const nsCSSValue& aValue) + { + return mozilla::css::ComputeCalc(aValue, *this); + } +}; + static_assert(css::eAuthorSheetFeatures == 0 && css::eUserSheetFeatures == 1 && css::eAgentSheetFeatures == 2, @@ -895,6 +911,7 @@ protected: }; bool IsFunctionTokenValidForImageLayerImage(const nsCSSToken& aToken) const; + bool IsCalcFunctionToken(const nsCSSToken& aToken) const; bool ParseImageLayersItem(ImageLayersShorthandParseState& aState, const nsCSSPropertyID aTable[]); @@ -7867,14 +7884,6 @@ CSSParserImpl::ParseOneOrLargerVariant(nsCSSValue& aValue, return result; } -static bool -IsCSSTokenCalcFunction(const nsCSSToken& aToken) -{ - return aToken.mType == eCSSToken_Function && - (aToken.mIdent.LowerCaseEqualsLiteral("calc") || - aToken.mIdent.LowerCaseEqualsLiteral("-moz-calc")); -} - // Assigns to aValue iff it returns CSSParseResult::Ok. CSSParseResult CSSParserImpl::ParseVariant(nsCSSValue& aValue, @@ -8174,7 +8183,7 @@ CSSParserImpl::ParseVariant(nsCSSValue& aValue, } } if ((aVariantMask & VARIANT_CALC) && - IsCSSTokenCalcFunction(*tk)) { + IsCalcFunctionToken(*tk)) { // calc() currently allows only lengths and percents and number inside it. // And note that in current implementation, number cannot be mixed with // length and percent. @@ -12438,6 +12447,14 @@ CSSParserImpl::IsFunctionTokenValidForImageLayerImage( funcName.LowerCaseEqualsLiteral("-webkit-repeating-radial-gradient"))); } +bool +CSSParserImpl::IsCalcFunctionToken(const nsCSSToken& aToken) const +{ + return aToken.mType == eCSSToken_Function && + (aToken.mIdent.LowerCaseEqualsLiteral("calc") || + aToken.mIdent.LowerCaseEqualsLiteral("-moz-calc")); +} + // Parse one item of the background shorthand property. bool CSSParserImpl::ParseImageLayersItem( @@ -13830,21 +13847,6 @@ CSSParserImpl::ParseCalcAdditiveExpression(nsCSSValue& aValue, } } -struct ReduceNumberCalcOps : public mozilla::css::BasicFloatCalcOps, - public mozilla::css::CSSValueInputCalcOps -{ - result_type ComputeLeafValue(const nsCSSValue& aValue) - { - MOZ_ASSERT(aValue.GetUnit() == eCSSUnit_Number, "unexpected unit"); - return aValue.GetFloatValue(); - } - - float ComputeNumber(const nsCSSValue& aValue) - { - return mozilla::css::ComputeCalc(aValue, *this); - } -}; - // * If aVariantMask is VARIANT_NUMBER, this function parses the // production. // * If aVariantMask does not contain VARIANT_NUMBER, this function @@ -13965,7 +13967,7 @@ CSSParserImpl::ParseCalcTerm(nsCSSValue& aValue, uint32_t& aVariantMask) // Either an additive expression in parentheses... if (mToken.IsSymbol('(') || // Treat nested calc() as plain parenthesis. - IsCSSTokenCalcFunction(mToken)) { + IsCalcFunctionToken(mToken)) { if (!ParseCalcAdditiveExpression(aValue, aVariantMask) || !ExpectSymbol(')', true)) { SkipUntil(')'); -- cgit v1.2.3 From e56b7b826d6f4f8cb1fc4bcd06fce7786540784c Mon Sep 17 00:00:00 2001 From: FranklinDM Date: Sat, 13 May 2023 18:15:13 +0800 Subject: Issue #1765 - Part 2: Implement calc() parsing inside rgb/a() and the non-hue component of hsl/a() This also adds a new helper method for checking the type of tokens that will be parsed after the current token, which is useful for determining the unit of values inside calc() functions. Partially based on https://github.com/roytam1/UXP/commit/8a0897d23f5b51526f8a2c6ef63cb26968e6b985 --- layout/style/nsCSSParser.cpp | 70 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 63 insertions(+), 7 deletions(-) (limited to 'layout') diff --git a/layout/style/nsCSSParser.cpp b/layout/style/nsCSSParser.cpp index 244abf36ae..14a935c321 100644 --- a/layout/style/nsCSSParser.cpp +++ b/layout/style/nsCSSParser.cpp @@ -676,6 +676,11 @@ protected: bool SkipAtRule(bool aInsideBlock); bool SkipDeclaration(bool aCheckForBraces); + // Returns true when the target token type is found, and false for the + // end of declaration, start of !important flag, end of declaration + // block, or EOF. + bool LookForTokenType(nsCSSTokenType aType); + void PushGroup(css::GroupRule* aRule); void PopGroup(); @@ -5419,6 +5424,33 @@ CSSParserImpl::SkipDeclaration(bool aCheckForBraces) return true; } +bool +CSSParserImpl::LookForTokenType(nsCSSTokenType aType) { + bool rv = false; + CSSParserInputState stateBeforeValue; + SaveInputState(stateBeforeValue); + + const char16_t stopChars[] = { ';', '!', '}', 0 }; + nsDependentString stopSymbolChars(stopChars); + while (GetToken(true)) { + // The current function has percentage values. + if (mToken.mType == eCSSToken_Percentage) { + rv = true; + break; + } + // Stop looking if we're at the end of the declaration, encountered an + // !important flag, or at the end of the declaration block. + if (mToken.mType == eCSSToken_Symbol && + stopSymbolChars.FindChar(mToken.mSymbol) != -1) { + rv = false; + break; + } + } + + RestoreSavedInputState(stateBeforeValue); + return rv; +} + void CSSParserImpl::SkipRuleSet(bool aInsideBraces) { @@ -7000,7 +7032,15 @@ CSSParserImpl::ParseColor(nsCSSValue& aValue) if (GetToken(true)) { UngetToken(); } - if (mToken.mType == eCSSToken_Number) { // + + bool isNumber = mToken.mType == eCSSToken_Number; + + // Check first if we have percentage values inside the function. + if (mToken.mType == eCSSToken_Function) { + isNumber = !LookForTokenType(eCSSToken_Percentage); + } + + if (isNumber) { // uint8_t r, g, b, a; if (ParseRGBColor(r, g, b, a)) { @@ -7107,14 +7147,22 @@ CSSParserImpl::ParseColorComponent(uint8_t& aComponent, Maybe aSeparator) return false; } - if (mToken.mType != eCSSToken_Number) { + float value; + if (mToken.mType == eCSSToken_Number) { + value = mToken.mNumber; + } else if (IsCalcFunctionToken(mToken)) { + nsCSSValue aValue; + if (!ParseCalc(aValue, VARIANT_LPN | VARIANT_CALC)) { + return false; + } + ReduceNumberCalcOps ops; + value = mozilla::css::ComputeCalc(aValue, ops); + } else { REPORT_UNEXPECTED_TOKEN(PEExpectedNumber); UngetToken(); return false; } - float value = mToken.mNumber; - if (aSeparator && !ExpectSymbol(*aSeparator, true)) { REPORT_UNEXPECTED_TOKEN_CHAR(PEColorComponentBadTerm, *aSeparator); return false; @@ -7135,14 +7183,22 @@ CSSParserImpl::ParseColorComponent(float& aComponent, Maybe aSeparator) return false; } - if (mToken.mType != eCSSToken_Percentage) { + float value; + if (mToken.mType == eCSSToken_Percentage) { + value = mToken.mNumber; + } else if (IsCalcFunctionToken(mToken)) { + nsCSSValue aValue; + if (!ParseCalc(aValue, VARIANT_LPN | VARIANT_CALC)) { + return false; + } + ReduceNumberCalcOps ops; + value = mozilla::css::ComputeCalc(aValue, ops); + } else { REPORT_UNEXPECTED_TOKEN(PEExpectedPercent); UngetToken(); return false; } - float value = mToken.mNumber; - if (aSeparator && !ExpectSymbol(*aSeparator, true)) { REPORT_UNEXPECTED_TOKEN_CHAR(PEColorComponentBadTerm, *aSeparator); return false; -- cgit v1.2.3 From ddf3f39070c662bf92320fdd0cafcdaff22ab377 Mon Sep 17 00:00:00 2001 From: FranklinDM Date: Sun, 14 May 2023 18:31:21 +0800 Subject: Issue #1765 - Part 3: Provided token type should be used in LookForTokenType I didn't realize this immediately after moving the code into a method. Oops. --- layout/style/nsCSSParser.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'layout') diff --git a/layout/style/nsCSSParser.cpp b/layout/style/nsCSSParser.cpp index 14a935c321..f66415ea9e 100644 --- a/layout/style/nsCSSParser.cpp +++ b/layout/style/nsCSSParser.cpp @@ -5433,8 +5433,7 @@ CSSParserImpl::LookForTokenType(nsCSSTokenType aType) { const char16_t stopChars[] = { ';', '!', '}', 0 }; nsDependentString stopSymbolChars(stopChars); while (GetToken(true)) { - // The current function has percentage values. - if (mToken.mType == eCSSToken_Percentage) { + if (mToken.mType == aType) { rv = true; break; } -- cgit v1.2.3 From c58f825821ad1b7d6d695116326118d01941f279 Mon Sep 17 00:00:00 2001 From: FranklinDM Date: Sun, 21 May 2023 15:17:29 +0800 Subject: Issue #2250 - Part 1: Return early if the element being tested for is likely an ancestor and does not have an assigned slot --- layout/style/nsCSSRuleProcessor.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'layout') diff --git a/layout/style/nsCSSRuleProcessor.cpp b/layout/style/nsCSSRuleProcessor.cpp index da25732d37..d5d18e75a9 100644 --- a/layout/style/nsCSSRuleProcessor.cpp +++ b/layout/style/nsCSSRuleProcessor.cpp @@ -1711,7 +1711,13 @@ static bool SelectorMatches(Element* aElement, Element* targetElement = aElement; if (aTreeMatchContext.mForAssignedSlot) { - targetElement = aElement->GetAssignedSlot()->AsElement(); + HTMLSlotElement* slot = aElement->GetAssignedSlot(); + // We're likely testing the slottable's ancestors and it might + // not have an assigned slot, so return early. + if (!slot) { + return false; + } + targetElement = slot->AsElement(); } // namespace/tag match -- cgit v1.2.3 From 0627dc763966836eee5c182560c744cb5a4233bc Mon Sep 17 00:00:00 2001 From: FranklinDM Date: Sun, 21 May 2023 15:24:31 +0800 Subject: Issue #2250 - Part 2: Ignore the ancestor filter assertion if rule matching is restricted or if the current element is under a shadow host This only affects debug builds. --- layout/style/nsCSSRuleProcessor.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'layout') diff --git a/layout/style/nsCSSRuleProcessor.cpp b/layout/style/nsCSSRuleProcessor.cpp index d5d18e75a9..15e5a2456c 100644 --- a/layout/style/nsCSSRuleProcessor.cpp +++ b/layout/style/nsCSSRuleProcessor.cpp @@ -680,7 +680,11 @@ void RuleHash::EnumerateAllRules(Element* aElement, ElementDependentRuleProcesso aData->mTreeMatchContext.mAncestorFilter.HasFilter() ? &aData->mTreeMatchContext.mAncestorFilter : nullptr; #ifdef DEBUG - if (filter) { + bool isRestricted = (aData->mTreeMatchContext.mShadowHosts.Length() > 0 || + aData->mTreeMatchContext.mRestrictToSlottedPseudo || + aData->mTreeMatchContext.mOnlyMatchHostPseudo || + aData->mTreeMatchContext.mForAssignedSlot); + if (filter && !isRestricted) { filter->AssertHasAllAncestors(aElement); } #endif -- cgit v1.2.3