| 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 419adc0c8689172fb5591fedd15974a368a99914..365a88dee4ca2ec5c7e41bd993ab6401e2962c64 100644
|
| --- a/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
|
| +++ b/third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp
|
| @@ -18,6 +18,7 @@
|
| #include "core/css/CSSGradientValue.h"
|
| #include "core/css/CSSGridAutoRepeatValue.h"
|
| #include "core/css/CSSGridLineNamesValue.h"
|
| +#include "core/css/CSSGridTemplateAreasValue.h"
|
| #include "core/css/CSSImageSetValue.h"
|
| #include "core/css/CSSPaintValue.h"
|
| #include "core/css/CSSPathValue.h"
|
| @@ -59,6 +60,39 @@ CSSPropertyParser::CSSPropertyParser(const CSSParserTokenRange& range,
|
| m_range.consumeWhitespace();
|
| }
|
|
|
| +void CSSPropertyParser::addProperty(CSSPropertyID property, CSSValue* value, bool important, bool implicit)
|
| +{
|
| + ASSERT(!isPropertyAlias(property));
|
| +
|
| + int shorthandIndex = 0;
|
| + bool setFromShorthand = false;
|
| +
|
| + if (m_currentShorthand) {
|
| + Vector<StylePropertyShorthand, 4> shorthands;
|
| + getMatchingShorthandsForLonghand(property, &shorthands);
|
| + setFromShorthand = true;
|
| + if (shorthands.size() > 1)
|
| + shorthandIndex = indexOfShorthandForLonghand(m_currentShorthand, shorthands);
|
| + }
|
| +
|
| + m_parsedProperties->append(CSSProperty(property, value, important, setFromShorthand, shorthandIndex, implicit));
|
| +}
|
| +
|
| +void CSSPropertyParser::addExpandedPropertyForValue(CSSPropertyID property, CSSValue* value, bool important)
|
| +{
|
| + const StylePropertyShorthand& shorthand = shorthandForProperty(property);
|
| + unsigned shorthandLength = shorthand.length();
|
| + if (!shorthandLength) {
|
| + addProperty(property, value, important);
|
| + return;
|
| + }
|
| +
|
| + ShorthandScope scope(this, property);
|
| + const CSSPropertyID* longhands = shorthand.properties();
|
| + for (unsigned i = 0; i < shorthandLength; ++i)
|
| + addProperty(longhands[i], value, important);
|
| +}
|
| +
|
| static bool hasInvalidNumericValues(const CSSParserTokenRange& range)
|
| {
|
| for (const CSSParserToken& token : range) {
|
| @@ -2923,7 +2957,7 @@ static CSSValue* consumeBackgroundSize(CSSPropertyID unresolvedProperty, CSSPars
|
| return CSSValuePair::create(horizontal, vertical, CSSValuePair::KeepIdenticalValues);
|
| }
|
|
|
| -CSSValueList* consumeGridAutoFlow(CSSParserTokenRange& range)
|
| +static CSSValueList* consumeGridAutoFlow(CSSParserTokenRange& range)
|
| {
|
| CSSPrimitiveValue* rowOrColumnValue = consumeIdent<CSSValueRow, CSSValueColumn>(range);
|
| CSSPrimitiveValue* denseAlgorithm = consumeIdent<CSSValueDense>(range);
|
| @@ -3102,6 +3136,124 @@ static CSSValue* consumeGridLine(CSSParserTokenRange& range)
|
| return values;
|
| }
|
|
|
| +static bool allTracksAreFixedSized(CSSValueList& valueList)
|
| +{
|
| + for (CSSValue* value : valueList) {
|
| + if (value->isGridLineNamesValue())
|
| + continue;
|
| + // The auto-repeat value holds a <fixed-size> = <fixed-breadth> | minmax( <fixed-breadth>, <track-breadth> )
|
| + if (value->isGridAutoRepeatValue()) {
|
| + if (!allTracksAreFixedSized(toCSSValueList(*value)))
|
| + return false;
|
| + continue;
|
| + }
|
| + 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 false;
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +static Vector<String> parseGridTemplateAreasColumnNames(const String& gridRowNames)
|
| +{
|
| + ASSERT(!gridRowNames.isEmpty());
|
| + Vector<String> columnNames;
|
| + // Using StringImpl to avoid checks and indirection in every call to String::operator[].
|
| + StringImpl& text = *gridRowNames.impl();
|
| +
|
| + StringBuilder areaName;
|
| + for (unsigned i = 0; i < text.length(); ++i) {
|
| + // TODO(rob.buis): this whitespace check misses \n and \t.
|
| + // https://drafts.csswg.org/css-grid/#valdef-grid-template-areas-string
|
| + // https://drafts.csswg.org/css-syntax-3/#whitespace
|
| + if (text[i] == ' ') {
|
| + if (!areaName.isEmpty()) {
|
| + columnNames.append(areaName.toString());
|
| + areaName.clear();
|
| + }
|
| + continue;
|
| + }
|
| + if (text[i] == '.') {
|
| + if (areaName == ".")
|
| + continue;
|
| + if (!areaName.isEmpty()) {
|
| + columnNames.append(areaName.toString());
|
| + areaName.clear();
|
| + }
|
| + } else {
|
| + // TODO(rob.buis): only allow name code points here.
|
| + if (areaName == ".") {
|
| + columnNames.append(areaName.toString());
|
| + areaName.clear();
|
| + }
|
| + }
|
| +
|
| + areaName.append(text[i]);
|
| + }
|
| +
|
| + if (!areaName.isEmpty())
|
| + columnNames.append(areaName.toString());
|
| +
|
| + return columnNames;
|
| +}
|
| +
|
| +static bool parseGridTemplateAreasRow(const String& gridRowNames, NamedGridAreaMap& gridAreaMap, const size_t rowCount, size_t& columnCount)
|
| +{
|
| + if (gridRowNames.isEmpty() || gridRowNames.containsOnlyWhitespace())
|
| + return false;
|
| +
|
| + Vector<String> columnNames = parseGridTemplateAreasColumnNames(gridRowNames);
|
| + if (rowCount == 0) {
|
| + columnCount = columnNames.size();
|
| + ASSERT(columnCount);
|
| + } else if (columnCount != columnNames.size()) {
|
| + // The declaration is invalid if all the rows don't have the number of columns.
|
| + return false;
|
| + }
|
| +
|
| + for (size_t currentColumn = 0; currentColumn < columnCount; ++currentColumn) {
|
| + const String& gridAreaName = columnNames[currentColumn];
|
| +
|
| + // Unamed areas are always valid (we consider them to be 1x1).
|
| + if (gridAreaName == ".")
|
| + continue;
|
| +
|
| + size_t lookAheadColumn = currentColumn + 1;
|
| + while (lookAheadColumn < columnCount && columnNames[lookAheadColumn] == gridAreaName)
|
| + lookAheadColumn++;
|
| +
|
| + NamedGridAreaMap::iterator gridAreaIt = gridAreaMap.find(gridAreaName);
|
| + if (gridAreaIt == gridAreaMap.end()) {
|
| + gridAreaMap.add(gridAreaName, GridArea(GridSpan::translatedDefiniteGridSpan(rowCount, rowCount + 1), GridSpan::translatedDefiniteGridSpan(currentColumn, lookAheadColumn)));
|
| + } else {
|
| + GridArea& gridArea = gridAreaIt->value;
|
| +
|
| + // The following checks test that the grid area is a single filled-in rectangle.
|
| + // 1. The new row is adjacent to the previously parsed row.
|
| + if (rowCount != gridArea.rows.endLine())
|
| + return false;
|
| +
|
| + // 2. The new area starts at the same position as the previously parsed area.
|
| + if (currentColumn != gridArea.columns.startLine())
|
| + return false;
|
| +
|
| + // 3. The new area ends at the same position as the previously parsed area.
|
| + if (lookAheadColumn != gridArea.columns.endLine())
|
| + return false;
|
| +
|
| + gridArea.rows = GridSpan::translatedDefiniteGridSpan(gridArea.rows.startLine(), gridArea.rows.endLine() + 1);
|
| + }
|
| + currentColumn = lookAheadColumn - 1;
|
| + }
|
| +
|
| + return true;
|
| +}
|
| +
|
| +enum TrackSizeRestriction { FixedSizeOnly, AllowAll };
|
| +
|
| static CSSPrimitiveValue* consumeGridBreadth(CSSParserTokenRange& range, CSSParserMode cssParserMode, TrackSizeRestriction restriction = AllowAll)
|
| {
|
| if (restriction == AllowAll) {
|
| @@ -3118,7 +3270,7 @@ static CSSPrimitiveValue* consumeGridBreadth(CSSParserTokenRange& range, CSSPars
|
| }
|
|
|
| // TODO(rob.buis): This needs a bool parameter so we can disallow <auto-track-list> for the grid shorthand.
|
| -CSSValue* consumeGridTrackSize(CSSParserTokenRange& range, CSSParserMode cssParserMode, TrackSizeRestriction restriction)
|
| +static CSSValue* consumeGridTrackSize(CSSParserTokenRange& range, CSSParserMode cssParserMode, TrackSizeRestriction restriction = AllowAll)
|
| {
|
| const CSSParserToken& token = range.peek();
|
| if (restriction == AllowAll && identMatches<CSSValueAuto>(token.id()))
|
| @@ -4563,6 +4715,70 @@ bool CSSPropertyParser::consumeGridTemplateShorthand(bool important)
|
| return consumeGridTemplateRowsAndAreasAndColumns(important);
|
| }
|
|
|
| +bool CSSPropertyParser::consumeGridShorthand(bool important)
|
| +{
|
| + ASSERT(RuntimeEnabledFeatures::cssGridLayoutEnabled());
|
| + ASSERT(shorthandForProperty(CSSPropertyGrid).length() == 8);
|
| +
|
| + CSSParserTokenRange rangeCopy = m_range;
|
| +
|
| + // 1- <grid-template>
|
| + if (consumeGridTemplateShorthand(important)) {
|
| + // It can only be specified the explicit or the implicit grid properties in a single grid declaration.
|
| + // The sub-properties not specified are set to their initial value, as normal for shorthands.
|
| + addProperty(CSSPropertyGridAutoFlow, cssValuePool().createImplicitInitialValue(), important);
|
| + addProperty(CSSPropertyGridAutoColumns, cssValuePool().createImplicitInitialValue(), important);
|
| + addProperty(CSSPropertyGridAutoRows, cssValuePool().createImplicitInitialValue(), important);
|
| + addProperty(CSSPropertyGridColumnGap, cssValuePool().createImplicitInitialValue(), important);
|
| + addProperty(CSSPropertyGridRowGap, cssValuePool().createImplicitInitialValue(), important);
|
| + return true;
|
| + }
|
| +
|
| + m_range = rangeCopy;
|
| +
|
| + // 2- <grid-auto-flow> [ <grid-auto-rows> [ / <grid-auto-columns> ]? ]
|
| + CSSValueList* gridAutoFlow = consumeGridAutoFlow(m_range);
|
| + if (!gridAutoFlow)
|
| + return false;
|
| +
|
| + CSSValue* autoColumnsValue = nullptr;
|
| + CSSValue* autoRowsValue = nullptr;
|
| +
|
| + if (!m_range.atEnd()) {
|
| + autoRowsValue = consumeGridTrackSize(m_range, m_context.mode());
|
| + if (!autoRowsValue)
|
| + return false;
|
| + if (consumeSlashIncludingWhitespace(m_range)) {
|
| + autoColumnsValue = consumeGridTrackSize(m_range, m_context.mode());
|
| + if (!autoColumnsValue)
|
| + return false;
|
| + }
|
| + if (!m_range.atEnd())
|
| + return false;
|
| + } else {
|
| + // Other omitted values are set to their initial values.
|
| + autoColumnsValue = cssValuePool().createImplicitInitialValue();
|
| + autoRowsValue = cssValuePool().createImplicitInitialValue();
|
| + }
|
| +
|
| + // if <grid-auto-columns> value is omitted, it is set to the value specified for grid-auto-rows.
|
| + if (!autoColumnsValue)
|
| + autoColumnsValue = autoRowsValue;
|
| +
|
| + // It can only be specified the explicit or the implicit grid properties in a single grid declaration.
|
| + // The sub-properties not specified are set to their initial value, as normal for shorthands.
|
| + addProperty(CSSPropertyGridTemplateColumns, cssValuePool().createImplicitInitialValue(), important);
|
| + addProperty(CSSPropertyGridTemplateRows, cssValuePool().createImplicitInitialValue(), important);
|
| + addProperty(CSSPropertyGridTemplateAreas, cssValuePool().createImplicitInitialValue(), important);
|
| + addProperty(CSSPropertyGridAutoFlow, gridAutoFlow, important);
|
| + addProperty(CSSPropertyGridAutoColumns, autoColumnsValue, important);
|
| + addProperty(CSSPropertyGridAutoRows, autoRowsValue, important);
|
| + addProperty(CSSPropertyGridColumnGap, cssValuePool().createImplicitInitialValue(), important);
|
| + addProperty(CSSPropertyGridRowGap, cssValuePool().createImplicitInitialValue(), important);
|
| +
|
| + return true;
|
| +}
|
| +
|
| bool CSSPropertyParser::parseShorthand(CSSPropertyID unresolvedProperty, bool important)
|
| {
|
| CSSPropertyID property = resolveCSSPropertyID(unresolvedProperty);
|
| @@ -4747,13 +4963,11 @@ bool CSSPropertyParser::parseShorthand(CSSPropertyID unresolvedProperty, bool im
|
| return consumeGridAreaShorthand(important);
|
| case CSSPropertyGridTemplate:
|
| return consumeGridTemplateShorthand(important);
|
| + case CSSPropertyGrid:
|
| + return consumeGridShorthand(important);
|
| default:
|
| m_currentShorthand = oldShorthand;
|
| - CSSParserValueList valueList(m_range);
|
| - if (!valueList.size())
|
| - return false;
|
| - m_valueList = &valueList;
|
| - return legacyParseShorthand(unresolvedProperty, important);
|
| + return false;
|
| }
|
| }
|
|
|
|
|