Chromium Code Reviews| Index: third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp |
| diff --git a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp |
| index b8661ea5d7ab6d062ef2ae17acbecf1a9999e8dd..ffbafd734ebe8a61a4fd1b0890215841bf37d51e 100644 |
| --- a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp |
| +++ b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp |
| @@ -126,6 +126,125 @@ static CSSParserTokenRange consumeFunction(CSSParserTokenRange& range) |
| return contents; |
| } |
| +static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> consumeCalcExpression(const CSSParserTokenRange& range, CSSPropertyParser::Units unitflags) |
| +{ |
| + bool mustBeNonNegative = unitflags & (CSSPropertyParser::FNonNeg | CSSPropertyParser::FPositiveInteger); |
| + RefPtrWillBeRawPtr<CSSCalcValue> calculation = CSSCalcValue::create(range, mustBeNonNegative ? ValueRangeNonNegative : ValueRangeAll); |
| + if (!calculation) |
| + return nullptr; |
| + bool b = false; |
| + switch (calculation->category()) { |
| + case CalcLength: |
| + b = (unitflags & CSSPropertyParser::FLength); |
| + break; |
| + case CalcNumber: |
| + b = (unitflags & CSSPropertyParser::FNumber); |
| + if (!b && (unitflags & (CSSPropertyParser::FInteger | CSSPropertyParser::FPositiveInteger)) && calculation->isInt()) |
| + b = true; |
| + if (b && mustBeNonNegative && calculation->isNegative()) |
| + b = false; |
| + // Always resolve calc() to a UnitType::Number in the CSSParserValue if there are no non-numbers specified in the unitflags. |
| + if (b && !(unitflags & ~(CSSPropertyParser::FInteger | CSSPropertyParser::FNumber | CSSPropertyParser::FPositiveInteger | CSSPropertyParser::FNonNeg))) { |
| + double number = calculation->doubleValue(); |
| + if ((unitflags & CSSPropertyParser::FPositiveInteger) && number <= 0) |
| + return nullptr; |
| + return cssValuePool().createValue(number, calculation->isInt() ? CSSPrimitiveValue::UnitType::Integer : CSSPrimitiveValue::UnitType::Number); |
| + } |
| + break; |
| + case CalcPercent: |
| + b = (unitflags & CSSPropertyParser::FPercent); |
| + if (b && mustBeNonNegative && calculation->isNegative()) |
| + b = false; |
| + break; |
| + case CalcPercentLength: |
| + b = (unitflags & CSSPropertyParser::FPercent) && (unitflags & CSSPropertyParser::FLength); |
| + break; |
| + case CalcPercentNumber: |
| + b = (unitflags & CSSPropertyParser::FPercent) && (unitflags & CSSPropertyParser::FNumber); |
| + break; |
| + case CalcAngle: |
| + b = (unitflags & CSSPropertyParser::FAngle); |
| + break; |
| + case CalcTime: |
| + b = (unitflags & CSSPropertyParser::FTime); |
| + break; |
| + case CalcFrequency: |
| + b = (unitflags & CSSPropertyParser::FFrequency); |
| + break; |
| + case CalcOther: |
| + break; |
| + } |
| + if (!b) |
| + return nullptr; |
| + return CSSPrimitiveValue::create(calculation.release()); |
| +} |
| + |
| +static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> consumeNumericValue(CSSParserTokenRange& range, CSSPropertyParser::Units unitflags, CSSParserMode cssParserMode) |
|
alancutter (OOO until 2018)
2015/09/25 04:13:06
After discussing with timloh we decided that split
|
| +{ |
| + const CSSParserToken& token = range.peek(); |
| + if (token.functionId() == CSSValueCalc || token.functionId() == CSSValueWebkitCalc) { |
| + CSSParserTokenRange args = consumeFunction(range); |
|
Timothy Loh
2015/09/25 04:44:33
BTW this will advance the token stream for invalid
|
| + return consumeCalcExpression(args, unitflags); |
| + } |
| + bool validNumber = false; |
| + CSSPrimitiveValue::UnitType unitType = token.unitType(); |
| + if (token.type() == NumberToken) { |
| + if (unitflags & CSSPropertyParser::FNumber) { |
| + validNumber = true; |
| + } else if (shouldAcceptUnitLessValues(token.numericValue(), unitflags, cssParserMode)) { |
| + unitType = (unitflags & CSSPropertyParser::FLength) ? CSSPrimitiveValue::UnitType::Pixels : CSSPrimitiveValue::UnitType::Degrees; |
| + validNumber = true; |
| + } else if ((unitflags & CSSPropertyParser::FInteger) && token.numericValueType() == IntegerValueType) { |
| + validNumber = true; |
| + } else if ((unitflags & CSSPropertyParser::FPositiveInteger) && token.numericValueType() == IntegerValueType && token.numericValue() > 0) { |
| + validNumber = true; |
| + } |
| + } else if (token.type() == PercentageToken) { |
| + validNumber = unitflags & CSSPropertyParser::FPercent; |
| + } else { // DimensionToken |
| + switch (token.unitType()) { |
| + case CSSPrimitiveValue::UnitType::QuirkyEms: |
| + if (cssParserMode != UASheetMode) |
| + return nullptr; |
| + /* fallthrough intentional */ |
| + case CSSPrimitiveValue::UnitType::Ems: |
| + case CSSPrimitiveValue::UnitType::Rems: |
| + case CSSPrimitiveValue::UnitType::Chs: |
| + case CSSPrimitiveValue::UnitType::Exs: |
| + case CSSPrimitiveValue::UnitType::Pixels: |
| + case CSSPrimitiveValue::UnitType::Centimeters: |
| + case CSSPrimitiveValue::UnitType::Millimeters: |
| + case CSSPrimitiveValue::UnitType::Inches: |
| + case CSSPrimitiveValue::UnitType::Points: |
| + case CSSPrimitiveValue::UnitType::Picas: |
| + case CSSPrimitiveValue::UnitType::ViewportWidth: |
| + case CSSPrimitiveValue::UnitType::ViewportHeight: |
| + case CSSPrimitiveValue::UnitType::ViewportMin: |
| + case CSSPrimitiveValue::UnitType::ViewportMax: |
| + validNumber = unitflags & CSSPropertyParser::FLength; |
| + break; |
| + case CSSPrimitiveValue::UnitType::Milliseconds: |
| + case CSSPrimitiveValue::UnitType::Seconds: |
| + validNumber = unitflags & CSSPropertyParser::FTime; |
| + break; |
| + case CSSPrimitiveValue::UnitType::Degrees: |
| + case CSSPrimitiveValue::UnitType::Radians: |
| + case CSSPrimitiveValue::UnitType::Gradians: |
| + case CSSPrimitiveValue::UnitType::Turns: |
| + validNumber = unitflags & CSSPropertyParser::FAngle; |
| + break; |
| + default: |
| + break; |
| + } |
| + } |
| + if (validNumber) { |
| + if (unitflags & CSSPropertyParser::FNonNeg && token.numericValue() < 0) |
| + return nullptr; |
| + return cssValuePool().createValue(range.consumeIncludingWhitespace().numericValue(), unitType); |
| + } |
| + return nullptr; |
| +} |
| + |
| static inline bool isCSSWideKeyword(const CSSValueID& id) |
| { |
| return id == CSSValueInitial || id == CSSValueInherit || id == CSSValueUnset || id == CSSValueDefault; |
| @@ -396,6 +515,18 @@ static PassRefPtrWillBeRawPtr<CSSValueList> consumeFontFamily(CSSParserTokenRang |
| return list.release(); |
| } |
| +PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::consumeSpacing() |
| +{ |
| + if (m_range.peek().id() == CSSValueNormal) |
| + return consumeIdent(m_range); |
| + return consumeNumericValue(m_range, FLength | FUnitlessQuirk, m_context.mode()); |
|
Timothy Loh
2015/09/25 04:44:33
// TODO(rwlbuis): Don't allow unitless values, and
|
| +} |
| + |
| +PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::consumeTabSize() |
| +{ |
| + return consumeNumericValue(m_range, FInteger | FLength | FNonNeg, m_context.mode()); |
| +} |
| + |
| PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseSingleValue(CSSPropertyID propId) |
| { |
| m_range.consumeWhitespace(); |
| @@ -418,6 +549,11 @@ PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseSingleValue(CSSProperty |
| return consumeFontFamily(m_range); |
| case CSSPropertyFontWeight: |
| return consumeFontWeight(m_range); |
| + case CSSPropertyLetterSpacing: |
| + case CSSPropertyWordSpacing: |
| + return consumeSpacing(); |
| + case CSSPropertyTabSize: |
| + return consumeTabSize(); |
| default: |
| return nullptr; |
| } |