⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 278311 in webkit


Ignore:
Timestamp:
Jun 1, 2021, 9:49:09 AM (5 years ago)
Author:
weinig@apple.com
Message:

Factor out token-type dependent CSS property parsing functions to allow more code sharing
https://bugs.webkit.org/show_bug.cgi?id=226473

Reviewed by Darin Adler.

As a step toward reducing duplicate code and making CSSPropertyParserHelpers a bit
easier to follow, this change extracts the token type specific parts of the primitive
consume functions (e.g. the part of consumeNumberRaw where the token is known to be
a FunctionToken) into their own functions. This allows sharing between functions that
both need that logic (e.g. consumeNumberRaw and consumeNumberRawOrPercentRaw can share)
without extra branches, rechecking the token type, or duplication. It also has the
benefit of creating a strict pattern for primitive consumers going forward.

The new names are rather long to make it very clear what they do, but they are unlikely
to stay for very long. Future changes will try to generalize through templates to allow
programatic combinations of the consumers without always haveing to write the boilerplate.

  • css/parser/CSSPropertyParserHelpers.cpp:

(WebCore::CSSPropertyParserHelpers::shouldAcceptUnitlessValue):
(WebCore::CSSPropertyParserHelpers::consumeIntegerTypeRawWithKnownTokenTypeFunction):
(WebCore::CSSPropertyParserHelpers::consumeIntegerTypeRawWithKnownTokenTypeNumber):
(WebCore::CSSPropertyParserHelpers::consumeIntegerTypeCSSPrimitiveValueWithCalcWithKnownTokenTypeFunction):
(WebCore::CSSPropertyParserHelpers::consumeIntegerTypeCSSPrimitiveValueWithCalcWithKnownTokenTypeNumber):
(WebCore::CSSPropertyParserHelpers::validatedNumberRaw):
(WebCore::CSSPropertyParserHelpers::consumeNumberRawWithKnownTokenTypeFunction):
(WebCore::CSSPropertyParserHelpers::consumeNumberRawWithKnownTokenTypeNumber):
(WebCore::CSSPropertyParserHelpers::consumeNumberRawWithKnownTokenTypeIdent):
(WebCore::CSSPropertyParserHelpers::consumeNumberCSSPrimitiveValueWithCalcWithKnownTokenTypeFunction):
(WebCore::CSSPropertyParserHelpers::consumeNumberCSSPrimitiveValueWithCalcWithKnownTokenTypeNumber):
(WebCore::CSSPropertyParserHelpers::validatedPercentRaw):
(WebCore::CSSPropertyParserHelpers::consumePercentRawWithKnownTokenTypeFunction):
(WebCore::CSSPropertyParserHelpers::consumePercentRawWithKnownTokenTypePercentage):
(WebCore::CSSPropertyParserHelpers::consumePercentRawWithKnownTokenTypeIdent):
(WebCore::CSSPropertyParserHelpers::consumePercentCSSPrimitiveValueWithCalcWithKnownTokenTypeFunction):
(WebCore::CSSPropertyParserHelpers::consumePercentCSSPrimitiveValueWithCalcWithKnownTokenTypePercentage):
(WebCore::CSSPropertyParserHelpers::validatedLengthRaw):
(WebCore::CSSPropertyParserHelpers::consumeLengthRawWithKnownTokenTypeFunction):
(WebCore::CSSPropertyParserHelpers::consumeLengthRawWithKnownTokenTypeDimension):
(WebCore::CSSPropertyParserHelpers::consumeLengthRawWithKnownTokenTypeNumber):
(WebCore::CSSPropertyParserHelpers::consumeLengthCSSPrimitiveValueWithCalcWithKnownTokenTypeFunction):
(WebCore::CSSPropertyParserHelpers::consumeLengthCSSPrimitiveValueWithCalcWithKnownTokenTypeDimension):
(WebCore::CSSPropertyParserHelpers::consumeLengthCSSPrimitiveValueWithCalcWithKnownTokenTypeNumber):
(WebCore::CSSPropertyParserHelpers::consumeAngleRawWithKnownTokenTypeFunction):
(WebCore::CSSPropertyParserHelpers::consumeAngleRawWithKnownTokenTypeDimension):
(WebCore::CSSPropertyParserHelpers::consumeAngleRawWithKnownTokenTypeNumber):
(WebCore::CSSPropertyParserHelpers::consumeAngleCSSPrimitiveValueWithCalcWithKnownTokenTypeFunction):
(WebCore::CSSPropertyParserHelpers::consumeAngleCSSPrimitiveValueWithCalcWithKnownTokenTypeDimension):
(WebCore::CSSPropertyParserHelpers::consumeAngleCSSPrimitiveValueWithCalcWithKnownTokenTypeNumber):
(WebCore::CSSPropertyParserHelpers::consumeTimeCSSPrimitiveValueWithCalcWithKnownTokenTypeFunction):
(WebCore::CSSPropertyParserHelpers::consumeTimeCSSPrimitiveValueWithCalcWithKnownTokenTypeDimension):
(WebCore::CSSPropertyParserHelpers::consumeTimeCSSPrimitiveValueWithCalcWithKnownTokenTypeNumber):
(WebCore::CSSPropertyParserHelpers::consumeResolutionCSSPrimitiveValueWithKnownTokenTypeDimension):
(WebCore::CSSPropertyParserHelpers::consumeIntegerTypeRaw):
(WebCore::CSSPropertyParserHelpers::consumeIntegerType):
(WebCore::CSSPropertyParserHelpers::consumeIntegerRaw):
(WebCore::CSSPropertyParserHelpers::consumeInteger):
(WebCore::CSSPropertyParserHelpers::consumePositiveIntegerRaw):
(WebCore::CSSPropertyParserHelpers::consumePositiveInteger):
(WebCore::CSSPropertyParserHelpers::consumeNumberRaw):
(WebCore::CSSPropertyParserHelpers::consumeNumber):
(WebCore::CSSPropertyParserHelpers::consumeLengthRaw):
(WebCore::CSSPropertyParserHelpers::consumeLength):
(WebCore::CSSPropertyParserHelpers::consumePercentRaw):
(WebCore::CSSPropertyParserHelpers::consumePercent):
(WebCore::CSSPropertyParserHelpers::consumePercentWorkerSafe):
(WebCore::CSSPropertyParserHelpers::canConsumeCalcValue):
(WebCore::CSSPropertyParserHelpers::consumeAngleRaw):
(WebCore::CSSPropertyParserHelpers::consumeAngle):
(WebCore::CSSPropertyParserHelpers::consumeAngleWorkerSafe):
(WebCore::CSSPropertyParserHelpers::consumeTime):
(WebCore::CSSPropertyParserHelpers::consumeResolution):
(WebCore::CSSPropertyParserHelpers::consumeAngleOrPercent):
(WebCore::CSSPropertyParserHelpers::consumeLengthOrPercentRaw):
(WebCore::CSSPropertyParserHelpers::consumeLengthOrPercent):
(WebCore::CSSPropertyParserHelpers::consumeNumberAllowingSymbolTableIdent):
(WebCore::CSSPropertyParserHelpers::consumePercentAllowingSymbolTableIdent):
(WebCore::CSSPropertyParserHelpers::consumeAngleRawOrNumberRaw):
(WebCore::CSSPropertyParserHelpers::consumeAngleRawOrNumberRawAllowingSymbolTableIdent):
(WebCore::CSSPropertyParserHelpers::consumeNumberRawOrPercentRaw):
(WebCore::CSSPropertyParserHelpers::consumeNumberRawOrPercentDividedBy100Raw):
(WebCore::CSSPropertyParserHelpers::consumeNumberRawOrPercentRawAllowingSymbolTableIdent):
(WebCore::CSSPropertyParserHelpers::consumeNumberRawOrPercentDividedBy100RawAllowingSymbolTableIdent):
(WebCore::CSSPropertyParserHelpers::divisibleBy100):
(WebCore::CSSPropertyParserHelpers::consumeFontWeightNumberRaw):
(WebCore::CSSPropertyParserHelpers::consumeFontWeightNumber):
(WebCore::CSSPropertyParserHelpers::consumeFontWeightNumberWorkerSafe):
(WebCore::CSSPropertyParserHelpers::consumeIdentRaw):
(WebCore::CSSPropertyParserHelpers::consumeIdent):
(WebCore::CSSPropertyParserHelpers::consumeIdentWorkerSafe):
(WebCore::CSSPropertyParserHelpers::consumeUrlAsStringView):
(WebCore::CSSPropertyParserHelpers::consumeOptionalAlpha):
(WebCore::CSSPropertyParserHelpers::consumeOptionalAlphaAllowingSymbolTableIdent):
(WebCore::CSSPropertyParserHelpers::normalizeRGBComponentNumber):
(WebCore::CSSPropertyParserHelpers::normalizeRGBComponentPercentage):
(WebCore::CSSPropertyParserHelpers::consumeRelativeRGBComponent):
(WebCore::CSSPropertyParserHelpers::clampRGBComponent):
(WebCore::CSSPropertyParserHelpers::consumeRGBOrHSLOptionalAlpha):
(WebCore::CSSPropertyParserHelpers::parseRelativeRGBParameters):
(WebCore::CSSPropertyParserHelpers::parseRelativeHSLParameters):
(WebCore::CSSPropertyParserHelpers::parseHSLParameters):
(WebCore::CSSPropertyParserHelpers::parseRelativeHWBParameters):
(WebCore::CSSPropertyParserHelpers::parseHWBParameters):
(WebCore::CSSPropertyParserHelpers::parseRelativeLabParameters):
(WebCore::CSSPropertyParserHelpers::parseRelativeLCHParameters):
(WebCore::CSSPropertyParserHelpers::parseLCHParameters):
(WebCore::CSSPropertyParserHelpers::parseColorFunctionForRGBTypes):
(WebCore::CSSPropertyParserHelpers::consumeDeprecatedGradientColorStop):
(WebCore::CSSPropertyParserHelpers::consumeCrossFade):
(WebCore::CSSPropertyParserHelpers::consumeNumberOrPercentDividedBy100Raw): Deleted.
(WebCore::CSSPropertyParserHelpers::consumeOptionalAlphaOrIdent): Deleted.
(WebCore::CSSPropertyParserHelpers::consumeHue): Deleted.
(WebCore::CSSPropertyParserHelpers::consumeHueOrIdent): Deleted.
(WebCore::CSSPropertyParserHelpers::consumeNumberOrIdent): Deleted.
(WebCore::CSSPropertyParserHelpers::consumePercentOrIdent): Deleted.
(WebCore::CSSPropertyParserHelpers::consumeNumberOrPercentOrIdentNormalizedForRelativeRGB): Deleted.

