Changeset 278311 in webkit
- Timestamp:
- Jun 1, 2021, 9:49:09 AM (5 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 3 edited
-
ChangeLog (modified) (1 diff)
-
css/parser/CSSParserMode.h (modified) (1 diff)
-
css/parser/CSSPropertyParserHelpers.cpp (modified) (37 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r278309 r278311 1 2021-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 1 119 2021-06-01 Chris Dumez <cdumez@apple.com> 2 120 -
trunk/Source/WebCore/css/parser/CSSParserMode.h
r255151 r278311 58 58 } 59 59 60 inline bool isUnit LessValueParsingEnabledForMode(CSSParserMode mode)60 inline bool isUnitlessValueParsingEnabledForMode(CSSParserMode mode) 61 61 { 62 62 return mode == SVGAttributeMode; -
trunk/Source/WebCore/css/parser/CSSPropertyParserHelpers.cpp
r278304 r278311 89 89 } 90 90 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; 91 inline 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 104 static 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; 98 116 } 99 117 … … 101 119 class CalcParser { 102 120 public: 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()) 104 122 : m_sourceRange(range) 105 123 , m_range(range) 106 , m_ valuePool(cssValuePool)124 , m_pool(pool) 107 125 { 108 126 const CSSParserToken& token = range.peek(); … … 119 137 return nullptr; 120 138 m_sourceRange = m_range; 121 return m_ valuePool.createValue(WTFMove(m_calcValue));139 return m_pool.createValue(WTFMove(m_calcValue)); 122 140 } 123 141 … … 127 145 return nullptr; 128 146 m_sourceRange = m_range; 129 return m_ valuePool.createValue(WTFMove(m_calcValue));147 return m_pool.createValue(WTFMove(m_calcValue)); 130 148 } 131 149 … … 135 153 return nullptr; 136 154 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); 138 156 } 139 157 … … 151 169 return nullptr; 152 170 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); 154 172 } 155 173 … … 212 230 CSSParserTokenRange m_range; 213 231 RefPtr<CSSCalcValue> m_calcValue; 214 CSSValuePool& m_ valuePool;232 CSSValuePool& m_pool; 215 233 }; 216 234 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 239 template<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 250 template<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) 227 255 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 261 template<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 270 template<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 281 static 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 288 static 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 296 static 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 } 233 304 return std::nullopt; 234 305 } 235 306 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: 307 static 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 } 375 318 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 561 320 default: 562 321 break; 563 322 } 564 break; 323 } 324 return std::nullopt; 325 } 326 327 // MARK: Number (CSSPrimitiveValue - maintaing calc) 328 329 static 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 337 static 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 354 static 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 363 static 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 371 static 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 382 static 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 405 static 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 413 static 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 426 static 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 435 static 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 443 static 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 484 static 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 502 static 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 510 static 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 519 static 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 530 static 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 538 static 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 556 static 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 567 static 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 575 static 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 584 static 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 596 static 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 604 static 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 617 static 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 631 static 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 646 template<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 664 template<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 682 std::optional<int> consumeIntegerRaw(CSSParserTokenRange& range, double minimumValue) 683 { 684 return consumeIntegerTypeRaw<int>(range, minimumValue); 685 } 686 687 RefPtr<CSSPrimitiveValue> consumeInteger(CSSParserTokenRange& range, double minimumValue) 688 { 689 return consumeIntegerType<int>(range, minimumValue, CSSValuePool::singleton()); 690 } 691 692 std::optional<unsigned> consumePositiveIntegerRaw(CSSParserTokenRange& range) 693 { 694 return consumeIntegerTypeRaw<unsigned>(range, 1); 695 } 696 697 RefPtr<CSSPrimitiveValue> consumePositiveInteger(CSSParserTokenRange& range) 698 { 699 return consumeIntegerType<unsigned>(range, 1, CSSValuePool::singleton()); 700 } 701 702 std::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 720 RefPtr<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 738 std::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); 565 748 566 749 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 759 RefPtr<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 780 std::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); 570 787 571 788 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 798 RefPtr<CSSPrimitiveValue> consumePercent(CSSParserTokenRange& range, ValueRange valueRange) 799 { 800 return consumePercentWorkerSafe(range, valueRange, CSSValuePool::singleton()); 801 } 802 803 RefPtr<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 821 std::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 843 RefPtr<CSSPrimitiveValue> consumeAngle(CSSParserTokenRange& range, CSSParserMode parserMode, UnitlessQuirk unitless, UnitlessZeroQuirk unitlessZero) 844 { 845 return consumeAngleWorkerSafe(range, parserMode, CSSValuePool::singleton(), unitless, unitlessZero); 846 } 847 848 RefPtr<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); 589 861 590 862 default: 591 863 break; 592 864 } 593 865 594 866 return nullptr; 595 867 } 596 868 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); 869 RefPtr<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; 617 888 } 618 889 619 890 RefPtr<CSSPrimitiveValue> consumeResolution(CSSParserTokenRange& range, AllowXResolutionUnit allowX) 620 891 { 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 909 static 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 935 std::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 970 RefPtr<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 1001 static 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 1022 static 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 1043 static 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 1072 static 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 1123 template<typename NumberTransformer, typename PercentTransformer> 1124 static 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 1154 static 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 1161 template<typename NumberTransformer, typename PercentTransformer> 1162 static 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 1215 static 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 1220 std::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 1266 RefPtr<CSSPrimitiveValue> consumeFontWeightNumber(CSSParserTokenRange& range) 1267 { 1268 return consumeFontWeightNumberWorkerSafe(range, CSSValuePool::singleton()); 1269 } 1270 1271 RefPtr<CSSPrimitiveValue> consumeFontWeightNumberWorkerSafe(CSSParserTokenRange& range, CSSValuePool& pool) 1272 { 1273 if (auto result = consumeFontWeightNumberRaw(range)) 1274 return pool.createValue(*result, CSSUnitType::CSS_NUMBER); 631 1275 return nullptr; 632 1276 } … … 644 1288 } 645 1289 646 RefPtr<CSSPrimitiveValue> consumeIdentWorkerSafe(CSSParserTokenRange& range, CSSValuePool& cssValuePool)1290 RefPtr<CSSPrimitiveValue> consumeIdentWorkerSafe(CSSParserTokenRange& range, CSSValuePool& pool) 647 1291 { 648 1292 if (auto result = consumeIdentRaw(range)) 649 return cssValuePool.createIdentifierValue(*result);1293 return pool.createIdentifierValue(*result); 650 1294 return nullptr; 651 1295 } … … 702 1346 } 703 1347 704 return StringView();1348 return { }; 705 1349 } 706 1350 … … 739 1383 return 1.0; 740 1384 741 if (auto alphaParameter = consumeNumber OrPercentDividedBy100Raw(range))1385 if (auto alphaParameter = consumeNumberRawOrPercentDividedBy100Raw(range)) 742 1386 return std::clamp(*alphaParameter, 0.0, 1.0); 743 1387 … … 745 1389 } 746 1390 747 static std::optional<double> consumeOptionalAlpha OrIdent(CSSParserTokenRange& range, const CSSCalcSymbolTable& symbolTable)1391 static std::optional<double> consumeOptionalAlphaAllowingSymbolTableIdent(CSSParserTokenRange& range, const CSSCalcSymbolTable& symbolTable) 748 1392 { 749 1393 if (!consumeSlashIncludingWhitespace(range)) 750 1394 return 1.0; 751 1395 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 1402 static double normalizeHue(double hue) 1403 { 1404 return std::fmod(std::fmod(hue, 360.0) + 360.0, 360.0); 1405 } 1406 1407 static uint8_t normalizeRGBComponentNumber(double value) 1408 { 1409 return convertPrescaledSRGBAFloatToSRGBAByte(value); 1410 } 1411 1412 static uint8_t normalizeRGBComponentPercentage(double value) 1413 { 1414 return convertPrescaledSRGBAFloatToSRGBAByte(value / 100.0 * 255.0); 1415 } 1416 1417 static std::optional<uint8_t> consumeRelativeRGBComponent(CSSParserTokenRange& range, const CSSCalcSymbolTable& symbolTable) 1418 { 1419 return consumeNumberRawOrPercentRawAllowingSymbolTableIdent(range, symbolTable, ValueRange::All, normalizeRGBComponentNumber, normalizeRGBComponentPercentage); 1420 } 1421 1422 enum class RGBComponentType { Number, Percentage }; 1423 static 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 802 1432 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; 1007 1434 } 1008 1435 … … 1028 1455 return 1.0; 1029 1456 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); 1068 1458 } 1069 1459 … … 1086 1476 }; 1087 1477 1088 auto red = consume NumberOrPercentOrIdentNormalizedForRelativeRGB(args, symbolTable);1478 auto red = consumeRelativeRGBComponent(args, symbolTable); 1089 1479 if (!red) 1090 1480 return { }; 1091 1481 1092 auto green = consume NumberOrPercentOrIdentNormalizedForRelativeRGB(args, symbolTable);1482 auto green = consumeRelativeRGBComponent(args, symbolTable); 1093 1483 if (!green) 1094 1484 return { }; 1095 1485 1096 auto blue = consume NumberOrPercentOrIdentNormalizedForRelativeRGB(args, symbolTable);1486 auto blue = consumeRelativeRGBComponent(args, symbolTable); 1097 1487 if (!blue) 1098 1488 return { }; 1099 1489 1100 auto alpha = consumeOptionalAlpha OrIdent(args, symbolTable);1490 auto alpha = consumeOptionalAlphaAllowingSymbolTableIdent(args, symbolTable); 1101 1491 if (!alpha) 1102 1492 return { }; … … 1198 1588 }; 1199 1589 1200 auto hue = consume HueOrIdent(args, symbolTable);1590 auto hue = consumeAngleRawOrNumberRawAllowingSymbolTableIdent(args, symbolTable, context.mode); 1201 1591 if (!hue) 1202 1592 return { }; 1203 1593 1204 auto saturation = consumePercent OrIdent(args, symbolTable);1594 auto saturation = consumePercentAllowingSymbolTableIdent(args, symbolTable); 1205 1595 if (!saturation) 1206 1596 return { }; 1207 1597 1208 auto lightness = consumePercent OrIdent(args, symbolTable);1598 auto lightness = consumePercentAllowingSymbolTableIdent(args, symbolTable); 1209 1599 if (!lightness) 1210 1600 return { }; 1211 1601 1212 auto alpha = consumeOptionalAlpha OrIdent(args, symbolTable);1602 auto alpha = consumeOptionalAlphaAllowingSymbolTableIdent(args, symbolTable); 1213 1603 if (!alpha) 1214 1604 return { }; … … 1237 1627 } 1238 1628 1239 auto hue = consume Hue(args, context);1629 auto hue = consumeAngleRawOrNumberRaw(args, context.mode); 1240 1630 if (!hue) 1241 1631 return { }; … … 1312 1702 }; 1313 1703 1314 auto hue = consume HueOrIdent(args, symbolTable);1704 auto hue = consumeAngleRawOrNumberRawAllowingSymbolTableIdent(args, symbolTable, context.mode); 1315 1705 if (!hue) 1316 1706 return { }; 1317 1707 1318 auto whiteness = consumePercent OrIdent(args, symbolTable);1708 auto whiteness = consumePercentAllowingSymbolTableIdent(args, symbolTable); 1319 1709 if (!whiteness) 1320 1710 return { }; 1321 1711 1322 auto blackness = consumePercent OrIdent(args, symbolTable);1712 auto blackness = consumePercentAllowingSymbolTableIdent(args, symbolTable); 1323 1713 if (!blackness) 1324 1714 return { }; 1325 1715 1326 auto alpha = consumeOptionalAlpha OrIdent(args, symbolTable);1716 auto alpha = consumeOptionalAlphaAllowingSymbolTableIdent(args, symbolTable); 1327 1717 if (!alpha) 1328 1718 return { }; … … 1349 1739 return parseRelativeHWBParameters(args, context); 1350 1740 1351 auto hue = consume Hue(args, context);1741 auto hue = consumeAngleRawOrNumberRaw(args, context.mode); 1352 1742 if (!hue) 1353 1743 return { }; … … 1392 1782 }; 1393 1783 1394 auto lightness = consumePercent OrIdent(args, symbolTable);1784 auto lightness = consumePercentAllowingSymbolTableIdent(args, symbolTable); 1395 1785 if (!lightness) 1396 1786 return { }; 1397 1787 1398 auto aValue = consumeNumber OrIdent(args, symbolTable);1788 auto aValue = consumeNumberAllowingSymbolTableIdent(args, symbolTable); 1399 1789 if (!aValue) 1400 1790 return { }; 1401 1791 1402 auto bValue = consumeNumber OrIdent(args, symbolTable);1792 auto bValue = consumeNumberAllowingSymbolTableIdent(args, symbolTable); 1403 1793 if (!bValue) 1404 1794 return { }; 1405 1795 1406 auto alpha = consumeOptionalAlpha OrIdent(args, symbolTable);1796 auto alpha = consumeOptionalAlphaAllowingSymbolTableIdent(args, symbolTable); 1407 1797 if (!alpha) 1408 1798 return { }; … … 1470 1860 }; 1471 1861 1472 auto lightness = consumePercent OrIdent(args, symbolTable);1862 auto lightness = consumePercentAllowingSymbolTableIdent(args, symbolTable); 1473 1863 if (!lightness) 1474 1864 return { }; 1475 1865 1476 auto chroma = consumeNumber OrIdent(args, symbolTable);1866 auto chroma = consumeNumberAllowingSymbolTableIdent(args, symbolTable); 1477 1867 if (!chroma) 1478 1868 return { }; 1479 1869 1480 auto hue = consume HueOrIdent(args, symbolTable);1870 auto hue = consumeAngleRawOrNumberRawAllowingSymbolTableIdent(args, symbolTable, context.mode); 1481 1871 if (!hue) 1482 1872 return { }; 1483 1873 1484 auto alpha = consumeOptionalAlpha OrIdent(args, symbolTable);1874 auto alpha = consumeOptionalAlphaAllowingSymbolTableIdent(args, symbolTable); 1485 1875 if (!alpha) 1486 1876 return { }; … … 1516 1906 return { }; 1517 1907 1518 auto hue = consume Hue(args, context);1908 auto hue = consumeAngleRawOrNumberRaw(args, context.mode); 1519 1909 if (!hue) 1520 1910 return { }; … … 1546 1936 double channels[3] = { 0, 0, 0 }; 1547 1937 for (int i = 0; i < 3; ++i) { 1548 auto value = consumeNumber OrPercentDividedBy100Raw(args);1938 auto value = consumeNumberRawOrPercentDividedBy100Raw(args); 1549 1939 if (!value) 1550 1940 break; … … 2073 2463 } 2074 2464 2075 static RefPtr<CSSPrimitiveValue> consumePositionComponent(CSSParserTokenRange& range, CSSParserMode cssParserMode, UnitlessQuirk unitless)2465 static RefPtr<CSSPrimitiveValue> consumePositionComponent(CSSParserTokenRange& range, CSSParserMode parserMode, UnitlessQuirk unitless) 2076 2466 { 2077 2467 if (range.peek().type() == IdentToken) 2078 2468 return consumeIdent<CSSValueLeft, CSSValueTop, CSSValueBottom, CSSValueRight, CSSValueCenter>(range); 2079 return consumeLengthOrPercent(range, cssParserMode, ValueRange::All, unitless);2469 return consumeLengthOrPercent(range, parserMode, ValueRange::All, unitless); 2080 2470 } 2081 2471 … … 2226 2616 // FIXME: This may consume from the range upon failure. The background 2227 2617 // 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);2618 std::optional<PositionCoordinates> consumePositionCoordinates(CSSParserTokenRange& range, CSSParserMode parserMode, UnitlessQuirk unitless, PositionSyntax positionSyntax) 2619 { 2620 auto value1 = consumePositionComponent(range, parserMode, unitless); 2231 2621 if (!value1) 2232 2622 return std::nullopt; 2233 2623 2234 auto value2 = consumePositionComponent(range, cssParserMode, unitless);2624 auto value2 = consumePositionComponent(range, parserMode, unitless); 2235 2625 if (!value2) 2236 2626 return positionFromOneValue(*value1); 2237 2627 2238 auto value3 = consumePositionComponent(range, cssParserMode, unitless);2628 auto value3 = consumePositionComponent(range, parserMode, unitless); 2239 2629 if (!value3) 2240 2630 return positionFromTwoValues(*value1, *value2); 2241 2631 2242 auto value4 = consumePositionComponent(range, cssParserMode, unitless);2632 auto value4 = consumePositionComponent(range, parserMode, unitless); 2243 2633 2244 2634 std::array<CSSPrimitiveValue*, 5> values { … … 2259 2649 } 2260 2650 2261 RefPtr<CSSPrimitiveValue> consumePosition(CSSParserTokenRange& range, CSSParserMode cssParserMode, UnitlessQuirk unitless, PositionSyntax positionSyntax)2262 { 2263 if (auto coordinates = consumePositionCoordinates(range, cssParserMode, unitless, positionSyntax))2651 RefPtr<CSSPrimitiveValue> consumePosition(CSSParserTokenRange& range, CSSParserMode parserMode, UnitlessQuirk unitless, PositionSyntax positionSyntax) 2652 { 2653 if (auto coordinates = consumePositionCoordinates(range, parserMode, unitless, positionSyntax)) 2264 2654 return CSSPropertyParserHelpersInternal::createPrimitiveValuePair(WTFMove(coordinates->x), WTFMove(coordinates->y)); 2265 2655 return nullptr; 2266 2656 } 2267 2657 2268 std::optional<PositionCoordinates> consumeOneOrTwoValuedPositionCoordinates(CSSParserTokenRange& range, CSSParserMode cssParserMode, UnitlessQuirk unitless)2269 { 2270 auto value1 = consumePositionComponent(range, cssParserMode, unitless);2658 std::optional<PositionCoordinates> consumeOneOrTwoValuedPositionCoordinates(CSSParserTokenRange& range, CSSParserMode parserMode, UnitlessQuirk unitless) 2659 { 2660 auto value1 = consumePositionComponent(range, parserMode, unitless); 2271 2661 if (!value1) 2272 2662 return std::nullopt; 2273 auto value2 = consumePositionComponent(range, cssParserMode, unitless);2663 auto value2 = consumePositionComponent(range, parserMode, unitless); 2274 2664 if (!value2) 2275 2665 return positionFromOneValue(*value1); … … 2315 2705 } else { 2316 2706 ASSERT(id == CSSValueColorStop); 2317 auto value = consumeNumber OrPercentDividedBy100Raw(args);2707 auto value = consumeNumberRawOrPercentDividedBy100Raw(args); 2318 2708 if (!value) 2319 2709 return false; … … 2664 3054 return nullptr; 2665 3055 2666 auto percentage = consumeNumber OrPercentDividedBy100Raw(args);3056 auto percentage = consumeNumberRawOrPercentDividedBy100Raw(args); 2667 3057 if (!percentage) 2668 3058 return nullptr; … … 3106 3496 } 3107 3497 3108 std::optional<FontStyleRaw> consumeFontStyleRaw(CSSParserTokenRange& range, CSSParserMode cssParserMode)3498 std::optional<FontStyleRaw> consumeFontStyleRaw(CSSParserTokenRange& range, CSSParserMode parserMode) 3109 3499 { 3110 3500 auto result = consumeFontStyleKeywordValueRaw(range); … … 3119 3509 if (!range.atEnd()) { 3120 3510 // 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)) { 3122 3512 if (isFontStyleAngleInRange(CSSPrimitiveValue::computeDegrees(angle->type, angle->value))) 3123 3513 return { { CSSValueOblique, WTFMove(angle) } }; … … 3126 3516 } 3127 3517 #else 3128 UNUSED_PARAM( cssParserMode);3518 UNUSED_PARAM(parserMode); 3129 3519 #endif 3130 3520 return { { CSSValueOblique, std::nullopt } }; … … 3178 3568 } 3179 3569 3180 std::optional<FontSizeRaw> consumeFontSizeRaw(CSSParserTokenRange& range, CSSParserMode cssParserMode, UnitlessQuirk unitless)3570 std::optional<FontSizeRaw> consumeFontSizeRaw(CSSParserTokenRange& range, CSSParserMode parserMode, UnitlessQuirk unitless) 3181 3571 { 3182 3572 if (range.peek().id() >= CSSValueXxSmall && range.peek().id() <= CSSValueLarger) { … … 3186 3576 } 3187 3577 3188 if (auto result = consumeLengthOrPercentRaw(range, cssParserMode, ValueRange::NonNegative, unitless))3578 if (auto result = consumeLengthOrPercentRaw(range, parserMode, ValueRange::NonNegative, unitless)) 3189 3579 return { *result }; 3190 3580 … … 3192 3582 } 3193 3583 3194 std::optional<LineHeightRaw> consumeLineHeightRaw(CSSParserTokenRange& range, CSSParserMode cssParserMode)3584 std::optional<LineHeightRaw> consumeLineHeightRaw(CSSParserTokenRange& range, CSSParserMode parserMode) 3195 3585 { 3196 3586 if (range.peek().id() == CSSValueNormal) { … … 3203 3593 return { *number }; 3204 3594 3205 if (auto lengthOrPercent = consumeLengthOrPercentRaw(range, cssParserMode, ValueRange::NonNegative))3595 if (auto lengthOrPercent = consumeLengthOrPercentRaw(range, parserMode, ValueRange::NonNegative)) 3206 3596 return { *lengthOrPercent }; 3207 3597 … … 3209 3599 } 3210 3600 3211 std::optional<FontRaw> consumeFontRaw(CSSParserTokenRange& range, CSSParserMode cssParserMode)3601 std::optional<FontRaw> consumeFontRaw(CSSParserTokenRange& range, CSSParserMode parserMode) 3212 3602 { 3213 3603 // Let's check if there is an inherit or initial somewhere in the shorthand. … … 3224 3614 CSSValueID id = range.peek().id(); 3225 3615 if (!result.style) { 3226 if ((result.style = consumeFontStyleRaw(range, cssParserMode)))3616 if ((result.style = consumeFontStyleRaw(range, parserMode))) 3227 3617 continue; 3228 3618 } … … 3248 3638 3249 3639 // Now a font size _must_ come. 3250 if (auto size = consumeFontSizeRaw(range, cssParserMode))3640 if (auto size = consumeFontSizeRaw(range, parserMode)) 3251 3641 result.size = *size; 3252 3642 else … … 3257 3647 3258 3648 if (consumeSlashIncludingWhitespace(range)) { 3259 if (!(result.lineHeight = consumeLineHeightRaw(range, cssParserMode)))3649 if (!(result.lineHeight = consumeLineHeightRaw(range, parserMode))) 3260 3650 return std::nullopt; 3261 3651 }
Note:
See TracChangeset
for help on using the changeset viewer.