Index: third_party/WebKit/Source/core/css/parser/LegacyCSSPropertyParser.cpp |
diff --git a/third_party/WebKit/Source/core/css/parser/LegacyCSSPropertyParser.cpp b/third_party/WebKit/Source/core/css/parser/LegacyCSSPropertyParser.cpp |
index d2980709446f0d1a9e01f75ad096fb9e7e7f785c..88a5992916845fb7fef8342b375bad3a1957fe21 100644 |
--- a/third_party/WebKit/Source/core/css/parser/LegacyCSSPropertyParser.cpp |
+++ b/third_party/WebKit/Source/core/css/parser/LegacyCSSPropertyParser.cpp |
@@ -1874,15 +1874,20 @@ PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseGridTrackList() |
return nullptr; |
bool seenTrackSizeOrRepeatFunction = false; |
+ bool seenAutoRepeat = false; |
while (CSSParserValue* currentValue = m_valueList->current()) { |
if (isForwardSlashOperator(currentValue)) |
break; |
if (currentValue->m_unit == CSSParserValue::Function && currentValue->function->id == CSSValueRepeat) { |
- if (!parseGridTrackRepeatFunction(*values)) |
+ bool isAutoRepeat; |
+ if (!parseGridTrackRepeatFunction(*values, isAutoRepeat)) |
+ return nullptr; |
+ if (isAutoRepeat && seenAutoRepeat) |
return nullptr; |
seenTrackSizeOrRepeatFunction = true; |
+ seenAutoRepeat = seenAutoRepeat || isAutoRepeat; |
} else { |
- RefPtrWillBeRawPtr<CSSValue> value = parseGridTrackSize(*m_valueList); |
+ RefPtrWillBeRawPtr<CSSValue> value = parseGridTrackSize(*m_valueList, seenAutoRepeat ? FixedSizeOnly : AllowAll); |
if (!value) |
return nullptr; |
values->append(value); |
@@ -1897,17 +1902,39 @@ PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseGridTrackList() |
if (!seenTrackSizeOrRepeatFunction) |
return nullptr; |
+ // <auto-repeat> requires definite minimum track sizes in order to compute the number of repetitions. |
+ // The above while loop detects those appearances after the <auto-repeat> but not the ones before. |
+ if (seenAutoRepeat) { |
+ for (auto value : *values) { |
+ if (value->isGridLineNamesValue()) |
+ continue; |
+ ASSERT(value->isPrimitiveValue() || (value->isFunctionValue() && toCSSFunctionValue(*value).item(0))); |
+ const CSSPrimitiveValue& primitiveValue = value->isPrimitiveValue() |
+ ? toCSSPrimitiveValue(*value) |
+ : toCSSPrimitiveValue(*toCSSFunctionValue(*value).item(0)); |
+ CSSValueID valueID = primitiveValue.getValueID(); |
+ if (valueID == CSSValueMinContent || valueID == CSSValueMaxContent || valueID == CSSValueAuto || primitiveValue.isFlex()) |
+ return nullptr; |
+ } |
+ } |
+ |
return values; |
} |
-bool CSSPropertyParser::parseGridTrackRepeatFunction(CSSValueList& list) |
+bool CSSPropertyParser::parseGridTrackRepeatFunction(CSSValueList& list, bool& isAutoRepeat) |
{ |
CSSParserValueList* arguments = m_valueList->current()->function->args.get(); |
- if (!arguments || arguments->size() < 3 || !validUnit(arguments->valueAt(0), FPositiveInteger) || !isComma(arguments->valueAt(1))) |
+ if (!arguments || arguments->size() < 3 || !isComma(arguments->valueAt(1))) |
return false; |
- ASSERT(arguments->valueAt(0)->fValue > 0); |
- size_t repetitions = clampTo<size_t>(arguments->valueAt(0)->fValue, 0, kGridMaxTracks); |
+ CSSParserValue* currentValue = arguments->valueAt(0); |
+ isAutoRepeat = currentValue->id == CSSValueAutoFill || currentValue->id == CSSValueAutoFit; |
+ if (!isAutoRepeat && !validUnit(currentValue, FPositiveInteger)) |
+ return false; |
+ |
+ // The number of repetitions for <auto-repeat> is not important at parsing level |
+ // because it will be computed later, let's set it to 1. |
+ size_t repetitions = isAutoRepeat ? 1 : clampTo<size_t>(currentValue->fValue, 0, kGridMaxTracks); |
RefPtrWillBeRawPtr<CSSValueList> repeatedValues = CSSValueList::createSpaceSeparated(); |
arguments->next(); // Skip the repetition count. |
@@ -1918,8 +1945,12 @@ bool CSSPropertyParser::parseGridTrackRepeatFunction(CSSValueList& list) |
return false; |
size_t numberOfTracks = 0; |
+ TrackSizeRestriction restriction = isAutoRepeat ? FixedSizeOnly : AllowAll; |
while (arguments->current()) { |
- RefPtrWillBeRawPtr<CSSValue> trackSize = parseGridTrackSize(*arguments); |
+ if (isAutoRepeat && numberOfTracks) |
+ return false; |
+ |
+ RefPtrWillBeRawPtr<CSSValue> trackSize = parseGridTrackSize(*arguments, restriction); |
if (!trackSize) |
return false; |
@@ -1950,7 +1981,7 @@ bool CSSPropertyParser::parseGridTrackRepeatFunction(CSSValueList& list) |
} |
-PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseGridTrackSize(CSSParserValueList& inputList) |
+PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseGridTrackSize(CSSParserValueList& inputList, TrackSizeRestriction restriction) |
{ |
ASSERT(RuntimeEnabledFeatures::cssGridLayoutEnabled()); |
@@ -1958,7 +1989,7 @@ PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseGridTrackSize(CSSParser |
inputList.next(); |
if (currentValue->id == CSSValueAuto) |
- return cssValuePool().createIdentifierValue(CSSValueAuto); |
+ return restriction == AllowAll ? cssValuePool().createIdentifierValue(CSSValueAuto) : nullptr; |
if (currentValue->m_unit == CSSParserValue::Function && currentValue->function->id == CSSValueMinmax) { |
// The spec defines the following grammar: minmax( <track-breadth> , <track-breadth> ) |
@@ -1966,7 +1997,7 @@ PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseGridTrackSize(CSSParser |
if (!arguments || arguments->size() != 3 || !isComma(arguments->valueAt(1))) |
return nullptr; |
- RefPtrWillBeRawPtr<CSSPrimitiveValue> minTrackBreadth = parseGridBreadth(arguments->valueAt(0)); |
+ RefPtrWillBeRawPtr<CSSPrimitiveValue> minTrackBreadth = parseGridBreadth(arguments->valueAt(0), restriction); |
if (!minTrackBreadth) |
return nullptr; |
@@ -1980,15 +2011,18 @@ PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseGridTrackSize(CSSParser |
return result.release(); |
} |
- return parseGridBreadth(currentValue); |
+ return parseGridBreadth(currentValue, restriction); |
} |
-PassRefPtrWillBeRawPtr<CSSPrimitiveValue> CSSPropertyParser::parseGridBreadth(CSSParserValue* currentValue) |
+PassRefPtrWillBeRawPtr<CSSPrimitiveValue> CSSPropertyParser::parseGridBreadth(CSSParserValue* currentValue, TrackSizeRestriction restriction) |
{ |
if (currentValue->id == CSSValueMinContent || currentValue->id == CSSValueMaxContent || currentValue->id == CSSValueAuto) |
- return cssValuePool().createIdentifierValue(currentValue->id); |
+ return restriction == AllowAll ? cssValuePool().createIdentifierValue(currentValue->id) : nullptr; |
if (currentValue->unit() == CSSPrimitiveValue::UnitType::Fraction) { |
+ if (restriction == FixedSizeOnly) |
+ return nullptr; |
+ |
double flexValue = currentValue->fValue; |
// Fractional unit is a non-negative dimension. |