Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(381)

Side by Side Diff: third_party/WebKit/Source/core/css/parser/CSSPropertyParser.cpp

Issue 1843773003: Move the grid-template shorthand into CSSPropertyParser (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address another issue Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "core/css/parser/CSSPropertyParser.h" 5 #include "core/css/parser/CSSPropertyParser.h"
6 6
7 #include "core/StylePropertyShorthand.h" 7 #include "core/StylePropertyShorthand.h"
8 #include "core/css/CSSBasicShapeValues.h" 8 #include "core/css/CSSBasicShapeValues.h"
9 #include "core/css/CSSBorderImage.h" 9 #include "core/css/CSSBorderImage.h"
10 #include "core/css/CSSContentDistributionValue.h" 10 #include "core/css/CSSContentDistributionValue.h"
(...skipping 3091 matching lines...) Expand 10 before | Expand all | Expand 10 after
3102 return nullptr; 3102 return nullptr;
3103 range = rangeCopy; 3103 range = rangeCopy;
3104 RawPtr<CSSFunctionValue> result = CSSFunctionValue::create(CSSValueMinma x); 3104 RawPtr<CSSFunctionValue> result = CSSFunctionValue::create(CSSValueMinma x);
3105 result->append(minTrackBreadth.release()); 3105 result->append(minTrackBreadth.release());
3106 result->append(maxTrackBreadth.release()); 3106 result->append(maxTrackBreadth.release());
3107 return result.release(); 3107 return result.release();
3108 } 3108 }
3109 return consumeGridBreadth(range, cssParserMode, restriction); 3109 return consumeGridBreadth(range, cssParserMode, restriction);
3110 } 3110 }
3111 3111
3112 static RawPtr<CSSGridLineNamesValue> consumeGridLineNames(CSSParserTokenRange& r ange) 3112 // Appends to the passed in CSSGridLineNamesValue if any, otherwise creates a ne w one.
3113 static CSSGridLineNamesValue* consumeGridLineNames(CSSParserTokenRange& range, C SSGridLineNamesValue* lineNames = nullptr)
3113 { 3114 {
3114 CSSParserTokenRange rangeCopy = range; 3115 CSSParserTokenRange rangeCopy = range;
3115 if (rangeCopy.consumeIncludingWhitespace().type() != LeftBracketToken) 3116 if (rangeCopy.consumeIncludingWhitespace().type() != LeftBracketToken)
3116 return nullptr; 3117 return nullptr;
3117 RawPtr<CSSGridLineNamesValue> lineNames = CSSGridLineNamesValue::create(); 3118 if (!lineNames)
3119 lineNames = CSSGridLineNamesValue::create();
3118 while (RawPtr<CSSCustomIdentValue> lineName = consumeCustomIdentForGridLine( rangeCopy)) 3120 while (RawPtr<CSSCustomIdentValue> lineName = consumeCustomIdentForGridLine( rangeCopy))
3119 lineNames->append(lineName.release()); 3121 lineNames->append(lineName.release());
3120 if (rangeCopy.consumeIncludingWhitespace().type() != RightBracketToken) 3122 if (rangeCopy.consumeIncludingWhitespace().type() != RightBracketToken)
3121 return nullptr; 3123 return nullptr;
3122 range = rangeCopy; 3124 range = rangeCopy;
3123 return lineNames.release(); 3125 return lineNames;
3124 } 3126 }
3125 3127
3126 static bool consumeGridTrackRepeatFunction(CSSParserTokenRange& range, CSSParser Mode cssParserMode, CSSValueList& list, bool& isAutoRepeat) 3128 static bool consumeGridTrackRepeatFunction(CSSParserTokenRange& range, CSSParser Mode cssParserMode, CSSValueList& list, bool& isAutoRepeat)
3127 { 3129 {
3128 CSSParserTokenRange args = consumeFunction(range); 3130 CSSParserTokenRange args = consumeFunction(range);
3129 // The number of repetitions for <auto-repeat> is not important at parsing l evel 3131 // The number of repetitions for <auto-repeat> is not important at parsing l evel
3130 // because it will be computed later, let's set it to 1. 3132 // because it will be computed later, let's set it to 1.
3131 size_t repetitions = 1; 3133 size_t repetitions = 1;
3132 isAutoRepeat = identMatches<CSSValueAutoFill, CSSValueAutoFit>(args.peek().i d()); 3134 isAutoRepeat = identMatches<CSSValueAutoFill, CSSValueAutoFit>(args.peek().i d());
3133 RawPtr<CSSValueList> repeatedValues; 3135 RawPtr<CSSValueList> repeatedValues;
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
3171 // We clamp the repetitions to a multiple of the repeat() track list's s ize, while staying below the max grid size. 3173 // We clamp the repetitions to a multiple of the repeat() track list's s ize, while staying below the max grid size.
3172 repetitions = std::min(repetitions, kGridMaxTracks / numberOfTracks); 3174 repetitions = std::min(repetitions, kGridMaxTracks / numberOfTracks);
3173 for (size_t i = 0; i < repetitions; ++i) { 3175 for (size_t i = 0; i < repetitions; ++i) {
3174 for (size_t j = 0; j < repeatedValues->length(); ++j) 3176 for (size_t j = 0; j < repeatedValues->length(); ++j)
3175 list.append(repeatedValues->item(j)); 3177 list.append(repeatedValues->item(j));
3176 } 3178 }
3177 } 3179 }
3178 return true; 3180 return true;
3179 } 3181 }
3180 3182
3183 static bool allTracksAreFixedSized(CSSValueList& valueList)
3184 {
3185 for (auto value : valueList) {
3186 if (value->isGridLineNamesValue())
3187 continue;
3188 // The auto-repeat value holds a <fixed-size> = <fixed-breadth> | minmax ( <fixed-breadth>, <track-breadth> )
3189 if (value->isGridAutoRepeatValue()) {
3190 if (!allTracksAreFixedSized(toCSSValueList(*value)))
3191 return false;
3192 continue;
3193 }
3194 ASSERT(value->isPrimitiveValue() || (value->isFunctionValue() && toCSSFu nctionValue(*value).item(0)));
3195 const CSSPrimitiveValue& primitiveValue = value->isPrimitiveValue()
3196 ? toCSSPrimitiveValue(*value)
3197 : toCSSPrimitiveValue(*toCSSFunctionValue(*value).item(0));
3198 CSSValueID valueID = primitiveValue.getValueID();
3199 if (valueID == CSSValueMinContent || valueID == CSSValueMaxContent || va lueID == CSSValueAuto || primitiveValue.isFlex())
3200 return false;
3201 }
3202 return true;
3203 }
3204
3181 static RawPtr<CSSValue> consumeGridTrackList(CSSParserTokenRange& range, CSSPars erMode cssParserMode) 3205 static RawPtr<CSSValue> consumeGridTrackList(CSSParserTokenRange& range, CSSPars erMode cssParserMode)
3182 { 3206 {
3183 RawPtr<CSSValueList> values = CSSValueList::createSpaceSeparated(); 3207 RawPtr<CSSValueList> values = CSSValueList::createSpaceSeparated();
3184 RawPtr<CSSGridLineNamesValue> lineNames = consumeGridLineNames(range); 3208 RawPtr<CSSGridLineNamesValue> lineNames = consumeGridLineNames(range);
3185 if (lineNames) 3209 if (lineNames)
3186 values->append(lineNames.release()); 3210 values->append(lineNames.release());
3187 3211
3188 bool seenAutoRepeat = false; 3212 bool seenAutoRepeat = false;
3189 // TODO(rob.buis): <line-names> should not be able to directly precede <auto -repeat>. 3213 // TODO(rob.buis): <line-names> should not be able to directly precede <auto -repeat>.
3190 do { 3214 do {
(...skipping 20 matching lines...) Expand all
3211 return values.release(); 3235 return values.release();
3212 } 3236 }
3213 3237
3214 static RawPtr<CSSValue> consumeGridTemplatesRowsOrColumns(CSSParserTokenRange& r ange, CSSParserMode cssParserMode) 3238 static RawPtr<CSSValue> consumeGridTemplatesRowsOrColumns(CSSParserTokenRange& r ange, CSSParserMode cssParserMode)
3215 { 3239 {
3216 if (range.peek().id() == CSSValueNone) 3240 if (range.peek().id() == CSSValueNone)
3217 return consumeIdent(range); 3241 return consumeIdent(range);
3218 return consumeGridTrackList(range, cssParserMode); 3242 return consumeGridTrackList(range, cssParserMode);
3219 } 3243 }
3220 3244
3245 static Vector<String> consumeGridTemplateAreasColumnNames(const String& gridRowN ames)
3246 {
3247 ASSERT(!gridRowNames.isEmpty());
3248 Vector<String> columnNames;
3249 // Using StringImpl to avoid checks and indirection in every call to String: :operator[].
3250 StringImpl& text = *gridRowNames.impl();
3251
3252 StringBuilder areaName;
3253 for (unsigned i = 0; i < text.length(); ++i) {
3254 if (text[i] == ' ') {
3255 if (!areaName.isEmpty()) {
3256 columnNames.append(areaName.toString());
3257 areaName.clear();
3258 }
3259 continue;
3260 }
3261 if (text[i] == '.') {
3262 if (areaName == ".")
3263 continue;
3264 if (!areaName.isEmpty()) {
3265 columnNames.append(areaName.toString());
3266 areaName.clear();
3267 }
3268 } else {
3269 if (areaName == ".") {
3270 columnNames.append(areaName.toString());
3271 areaName.clear();
3272 }
3273 }
3274
3275 areaName.append(text[i]);
3276 }
3277
3278 if (!areaName.isEmpty())
3279 columnNames.append(areaName.toString());
3280
3281 return columnNames;
3282 }
3283
3284 static bool consumeGridTemplateAreasRow(const String& gridRowNames, NamedGridAre aMap& gridAreaMap, const size_t rowCount, size_t& columnCount)
3285 {
3286 if (gridRowNames.isEmpty() || gridRowNames.containsOnlyWhitespace())
3287 return false;
3288
3289 Vector<String> columnNames = consumeGridTemplateAreasColumnNames(gridRowName s);
3290 if (!columnCount) {
3291 columnCount = columnNames.size();
3292 ASSERT(columnCount);
3293 } else if (columnCount != columnNames.size()) {
3294 // The declaration is invalid is all the rows don't have the number of c olumns.
3295 return false;
3296 }
3297
3298 for (size_t currentCol = 0; currentCol < columnCount; ++currentCol) {
3299 const String& gridAreaName = columnNames[currentCol];
3300
3301 // Unamed areas are always valid (we consider them to be 1x1).
3302 if (gridAreaName == ".")
3303 continue;
3304
3305 // We handle several grid areas with the same name at once to simplify t he validation code.
3306 size_t lookAheadCol;
3307 for (lookAheadCol = currentCol + 1; lookAheadCol < columnCount; ++lookAh eadCol) {
3308 if (columnNames[lookAheadCol] != gridAreaName)
3309 break;
3310 }
3311
3312 NamedGridAreaMap::iterator gridAreaIt = gridAreaMap.find(gridAreaName);
3313 if (gridAreaIt == gridAreaMap.end()) {
3314 gridAreaMap.add(gridAreaName, GridArea(GridSpan::translatedDefiniteG ridSpan(rowCount, rowCount + 1), GridSpan::translatedDefiniteGridSpan(currentCol , lookAheadCol)));
3315 } else {
3316 GridArea& gridArea = gridAreaIt->value;
3317
3318 // The following checks test that the grid area is a single filled-i n rectangle.
3319 // 1. The new row is adjacent to the previously parsed row.
3320 if (rowCount != gridArea.rows.endLine())
3321 return false;
3322
3323 // 2. The new area starts at the same position as the previously par sed area.
3324 if (currentCol != gridArea.columns.startLine())
3325 return false;
3326
3327 // 3. The new area ends at the same position as the previously parse d area.
3328 if (lookAheadCol != gridArea.columns.endLine())
3329 return false;
3330
3331 gridArea.rows = GridSpan::translatedDefiniteGridSpan(gridArea.rows.s tartLine(), gridArea.rows.endLine() + 1);
3332 }
3333 currentCol = lookAheadCol - 1;
3334 }
3335
3336 return true;
3337 }
3338
3221 static RawPtr<CSSValue> consumeGridTemplateAreas(CSSParserTokenRange& range) 3339 static RawPtr<CSSValue> consumeGridTemplateAreas(CSSParserTokenRange& range)
3222 { 3340 {
3223 if (range.peek().id() == CSSValueNone) 3341 if (range.peek().id() == CSSValueNone)
3224 return consumeIdent(range); 3342 return consumeIdent(range);
3225 3343
3226 NamedGridAreaMap gridAreaMap; 3344 NamedGridAreaMap gridAreaMap;
3227 size_t rowCount = 0; 3345 size_t rowCount = 0;
3228 size_t columnCount = 0; 3346 size_t columnCount = 0;
3229 3347
3230 while (range.peek().type() == StringToken) { 3348 while (range.peek().type() == StringToken) {
3231 if (!parseGridTemplateAreasRow(range.consumeIncludingWhitespace().value( ), gridAreaMap, rowCount, columnCount)) 3349 if (!consumeGridTemplateAreasRow(range.consumeIncludingWhitespace().valu e(), gridAreaMap, rowCount, columnCount))
3232 return nullptr; 3350 return nullptr;
3233 ++rowCount; 3351 ++rowCount;
3234 } 3352 }
3235 3353
3236 if (rowCount == 0) 3354 if (rowCount == 0)
3237 return nullptr; 3355 return nullptr;
3238 ASSERT(columnCount); 3356 ASSERT(columnCount);
3239 return CSSGridTemplateAreasValue::create(gridAreaMap, rowCount, columnCount) ; 3357 return CSSGridTemplateAreasValue::create(gridAreaMap, rowCount, columnCount) ;
3240 } 3358 }
3241 3359
(...skipping 1189 matching lines...) Expand 10 before | Expand all | Expand 10 after
4431 if (!columnEndValue) 4549 if (!columnEndValue)
4432 columnEndValue = columnStartValue->isCustomIdentValue() ? columnStartVal ue : cssValuePool().createIdentifierValue(CSSValueAuto); 4550 columnEndValue = columnStartValue->isCustomIdentValue() ? columnStartVal ue : cssValuePool().createIdentifierValue(CSSValueAuto);
4433 4551
4434 addProperty(CSSPropertyGridRowStart, rowStartValue, important); 4552 addProperty(CSSPropertyGridRowStart, rowStartValue, important);
4435 addProperty(CSSPropertyGridColumnStart, columnStartValue, important); 4553 addProperty(CSSPropertyGridColumnStart, columnStartValue, important);
4436 addProperty(CSSPropertyGridRowEnd, rowEndValue, important); 4554 addProperty(CSSPropertyGridRowEnd, rowEndValue, important);
4437 addProperty(CSSPropertyGridColumnEnd, columnEndValue, important); 4555 addProperty(CSSPropertyGridColumnEnd, columnEndValue, important);
4438 return true; 4556 return true;
4439 } 4557 }
4440 4558
4559 bool CSSPropertyParser::consumeGridTemplateRowsAndAreasAndColumns(bool important )
4560 {
4561 NamedGridAreaMap gridAreaMap;
4562 size_t rowCount = 0;
4563 size_t columnCount = 0;
4564 RawPtr<CSSValueList> templateRows = CSSValueList::createSpaceSeparated();
4565
4566 // Persists between loop iterations so we can use the same value for
4567 // consecutive <line-names> values
4568 CSSGridLineNamesValue* lineNames = nullptr;
4569
4570 do {
4571 // Handle leading <custom-ident>*.
4572 bool hasPreviousLineNames = lineNames;
4573 lineNames = consumeGridLineNames(m_range, lineNames);
4574 if (lineNames && !hasPreviousLineNames)
4575 templateRows->append(lineNames);
4576
4577 // Handle a template-area's row.
4578 if (m_range.peek().type() != StringToken || !consumeGridTemplateAreasRow (m_range.consumeIncludingWhitespace().value(), gridAreaMap, rowCount, columnCoun t))
4579 return false;
4580 ++rowCount;
4581
4582 // Handle template-rows's track-size.
4583 RawPtr<CSSValue> value = consumeGridTrackSize(m_range, m_context.mode()) ;
4584 if (!value)
4585 value = cssValuePool().createIdentifierValue(CSSValueAuto);
4586 templateRows->append(value.release());
4587
4588 // This will handle the trailing/leading <custom-ident>* in the grammar.
4589 lineNames = consumeGridLineNames(m_range);
4590 if (lineNames)
4591 templateRows->append(lineNames);
4592 } while (!m_range.atEnd() && !(m_range.peek().type() == DelimiterToken && m_ range.peek().delimiter() == '/'));
4593
4594 RawPtr<CSSValue> columnsValue = nullptr;
4595 if (!m_range.atEnd()) {
4596 if (!consumeSlashIncludingWhitespace(m_range))
4597 return false;
4598 columnsValue = consumeGridTrackList(m_range, m_context.mode());
4599 if (!columnsValue || !m_range.atEnd())
4600 return false;
4601 } else {
4602 columnsValue = cssValuePool().createIdentifierValue(CSSValueNone);
4603 }
4604 addProperty(CSSPropertyGridTemplateRows, templateRows.release(), important);
4605 addProperty(CSSPropertyGridTemplateColumns, columnsValue.release(), importan t);
4606 addProperty(CSSPropertyGridTemplateAreas, CSSGridTemplateAreasValue::create( gridAreaMap, rowCount, columnCount), important);
4607 return true;
4608 }
4609
4610 bool CSSPropertyParser::consumeGridTemplateShorthand(bool important)
4611 {
4612 ASSERT(RuntimeEnabledFeatures::cssGridLayoutEnabled());
4613 ASSERT(gridTemplateShorthand().length() == 3);
4614
4615 CSSParserTokenRange rangeCopy = m_range;
4616 RawPtr<CSSValue> rowsValue = consumeIdent<CSSValueNone>(m_range);
4617
4618 // 1- 'none' case.
4619 if (rowsValue && m_range.atEnd()) {
4620 addProperty(CSSPropertyGridTemplateRows, cssValuePool().createIdentifier Value(CSSValueNone), important);
4621 addProperty(CSSPropertyGridTemplateColumns, cssValuePool().createIdentif ierValue(CSSValueNone), important);
4622 addProperty(CSSPropertyGridTemplateAreas, cssValuePool().createIdentifie rValue(CSSValueNone), important);
4623 return true;
4624 }
4625
4626 // 2- <grid-template-rows> / <grid-template-columns>
4627 if (!rowsValue)
4628 rowsValue = consumeGridTrackList(m_range, m_context.mode());
4629
4630 if (rowsValue) {
4631 if (!consumeSlashIncludingWhitespace(m_range))
4632 return false;
4633 RawPtr<CSSValue> columnsValue = consumeGridTemplatesRowsOrColumns(m_rang e, m_context.mode());
4634 if (!columnsValue || !m_range.atEnd())
4635 return false;
4636
4637 addProperty(CSSPropertyGridTemplateRows, rowsValue.release(), important) ;
4638 addProperty(CSSPropertyGridTemplateColumns, columnsValue.release(), impo rtant);
4639 addProperty(CSSPropertyGridTemplateAreas, cssValuePool().createIdentifie rValue(CSSValueNone), important);
4640 return true;
4641 }
4642
4643 // 3- [<line-names>? <string> <track-size>? <line-names>? ]+ syntax.
Timothy Loh 2016/04/07 06:48:22 might as well just write it out completely [ <lin
rwlbuis 2016/04/07 19:51:22 Done.
4644 m_range = rangeCopy;
4645 return consumeGridTemplateRowsAndAreasAndColumns(important);
4646 }
4647
4441 bool CSSPropertyParser::parseShorthand(CSSPropertyID unresolvedProperty, bool im portant) 4648 bool CSSPropertyParser::parseShorthand(CSSPropertyID unresolvedProperty, bool im portant)
4442 { 4649 {
4443 CSSPropertyID property = resolveCSSPropertyID(unresolvedProperty); 4650 CSSPropertyID property = resolveCSSPropertyID(unresolvedProperty);
4444 4651
4445 CSSPropertyID oldShorthand = m_currentShorthand; 4652 CSSPropertyID oldShorthand = m_currentShorthand;
4446 // TODO(rob.buis): Remove this when the legacy property parser is gone 4653 // TODO(rob.buis): Remove this when the legacy property parser is gone
4447 m_currentShorthand = property; 4654 m_currentShorthand = property;
4448 switch (property) { 4655 switch (property) {
4449 case CSSPropertyWebkitMarginCollapse: { 4656 case CSSPropertyWebkitMarginCollapse: {
4450 CSSValueID id = m_range.consumeIncludingWhitespace().id(); 4657 CSSValueID id = m_range.consumeIncludingWhitespace().id();
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
4613 columnGap = rowGap; 4820 columnGap = rowGap;
4614 addProperty(CSSPropertyGridRowGap, rowGap.release(), important); 4821 addProperty(CSSPropertyGridRowGap, rowGap.release(), important);
4615 addProperty(CSSPropertyGridColumnGap, columnGap.release(), important); 4822 addProperty(CSSPropertyGridColumnGap, columnGap.release(), important);
4616 return true; 4823 return true;
4617 } 4824 }
4618 case CSSPropertyGridColumn: 4825 case CSSPropertyGridColumn:
4619 case CSSPropertyGridRow: 4826 case CSSPropertyGridRow:
4620 return consumeGridItemPositionShorthand(property, important); 4827 return consumeGridItemPositionShorthand(property, important);
4621 case CSSPropertyGridArea: 4828 case CSSPropertyGridArea:
4622 return consumeGridAreaShorthand(important); 4829 return consumeGridAreaShorthand(important);
4830 case CSSPropertyGridTemplate:
4831 return consumeGridTemplateShorthand(important);
4623 default: 4832 default:
4624 m_currentShorthand = oldShorthand; 4833 m_currentShorthand = oldShorthand;
4625 CSSParserValueList valueList(m_range); 4834 CSSParserValueList valueList(m_range);
4626 if (!valueList.size()) 4835 if (!valueList.size())
4627 return false; 4836 return false;
4628 m_valueList = &valueList; 4837 m_valueList = &valueList;
4629 return legacyParseShorthand(unresolvedProperty, important); 4838 return legacyParseShorthand(unresolvedProperty, important);
4630 } 4839 }
4631 } 4840 }
4632 4841
4633 } // namespace blink 4842 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698