| Index: third_party/WebKit/Source/core/css/parser/CSSPropertyParserHelpers.cpp
|
| diff --git a/third_party/WebKit/Source/core/css/parser/CSSPropertyParserHelpers.cpp b/third_party/WebKit/Source/core/css/parser/CSSPropertyParserHelpers.cpp
|
| index 6ee13b885bf0ed761aba96a92f91b0b31f7c45b4..c4dafc3a74957260a00076a92d15b6c99e22df1a 100644
|
| --- a/third_party/WebKit/Source/core/css/parser/CSSPropertyParserHelpers.cpp
|
| +++ b/third_party/WebKit/Source/core/css/parser/CSSPropertyParserHelpers.cpp
|
| @@ -488,11 +488,24 @@ CSSValue* consumeColor(CSSParserTokenRange& range, CSSParserMode cssParserMode,
|
| return CSSColorValue::create(color);
|
| }
|
|
|
| -static CSSPrimitiveValue* consumePositionComponent(CSSParserTokenRange& range, CSSParserMode cssParserMode, UnitlessQuirk unitless)
|
| +static CSSPrimitiveValue* consumePositionComponent(CSSParserTokenRange& range, CSSParserMode cssParserMode, UnitlessQuirk unitless, bool& horizontalEdge, bool& verticalEdge)
|
| {
|
| - if (range.peek().type() == IdentToken)
|
| - return consumeIdent<CSSValueLeft, CSSValueTop, CSSValueBottom, CSSValueRight, CSSValueCenter>(range);
|
| - return consumeLengthOrPercent(range, cssParserMode, ValueRangeAll, unitless);
|
| + if (range.peek().type() != IdentToken)
|
| + return consumeLengthOrPercent(range, cssParserMode, ValueRangeAll, unitless);
|
| +
|
| + CSSValueID id = range.peek().id();
|
| + if (id == CSSValueLeft || id == CSSValueRight) {
|
| + if (horizontalEdge)
|
| + return nullptr;
|
| + horizontalEdge = true;
|
| + } else if (id == CSSValueTop || id == CSSValueBottom) {
|
| + if (verticalEdge)
|
| + return nullptr;
|
| + verticalEdge = true;
|
| + } else if (id != CSSValueCenter) {
|
| + return nullptr;
|
| + }
|
| + return consumeIdent(range);
|
| }
|
|
|
| static bool isHorizontalPositionKeywordOnly(const CSSPrimitiveValue& value)
|
| @@ -514,33 +527,29 @@ static void positionFromOneValue(CSSPrimitiveValue* value, CSSValue*& resultX, C
|
| std::swap(resultX, resultY);
|
| }
|
|
|
| -static bool positionFromTwoValues(CSSPrimitiveValue* value1, CSSPrimitiveValue* value2,
|
| +static void positionFromTwoValues(CSSPrimitiveValue* value1, CSSPrimitiveValue* value2,
|
| CSSValue*& resultX, CSSValue*& resultY)
|
| {
|
| bool mustOrderAsXY = isHorizontalPositionKeywordOnly(*value1) || isVerticalPositionKeywordOnly(*value2)
|
| || !value1->isValueID() || !value2->isValueID();
|
| bool mustOrderAsYX = isVerticalPositionKeywordOnly(*value1) || isHorizontalPositionKeywordOnly(*value2);
|
| - if (mustOrderAsXY && mustOrderAsYX)
|
| - return false;
|
| + DCHECK(!mustOrderAsXY || !mustOrderAsYX);
|
| resultX = value1;
|
| resultY = value2;
|
| if (mustOrderAsYX)
|
| std::swap(resultX, resultY);
|
| - return true;
|
| }
|
|
|
| -static bool positionFromThreeOrFourValues(CSSPrimitiveValue** values, CSSValue*& resultX, CSSValue*& resultY)
|
| +static void positionFromThreeOrFourValues(CSSPrimitiveValue** values, CSSValue*& resultX, CSSValue*& resultY)
|
| {
|
| CSSPrimitiveValue* center = nullptr;
|
| for (int i = 0; values[i]; i++) {
|
| CSSPrimitiveValue* currentValue = values[i];
|
| - if (!currentValue->isValueID())
|
| - return false;
|
| + DCHECK(currentValue->isValueID());
|
| CSSValueID id = currentValue->getValueID();
|
|
|
| if (id == CSSValueCenter) {
|
| - if (center)
|
| - return false;
|
| + DCHECK(!center);
|
| center = currentValue;
|
| continue;
|
| }
|
| @@ -553,57 +562,69 @@ static bool positionFromThreeOrFourValues(CSSPrimitiveValue** values, CSSValue*&
|
| }
|
|
|
| if (id == CSSValueLeft || id == CSSValueRight) {
|
| - if (resultX)
|
| - return false;
|
| + DCHECK(!resultX);
|
| resultX = result;
|
| } else {
|
| - ASSERT(id == CSSValueTop || id == CSSValueBottom);
|
| - if (resultY)
|
| - return false;
|
| + DCHECK(id == CSSValueTop || id == CSSValueBottom);
|
| + DCHECK(!resultY);
|
| resultY = result;
|
| }
|
| }
|
|
|
| if (center) {
|
| - ASSERT(resultX || resultY);
|
| - if (resultX && resultY)
|
| - return false;
|
| + DCHECK(!!resultX != !!resultY);
|
| if (!resultX)
|
| resultX = center;
|
| else
|
| resultY = center;
|
| }
|
|
|
| - ASSERT(resultX && resultY);
|
| - return true;
|
| + DCHECK(resultX && resultY);
|
| }
|
|
|
| -// TODO(timloh): This may consume from the range upon failure. The background
|
| -// shorthand works around it, but we should just fix it here.
|
| bool consumePosition(CSSParserTokenRange& range, CSSParserMode cssParserMode, UnitlessQuirk unitless, CSSValue*& resultX, CSSValue*& resultY)
|
| {
|
| - CSSPrimitiveValue* value1 = consumePositionComponent(range, cssParserMode, unitless);
|
| + bool horizontalEdge = false;
|
| + bool verticalEdge = false;
|
| + CSSPrimitiveValue* value1 = consumePositionComponent(range, cssParserMode, unitless, horizontalEdge, verticalEdge);
|
| if (!value1)
|
| return false;
|
| + if (!value1->isValueID())
|
| + horizontalEdge = true;
|
|
|
| - CSSPrimitiveValue* value2 = consumePositionComponent(range, cssParserMode, unitless);
|
| + CSSParserTokenRange rangeAfterFirstConsume = range;
|
| + CSSPrimitiveValue* value2 = consumePositionComponent(range, cssParserMode, unitless, horizontalEdge, verticalEdge);
|
| if (!value2) {
|
| positionFromOneValue(value1, resultX, resultY);
|
| return true;
|
| }
|
|
|
| - CSSPrimitiveValue* value3 = consumePositionComponent(range, cssParserMode, unitless);
|
| - if (!value3)
|
| - return positionFromTwoValues(value1, value2, resultX, resultY);
|
| + CSSPrimitiveValue* value3 = nullptr;
|
| + if (value1->isValueID()
|
| + && value2->isValueID() != (range.peek().type() == IdentToken)
|
| + && (value2->isValueID() ? value2->getValueID() : value1->getValueID()) != CSSValueCenter)
|
| + value3 = consumePositionComponent(range, cssParserMode, unitless, horizontalEdge, verticalEdge);
|
| + if (!value3) {
|
| + if (verticalEdge && !value2->isValueID()) {
|
| + range = rangeAfterFirstConsume;
|
| + positionFromOneValue(value1, resultX, resultY);
|
| + return true;
|
| + }
|
| + positionFromTwoValues(value1, value2, resultX, resultY);
|
| + return true;
|
| + }
|
|
|
| - CSSPrimitiveValue* value4 = consumePositionComponent(range, cssParserMode, unitless);
|
| + CSSPrimitiveValue* value4 = nullptr;
|
| + if (value3->isValueID() && value3->getValueID() != CSSValueCenter && range.peek().type() != IdentToken)
|
| + value4 = consumePositionComponent(range, cssParserMode, unitless, horizontalEdge, verticalEdge);
|
| CSSPrimitiveValue* values[5];
|
| values[0] = value1;
|
| values[1] = value2;
|
| values[2] = value3;
|
| values[3] = value4;
|
| values[4] = nullptr;
|
| - return positionFromThreeOrFourValues(values, resultX, resultY);
|
| + positionFromThreeOrFourValues(values, resultX, resultY);
|
| + return true;
|
| }
|
|
|
| CSSValuePair* consumePosition(CSSParserTokenRange& range, CSSParserMode cssParserMode, UnitlessQuirk unitless)
|
| @@ -617,15 +638,23 @@ CSSValuePair* consumePosition(CSSParserTokenRange& range, CSSParserMode cssParse
|
|
|
| bool consumeOneOrTwoValuedPosition(CSSParserTokenRange& range, CSSParserMode cssParserMode, UnitlessQuirk unitless, CSSValue*& resultX, CSSValue*& resultY)
|
| {
|
| - CSSPrimitiveValue* value1 = consumePositionComponent(range, cssParserMode, unitless);
|
| + bool horizontalEdge = false;
|
| + bool verticalEdge = false;
|
| + CSSPrimitiveValue* value1 = consumePositionComponent(range, cssParserMode, unitless, horizontalEdge, verticalEdge);
|
| if (!value1)
|
| return false;
|
| - CSSPrimitiveValue* value2 = consumePositionComponent(range, cssParserMode, unitless);
|
| + if (!value1->isValueID())
|
| + horizontalEdge = true;
|
| +
|
| + CSSPrimitiveValue* value2 = nullptr;
|
| + if (!verticalEdge || range.peek().type() == IdentToken)
|
| + value2 = consumePositionComponent(range, cssParserMode, unitless, horizontalEdge, verticalEdge);
|
| if (!value2) {
|
| positionFromOneValue(value1, resultX, resultY);
|
| return true;
|
| }
|
| - return positionFromTwoValues(value1, value2, resultX, resultY);
|
| + positionFromTwoValues(value1, value2, resultX, resultY);
|
| + return true;
|
| }
|
|
|
| // This should go away once we drop support for -webkit-gradient
|
|
|