OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2003 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 2003 Lars Knoll (knoll@kde.org) |
3 * Copyright (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com) | 3 * Copyright (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com) |
4 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc.
All rights reserved. | 4 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc.
All rights reserved. |
5 * Copyright (C) 2007 Nicholas Shanks <webkit@nickshanks.com> | 5 * Copyright (C) 2007 Nicholas Shanks <webkit@nickshanks.com> |
6 * Copyright (C) 2008 Eric Seidel <eric@webkit.org> | 6 * Copyright (C) 2008 Eric Seidel <eric@webkit.org> |
7 * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmo
bile.com/) | 7 * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmo
bile.com/) |
8 * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved. | 8 * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved. |
9 * Copyright (C) 2012 Intel Corporation. All rights reserved. | 9 * Copyright (C) 2012 Intel Corporation. All rights reserved. |
10 * | 10 * |
(...skipping 22 matching lines...) Expand all Loading... |
33 #include "core/css/CSSGridLineNamesValue.h" | 33 #include "core/css/CSSGridLineNamesValue.h" |
34 #include "core/css/CSSPrimitiveValueMappings.h" | 34 #include "core/css/CSSPrimitiveValueMappings.h" |
35 #include "core/css/CSSValuePair.h" | 35 #include "core/css/CSSValuePair.h" |
36 #include "core/css/CSSValuePool.h" | 36 #include "core/css/CSSValuePool.h" |
37 #include "core/css/parser/CSSParserValues.h" | 37 #include "core/css/parser/CSSParserValues.h" |
38 #include "core/style/GridArea.h" | 38 #include "core/style/GridArea.h" |
39 #include "platform/RuntimeEnabledFeatures.h" | 39 #include "platform/RuntimeEnabledFeatures.h" |
40 | 40 |
41 namespace blink { | 41 namespace blink { |
42 | 42 |
43 void CSSPropertyParser::addProperty(CSSPropertyID propId, RawPtr<CSSValue> value
, bool important, bool implicit) | 43 void CSSPropertyParser::addProperty(CSSPropertyID propId, CSSValue* value, bool
important, bool implicit) |
44 { | 44 { |
45 ASSERT(!isPropertyAlias(propId)); | 45 ASSERT(!isPropertyAlias(propId)); |
46 | 46 |
47 int shorthandIndex = 0; | 47 int shorthandIndex = 0; |
48 bool setFromShorthand = false; | 48 bool setFromShorthand = false; |
49 | 49 |
50 if (m_currentShorthand) { | 50 if (m_currentShorthand) { |
51 Vector<StylePropertyShorthand, 4> shorthands; | 51 Vector<StylePropertyShorthand, 4> shorthands; |
52 getMatchingShorthandsForLonghand(propId, &shorthands); | 52 getMatchingShorthandsForLonghand(propId, &shorthands); |
53 setFromShorthand = true; | 53 setFromShorthand = true; |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
185 return unitflags & FAngle; | 185 return unitflags & FAngle; |
186 case CSSPrimitiveValue::UnitType::DotsPerPixel: | 186 case CSSPrimitiveValue::UnitType::DotsPerPixel: |
187 case CSSPrimitiveValue::UnitType::DotsPerInch: | 187 case CSSPrimitiveValue::UnitType::DotsPerInch: |
188 case CSSPrimitiveValue::UnitType::DotsPerCentimeter: | 188 case CSSPrimitiveValue::UnitType::DotsPerCentimeter: |
189 return unitflags & FResolution; | 189 return unitflags & FResolution; |
190 default: | 190 default: |
191 return false; | 191 return false; |
192 } | 192 } |
193 } | 193 } |
194 | 194 |
195 RawPtr<CSSPrimitiveValue> CSSPropertyParser::createPrimitiveNumericValue(CSSPars
erValue* value) | 195 CSSPrimitiveValue* CSSPropertyParser::createPrimitiveNumericValue(CSSParserValue
* value) |
196 { | 196 { |
197 if (m_parsedCalculation) { | 197 if (m_parsedCalculation) { |
198 ASSERT(isCalculation(value)); | 198 ASSERT(isCalculation(value)); |
199 return CSSPrimitiveValue::create(m_parsedCalculation.release()); | 199 return CSSPrimitiveValue::create(m_parsedCalculation.release()); |
200 } | 200 } |
201 | 201 |
202 ASSERT((value->unit() >= CSSPrimitiveValue::UnitType::Number && value->unit(
) <= CSSPrimitiveValue::UnitType::Kilohertz) | 202 ASSERT((value->unit() >= CSSPrimitiveValue::UnitType::Number && value->unit(
) <= CSSPrimitiveValue::UnitType::Kilohertz) |
203 || (value->unit() >= CSSPrimitiveValue::UnitType::Turns && value->unit()
<= CSSPrimitiveValue::UnitType::Chs) | 203 || (value->unit() >= CSSPrimitiveValue::UnitType::Turns && value->unit()
<= CSSPrimitiveValue::UnitType::Chs) |
204 || (value->unit() >= CSSPrimitiveValue::UnitType::ViewportWidth && value
->unit() <= CSSPrimitiveValue::UnitType::ViewportMax) | 204 || (value->unit() >= CSSPrimitiveValue::UnitType::ViewportWidth && value
->unit() <= CSSPrimitiveValue::UnitType::ViewportMax) |
205 || (value->unit() >= CSSPrimitiveValue::UnitType::DotsPerPixel && value-
>unit() <= CSSPrimitiveValue::UnitType::DotsPerCentimeter)); | 205 || (value->unit() >= CSSPrimitiveValue::UnitType::DotsPerPixel && value-
>unit() <= CSSPrimitiveValue::UnitType::DotsPerCentimeter)); |
206 return cssValuePool().createValue(value->fValue, value->unit()); | 206 return cssValuePool().createValue(value->fValue, value->unit()); |
207 } | 207 } |
208 | 208 |
209 inline RawPtr<CSSCustomIdentValue> CSSPropertyParser::createPrimitiveCustomIdent
Value(CSSParserValue* value) | 209 inline CSSCustomIdentValue* CSSPropertyParser::createPrimitiveCustomIdentValue(C
SSParserValue* value) |
210 { | 210 { |
211 ASSERT(value->m_unit == CSSParserValue::String || value->m_unit == CSSParser
Value::Identifier); | 211 ASSERT(value->m_unit == CSSParserValue::String || value->m_unit == CSSParser
Value::Identifier); |
212 return CSSCustomIdentValue::create(value->string); | 212 return CSSCustomIdentValue::create(value->string); |
213 } | 213 } |
214 | 214 |
215 static inline bool isComma(CSSParserValue* value) | 215 static inline bool isComma(CSSParserValue* value) |
216 { | 216 { |
217 ASSERT(value); | 217 ASSERT(value); |
218 return value->m_unit == CSSParserValue::Operator && value->iValue == ','; | 218 return value->m_unit == CSSParserValue::Operator && value->iValue == ','; |
219 } | 219 } |
220 | 220 |
221 static inline bool isForwardSlashOperator(CSSParserValue* value) | 221 static inline bool isForwardSlashOperator(CSSParserValue* value) |
222 { | 222 { |
223 ASSERT(value); | 223 ASSERT(value); |
224 return value->m_unit == CSSParserValue::Operator && value->iValue == '/'; | 224 return value->m_unit == CSSParserValue::Operator && value->iValue == '/'; |
225 } | 225 } |
226 | 226 |
227 void CSSPropertyParser::addExpandedPropertyForValue(CSSPropertyID propId, RawPtr
<CSSValue> prpValue, bool important) | 227 void CSSPropertyParser::addExpandedPropertyForValue(CSSPropertyID propId, CSSVal
ue* value, bool important) |
228 { | 228 { |
229 const StylePropertyShorthand& shorthand = shorthandForProperty(propId); | 229 const StylePropertyShorthand& shorthand = shorthandForProperty(propId); |
230 unsigned shorthandLength = shorthand.length(); | 230 unsigned shorthandLength = shorthand.length(); |
231 if (!shorthandLength) { | 231 if (!shorthandLength) { |
232 addProperty(propId, prpValue, important); | 232 addProperty(propId, value, important); |
233 return; | 233 return; |
234 } | 234 } |
235 | 235 |
236 RawPtr<CSSValue> value = prpValue; | |
237 ShorthandScope scope(this, propId); | 236 ShorthandScope scope(this, propId); |
238 const CSSPropertyID* longhands = shorthand.properties(); | 237 const CSSPropertyID* longhands = shorthand.properties(); |
239 for (unsigned i = 0; i < shorthandLength; ++i) | 238 for (unsigned i = 0; i < shorthandLength; ++i) |
240 addProperty(longhands[i], value, important); | 239 addProperty(longhands[i], value, important); |
241 } | 240 } |
242 | 241 |
243 bool CSSPropertyParser::legacyParseAndApplyValue(CSSPropertyID propertyID, bool
important) | 242 bool CSSPropertyParser::legacyParseAndApplyValue(CSSPropertyID propertyID, bool
important) |
244 { | 243 { |
245 RawPtr<CSSValue> result = legacyParseValue(propertyID); | 244 CSSValue* result = legacyParseValue(propertyID); |
246 if (!result) | 245 if (!result) |
247 return false; | 246 return false; |
248 addProperty(propertyID, result.release(), important); | 247 addProperty(propertyID, result, important); |
249 return true; | 248 return true; |
250 } | 249 } |
251 | 250 |
252 RawPtr<CSSValue> CSSPropertyParser::legacyParseValue(CSSPropertyID unresolvedPro
perty) | 251 CSSValue* CSSPropertyParser::legacyParseValue(CSSPropertyID unresolvedProperty) |
253 { | 252 { |
254 CSSPropertyID propId = resolveCSSPropertyID(unresolvedProperty); | 253 CSSPropertyID propId = resolveCSSPropertyID(unresolvedProperty); |
255 | 254 |
256 // Note: m_parsedCalculation is used to pass the calc value to validUnit and
then cleared at the end of this function. | 255 // Note: m_parsedCalculation is used to pass the calc value to validUnit and
then cleared at the end of this function. |
257 // FIXME: This is to avoid having to pass parsedCalc to all validUnit caller
s. | 256 // FIXME: This is to avoid having to pass parsedCalc to all validUnit caller
s. |
258 ASSERT(!m_parsedCalculation); | 257 ASSERT(!m_parsedCalculation); |
259 | 258 |
260 RawPtr<CSSValue> parsedValue = nullptr; | 259 CSSValue* parsedValue = nullptr; |
261 | 260 |
262 switch (propId) { | 261 switch (propId) { |
263 case CSSPropertyGridAutoFlow: | 262 case CSSPropertyGridAutoFlow: |
264 ASSERT(RuntimeEnabledFeatures::cssGridLayoutEnabled()); | 263 ASSERT(RuntimeEnabledFeatures::cssGridLayoutEnabled()); |
265 parsedValue = parseGridAutoFlow(*m_valueList); | 264 parsedValue = parseGridAutoFlow(*m_valueList); |
266 break; | 265 break; |
267 | 266 |
268 // Everything else is handled in CSSPropertyParser.cpp | 267 // Everything else is handled in CSSPropertyParser.cpp |
269 default: | 268 default: |
270 return nullptr; | 269 return nullptr; |
271 } | 270 } |
272 | 271 |
273 ASSERT(!m_parsedCalculation); | 272 ASSERT(!m_parsedCalculation); |
274 if (parsedValue) { | 273 if (parsedValue) { |
275 if (!m_valueList->current() || inShorthand()) | 274 if (!m_valueList->current() || inShorthand()) |
276 return parsedValue.release(); | 275 return parsedValue; |
277 } | 276 } |
278 return nullptr; | 277 return nullptr; |
279 } | 278 } |
280 | 279 |
281 bool CSSPropertyParser::legacyParseShorthand(CSSPropertyID propertyID, bool impo
rtant) | 280 bool CSSPropertyParser::legacyParseShorthand(CSSPropertyID propertyID, bool impo
rtant) |
282 { | 281 { |
283 switch (propertyID) { | 282 switch (propertyID) { |
284 case CSSPropertyGridTemplate: | 283 case CSSPropertyGridTemplate: |
285 ASSERT(RuntimeEnabledFeatures::cssGridLayoutEnabled()); | 284 ASSERT(RuntimeEnabledFeatures::cssGridLayoutEnabled()); |
286 return parseGridTemplateShorthand(important); | 285 return parseGridTemplateShorthand(important); |
(...skipping 12 matching lines...) Expand all Loading... |
299 { | 298 { |
300 return value.id == CSSValueInitial || value.id == CSSValueInherit || value.i
d == CSSValueUnset || value.id == CSSValueDefault; | 299 return value.id == CSSValueInitial || value.id == CSSValueInherit || value.i
d == CSSValueUnset || value.id == CSSValueDefault; |
301 } | 300 } |
302 | 301 |
303 static inline bool isValidCustomIdentForGridPositions(const CSSParserValue& valu
e) | 302 static inline bool isValidCustomIdentForGridPositions(const CSSParserValue& valu
e) |
304 { | 303 { |
305 // FIXME: we need a more general solution for <custom-ident> in all properti
es. | 304 // FIXME: we need a more general solution for <custom-ident> in all properti
es. |
306 return value.m_unit == CSSParserValue::Identifier && value.id != CSSValueSpa
n && value.id != CSSValueAuto && !isCSSWideKeyword(value); | 305 return value.m_unit == CSSParserValue::Identifier && value.id != CSSValueSpa
n && value.id != CSSValueAuto && !isCSSWideKeyword(value); |
307 } | 306 } |
308 | 307 |
309 RawPtr<CSSValue> CSSPropertyParser::parseGridTemplateColumns(bool important) | 308 CSSValue* CSSPropertyParser::parseGridTemplateColumns(bool important) |
310 { | 309 { |
311 if (!(m_valueList->current() && isForwardSlashOperator(m_valueList->current(
)) && m_valueList->next())) | 310 if (!(m_valueList->current() && isForwardSlashOperator(m_valueList->current(
)) && m_valueList->next())) |
312 return nullptr; | 311 return nullptr; |
313 if (RawPtr<CSSValue> columnsValue = parseGridTrackList()) { | 312 if (CSSValue* columnsValue = parseGridTrackList()) { |
314 if (m_valueList->current()) | 313 if (m_valueList->current()) |
315 return nullptr; | 314 return nullptr; |
316 return columnsValue; | 315 return columnsValue; |
317 } | 316 } |
318 | 317 |
319 return nullptr; | 318 return nullptr; |
320 } | 319 } |
321 | 320 |
322 bool CSSPropertyParser::parseGridTemplateRowsAndAreasAndColumns(bool important) | 321 bool CSSPropertyParser::parseGridTemplateRowsAndAreasAndColumns(bool important) |
323 { | 322 { |
324 NamedGridAreaMap gridAreaMap; | 323 NamedGridAreaMap gridAreaMap; |
325 size_t rowCount = 0; | 324 size_t rowCount = 0; |
326 size_t columnCount = 0; | 325 size_t columnCount = 0; |
327 bool trailingIdentWasAdded = false; | 326 bool trailingIdentWasAdded = false; |
328 RawPtr<CSSValueList> templateRows = CSSValueList::createSpaceSeparated(); | 327 CSSValueList* templateRows = CSSValueList::createSpaceSeparated(); |
329 | 328 |
330 // At least template-areas strings must be defined. | 329 // At least template-areas strings must be defined. |
331 if (!m_valueList->current() || isForwardSlashOperator(m_valueList->current()
)) | 330 if (!m_valueList->current() || isForwardSlashOperator(m_valueList->current()
)) |
332 return false; | 331 return false; |
333 | 332 |
334 while (m_valueList->current() && !isForwardSlashOperator(m_valueList->curren
t())) { | 333 while (m_valueList->current() && !isForwardSlashOperator(m_valueList->curren
t())) { |
335 // Handle leading <custom-ident>*. | 334 // Handle leading <custom-ident>*. |
336 if (!parseGridLineNames(*m_valueList, *templateRows, trailingIdentWasAdd
ed ? toCSSGridLineNamesValue(templateRows->item(templateRows->length() - 1)) : n
ullptr)) | 335 if (!parseGridLineNames(*m_valueList, *templateRows, trailingIdentWasAdd
ed ? toCSSGridLineNamesValue(templateRows->item(templateRows->length() - 1)) : n
ullptr)) |
337 return false; | 336 return false; |
338 | 337 |
339 // Handle a template-area's row. | 338 // Handle a template-area's row. |
340 CSSParserValue* currentValue = m_valueList->current(); | 339 CSSParserValue* currentValue = m_valueList->current(); |
341 if (!currentValue || currentValue->m_unit != CSSParserValue::String) | 340 if (!currentValue || currentValue->m_unit != CSSParserValue::String) |
342 return false; | 341 return false; |
343 if (!parseGridTemplateAreasRow(currentValue->string, gridAreaMap, rowCou
nt, columnCount)) | 342 if (!parseGridTemplateAreasRow(currentValue->string, gridAreaMap, rowCou
nt, columnCount)) |
344 return false; | 343 return false; |
345 m_valueList->next(); | 344 m_valueList->next(); |
346 ++rowCount; | 345 ++rowCount; |
347 | 346 |
348 // Handle template-rows's track-size. | 347 // Handle template-rows's track-size. |
349 if (m_valueList->current() && m_valueList->current()->m_unit != CSSParse
rValue::Operator && m_valueList->current()->m_unit != CSSParserValue::String) { | 348 if (m_valueList->current() && m_valueList->current()->m_unit != CSSParse
rValue::Operator && m_valueList->current()->m_unit != CSSParserValue::String) { |
350 RawPtr<CSSValue> value = parseGridTrackSize(*m_valueList); | 349 CSSValue* value = parseGridTrackSize(*m_valueList); |
351 if (!value) | 350 if (!value) |
352 return false; | 351 return false; |
353 templateRows->append(value); | 352 templateRows->append(value); |
354 } else { | 353 } else { |
355 templateRows->append(cssValuePool().createIdentifierValue(CSSValueAu
to)); | 354 templateRows->append(cssValuePool().createIdentifierValue(CSSValueAu
to)); |
356 } | 355 } |
357 | 356 |
358 // This will handle the trailing/leading <custom-ident>* in the grammar. | 357 // This will handle the trailing/leading <custom-ident>* in the grammar. |
359 if (!parseGridLineNames(*m_valueList, *templateRows)) | 358 if (!parseGridLineNames(*m_valueList, *templateRows)) |
360 return false; | 359 return false; |
361 trailingIdentWasAdded = templateRows->item(templateRows->length() - 1)->
isGridLineNamesValue(); | 360 trailingIdentWasAdded = templateRows->item(templateRows->length() - 1)->
isGridLineNamesValue(); |
362 } | 361 } |
363 | 362 |
364 RawPtr<CSSValue> columnsValue = nullptr; | 363 CSSValue* columnsValue = nullptr; |
365 if (m_valueList->current()) { | 364 if (m_valueList->current()) { |
366 ASSERT(isForwardSlashOperator(m_valueList->current())); | 365 ASSERT(isForwardSlashOperator(m_valueList->current())); |
367 columnsValue = parseGridTemplateColumns(important); | 366 columnsValue = parseGridTemplateColumns(important); |
368 if (!columnsValue) | 367 if (!columnsValue) |
369 return false; | 368 return false; |
370 // The template-columns <track-list> can't be 'none'. | 369 // The template-columns <track-list> can't be 'none'. |
371 if (columnsValue->isPrimitiveValue() && toCSSPrimitiveValue(*columnsValu
e).getValueID() == CSSValueNone) | 370 if (columnsValue->isPrimitiveValue() && toCSSPrimitiveValue(*columnsValu
e).getValueID() == CSSValueNone) |
372 return false; | 371 return false; |
373 } | 372 } |
374 | 373 |
375 addProperty(CSSPropertyGridTemplateRows, templateRows.release(), important); | 374 addProperty(CSSPropertyGridTemplateRows, templateRows, important); |
376 addProperty(CSSPropertyGridTemplateColumns, columnsValue ? columnsValue.rele
ase() : cssValuePool().createIdentifierValue(CSSValueNone), important); | 375 addProperty(CSSPropertyGridTemplateColumns, columnsValue ? columnsValue : cs
sValuePool().createIdentifierValue(CSSValueNone), important); |
377 | 376 |
378 RawPtr<CSSValue> templateAreas = CSSGridTemplateAreasValue::create(gridAreaM
ap, rowCount, columnCount); | 377 CSSValue* templateAreas = CSSGridTemplateAreasValue::create(gridAreaMap, row
Count, columnCount); |
379 addProperty(CSSPropertyGridTemplateAreas, templateAreas.release(), important
); | 378 addProperty(CSSPropertyGridTemplateAreas, templateAreas, important); |
380 | 379 |
381 return true; | 380 return true; |
382 } | 381 } |
383 | 382 |
384 | 383 |
385 bool CSSPropertyParser::parseGridTemplateShorthand(bool important) | 384 bool CSSPropertyParser::parseGridTemplateShorthand(bool important) |
386 { | 385 { |
387 ASSERT(RuntimeEnabledFeatures::cssGridLayoutEnabled()); | 386 ASSERT(RuntimeEnabledFeatures::cssGridLayoutEnabled()); |
388 | 387 |
389 ShorthandScope scope(this, CSSPropertyGridTemplate); | 388 ShorthandScope scope(this, CSSPropertyGridTemplate); |
390 ASSERT(gridTemplateShorthand().length() == 3); | 389 ASSERT(gridTemplateShorthand().length() == 3); |
391 | 390 |
392 // At least "none" must be defined. | 391 // At least "none" must be defined. |
393 if (!m_valueList->current()) | 392 if (!m_valueList->current()) |
394 return false; | 393 return false; |
395 | 394 |
396 bool firstValueIsNone = m_valueList->current()->id == CSSValueNone; | 395 bool firstValueIsNone = m_valueList->current()->id == CSSValueNone; |
397 | 396 |
398 // 1- 'none' case. | 397 // 1- 'none' case. |
399 if (firstValueIsNone && !m_valueList->next()) { | 398 if (firstValueIsNone && !m_valueList->next()) { |
400 addProperty(CSSPropertyGridTemplateColumns, cssValuePool().createIdentif
ierValue(CSSValueNone), important); | 399 addProperty(CSSPropertyGridTemplateColumns, cssValuePool().createIdentif
ierValue(CSSValueNone), important); |
401 addProperty(CSSPropertyGridTemplateRows, cssValuePool().createIdentifier
Value(CSSValueNone), important); | 400 addProperty(CSSPropertyGridTemplateRows, cssValuePool().createIdentifier
Value(CSSValueNone), important); |
402 addProperty(CSSPropertyGridTemplateAreas, cssValuePool().createIdentifie
rValue(CSSValueNone), important); | 401 addProperty(CSSPropertyGridTemplateAreas, cssValuePool().createIdentifie
rValue(CSSValueNone), important); |
403 return true; | 402 return true; |
404 } | 403 } |
405 | 404 |
406 // 2- <grid-template-rows> / <grid-template-columns> | 405 // 2- <grid-template-rows> / <grid-template-columns> |
407 RawPtr<CSSValue> rowsValue = nullptr; | 406 CSSValue* rowsValue = nullptr; |
408 if (firstValueIsNone) { | 407 if (firstValueIsNone) { |
409 rowsValue = cssValuePool().createIdentifierValue(CSSValueNone); | 408 rowsValue = cssValuePool().createIdentifierValue(CSSValueNone); |
410 } else { | 409 } else { |
411 rowsValue = parseGridTrackList(); | 410 rowsValue = parseGridTrackList(); |
412 } | 411 } |
413 | 412 |
414 if (rowsValue) { | 413 if (rowsValue) { |
415 RawPtr<CSSValue> columnsValue = parseGridTemplateColumns(important); | 414 CSSValue* columnsValue = parseGridTemplateColumns(important); |
416 if (!columnsValue) | 415 if (!columnsValue) |
417 return false; | 416 return false; |
418 | 417 |
419 addProperty(CSSPropertyGridTemplateRows, rowsValue.release(), important)
; | 418 addProperty(CSSPropertyGridTemplateRows, rowsValue, important); |
420 addProperty(CSSPropertyGridTemplateColumns, columnsValue.release(), impo
rtant); | 419 addProperty(CSSPropertyGridTemplateColumns, columnsValue, important); |
421 addProperty(CSSPropertyGridTemplateAreas, cssValuePool().createIdentifie
rValue(CSSValueNone), important); | 420 addProperty(CSSPropertyGridTemplateAreas, cssValuePool().createIdentifie
rValue(CSSValueNone), important); |
422 return true; | 421 return true; |
423 } | 422 } |
424 | 423 |
425 // 3- [<line-names>? <string> <track-size>? <line-names>? ]+ syntax. | 424 // 3- [<line-names>? <string> <track-size>? <line-names>? ]+ syntax. |
426 // It requires to rewind parsing due to previous syntax failures. | 425 // It requires to rewind parsing due to previous syntax failures. |
427 m_valueList->setCurrentIndex(0); | 426 m_valueList->setCurrentIndex(0); |
428 return parseGridTemplateRowsAndAreasAndColumns(important); | 427 return parseGridTemplateRowsAndAreasAndColumns(important); |
429 } | 428 } |
430 | 429 |
(...skipping 14 matching lines...) Expand all Loading... |
445 return true; | 444 return true; |
446 } | 445 } |
447 | 446 |
448 // Need to rewind parsing to explore the alternative syntax of this shorthan
d. | 447 // Need to rewind parsing to explore the alternative syntax of this shorthan
d. |
449 m_valueList->setCurrentIndex(0); | 448 m_valueList->setCurrentIndex(0); |
450 | 449 |
451 // 2- <grid-auto-flow> [ <grid-auto-rows> [ / <grid-auto-columns> ]? ] | 450 // 2- <grid-auto-flow> [ <grid-auto-rows> [ / <grid-auto-columns> ]? ] |
452 if (!legacyParseAndApplyValue(CSSPropertyGridAutoFlow, important)) | 451 if (!legacyParseAndApplyValue(CSSPropertyGridAutoFlow, important)) |
453 return false; | 452 return false; |
454 | 453 |
455 RawPtr<CSSValue> autoColumnsValue = nullptr; | 454 CSSValue* autoColumnsValue = nullptr; |
456 RawPtr<CSSValue> autoRowsValue = nullptr; | 455 CSSValue* autoRowsValue = nullptr; |
457 | 456 |
458 if (m_valueList->current()) { | 457 if (m_valueList->current()) { |
459 autoRowsValue = parseGridTrackSize(*m_valueList); | 458 autoRowsValue = parseGridTrackSize(*m_valueList); |
460 if (!autoRowsValue) | 459 if (!autoRowsValue) |
461 return false; | 460 return false; |
462 if (m_valueList->current()) { | 461 if (m_valueList->current()) { |
463 if (!isForwardSlashOperator(m_valueList->current()) || !m_valueList-
>next()) | 462 if (!isForwardSlashOperator(m_valueList->current()) || !m_valueList-
>next()) |
464 return false; | 463 return false; |
465 autoColumnsValue = parseGridTrackSize(*m_valueList); | 464 autoColumnsValue = parseGridTrackSize(*m_valueList); |
466 if (!autoColumnsValue) | 465 if (!autoColumnsValue) |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
498 } | 497 } |
499 | 498 |
500 bool CSSPropertyParser::parseGridLineNames(CSSParserValueList& inputList, CSSVal
ueList& valueList, CSSGridLineNamesValue* previousNamedAreaTrailingLineNames) | 499 bool CSSPropertyParser::parseGridLineNames(CSSParserValueList& inputList, CSSVal
ueList& valueList, CSSGridLineNamesValue* previousNamedAreaTrailingLineNames) |
501 { | 500 { |
502 if (!inputList.current() || inputList.current()->m_unit != CSSParserValue::O
perator || inputList.current()->iValue != '[') | 501 if (!inputList.current() || inputList.current()->m_unit != CSSParserValue::O
perator || inputList.current()->iValue != '[') |
503 return true; | 502 return true; |
504 | 503 |
505 // Skip '[' | 504 // Skip '[' |
506 inputList.next(); | 505 inputList.next(); |
507 | 506 |
508 RawPtr<CSSGridLineNamesValue> lineNames = previousNamedAreaTrailingLineNames
; | 507 CSSGridLineNamesValue* lineNames = previousNamedAreaTrailingLineNames; |
509 if (!lineNames) | 508 if (!lineNames) |
510 lineNames = CSSGridLineNamesValue::create(); | 509 lineNames = CSSGridLineNamesValue::create(); |
511 | 510 |
512 while (CSSParserValue* identValue = inputList.current()) { | 511 while (CSSParserValue* identValue = inputList.current()) { |
513 if (isClosingBracket(*identValue)) | 512 if (isClosingBracket(*identValue)) |
514 break; | 513 break; |
515 | 514 |
516 if (!isValidCustomIdentForGridPositions(*identValue)) | 515 if (!isValidCustomIdentForGridPositions(*identValue)) |
517 return false; | 516 return false; |
518 | 517 |
519 RawPtr<CSSCustomIdentValue> lineName = createPrimitiveCustomIdentValue(i
dentValue); | 518 CSSCustomIdentValue* lineName = createPrimitiveCustomIdentValue(identVal
ue); |
520 lineNames->append(lineName.release()); | 519 lineNames->append(lineName); |
521 inputList.next(); | 520 inputList.next(); |
522 } | 521 } |
523 | 522 |
524 if (!inputList.current() || !isClosingBracket(*inputList.current())) | 523 if (!inputList.current() || !isClosingBracket(*inputList.current())) |
525 return false; | 524 return false; |
526 | 525 |
527 if (!previousNamedAreaTrailingLineNames) | 526 if (!previousNamedAreaTrailingLineNames) |
528 valueList.append(lineNames.release()); | 527 valueList.append(lineNames); |
529 | 528 |
530 // Consume ']' | 529 // Consume ']' |
531 inputList.next(); | 530 inputList.next(); |
532 return true; | 531 return true; |
533 } | 532 } |
534 | 533 |
535 bool allTracksAreFixedSized(CSSValueList& valueList) | 534 bool allTracksAreFixedSized(CSSValueList& valueList) |
536 { | 535 { |
537 for (auto value : valueList) { | 536 for (auto value : valueList) { |
538 if (value->isGridLineNamesValue()) | 537 if (value->isGridLineNamesValue()) |
539 continue; | 538 continue; |
540 // The auto-repeat value holds a <fixed-size> = <fixed-breadth> | minmax
( <fixed-breadth>, <track-breadth> ) | 539 // The auto-repeat value holds a <fixed-size> = <fixed-breadth> | minmax
( <fixed-breadth>, <track-breadth> ) |
541 if (value->isGridAutoRepeatValue()) { | 540 if (value->isGridAutoRepeatValue()) { |
542 if (!allTracksAreFixedSized(toCSSValueList(*value))) | 541 if (!allTracksAreFixedSized(toCSSValueList(*value))) |
543 return false; | 542 return false; |
544 continue; | 543 continue; |
545 } | 544 } |
546 ASSERT(value->isPrimitiveValue() || (value->isFunctionValue() && toCSSFu
nctionValue(*value).item(0))); | 545 ASSERT(value->isPrimitiveValue() || (value->isFunctionValue() && toCSSFu
nctionValue(*value).item(0))); |
547 const CSSPrimitiveValue& primitiveValue = value->isPrimitiveValue() | 546 const CSSPrimitiveValue& primitiveValue = value->isPrimitiveValue() |
548 ? toCSSPrimitiveValue(*value) | 547 ? toCSSPrimitiveValue(*value) |
549 : toCSSPrimitiveValue(*toCSSFunctionValue(*value).item(0)); | 548 : toCSSPrimitiveValue(*toCSSFunctionValue(*value).item(0)); |
550 CSSValueID valueID = primitiveValue.getValueID(); | 549 CSSValueID valueID = primitiveValue.getValueID(); |
551 if (valueID == CSSValueMinContent || valueID == CSSValueMaxContent || va
lueID == CSSValueAuto || primitiveValue.isFlex()) | 550 if (valueID == CSSValueMinContent || valueID == CSSValueMaxContent || va
lueID == CSSValueAuto || primitiveValue.isFlex()) |
552 return false; | 551 return false; |
553 } | 552 } |
554 return true; | 553 return true; |
555 } | 554 } |
556 | 555 |
557 RawPtr<CSSValue> CSSPropertyParser::parseGridTrackList() | 556 CSSValue* CSSPropertyParser::parseGridTrackList() |
558 { | 557 { |
559 ASSERT(RuntimeEnabledFeatures::cssGridLayoutEnabled()); | 558 ASSERT(RuntimeEnabledFeatures::cssGridLayoutEnabled()); |
560 | 559 |
561 CSSParserValue* value = m_valueList->current(); | 560 CSSParserValue* value = m_valueList->current(); |
562 if (value->id == CSSValueNone) { | 561 if (value->id == CSSValueNone) { |
563 m_valueList->next(); | 562 m_valueList->next(); |
564 return cssValuePool().createIdentifierValue(CSSValueNone); | 563 return cssValuePool().createIdentifierValue(CSSValueNone); |
565 } | 564 } |
566 | 565 |
567 RawPtr<CSSValueList> values = CSSValueList::createSpaceSeparated(); | 566 CSSValueList* values = CSSValueList::createSpaceSeparated(); |
568 // Handle leading <custom-ident>*. | 567 // Handle leading <custom-ident>*. |
569 if (!parseGridLineNames(*m_valueList, *values)) | 568 if (!parseGridLineNames(*m_valueList, *values)) |
570 return nullptr; | 569 return nullptr; |
571 | 570 |
572 bool seenTrackSizeOrRepeatFunction = false; | 571 bool seenTrackSizeOrRepeatFunction = false; |
573 bool seenAutoRepeat = false; | 572 bool seenAutoRepeat = false; |
574 while (CSSParserValue* currentValue = m_valueList->current()) { | 573 while (CSSParserValue* currentValue = m_valueList->current()) { |
575 if (isForwardSlashOperator(currentValue)) | 574 if (isForwardSlashOperator(currentValue)) |
576 break; | 575 break; |
577 if (currentValue->m_unit == CSSParserValue::Function && currentValue->fu
nction->id == CSSValueRepeat) { | 576 if (currentValue->m_unit == CSSParserValue::Function && currentValue->fu
nction->id == CSSValueRepeat) { |
578 bool isAutoRepeat; | 577 bool isAutoRepeat; |
579 if (!parseGridTrackRepeatFunction(*values, isAutoRepeat)) | 578 if (!parseGridTrackRepeatFunction(*values, isAutoRepeat)) |
580 return nullptr; | 579 return nullptr; |
581 if (isAutoRepeat && seenAutoRepeat) | 580 if (isAutoRepeat && seenAutoRepeat) |
582 return nullptr; | 581 return nullptr; |
583 seenTrackSizeOrRepeatFunction = true; | 582 seenTrackSizeOrRepeatFunction = true; |
584 seenAutoRepeat = seenAutoRepeat || isAutoRepeat; | 583 seenAutoRepeat = seenAutoRepeat || isAutoRepeat; |
585 } else { | 584 } else { |
586 RawPtr<CSSValue> value = parseGridTrackSize(*m_valueList, seenAutoRe
peat ? FixedSizeOnly : AllowAll); | 585 CSSValue* value = parseGridTrackSize(*m_valueList, seenAutoRepeat ?
FixedSizeOnly : AllowAll); |
587 if (!value) | 586 if (!value) |
588 return nullptr; | 587 return nullptr; |
589 values->append(value); | 588 values->append(value); |
590 seenTrackSizeOrRepeatFunction = true; | 589 seenTrackSizeOrRepeatFunction = true; |
591 } | 590 } |
592 // This will handle the trailing <custom-ident>* in the grammar. | 591 // This will handle the trailing <custom-ident>* in the grammar. |
593 if (!parseGridLineNames(*m_valueList, *values)) | 592 if (!parseGridLineNames(*m_valueList, *values)) |
594 return nullptr; | 593 return nullptr; |
595 } | 594 } |
596 | 595 |
(...skipping 17 matching lines...) Expand all Loading... |
614 | 613 |
615 CSSParserValue* currentValue = arguments->valueAt(0); | 614 CSSParserValue* currentValue = arguments->valueAt(0); |
616 isAutoRepeat = currentValue->id == CSSValueAutoFill || currentValue->id == C
SSValueAutoFit; | 615 isAutoRepeat = currentValue->id == CSSValueAutoFill || currentValue->id == C
SSValueAutoFit; |
617 if (!isAutoRepeat && !validUnit(currentValue, FPositiveInteger)) | 616 if (!isAutoRepeat && !validUnit(currentValue, FPositiveInteger)) |
618 return false; | 617 return false; |
619 | 618 |
620 // The number of repetitions for <auto-repeat> is not important at parsing l
evel | 619 // The number of repetitions for <auto-repeat> is not important at parsing l
evel |
621 // because it will be computed later, let's set it to 1. | 620 // because it will be computed later, let's set it to 1. |
622 size_t repetitions = isAutoRepeat ? 1 : clampTo<size_t>(currentValue->fValue
, 0, kGridMaxTracks); | 621 size_t repetitions = isAutoRepeat ? 1 : clampTo<size_t>(currentValue->fValue
, 0, kGridMaxTracks); |
623 | 622 |
624 RawPtr<CSSValueList> repeatedValues = isAutoRepeat ? CSSGridAutoRepeatValue:
:create(currentValue->id) : CSSValueList::createSpaceSeparated(); | 623 CSSValueList* repeatedValues = isAutoRepeat ? CSSGridAutoRepeatValue::create
(currentValue->id) : CSSValueList::createSpaceSeparated(); |
625 arguments->next(); // Skip the repetition count. | 624 arguments->next(); // Skip the repetition count. |
626 arguments->next(); // Skip the comma. | 625 arguments->next(); // Skip the comma. |
627 | 626 |
628 // Handle leading <custom-ident>*. | 627 // Handle leading <custom-ident>*. |
629 if (!parseGridLineNames(*arguments, *repeatedValues)) | 628 if (!parseGridLineNames(*arguments, *repeatedValues)) |
630 return false; | 629 return false; |
631 | 630 |
632 size_t numberOfTracks = 0; | 631 size_t numberOfTracks = 0; |
633 TrackSizeRestriction restriction = isAutoRepeat ? FixedSizeOnly : AllowAll; | 632 TrackSizeRestriction restriction = isAutoRepeat ? FixedSizeOnly : AllowAll; |
634 while (arguments->current()) { | 633 while (arguments->current()) { |
635 if (isAutoRepeat && numberOfTracks) | 634 if (isAutoRepeat && numberOfTracks) |
636 return false; | 635 return false; |
637 | 636 |
638 RawPtr<CSSValue> trackSize = parseGridTrackSize(*arguments, restriction)
; | 637 CSSValue* trackSize = parseGridTrackSize(*arguments, restriction); |
639 if (!trackSize) | 638 if (!trackSize) |
640 return false; | 639 return false; |
641 | 640 |
642 repeatedValues->append(trackSize); | 641 repeatedValues->append(trackSize); |
643 ++numberOfTracks; | 642 ++numberOfTracks; |
644 | 643 |
645 // This takes care of any trailing <custom-ident>* in the grammar. | 644 // This takes care of any trailing <custom-ident>* in the grammar. |
646 if (!parseGridLineNames(*arguments, *repeatedValues)) | 645 if (!parseGridLineNames(*arguments, *repeatedValues)) |
647 return false; | 646 return false; |
648 } | 647 } |
649 | 648 |
650 // We should have found at least one <track-size> or else it is not a valid
<track-list>. | 649 // We should have found at least one <track-size> or else it is not a valid
<track-list>. |
651 if (!numberOfTracks) | 650 if (!numberOfTracks) |
652 return false; | 651 return false; |
653 | 652 |
654 if (isAutoRepeat) { | 653 if (isAutoRepeat) { |
655 list.append(repeatedValues.release()); | 654 list.append(repeatedValues); |
656 } else { | 655 } else { |
657 // We clamp the number of repetitions to a multiple of the repeat() trac
k list's size, while staying below the max | 656 // We clamp the number of repetitions to a multiple of the repeat() trac
k list's size, while staying below the max |
658 // grid size. | 657 // grid size. |
659 repetitions = std::min(repetitions, kGridMaxTracks / numberOfTracks); | 658 repetitions = std::min(repetitions, kGridMaxTracks / numberOfTracks); |
660 | 659 |
661 for (size_t i = 0; i < repetitions; ++i) { | 660 for (size_t i = 0; i < repetitions; ++i) { |
662 for (size_t j = 0; j < repeatedValues->length(); ++j) | 661 for (size_t j = 0; j < repeatedValues->length(); ++j) |
663 list.append(repeatedValues->item(j)); | 662 list.append(repeatedValues->item(j)); |
664 } | 663 } |
665 } | 664 } |
666 | 665 |
667 // parseGridTrackSize iterated over the repeat arguments, move to the next v
alue. | 666 // parseGridTrackSize iterated over the repeat arguments, move to the next v
alue. |
668 m_valueList->next(); | 667 m_valueList->next(); |
669 return true; | 668 return true; |
670 } | 669 } |
671 | 670 |
672 | 671 |
673 RawPtr<CSSValue> CSSPropertyParser::parseGridTrackSize(CSSParserValueList& input
List, TrackSizeRestriction restriction) | 672 CSSValue* CSSPropertyParser::parseGridTrackSize(CSSParserValueList& inputList, T
rackSizeRestriction restriction) |
674 { | 673 { |
675 ASSERT(RuntimeEnabledFeatures::cssGridLayoutEnabled()); | 674 ASSERT(RuntimeEnabledFeatures::cssGridLayoutEnabled()); |
676 | 675 |
677 CSSParserValue* currentValue = inputList.current(); | 676 CSSParserValue* currentValue = inputList.current(); |
678 inputList.next(); | 677 inputList.next(); |
679 | 678 |
680 if (currentValue->id == CSSValueAuto) | 679 if (currentValue->id == CSSValueAuto) |
681 return restriction == AllowAll ? cssValuePool().createIdentifierValue(CS
SValueAuto) : nullptr; | 680 return restriction == AllowAll ? cssValuePool().createIdentifierValue(CS
SValueAuto) : nullptr; |
682 | 681 |
683 if (currentValue->m_unit == CSSParserValue::Function && currentValue->functi
on->id == CSSValueMinmax) { | 682 if (currentValue->m_unit == CSSParserValue::Function && currentValue->functi
on->id == CSSValueMinmax) { |
684 // The spec defines the following grammar: minmax( <track-breadth> , <tr
ack-breadth> ) | 683 // The spec defines the following grammar: minmax( <track-breadth> , <tr
ack-breadth> ) |
685 CSSParserValueList* arguments = currentValue->function->args.get(); | 684 CSSParserValueList* arguments = currentValue->function->args.get(); |
686 if (!arguments || arguments->size() != 3 || !isComma(arguments->valueAt(
1))) | 685 if (!arguments || arguments->size() != 3 || !isComma(arguments->valueAt(
1))) |
687 return nullptr; | 686 return nullptr; |
688 | 687 |
689 RawPtr<CSSPrimitiveValue> minTrackBreadth = parseGridBreadth(arguments->
valueAt(0), restriction); | 688 CSSPrimitiveValue* minTrackBreadth = parseGridBreadth(arguments->valueAt
(0), restriction); |
690 if (!minTrackBreadth) | 689 if (!minTrackBreadth) |
691 return nullptr; | 690 return nullptr; |
692 | 691 |
693 RawPtr<CSSPrimitiveValue> maxTrackBreadth = parseGridBreadth(arguments->
valueAt(2)); | 692 CSSPrimitiveValue* maxTrackBreadth = parseGridBreadth(arguments->valueAt
(2)); |
694 if (!maxTrackBreadth) | 693 if (!maxTrackBreadth) |
695 return nullptr; | 694 return nullptr; |
696 | 695 |
697 RawPtr<CSSFunctionValue> result = CSSFunctionValue::create(CSSValueMinma
x); | 696 CSSFunctionValue* result = CSSFunctionValue::create(CSSValueMinmax); |
698 result->append(minTrackBreadth); | 697 result->append(minTrackBreadth); |
699 result->append(maxTrackBreadth); | 698 result->append(maxTrackBreadth); |
700 return result.release(); | 699 return result; |
701 } | 700 } |
702 | 701 |
703 return parseGridBreadth(currentValue, restriction); | 702 return parseGridBreadth(currentValue, restriction); |
704 } | 703 } |
705 | 704 |
706 RawPtr<CSSPrimitiveValue> CSSPropertyParser::parseGridBreadth(CSSParserValue* cu
rrentValue, TrackSizeRestriction restriction) | 705 CSSPrimitiveValue* CSSPropertyParser::parseGridBreadth(CSSParserValue* currentVa
lue, TrackSizeRestriction restriction) |
707 { | 706 { |
708 if (currentValue->id == CSSValueMinContent || currentValue->id == CSSValueMa
xContent || currentValue->id == CSSValueAuto) | 707 if (currentValue->id == CSSValueMinContent || currentValue->id == CSSValueMa
xContent || currentValue->id == CSSValueAuto) |
709 return restriction == AllowAll ? cssValuePool().createIdentifierValue(cu
rrentValue->id) : nullptr; | 708 return restriction == AllowAll ? cssValuePool().createIdentifierValue(cu
rrentValue->id) : nullptr; |
710 | 709 |
711 if (currentValue->unit() == CSSPrimitiveValue::UnitType::Fraction) { | 710 if (currentValue->unit() == CSSPrimitiveValue::UnitType::Fraction) { |
712 if (restriction == FixedSizeOnly) | 711 if (restriction == FixedSizeOnly) |
713 return nullptr; | 712 return nullptr; |
714 | 713 |
715 double flexValue = currentValue->fValue; | 714 double flexValue = currentValue->fValue; |
716 | 715 |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
814 return false; | 813 return false; |
815 | 814 |
816 gridArea.rows = GridSpan::translatedDefiniteGridSpan(gridArea.rows.s
tartLine(), gridArea.rows.endLine() + 1); | 815 gridArea.rows = GridSpan::translatedDefiniteGridSpan(gridArea.rows.s
tartLine(), gridArea.rows.endLine() + 1); |
817 } | 816 } |
818 currentCol = lookAheadCol - 1; | 817 currentCol = lookAheadCol - 1; |
819 } | 818 } |
820 | 819 |
821 return true; | 820 return true; |
822 } | 821 } |
823 | 822 |
824 RawPtr<CSSValue> CSSPropertyParser::parseGridAutoFlow(CSSParserValueList& list) | 823 CSSValue* CSSPropertyParser::parseGridAutoFlow(CSSParserValueList& list) |
825 { | 824 { |
826 // [ row | column ] || dense | 825 // [ row | column ] || dense |
827 ASSERT(RuntimeEnabledFeatures::cssGridLayoutEnabled()); | 826 ASSERT(RuntimeEnabledFeatures::cssGridLayoutEnabled()); |
828 | 827 |
829 CSSParserValue* value = list.current(); | 828 CSSParserValue* value = list.current(); |
830 if (!value) | 829 if (!value) |
831 return nullptr; | 830 return nullptr; |
832 | 831 |
833 RawPtr<CSSValueList> parsedValues = CSSValueList::createSpaceSeparated(); | 832 CSSValueList* parsedValues = CSSValueList::createSpaceSeparated(); |
834 | 833 |
835 // First parameter. | 834 // First parameter. |
836 CSSValueID firstId = value->id; | 835 CSSValueID firstId = value->id; |
837 if (firstId != CSSValueRow && firstId != CSSValueColumn && firstId != CSSVal
ueDense) | 836 if (firstId != CSSValueRow && firstId != CSSValueColumn && firstId != CSSVal
ueDense) |
838 return nullptr; | 837 return nullptr; |
839 parsedValues->append(cssValuePool().createIdentifierValue(firstId)); | 838 parsedValues->append(cssValuePool().createIdentifierValue(firstId)); |
840 | 839 |
841 // Second parameter, if any. | 840 // Second parameter, if any. |
842 value = list.next(); | 841 value = list.next(); |
843 if (value) { | 842 if (value) { |
(...skipping 26 matching lines...) Expand all Loading... |
870 ASSERT(!m_parsedCalculation); | 869 ASSERT(!m_parsedCalculation); |
871 m_parsedCalculation = CSSCalcValue::create(args, range); | 870 m_parsedCalculation = CSSCalcValue::create(args, range); |
872 | 871 |
873 if (!m_parsedCalculation) | 872 if (!m_parsedCalculation) |
874 return false; | 873 return false; |
875 | 874 |
876 return true; | 875 return true; |
877 } | 876 } |
878 | 877 |
879 } // namespace blink | 878 } // namespace blink |
OLD | NEW |