Location:
trunk/Source/WebCore
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r278309 r278311  
     12021-06-01  Sam Weinig  <weinig@apple.com>
     2
     3        Factor out token-type dependent CSS property parsing functions to allow more code sharing
     4        https://bugs.webkit.org/show_bug.cgi?id=226473
     5
     6        Reviewed by Darin Adler.
     7
     8        As a step toward reducing duplicate code and making CSSPropertyParserHelpers a bit
     9        easier to follow, this change extracts the token type specific parts of the primitive
     10        consume functions (e.g. the part of consumeNumberRaw where the token is known to be
     11        a FunctionToken) into their own functions. This allows sharing between functions that
     12        both need that logic (e.g. consumeNumberRaw and consumeNumberRawOrPercentRaw can share)
     13        without extra branches, rechecking the token type, or duplication. It also has the
     14        benefit of creating a strict pattern for primitive consumers going forward.
     15
     16        The new names are rather long to make it very clear what they do, but they are unlikely
     17        to stay for very long. Future changes will try to generalize through templates to allow
     18        programatic combinations of the consumers without always haveing to write the boilerplate.
     19
     20        * css/parser/CSSPropertyParserHelpers.cpp:
     21        (WebCore::CSSPropertyParserHelpers::shouldAcceptUnitlessValue):
     22        (WebCore::CSSPropertyParserHelpers::consumeIntegerTypeRawWithKnownTokenTypeFunction):
     23        (WebCore::CSSPropertyParserHelpers::consumeIntegerTypeRawWithKnownTokenTypeNumber):
     24        (WebCore::CSSPropertyParserHelpers::consumeIntegerTypeCSSPrimitiveValueWithCalcWithKnownTokenTypeFunction):
     25        (WebCore::CSSPropertyParserHelpers::consumeIntegerTypeCSSPrimitiveValueWithCalcWithKnownTokenTypeNumber):
     26        (WebCore::CSSPropertyParserHelpers::validatedNumberRaw):
     27        (WebCore::CSSPropertyParserHelpers::consumeNumberRawWithKnownTokenTypeFunction):
     28        (WebCore::CSSPropertyParserHelpers::consumeNumberRawWithKnownTokenTypeNumber):
     29        (WebCore::CSSPropertyParserHelpers::consumeNumberRawWithKnownTokenTypeIdent):
     30        (WebCore::CSSPropertyParserHelpers::consumeNumberCSSPrimitiveValueWithCalcWithKnownTokenTypeFunction):
     31        (WebCore::CSSPropertyParserHelpers::consumeNumberCSSPrimitiveValueWithCalcWithKnownTokenTypeNumber):
     32        (WebCore::CSSPropertyParserHelpers::validatedPercentRaw):
     33        (WebCore::CSSPropertyParserHelpers::consumePercentRawWithKnownTokenTypeFunction):
     34        (WebCore::CSSPropertyParserHelpers::consumePercentRawWithKnownTokenTypePercentage):
     35        (WebCore::CSSPropertyParserHelpers::consumePercentRawWithKnownTokenTypeIdent):
     36        (WebCore::CSSPropertyParserHelpers::consumePercentCSSPrimitiveValueWithCalcWithKnownTokenTypeFunction):
     37        (WebCore::CSSPropertyParserHelpers::consumePercentCSSPrimitiveValueWithCalcWithKnownTokenTypePercentage):
     38        (WebCore::CSSPropertyParserHelpers::validatedLengthRaw):
     39        (WebCore::CSSPropertyParserHelpers::consumeLengthRawWithKnownTokenTypeFunction):
     40        (WebCore::CSSPropertyParserHelpers::consumeLengthRawWithKnownTokenTypeDimension):
     41        (WebCore::CSSPropertyParserHelpers::consumeLengthRawWithKnownTokenTypeNumber):
     42        (WebCore::CSSPropertyParserHelpers::consumeLengthCSSPrimitiveValueWithCalcWithKnownTokenTypeFunction):
     43        (WebCore::CSSPropertyParserHelpers::consumeLengthCSSPrimitiveValueWithCalcWithKnownTokenTypeDimension):
     44        (WebCore::CSSPropertyParserHelpers::consumeLengthCSSPrimitiveValueWithCalcWithKnownTokenTypeNumber):
     45        (WebCore::CSSPropertyParserHelpers::consumeAngleRawWithKnownTokenTypeFunction):
     46        (WebCore::CSSPropertyParserHelpers::consumeAngleRawWithKnownTokenTypeDimension):
     47        (WebCore::CSSPropertyParserHelpers::consumeAngleRawWithKnownTokenTypeNumber):
     48        (WebCore::CSSPropertyParserHelpers::consumeAngleCSSPrimitiveValueWithCalcWithKnownTokenTypeFunction):
     49        (WebCore::CSSPropertyParserHelpers::consumeAngleCSSPrimitiveValueWithCalcWithKnownTokenTypeDimension):
     50        (WebCore::CSSPropertyParserHelpers::consumeAngleCSSPrimitiveValueWithCalcWithKnownTokenTypeNumber):
     51        (WebCore::CSSPropertyParserHelpers::consumeTimeCSSPrimitiveValueWithCalcWithKnownTokenTypeFunction):
     52        (WebCore::CSSPropertyParserHelpers::consumeTimeCSSPrimitiveValueWithCalcWithKnownTokenTypeDimension):
     53        (WebCore::CSSPropertyParserHelpers::consumeTimeCSSPrimitiveValueWithCalcWithKnownTokenTypeNumber):
     54        (WebCore::CSSPropertyParserHelpers::consumeResolutionCSSPrimitiveValueWithKnownTokenTypeDimension):
     55        (WebCore::CSSPropertyParserHelpers::consumeIntegerTypeRaw):
     56        (WebCore::CSSPropertyParserHelpers::consumeIntegerType):
     57        (WebCore::CSSPropertyParserHelpers::consumeIntegerRaw):
     58        (WebCore::CSSPropertyParserHelpers::consumeInteger):
     59        (WebCore::CSSPropertyParserHelpers::consumePositiveIntegerRaw):
     60        (WebCore::CSSPropertyParserHelpers::consumePositiveInteger):
     61        (WebCore::CSSPropertyParserHelpers::consumeNumberRaw):
     62        (WebCore::CSSPropertyParserHelpers::consumeNumber):
     63        (WebCore::CSSPropertyParserHelpers::consumeLengthRaw):
     64        (WebCore::CSSPropertyParserHelpers::consumeLength):
     65        (WebCore::CSSPropertyParserHelpers::consumePercentRaw):
     66        (WebCore::CSSPropertyParserHelpers::consumePercent):
     67        (WebCore::CSSPropertyParserHelpers::consumePercentWorkerSafe):
     68        (WebCore::CSSPropertyParserHelpers::canConsumeCalcValue):
     69        (WebCore::CSSPropertyParserHelpers::consumeAngleRaw):
     70        (WebCore::CSSPropertyParserHelpers::consumeAngle):
     71        (WebCore::CSSPropertyParserHelpers::consumeAngleWorkerSafe):
     72        (WebCore::CSSPropertyParserHelpers::consumeTime):
     73        (WebCore::CSSPropertyParserHelpers::consumeResolution):
     74        (WebCore::CSSPropertyParserHelpers::consumeAngleOrPercent):
     75        (WebCore::CSSPropertyParserHelpers::consumeLengthOrPercentRaw):
     76        (WebCore::CSSPropertyParserHelpers::consumeLengthOrPercent):
     77        (WebCore::CSSPropertyParserHelpers::consumeNumberAllowingSymbolTableIdent):
     78        (WebCore::CSSPropertyParserHelpers::consumePercentAllowingSymbolTableIdent):
     79        (WebCore::CSSPropertyParserHelpers::consumeAngleRawOrNumberRaw):
     80        (WebCore::CSSPropertyParserHelpers::consumeAngleRawOrNumberRawAllowingSymbolTableIdent):
     81        (WebCore::CSSPropertyParserHelpers::consumeNumberRawOrPercentRaw):
     82        (WebCore::CSSPropertyParserHelpers::consumeNumberRawOrPercentDividedBy100Raw):
     83        (WebCore::CSSPropertyParserHelpers::consumeNumberRawOrPercentRawAllowingSymbolTableIdent):
     84        (WebCore::CSSPropertyParserHelpers::consumeNumberRawOrPercentDividedBy100RawAllowingSymbolTableIdent):
     85        (WebCore::CSSPropertyParserHelpers::divisibleBy100):
     86        (WebCore::CSSPropertyParserHelpers::consumeFontWeightNumberRaw):
     87        (WebCore::CSSPropertyParserHelpers::consumeFontWeightNumber):
     88        (WebCore::CSSPropertyParserHelpers::consumeFontWeightNumberWorkerSafe):
     89        (WebCore::CSSPropertyParserHelpers::consumeIdentRaw):
     90        (WebCore::CSSPropertyParserHelpers::consumeIdent):
     91        (WebCore::CSSPropertyParserHelpers::consumeIdentWorkerSafe):
     92        (WebCore::CSSPropertyParserHelpers::consumeUrlAsStringView):
     93        (WebCore::CSSPropertyParserHelpers::consumeOptionalAlpha):
     94        (WebCore::CSSPropertyParserHelpers::consumeOptionalAlphaAllowingSymbolTableIdent):
     95        (WebCore::CSSPropertyParserHelpers::normalizeRGBComponentNumber):
     96        (WebCore::CSSPropertyParserHelpers::normalizeRGBComponentPercentage):
     97        (WebCore::CSSPropertyParserHelpers::consumeRelativeRGBComponent):
     98        (WebCore::CSSPropertyParserHelpers::clampRGBComponent):
     99        (WebCore::CSSPropertyParserHelpers::consumeRGBOrHSLOptionalAlpha):
     100        (WebCore::CSSPropertyParserHelpers::parseRelativeRGBParameters):
     101        (WebCore::CSSPropertyParserHelpers::parseRelativeHSLParameters):
     102        (WebCore::CSSPropertyParserHelpers::parseHSLParameters):
     103        (WebCore::CSSPropertyParserHelpers::parseRelativeHWBParameters):
     104        (WebCore::CSSPropertyParserHelpers::parseHWBParameters):
     105        (WebCore::CSSPropertyParserHelpers::parseRelativeLabParameters):
     106        (WebCore::CSSPropertyParserHelpers::parseRelativeLCHParameters):
     107        (WebCore::CSSPropertyParserHelpers::parseLCHParameters):
     108        (WebCore::CSSPropertyParserHelpers::parseColorFunctionForRGBTypes):
     109        (WebCore::CSSPropertyParserHelpers::consumeDeprecatedGradientColorStop):
     110        (WebCore::CSSPropertyParserHelpers::consumeCrossFade):
     111        (WebCore::CSSPropertyParserHelpers::consumeNumberOrPercentDividedBy100Raw): Deleted.
     112        (WebCore::CSSPropertyParserHelpers::consumeOptionalAlphaOrIdent): Deleted.
     113        (WebCore::CSSPropertyParserHelpers::consumeHue): Deleted.
     114        (WebCore::CSSPropertyParserHelpers::consumeHueOrIdent): Deleted.
     115        (WebCore::CSSPropertyParserHelpers::consumeNumberOrIdent): Deleted.
     116        (WebCore::CSSPropertyParserHelpers::consumePercentOrIdent): Deleted.
     117        (WebCore::CSSPropertyParserHelpers::consumeNumberOrPercentOrIdentNormalizedForRelativeRGB): Deleted.
     118
    11192021-06-01  Chris Dumez  <cdumez@apple.com>
    2120
  • trunk/Source/WebCore/css/parser/CSSParserMode.h

    r255151 r278311  
    5858}
    5959
    60 inline bool isUnitLessValueParsingEnabledForMode(CSSParserMode mode)
     60inline bool isUnitlessValueParsingEnabledForMode(CSSParserMode mode)
    6161{
    6262    return mode == SVGAttributeMode;
  • trunk/Source/WebCore/css/parser/CSSPropertyParserHelpers.cpp

    r278304 r278311  
    8989}
    9090
    91 static std::optional<double> consumeNumberOrPercentDividedBy100Raw(CSSParserTokenRange& range, ValueRange valueRange = ValueRange::All)
    92 {
    93     if (auto percent = consumePercentRaw(range, valueRange))
    94         return *percent / 100.0;
    95     if (auto number = consumeNumberRaw(range, valueRange))
    96         return *number;
    97     return std::nullopt;
     91inline bool shouldAcceptUnitlessValue(double value, CSSParserMode parserMode, UnitlessQuirk unitless, UnitlessZeroQuirk unitlessZero)
     92{
     93    // FIXME: Presentational HTML attributes shouldn't use the CSS parser for lengths.
     94
     95    if (value == 0 && unitlessZero == UnitlessZeroQuirk::Allow)
     96        return true;
     97
     98    if (isUnitlessValueParsingEnabledForMode(parserMode))
     99        return true;
     100   
     101    return parserMode == HTMLQuirksMode && unitless == UnitlessQuirk::Allow;
     102}
     103
     104static bool canConsumeCalcValue(CalculationCategory category, CSSParserMode parserMode)
     105{
     106    if (category == CalculationCategory::Length || category == CalculationCategory::Percent || category == CalculationCategory::PercentLength)
     107        return true;
     108
     109    if (parserMode != SVGAttributeMode)
     110        return false;
     111
     112    if (category == CalculationCategory::Number || category == CalculationCategory::PercentNumber)
     113        return true;
     114
     115    return false;
    98116}
    99117
     
    101119class CalcParser {
    102120public:
    103     explicit CalcParser(CSSParserTokenRange& range, CalculationCategory destinationCategory, ValueRange valueRange = ValueRange::All, const CSSCalcSymbolTable& symbolTable = { }, CSSValuePool& cssValuePool = CSSValuePool::singleton())
     121    explicit CalcParser(CSSParserTokenRange& range, CalculationCategory destinationCategory, ValueRange valueRange = ValueRange::All, const CSSCalcSymbolTable& symbolTable = { }, CSSValuePool& pool = CSSValuePool::singleton())
    104122        : m_sourceRange(range)
    105123        , m_range(range)
    106         , m_valuePool(cssValuePool)
     124        , m_pool(pool)
    107125    {
    108126        const CSSParserToken& token = range.peek();
     
    119137            return nullptr;
    120138        m_sourceRange = m_range;
    121         return m_valuePool.createValue(WTFMove(m_calcValue));
     139        return m_pool.createValue(WTFMove(m_calcValue));
    122140    }
    123141
     
    127145            return nullptr;
    128146        m_sourceRange = m_range;
    129         return m_valuePool.createValue(WTFMove(m_calcValue));
     147        return m_pool.createValue(WTFMove(m_calcValue));
    130148    }
    131149
     
    135153            return nullptr;
    136154        m_sourceRange = m_range;
    137         return m_valuePool.createValue(std::round(std::max(m_calcValue->doubleValue(), minimumValue)), CSSUnitType::CSS_NUMBER);
     155        return m_pool.createValue(std::round(std::max(m_calcValue->doubleValue(), minimumValue)), CSSUnitType::CSS_NUMBER);
    138156    }
    139157
     
    151169            return nullptr;
    152170        m_sourceRange = m_range;
    153         return m_valuePool.createValue(m_calcValue->doubleValue(), CSSUnitType::CSS_NUMBER);
     171        return m_pool.createValue(m_calcValue->doubleValue(), CSSUnitType::CSS_NUMBER);
    154172    }
    155173
     
    212230    CSSParserTokenRange m_range;
    213231    RefPtr<CSSCalcValue> m_calcValue;
    214     CSSValuePool& m_valuePool;
     232    CSSValuePool& m_pool;
    215233};
    216234
    217 template<typename IntType> std::optional<IntType> consumeIntegerTypeRaw(CSSParserTokenRange& range, double minimumValue)
    218 {
    219     const CSSParserToken& token = range.peek();
    220     if (token.type() == NumberToken) {
    221         if (token.numericValueType() == NumberValueType || token.numericValue() < minimumValue)
    222             return std::nullopt;
    223         return clampTo<IntType>(range.consumeIncludingWhitespace().numericValue());
    224     }
    225 
    226     if (token.type() != FunctionToken)
     235// MARK: - Primitive value consumers for callers that know the token type.
     236
     237// MARK: Integer (Raw)
     238
     239template<typename IntType> static std::optional<IntType> consumeIntegerTypeRawWithKnownTokenTypeFunction(CSSParserTokenRange& range, double minimumValue)
     240{
     241    ASSERT(range.peek().type() == FunctionToken);
     242
     243    CalcParser parser(range, CalculationCategory::Number);
     244    if (auto calculation = parser.value(); calculation && calculation->category() == CalculationCategory::Number)
     245        return parser.consumeIntegerTypeRaw<IntType>(minimumValue);
     246
     247    return std::nullopt;
     248}
     249
     250template<typename IntType> static std::optional<IntType> consumeIntegerTypeRawWithKnownTokenTypeNumber(CSSParserTokenRange& range, double minimumValue)
     251{
     252    ASSERT(range.peek().type() == NumberToken);
     253   
     254    if (range.peek().numericValueType() == NumberValueType || range.peek().numericValue() < minimumValue)
    227255        return std::nullopt;
    228 
    229     CalcParser calcParser(range, CalculationCategory::Number);
    230     if (auto calculation = calcParser.value(); calculation && calculation->category() == CalculationCategory::Number)
    231         return calcParser.consumeIntegerTypeRaw<IntType>(minimumValue);
    232 
     256    return clampTo<IntType>(range.consumeIncludingWhitespace().numericValue());
     257}
     258
     259// MARK: Integer (CSSPrimitiveValue - not maintaing calc)
     260
     261template<typename IntType> static RefPtr<CSSPrimitiveValue> consumeIntegerTypeCSSPrimitiveValueWithCalcWithKnownTokenTypeFunction(CSSParserTokenRange& range, double minimumValue, CSSValuePool& pool)
     262{
     263    ASSERT(range.peek().type() == FunctionToken);
     264
     265    if (auto integer = consumeIntegerTypeRawWithKnownTokenTypeFunction<IntType>(range, minimumValue))
     266        return pool.createValue(*integer, CSSUnitType::CSS_NUMBER);
     267    return nullptr;
     268}
     269
     270template<typename IntType> static RefPtr<CSSPrimitiveValue> consumeIntegerTypeCSSPrimitiveValueWithCalcWithKnownTokenTypeNumber(CSSParserTokenRange& range, double minimumValue, CSSValuePool& pool)
     271{
     272    ASSERT(range.peek().type() == NumberToken);
     273
     274    if (auto integer = consumeIntegerTypeRawWithKnownTokenTypeNumber<IntType>(range, minimumValue))
     275        return pool.createValue(*integer, CSSUnitType::CSS_NUMBER);
     276    return nullptr;
     277}
     278
     279// MARK: Number (Raw)
     280
     281static std::optional<double> validatedNumberRaw(double value, ValueRange valueRange)
     282{
     283    if (valueRange == ValueRange::NonNegative && value < 0)
     284        return std::nullopt;
     285    return value;
     286}
     287
     288static std::optional<double> consumeNumberRawWithKnownTokenTypeFunction(CSSParserTokenRange& range, const CSSCalcSymbolTable& symbolTable, ValueRange valueRange)
     289{
     290    ASSERT(range.peek().type() == FunctionToken);
     291
     292    CalcParser parser(range, CalculationCategory::Number, valueRange, symbolTable);
     293    return parser.consumeNumberRaw();
     294}
     295
     296static std::optional<double> consumeNumberRawWithKnownTokenTypeNumber(CSSParserTokenRange& range, const CSSCalcSymbolTable&, ValueRange valueRange)
     297{
     298    ASSERT(range.peek().type() == NumberToken);
     299   
     300    if (auto validatedValue = validatedNumberRaw(range.peek().numericValue(), valueRange)) {
     301        range.consumeIncludingWhitespace();
     302        return validatedValue;
     303    }
    233304    return std::nullopt;
    234305}
    235306
    236 std::optional<int> consumeIntegerRaw(CSSParserTokenRange& range, double minimumValue)
    237 {
    238     return consumeIntegerTypeRaw<int>(range, minimumValue);
    239 }
    240 
    241 RefPtr<CSSPrimitiveValue> consumeInteger(CSSParserTokenRange& range, double minimumValue)
    242 {
    243     if (auto integer = consumeIntegerRaw(range, minimumValue))
    244         return CSSValuePool::singleton().createValue(*integer, CSSUnitType::CSS_NUMBER);
    245     return nullptr;
    246 }
    247 
    248 std::optional<unsigned> consumePositiveIntegerRaw(CSSParserTokenRange& range)
    249 {
    250     return consumeIntegerTypeRaw<unsigned>(range, 1);
    251 }
    252 
    253 RefPtr<CSSPrimitiveValue> consumePositiveInteger(CSSParserTokenRange& range)
    254 {
    255     if (auto integer = consumePositiveIntegerRaw(range))
    256         return CSSValuePool::singleton().createValue(*integer, CSSUnitType::CSS_NUMBER);
    257     return nullptr;
    258 }
    259 
    260 std::optional<double> consumeNumberRaw(CSSParserTokenRange& range, ValueRange valueRange)
    261 {
    262     const CSSParserToken& token = range.peek();
    263     if (token.type() == NumberToken) {
    264         if (valueRange == ValueRange::NonNegative && token.numericValue() < 0)
    265             return std::nullopt;
    266         return range.consumeIncludingWhitespace().numericValue();
    267     }
    268 
    269     if (token.type() != FunctionToken)
    270         return std::nullopt;
    271 
    272     CalcParser calcParser(range, CalculationCategory::Number, valueRange);
    273     return calcParser.consumeNumberRaw();
    274 }
    275 
    276 // FIXME: Work out if this can just call consumeNumberRaw
    277 RefPtr<CSSPrimitiveValue> consumeNumber(CSSParserTokenRange& range, ValueRange valueRange)
    278 {
    279     const CSSParserToken& token = range.peek();
    280     if (token.type() == FunctionToken) {
    281         CalcParser calcParser(range, CalculationCategory::Number, valueRange);
    282         return calcParser.consumeValueIfCategory(CalculationCategory::Number);
    283     }
    284 
    285     if (auto number = consumeNumberRaw(range, valueRange))
    286         return CSSValuePool::singleton().createValue(*number, token.unitType());
    287 
    288     return nullptr;
    289 }
    290 
    291 #if !ENABLE(VARIATION_FONTS)
    292 static inline bool divisibleBy100(double value)
    293 {
    294     return static_cast<int>(value / 100) * 100 == value;
    295 }
    296 #endif
    297 
    298 std::optional<double> consumeFontWeightNumberRaw(CSSParserTokenRange& range)
    299 {
    300     // Values less than or equal to 0 or greater than or equal to 1000 are parse errors.
    301     auto& token = range.peek();
    302     if (token.type() == NumberToken && token.numericValue() >= 1 && token.numericValue() <= 1000
    303 #if !ENABLE(VARIATION_FONTS)
    304         && token.numericValueType() == IntegerValueType && divisibleBy100(token.numericValue())
    305 #endif
    306     )
    307         return consumeNumberRaw(range);
    308 
    309     if (token.type() != FunctionToken)
    310         return std::nullopt;
    311 
    312     // "[For calc()], the used value resulting from an expression must be clamped to the range allowed in the target context."
    313     CalcParser calcParser(range, CalculationCategory::Number, ValueRange::All);
    314     if (auto result = calcParser.consumeNumberRaw(); result
    315 #if !ENABLE(VARIATION_FONTS)
    316         && *result > 0 && *result < 1000 && divisibleBy100(*result)
    317 #endif
    318     )
    319         return std::min(std::max(*result, std::nextafter(0., 1.)), std::nextafter(1000., 0.));
    320 
    321     return std::nullopt;
    322 }
    323 
    324 RefPtr<CSSPrimitiveValue> consumeFontWeightNumber(CSSParserTokenRange& range)
    325 {
    326     return consumeFontWeightNumberWorkerSafe(range, CSSValuePool::singleton());
    327 }
    328 
    329 RefPtr<CSSPrimitiveValue> consumeFontWeightNumberWorkerSafe(CSSParserTokenRange& range, CSSValuePool& cssValuePool)
    330 {
    331     if (auto result = consumeFontWeightNumberRaw(range))
    332         return cssValuePool.createValue(*result, CSSUnitType::CSS_NUMBER);
    333     return nullptr;
    334 }
    335 
    336 inline bool shouldAcceptUnitlessValue(double value, CSSParserMode cssParserMode, UnitlessQuirk unitless, UnitlessZeroQuirk unitlessZero)
    337 {
    338     // FIXME: Presentational HTML attributes shouldn't use the CSS parser for lengths
    339 
    340     if (value == 0 && unitlessZero == UnitlessZeroQuirk::Allow)
    341         return true;
    342 
    343     if (isUnitLessValueParsingEnabledForMode(cssParserMode))
    344         return true;
    345    
    346     return cssParserMode == HTMLQuirksMode && unitless == UnitlessQuirk::Allow;
    347 }
    348 
    349 std::optional<LengthRaw> consumeLengthRaw(CSSParserTokenRange& range, CSSParserMode cssParserMode, ValueRange valueRange, UnitlessQuirk unitless)
    350 {
    351     const CSSParserToken& token = range.peek();
    352     if (token.type() == DimensionToken) {
    353         switch (token.unitType()) {
    354         case CSSUnitType::CSS_QUIRKY_EMS:
    355             if (cssParserMode != UASheetMode)
    356                 return std::nullopt;
    357             FALLTHROUGH;
    358         case CSSUnitType::CSS_EMS:
    359         case CSSUnitType::CSS_REMS:
    360         case CSSUnitType::CSS_LHS:
    361         case CSSUnitType::CSS_RLHS:
    362         case CSSUnitType::CSS_CHS:
    363         case CSSUnitType::CSS_EXS:
    364         case CSSUnitType::CSS_PX:
    365         case CSSUnitType::CSS_CM:
    366         case CSSUnitType::CSS_MM:
    367         case CSSUnitType::CSS_IN:
    368         case CSSUnitType::CSS_PT:
    369         case CSSUnitType::CSS_PC:
    370         case CSSUnitType::CSS_VW:
    371         case CSSUnitType::CSS_VH:
    372         case CSSUnitType::CSS_VMIN:
    373         case CSSUnitType::CSS_VMAX:
    374         case CSSUnitType::CSS_Q:
     307static std::optional<double> consumeNumberRawWithKnownTokenTypeIdent(CSSParserTokenRange& range, const CSSCalcSymbolTable& symbolTable, ValueRange valueRange)
     308{
     309    ASSERT(range.peek().type() == IdentToken);
     310
     311    if (auto variable = symbolTable.get(range.peek().id())) {
     312        switch (variable->type) {
     313        case CSSUnitType::CSS_NUMBER:
     314            if (auto validatedValue = validatedNumberRaw(variable->value, valueRange)) {
     315                range.consumeIncludingWhitespace();
     316                return validatedValue;
     317            }
    375318            break;
    376         default:
    377             return std::nullopt;
    378         }
    379         if ((valueRange == ValueRange::NonNegative && token.numericValue() < 0) || std::isinf(token.numericValue()))
    380             return std::nullopt;
    381         return { { token.unitType(), range.consumeIncludingWhitespace().numericValue() } };
    382     }
    383     if (token.type() == NumberToken) {
    384         if (!shouldAcceptUnitlessValue(token.numericValue(), cssParserMode, unitless, UnitlessZeroQuirk::Allow)
    385             || (valueRange == ValueRange::NonNegative && token.numericValue() < 0))
    386             return std::nullopt;
    387         if (std::isinf(token.numericValue()))
    388             return std::nullopt;
    389         return { { CSSUnitType::CSS_PX, range.consumeIncludingWhitespace().numericValue() } };
    390     }
    391 
    392     if (token.type() != FunctionToken)
    393         return std::nullopt;
    394 
    395     CalcParser calcParser(range, CalculationCategory::Length, valueRange);
    396     return calcParser.consumeLengthRaw();
    397 }
    398 
    399 RefPtr<CSSPrimitiveValue> consumeLength(CSSParserTokenRange& range, CSSParserMode cssParserMode, ValueRange valueRange, UnitlessQuirk unitless)
    400 {
    401     const CSSParserToken& token = range.peek();
    402     if (token.type() == FunctionToken) {
    403         CalcParser calcParser(range, CalculationCategory::Length, valueRange);
    404         return calcParser.consumeValueIfCategory(CalculationCategory::Length);
    405     }
    406 
    407     if (auto result = consumeLengthRaw(range, cssParserMode, valueRange, unitless))
    408         return CSSValuePool::singleton().createValue(result->value, result->type);
    409 
    410     return nullptr;
    411 }
    412 
    413 std::optional<double> consumePercentRaw(CSSParserTokenRange& range, ValueRange valueRange)
    414 {
    415     const CSSParserToken& token = range.peek();
    416     if (token.type() == PercentageToken) {
    417         if (std::isinf(token.numericValue()) || (valueRange == ValueRange::NonNegative && token.numericValue() < 0))
    418             return std::nullopt;
    419         return range.consumeIncludingWhitespace().numericValue();
    420     }
    421 
    422     if (token.type() != FunctionToken)
    423         return std::nullopt;
    424 
    425     CalcParser calcParser(range, CalculationCategory::Percent, valueRange);
    426     return calcParser.consumePercentRaw();
    427 }
    428 
    429 RefPtr<CSSPrimitiveValue> consumePercent(CSSParserTokenRange& range, ValueRange valueRange)
    430 {
    431     return consumePercentWorkerSafe(range, valueRange, CSSValuePool::singleton());
    432 }
    433 
    434 RefPtr<CSSPrimitiveValue> consumePercentWorkerSafe(CSSParserTokenRange& range, ValueRange valueRange, CSSValuePool& cssValuePool)
    435 {
    436     const CSSParserToken& token = range.peek();
    437     if (token.type() == FunctionToken) {
    438         CalcParser calcParser(range, CalculationCategory::Percent, valueRange, { }, cssValuePool);
    439         return calcParser.consumeValueIfCategory(CalculationCategory::Percent);
    440     }
    441 
    442     if (auto percent = consumePercentRaw(range, valueRange))
    443         return cssValuePool.createValue(*percent, CSSUnitType::CSS_PERCENTAGE);
    444 
    445     return nullptr;
    446 }
    447 
    448 static bool canConsumeCalcValue(CalculationCategory category, CSSParserMode cssParserMode)
    449 {
    450     if (category == CalculationCategory::Length || category == CalculationCategory::Percent || category == CalculationCategory::PercentLength)
    451         return true;
    452 
    453     if (cssParserMode != SVGAttributeMode)
    454         return false;
    455 
    456     if (category == CalculationCategory::Number || category == CalculationCategory::PercentNumber)
    457         return true;
    458 
    459     return false;
    460 }
    461 
    462 std::optional<LengthOrPercentRaw> consumeLengthOrPercentRaw(CSSParserTokenRange& range, CSSParserMode cssParserMode, ValueRange valueRange, UnitlessQuirk unitless)
    463 {
    464     const CSSParserToken& token = range.peek();
    465     if (token.type() == DimensionToken || token.type() == NumberToken) {
    466         if (auto result = consumeLengthRaw(range, cssParserMode, valueRange, unitless))
    467             return { *result };
    468         return std::nullopt;
    469     }
    470     if (token.type() == PercentageToken) {
    471         if (auto result = consumePercentRaw(range, valueRange))
    472             return { *result };
    473         return std::nullopt;
    474     }
    475 
    476     if (token.type() != FunctionToken)
    477         return std::nullopt;
    478 
    479     CalcParser calcParser(range, CalculationCategory::Length, valueRange);
    480     if (auto calculation = calcParser.value(); calculation && canConsumeCalcValue(calculation->category(), cssParserMode))
    481         return calcParser.consumeLengthOrPercentRaw();
    482     return std::nullopt;
    483 }
    484 
    485 RefPtr<CSSPrimitiveValue> consumeLengthOrPercent(CSSParserTokenRange& range, CSSParserMode cssParserMode, ValueRange valueRange, UnitlessQuirk unitless)
    486 {
    487     const CSSParserToken& token = range.peek();
    488     if (token.type() == FunctionToken) {
    489         CalcParser calcParser(range, CalculationCategory::Length, valueRange);
    490         if (auto calculation = calcParser.value(); calculation && canConsumeCalcValue(calculation->category(), cssParserMode))
    491             return calcParser.consumeValue();
    492         return nullptr;
    493     }
    494 
    495     if (auto result = consumeLengthOrPercentRaw(range, cssParserMode, valueRange, unitless)) {
    496         return switchOn(*result, [] (LengthRaw length) {
    497             return CSSValuePool::singleton().createValue(length.value, length.type);
    498         }, [] (double percentage) {
    499             return CSSValuePool::singleton().createValue(percentage, CSSUnitType::CSS_PERCENTAGE);
    500         });
    501     }
    502     return nullptr;
    503 }
    504 
    505 std::optional<AngleRaw> consumeAngleRaw(CSSParserTokenRange& range, CSSParserMode cssParserMode, UnitlessQuirk unitless, UnitlessZeroQuirk unitlessZero)
    506 {
    507     const CSSParserToken& token = range.peek();
    508     if (token.type() == DimensionToken) {
    509         auto unitType = token.unitType();
    510         switch (unitType) {
    511         case CSSUnitType::CSS_DEG:
    512         case CSSUnitType::CSS_RAD:
    513         case CSSUnitType::CSS_GRAD:
    514         case CSSUnitType::CSS_TURN:
    515             return { { unitType, range.consumeIncludingWhitespace().numericValue() } };
    516         default:
    517             return std::nullopt;
    518         }
    519     }
    520 
    521     if (token.type() == NumberToken && shouldAcceptUnitlessValue(token.numericValue(), cssParserMode, unitless, unitlessZero))
    522         return { { CSSUnitType::CSS_DEG, range.consumeIncludingWhitespace().numericValue() } };
    523 
    524     if (token.type() != FunctionToken)
    525         return std::nullopt;
    526 
    527     CalcParser calcParser(range, CalculationCategory::Angle, ValueRange::All);
    528     return calcParser.consumeAngleRaw();
    529 }
    530 
    531 RefPtr<CSSPrimitiveValue> consumeAngle(CSSParserTokenRange& range, CSSParserMode cssParserMode, UnitlessQuirk unitless, UnitlessZeroQuirk unitlessZero)
    532 {
    533     return consumeAngleWorkerSafe(range, cssParserMode, CSSValuePool::singleton(), unitless, unitlessZero);
    534 }
    535 
    536 RefPtr<CSSPrimitiveValue> consumeAngleWorkerSafe(CSSParserTokenRange& range, CSSParserMode cssParserMode, CSSValuePool& cssValuePool, UnitlessQuirk unitless, UnitlessZeroQuirk unitlessZero)
    537 {
    538     const CSSParserToken& token = range.peek();
    539     if (token.type() == FunctionToken) {
    540         CalcParser calcParser(range, CalculationCategory::Angle, ValueRange::All, { }, cssValuePool);
    541         return calcParser.consumeValueIfCategory(CalculationCategory::Angle);
    542     }
    543 
    544     if (auto angle = consumeAngleRaw(range, cssParserMode, unitless, unitlessZero))
    545         return cssValuePool.createValue(angle->value, angle->type);
    546 
    547     return nullptr;
    548 }
    549 
    550 static RefPtr<CSSPrimitiveValue> consumeAngleOrPercent(CSSParserTokenRange& range, CSSParserMode cssParserMode, ValueRange valueRange, UnitlessQuirk unitless, UnitlessZeroQuirk unitlessZero)
    551 {
    552     const CSSParserToken& token = range.peek();
    553     switch (token.type()) {
    554     case DimensionToken:
    555         switch (token.unitType()) {
    556         case CSSUnitType::CSS_DEG:
    557         case CSSUnitType::CSS_RAD:
    558         case CSSUnitType::CSS_GRAD:
    559         case CSSUnitType::CSS_TURN:
    560             return CSSValuePool::singleton().createValue(range.consumeIncludingWhitespace().numericValue(), token.unitType());
     319
    561320        default:
    562321            break;
    563322        }
    564         break;
     323    }
     324    return std::nullopt;
     325}
     326
     327// MARK: Number (CSSPrimitiveValue - maintaing calc)
     328
     329static RefPtr<CSSPrimitiveValue> consumeNumberCSSPrimitiveValueWithCalcWithKnownTokenTypeFunction(CSSParserTokenRange& range, const CSSCalcSymbolTable& symbolTable, ValueRange valueRange, CSSValuePool& pool)
     330{
     331    ASSERT(range.peek().type() == FunctionToken);
     332
     333    CalcParser parser(range, CalculationCategory::Number, valueRange, symbolTable, pool);
     334    return parser.consumeValueIfCategory(CalculationCategory::Number);
     335}
     336
     337static RefPtr<CSSPrimitiveValue> consumeNumberCSSPrimitiveValueWithCalcWithKnownTokenTypeNumber(CSSParserTokenRange& range, const CSSCalcSymbolTable&, ValueRange valueRange, CSSValuePool& pool)
     338{
     339    ASSERT(range.peek().type() == NumberToken);
     340   
     341    auto token = range.peek();
     342   
     343    if (auto validatedValue = validatedNumberRaw(token.numericValue(), valueRange)) {
     344        auto unitType = token.unitType();
     345        range.consumeIncludingWhitespace();
     346        return pool.createValue(*validatedValue, unitType);
     347    }
     348    return nullptr;
     349}
     350
     351
     352// MARK: Percent (raw)
     353
     354static std::optional<double> validatedPercentRaw(double value, ValueRange valueRange)
     355{
     356    if (valueRange == ValueRange::NonNegative && value < 0)
     357        return std::nullopt;
     358    if (std::isinf(value))
     359        return std::nullopt;
     360    return value;
     361}
     362
     363static std::optional<double> consumePercentRawWithKnownTokenTypeFunction(CSSParserTokenRange& range, const CSSCalcSymbolTable& symbolTable, ValueRange valueRange)
     364{
     365    ASSERT(range.peek().type() == FunctionToken);
     366
     367    CalcParser parser(range, CalculationCategory::Percent, valueRange, symbolTable);
     368    return parser.consumePercentRaw();
     369}
     370
     371static std::optional<double> consumePercentRawWithKnownTokenTypePercentage(CSSParserTokenRange& range, const CSSCalcSymbolTable&, ValueRange valueRange)
     372{
     373    ASSERT(range.peek().type() == PercentageToken);
     374
     375    if (auto validatedValue = validatedPercentRaw(range.peek().numericValue(), valueRange)) {
     376        range.consumeIncludingWhitespace();
     377        return validatedValue;
     378    }
     379    return std::nullopt;
     380}
     381
     382static std::optional<double> consumePercentRawWithKnownTokenTypeIdent(CSSParserTokenRange& range, const CSSCalcSymbolTable& symbolTable, ValueRange valueRange)
     383{
     384    ASSERT(range.peek().type() == IdentToken);
     385
     386    if (auto variable = symbolTable.get(range.peek().id())) {
     387        switch (variable->type) {
     388        case CSSUnitType::CSS_PERCENTAGE:
     389            if (auto validatedValue = validatedPercentRaw(variable->value, valueRange)) {
     390                range.consumeIncludingWhitespace();
     391                return validatedValue;
     392            }
     393            break;
     394
     395        default:
     396            break;
     397        }
     398    }
     399    return std::nullopt;
     400}
     401
     402
     403// MARK: Percent (CSSPrimitiveValue - maintaing calc)
     404
     405static RefPtr<CSSPrimitiveValue> consumePercentCSSPrimitiveValueWithCalcWithKnownTokenTypeFunction(CSSParserTokenRange& range, const CSSCalcSymbolTable& symbolTable, ValueRange valueRange, CSSValuePool& pool)
     406{
     407    ASSERT(range.peek().type() == FunctionToken);
     408
     409    CalcParser parser(range, CalculationCategory::Percent, valueRange, symbolTable, pool);
     410    return parser.consumeValueIfCategory(CalculationCategory::Percent);
     411}
     412
     413static RefPtr<CSSPrimitiveValue> consumePercentCSSPrimitiveValueWithCalcWithKnownTokenTypePercentage(CSSParserTokenRange& range, const CSSCalcSymbolTable&, ValueRange valueRange, CSSValuePool& pool)
     414{
     415    ASSERT(range.peek().type() == PercentageToken);
     416
     417    if (auto validatedValue = validatedPercentRaw(range.peek().numericValue(), valueRange)) {
     418        range.consumeIncludingWhitespace();
     419        return pool.createValue(*validatedValue, CSSUnitType::CSS_PERCENTAGE);
     420    }
     421    return nullptr;
     422}
     423
     424// MARK: Length (raw)
     425
     426static std::optional<double> validatedLengthRaw(double value, ValueRange valueRange)
     427{
     428    if (valueRange == ValueRange::NonNegative && value < 0)
     429        return std::nullopt;
     430    if (std::isinf(value))
     431        return std::nullopt;
     432    return value;
     433}
     434
     435static std::optional<LengthRaw> consumeLengthRawWithKnownTokenTypeFunction(CSSParserTokenRange& range, const CSSCalcSymbolTable& symbolTable, ValueRange valueRange, CSSParserMode, UnitlessQuirk)
     436{
     437    ASSERT(range.peek().type() == FunctionToken);
     438
     439    CalcParser parser(range, CalculationCategory::Length, valueRange, symbolTable);
     440    return parser.consumeLengthRaw();
     441}
     442
     443static std::optional<LengthRaw> consumeLengthRawWithKnownTokenTypeDimension(CSSParserTokenRange& range, const CSSCalcSymbolTable&, ValueRange valueRange, CSSParserMode parserMode, UnitlessQuirk)
     444{
     445    ASSERT(range.peek().type() == DimensionToken);
     446
     447    auto& token = range.peek();
     448
     449    auto unitType = token.unitType();
     450    switch (unitType) {
     451    case CSSUnitType::CSS_QUIRKY_EMS:
     452        if (parserMode != UASheetMode)
     453            return std::nullopt;
     454        FALLTHROUGH;
     455    case CSSUnitType::CSS_EMS:
     456    case CSSUnitType::CSS_REMS:
     457    case CSSUnitType::CSS_LHS:
     458    case CSSUnitType::CSS_RLHS:
     459    case CSSUnitType::CSS_CHS:
     460    case CSSUnitType::CSS_EXS:
     461    case CSSUnitType::CSS_PX:
     462    case CSSUnitType::CSS_CM:
     463    case CSSUnitType::CSS_MM:
     464    case CSSUnitType::CSS_IN:
     465    case CSSUnitType::CSS_PT:
     466    case CSSUnitType::CSS_PC:
     467    case CSSUnitType::CSS_VW:
     468    case CSSUnitType::CSS_VH:
     469    case CSSUnitType::CSS_VMIN:
     470    case CSSUnitType::CSS_VMAX:
     471    case CSSUnitType::CSS_Q:
     472        break;
     473    default:
     474        return std::nullopt;
     475    }
     476
     477    if (auto validatedValue = validatedLengthRaw(token.numericValue(), valueRange)) {
     478        range.consumeIncludingWhitespace();
     479        return { { unitType, *validatedValue } };
     480    }
     481    return std::nullopt;
     482}
     483
     484static std::optional<LengthRaw> consumeLengthRawWithKnownTokenTypeNumber(CSSParserTokenRange& range, const CSSCalcSymbolTable&, ValueRange valueRange, CSSParserMode parserMode, UnitlessQuirk unitless)
     485{
     486    ASSERT(range.peek().type() == NumberToken);
     487
     488    auto& token = range.peek();
     489
     490    if (!shouldAcceptUnitlessValue(token.numericValue(), parserMode, unitless, UnitlessZeroQuirk::Allow))
     491        return std::nullopt;
     492
     493    if (auto validatedValue = validatedLengthRaw(token.numericValue(), valueRange)) {
     494        range.consumeIncludingWhitespace();
     495        return { { CSSUnitType::CSS_PX, *validatedValue } };
     496    }
     497    return std::nullopt;
     498}
     499
     500// MARK: Length (CSSPrimitiveValue - maintaing calc)
     501
     502static RefPtr<CSSPrimitiveValue> consumeLengthCSSPrimitiveValueWithCalcWithKnownTokenTypeFunction(CSSParserTokenRange& range, const CSSCalcSymbolTable& symbolTable, ValueRange valueRange, CSSParserMode, UnitlessQuirk, CSSValuePool& pool)
     503{
     504    ASSERT(range.peek().type() == FunctionToken);
     505
     506    CalcParser parser(range, CalculationCategory::Length, valueRange, symbolTable, pool);
     507    return parser.consumeValueIfCategory(CalculationCategory::Length);
     508}
     509
     510static RefPtr<CSSPrimitiveValue> consumeLengthCSSPrimitiveValueWithCalcWithKnownTokenTypeDimension(CSSParserTokenRange& range, const CSSCalcSymbolTable& symbolTable, ValueRange valueRange, CSSParserMode parserMode, UnitlessQuirk unitless, CSSValuePool& pool)
     511{
     512    ASSERT(range.peek().type() == DimensionToken);
     513
     514    if (auto lengthRaw = consumeLengthRawWithKnownTokenTypeDimension(range, symbolTable, valueRange, parserMode, unitless))
     515        return pool.createValue(lengthRaw->value, lengthRaw->type);
     516    return nullptr;
     517}
     518
     519static RefPtr<CSSPrimitiveValue> consumeLengthCSSPrimitiveValueWithCalcWithKnownTokenTypeNumber(CSSParserTokenRange& range, const CSSCalcSymbolTable& symbolTable, ValueRange valueRange, CSSParserMode parserMode, UnitlessQuirk unitless, CSSValuePool& pool)
     520{
     521    ASSERT(range.peek().type() == NumberToken);
     522
     523    if (auto lengthRaw = consumeLengthRawWithKnownTokenTypeNumber(range, symbolTable, valueRange, parserMode, unitless))
     524        return pool.createValue(lengthRaw->value, lengthRaw->type);
     525    return nullptr;
     526}
     527
     528// MARK: Angle (raw)
     529
     530static std::optional<AngleRaw> consumeAngleRawWithKnownTokenTypeFunction(CSSParserTokenRange& range, const CSSCalcSymbolTable& symbolTable, ValueRange valueRange, CSSParserMode, UnitlessQuirk, UnitlessZeroQuirk)
     531{
     532    ASSERT(range.peek().type() == FunctionToken);
     533
     534    CalcParser parser(range, CalculationCategory::Angle, valueRange, symbolTable);
     535    return parser.consumeAngleRaw();
     536}
     537
     538static std::optional<AngleRaw> consumeAngleRawWithKnownTokenTypeDimension(CSSParserTokenRange& range, const CSSCalcSymbolTable&, ValueRange, CSSParserMode, UnitlessQuirk, UnitlessZeroQuirk)
     539{
     540    ASSERT(range.peek().type() == DimensionToken);
     541
     542    auto unitType = range.peek().unitType();
     543    switch (unitType) {
     544    case CSSUnitType::CSS_DEG:
     545    case CSSUnitType::CSS_RAD:
     546    case CSSUnitType::CSS_GRAD:
     547    case CSSUnitType::CSS_TURN:
     548        return { { unitType, range.consumeIncludingWhitespace().numericValue() } };
     549    default:
     550        break;
     551    }
     552
     553    return std::nullopt;
     554}
     555
     556static std::optional<AngleRaw> consumeAngleRawWithKnownTokenTypeNumber(CSSParserTokenRange& range, const CSSCalcSymbolTable&, ValueRange, CSSParserMode parserMode, UnitlessQuirk unitless, UnitlessZeroQuirk unitlessZero)
     557{
     558    ASSERT(range.peek().type() == NumberToken);
     559
     560    if (shouldAcceptUnitlessValue(range.peek().numericValue(), parserMode, unitless, unitlessZero))
     561        return { { CSSUnitType::CSS_DEG, range.consumeIncludingWhitespace().numericValue() } };
     562    return std::nullopt;
     563}
     564
     565// MARK: Angle (CSSPrimitiveValue - maintaing calc)
     566
     567static RefPtr<CSSPrimitiveValue> consumeAngleCSSPrimitiveValueWithCalcWithKnownTokenTypeFunction(CSSParserTokenRange& range, const CSSCalcSymbolTable& symbolTable, ValueRange valueRange, CSSParserMode, UnitlessQuirk, UnitlessZeroQuirk, CSSValuePool& pool)
     568{
     569    ASSERT(range.peek().type() == FunctionToken);
     570
     571    CalcParser parser(range, CalculationCategory::Angle, valueRange, symbolTable, pool);
     572    return parser.consumeValueIfCategory(CalculationCategory::Angle);
     573}
     574
     575static RefPtr<CSSPrimitiveValue> consumeAngleCSSPrimitiveValueWithCalcWithKnownTokenTypeDimension(CSSParserTokenRange& range, const CSSCalcSymbolTable& symbolTable, ValueRange valueRange, CSSParserMode parserMode, UnitlessQuirk unitless, UnitlessZeroQuirk unitlessZero, CSSValuePool& pool)
     576{
     577    ASSERT(range.peek().type() == DimensionToken);
     578
     579    if (auto angleRaw = consumeAngleRawWithKnownTokenTypeDimension(range, symbolTable, valueRange, parserMode, unitless, unitlessZero))
     580        return pool.createValue(angleRaw->value, angleRaw->type);
     581    return nullptr;
     582}
     583
     584static RefPtr<CSSPrimitiveValue> consumeAngleCSSPrimitiveValueWithCalcWithKnownTokenTypeNumber(CSSParserTokenRange& range, const CSSCalcSymbolTable& symbolTable, ValueRange valueRange, CSSParserMode parserMode, UnitlessQuirk unitless, UnitlessZeroQuirk unitlessZero, CSSValuePool& pool)
     585{
     586    ASSERT(range.peek().type() == NumberToken);
     587
     588    if (auto angleRaw = consumeAngleRawWithKnownTokenTypeNumber(range, symbolTable, valueRange, parserMode, unitless, unitlessZero))
     589        return pool.createValue(angleRaw->value, angleRaw->type);
     590    return nullptr;
     591}
     592
     593
     594// MARK: Time (CSSPrimitiveValue - maintaing calc)
     595
     596static RefPtr<CSSPrimitiveValue> consumeTimeCSSPrimitiveValueWithCalcWithKnownTokenTypeFunction(CSSParserTokenRange& range, const CSSCalcSymbolTable& symbolTable, ValueRange valueRange, CSSParserMode, UnitlessQuirk, CSSValuePool& pool)
     597{
     598    ASSERT(range.peek().type() == FunctionToken);
     599
     600    CalcParser parser(range, CalculationCategory::Time, valueRange, symbolTable, pool);
     601    return parser.consumeValueIfCategory(CalculationCategory::Time);
     602}
     603
     604static RefPtr<CSSPrimitiveValue> consumeTimeCSSPrimitiveValueWithCalcWithKnownTokenTypeDimension(CSSParserTokenRange& range, const CSSCalcSymbolTable&, ValueRange valueRange, CSSParserMode, UnitlessQuirk, CSSValuePool& pool)
     605{
     606    ASSERT(range.peek().type() == DimensionToken);
     607
     608    if (valueRange == ValueRange::NonNegative && range.peek().numericValue() < 0)
     609        return nullptr;
     610
     611    if (auto unit = range.peek().unitType(); unit == CSSUnitType::CSS_MS || unit == CSSUnitType::CSS_S)
     612        return pool.createValue(range.consumeIncludingWhitespace().numericValue(), unit);
     613
     614    return nullptr;
     615}
     616
     617static RefPtr<CSSPrimitiveValue> consumeTimeCSSPrimitiveValueWithCalcWithKnownTokenTypeNumber(CSSParserTokenRange& range, const CSSCalcSymbolTable&, ValueRange valueRange, CSSParserMode parserMode, UnitlessQuirk unitless, CSSValuePool& pool)
     618{
     619    ASSERT(range.peek().type() == NumberToken);
     620
     621    if (unitless == UnitlessQuirk::Allow && shouldAcceptUnitlessValue(range.peek().numericValue(), parserMode, unitless, UnitlessZeroQuirk::Allow)) {
     622        if (valueRange == ValueRange::NonNegative && range.peek().numericValue() < 0)
     623            return nullptr;
     624        return pool.createValue(range.consumeIncludingWhitespace().numericValue(), CSSUnitType::CSS_MS);
     625    }
     626    return nullptr;
     627}
     628
     629// MARK: Resolution (CSSPrimitiveValue - no calc)
     630
     631static RefPtr<CSSPrimitiveValue> consumeResolutionCSSPrimitiveValueWithKnownTokenTypeDimension(CSSParserTokenRange& range, AllowXResolutionUnit allowX, CSSValuePool& pool)
     632{
     633    ASSERT(range.peek().type() == DimensionToken);
     634
     635    if (auto unit = range.peek().unitType(); unit == CSSUnitType::CSS_DPPX || unit == CSSUnitType::CSS_DPI || unit == CSSUnitType::CSS_DPCM)
     636        return pool.createValue(range.consumeIncludingWhitespace().numericValue(), unit);
     637    if (allowX == AllowXResolutionUnit::Allow && range.peek().value() == "x")
     638        return pool.createValue(range.consumeIncludingWhitespace().numericValue(), CSSUnitType::CSS_DPPX);
     639
     640    return nullptr;
     641}
     642
     643
     644// MARK: - Primitive value consumers for callers that do NOT know the token type.
     645
     646template<typename IntType> std::optional<IntType> consumeIntegerTypeRaw(CSSParserTokenRange& range, double minimumValue)
     647{
     648    auto& token = range.peek();
     649
     650    switch (token.type()) {
     651    case FunctionToken:
     652        return consumeIntegerTypeRawWithKnownTokenTypeFunction<IntType>(range, minimumValue);
     653
     654    case NumberToken:
     655        return consumeIntegerTypeRawWithKnownTokenTypeNumber<IntType>(range, minimumValue);
     656   
     657    default:
     658        break;
     659    }
     660
     661    return std::nullopt;
     662}
     663
     664template<typename IntType> RefPtr<CSSPrimitiveValue> consumeIntegerType(CSSParserTokenRange& range, double minimumValue, CSSValuePool& pool)
     665{
     666    auto& token = range.peek();
     667
     668    switch (token.type()) {
     669    case FunctionToken:
     670        return consumeIntegerTypeCSSPrimitiveValueWithCalcWithKnownTokenTypeFunction<IntType>(range, minimumValue, pool);
     671
     672    case NumberToken:
     673        return consumeIntegerTypeCSSPrimitiveValueWithCalcWithKnownTokenTypeNumber<IntType>(range, minimumValue, pool);
     674
     675    default:
     676        break;
     677    }
     678
     679    return nullptr;
     680}
     681
     682std::optional<int> consumeIntegerRaw(CSSParserTokenRange& range, double minimumValue)
     683{
     684    return consumeIntegerTypeRaw<int>(range, minimumValue);
     685}
     686
     687RefPtr<CSSPrimitiveValue> consumeInteger(CSSParserTokenRange& range, double minimumValue)
     688{
     689    return consumeIntegerType<int>(range, minimumValue, CSSValuePool::singleton());
     690}
     691
     692std::optional<unsigned> consumePositiveIntegerRaw(CSSParserTokenRange& range)
     693{
     694    return consumeIntegerTypeRaw<unsigned>(range, 1);
     695}
     696
     697RefPtr<CSSPrimitiveValue> consumePositiveInteger(CSSParserTokenRange& range)
     698{
     699    return consumeIntegerType<unsigned>(range, 1, CSSValuePool::singleton());
     700}
     701
     702std::optional<double> consumeNumberRaw(CSSParserTokenRange& range, ValueRange valueRange)
     703{
     704    auto& token = range.peek();
     705
     706    switch (token.type()) {
     707    case FunctionToken:
     708        return consumeNumberRawWithKnownTokenTypeFunction(range, { }, valueRange);
     709
     710    case NumberToken:
     711        return consumeNumberRawWithKnownTokenTypeNumber(range, { }, valueRange);
     712
     713    default:
     714        break;
     715    }
     716
     717    return std::nullopt;
     718}
     719
     720RefPtr<CSSPrimitiveValue> consumeNumber(CSSParserTokenRange& range, ValueRange valueRange)
     721{
     722    auto& token = range.peek();
     723
     724    switch (token.type()) {
     725    case FunctionToken:
     726        return consumeNumberCSSPrimitiveValueWithCalcWithKnownTokenTypeFunction(range, { }, valueRange, CSSValuePool::singleton());
     727
     728    case NumberToken:
     729        return consumeNumberCSSPrimitiveValueWithCalcWithKnownTokenTypeNumber(range, { }, valueRange, CSSValuePool::singleton());
     730
     731    default:
     732        break;
     733    }
     734
     735    return nullptr;
     736}
     737
     738std::optional<LengthRaw> consumeLengthRaw(CSSParserTokenRange& range, CSSParserMode parserMode, ValueRange valueRange, UnitlessQuirk unitless)
     739{
     740    auto& token = range.peek();
     741   
     742    switch (token.type()) {
     743    case FunctionToken:
     744        return consumeLengthRawWithKnownTokenTypeFunction(range, { }, valueRange, parserMode, unitless);
     745
     746    case DimensionToken:
     747        return consumeLengthRawWithKnownTokenTypeDimension(range, { }, valueRange, parserMode, unitless);
    565748   
    566749    case NumberToken:
    567         if (shouldAcceptUnitlessValue(token.numericValue(), cssParserMode, unitless, unitlessZero))
    568             return CSSValuePool::singleton().createValue(range.consumeIncludingWhitespace().numericValue(), CSSUnitType::CSS_DEG);
    569         break;
     750        return consumeLengthRawWithKnownTokenTypeNumber(range, { }, valueRange, parserMode, unitless);
     751
     752    default:
     753        break;
     754    }
     755
     756    return std::nullopt;
     757}
     758
     759RefPtr<CSSPrimitiveValue> consumeLength(CSSParserTokenRange& range, CSSParserMode parserMode, ValueRange valueRange, UnitlessQuirk unitless)
     760{
     761    auto& token = range.peek();
     762
     763    switch (token.type()) {
     764    case FunctionToken:
     765        return consumeLengthCSSPrimitiveValueWithCalcWithKnownTokenTypeFunction(range, { }, valueRange, parserMode, unitless, CSSValuePool::singleton());
     766
     767    case DimensionToken:
     768        return consumeLengthCSSPrimitiveValueWithCalcWithKnownTokenTypeDimension(range, { }, valueRange, parserMode, unitless, CSSValuePool::singleton());
     769   
     770    case NumberToken:
     771        return consumeLengthCSSPrimitiveValueWithCalcWithKnownTokenTypeNumber(range, { }, valueRange, parserMode, unitless, CSSValuePool::singleton());
     772
     773    default:
     774        break;
     775    }
     776
     777    return nullptr;
     778}
     779
     780std::optional<double> consumePercentRaw(CSSParserTokenRange& range, ValueRange valueRange)
     781{
     782    const auto& token = range.peek();
     783
     784    switch (token.type()) {
     785    case FunctionToken:
     786        return consumePercentRawWithKnownTokenTypeFunction(range, { }, valueRange);
    570787
    571788    case PercentageToken:
    572         return consumePercent(range, valueRange);
    573 
    574     case FunctionToken: {
    575         CalcParser angleCalcParser(range, CalculationCategory::Angle, valueRange);
    576         if (const CSSCalcValue* calculation = angleCalcParser.value()) {
    577             if (calculation->category() == CalculationCategory::Angle)
    578                 return angleCalcParser.consumeValue();
    579         }
    580 
    581         CalcParser percentCalcParser(range, CalculationCategory::Percent, valueRange);
    582         if (const CSSCalcValue* calculation = percentCalcParser.value()) {
    583             if (calculation->category() == CalculationCategory::Percent)
    584                 return percentCalcParser.consumeValue();
    585         }
    586    
    587         break;
    588     }
     789        return consumePercentRawWithKnownTokenTypePercentage(range, { }, valueRange);
     790
     791    default:
     792        break;
     793    }
     794
     795    return std::nullopt;
     796}
     797
     798RefPtr<CSSPrimitiveValue> consumePercent(CSSParserTokenRange& range, ValueRange valueRange)
     799{
     800    return consumePercentWorkerSafe(range, valueRange, CSSValuePool::singleton());
     801}
     802
     803RefPtr<CSSPrimitiveValue> consumePercentWorkerSafe(CSSParserTokenRange& range, ValueRange valueRange, CSSValuePool& pool)
     804{
     805    auto& token = range.peek();
     806
     807    switch (token.type()) {
     808    case FunctionToken:
     809        return consumePercentCSSPrimitiveValueWithCalcWithKnownTokenTypeFunction(range, { }, valueRange, pool);
     810
     811    case PercentageToken:
     812        return consumePercentCSSPrimitiveValueWithCalcWithKnownTokenTypePercentage(range, { }, valueRange, pool);
     813
     814    default:
     815        break;
     816    }
     817
     818    return nullptr;
     819}
     820
     821std::optional<AngleRaw> consumeAngleRaw(CSSParserTokenRange& range, CSSParserMode parserMode, UnitlessQuirk unitless, UnitlessZeroQuirk unitlessZero)
     822{
     823    auto& token = range.peek();
     824
     825    switch (token.type()) {
     826    case FunctionToken:
     827        return consumeAngleRawWithKnownTokenTypeFunction(range, { }, ValueRange::All, parserMode, unitless, unitlessZero);
     828
     829    case DimensionToken:
     830        return consumeAngleRawWithKnownTokenTypeDimension(range, { }, ValueRange::All, parserMode, unitless, unitlessZero);
     831
     832    case NumberToken:
     833        return consumeAngleRawWithKnownTokenTypeNumber(range, { }, ValueRange::All, parserMode, unitless, unitlessZero);
     834        break;
     835
     836    default:
     837        break;
     838    }
     839
     840    return std::nullopt;
     841}
     842
     843RefPtr<CSSPrimitiveValue> consumeAngle(CSSParserTokenRange& range, CSSParserMode parserMode, UnitlessQuirk unitless, UnitlessZeroQuirk unitlessZero)
     844{
     845    return consumeAngleWorkerSafe(range, parserMode, CSSValuePool::singleton(), unitless, unitlessZero);
     846}
     847
     848RefPtr<CSSPrimitiveValue> consumeAngleWorkerSafe(CSSParserTokenRange& range, CSSParserMode parserMode, CSSValuePool& pool, UnitlessQuirk unitless, UnitlessZeroQuirk unitlessZero)
     849{
     850    auto& token = range.peek();
     851
     852    switch (token.type()) {
     853    case FunctionToken:
     854        return consumeAngleCSSPrimitiveValueWithCalcWithKnownTokenTypeFunction(range, { }, ValueRange::All, parserMode, unitless, unitlessZero, pool);
     855
     856    case DimensionToken:
     857        return consumeAngleCSSPrimitiveValueWithCalcWithKnownTokenTypeDimension(range, { }, ValueRange::All, parserMode, unitless, unitlessZero, pool);
     858
     859    case NumberToken:
     860        return consumeAngleCSSPrimitiveValueWithCalcWithKnownTokenTypeNumber(range, { }, ValueRange::All, parserMode, unitless, unitlessZero, pool);
    589861   
    590862    default:
    591863        break;
    592864    }
    593 
     865   
    594866    return nullptr;
    595867}
    596868
    597 RefPtr<CSSPrimitiveValue> consumeTime(CSSParserTokenRange& range, CSSParserMode cssParserMode, ValueRange valueRange, UnitlessQuirk unitless)
    598 {
    599     const CSSParserToken& token = range.peek();
    600     CSSUnitType unit = token.unitType();
    601     bool acceptUnitless = token.type() == NumberToken && unitless == UnitlessQuirk::Allow && shouldAcceptUnitlessValue(token.numericValue(), cssParserMode, unitless, UnitlessZeroQuirk::Allow);
    602     if (acceptUnitless)
    603         unit = CSSUnitType::CSS_MS;
    604     if (token.type() == DimensionToken || acceptUnitless) {
    605         if (valueRange == ValueRange::NonNegative && token.numericValue() < 0)
    606             return nullptr;
    607         if (unit == CSSUnitType::CSS_MS || unit == CSSUnitType::CSS_S)
    608             return CSSValuePool::singleton().createValue(range.consumeIncludingWhitespace().numericValue(), unit);
    609         return nullptr;
    610     }
    611 
    612     if (token.type() != FunctionToken)
    613         return nullptr;
    614 
    615     CalcParser calcParser(range, CalculationCategory::Time, valueRange);
    616     return calcParser.consumeValueIfCategory(CalculationCategory::Time);
     869RefPtr<CSSPrimitiveValue> consumeTime(CSSParserTokenRange& range, CSSParserMode parserMode, ValueRange valueRange, UnitlessQuirk unitless)
     870{
     871    auto& token = range.peek();
     872
     873    switch (token.type()) {
     874    case FunctionToken:
     875        return consumeTimeCSSPrimitiveValueWithCalcWithKnownTokenTypeFunction(range, { }, valueRange, parserMode, unitless, CSSValuePool::singleton());
     876
     877    case DimensionToken:
     878        return consumeTimeCSSPrimitiveValueWithCalcWithKnownTokenTypeDimension(range, { }, valueRange, parserMode, unitless, CSSValuePool::singleton());
     879
     880    case NumberToken:
     881        return consumeTimeCSSPrimitiveValueWithCalcWithKnownTokenTypeNumber(range, { }, valueRange, parserMode, unitless, CSSValuePool::singleton());
     882
     883    default:
     884        break;
     885    }
     886   
     887    return nullptr;
    617888}
    618889
    619890RefPtr<CSSPrimitiveValue> consumeResolution(CSSParserTokenRange& range, AllowXResolutionUnit allowX)
    620891{
    621     const CSSParserToken& token = range.peek();
    622     // Unlike the other types, calc() does not work with <resolution>.
    623     if (token.type() != DimensionToken)
    624         return nullptr;
    625     CSSUnitType unit = token.unitType();
    626     if (unit == CSSUnitType::CSS_DPPX || unit == CSSUnitType::CSS_DPI || unit == CSSUnitType::CSS_DPCM)
    627         return CSSValuePool::singleton().createValue(range.consumeIncludingWhitespace().numericValue(), unit);
    628     if (allowX == AllowXResolutionUnit::Allow && token.value() == "x")
    629         return CSSValuePool::singleton().createValue(range.consumeIncludingWhitespace().numericValue(), CSSUnitType::CSS_DPPX);
    630 
     892    // NOTE: Unlike the other types, calc() does not work with <resolution>.
     893
     894    auto& token = range.peek();
     895
     896    switch (token.type()) {
     897    case DimensionToken:
     898        return consumeResolutionCSSPrimitiveValueWithKnownTokenTypeDimension(range, allowX, CSSValuePool::singleton());
     899   
     900    default:
     901        break;
     902    }
     903
     904    return nullptr;
     905}
     906
     907// MARK: - Combination consumers (token type unknown by caller).
     908
     909static RefPtr<CSSPrimitiveValue> consumeAngleOrPercent(CSSParserTokenRange& range, CSSParserMode parserMode, ValueRange valueRange, UnitlessQuirk unitless, UnitlessZeroQuirk unitlessZero, CSSValuePool& pool = CSSValuePool::singleton())
     910{
     911    auto& token = range.peek();
     912
     913    switch (token.type()) {
     914    case FunctionToken:
     915        if (auto value = consumeAngleCSSPrimitiveValueWithCalcWithKnownTokenTypeFunction(range, { }, valueRange, parserMode, unitless, unitlessZero, pool))
     916            return value;
     917        return consumePercentCSSPrimitiveValueWithCalcWithKnownTokenTypeFunction(range, { }, valueRange, pool);
     918
     919    case DimensionToken:
     920        return consumeAngleCSSPrimitiveValueWithCalcWithKnownTokenTypeDimension(range, { }, valueRange, parserMode, unitless, unitlessZero, pool);
     921   
     922    case NumberToken:
     923        return consumeAngleCSSPrimitiveValueWithCalcWithKnownTokenTypeNumber(range, { }, valueRange, parserMode, unitless, unitlessZero, pool);
     924
     925    case PercentageToken:
     926        return consumePercentCSSPrimitiveValueWithCalcWithKnownTokenTypePercentage(range, { }, valueRange, pool);
     927   
     928    default:
     929        break;
     930    }
     931
     932    return nullptr;
     933}
     934
     935std::optional<LengthOrPercentRaw> consumeLengthOrPercentRaw(CSSParserTokenRange& range, CSSParserMode parserMode, ValueRange valueRange, UnitlessQuirk unitless)
     936{
     937    auto convertToLengthOrPercentRaw = [](auto result) -> std::optional<LengthOrPercentRaw> {
     938        if (result)
     939            return { *result };
     940        return std::nullopt;
     941    };
     942
     943    auto& token = range.peek();
     944
     945    switch (token.type()) {
     946    case FunctionToken: {
     947        // FIXME: Should this be using trying to generate the calc with both Length and Percent destination category types?
     948        CalcParser parser(range, CalculationCategory::Length, valueRange);
     949        if (auto calculation = parser.value(); calculation && canConsumeCalcValue(calculation->category(), parserMode))
     950            return parser.consumeLengthOrPercentRaw();
     951        break;
     952    }
     953
     954    case DimensionToken:
     955        return convertToLengthOrPercentRaw(consumeLengthRawWithKnownTokenTypeDimension(range, { }, valueRange, parserMode, unitless));
     956   
     957    case NumberToken:
     958        return convertToLengthOrPercentRaw(consumeLengthRawWithKnownTokenTypeNumber(range, { }, valueRange, parserMode, unitless));
     959
     960    case PercentageToken:
     961        return convertToLengthOrPercentRaw(consumePercentRawWithKnownTokenTypePercentage(range, { }, valueRange));
     962
     963    default:
     964        break;
     965    }
     966
     967    return std::nullopt;
     968}
     969
     970RefPtr<CSSPrimitiveValue> consumeLengthOrPercent(CSSParserTokenRange& range, CSSParserMode parserMode, ValueRange valueRange, UnitlessQuirk unitless)
     971{
     972    auto& token = range.peek();
     973
     974    switch (token.type()) {
     975    case FunctionToken: {
     976        // FIXME: Should this be using trying to generate the calc with both Length and Percent destination category types?
     977        CalcParser parser(range, CalculationCategory::Length, valueRange);
     978        if (auto calculation = parser.value(); calculation && canConsumeCalcValue(calculation->category(), parserMode))
     979            return parser.consumeValue();
     980        break;
     981    }
     982
     983    case DimensionToken:
     984        return consumeLengthCSSPrimitiveValueWithCalcWithKnownTokenTypeDimension(range, { }, valueRange, parserMode, unitless, CSSValuePool::singleton());
     985   
     986    case NumberToken:
     987        return consumeLengthCSSPrimitiveValueWithCalcWithKnownTokenTypeNumber(range, { }, valueRange, parserMode, unitless, CSSValuePool::singleton());
     988
     989    case PercentageToken:
     990        return consumePercentCSSPrimitiveValueWithCalcWithKnownTokenTypePercentage(range, { }, valueRange, CSSValuePool::singleton());
     991
     992    default:
     993        break;
     994    }
     995
     996    return nullptr;
     997}
     998
     999// MARK: - Combination consumers that allow lookup in the symbol table for IdentTokens (by default, other consumers only lookup in the symbol table for calc()).
     1000
     1001static std::optional<double> consumeNumberAllowingSymbolTableIdent(CSSParserTokenRange& range, const CSSCalcSymbolTable& symbolTable, ValueRange valueRange = ValueRange::All)
     1002{
     1003    auto& token = range.peek();
     1004
     1005    switch (token.type()) {
     1006    case FunctionToken:
     1007        return consumeNumberRawWithKnownTokenTypeFunction(range, symbolTable, valueRange);
     1008
     1009    case NumberToken:
     1010        return consumeNumberRawWithKnownTokenTypeNumber(range, symbolTable, valueRange);
     1011
     1012    case IdentToken:
     1013        return consumeNumberRawWithKnownTokenTypeIdent(range, symbolTable, valueRange);
     1014
     1015    default:
     1016        break;
     1017    }
     1018
     1019    return std::nullopt;
     1020}
     1021
     1022static std::optional<double> consumePercentAllowingSymbolTableIdent(CSSParserTokenRange& range, const CSSCalcSymbolTable& symbolTable, ValueRange valueRange = ValueRange::All)
     1023{
     1024    auto& token = range.peek();
     1025
     1026    switch (token.type()) {
     1027    case FunctionToken:
     1028        return consumePercentRawWithKnownTokenTypeFunction(range, symbolTable, valueRange);
     1029
     1030    case PercentageToken:
     1031        return consumePercentRawWithKnownTokenTypePercentage(range, symbolTable, valueRange);
     1032
     1033    case IdentToken:
     1034        return consumePercentRawWithKnownTokenTypeIdent(range, symbolTable, valueRange);
     1035
     1036    default:
     1037        break;
     1038    }
     1039
     1040    return std::nullopt;
     1041}
     1042
     1043static std::optional<double> consumeAngleRawOrNumberRaw(CSSParserTokenRange& range, CSSParserMode parserMode)
     1044{
     1045    auto computeDegrees = [](auto angleRaw) -> std::optional<double> {
     1046        if (angleRaw)
     1047            return CSSPrimitiveValue::computeDegrees(angleRaw->type, angleRaw->value);
     1048        return std::nullopt;
     1049    };
     1050
     1051    auto& token = range.peek();
     1052
     1053    switch (token.type()) {
     1054    case FunctionToken:
     1055        if (auto angleRaw = consumeAngleRawWithKnownTokenTypeFunction(range, { }, ValueRange::All, parserMode, UnitlessQuirk::Forbid, UnitlessZeroQuirk::Forbid))
     1056            return computeDegrees(angleRaw);
     1057        return consumeNumberRawWithKnownTokenTypeFunction(range, { }, ValueRange::All);
     1058   
     1059    case DimensionToken:
     1060        return computeDegrees(consumeAngleRawWithKnownTokenTypeDimension(range, { }, ValueRange::All, parserMode, UnitlessQuirk::Forbid, UnitlessZeroQuirk::Forbid));
     1061   
     1062    case NumberToken:
     1063        return consumeNumberRawWithKnownTokenTypeNumber(range, { }, ValueRange::All);
     1064
     1065    default:
     1066        break;
     1067    }
     1068
     1069    return std::nullopt;
     1070}
     1071
     1072static std::optional<double> consumeAngleRawOrNumberRawAllowingSymbolTableIdent(CSSParserTokenRange& range, const CSSCalcSymbolTable& symbolTable, CSSParserMode parserMode)
     1073{
     1074    auto computeDegrees = [](auto angleRaw) -> std::optional<double> {
     1075        if (angleRaw)
     1076            return CSSPrimitiveValue::computeDegrees(angleRaw->type, angleRaw->value);
     1077        return std::nullopt;
     1078    };
     1079
     1080    auto& token = range.peek();
     1081
     1082    switch (token.type()) {
     1083    case FunctionToken:
     1084        if (auto angleRaw = consumeAngleRawWithKnownTokenTypeFunction(range, symbolTable, ValueRange::All, parserMode, UnitlessQuirk::Forbid, UnitlessZeroQuirk::Forbid))
     1085            return computeDegrees(angleRaw);
     1086        return consumeNumberRawWithKnownTokenTypeFunction(range, symbolTable, ValueRange::All);
     1087   
     1088    case DimensionToken:
     1089        return computeDegrees(consumeAngleRawWithKnownTokenTypeDimension(range, { }, ValueRange::All, parserMode, UnitlessQuirk::Forbid, UnitlessZeroQuirk::Forbid));
     1090   
     1091    case NumberToken:
     1092        return consumeNumberRawWithKnownTokenTypeNumber(range, { }, ValueRange::All);
     1093
     1094    case IdentToken:
     1095        if (auto variable = symbolTable.get(token.id())) {
     1096            switch (variable->type) {
     1097            case CSSUnitType::CSS_DEG:
     1098            case CSSUnitType::CSS_RAD:
     1099            case CSSUnitType::CSS_GRAD:
     1100            case CSSUnitType::CSS_TURN:
     1101                range.consumeIncludingWhitespace();
     1102                return CSSPrimitiveValue::computeDegrees(variable->type, variable->value);
     1103
     1104            case CSSUnitType::CSS_NUMBER:
     1105                range.consumeIncludingWhitespace();
     1106                return variable->value;
     1107
     1108            default:
     1109                break;
     1110            }
     1111        }
     1112        break;
     1113
     1114    default:
     1115        break;
     1116    }
     1117
     1118    return std::nullopt;
     1119}
     1120
     1121// MARK: - Combination consumers with transformations based on result type.
     1122
     1123template<typename NumberTransformer, typename PercentTransformer>
     1124static auto consumeNumberRawOrPercentRaw(CSSParserTokenRange& range, ValueRange valueRange, NumberTransformer&& numberTranformer, PercentTransformer&& percentTranformer) -> std::optional<decltype(numberTranformer(std::declval<double>()))>
     1125{
     1126    const auto& token = range.peek();
     1127
     1128    switch (token.type()) {
     1129    case FunctionToken: {
     1130        if (auto number = consumeNumberRawWithKnownTokenTypeFunction(range, { }, valueRange))
     1131            return numberTranformer(*number);
     1132        if (auto percent = consumePercentRawWithKnownTokenTypeFunction(range, { }, valueRange))
     1133            return percentTranformer(*percent);
     1134        break;
     1135    }
     1136
     1137    case PercentageToken:
     1138        if (auto percent = consumePercentRawWithKnownTokenTypePercentage(range, { }, valueRange))
     1139            return percentTranformer(*percent);
     1140        break;
     1141
     1142    case NumberToken:
     1143        if (auto number = consumeNumberRawWithKnownTokenTypeNumber(range, { }, valueRange))
     1144            return numberTranformer(*number);
     1145        break;
     1146
     1147    default:
     1148        break;
     1149    }
     1150
     1151    return std::nullopt;
     1152}
     1153
     1154static std::optional<double> consumeNumberRawOrPercentDividedBy100Raw(CSSParserTokenRange& range, ValueRange valueRange = ValueRange::All)
     1155{
     1156    return consumeNumberRawOrPercentRaw(range, valueRange, [](double number) { return number; }, [](double percent) { return percent / 100.0; });
     1157}
     1158
     1159// MARK: - Combination consumers that both allow lookup in the symbol table for IdentTokens and transformations based on result type.
     1160
     1161template<typename NumberTransformer, typename PercentTransformer>
     1162static auto consumeNumberRawOrPercentRawAllowingSymbolTableIdent(CSSParserTokenRange& range, const CSSCalcSymbolTable& symbolTable, ValueRange valueRange, NumberTransformer&& numberTranformer, PercentTransformer&& percentTranformer) -> std::optional<decltype(numberTranformer(std::declval<double>()))>
     1163{
     1164    auto& token = range.peek();
     1165
     1166    switch (token.type()) {
     1167    case FunctionToken: {
     1168        if (auto number = consumeNumberRawWithKnownTokenTypeFunction(range, symbolTable, valueRange))
     1169            return numberTranformer(*number);
     1170        if (auto percent = consumePercentRawWithKnownTokenTypeFunction(range, symbolTable, valueRange))
     1171            return percentTranformer(*percent);
     1172        break;
     1173    }
     1174
     1175    case PercentageToken:
     1176        if (auto percent = consumePercentRawWithKnownTokenTypePercentage(range, symbolTable, valueRange))
     1177            return percentTranformer(*percent);
     1178        break;
     1179
     1180    case NumberToken:
     1181        if (auto number = consumeNumberRawWithKnownTokenTypeNumber(range, symbolTable, valueRange))
     1182            return numberTranformer(*number);
     1183        break;
     1184
     1185    case IdentToken:
     1186        if (auto variable = symbolTable.get(range.peek().id())) {
     1187            switch (variable->type) {
     1188            case CSSUnitType::CSS_PERCENTAGE:
     1189                if (auto validatedValue = validatedPercentRaw(variable->value, valueRange)) {
     1190                    range.consumeIncludingWhitespace();
     1191                    return percentTranformer(*validatedValue);
     1192                }
     1193                break;
     1194
     1195            case CSSUnitType::CSS_NUMBER:
     1196                if (auto validatedValue = validatedNumberRaw(variable->value, valueRange)) {
     1197                    range.consumeIncludingWhitespace();
     1198                    return numberTranformer(*validatedValue);
     1199                }
     1200                break;
     1201
     1202            default:
     1203                break;
     1204            }
     1205        }
     1206        break;
     1207
     1208    default:
     1209        break;
     1210    }
     1211
     1212    return std::nullopt;
     1213}
     1214
     1215static std::optional<double> consumeNumberRawOrPercentDividedBy100RawAllowingSymbolTableIdent(CSSParserTokenRange& range, const CSSCalcSymbolTable& symbolTable, ValueRange valueRange)
     1216{
     1217    return consumeNumberRawOrPercentRawAllowingSymbolTableIdent(range, symbolTable, valueRange, [](double number) { return number; }, [](double percent) { return percent / 100.0; });
     1218}
     1219
     1220std::optional<double> consumeFontWeightNumberRaw(CSSParserTokenRange& range)
     1221{
     1222    // Values less than or equal to 0 or greater than or equal to 1000 are parse errors.
     1223
     1224#if !ENABLE(VARIATION_FONTS)
     1225    auto isIntegerAndDivisibleBy100 = [](double value) {
     1226        ASSERT(value > 0 && value <= 1000);
     1227        return static_cast<int>(value / 100) * 100 == value;
     1228    };
     1229#endif
     1230
     1231    auto& token = range.peek();
     1232    switch (token.type()) {
     1233    case FunctionToken: {
     1234        // "[For calc()], the used value resulting from an expression must be clamped to the range allowed in the target context."
     1235        auto result = consumeNumberRawWithKnownTokenTypeFunction(range, { }, ValueRange::All);
     1236        if (!result)
     1237            break;
     1238#if !ENABLE(VARIATION_FONTS)
     1239        if (!(*result > 0 && *result < 1000) || !isIntegerAndDivisibleBy100(*result))
     1240            break;
     1241#endif
     1242        return std::clamp(*result, std::nextafter(0.0, 1.0), std::nextafter(1000.0, 0.0));
     1243    }
     1244
     1245    case NumberToken: {
     1246        auto result = token.numericValue();
     1247       
     1248        // FIXME: This allows value of 1000, unlike the comment above and the behavior of the FunctionToken parsing path.
     1249        if (!(result >= 1 && result <= 1000))
     1250            break;
     1251#if !ENABLE(VARIATION_FONTS)
     1252        if (token.numericValueType() != IntegerValueType || !isIntegerAndDivisibleBy100(result))
     1253            break;
     1254#endif
     1255        range.consumeIncludingWhitespace();
     1256        return result;
     1257    }
     1258   
     1259    default:
     1260        break;
     1261    }
     1262
     1263    return std::nullopt;
     1264}
     1265
     1266RefPtr<CSSPrimitiveValue> consumeFontWeightNumber(CSSParserTokenRange& range)
     1267{
     1268    return consumeFontWeightNumberWorkerSafe(range, CSSValuePool::singleton());
     1269}
     1270
     1271RefPtr<CSSPrimitiveValue> consumeFontWeightNumberWorkerSafe(CSSParserTokenRange& range, CSSValuePool& pool)
     1272{
     1273    if (auto result = consumeFontWeightNumberRaw(range))
     1274        return pool.createValue(*result, CSSUnitType::CSS_NUMBER);
    6311275    return nullptr;
    6321276}
     
    6441288}
    6451289
    646 RefPtr<CSSPrimitiveValue> consumeIdentWorkerSafe(CSSParserTokenRange& range, CSSValuePool& cssValuePool)
     1290RefPtr<CSSPrimitiveValue> consumeIdentWorkerSafe(CSSParserTokenRange& range, CSSValuePool& pool)
    6471291{
    6481292    if (auto result = consumeIdentRaw(range))
    649         return cssValuePool.createIdentifierValue(*result);
     1293        return pool.createIdentifierValue(*result);
    6501294    return nullptr;
    6511295}
     
    7021346    }
    7031347
    704     return StringView();
     1348    return { };
    7051349}
    7061350
     
    7391383        return 1.0;
    7401384
    741     if (auto alphaParameter = consumeNumberOrPercentDividedBy100Raw(range))
     1385    if (auto alphaParameter = consumeNumberRawOrPercentDividedBy100Raw(range))
    7421386        return std::clamp(*alphaParameter, 0.0, 1.0);
    7431387
     
    7451389}
    7461390
    747 static std::optional<double> consumeOptionalAlphaOrIdent(CSSParserTokenRange& range, const CSSCalcSymbolTable& symbolTable)
     1391static std::optional<double> consumeOptionalAlphaAllowingSymbolTableIdent(CSSParserTokenRange& range, const CSSCalcSymbolTable& symbolTable)
    7481392{
    7491393    if (!consumeSlashIncludingWhitespace(range))
    7501394        return 1.0;
    7511395
    752     auto normalizePercent = [](double percent) {
    753         return std::clamp(percent / 100.0, 0.0, 1.0);
    754     };
    755 
    756     auto normalizeNumber = [](double alpha) {
    757         return std::clamp(alpha, 0.0, 1.0);
    758     };
    759 
    760     const CSSParserToken& token = range.peek();
    761 
    762     switch (token.type()) {
    763     case FunctionToken: {
    764         CalcParser percentageCalcParser(range, CalculationCategory::Percent, ValueRange::All, symbolTable);
    765         if (auto percent = percentageCalcParser.consumePercentRaw())
    766             return normalizePercent(*percent);
    767        
    768         CalcParser numberCalcParser(range, CalculationCategory::Number, ValueRange::All, symbolTable);
    769         if (auto number = numberCalcParser.consumeNumberRaw())
    770             return normalizeNumber(*number);
    771 
    772         return std::nullopt;
    773     }
    774 
    775     case PercentageToken:
    776         if (std::isinf(token.numericValue()))
    777             return std::nullopt;
    778         return normalizePercent(range.consumeIncludingWhitespace().numericValue());
    779 
    780     case NumberToken:
    781         return normalizeNumber(range.consumeIncludingWhitespace().numericValue());
    782 
    783     case IdentToken:
    784         if (auto variable = symbolTable.get(range.consumeIncludingWhitespace().id())) {
    785             switch (variable->type) {
    786             case CSSUnitType::CSS_PERCENTAGE:
    787                 return normalizePercent(variable->value);
    788 
    789             case CSSUnitType::CSS_NUMBER:
    790                 return normalizeNumber(variable->value);
    791 
    792             default:
    793                 return std::nullopt;
    794             }
    795         }
    796         return std::nullopt;
    797 
    798     default:
    799         return std::nullopt;
    800     }
    801 
     1396    if (auto alphaParameter = consumeNumberRawOrPercentDividedBy100RawAllowingSymbolTableIdent(range, symbolTable, ValueRange::All))
     1397        return std::clamp(*alphaParameter, 0.0, 1.0);
     1398
     1399    return std::nullopt;
     1400}
     1401
     1402static double normalizeHue(double hue)
     1403{
     1404    return std::fmod(std::fmod(hue, 360.0) + 360.0, 360.0);
     1405}
     1406
     1407static uint8_t normalizeRGBComponentNumber(double value)
     1408{
     1409    return convertPrescaledSRGBAFloatToSRGBAByte(value);
     1410}
     1411
     1412static uint8_t normalizeRGBComponentPercentage(double value)
     1413{
     1414    return convertPrescaledSRGBAFloatToSRGBAByte(value / 100.0 * 255.0);
     1415}
     1416
     1417static std::optional<uint8_t> consumeRelativeRGBComponent(CSSParserTokenRange& range, const CSSCalcSymbolTable& symbolTable)
     1418{
     1419    return consumeNumberRawOrPercentRawAllowingSymbolTableIdent(range, symbolTable, ValueRange::All, normalizeRGBComponentNumber, normalizeRGBComponentPercentage);
     1420}
     1421
     1422enum class RGBComponentType { Number, Percentage };
     1423static uint8_t clampRGBComponent(double value, RGBComponentType componentType)
     1424{
     1425    switch (componentType) {
     1426    case RGBComponentType::Number:
     1427        return normalizeRGBComponentNumber(value);
     1428    case RGBComponentType::Percentage:
     1429        return normalizeRGBComponentPercentage(value);
     1430    }
     1431   
    8021432    ASSERT_NOT_REACHED();
    803     return std::nullopt;
    804 }
    805 
    806 static std::optional<double> consumeHue(CSSParserTokenRange& range, const CSSParserContext& context)
    807 {
    808     if (auto angle = consumeAngleRaw(range, context.mode, UnitlessQuirk::Forbid, UnitlessZeroQuirk::Forbid))
    809         return CSSPrimitiveValue::computeDegrees(angle->type, angle->value);
    810 
    811     return consumeNumberRaw(range);
    812 }
    813 
    814 static std::optional<double> consumeHueOrIdent(CSSParserTokenRange& range, const CSSCalcSymbolTable& symbolTable)
    815 {
    816     const CSSParserToken& token = range.peek();
    817 
    818     switch (token.type()) {
    819     case FunctionToken: {
    820         CalcParser angleCalcParser(range, CalculationCategory::Angle, ValueRange::All, symbolTable);
    821         if (auto angle = angleCalcParser.consumeAngleRaw())
    822             return CSSPrimitiveValue::computeDegrees(angle->type, angle->value);
    823        
    824         CalcParser numberCalcParser(range, CalculationCategory::Number, ValueRange::All, symbolTable);
    825         return numberCalcParser.consumeNumberRaw();
    826     }
    827    
    828     case DimensionToken: {
    829         auto unitType = token.unitType();
    830         switch (unitType) {
    831         case CSSUnitType::CSS_DEG:
    832         case CSSUnitType::CSS_RAD:
    833         case CSSUnitType::CSS_GRAD:
    834         case CSSUnitType::CSS_TURN:
    835             return CSSPrimitiveValue::computeDegrees(unitType, range.consumeIncludingWhitespace().numericValue());
    836         default:
    837             return std::nullopt;
    838         }
    839     }
    840    
    841     case NumberToken:
    842         return range.consumeIncludingWhitespace().numericValue();
    843 
    844     case IdentToken:
    845         if (auto variable = symbolTable.get(range.consumeIncludingWhitespace().id())) {
    846             switch (variable->type) {
    847             case CSSUnitType::CSS_DEG:
    848             case CSSUnitType::CSS_RAD:
    849             case CSSUnitType::CSS_GRAD:
    850             case CSSUnitType::CSS_TURN:
    851                 return CSSPrimitiveValue::computeDegrees(variable->type, variable->value);
    852 
    853             case CSSUnitType::CSS_NUMBER:
    854                 return variable->value;
    855 
    856             default:
    857                 return std::nullopt;
    858             }
    859         }
    860         return std::nullopt;
    861 
    862     default:
    863         return std::nullopt;
    864     }
    865 
    866     ASSERT_NOT_REACHED();
    867     return std::nullopt;
    868 }
    869 
    870 static double normalizeHue(double hue)
    871 {
    872     return std::fmod(std::fmod(hue, 360.0) + 360.0, 360.0);
    873 }
    874 
    875 static std::optional<double> consumeNumberOrIdent(CSSParserTokenRange& range, const CSSCalcSymbolTable& symbolTable)
    876 {
    877     const CSSParserToken& token = range.peek();
    878 
    879     switch (token.type()) {
    880     case FunctionToken: {
    881         CalcParser calcParser(range, CalculationCategory::Number, ValueRange::All, symbolTable);
    882         return calcParser.consumeNumberRaw();
    883     }
    884 
    885     case NumberToken:
    886         return range.consumeIncludingWhitespace().numericValue();
    887 
    888     case IdentToken:
    889         if (auto variable = symbolTable.get(range.consumeIncludingWhitespace().id())) {
    890             switch (variable->type) {
    891             case CSSUnitType::CSS_NUMBER:
    892                 return variable->value;
    893 
    894             default:
    895                 return std::nullopt;
    896             }
    897         }
    898         return std::nullopt;
    899 
    900     default:
    901         return std::nullopt;
    902     }
    903 
    904     ASSERT_NOT_REACHED();
    905     return std::nullopt;
    906 }
    907 
    908 static std::optional<double> consumePercentOrIdent(CSSParserTokenRange& range, const CSSCalcSymbolTable& symbolTable)
    909 {
    910     const CSSParserToken& token = range.peek();
    911 
    912     switch (token.type()) {
    913     case FunctionToken: {
    914         CalcParser calcParser(range, CalculationCategory::Percent, ValueRange::All, symbolTable);
    915         return calcParser.consumePercentRaw();
    916     }
    917 
    918     case PercentageToken:
    919         if (std::isinf(token.numericValue()))
    920             return std::nullopt;
    921         return range.consumeIncludingWhitespace().numericValue();
    922 
    923     case IdentToken:
    924         if (auto variable = symbolTable.get(range.consumeIncludingWhitespace().id())) {
    925             switch (variable->type) {
    926             case CSSUnitType::CSS_PERCENTAGE:
    927                 return variable->value;
    928 
    929             default:
    930                 return std::nullopt;
    931             }
    932         }
    933         return std::nullopt;
    934 
    935     default:
    936         return std::nullopt;
    937     }
    938 
    939     ASSERT_NOT_REACHED();
    940     return std::nullopt;
    941 }
    942 
    943 enum class RGBComponentType { Number, Percentage };
    944 
    945 static std::optional<uint8_t> consumeNumberOrPercentOrIdentNormalizedForRelativeRGB(CSSParserTokenRange& range, const CSSCalcSymbolTable& symbolTable)
    946 {
    947     auto normalizePercent = [](double percent) {
    948         return convertPrescaledSRGBAFloatToSRGBAByte(percent / 100.0 * 255.0);
    949     };
    950 
    951     auto normalizeNumber = [](double number) {
    952         return convertPrescaledSRGBAFloatToSRGBAByte(number);
    953     };
    954 
    955     const CSSParserToken& token = range.peek();
    956 
    957     switch (token.type()) {
    958     case FunctionToken: {
    959         CalcParser percentageCalcParser(range, CalculationCategory::Percent, ValueRange::All, symbolTable);
    960         if (auto percent = percentageCalcParser.consumePercentRaw())
    961             return normalizePercent(*percent);
    962        
    963         CalcParser numberCalcParser(range, CalculationCategory::Number, ValueRange::All, symbolTable);
    964         if (auto number = numberCalcParser.consumeNumberRaw())
    965             return normalizeNumber(*number);
    966        
    967         return std::nullopt;
    968     }
    969 
    970     case PercentageToken:
    971         if (std::isinf(token.numericValue()))
    972             return std::nullopt;
    973         return normalizePercent(range.consumeIncludingWhitespace().numericValue());
    974 
    975     case NumberToken:
    976         return normalizeNumber(range.consumeIncludingWhitespace().numericValue());
    977 
    978     case IdentToken:
    979         if (auto variable = symbolTable.get(range.consumeIncludingWhitespace().id())) {
    980             switch (variable->type) {
    981             case CSSUnitType::CSS_PERCENTAGE:
    982                 return normalizePercent(variable->value);
    983 
    984             case CSSUnitType::CSS_NUMBER:
    985                 return normalizeNumber(variable->value);
    986 
    987             default:
    988                 return std::nullopt;
    989             }
    990         }
    991         return std::nullopt;
    992 
    993     default:
    994         return std::nullopt;
    995     }
    996 
    997     ASSERT_NOT_REACHED();
    998     return std::nullopt;
    999 }
    1000 
    1001 static uint8_t clampRGBComponent(double value, RGBComponentType componentType)
    1002 {
    1003     if (componentType == RGBComponentType::Percentage)
    1004         value = value / 100.0 * 255.0;
    1005 
    1006     return convertPrescaledSRGBAFloatToSRGBAByte(value);
     1433    return 0;
    10071434}
    10081435
     
    10281455        return 1.0;
    10291456
    1030     return consumeNumberOrPercentDividedBy100Raw(args);
    1031 }
    1032 
    1033 struct RelativeRGBComponent {
    1034     Variant<double, CSSValueID> value;
    1035     std::optional<RGBComponentType> type;
    1036 };
    1037 
    1038 template<CSSValueID C> static std::optional<RelativeRGBComponent> consumeRelativeRGBComponent(CSSParserTokenRange& args, std::optional<RGBComponentType> componentType)
    1039 {
    1040     if (!componentType) {
    1041         if (auto number = consumeNumberRaw(args))
    1042             return RelativeRGBComponent { *number, RGBComponentType::Number };
    1043         if (auto percent = consumePercentRaw(args))
    1044             return RelativeRGBComponent { *percent, RGBComponentType::Percentage };
    1045         if (auto channel = consumeIdentRaw<C>(args))
    1046             return RelativeRGBComponent { *channel, std::nullopt };
    1047         return std::nullopt;
    1048     }
    1049 
    1050     switch (*componentType) {
    1051     case RGBComponentType::Number: {
    1052         if (auto number = consumeNumberRaw(args))
    1053             return RelativeRGBComponent { *number, RGBComponentType::Number };
    1054         if (auto channel = consumeIdentRaw<C>(args))
    1055             return RelativeRGBComponent { *channel, RGBComponentType::Number };
    1056         return std::nullopt;
    1057     }
    1058     case RGBComponentType::Percentage: {
    1059         if (auto percent = consumePercentRaw(args))
    1060             return RelativeRGBComponent { *percent, RGBComponentType::Percentage };
    1061         if (auto channel = consumeIdentRaw<C>(args))
    1062             return RelativeRGBComponent { *channel, RGBComponentType::Percentage };
    1063         return std::nullopt;
    1064     }
    1065     }
    1066 
    1067     RELEASE_ASSERT_NOT_REACHED();
     1457    return consumeNumberRawOrPercentDividedBy100Raw(args);
    10681458}
    10691459
     
    10861476    };
    10871477
    1088     auto red = consumeNumberOrPercentOrIdentNormalizedForRelativeRGB(args, symbolTable);
     1478    auto red = consumeRelativeRGBComponent(args, symbolTable);
    10891479    if (!red)
    10901480        return { };
    10911481
    1092     auto green = consumeNumberOrPercentOrIdentNormalizedForRelativeRGB(args, symbolTable);
     1482    auto green = consumeRelativeRGBComponent(args, symbolTable);
    10931483    if (!green)
    10941484        return { };
    10951485
    1096     auto blue = consumeNumberOrPercentOrIdentNormalizedForRelativeRGB(args, symbolTable);
     1486    auto blue = consumeRelativeRGBComponent(args, symbolTable);
    10971487    if (!blue)
    10981488        return { };
    10991489
    1100     auto alpha = consumeOptionalAlphaOrIdent(args, symbolTable);
     1490    auto alpha = consumeOptionalAlphaAllowingSymbolTableIdent(args, symbolTable);
    11011491    if (!alpha)
    11021492        return { };
     
    11981588    };
    11991589
    1200     auto hue = consumeHueOrIdent(args, symbolTable);
     1590    auto hue = consumeAngleRawOrNumberRawAllowingSymbolTableIdent(args, symbolTable, context.mode);
    12011591    if (!hue)
    12021592        return { };
    12031593
    1204     auto saturation = consumePercentOrIdent(args, symbolTable);
     1594    auto saturation = consumePercentAllowingSymbolTableIdent(args, symbolTable);
    12051595    if (!saturation)
    12061596        return { };
    12071597
    1208     auto lightness = consumePercentOrIdent(args, symbolTable);
     1598    auto lightness = consumePercentAllowingSymbolTableIdent(args, symbolTable);
    12091599    if (!lightness)
    12101600        return { };
    12111601
    1212     auto alpha = consumeOptionalAlphaOrIdent(args, symbolTable);
     1602    auto alpha = consumeOptionalAlphaAllowingSymbolTableIdent(args, symbolTable);
    12131603    if (!alpha)
    12141604        return { };
     
    12371627    }
    12381628
    1239     auto hue = consumeHue(args, context);
     1629    auto hue = consumeAngleRawOrNumberRaw(args, context.mode);
    12401630    if (!hue)
    12411631        return { };
     
    13121702    };
    13131703
    1314     auto hue = consumeHueOrIdent(args, symbolTable);
     1704    auto hue = consumeAngleRawOrNumberRawAllowingSymbolTableIdent(args, symbolTable, context.mode);
    13151705    if (!hue)
    13161706        return { };
    13171707
    1318     auto whiteness = consumePercentOrIdent(args, symbolTable);
     1708    auto whiteness = consumePercentAllowingSymbolTableIdent(args, symbolTable);
    13191709    if (!whiteness)
    13201710        return { };
    13211711
    1322     auto blackness = consumePercentOrIdent(args, symbolTable);
     1712    auto blackness = consumePercentAllowingSymbolTableIdent(args, symbolTable);
    13231713    if (!blackness)
    13241714        return { };
    13251715
    1326     auto alpha = consumeOptionalAlphaOrIdent(args, symbolTable);
     1716    auto alpha = consumeOptionalAlphaAllowingSymbolTableIdent(args, symbolTable);
    13271717    if (!alpha)
    13281718        return { };
     
    13491739        return parseRelativeHWBParameters(args, context);
    13501740
    1351     auto hue = consumeHue(args, context);
     1741    auto hue = consumeAngleRawOrNumberRaw(args, context.mode);
    13521742    if (!hue)
    13531743        return { };
     
    13921782    };
    13931783
    1394     auto lightness = consumePercentOrIdent(args, symbolTable);
     1784    auto lightness = consumePercentAllowingSymbolTableIdent(args, symbolTable);
    13951785    if (!lightness)
    13961786        return { };
    13971787
    1398     auto aValue = consumeNumberOrIdent(args, symbolTable);
     1788    auto aValue = consumeNumberAllowingSymbolTableIdent(args, symbolTable);
    13991789    if (!aValue)
    14001790        return { };
    14011791
    1402     auto bValue = consumeNumberOrIdent(args, symbolTable);
     1792    auto bValue = consumeNumberAllowingSymbolTableIdent(args, symbolTable);
    14031793    if (!bValue)
    14041794        return { };
    14051795
    1406     auto alpha = consumeOptionalAlphaOrIdent(args, symbolTable);
     1796    auto alpha = consumeOptionalAlphaAllowingSymbolTableIdent(args, symbolTable);
    14071797    if (!alpha)
    14081798        return { };
     
    14701860    };
    14711861
    1472     auto lightness = consumePercentOrIdent(args, symbolTable);
     1862    auto lightness = consumePercentAllowingSymbolTableIdent(args, symbolTable);
    14731863    if (!lightness)
    14741864        return { };
    14751865
    1476     auto chroma = consumeNumberOrIdent(args, symbolTable);
     1866    auto chroma = consumeNumberAllowingSymbolTableIdent(args, symbolTable);
    14771867    if (!chroma)
    14781868        return { };
    14791869
    1480     auto hue = consumeHueOrIdent(args, symbolTable);
     1870    auto hue = consumeAngleRawOrNumberRawAllowingSymbolTableIdent(args, symbolTable, context.mode);
    14811871    if (!hue)
    14821872        return { };
    14831873
    1484     auto alpha = consumeOptionalAlphaOrIdent(args, symbolTable);
     1874    auto alpha = consumeOptionalAlphaAllowingSymbolTableIdent(args, symbolTable);
    14851875    if (!alpha)
    14861876        return { };
     
    15161906        return { };
    15171907
    1518     auto hue = consumeHue(args, context);
     1908    auto hue = consumeAngleRawOrNumberRaw(args, context.mode);
    15191909    if (!hue)
    15201910        return { };
     
    15461936    double channels[3] = { 0, 0, 0 };
    15471937    for (int i = 0; i < 3; ++i) {
    1548         auto value = consumeNumberOrPercentDividedBy100Raw(args);
     1938        auto value = consumeNumberRawOrPercentDividedBy100Raw(args);
    15491939        if (!value)
    15501940            break;
     
    20732463}
    20742464
    2075 static RefPtr<CSSPrimitiveValue> consumePositionComponent(CSSParserTokenRange& range, CSSParserMode cssParserMode, UnitlessQuirk unitless)
     2465static RefPtr<CSSPrimitiveValue> consumePositionComponent(CSSParserTokenRange& range, CSSParserMode parserMode, UnitlessQuirk unitless)
    20762466{
    20772467    if (range.peek().type() == IdentToken)
    20782468        return consumeIdent<CSSValueLeft, CSSValueTop, CSSValueBottom, CSSValueRight, CSSValueCenter>(range);
    2079     return consumeLengthOrPercent(range, cssParserMode, ValueRange::All, unitless);
     2469    return consumeLengthOrPercent(range, parserMode, ValueRange::All, unitless);
    20802470}
    20812471
     
    22262616// FIXME: This may consume from the range upon failure. The background
    22272617// shorthand works around it, but we should just fix it here.
    2228 std::optional<PositionCoordinates> consumePositionCoordinates(CSSParserTokenRange& range, CSSParserMode cssParserMode, UnitlessQuirk unitless, PositionSyntax positionSyntax)
    2229 {
    2230     auto value1 = consumePositionComponent(range, cssParserMode, unitless);
     2618std::optional<PositionCoordinates> consumePositionCoordinates(CSSParserTokenRange& range, CSSParserMode parserMode, UnitlessQuirk unitless, PositionSyntax positionSyntax)
     2619{
     2620    auto value1 = consumePositionComponent(range, parserMode, unitless);
    22312621    if (!value1)
    22322622        return std::nullopt;
    22332623
    2234     auto value2 = consumePositionComponent(range, cssParserMode, unitless);
     2624    auto value2 = consumePositionComponent(range, parserMode, unitless);
    22352625    if (!value2)
    22362626        return positionFromOneValue(*value1);
    22372627
    2238     auto value3 = consumePositionComponent(range, cssParserMode, unitless);
     2628    auto value3 = consumePositionComponent(range, parserMode, unitless);
    22392629    if (!value3)
    22402630        return positionFromTwoValues(*value1, *value2);
    22412631
    2242     auto value4 = consumePositionComponent(range, cssParserMode, unitless);
     2632    auto value4 = consumePositionComponent(range, parserMode, unitless);
    22432633   
    22442634    std::array<CSSPrimitiveValue*, 5> values {
     
    22592649}
    22602650
    2261 RefPtr<CSSPrimitiveValue> consumePosition(CSSParserTokenRange& range, CSSParserMode cssParserMode, UnitlessQuirk unitless, PositionSyntax positionSyntax)
    2262 {
    2263     if (auto coordinates = consumePositionCoordinates(range, cssParserMode, unitless, positionSyntax))
     2651RefPtr<CSSPrimitiveValue> consumePosition(CSSParserTokenRange& range, CSSParserMode parserMode, UnitlessQuirk unitless, PositionSyntax positionSyntax)
     2652{
     2653    if (auto coordinates = consumePositionCoordinates(range, parserMode, unitless, positionSyntax))
    22642654        return CSSPropertyParserHelpersInternal::createPrimitiveValuePair(WTFMove(coordinates->x), WTFMove(coordinates->y));
    22652655    return nullptr;
    22662656}
    22672657
    2268 std::optional<PositionCoordinates> consumeOneOrTwoValuedPositionCoordinates(CSSParserTokenRange& range, CSSParserMode cssParserMode, UnitlessQuirk unitless)
    2269 {
    2270     auto value1 = consumePositionComponent(range, cssParserMode, unitless);
     2658std::optional<PositionCoordinates> consumeOneOrTwoValuedPositionCoordinates(CSSParserTokenRange& range, CSSParserMode parserMode, UnitlessQuirk unitless)
     2659{
     2660    auto value1 = consumePositionComponent(range, parserMode, unitless);
    22712661    if (!value1)
    22722662        return std::nullopt;
    2273     auto value2 = consumePositionComponent(range, cssParserMode, unitless);
     2663    auto value2 = consumePositionComponent(range, parserMode, unitless);
    22742664    if (!value2)
    22752665        return positionFromOneValue(*value1);
     
    23152705    } else {
    23162706        ASSERT(id == CSSValueColorStop);
    2317         auto value = consumeNumberOrPercentDividedBy100Raw(args);
     2707        auto value = consumeNumberRawOrPercentDividedBy100Raw(args);
    23182708        if (!value)
    23192709            return false;
     
    26643054        return nullptr;
    26653055
    2666     auto percentage = consumeNumberOrPercentDividedBy100Raw(args);
     3056    auto percentage = consumeNumberRawOrPercentDividedBy100Raw(args);
    26673057    if (!percentage)
    26683058        return nullptr;
     
    31063496}
    31073497
    3108 std::optional<FontStyleRaw> consumeFontStyleRaw(CSSParserTokenRange& range, CSSParserMode cssParserMode)
     3498std::optional<FontStyleRaw> consumeFontStyleRaw(CSSParserTokenRange& range, CSSParserMode parserMode)
    31093499{
    31103500    auto result = consumeFontStyleKeywordValueRaw(range);
     
    31193509    if (!range.atEnd()) {
    31203510        // FIXME: This angle does specify that unitless 0 is allowed - see https://drafts.csswg.org/css-fonts-4/#valdef-font-style-oblique-angle
    3121         if (auto angle = consumeAngleRaw(range, cssParserMode, UnitlessQuirk::Forbid, UnitlessZeroQuirk::Allow)) {
     3511        if (auto angle = consumeAngleRaw(range, parserMode, UnitlessQuirk::Forbid, UnitlessZeroQuirk::Allow)) {
    31223512            if (isFontStyleAngleInRange(CSSPrimitiveValue::computeDegrees(angle->type, angle->value)))
    31233513                return { { CSSValueOblique, WTFMove(angle) } };
     
    31263516    }
    31273517#else
    3128     UNUSED_PARAM(cssParserMode);
     3518    UNUSED_PARAM(parserMode);
    31293519#endif
    31303520    return { { CSSValueOblique, std::nullopt } };
     
    31783568}
    31793569
    3180 std::optional<FontSizeRaw> consumeFontSizeRaw(CSSParserTokenRange& range, CSSParserMode cssParserMode, UnitlessQuirk unitless)
     3570std::optional<FontSizeRaw> consumeFontSizeRaw(CSSParserTokenRange& range, CSSParserMode parserMode, UnitlessQuirk unitless)
    31813571{
    31823572    if (range.peek().id() >= CSSValueXxSmall && range.peek().id() <= CSSValueLarger) {
     
    31863576    }
    31873577
    3188     if (auto result = consumeLengthOrPercentRaw(range, cssParserMode, ValueRange::NonNegative, unitless))
     3578    if (auto result = consumeLengthOrPercentRaw(range, parserMode, ValueRange::NonNegative, unitless))
    31893579        return { *result };
    31903580
     
    31923582}
    31933583
    3194 std::optional<LineHeightRaw> consumeLineHeightRaw(CSSParserTokenRange& range, CSSParserMode cssParserMode)
     3584std::optional<LineHeightRaw> consumeLineHeightRaw(CSSParserTokenRange& range, CSSParserMode parserMode)
    31953585{
    31963586    if (range.peek().id() == CSSValueNormal) {
     
    32033593        return { *number };
    32043594
    3205     if (auto lengthOrPercent = consumeLengthOrPercentRaw(range, cssParserMode, ValueRange::NonNegative))
     3595    if (auto lengthOrPercent = consumeLengthOrPercentRaw(range, parserMode, ValueRange::NonNegative))
    32063596        return { *lengthOrPercent };
    32073597
     
    32093599}
    32103600
    3211 std::optional<FontRaw> consumeFontRaw(CSSParserTokenRange& range, CSSParserMode cssParserMode)
     3601std::optional<FontRaw> consumeFontRaw(CSSParserTokenRange& range, CSSParserMode parserMode)
    32123602{
    32133603    // Let's check if there is an inherit or initial somewhere in the shorthand.
     
    32243614        CSSValueID id = range.peek().id();
    32253615        if (!result.style) {
    3226             if ((result.style = consumeFontStyleRaw(range, cssParserMode)))
     3616            if ((result.style = consumeFontStyleRaw(range, parserMode)))
    32273617                continue;
    32283618        }
     
    32483638
    32493639    // Now a font size _must_ come.
    3250     if (auto size = consumeFontSizeRaw(range, cssParserMode))
     3640    if (auto size = consumeFontSizeRaw(range, parserMode))
    32513641        result.size = *size;
    32523642    else
     
    32573647
    32583648    if (consumeSlashIncludingWhitespace(range)) {
    3259         if (!(result.lineHeight = consumeLineHeightRaw(range, cssParserMode)))
     3649        if (!(result.lineHeight = consumeLineHeightRaw(range, parserMode)))
    32603650            return std::nullopt;
    32613651    }
Note: See TracChangeset for help on using the changeset viewer.