Provide a way for web developers to draw a Theme-specific Wireless Playback icon
[WebKit-https.git] / Source / WebCore / css / CSSParser.cpp
1 /*
2  * Copyright (C) 2003 Lars Knoll (knoll@kde.org)
3  * Copyright (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com)
4  * Copyright (C) 2004-2015 Apple Inc. All rights reserved.
5  * Copyright (C) 2007 Nicholas Shanks <webkit@nickshanks.com>
6  * Copyright (C) 2008 Eric Seidel <eric@webkit.org>
7  * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
8  * Copyright (C) 2012, 2013 Adobe Systems Incorporated. All rights reserved.
9  * Copyright (C) 2012 Intel Corporation. All rights reserved.
10  * Copyright (C) 2014 Google Inc. All rights reserved.
11  *
12  * This library is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU Library General Public
14  * License as published by the Free Software Foundation; either
15  * version 2 of the License, or (at your option) any later version.
16  *
17  * This library is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20  * Library General Public License for more details.
21  *
22  * You should have received a copy of the GNU Library General Public License
23  * along with this library; see the file COPYING.LIB.  If not, write to
24  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
25  * Boston, MA 02110-1301, USA.
26  */
27
28 #include "config.h"
29 #include "CSSParser.h"
30
31 #include "CSSAnimationTriggerScrollValue.h"
32 #include "CSSAspectRatioValue.h"
33 #include "CSSBasicShapes.h"
34 #include "CSSBorderImage.h"
35 #include "CSSCanvasValue.h"
36 #include "CSSContentDistributionValue.h"
37 #include "CSSCrossfadeValue.h"
38 #include "CSSCursorImageValue.h"
39 #include "CSSFilterImageValue.h"
40 #include "CSSFontFaceRule.h"
41 #include "CSSFontFaceSrcValue.h"
42 #include "CSSFontFeatureValue.h"
43 #include "CSSFontValue.h"
44 #include "CSSFunctionValue.h"
45 #include "CSSGradientValue.h"
46 #include "CSSImageValue.h"
47 #include "CSSInheritedValue.h"
48 #include "CSSInitialValue.h"
49 #include "CSSKeyframeRule.h"
50 #include "CSSKeyframesRule.h"
51 #include "CSSLineBoxContainValue.h"
52 #include "CSSMediaRule.h"
53 #include "CSSNamedImageValue.h"
54 #include "CSSPageRule.h"
55 #include "CSSPrimitiveValue.h"
56 #include "CSSPrimitiveValueMappings.h"
57 #include "CSSPropertySourceData.h"
58 #include "CSSReflectValue.h"
59 #include "CSSSelector.h"
60 #include "CSSShadowValue.h"
61 #include "CSSStyleSheet.h"
62 #include "CSSTimingFunctionValue.h"
63 #include "CSSUnicodeRangeValue.h"
64 #include "CSSValueKeywords.h"
65 #include "CSSValueList.h"
66 #include "CSSValuePool.h"
67 #include "Counter.h"
68 #include "Document.h"
69 #include "FloatConversion.h"
70 #include "GridCoordinate.h"
71 #include "HTMLParserIdioms.h"
72 #include "HashTools.h"
73 #include "MediaList.h"
74 #include "MediaQueryExp.h"
75 #include "Page.h"
76 #include "PageConsoleClient.h"
77 #include "Pair.h"
78 #include "Rect.h"
79 #include "RenderTheme.h"
80 #include "RuntimeEnabledFeatures.h"
81 #include "SVGParserUtilities.h"
82 #include "SelectorChecker.h"
83 #include "SelectorCheckerTestFunctions.h"
84 #include "Settings.h"
85 #include "StyleProperties.h"
86 #include "StylePropertyShorthand.h"
87 #include "StyleRule.h"
88 #include "StyleRuleImport.h"
89 #include "StyleSheetContents.h"
90 #include "TextEncoding.h"
91 #include "WebKitCSSFilterValue.h"
92 #include "WebKitCSSRegionRule.h"
93 #include "WebKitCSSResourceValue.h"
94 #include "WebKitCSSTransformValue.h"
95 #include <JavaScriptCore/Profile.h>
96 #include <bitset>
97 #include <limits.h>
98 #include <wtf/HexNumber.h>
99 #include <wtf/NeverDestroyed.h>
100 #include <wtf/StdLibExtras.h>
101 #include <wtf/dtoa.h>
102 #include <wtf/text/StringBuffer.h>
103 #include <wtf/text/StringBuilder.h>
104 #include <wtf/text/StringImpl.h>
105
106 #if ENABLE(CSS_GRID_LAYOUT)
107 #include "CSSGridLineNamesValue.h"
108 #include "CSSGridTemplateAreasValue.h"
109 #endif
110
111 #if ENABLE(CSS_IMAGE_SET)
112 #include "CSSImageSetValue.h"
113 #endif
114
115 #if ENABLE(CSS_SCROLL_SNAP)
116 #include "LengthRepeat.h"
117 #endif
118
119 #if ENABLE(DASHBOARD_SUPPORT)
120 #include "DashboardRegion.h"
121 #endif
122
123 #define YYDEBUG 0
124
125 #if YYDEBUG > 0
126 extern int cssyydebug;
127 #endif
128
129 extern int cssyyparse(WebCore::CSSParser*);
130
131 using namespace WTF;
132
133 namespace {
134
135 enum PropertyType {
136     PropertyExplicit,
137     PropertyImplicit
138 };
139
140 class ImplicitScope {
141     WTF_MAKE_NONCOPYABLE(ImplicitScope);
142 public:
143     ImplicitScope(WebCore::CSSParser& parser, PropertyType propertyType)
144         : m_parser(parser)
145     {
146         m_parser.m_implicitShorthand = propertyType == PropertyImplicit;
147     }
148
149     ~ImplicitScope()
150     {
151         m_parser.m_implicitShorthand = false;
152     }
153
154 private:
155     WebCore::CSSParser& m_parser;
156 };
157
158 } // namespace
159
160 namespace WebCore {
161
162 static const unsigned INVALID_NUM_PARSED_PROPERTIES = UINT_MAX;
163 static const double MAX_SCALE = 1000000;
164
165 template <unsigned N>
166 static bool equal(const CSSParserString& a, const char (&b)[N])
167 {
168     unsigned length = N - 1; // Ignore the trailing null character
169     if (a.length() != length)
170         return false;
171
172     return a.is8Bit() ? WTF::equal(a.characters8(), reinterpret_cast<const LChar*>(b), length) : WTF::equal(a.characters16(), reinterpret_cast<const LChar*>(b), length);
173 }
174
175 template <unsigned N>
176 static bool equalIgnoringCase(const CSSParserString& a, const char (&b)[N])
177 {
178     unsigned length = N - 1; // Ignore the trailing null character
179     if (a.length() != length)
180         return false;
181
182     return a.is8Bit() ? WTF::equalIgnoringCase(b, a.characters8(), length) : WTF::equalIgnoringCase(b, a.characters16(), length);
183 }
184
185 template <unsigned N>
186 static bool equalIgnoringCase(CSSParserValue& value, const char (&b)[N])
187 {
188     ASSERT(value.unit == CSSPrimitiveValue::CSS_IDENT || value.unit == CSSPrimitiveValue::CSS_STRING);
189     return equalIgnoringCase(value.string, b);
190 }
191
192 static bool hasPrefix(const char* string, unsigned length, const char* prefix)
193 {
194     for (unsigned i = 0; i < length; ++i) {
195         if (!prefix[i])
196             return true;
197         if (string[i] != prefix[i])
198             return false;
199     }
200     return false;
201 }
202
203 static Ref<CSSPrimitiveValue> createPrimitiveValuePair(PassRefPtr<CSSPrimitiveValue> first, PassRefPtr<CSSPrimitiveValue> second)
204 {
205     return cssValuePool().createValue(Pair::create(first, second));
206 }
207
208 class AnimationParseContext {
209 public:
210     AnimationParseContext()
211         : m_animationPropertyKeywordAllowed(true)
212         , m_firstAnimationCommitted(false)
213         , m_hasSeenAnimationPropertyKeyword(false)
214     {
215     }
216
217     void commitFirstAnimation()
218     {
219         m_firstAnimationCommitted = true;
220     }
221
222     bool hasCommittedFirstAnimation() const
223     {
224         return m_firstAnimationCommitted;
225     }
226
227     void commitAnimationPropertyKeyword()
228     {
229         m_animationPropertyKeywordAllowed = false;
230     }
231
232     bool animationPropertyKeywordAllowed() const
233     {
234         return m_animationPropertyKeywordAllowed;
235     }
236
237     bool hasSeenAnimationPropertyKeyword() const
238     {
239         return m_hasSeenAnimationPropertyKeyword;
240     }
241
242     void sawAnimationPropertyKeyword()
243     {
244         m_hasSeenAnimationPropertyKeyword = true;
245     }
246
247 private:
248     bool m_animationPropertyKeywordAllowed;
249     bool m_firstAnimationCommitted;
250     bool m_hasSeenAnimationPropertyKeyword;
251 };
252
253 const CSSParserContext& strictCSSParserContext()
254 {
255     static NeverDestroyed<CSSParserContext> strictContext(CSSStrictMode);
256     return strictContext;
257 }
258
259 CSSParserContext::CSSParserContext(CSSParserMode mode, const URL& baseURL)
260     : baseURL(baseURL)
261     , mode(mode)
262     , isHTMLDocument(false)
263     , isCSSRegionsEnabled(RuntimeEnabledFeatures::sharedFeatures().cssRegionsEnabled())
264     , isCSSCompositingEnabled(RuntimeEnabledFeatures::sharedFeatures().cssCompositingEnabled())
265     , needsSiteSpecificQuirks(false)
266     , enforcesCSSMIMETypeInNoQuirksMode(true)
267     , useLegacyBackgroundSizeShorthandBehavior(false)
268 {
269 #if PLATFORM(IOS)
270     // FIXME: Force the site specific quirk below to work on iOS. Investigating other site specific quirks
271     // to see if we can enable the preference all together is to be handled by:
272     // <rdar://problem/8493309> Investigate Enabling Site Specific Quirks in MobileSafari and UIWebView
273     needsSiteSpecificQuirks = true;
274 #endif
275 }
276
277 CSSParserContext::CSSParserContext(Document& document, const URL& baseURL, const String& charset)
278     : baseURL(baseURL.isNull() ? document.baseURL() : baseURL)
279     , charset(charset)
280     , mode(document.inQuirksMode() ? CSSQuirksMode : CSSStrictMode)
281     , isHTMLDocument(document.isHTMLDocument())
282     , isCSSRegionsEnabled(document.cssRegionsEnabled())
283     , isCSSCompositingEnabled(document.cssCompositingEnabled())
284     , needsSiteSpecificQuirks(document.settings() ? document.settings()->needsSiteSpecificQuirks() : false)
285     , enforcesCSSMIMETypeInNoQuirksMode(!document.settings() || document.settings()->enforceCSSMIMETypeInNoQuirksMode())
286     , useLegacyBackgroundSizeShorthandBehavior(document.settings() ? document.settings()->useLegacyBackgroundSizeShorthandBehavior() : false)
287 {
288 #if PLATFORM(IOS)
289     // FIXME: Force the site specific quirk below to work on iOS. Investigating other site specific quirks
290     // to see if we can enable the preference all together is to be handled by:
291     // <rdar://problem/8493309> Investigate Enabling Site Specific Quirks in MobileSafari and UIWebView
292     needsSiteSpecificQuirks = true;
293 #endif
294 }
295
296 bool operator==(const CSSParserContext& a, const CSSParserContext& b)
297 {
298     return a.baseURL == b.baseURL
299         && a.charset == b.charset
300         && a.mode == b.mode
301         && a.isHTMLDocument == b.isHTMLDocument
302         && a.isCSSRegionsEnabled == b.isCSSRegionsEnabled
303         && a.isCSSCompositingEnabled == b.isCSSCompositingEnabled
304         && a.needsSiteSpecificQuirks == b.needsSiteSpecificQuirks
305         && a.enforcesCSSMIMETypeInNoQuirksMode == b.enforcesCSSMIMETypeInNoQuirksMode
306         && a.useLegacyBackgroundSizeShorthandBehavior == b.useLegacyBackgroundSizeShorthandBehavior;
307 }
308
309 CSSParser::CSSParser(const CSSParserContext& context)
310     : m_context(context)
311     , m_important(false)
312     , m_id(CSSPropertyInvalid)
313     , m_styleSheet(nullptr)
314     , m_supportsCondition(false)
315     , m_selectorListForParseSelector(nullptr)
316     , m_numParsedPropertiesBeforeMarginBox(INVALID_NUM_PARSED_PROPERTIES)
317     , m_inParseShorthand(0)
318     , m_currentShorthand(CSSPropertyInvalid)
319     , m_implicitShorthand(false)
320     , m_hasFontFaceOnlyValues(false)
321     , m_hadSyntacticallyValidCSSRule(false)
322     , m_logErrors(false)
323     , m_ignoreErrorsInDeclaration(false)
324     , m_defaultNamespace(starAtom)
325     , m_parsedTextPrefixLength(0)
326     , m_nestedSelectorLevel(0)
327     , m_propertyRange(UINT_MAX, UINT_MAX)
328     , m_ruleSourceDataResult(nullptr)
329     , m_parsingMode(NormalMode)
330     , m_is8BitSource(false)
331     , m_currentCharacter8(nullptr)
332     , m_currentCharacter16(nullptr)
333     , m_length(0)
334     , m_token(0)
335     , m_lineNumber(0)
336     , m_tokenStartLineNumber(0)
337     , m_tokenStartColumnNumber(0)
338     , m_lastSelectorLineNumber(0)
339     , m_columnOffsetForLine(0)
340     , m_sheetStartLineNumber(0)
341     , m_sheetStartColumnNumber(0)
342     , m_allowImportRules(true)
343     , m_allowNamespaceDeclarations(true)
344 #if ENABLE(CSS_DEVICE_ADAPTATION)
345     , m_inViewport(false)
346 #endif
347 {
348 #if YYDEBUG > 0
349     cssyydebug = 1;
350 #endif
351     m_tokenStart.ptr8 = nullptr;
352 }
353
354 CSSParser::~CSSParser()
355 {
356     clearProperties();
357 }
358
359 template <typename CharacterType>
360 ALWAYS_INLINE static void makeLower(const CharacterType* input, CharacterType* output, unsigned length)
361 {
362     // FIXME: If we need Unicode lowercasing here, then we probably want the real kind
363     // that can potentially change the length of the string rather than the character
364     // by character kind. If we don't need Unicode lowercasing, it would be good to
365     // simplify this function.
366
367     if (charactersAreAllASCII(input, length)) {
368         // Fast case for all-ASCII.
369         for (unsigned i = 0; i < length; ++i)
370             output[i] = toASCIILower(input[i]);
371     } else {
372         for (unsigned i = 0; i < length; ++i) {
373             ASSERT(u_tolower(input[i]) <= 0xFFFF);
374             output[i] = u_tolower(input[i]);
375         }
376     }
377 }
378
379 void CSSParserString::lower()
380 {
381     if (is8Bit()) {
382         makeLower(characters8(), characters8(), length());
383         return;
384     }
385
386     makeLower(characters16(), characters16(), length());
387 }
388
389 void CSSParser::setupParser(const char* prefix, unsigned prefixLength, StringView string, const char* suffix, unsigned suffixLength)
390 {
391     m_parsedTextPrefixLength = prefixLength;
392     unsigned stringLength = string.length();
393     unsigned length = stringLength + m_parsedTextPrefixLength + suffixLength + 1;
394     m_length = length;
395
396     if (!stringLength || string.is8Bit()) {
397         m_dataStart8 = std::make_unique<LChar[]>(length);
398         for (unsigned i = 0; i < m_parsedTextPrefixLength; ++i)
399             m_dataStart8[i] = prefix[i];
400
401         if (stringLength)
402             memcpy(m_dataStart8.get() + m_parsedTextPrefixLength, string.characters8(), stringLength * sizeof(LChar));
403
404         unsigned start = m_parsedTextPrefixLength + stringLength;
405         unsigned end = start + suffixLength;
406         for (unsigned i = start; i < end; i++)
407             m_dataStart8[i] = suffix[i - start];
408
409         m_dataStart8[length - 1] = '\0';
410
411         m_is8BitSource = true;
412         m_currentCharacter8 = m_dataStart8.get();
413         m_currentCharacter16 = nullptr;
414         setTokenStart<LChar>(m_currentCharacter8);
415         m_lexFunc = &CSSParser::realLex<LChar>;
416         return;
417     }
418
419     m_dataStart16 = std::make_unique<UChar[]>(length);
420     for (unsigned i = 0; i < m_parsedTextPrefixLength; ++i)
421         m_dataStart16[i] = prefix[i];
422
423     ASSERT(stringLength);
424     memcpy(m_dataStart16.get() + m_parsedTextPrefixLength, string.characters16(), stringLength * sizeof(UChar));
425
426     unsigned start = m_parsedTextPrefixLength + stringLength;
427     unsigned end = start + suffixLength;
428     for (unsigned i = start; i < end; i++)
429         m_dataStart16[i] = suffix[i - start];
430
431     m_dataStart16[length - 1] = '\0';
432
433     m_is8BitSource = false;
434     m_currentCharacter8 = nullptr;
435     m_currentCharacter16 = m_dataStart16.get();
436     setTokenStart<UChar>(m_currentCharacter16);
437     m_lexFunc = &CSSParser::realLex<UChar>;
438 }
439
440 void CSSParser::parseSheet(StyleSheetContents* sheet, const String& string, const TextPosition& textPosition, RuleSourceDataList* ruleSourceDataResult, bool logErrors)
441 {
442     setStyleSheet(sheet);
443     m_defaultNamespace = starAtom; // Reset the default namespace.
444     if (ruleSourceDataResult)
445         m_currentRuleDataStack = std::make_unique<RuleSourceDataList>();
446     m_ruleSourceDataResult = ruleSourceDataResult;
447
448     m_logErrors = logErrors && sheet->singleOwnerDocument() && !sheet->baseURL().isEmpty() && sheet->singleOwnerDocument()->page();
449     m_ignoreErrorsInDeclaration = false;
450     m_sheetStartLineNumber = textPosition.m_line.zeroBasedInt();
451     m_sheetStartColumnNumber = textPosition.m_column.zeroBasedInt();
452     m_lineNumber = m_sheetStartLineNumber;
453     m_columnOffsetForLine = 0;
454     setupParser("", string, "");
455     cssyyparse(this);
456     sheet->shrinkToFit();
457     m_currentRuleDataStack.reset();
458     m_ruleSourceDataResult = nullptr;
459     m_rule = nullptr;
460     m_ignoreErrorsInDeclaration = false;
461     m_logErrors = false;
462 }
463
464 PassRefPtr<StyleRuleBase> CSSParser::parseRule(StyleSheetContents* sheet, const String& string)
465 {
466     setStyleSheet(sheet);
467     m_allowNamespaceDeclarations = false;
468     setupParser("@-webkit-rule{", string, "} ");
469     cssyyparse(this);
470     return m_rule.release();
471 }
472
473 PassRefPtr<StyleKeyframe> CSSParser::parseKeyframeRule(StyleSheetContents* sheet, const String& string)
474 {
475     setStyleSheet(sheet);
476     setupParser("@-webkit-keyframe-rule{ ", string, "} ");
477     cssyyparse(this);
478     return m_keyframe.release();
479 }
480
481 bool CSSParser::parseSupportsCondition(const String& string)
482 {
483     m_supportsCondition = false;
484     // can't use { because tokenizer state switches from supports to initial state when it sees { token.
485     // instead insert one " " (which is WHITESPACE in CSSGrammar.y)
486     setupParser("@-webkit-supports-condition ", string, "} ");
487     cssyyparse(this);
488     return m_supportsCondition;
489 }
490
491 static inline bool isColorPropertyID(CSSPropertyID propertyId)
492 {
493     switch (propertyId) {
494     case CSSPropertyColor:
495     case CSSPropertyBackgroundColor:
496     case CSSPropertyBorderBottomColor:
497     case CSSPropertyBorderLeftColor:
498     case CSSPropertyBorderRightColor:
499     case CSSPropertyBorderTopColor:
500     case CSSPropertyOutlineColor:
501     case CSSPropertyTextLineThroughColor:
502     case CSSPropertyTextOverlineColor:
503     case CSSPropertyTextUnderlineColor:
504     case CSSPropertyWebkitBorderAfterColor:
505     case CSSPropertyWebkitBorderBeforeColor:
506     case CSSPropertyWebkitBorderEndColor:
507     case CSSPropertyWebkitBorderStartColor:
508     case CSSPropertyColumnRuleColor:
509     case CSSPropertyWebkitTextDecorationColor:
510     case CSSPropertyWebkitTextEmphasisColor:
511     case CSSPropertyWebkitTextFillColor:
512     case CSSPropertyWebkitTextStrokeColor:
513         return true;
514     default:
515         return false;
516     }
517 }
518
519 bool CSSParser::isValidSystemColorValue(CSSValueID valueID)
520 {
521     return valueID >= CSSValueAqua && valueID <= CSSValueAppleSystemYellow;
522 }
523
524 static bool validPrimitiveValueColor(CSSValueID valueID, bool strict = false)
525 {
526     return (valueID == CSSValueWebkitText || valueID == CSSValueCurrentcolor || valueID == CSSValueMenu
527         || CSSParser::isValidSystemColorValue(valueID) || valueID == CSSValueAlpha
528         || (valueID >= CSSValueWebkitFocusRingColor && valueID < CSSValueWebkitText && !strict));
529 }
530
531 static CSSParser::ParseResult parseColorValue(MutableStyleProperties* declaration, CSSPropertyID propertyId, const String& string, bool important, CSSParserMode cssParserMode)
532 {
533     ASSERT(!string.isEmpty());
534     bool strict = isStrictParserMode(cssParserMode);
535     if (!isColorPropertyID(propertyId))
536         return CSSParser::ParseResult::Error;
537
538     CSSParserString cssString;
539     cssString.init(string);
540     CSSValueID valueID = cssValueKeywordID(cssString);
541     if (validPrimitiveValueColor(valueID, strict)) {
542         RefPtr<CSSValue> value = cssValuePool().createIdentifierValue(valueID);
543         return declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important)) ? CSSParser::ParseResult::Changed : CSSParser::ParseResult::Unchanged;
544     }
545     RGBA32 color;
546     if (!CSSParser::fastParseColor(color, string, strict && string[0] != '#'))
547         return CSSParser::ParseResult::Error;
548
549     RefPtr<CSSValue> value = cssValuePool().createColorValue(color);
550     return declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important)) ? CSSParser::ParseResult::Changed : CSSParser::ParseResult::Unchanged;
551 }
552
553 static inline bool isSimpleLengthPropertyID(CSSPropertyID propertyId, bool& acceptsNegativeNumbers)
554 {
555     switch (propertyId) {
556     case CSSPropertyFontSize:
557     case CSSPropertyHeight:
558     case CSSPropertyWidth:
559     case CSSPropertyMinHeight:
560     case CSSPropertyMinWidth:
561     case CSSPropertyPaddingBottom:
562     case CSSPropertyPaddingLeft:
563     case CSSPropertyPaddingRight:
564     case CSSPropertyPaddingTop:
565     case CSSPropertyWebkitLogicalWidth:
566     case CSSPropertyWebkitLogicalHeight:
567     case CSSPropertyWebkitMinLogicalWidth:
568     case CSSPropertyWebkitMinLogicalHeight:
569     case CSSPropertyWebkitPaddingAfter:
570     case CSSPropertyWebkitPaddingBefore:
571     case CSSPropertyWebkitPaddingEnd:
572     case CSSPropertyWebkitPaddingStart:
573         acceptsNegativeNumbers = false;
574         return true;
575 #if ENABLE(CSS_SHAPES)
576     case CSSPropertyWebkitShapeMargin:
577         acceptsNegativeNumbers = false;
578         return RuntimeEnabledFeatures::sharedFeatures().cssShapesEnabled();
579 #endif
580     case CSSPropertyBottom:
581     case CSSPropertyCx:
582     case CSSPropertyCy:
583     case CSSPropertyLeft:
584     case CSSPropertyMarginBottom:
585     case CSSPropertyMarginLeft:
586     case CSSPropertyMarginRight:
587     case CSSPropertyMarginTop:
588     case CSSPropertyR:
589     case CSSPropertyRx:
590     case CSSPropertyRy:
591     case CSSPropertyRight:
592     case CSSPropertyTop:
593     case CSSPropertyWebkitMarginAfter:
594     case CSSPropertyWebkitMarginBefore:
595     case CSSPropertyWebkitMarginEnd:
596     case CSSPropertyWebkitMarginStart:
597     case CSSPropertyX:
598     case CSSPropertyY:
599         acceptsNegativeNumbers = true;
600         return true;
601     default:
602         return false;
603     }
604 }
605
606 template <typename CharacterType>
607 static inline bool parseSimpleLength(const CharacterType* characters, unsigned& length, CSSPrimitiveValue::UnitTypes& unit, double& number)
608 {
609     if (length > 2 && (characters[length - 2] | 0x20) == 'p' && (characters[length - 1] | 0x20) == 'x') {
610         length -= 2;
611         unit = CSSPrimitiveValue::CSS_PX;
612     } else if (length > 1 && characters[length - 1] == '%') {
613         length -= 1;
614         unit = CSSPrimitiveValue::CSS_PERCENTAGE;
615     }
616
617     // We rely on charactersToDouble for validation as well. The function
618     // will set "ok" to "false" if the entire passed-in character range does
619     // not represent a double.
620     bool ok;
621     number = charactersToDouble(characters, length, &ok);
622     return ok;
623 }
624
625 static CSSParser::ParseResult parseSimpleLengthValue(MutableStyleProperties* declaration, CSSPropertyID propertyId, const String& string, bool important, CSSParserMode cssParserMode)
626 {
627     ASSERT(!string.isEmpty());
628     bool acceptsNegativeNumbers;
629     if (!isSimpleLengthPropertyID(propertyId, acceptsNegativeNumbers))
630         return CSSParser::ParseResult::Error;
631
632     unsigned length = string.length();
633     double number;
634     CSSPrimitiveValue::UnitTypes unit = CSSPrimitiveValue::CSS_NUMBER;
635
636     if (string.is8Bit()) {
637         if (!parseSimpleLength(string.characters8(), length, unit, number))
638             return CSSParser::ParseResult::Error;
639     } else {
640         if (!parseSimpleLength(string.characters16(), length, unit, number))
641             return CSSParser::ParseResult::Error;
642     }
643
644     if (unit == CSSPrimitiveValue::CSS_NUMBER) {
645         if (number && isStrictParserMode(cssParserMode))
646             return CSSParser::ParseResult::Error;
647         unit = CSSPrimitiveValue::CSS_PX;
648     }
649     if (number < 0 && !acceptsNegativeNumbers)
650         return CSSParser::ParseResult::Error;
651     if (std::isinf(number))
652         return CSSParser::ParseResult::Error;
653
654     RefPtr<CSSValue> value = cssValuePool().createValue(number, unit);
655     return declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important)) ? CSSParser::ParseResult::Changed : CSSParser::ParseResult::Unchanged;
656 }
657
658 static inline bool isValidKeywordPropertyAndValue(CSSPropertyID propertyId, int valueID, const CSSParserContext& parserContext, StyleSheetContents* styleSheetContents)
659 {
660     if (!valueID)
661         return false;
662
663     switch (propertyId) {
664     case CSSPropertyBorderCollapse: // collapse | separate | inherit
665         if (valueID == CSSValueCollapse || valueID == CSSValueSeparate)
666             return true;
667         break;
668     case CSSPropertyBorderTopStyle: // <border-style> | inherit
669     case CSSPropertyBorderRightStyle: // Defined as: none | hidden | dotted | dashed |
670     case CSSPropertyBorderBottomStyle: // solid | double | groove | ridge | inset | outset
671     case CSSPropertyBorderLeftStyle:
672     case CSSPropertyWebkitBorderAfterStyle:
673     case CSSPropertyWebkitBorderBeforeStyle:
674     case CSSPropertyWebkitBorderEndStyle:
675     case CSSPropertyWebkitBorderStartStyle:
676     case CSSPropertyColumnRuleStyle:
677         if (valueID >= CSSValueNone && valueID <= CSSValueDouble)
678             return true;
679         break;
680     case CSSPropertyBoxSizing:
681          if (valueID == CSSValueBorderBox || valueID == CSSValueContentBox)
682              return true;
683          break;
684     case CSSPropertyCaptionSide: // top | bottom | left | right | inherit
685         if (valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueTop || valueID == CSSValueBottom)
686             return true;
687         break;
688     case CSSPropertyClear: // none | left | right | both | inherit
689         if (valueID == CSSValueNone || valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueBoth)
690             return true;
691         break;
692     case CSSPropertyDirection: // ltr | rtl | inherit
693         if (valueID == CSSValueLtr || valueID == CSSValueRtl)
694             return true;
695         break;
696     case CSSPropertyDisplay:
697         // inline | block | list-item | inline-block | table |
698         // inline-table | table-row-group | table-header-group | table-footer-group | table-row |
699         // table-column-group | table-column | table-cell | table-caption | -webkit-box | -webkit-inline-box | none | inherit
700         // flex | -webkit-flex | inline-flex | -webkit-inline-flex | -webkit-grid | -webkit-inline-grid
701         if ((valueID >= CSSValueInline && valueID <= CSSValueWebkitInlineFlex) || valueID == CSSValueNone)
702             return true;
703 #if ENABLE(CSS_GRID_LAYOUT)
704         if (valueID == CSSValueWebkitGrid || valueID == CSSValueWebkitInlineGrid)
705             return true;
706 #endif
707         break;
708
709     case CSSPropertyEmptyCells: // show | hide | inherit
710         if (valueID == CSSValueShow || valueID == CSSValueHide)
711             return true;
712         break;
713     case CSSPropertyFloat: // left | right | none | center (for buggy CSS, maps to none)
714         if (valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueNone || valueID == CSSValueCenter)
715             return true;
716         break;
717     case CSSPropertyFontStyle: // normal | italic | oblique | inherit
718         if (valueID == CSSValueNormal || valueID == CSSValueItalic || valueID == CSSValueOblique)
719             return true;
720         break;
721     case CSSPropertyImageRendering: // auto | optimizeSpeed | optimizeQuality | -webkit-crisp-edges | -webkit-optimize-contrast
722         if (valueID == CSSValueAuto || valueID == CSSValueOptimizespeed || valueID == CSSValueOptimizequality
723             || valueID == CSSValueWebkitCrispEdges || valueID == CSSValueWebkitOptimizeContrast)
724             return true;
725         break;
726     case CSSPropertyListStylePosition: // inside | outside | inherit
727         if (valueID == CSSValueInside || valueID == CSSValueOutside)
728             return true;
729         break;
730     case CSSPropertyListStyleType:
731         // See section CSS_PROP_LIST_STYLE_TYPE of file CSSValueKeywords.in
732         // for the list of supported list-style-types.
733         if ((valueID >= CSSValueDisc && valueID <= CSSValueKatakanaIroha) || valueID == CSSValueNone)
734             return true;
735         break;
736     case CSSPropertyObjectFit:
737         if (valueID == CSSValueFill || valueID == CSSValueContain || valueID == CSSValueCover || valueID == CSSValueNone || valueID == CSSValueScaleDown)
738             return true;
739         break;
740     case CSSPropertyOutlineStyle: // (<border-style> except hidden) | auto | inherit
741         if (valueID == CSSValueAuto || valueID == CSSValueNone || (valueID >= CSSValueInset && valueID <= CSSValueDouble))
742             return true;
743         break;
744     case CSSPropertyOverflowWrap: // normal | break-word
745     case CSSPropertyWordWrap:
746         if (valueID == CSSValueNormal || valueID == CSSValueBreakWord)
747             return true;
748         break;
749 #if ENABLE(CSS_SCROLL_SNAP)
750     case CSSPropertyWebkitScrollSnapType: // none | mandatory | proximity
751         if (valueID == CSSValueNone || valueID == CSSValueMandatory || valueID == CSSValueProximity)
752             return true;
753         break;
754 #endif
755     case CSSPropertyOverflowX: // visible | hidden | scroll | auto | marquee | overlay | inherit
756         if (valueID == CSSValueVisible || valueID == CSSValueHidden || valueID == CSSValueScroll || valueID == CSSValueAuto || valueID == CSSValueOverlay || valueID == CSSValueWebkitMarquee)
757             return true;
758         break;
759     case CSSPropertyOverflowY: // visible | hidden | scroll | auto | marquee | overlay | inherit | -webkit-paged-x | -webkit-paged-y
760         if (valueID == CSSValueVisible || valueID == CSSValueHidden || valueID == CSSValueScroll || valueID == CSSValueAuto || valueID == CSSValueOverlay || valueID == CSSValueWebkitMarquee || valueID == CSSValueWebkitPagedX || valueID == CSSValueWebkitPagedY)
761             return true;
762         break;
763     case CSSPropertyPageBreakAfter: // auto | always | avoid | left | right | inherit
764     case CSSPropertyPageBreakBefore:
765     case CSSPropertyWebkitColumnBreakAfter:
766     case CSSPropertyWebkitColumnBreakBefore:
767         if (valueID == CSSValueAuto || valueID == CSSValueAlways || valueID == CSSValueAvoid || valueID == CSSValueLeft || valueID == CSSValueRight)
768             return true;
769         break;
770     case CSSPropertyPageBreakInside: // avoid | auto | inherit
771     case CSSPropertyWebkitColumnBreakInside:
772         if (valueID == CSSValueAuto || valueID == CSSValueAvoid)
773             return true;
774         break;
775     case CSSPropertyPointerEvents:
776         // none | visiblePainted | visibleFill | visibleStroke | visible |
777         // painted | fill | stroke | auto | all | inherit
778         if (valueID == CSSValueVisible || valueID == CSSValueNone || valueID == CSSValueAll || valueID == CSSValueAuto || (valueID >= CSSValueVisiblepainted && valueID <= CSSValueStroke))
779             return true;
780         break;
781     case CSSPropertyPosition: // static | relative | absolute | fixed | sticky | inherit
782         if (valueID == CSSValueStatic || valueID == CSSValueRelative || valueID == CSSValueAbsolute || valueID == CSSValueFixed || valueID == CSSValueWebkitSticky)
783             return true;
784         break;
785     case CSSPropertyResize: // none | both | horizontal | vertical | auto
786         if (valueID == CSSValueNone || valueID == CSSValueBoth || valueID == CSSValueHorizontal || valueID == CSSValueVertical || valueID == CSSValueAuto)
787             return true;
788         break;
789     case CSSPropertySpeak: // none | normal | spell-out | digits | literal-punctuation | no-punctuation | inherit
790         if (valueID == CSSValueNone || valueID == CSSValueNormal || valueID == CSSValueSpellOut || valueID == CSSValueDigits || valueID == CSSValueLiteralPunctuation || valueID == CSSValueNoPunctuation)
791             return true;
792         break;
793     case CSSPropertyTableLayout: // auto | fixed | inherit
794         if (valueID == CSSValueAuto || valueID == CSSValueFixed)
795             return true;
796         break;
797     case CSSPropertyTextLineThroughMode:
798     case CSSPropertyTextOverlineMode:
799     case CSSPropertyTextUnderlineMode:
800         if (valueID == CSSValueContinuous || valueID == CSSValueSkipWhiteSpace)
801             return true;
802         break;
803     case CSSPropertyTextLineThroughStyle:
804     case CSSPropertyTextOverlineStyle:
805     case CSSPropertyTextUnderlineStyle:
806         if (valueID == CSSValueNone || valueID == CSSValueSolid || valueID == CSSValueDouble || valueID == CSSValueDashed || valueID == CSSValueDotDash || valueID == CSSValueDotDotDash || valueID == CSSValueWave)
807             return true;
808         break;
809     case CSSPropertyTextOverflow: // clip | ellipsis
810         if (valueID == CSSValueClip || valueID == CSSValueEllipsis)
811             return true;
812         break;
813     case CSSPropertyTextRendering: // auto | optimizeSpeed | optimizeLegibility | geometricPrecision
814         if (valueID == CSSValueAuto || valueID == CSSValueOptimizespeed || valueID == CSSValueOptimizelegibility || valueID == CSSValueGeometricprecision)
815             return true;
816         break;
817     case CSSPropertyTextTransform: // capitalize | uppercase | lowercase | none | inherit
818         if ((valueID >= CSSValueCapitalize && valueID <= CSSValueLowercase) || valueID == CSSValueNone)
819             return true;
820         break;
821     case CSSPropertyVisibility: // visible | hidden | collapse | inherit
822         if (valueID == CSSValueVisible || valueID == CSSValueHidden || valueID == CSSValueCollapse)
823             return true;
824         break;
825     case CSSPropertyWebkitAppearance:
826         if ((valueID >= CSSValueCheckbox && valueID <= CSSValueCapsLockIndicator) || valueID == CSSValueNone)
827             return true;
828         break;
829     case CSSPropertyWebkitBackfaceVisibility:
830         if (valueID == CSSValueVisible || valueID == CSSValueHidden)
831             return true;
832         break;
833 #if ENABLE(CSS_COMPOSITING)
834     case CSSPropertyMixBlendMode:
835         if (parserContext.isCSSCompositingEnabled && (valueID == CSSValueNormal || valueID == CSSValueMultiply || valueID == CSSValueScreen
836             || valueID == CSSValueOverlay || valueID == CSSValueDarken || valueID == CSSValueLighten ||  valueID == CSSValueColorDodge
837             || valueID == CSSValueColorBurn || valueID == CSSValueHardLight || valueID == CSSValueSoftLight || valueID == CSSValueDifference
838             || valueID == CSSValueExclusion || valueID == CSSValuePlusDarker || valueID == CSSValuePlusLighter))
839             return true;
840         break;
841     case CSSPropertyIsolation:
842         if (parserContext.isCSSCompositingEnabled && (valueID == CSSValueAuto || valueID == CSSValueIsolate))
843             return true;
844         break;
845 #endif
846     case CSSPropertyWebkitBorderFit:
847         if (valueID == CSSValueBorder || valueID == CSSValueLines)
848             return true;
849         break;
850     case CSSPropertyWebkitBoxAlign:
851         if (valueID == CSSValueStretch || valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueCenter || valueID == CSSValueBaseline)
852             return true;
853         break;
854 #if ENABLE(CSS_BOX_DECORATION_BREAK)
855     case CSSPropertyWebkitBoxDecorationBreak:
856          if (valueID == CSSValueClone || valueID == CSSValueSlice)
857              return true;
858          break;
859 #endif
860     case CSSPropertyWebkitBoxDirection:
861         if (valueID == CSSValueNormal || valueID == CSSValueReverse)
862             return true;
863         break;
864     case CSSPropertyWebkitBoxLines:
865         if (valueID == CSSValueSingle || valueID == CSSValueMultiple)
866                 return true;
867         break;
868     case CSSPropertyWebkitBoxOrient:
869         if (valueID == CSSValueHorizontal || valueID == CSSValueVertical || valueID == CSSValueInlineAxis || valueID == CSSValueBlockAxis)
870             return true;
871         break;
872     case CSSPropertyWebkitBoxPack:
873         if (valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueCenter || valueID == CSSValueJustify)
874             return true;
875         break;
876     case CSSPropertyWebkitColorCorrection:
877         if (valueID == CSSValueSrgb || valueID == CSSValueDefault)
878             return true;
879         break;
880     case CSSPropertyColumnFill:
881         if (valueID == CSSValueAuto || valueID == CSSValueBalance)
882             return true;
883         break;
884     case CSSPropertyFlexDirection:
885         if (valueID == CSSValueRow || valueID == CSSValueRowReverse || valueID == CSSValueColumn || valueID == CSSValueColumnReverse)
886             return true;
887         break;
888     case CSSPropertyFlexWrap:
889         if (valueID == CSSValueNowrap || valueID == CSSValueWrap || valueID == CSSValueWrapReverse)
890              return true;
891         break;
892     case CSSPropertyWebkitFontKerning:
893         if (valueID == CSSValueAuto || valueID == CSSValueNormal || valueID == CSSValueNone)
894             return true;
895         break;
896     case CSSPropertyWebkitFontSmoothing:
897         if (valueID == CSSValueAuto || valueID == CSSValueNone || valueID == CSSValueAntialiased || valueID == CSSValueSubpixelAntialiased)
898             return true;
899         break;
900     case CSSPropertyWebkitHyphens:
901         if (valueID == CSSValueNone || valueID == CSSValueManual || valueID == CSSValueAuto)
902             return true;
903         break;
904     case CSSPropertyWebkitLineAlign:
905         if (valueID == CSSValueNone || valueID == CSSValueEdges)
906             return true;
907         break;
908     case CSSPropertyWebkitLineBreak: // auto | loose | normal | strict | after-white-space
909         if (valueID == CSSValueAuto || valueID == CSSValueLoose || valueID == CSSValueNormal || valueID == CSSValueStrict || valueID == CSSValueAfterWhiteSpace)
910             return true;
911         break;
912     case CSSPropertyWebkitLineSnap:
913         if (valueID == CSSValueNone || valueID == CSSValueBaseline || valueID == CSSValueContain)
914             return true;
915         break;
916     case CSSPropertyWebkitMarginAfterCollapse:
917     case CSSPropertyWebkitMarginBeforeCollapse:
918     case CSSPropertyWebkitMarginBottomCollapse:
919     case CSSPropertyWebkitMarginTopCollapse:
920         if (valueID == CSSValueCollapse || valueID == CSSValueSeparate || valueID == CSSValueDiscard)
921             return true;
922         break;
923     case CSSPropertyWebkitMarqueeDirection:
924         if (valueID == CSSValueForwards || valueID == CSSValueBackwards || valueID == CSSValueAhead || valueID == CSSValueReverse || valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueDown
925             || valueID == CSSValueUp || valueID == CSSValueAuto)
926             return true;
927         break;
928     case CSSPropertyWebkitMarqueeStyle:
929         if (valueID == CSSValueNone || valueID == CSSValueSlide || valueID == CSSValueScroll || valueID == CSSValueAlternate)
930             return true;
931         break;
932     case CSSPropertyWebkitNbspMode: // normal | space
933         if (valueID == CSSValueNormal || valueID == CSSValueSpace)
934             return true;
935         break;
936 #if ENABLE(ACCELERATED_OVERFLOW_SCROLLING)
937     case CSSPropertyWebkitOverflowScrolling:
938         if (valueID == CSSValueAuto || valueID == CSSValueTouch)
939             return true;
940         break;
941 #endif
942     case CSSPropertyWebkitPrintColorAdjust:
943         if (valueID == CSSValueExact || valueID == CSSValueEconomy)
944             return true;
945         break;
946 #if ENABLE(CSS_REGIONS)
947     case CSSPropertyWebkitRegionBreakAfter:
948     case CSSPropertyWebkitRegionBreakBefore:
949         if (parserContext.isCSSRegionsEnabled && (valueID == CSSValueAuto || valueID == CSSValueAlways || valueID == CSSValueAvoid || valueID == CSSValueLeft || valueID == CSSValueRight))
950             return true;
951         break;
952     case CSSPropertyWebkitRegionBreakInside:
953         if (parserContext.isCSSRegionsEnabled && (valueID == CSSValueAuto || valueID == CSSValueAvoid))
954             return true;
955         break;
956     case CSSPropertyWebkitRegionFragment:
957         if (parserContext.isCSSRegionsEnabled && (valueID == CSSValueAuto || valueID == CSSValueBreak))
958             return true;
959         break;
960 #endif
961     case CSSPropertyWebkitRtlOrdering:
962         if (valueID == CSSValueLogical || valueID == CSSValueVisual)
963             return true;
964         break;
965
966     case CSSPropertyWebkitRubyPosition:
967         if (valueID == CSSValueBefore || valueID == CSSValueAfter || valueID == CSSValueInterCharacter)
968             return true;
969         break;
970
971 #if ENABLE(CSS3_TEXT)
972     case CSSPropertyWebkitTextAlignLast:
973         // auto | start | end | left | right | center | justify
974         if ((valueID >= CSSValueLeft && valueID <= CSSValueJustify) || valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueAuto)
975             return true;
976         break;
977 #endif // CSS3_TEXT
978     case CSSPropertyWebkitTextCombine:
979         if (valueID == CSSValueNone || valueID == CSSValueHorizontal)
980             return true;
981         break;
982 #if ENABLE(CSS3_TEXT)
983     case CSSPropertyWebkitTextJustify:
984         // auto | none | inter-word | distribute
985         if (valueID == CSSValueInterWord || valueID == CSSValueDistribute || valueID == CSSValueAuto || valueID == CSSValueNone)
986             return true;
987         break;
988 #endif // CSS3_TEXT
989     case CSSPropertyWebkitTextSecurity:
990         // disc | circle | square | none | inherit
991         if (valueID == CSSValueDisc || valueID == CSSValueCircle || valueID == CSSValueSquare || valueID == CSSValueNone)
992             return true;
993         break;
994 #if ENABLE(IOS_TEXT_AUTOSIZING)
995     case CSSPropertyWebkitTextSizeAdjust:
996         if (valueID == CSSValueAuto || valueID == CSSValueNone)
997             return true;
998         break;
999 #endif
1000     case CSSPropertyTransformStyle:
1001     case CSSPropertyWebkitTransformStyle:
1002         if (valueID == CSSValueFlat || valueID == CSSValuePreserve3d)
1003             return true;
1004         break;
1005     case CSSPropertyWebkitUserDrag: // auto | none | element
1006         if (valueID == CSSValueAuto || valueID == CSSValueNone || valueID == CSSValueElement)
1007             return true;
1008         break;
1009     case CSSPropertyWebkitUserModify: // read-only | read-write
1010         if (valueID == CSSValueReadOnly || valueID == CSSValueReadWrite || valueID == CSSValueReadWritePlaintextOnly) {
1011             if (styleSheetContents)
1012                 styleSheetContents->parserSetUsesStyleBasedEditability();
1013             return true;
1014         }
1015         break;
1016     case CSSPropertyWebkitUserSelect: // auto | none | text | all
1017         if (valueID == CSSValueAuto || valueID == CSSValueNone || valueID == CSSValueText)
1018             return true;
1019         if (valueID == CSSValueAll) {
1020             if (styleSheetContents)
1021                 styleSheetContents->parserSetUsesStyleBasedEditability();
1022             return true;
1023         }
1024         break;
1025     case CSSPropertyWebkitWritingMode:
1026         if (valueID >= CSSValueHorizontalTb && valueID <= CSSValueHorizontalBt)
1027             return true;
1028         break;
1029     case CSSPropertyWhiteSpace: // normal | pre | nowrap | inherit
1030         if (valueID == CSSValueNormal || valueID == CSSValuePre || valueID == CSSValuePreWrap || valueID == CSSValuePreLine || valueID == CSSValueNowrap)
1031             return true;
1032         break;
1033     case CSSPropertyWordBreak: // normal | break-all | keep-all | break-word (this is a custom extension)
1034         if (valueID == CSSValueNormal || valueID == CSSValueBreakAll || valueID == CSSValueKeepAll || valueID == CSSValueBreakWord)
1035             return true;
1036         break;
1037 #if ENABLE(CSS_TRAILING_WORD)
1038     case CSSPropertyAppleTrailingWord: // auto | -apple-partially-balanced
1039         if (valueID == CSSValueAuto || valueID == CSSValueWebkitPartiallyBalanced)
1040             return true;
1041         break;
1042 #endif
1043     default:
1044         ASSERT_NOT_REACHED();
1045         return false;
1046     }
1047 #if !ENABLE(CSS_COMPOSITING) && !ENABLE(CSS_REGIONS)
1048     UNUSED_PARAM(parserContext);
1049 #endif
1050     return false;
1051 }
1052
1053 static inline bool isKeywordPropertyID(CSSPropertyID propertyId)
1054 {
1055     switch (propertyId) {
1056     case CSSPropertyBorderBottomStyle:
1057     case CSSPropertyBorderCollapse:
1058     case CSSPropertyBorderLeftStyle:
1059     case CSSPropertyBorderRightStyle:
1060     case CSSPropertyBorderTopStyle:
1061     case CSSPropertyBoxSizing:
1062     case CSSPropertyCaptionSide:
1063     case CSSPropertyClear:
1064     case CSSPropertyDirection:
1065     case CSSPropertyDisplay:
1066     case CSSPropertyEmptyCells:
1067     case CSSPropertyFloat:
1068     case CSSPropertyFontStyle:
1069     case CSSPropertyImageRendering:
1070     case CSSPropertyListStylePosition:
1071     case CSSPropertyListStyleType:
1072     case CSSPropertyObjectFit:
1073     case CSSPropertyOutlineStyle:
1074     case CSSPropertyOverflowWrap:
1075     case CSSPropertyOverflowX:
1076     case CSSPropertyOverflowY:
1077     case CSSPropertyPageBreakAfter:
1078     case CSSPropertyPageBreakBefore:
1079     case CSSPropertyPageBreakInside:
1080     case CSSPropertyPointerEvents:
1081     case CSSPropertyPosition:
1082     case CSSPropertyResize:
1083     case CSSPropertySpeak:
1084     case CSSPropertyTableLayout:
1085     case CSSPropertyTextLineThroughMode:
1086     case CSSPropertyTextLineThroughStyle:
1087     case CSSPropertyTextOverflow:
1088     case CSSPropertyTextOverlineMode:
1089     case CSSPropertyTextOverlineStyle:
1090     case CSSPropertyTextRendering:
1091     case CSSPropertyTextTransform:
1092     case CSSPropertyTextUnderlineMode:
1093     case CSSPropertyTextUnderlineStyle:
1094     case CSSPropertyVisibility:
1095     case CSSPropertyWebkitAppearance:
1096 #if ENABLE(CSS_COMPOSITING)
1097     case CSSPropertyMixBlendMode:
1098     case CSSPropertyIsolation:
1099 #endif
1100     case CSSPropertyWebkitBackfaceVisibility:
1101     case CSSPropertyWebkitBorderAfterStyle:
1102     case CSSPropertyWebkitBorderBeforeStyle:
1103     case CSSPropertyWebkitBorderEndStyle:
1104     case CSSPropertyWebkitBorderFit:
1105     case CSSPropertyWebkitBorderStartStyle:
1106     case CSSPropertyWebkitBoxAlign:
1107 #if ENABLE(CSS_BOX_DECORATION_BREAK)
1108     case CSSPropertyWebkitBoxDecorationBreak:
1109 #endif
1110     case CSSPropertyWebkitBoxDirection:
1111     case CSSPropertyWebkitBoxLines:
1112     case CSSPropertyWebkitBoxOrient:
1113     case CSSPropertyWebkitBoxPack:
1114     case CSSPropertyWebkitColorCorrection:
1115     case CSSPropertyWebkitColumnBreakAfter:
1116     case CSSPropertyWebkitColumnBreakBefore:
1117     case CSSPropertyWebkitColumnBreakInside:
1118     case CSSPropertyColumnFill:
1119     case CSSPropertyColumnRuleStyle:
1120     case CSSPropertyFlexDirection:
1121     case CSSPropertyFlexWrap:
1122     case CSSPropertyWebkitFontKerning:
1123     case CSSPropertyWebkitFontSmoothing:
1124     case CSSPropertyWebkitHyphens:
1125     case CSSPropertyWebkitLineAlign:
1126     case CSSPropertyWebkitLineBreak:
1127     case CSSPropertyWebkitLineSnap:
1128     case CSSPropertyWebkitMarginAfterCollapse:
1129     case CSSPropertyWebkitMarginBeforeCollapse:
1130     case CSSPropertyWebkitMarginBottomCollapse:
1131     case CSSPropertyWebkitMarginTopCollapse:
1132     case CSSPropertyWebkitMarqueeDirection:
1133     case CSSPropertyWebkitMarqueeStyle:
1134     case CSSPropertyWebkitNbspMode:
1135 #if ENABLE(ACCELERATED_OVERFLOW_SCROLLING)
1136     case CSSPropertyWebkitOverflowScrolling:
1137 #endif
1138     case CSSPropertyWebkitPrintColorAdjust:
1139 #if ENABLE(CSS_REGIONS)
1140     case CSSPropertyWebkitRegionBreakAfter:
1141     case CSSPropertyWebkitRegionBreakBefore:
1142     case CSSPropertyWebkitRegionBreakInside:
1143     case CSSPropertyWebkitRegionFragment:
1144 #endif
1145     case CSSPropertyWebkitRtlOrdering:
1146     case CSSPropertyWebkitRubyPosition:
1147 #if ENABLE(CSS3_TEXT)
1148     case CSSPropertyWebkitTextAlignLast:
1149 #endif // CSS3_TEXT
1150     case CSSPropertyWebkitTextCombine:
1151 #if ENABLE(CSS3_TEXT)
1152     case CSSPropertyWebkitTextJustify:
1153 #endif // CSS3_TEXT
1154     case CSSPropertyWebkitTextSecurity:
1155     case CSSPropertyTransformStyle:
1156     case CSSPropertyWebkitTransformStyle:
1157     case CSSPropertyWebkitUserDrag:
1158     case CSSPropertyWebkitUserModify:
1159     case CSSPropertyWebkitUserSelect:
1160     case CSSPropertyWebkitWritingMode:
1161     case CSSPropertyWhiteSpace:
1162     case CSSPropertyWordBreak:
1163     case CSSPropertyWordWrap:
1164 #if ENABLE(CSS_SCROLL_SNAP)
1165     case CSSPropertyWebkitScrollSnapType:
1166 #endif
1167 #if ENABLE(CSS_TRAILING_WORD)
1168     case CSSPropertyAppleTrailingWord:
1169 #endif
1170         return true;
1171     default:
1172         return false;
1173     }
1174 }
1175
1176 static CSSParser::ParseResult parseKeywordValue(MutableStyleProperties* declaration, CSSPropertyID propertyId, const String& string, bool important, const CSSParserContext& parserContext, StyleSheetContents* styleSheetContents)
1177 {
1178     ASSERT(!string.isEmpty());
1179
1180     if (!isKeywordPropertyID(propertyId)) {
1181         // All properties accept the values of "initial" and "inherit".
1182         String lowerCaseString = string.lower();
1183         if (lowerCaseString != "initial" && lowerCaseString != "inherit")
1184             return CSSParser::ParseResult::Error;
1185
1186         // Parse initial/inherit shorthands using the CSSParser.
1187         if (shorthandForProperty(propertyId).length())
1188             return CSSParser::ParseResult::Error;
1189     }
1190
1191     CSSParserString cssString;
1192     cssString.init(string);
1193     CSSValueID valueID = cssValueKeywordID(cssString);
1194
1195     if (!valueID)
1196         return CSSParser::ParseResult::Error;
1197
1198     RefPtr<CSSValue> value;
1199     if (valueID == CSSValueInherit)
1200         value = cssValuePool().createInheritedValue();
1201     else if (valueID == CSSValueInitial)
1202         value = cssValuePool().createExplicitInitialValue();
1203     else if (isValidKeywordPropertyAndValue(propertyId, valueID, parserContext, styleSheetContents))
1204         value = cssValuePool().createIdentifierValue(valueID);
1205     else
1206         return CSSParser::ParseResult::Error;
1207
1208     return declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important)) ? CSSParser::ParseResult::Changed : CSSParser::ParseResult::Unchanged;
1209 }
1210
1211 template <typename CharacterType>
1212 static bool parseTransformTranslateArguments(WebKitCSSTransformValue& transformValue, CharacterType* characters, unsigned length, unsigned start, unsigned expectedCount)
1213 {
1214     while (expectedCount) {
1215         size_t end = WTF::find(characters, length, expectedCount == 1 ? ')' : ',', start);
1216         if (end == notFound || (expectedCount == 1 && end != length - 1))
1217             return false;
1218         unsigned argumentLength = end - start;
1219         CSSPrimitiveValue::UnitTypes unit = CSSPrimitiveValue::CSS_NUMBER;
1220         double number;
1221         if (!parseSimpleLength(characters + start, argumentLength, unit, number))
1222             return false;
1223         if (unit != CSSPrimitiveValue::CSS_PX && (number || unit != CSSPrimitiveValue::CSS_NUMBER))
1224             return false;
1225         transformValue.append(cssValuePool().createValue(number, CSSPrimitiveValue::CSS_PX));
1226         start = end + 1;
1227         --expectedCount;
1228     }
1229     return true;
1230 }
1231
1232 static CSSParser::ParseResult parseTranslateTransformValue(MutableStyleProperties* properties, CSSPropertyID propertyID, const String& string, bool important)
1233 {
1234     if (propertyID != CSSPropertyTransform)
1235         return CSSParser::ParseResult::Error;
1236
1237     static const unsigned shortestValidTransformStringLength = 12;
1238     static const unsigned likelyMultipartTransformStringLengthCutoff = 32;
1239     if (string.length() < shortestValidTransformStringLength || string.length() > likelyMultipartTransformStringLengthCutoff)
1240         return CSSParser::ParseResult::Error;
1241
1242     if (!string.startsWith("translate", false))
1243         return CSSParser::ParseResult::Error;
1244
1245     UChar c9 = toASCIILower(string[9]);
1246     UChar c10 = toASCIILower(string[10]);
1247
1248     WebKitCSSTransformValue::TransformOperationType transformType;
1249     unsigned expectedArgumentCount = 1;
1250     unsigned argumentStart = 11;
1251     if (c9 == 'x' && c10 == '(')
1252         transformType = WebKitCSSTransformValue::TranslateXTransformOperation;
1253     else if (c9 == 'y' && c10 == '(')
1254         transformType = WebKitCSSTransformValue::TranslateYTransformOperation;
1255     else if (c9 == 'z' && c10 == '(')
1256         transformType = WebKitCSSTransformValue::TranslateZTransformOperation;
1257     else if (c9 == '(') {
1258         transformType = WebKitCSSTransformValue::TranslateTransformOperation;
1259         expectedArgumentCount = 2;
1260         argumentStart = 10;
1261     } else if (c9 == '3' && c10 == 'd' && string[11] == '(') {
1262         transformType = WebKitCSSTransformValue::Translate3DTransformOperation;
1263         expectedArgumentCount = 3;
1264         argumentStart = 12;
1265     } else
1266         return CSSParser::ParseResult::Error;
1267
1268     RefPtr<WebKitCSSTransformValue> transformValue = WebKitCSSTransformValue::create(transformType);
1269     bool success;
1270     if (string.is8Bit())
1271         success = parseTransformTranslateArguments(*transformValue, string.characters8(), string.length(), argumentStart, expectedArgumentCount);
1272     else
1273         success = parseTransformTranslateArguments(*transformValue, string.characters16(), string.length(), argumentStart, expectedArgumentCount);
1274     if (!success)
1275         return CSSParser::ParseResult::Error;
1276
1277     RefPtr<CSSValueList> result = CSSValueList::createSpaceSeparated();
1278     result->append(transformValue.releaseNonNull());
1279     return properties->addParsedProperty(CSSProperty(CSSPropertyTransform, result.release(), important)) ? CSSParser::ParseResult::Changed : CSSParser::ParseResult::Unchanged;
1280 }
1281
1282 PassRefPtr<CSSValueList> CSSParser::parseFontFaceValue(const AtomicString& string)
1283 {
1284     if (string.isEmpty())
1285         return nullptr;
1286
1287     Ref<CSSValueList> valueList = CSSValueList::createCommaSeparated();
1288
1289     Vector<String> familyNames;
1290     string.string().split(',', true, familyNames);
1291
1292     for (auto& familyName : familyNames) {
1293         String stripped = stripLeadingAndTrailingHTMLSpaces(familyName);
1294         if (stripped.isEmpty())
1295             return nullptr;
1296
1297         RefPtr<CSSValue> value;
1298         for (auto propertyID : { CSSValueSerif, CSSValueSansSerif, CSSValueCursive, CSSValueFantasy, CSSValueMonospace, CSSValueWebkitBody }) {
1299             if (equalIgnoringCase(stripped, getValueName(propertyID))) {
1300                 value = cssValuePool().createIdentifierValue(propertyID);
1301                 break;
1302             }
1303         }
1304         if (!value)
1305             value = cssValuePool().createFontFamilyValue(stripped);
1306         valueList->append(value.releaseNonNull());
1307     }
1308
1309     return WTF::move(valueList);
1310 }
1311
1312 CSSParser::ParseResult CSSParser::parseValue(MutableStyleProperties* declaration, CSSPropertyID propertyID, const String& string, bool important, CSSParserMode cssParserMode, StyleSheetContents* contextStyleSheet)
1313 {
1314     ASSERT(!string.isEmpty());
1315     CSSParser::ParseResult result = parseSimpleLengthValue(declaration, propertyID, string, important, cssParserMode);
1316     if (result != ParseResult::Error)
1317         return result;
1318
1319     result = parseColorValue(declaration, propertyID, string, important, cssParserMode);
1320     if (result != ParseResult::Error)
1321         return result;
1322
1323     CSSParserContext context(cssParserMode);
1324     if (contextStyleSheet) {
1325         context = contextStyleSheet->parserContext();
1326         context.mode = cssParserMode;
1327     }
1328
1329     result = parseKeywordValue(declaration, propertyID, string, important, context, contextStyleSheet);
1330     if (result != ParseResult::Error)
1331         return result;
1332
1333     result = parseTranslateTransformValue(declaration, propertyID, string, important);
1334     if (result != ParseResult::Error)
1335         return result;
1336
1337     CSSParser parser(context);
1338     return parser.parseValue(declaration, propertyID, string, important, contextStyleSheet);
1339 }
1340
1341 CSSParser::ParseResult CSSParser::parseValue(MutableStyleProperties* declaration, CSSPropertyID propertyID, const String& string, bool important, StyleSheetContents* contextStyleSheet)
1342 {
1343     setStyleSheet(contextStyleSheet);
1344
1345     setupParser("@-webkit-value{", string, "} ");
1346
1347     m_id = propertyID;
1348     m_important = important;
1349
1350     cssyyparse(this);
1351
1352     m_rule = nullptr;
1353
1354     ParseResult result = ParseResult::Error;
1355     if (m_hasFontFaceOnlyValues)
1356         deleteFontFaceOnlyValues();
1357
1358     if (!m_parsedProperties.isEmpty()) {
1359         result = declaration->addParsedProperties(m_parsedProperties) ? ParseResult::Changed : ParseResult::Unchanged;
1360         clearProperties();
1361     }
1362
1363     return result;
1364 }
1365
1366 // The color will only be changed when string contains a valid CSS color, so callers
1367 // can set it to a default color and ignore the boolean result.
1368 bool CSSParser::parseColor(RGBA32& color, const String& string, bool strict)
1369 {
1370     // First try creating a color specified by name, rgba(), rgb() or "#" syntax.
1371     if (fastParseColor(color, string, strict))
1372         return true;
1373
1374     CSSParser parser(CSSStrictMode);
1375
1376     // In case the fast-path parser didn't understand the color, try the full parser.
1377     if (!parser.parseColor(string))
1378         return false;
1379
1380     CSSValue& value = *parser.m_parsedProperties.first().value();
1381     if (!is<CSSPrimitiveValue>(value))
1382         return false;
1383
1384     CSSPrimitiveValue& primitiveValue = downcast<CSSPrimitiveValue>(value);
1385     if (!primitiveValue.isRGBColor())
1386         return false;
1387
1388     color = primitiveValue.getRGBA32Value();
1389     return true;
1390 }
1391
1392 bool CSSParser::parseColor(const String& string)
1393 {
1394     setupParser("@-webkit-decls{color:", string, "} ");
1395     cssyyparse(this);
1396     m_rule = nullptr;
1397
1398     return !m_parsedProperties.isEmpty() && m_parsedProperties.first().id() == CSSPropertyColor;
1399 }
1400
1401 bool CSSParser::parseSystemColor(RGBA32& color, const String& string, Document* document)
1402 {
1403     if (!document || !document->page())
1404         return false;
1405
1406     CSSParserString cssColor;
1407     cssColor.init(string);
1408     CSSValueID id = cssValueKeywordID(cssColor);
1409     if (!validPrimitiveValueColor(id))
1410         return false;
1411
1412     Color parsedColor = document->page()->theme().systemColor(id);
1413     if (!parsedColor.isValid())
1414         return false;
1415
1416     color = parsedColor.rgb();
1417     return true;
1418 }
1419
1420 void CSSParser::parseSelector(const String& string, CSSSelectorList& selectorList)
1421 {
1422     m_selectorListForParseSelector = &selectorList;
1423
1424     setupParser("@-webkit-selector{", string, "}");
1425
1426     cssyyparse(this);
1427
1428     m_selectorListForParseSelector = nullptr;
1429 }
1430
1431 Ref<ImmutableStyleProperties> CSSParser::parseInlineStyleDeclaration(const String& string, Element* element)
1432 {
1433     CSSParserContext context = element->document().elementSheet().contents().parserContext();
1434     context.mode = strictToCSSParserMode(element->isHTMLElement() && !element->document().inQuirksMode());
1435     return CSSParser(context).parseDeclaration(string, &element->document().elementSheet().contents());
1436 }
1437
1438 Ref<ImmutableStyleProperties> CSSParser::parseDeclaration(const String& string, StyleSheetContents* contextStyleSheet)
1439 {
1440     setStyleSheet(contextStyleSheet);
1441
1442     setupParser("@-webkit-decls{", string, "} ");
1443     cssyyparse(this);
1444     m_rule = nullptr;
1445
1446     if (m_hasFontFaceOnlyValues)
1447         deleteFontFaceOnlyValues();
1448
1449     Ref<ImmutableStyleProperties> style = createStyleProperties();
1450     clearProperties();
1451     return style;
1452 }
1453
1454
1455 bool CSSParser::parseDeclaration(MutableStyleProperties* declaration, const String& string, PassRefPtr<CSSRuleSourceData> prpRuleSourceData, StyleSheetContents* contextStyleSheet)
1456 {
1457     // Length of the "@-webkit-decls{" prefix.
1458     static const unsigned prefixLength = 15;
1459
1460     setStyleSheet(contextStyleSheet);
1461
1462     RefPtr<CSSRuleSourceData> ruleSourceData = prpRuleSourceData;
1463     if (ruleSourceData) {
1464         m_currentRuleDataStack = std::make_unique<RuleSourceDataList>();
1465         m_currentRuleDataStack->append(ruleSourceData);
1466     }
1467
1468     setupParser("@-webkit-decls{", string, "} ");
1469     cssyyparse(this);
1470     m_rule = nullptr;
1471
1472     bool ok = false;
1473     if (m_hasFontFaceOnlyValues)
1474         deleteFontFaceOnlyValues();
1475     if (!m_parsedProperties.isEmpty()) {
1476         ok = true;
1477         declaration->addParsedProperties(m_parsedProperties);
1478         clearProperties();
1479     }
1480
1481     if (ruleSourceData) {
1482         ASSERT(m_currentRuleDataStack->size() == 1);
1483         ruleSourceData->ruleBodyRange.start = 0;
1484         ruleSourceData->ruleBodyRange.end = string.length();
1485         for (size_t i = 0, size = ruleSourceData->styleSourceData->propertyData.size(); i < size; ++i) {
1486             CSSPropertySourceData& propertyData = ruleSourceData->styleSourceData->propertyData.at(i);
1487             propertyData.range.start -= prefixLength;
1488             propertyData.range.end -= prefixLength;
1489         }
1490
1491         fixUnparsedPropertyRanges(ruleSourceData.get());
1492         m_currentRuleDataStack.reset();
1493     }
1494
1495     return ok;
1496 }
1497
1498 std::unique_ptr<MediaQuery> CSSParser::parseMediaQuery(const String& string)
1499 {
1500     if (string.isEmpty())
1501         return nullptr;
1502
1503     ASSERT(!m_mediaQuery);
1504
1505     // can't use { because tokenizer state switches from mediaquery to initial state when it sees { token.
1506     // instead insert one " " (which is WHITESPACE in CSSGrammar.y)
1507     setupParser("@-webkit-mediaquery ", string, "} ");
1508     cssyyparse(this);
1509
1510     return WTF::move(m_mediaQuery);
1511 }
1512
1513 Vector<CSSParser::SourceSize> CSSParser::parseSizesAttribute(StringView string)
1514 {
1515     Vector<SourceSize> result;
1516
1517     if (string.isEmpty())
1518         return result;
1519
1520     ASSERT(!m_sourceSizeList);
1521
1522     setupParser("@-webkit-sizesattr ", string, "}");
1523     cssyyparse(this);
1524
1525     if (!m_sourceSizeList)
1526         return result;
1527
1528     result = WTF::move(*m_sourceSizeList);
1529     m_sourceSizeList = nullptr;
1530     return result;
1531 }
1532
1533 // FIXME(141289): The following two constructors are only needed because of a bug in MSVC 2013 (and prior).
1534 // We should remove this code as soon as a Visual Studio update that fixes this problem is released.
1535 CSSParser::SourceSize::SourceSize(CSSParser::SourceSize&& original)
1536     : expression(WTF::move(original.expression))
1537     , length(original.length)
1538 {
1539 }
1540
1541 CSSParser::SourceSize::SourceSize(std::unique_ptr<MediaQueryExp>&& origExp, RefPtr<CSSValue> value)
1542     : expression(WTF::move(origExp))
1543     , length(value)
1544 {
1545 }
1546
1547 CSSParser::SourceSize CSSParser::sourceSize(std::unique_ptr<MediaQueryExp>&& expression, CSSParserValue& parserValue)
1548 {
1549     RefPtr<CSSValue> value;
1550     if (isCalculation(parserValue)) {
1551         auto* args = parserValue.function->args.get();
1552         if (args && args->size())
1553             value = CSSCalcValue::create(parserValue.function->name, *args, CalculationRangeNonNegative);
1554     }
1555     if (!value)
1556         value = parserValue.createCSSValue();
1557     destroy(parserValue);
1558     // FIXME: Calling the constructor explicitly here to work around an MSVC bug.
1559     // For other compilers, we did not need to define the constructors and we could use aggregate initialization syntax.
1560     return SourceSize(WTF::move(expression), WTF::move(value));
1561 }
1562
1563 static inline void filterProperties(bool important, const CSSParser::ParsedPropertyVector& input, Vector<CSSProperty, 256>& output, size_t& unusedEntries, std::bitset<numCSSProperties>& seenProperties)
1564 {
1565     // Add properties in reverse order so that highest priority definitions are reached first. Duplicate definitions can then be ignored when found.
1566     for (int i = input.size() - 1; i >= 0; --i) {
1567         const CSSProperty& property = input[i];
1568         if (property.isImportant() != important)
1569             continue;
1570         const unsigned propertyIDIndex = property.id() - firstCSSProperty;
1571         ASSERT(propertyIDIndex < seenProperties.size());
1572         if (seenProperties[propertyIDIndex])
1573             continue;
1574         seenProperties.set(propertyIDIndex);
1575         output[--unusedEntries] = property;
1576     }
1577 }
1578
1579 Ref<ImmutableStyleProperties> CSSParser::createStyleProperties()
1580 {
1581     std::bitset<numCSSProperties> seenProperties;
1582     size_t unusedEntries = m_parsedProperties.size();
1583     Vector<CSSProperty, 256> results(unusedEntries);
1584
1585     // Important properties have higher priority, so add them first. Duplicate definitions can then be ignored when found.
1586     filterProperties(true, m_parsedProperties, results, unusedEntries, seenProperties);
1587     filterProperties(false, m_parsedProperties, results, unusedEntries, seenProperties);
1588     if (unusedEntries)
1589         results.remove(0, unusedEntries);
1590
1591     return ImmutableStyleProperties::create(results.data(), results.size(), m_context.mode);
1592 }
1593
1594 void CSSParser::addPropertyWithPrefixingVariant(CSSPropertyID propId, PassRefPtr<CSSValue> value, bool important, bool implicit)
1595 {
1596     RefPtr<CSSValue> val = value.get();
1597     addProperty(propId, value, important, implicit);
1598
1599     CSSPropertyID prefixingVariant = prefixingVariantForPropertyId(propId);
1600     if (prefixingVariant == propId)
1601         return;
1602
1603     if (m_currentShorthand) {
1604         // We can't use ShorthandScope here as we can already be inside one (e.g we are parsing CSSTransition).
1605         m_currentShorthand = prefixingVariantForPropertyId(m_currentShorthand);
1606         addProperty(prefixingVariant, val.release(), important, implicit);
1607         m_currentShorthand = prefixingVariantForPropertyId(m_currentShorthand);
1608     } else
1609         addProperty(prefixingVariant, val.release(), important, implicit);
1610 }
1611
1612 void CSSParser::addProperty(CSSPropertyID propId, PassRefPtr<CSSValue> value, bool important, bool implicit)
1613 {
1614     // This property doesn't belong to a shorthand or is a CSS variable (which will be resolved later).
1615     if (!m_currentShorthand) {
1616         m_parsedProperties.append(CSSProperty(propId, value, important, false, CSSPropertyInvalid, m_implicitShorthand || implicit));
1617         return;
1618     }
1619
1620     Vector<StylePropertyShorthand> shorthands = matchingShorthandsForLonghand(propId);
1621     if (shorthands.size() == 1)
1622         m_parsedProperties.append(CSSProperty(propId, value, important, true, CSSPropertyInvalid, m_implicitShorthand || implicit));
1623     else
1624         m_parsedProperties.append(CSSProperty(propId, value, important, true, indexOfShorthandForLonghand(m_currentShorthand, shorthands), m_implicitShorthand || implicit));
1625 }
1626
1627 void CSSParser::rollbackLastProperties(int num)
1628 {
1629     ASSERT(num >= 0);
1630     ASSERT(m_parsedProperties.size() >= static_cast<unsigned>(num));
1631     m_parsedProperties.shrink(m_parsedProperties.size() - num);
1632 }
1633
1634 void CSSParser::clearProperties()
1635 {
1636     m_parsedProperties.clear();
1637     m_numParsedPropertiesBeforeMarginBox = INVALID_NUM_PARSED_PROPERTIES;
1638     m_hasFontFaceOnlyValues = false;
1639 }
1640
1641 URL CSSParser::completeURL(const CSSParserContext& context, const String& url)
1642 {
1643     if (url.isNull())
1644         return URL();
1645     if (context.charset.isEmpty())
1646         return URL(context.baseURL, url);
1647     return URL(context.baseURL, url, context.charset);
1648 }
1649
1650 URL CSSParser::completeURL(const String& url) const
1651 {
1652     return completeURL(m_context, url);
1653 }
1654
1655 bool CSSParser::validateCalculationUnit(ValueWithCalculation& valueWithCalculation, Units unitFlags)
1656 {
1657     bool mustBeNonNegative = unitFlags & FNonNeg;
1658
1659     RefPtr<CSSCalcValue> calculation;
1660     if (valueWithCalculation.calculation()) {
1661         // The calculation value was already parsed so we reuse it. However, we may need to update its range.
1662         calculation = valueWithCalculation.calculation();
1663         calculation->setPermittedValueRange(mustBeNonNegative ? CalculationRangeNonNegative : CalculationRangeAll);
1664     } else {
1665         valueWithCalculation.setCalculation(parseCalculation(valueWithCalculation, mustBeNonNegative ? CalculationRangeNonNegative : CalculationRangeAll));
1666         calculation = valueWithCalculation.calculation();
1667         if (!calculation)
1668             return false;
1669     }
1670
1671     bool isValid = false;
1672     switch (calculation->category()) {
1673     case CalcNumber:
1674         isValid = (unitFlags & FNumber);
1675         if (!isValid && (unitFlags & FInteger) && calculation->isInt())
1676             isValid = true;
1677         if (!isValid && (unitFlags & FPositiveInteger) && calculation->isInt() && calculation->isPositive())
1678             isValid = true;
1679         break;
1680     case CalcLength:
1681         isValid = (unitFlags & FLength);
1682         break;
1683     case CalcPercent:
1684         isValid = (unitFlags & FPercent);
1685         break;
1686     case CalcPercentLength:
1687         isValid = (unitFlags & FPercent) && (unitFlags & FLength);
1688         break;
1689     case CalcPercentNumber:
1690         isValid = (unitFlags & FPercent) && (unitFlags & FNumber);
1691         break;
1692     case CalcAngle:
1693         isValid = (unitFlags & FAngle);
1694         break;
1695     case CalcTime:
1696         isValid = (unitFlags & FTime);
1697         break;
1698     case CalcFrequency:
1699         isValid = (unitFlags & FFrequency);
1700         break;
1701     case CalcOther:
1702         break;
1703     }
1704
1705     return isValid;
1706 }
1707
1708 inline bool CSSParser::shouldAcceptUnitLessValues(CSSParserValue& value, Units unitFlags, CSSParserMode cssParserMode)
1709 {
1710     // Qirks mode and svg presentation attributes accept unit less values.
1711     return (unitFlags & (FLength | FAngle | FTime)) && (!value.fValue || cssParserMode == CSSQuirksMode || cssParserMode == SVGAttributeMode);
1712 }
1713
1714 bool CSSParser::validateUnit(ValueWithCalculation& valueWithCalculation, Units unitFlags, CSSParserMode cssParserMode)
1715 {
1716     if (isCalculation(valueWithCalculation))
1717         return validateCalculationUnit(valueWithCalculation, unitFlags);
1718         
1719     bool b = false;
1720     switch (valueWithCalculation.value().unit) {
1721     case CSSPrimitiveValue::CSS_NUMBER:
1722         b = (unitFlags & FNumber);
1723         if (!b && shouldAcceptUnitLessValues(valueWithCalculation, unitFlags, cssParserMode)) {
1724             valueWithCalculation.value().unit = (unitFlags & FLength) ? CSSPrimitiveValue::CSS_PX :
1725                           ((unitFlags & FAngle) ? CSSPrimitiveValue::CSS_DEG : CSSPrimitiveValue::CSS_MS);
1726             b = true;
1727         }
1728         if (!b && (unitFlags & FInteger) && valueWithCalculation.value().isInt)
1729             b = true;
1730         if (!b && (unitFlags & FPositiveInteger) && valueWithCalculation.value().isInt && valueWithCalculation.value().fValue > 0)
1731             b = true;
1732         break;
1733     case CSSPrimitiveValue::CSS_PERCENTAGE:
1734         b = (unitFlags & FPercent);
1735         break;
1736     case CSSParserValue::Q_EMS:
1737     case CSSPrimitiveValue::CSS_EMS:
1738     case CSSPrimitiveValue::CSS_REMS:
1739     case CSSPrimitiveValue::CSS_CHS:
1740     case CSSPrimitiveValue::CSS_EXS:
1741     case CSSPrimitiveValue::CSS_PX:
1742     case CSSPrimitiveValue::CSS_CM:
1743     case CSSPrimitiveValue::CSS_MM:
1744     case CSSPrimitiveValue::CSS_IN:
1745     case CSSPrimitiveValue::CSS_PT:
1746     case CSSPrimitiveValue::CSS_PC:
1747     case CSSPrimitiveValue::CSS_VW:
1748     case CSSPrimitiveValue::CSS_VH:
1749     case CSSPrimitiveValue::CSS_VMIN:
1750     case CSSPrimitiveValue::CSS_VMAX:
1751         b = (unitFlags & FLength);
1752         break;
1753     case CSSPrimitiveValue::CSS_MS:
1754     case CSSPrimitiveValue::CSS_S:
1755         b = (unitFlags & FTime);
1756         break;
1757     case CSSPrimitiveValue::CSS_DEG:
1758     case CSSPrimitiveValue::CSS_RAD:
1759     case CSSPrimitiveValue::CSS_GRAD:
1760     case CSSPrimitiveValue::CSS_TURN:
1761         b = (unitFlags & FAngle);
1762         break;
1763 #if ENABLE(CSS_IMAGE_RESOLUTION) || ENABLE(RESOLUTION_MEDIA_QUERY)
1764     case CSSPrimitiveValue::CSS_DPPX:
1765     case CSSPrimitiveValue::CSS_DPI:
1766     case CSSPrimitiveValue::CSS_DPCM:
1767         b = (unitFlags & FResolution);
1768         break;
1769 #endif
1770     case CSSPrimitiveValue::CSS_HZ:
1771     case CSSPrimitiveValue::CSS_KHZ:
1772     case CSSPrimitiveValue::CSS_DIMENSION:
1773     default:
1774         break;
1775     }
1776     if (b && unitFlags & FNonNeg && valueWithCalculation.value().fValue < 0)
1777         b = false;
1778     if (b && std::isinf(valueWithCalculation.value().fValue))
1779         b = false;
1780     return b;
1781 }
1782
1783 inline Ref<CSSPrimitiveValue> CSSParser::createPrimitiveNumericValue(ValueWithCalculation& valueWithCalculation)
1784 {
1785     if (valueWithCalculation.calculation())
1786         return CSSPrimitiveValue::create(valueWithCalculation.calculation());
1787
1788     CSSParserValue& value = valueWithCalculation;
1789 #if ENABLE(CSS_IMAGE_RESOLUTION) || ENABLE(RESOLUTION_MEDIA_QUERY)
1790     ASSERT((value.unit >= CSSPrimitiveValue::CSS_NUMBER && value.unit <= CSSPrimitiveValue::CSS_KHZ)
1791         || (value.unit >= CSSPrimitiveValue::CSS_TURN && value.unit <= CSSPrimitiveValue::CSS_CHS)
1792         || (value.unit >= CSSPrimitiveValue::CSS_VW && value.unit <= CSSPrimitiveValue::CSS_VMAX)
1793         || (value.unit >= CSSPrimitiveValue::CSS_DPPX && value.unit <= CSSPrimitiveValue::CSS_DPCM));
1794 #else
1795     ASSERT((value.unit >= CSSPrimitiveValue::CSS_NUMBER && value.unit <= CSSPrimitiveValue::CSS_KHZ)
1796         || (value.unit >= CSSPrimitiveValue::CSS_TURN && value.unit <= CSSPrimitiveValue::CSS_CHS)
1797         || (value.unit >= CSSPrimitiveValue::CSS_VW && value.unit <= CSSPrimitiveValue::CSS_VMAX));
1798 #endif
1799     return cssValuePool().createValue(value.fValue, static_cast<CSSPrimitiveValue::UnitTypes>(value.unit));
1800 }
1801
1802 inline Ref<CSSPrimitiveValue> CSSParser::createPrimitiveStringValue(CSSParserValue& value)
1803 {
1804     ASSERT(value.unit == CSSPrimitiveValue::CSS_STRING || value.unit == CSSPrimitiveValue::CSS_IDENT);
1805     return cssValuePool().createValue(value.string, CSSPrimitiveValue::CSS_STRING);
1806 }
1807
1808 static inline bool isComma(CSSParserValue* value)
1809
1810     return value && value->unit == CSSParserValue::Operator && value->iValue == ','; 
1811 }
1812
1813 static inline bool isForwardSlashOperator(CSSParserValue& value)
1814 {
1815     return value.unit == CSSParserValue::Operator && value.iValue == '/';
1816 }
1817
1818 bool CSSParser::validateWidth(ValueWithCalculation& valueWithCalculation)
1819 {
1820     int id = valueWithCalculation.value().id;
1821     if (id == CSSValueIntrinsic || id == CSSValueMinIntrinsic || id == CSSValueWebkitMinContent || id == CSSValueWebkitMaxContent || id == CSSValueWebkitFillAvailable || id == CSSValueWebkitFitContent)
1822         return true;
1823     return !id && validateUnit(valueWithCalculation, FLength | FPercent | FNonNeg);
1824 }
1825
1826 // FIXME: Combine this with validWidth when we support fit-content, et al, for heights.
1827 bool CSSParser::validateHeight(ValueWithCalculation& valueWithCalculation)
1828 {
1829     int id = valueWithCalculation.value().id;
1830     if (id == CSSValueIntrinsic || id == CSSValueMinIntrinsic)
1831         return true;
1832     return !id && validateUnit(valueWithCalculation, FLength | FPercent | FNonNeg);
1833 }
1834
1835 inline PassRefPtr<CSSPrimitiveValue> CSSParser::parseValidPrimitive(CSSValueID identifier, ValueWithCalculation& valueWithCalculation)
1836 {
1837     if (identifier)
1838         return cssValuePool().createIdentifierValue(identifier);
1839
1840     if (valueWithCalculation.value().unit == CSSPrimitiveValue::CSS_STRING)
1841         return createPrimitiveStringValue(valueWithCalculation);
1842     if (valueWithCalculation.value().unit >= CSSPrimitiveValue::CSS_NUMBER && valueWithCalculation.value().unit <= CSSPrimitiveValue::CSS_KHZ)
1843         return createPrimitiveNumericValue(valueWithCalculation);
1844     if (valueWithCalculation.value().unit >= CSSPrimitiveValue::CSS_TURN && valueWithCalculation.value().unit <= CSSPrimitiveValue::CSS_CHS)
1845         return createPrimitiveNumericValue(valueWithCalculation);
1846     if (valueWithCalculation.value().unit >= CSSPrimitiveValue::CSS_VW && valueWithCalculation.value().unit <= CSSPrimitiveValue::CSS_VMAX)
1847         return createPrimitiveNumericValue(valueWithCalculation);
1848 #if ENABLE(CSS_IMAGE_RESOLUTION) || ENABLE(RESOLUTION_MEDIA_QUERY)
1849     if (valueWithCalculation.value().unit >= CSSPrimitiveValue::CSS_DPPX && valueWithCalculation.value().unit <= CSSPrimitiveValue::CSS_DPCM)
1850         return createPrimitiveNumericValue(valueWithCalculation);
1851 #endif
1852     if (valueWithCalculation.value().unit >= CSSParserValue::Q_EMS)
1853         return CSSPrimitiveValue::createAllowingMarginQuirk(valueWithCalculation.value().fValue, CSSPrimitiveValue::CSS_EMS);
1854     if (valueWithCalculation.calculation())
1855         return CSSPrimitiveValue::create(valueWithCalculation.calculation());
1856
1857     return nullptr;
1858 }
1859
1860 void CSSParser::addExpandedPropertyForValue(CSSPropertyID propId, PassRefPtr<CSSValue> prpValue, bool important)
1861 {
1862     const StylePropertyShorthand& shorthand = shorthandForProperty(propId);
1863     unsigned shorthandLength = shorthand.length();
1864     if (!shorthandLength) {
1865         addProperty(propId, prpValue, important);
1866         return;
1867     }
1868
1869     RefPtr<CSSValue> value = prpValue;
1870     ShorthandScope scope(this, propId);
1871     const CSSPropertyID* longhands = shorthand.properties();
1872     for (unsigned i = 0; i < shorthandLength; ++i)
1873         addProperty(longhands[i], value, important);
1874 }
1875
1876 bool CSSParser::parseValue(CSSPropertyID propId, bool important)
1877 {
1878     if (!m_valueList || !m_valueList->current())
1879         return false;
1880
1881     ValueWithCalculation valueWithCalculation(*m_valueList->current());
1882     CSSValueID id = valueWithCalculation.value().id;
1883
1884     unsigned num = inShorthand() ? 1 : m_valueList->size();
1885
1886     if (id == CSSValueInherit) {
1887         if (num != 1)
1888             return false;
1889         addExpandedPropertyForValue(propId, cssValuePool().createInheritedValue(), important);
1890         return true;
1891     }
1892     else if (id == CSSValueInitial) {
1893         if (num != 1)
1894             return false;
1895         addExpandedPropertyForValue(propId, cssValuePool().createExplicitInitialValue(), important);
1896         return true;
1897     }
1898
1899     if (isKeywordPropertyID(propId)) {
1900         if (!isValidKeywordPropertyAndValue(propId, id, m_context, m_styleSheet))
1901             return false;
1902         if (m_valueList->next() && !inShorthand())
1903             return false;
1904         addProperty(propId, cssValuePool().createIdentifierValue(id), important);
1905         return true;
1906     }
1907
1908 #if ENABLE(CSS_DEVICE_ADAPTATION)
1909     if (inViewport())
1910         return parseViewportProperty(propId, important);
1911 #endif
1912
1913     bool validPrimitive = false;
1914     RefPtr<CSSValue> parsedValue;
1915
1916     switch (propId) {
1917     case CSSPropertySize:                 // <length>{1,2} | auto | [ <page-size> || [ portrait | landscape] ]
1918         return parseSize(propId, important);
1919
1920     case CSSPropertyQuotes:               // [<string> <string>]+ | none | inherit
1921         if (id == CSSValueNone)
1922             validPrimitive = true;
1923         else
1924             return parseQuotes(propId, important);
1925         break;
1926     case CSSPropertyUnicodeBidi: // normal | embed | bidi-override | isolate | isolate-override | plaintext | inherit
1927         if (id == CSSValueNormal
1928             || id == CSSValueEmbed
1929             || id == CSSValueBidiOverride
1930             || id == CSSValueWebkitIsolate
1931             || id == CSSValueWebkitIsolateOverride
1932             || id == CSSValueWebkitPlaintext)
1933             validPrimitive = true;
1934         break;
1935
1936     case CSSPropertyContent:              // [ <string> | <uri> | <counter> | attr(X) | open-quote |
1937         // close-quote | no-open-quote | no-close-quote ]+ | inherit
1938         return parseContent(propId, important);
1939
1940     case CSSPropertyAlt: // [ <string> | attr(X) ]
1941         return parseAlt(propId, important);
1942             
1943     case CSSPropertyClip:                 // <shape> | auto | inherit
1944         if (id == CSSValueAuto)
1945             validPrimitive = true;
1946         else if (valueWithCalculation.value().unit == CSSParserValue::Function)
1947             return parseClipShape(propId, important);
1948         break;
1949
1950     /* Start of supported CSS properties with validation. This is needed for parseShorthand to work
1951      * correctly and allows optimization in WebCore::applyRule(..)
1952      */
1953     case CSSPropertyOverflow: {
1954         ShorthandScope scope(this, propId);
1955         if (num != 1 || !parseValue(CSSPropertyOverflowY, important))
1956             return false;
1957
1958         RefPtr<CSSValue> overflowXValue;
1959
1960         // FIXME: -webkit-paged-x or -webkit-paged-y only apply to overflow-y. If this value has been
1961         // set using the shorthand, then for now overflow-x will default to auto, but once we implement
1962         // pagination controls, it should default to hidden. If the overflow-y value is anything but
1963         // paged-x or paged-y, then overflow-x and overflow-y should have the same value.
1964         if (id == CSSValueWebkitPagedX || id == CSSValueWebkitPagedY)
1965             overflowXValue = cssValuePool().createIdentifierValue(CSSValueAuto);
1966         else
1967             overflowXValue = m_parsedProperties.last().value();
1968         addProperty(CSSPropertyOverflowX, overflowXValue.release(), important);
1969         return true;
1970     }
1971
1972     case CSSPropertyTextAlign:
1973         // left | right | center | justify | -webkit-left | -webkit-right | -webkit-center | -webkit-match-parent
1974         // | start | end | inherit | -webkit-auto (converted to start)
1975         // NOTE: <string> is not supported.
1976         if ((id >= CSSValueWebkitAuto && id <= CSSValueWebkitMatchParent) || id == CSSValueStart || id == CSSValueEnd)
1977             validPrimitive = true;
1978         break;
1979
1980     case CSSPropertyFontWeight:  { // normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | inherit
1981         if (m_valueList->size() != 1)
1982             return false;
1983         return parseFontWeight(important);
1984     }
1985
1986     case CSSPropertyFontSynthesis: // none | [ weight || style ]
1987         return parseFontSynthesis(important);
1988
1989     case CSSPropertyBorderSpacing: {
1990         if (num == 1) {
1991             ShorthandScope scope(this, CSSPropertyBorderSpacing);
1992             if (!parseValue(CSSPropertyWebkitBorderHorizontalSpacing, important))
1993                 return false;
1994             CSSValue* value = m_parsedProperties.last().value();
1995             addProperty(CSSPropertyWebkitBorderVerticalSpacing, value, important);
1996             return true;
1997         }
1998         else if (num == 2) {
1999             ShorthandScope scope(this, CSSPropertyBorderSpacing);
2000             if (!parseValue(CSSPropertyWebkitBorderHorizontalSpacing, important) || !parseValue(CSSPropertyWebkitBorderVerticalSpacing, important))
2001                 return false;
2002             return true;
2003         }
2004         return false;
2005     }
2006     case CSSPropertyWebkitBorderHorizontalSpacing:
2007     case CSSPropertyWebkitBorderVerticalSpacing:
2008         validPrimitive = validateUnit(valueWithCalculation, FLength | FNonNeg);
2009         break;
2010     case CSSPropertyOutlineColor:        // <color> | invert | inherit
2011         // Outline color has "invert" as additional keyword.
2012         // Also, we want to allow the special focus color even in strict parsing mode.
2013         if (id == CSSValueInvert || id == CSSValueWebkitFocusRingColor) {
2014             validPrimitive = true;
2015             break;
2016         }
2017         FALLTHROUGH;
2018     case CSSPropertyBackgroundColor: // <color> | inherit
2019     case CSSPropertyBorderTopColor: // <color> | inherit
2020     case CSSPropertyBorderRightColor:
2021     case CSSPropertyBorderBottomColor:
2022     case CSSPropertyBorderLeftColor:
2023     case CSSPropertyWebkitBorderStartColor:
2024     case CSSPropertyWebkitBorderEndColor:
2025     case CSSPropertyWebkitBorderBeforeColor:
2026     case CSSPropertyWebkitBorderAfterColor:
2027     case CSSPropertyColor: // <color> | inherit
2028     case CSSPropertyTextLineThroughColor: // CSS3 text decoration colors
2029     case CSSPropertyTextUnderlineColor:
2030     case CSSPropertyTextOverlineColor:
2031     case CSSPropertyColumnRuleColor:
2032     case CSSPropertyWebkitTextDecorationColor:
2033     case CSSPropertyWebkitTextEmphasisColor:
2034     case CSSPropertyWebkitTextFillColor:
2035     case CSSPropertyWebkitTextStrokeColor:
2036         if (id == CSSValueWebkitText)
2037             validPrimitive = true; // Always allow this, even when strict parsing is on,
2038                                     // since we use this in our UA sheets.
2039         else if (id == CSSValueCurrentcolor)
2040             validPrimitive = true;
2041         else if (isValidSystemColorValue(id) || id == CSSValueMenu
2042             || (id >= CSSValueWebkitFocusRingColor && id < CSSValueWebkitText && inQuirksMode())) {
2043             validPrimitive = true;
2044         } else {
2045             parsedValue = parseColor();
2046             if (parsedValue)
2047                 m_valueList->next();
2048         }
2049         break;
2050
2051     case CSSPropertyCursor: {
2052         // Grammar defined by CSS3 UI and modified by CSS4 images:
2053         // [ [<image> [<x> <y>]?,]*
2054         // [ auto | crosshair | default | pointer | progress | move | e-resize | ne-resize |
2055         // nw-resize | n-resize | se-resize | sw-resize | s-resize | w-resize | ew-resize |
2056         // ns-resize | nesw-resize | nwse-resize | col-resize | row-resize | text | wait | help |
2057         // vertical-text | cell | context-menu | alias | copy | no-drop | not-allowed |
2058         // zoom-in | zoom-out | all-scroll | -webkit-grab | -webkit-grabbing | -webkit-zoom-in |
2059         // -webkit-zoom-out ] ] | inherit
2060         RefPtr<CSSValueList> list;
2061         CSSParserValue* value = &valueWithCalculation.value();
2062         while (value) {
2063             RefPtr<CSSValue> image;
2064             if (value->unit == CSSPrimitiveValue::CSS_URI) {
2065                 String uri = value->string;
2066                 if (!uri.isNull())
2067                     image = CSSImageValue::create(completeURL(uri));
2068 #if ENABLE(CSS_IMAGE_SET) && ENABLE(MOUSE_CURSOR_SCALE)
2069             } else if (value->unit == CSSParserValue::Function && equalIgnoringCase(value->function->name, "-webkit-image-set(")) {
2070                 image = parseImageSet();
2071                 if (!image)
2072                     break;
2073 #endif
2074             } else
2075                 break;
2076
2077             Vector<int> coords;
2078             value = m_valueList->next();
2079             while (value && value->unit == CSSPrimitiveValue::CSS_NUMBER) {
2080                 coords.append(int(value->fValue));
2081                 value = m_valueList->next();
2082             }
2083             bool hasHotSpot = false;
2084             IntPoint hotSpot(-1, -1);
2085             int nrcoords = coords.size();
2086             if (nrcoords > 0 && nrcoords != 2)
2087                 return false;
2088             if (nrcoords == 2) {
2089                 hasHotSpot = true;
2090                 hotSpot = IntPoint(coords[0], coords[1]);
2091             }
2092
2093             if (!list)
2094                 list = CSSValueList::createCommaSeparated();
2095
2096             if (image)
2097                 list->append(CSSCursorImageValue::create(image.releaseNonNull(), hasHotSpot, hotSpot));
2098
2099             if ((inStrictMode() && !value) || (value && !(value->unit == CSSParserValue::Operator && value->iValue == ',')))
2100                 return false;
2101             value = m_valueList->next(); // comma
2102         }
2103         if (list) {
2104             if (!value) {
2105                 // no value after url list (MSIE 5 compatibility)
2106                 if (list->length() != 1)
2107                     return false;
2108             } else if (inQuirksMode() && value->id == CSSValueHand) // MSIE 5 compatibility :/
2109                 list->append(cssValuePool().createIdentifierValue(CSSValuePointer));
2110             else if ((value->id >= CSSValueAuto && value->id <= CSSValueWebkitZoomOut) || value->id == CSSValueCopy || value->id == CSSValueNone)
2111                 list->append(cssValuePool().createIdentifierValue(value->id));
2112             m_valueList->next();
2113             parsedValue = list.release();
2114             break;
2115         } else if (value) {
2116             id = value->id;
2117             if (inQuirksMode() && value->id == CSSValueHand) {
2118                 // MSIE 5 compatibility :/
2119                 id = CSSValuePointer;
2120                 validPrimitive = true;
2121             } else if ((value->id >= CSSValueAuto && value->id <= CSSValueWebkitZoomOut) || value->id == CSSValueCopy || value->id == CSSValueNone)
2122                 validPrimitive = true;
2123         } else {
2124             ASSERT_NOT_REACHED();
2125             return false;
2126         }
2127         break;
2128     }
2129
2130 #if ENABLE(CURSOR_VISIBILITY)
2131     case CSSPropertyWebkitCursorVisibility:
2132         if (id == CSSValueAuto || id == CSSValueAutoHide)
2133             validPrimitive = true;
2134         break;
2135 #endif
2136
2137     case CSSPropertyBackgroundAttachment:
2138     case CSSPropertyBackgroundBlendMode:
2139     case CSSPropertyBackgroundClip:
2140     case CSSPropertyWebkitBackgroundClip:
2141     case CSSPropertyWebkitBackgroundComposite:
2142     case CSSPropertyBackgroundImage:
2143     case CSSPropertyBackgroundOrigin:
2144     case CSSPropertyWebkitBackgroundOrigin:
2145     case CSSPropertyBackgroundPosition:
2146     case CSSPropertyBackgroundPositionX:
2147     case CSSPropertyBackgroundPositionY:
2148     case CSSPropertyBackgroundSize:
2149     case CSSPropertyWebkitBackgroundSize:
2150     case CSSPropertyBackgroundRepeat:
2151     case CSSPropertyBackgroundRepeatX:
2152     case CSSPropertyBackgroundRepeatY:
2153     case CSSPropertyWebkitMaskClip:
2154     case CSSPropertyWebkitMaskComposite:
2155     case CSSPropertyWebkitMaskImage:
2156     case CSSPropertyWebkitMaskOrigin:
2157     case CSSPropertyWebkitMaskPosition:
2158     case CSSPropertyWebkitMaskPositionX:
2159     case CSSPropertyWebkitMaskPositionY:
2160     case CSSPropertyWebkitMaskSize:
2161     case CSSPropertyWebkitMaskSourceType:
2162     case CSSPropertyWebkitMaskRepeat:
2163     case CSSPropertyWebkitMaskRepeatX:
2164     case CSSPropertyWebkitMaskRepeatY:
2165     {
2166         RefPtr<CSSValue> val1;
2167         RefPtr<CSSValue> val2;
2168         CSSPropertyID propId1, propId2;
2169         bool result = false;
2170         if (parseFillProperty(propId, propId1, propId2, val1, val2)) {
2171             std::unique_ptr<ShorthandScope> shorthandScope;
2172             if (propId == CSSPropertyBackgroundPosition ||
2173                 propId == CSSPropertyBackgroundRepeat ||
2174                 propId == CSSPropertyWebkitMaskPosition ||
2175                 propId == CSSPropertyWebkitMaskRepeat) {
2176                 shorthandScope = std::make_unique<ShorthandScope>(this, propId);
2177             }
2178             addProperty(propId1, val1.release(), important);
2179             if (val2)
2180                 addProperty(propId2, val2.release(), important);
2181             result = true;
2182         }
2183         m_implicitShorthand = false;
2184         return result;
2185     }
2186     case CSSPropertyListStyleImage:     // <uri> | none | inherit
2187     case CSSPropertyBorderImageSource:
2188     case CSSPropertyWebkitMaskBoxImageSource:
2189         if (id == CSSValueNone) {
2190             parsedValue = cssValuePool().createIdentifierValue(CSSValueNone);
2191             m_valueList->next();
2192         } else if (valueWithCalculation.value().unit == CSSPrimitiveValue::CSS_URI) {
2193             parsedValue = CSSImageValue::create(completeURL(valueWithCalculation.value().string));
2194             m_valueList->next();
2195         } else if (isGeneratedImageValue(valueWithCalculation)) {
2196             if (parseGeneratedImage(*m_valueList, parsedValue))
2197                 m_valueList->next();
2198             else
2199                 return false;
2200         }
2201 #if ENABLE(CSS_IMAGE_SET)
2202         else if (valueWithCalculation.value().unit == CSSParserValue::Function && equalIgnoringCase(valueWithCalculation.value().function->name, "-webkit-image-set(")) {
2203             parsedValue = parseImageSet();
2204             if (!parsedValue)
2205                 return false;
2206             m_valueList->next();
2207         }
2208 #endif
2209         break;
2210
2211     case CSSPropertyWebkitTextStrokeWidth:
2212     case CSSPropertyOutlineWidth:        // <border-width> | inherit
2213     case CSSPropertyBorderTopWidth:     //// <border-width> | inherit
2214     case CSSPropertyBorderRightWidth:   //   Which is defined as
2215     case CSSPropertyBorderBottomWidth:  //   thin | medium | thick | <length>
2216     case CSSPropertyBorderLeftWidth:
2217     case CSSPropertyWebkitBorderStartWidth:
2218     case CSSPropertyWebkitBorderEndWidth:
2219     case CSSPropertyWebkitBorderBeforeWidth:
2220     case CSSPropertyWebkitBorderAfterWidth:
2221     case CSSPropertyColumnRuleWidth:
2222         if (id == CSSValueThin || id == CSSValueMedium || id == CSSValueThick)
2223             validPrimitive = true;
2224         else
2225             validPrimitive = validateUnit(valueWithCalculation, FLength | FNonNeg);
2226         break;
2227
2228     case CSSPropertyLetterSpacing:       // normal | <length> | inherit
2229         if (id == CSSValueNormal)
2230             validPrimitive = true;
2231         else
2232             validPrimitive = validateUnit(valueWithCalculation, FLength);
2233         break;
2234
2235     case CSSPropertyWordSpacing:         // normal | <length> | <percentage> | inherit
2236         if (id == CSSValueNormal)
2237             validPrimitive = true;
2238         else
2239             validPrimitive = validateUnit(valueWithCalculation, FLength | FPercent);
2240         break;
2241
2242     case CSSPropertyTextIndent:
2243         parsedValue = parseTextIndent();
2244         break;
2245
2246     case CSSPropertyPaddingTop:          //// <padding-width> | inherit
2247     case CSSPropertyPaddingRight:        //   Which is defined as
2248     case CSSPropertyPaddingBottom:       //   <length> | <percentage>
2249     case CSSPropertyPaddingLeft:         ////
2250     case CSSPropertyWebkitPaddingStart:
2251     case CSSPropertyWebkitPaddingEnd:
2252     case CSSPropertyWebkitPaddingBefore:
2253     case CSSPropertyWebkitPaddingAfter:
2254         validPrimitive = (!id && validateUnit(valueWithCalculation, FLength | FPercent | FNonNeg));
2255         break;
2256
2257     case CSSPropertyMaxWidth:
2258     case CSSPropertyWebkitMaxLogicalWidth:
2259         validPrimitive = (id == CSSValueNone || validateWidth(valueWithCalculation));
2260         break;
2261
2262     case CSSPropertyMinWidth:
2263     case CSSPropertyWebkitMinLogicalWidth:
2264         validPrimitive = validateWidth(valueWithCalculation);
2265         break;
2266
2267     case CSSPropertyWidth:
2268     case CSSPropertyWebkitLogicalWidth:
2269         validPrimitive = (id == CSSValueAuto || validateWidth(valueWithCalculation));
2270         break;
2271
2272     case CSSPropertyMaxHeight:
2273     case CSSPropertyWebkitMaxLogicalHeight:
2274         validPrimitive = (id == CSSValueNone || validateHeight(valueWithCalculation));
2275         break;
2276
2277     case CSSPropertyMinHeight:
2278     case CSSPropertyWebkitMinLogicalHeight:
2279         validPrimitive = validateHeight(valueWithCalculation);
2280         break;
2281
2282     case CSSPropertyHeight:
2283     case CSSPropertyWebkitLogicalHeight:
2284         validPrimitive = (id == CSSValueAuto || validateHeight(valueWithCalculation));
2285         break;
2286
2287     case CSSPropertyFontSize:
2288         return parseFontSize(important);
2289
2290     case CSSPropertyFontVariant:         // normal | small-caps | inherit
2291         return parseFontVariant(important);
2292
2293     case CSSPropertyVerticalAlign:
2294         // baseline | sub | super | top | text-top | middle | bottom | text-bottom |
2295         // <percentage> | <length> | inherit
2296
2297         if (id >= CSSValueBaseline && id <= CSSValueWebkitBaselineMiddle)
2298             validPrimitive = true;
2299         else
2300             validPrimitive = (!id && validateUnit(valueWithCalculation, FLength | FPercent));
2301         break;
2302
2303     case CSSPropertyBottom:               // <length> | <percentage> | auto | inherit
2304     case CSSPropertyLeft:                 // <length> | <percentage> | auto | inherit
2305     case CSSPropertyRight:                // <length> | <percentage> | auto | inherit
2306     case CSSPropertyTop:                  // <length> | <percentage> | auto | inherit
2307     case CSSPropertyMarginTop:           //// <margin-width> | inherit
2308     case CSSPropertyMarginRight:         //   Which is defined as
2309     case CSSPropertyMarginBottom:        //   <length> | <percentage> | auto | inherit
2310     case CSSPropertyMarginLeft:          ////
2311     case CSSPropertyWebkitMarginStart:
2312     case CSSPropertyWebkitMarginEnd:
2313     case CSSPropertyWebkitMarginBefore:
2314     case CSSPropertyWebkitMarginAfter:
2315         if (id == CSSValueAuto)
2316             validPrimitive = true;
2317         else
2318             validPrimitive = (!id && validateUnit(valueWithCalculation, FLength | FPercent));
2319         break;
2320
2321     case CSSPropertyZIndex:              // auto | <integer> | inherit
2322         if (id == CSSValueAuto)
2323             validPrimitive = true;
2324         else
2325             validPrimitive = (!id && validateUnit(valueWithCalculation, FInteger, CSSQuirksMode));
2326         break;
2327
2328     case CSSPropertyOrphans: // <integer> | inherit | auto (We've added support for auto for backwards compatibility)
2329     case CSSPropertyWidows: // <integer> | inherit | auto (Ditto)
2330         if (id == CSSValueAuto)
2331             validPrimitive = true;
2332         else
2333             validPrimitive = (!id && validateUnit(valueWithCalculation, FPositiveInteger, CSSQuirksMode));
2334         break;
2335
2336     case CSSPropertyLineHeight:
2337         return parseLineHeight(important);
2338     case CSSPropertyCounterIncrement:    // [ <identifier> <integer>? ]+ | none | inherit
2339         if (id != CSSValueNone)
2340             return parseCounter(propId, 1, important);
2341         validPrimitive = true;
2342         break;
2343     case CSSPropertyCounterReset:        // [ <identifier> <integer>? ]+ | none | inherit
2344         if (id != CSSValueNone)
2345             return parseCounter(propId, 0, important);
2346         validPrimitive = true;
2347         break;
2348     case CSSPropertyFontFamily:
2349         // [[ <family-name> | <generic-family> ],]* [<family-name> | <generic-family>] | inherit
2350     {
2351         parsedValue = parseFontFamily();
2352         break;
2353     }
2354
2355     case CSSPropertyWebkitTextDecoration:
2356         // [ <text-decoration-line> || <text-decoration-style> || <text-decoration-color> ] | inherit
2357         return parseShorthand(CSSPropertyWebkitTextDecoration, webkitTextDecorationShorthand(), important);
2358
2359     case CSSPropertyTextDecoration:
2360     case CSSPropertyWebkitTextDecorationsInEffect:
2361     case CSSPropertyWebkitTextDecorationLine:
2362         // none | [ underline || overline || line-through || blink ] | inherit
2363         return parseTextDecoration(propId, important);
2364
2365     case CSSPropertyWebkitTextDecorationStyle:
2366         // solid | double | dotted | dashed | wavy
2367         if (id == CSSValueSolid || id == CSSValueDouble || id == CSSValueDotted || id == CSSValueDashed || id == CSSValueWavy)
2368             validPrimitive = true;
2369         break;
2370
2371     case CSSPropertyWebkitTextDecorationSkip:
2372         // none | [ objects || spaces || ink || edges || box-decoration ]
2373         return parseTextDecorationSkip(important);
2374
2375     case CSSPropertyWebkitTextUnderlinePosition:
2376         // auto | alphabetic | under
2377         return parseTextUnderlinePosition(important);
2378
2379     case CSSPropertyZoom:          // normal | reset | document | <number> | <percentage> | inherit
2380         if (id == CSSValueNormal || id == CSSValueReset || id == CSSValueDocument)
2381             validPrimitive = true;
2382         else
2383             validPrimitive = (!id && validateUnit(valueWithCalculation, FNumber | FPercent | FNonNeg, CSSStrictMode));
2384         break;
2385
2386     case CSSPropertySrc: // Only used within @font-face and @-webkit-filter, so cannot use inherit | initial or be !important. This is a list of urls or local references.
2387         return parseFontFaceSrc();
2388
2389     case CSSPropertyUnicodeRange:
2390         return parseFontFaceUnicodeRange();
2391
2392     /* CSS3 properties */
2393
2394     case CSSPropertyBorderImage: {
2395         RefPtr<CSSValue> result;
2396         return parseBorderImage(propId, result, important);
2397     }
2398     case CSSPropertyWebkitBorderImage:
2399     case CSSPropertyWebkitMaskBoxImage: {
2400         RefPtr<CSSValue> result;
2401         if (parseBorderImage(propId, result)) {
2402             addProperty(propId, result, important);
2403             return true;
2404         }
2405         break;
2406     }
2407     case CSSPropertyBorderImageOutset:
2408     case CSSPropertyWebkitMaskBoxImageOutset: {
2409         RefPtr<CSSPrimitiveValue> result;
2410         if (parseBorderImageOutset(result)) {
2411             addProperty(propId, result, important);
2412             return true;
2413         }
2414         break;
2415     }
2416     case CSSPropertyBorderImageRepeat:
2417     case CSSPropertyWebkitMaskBoxImageRepeat: {
2418         RefPtr<CSSValue> result;
2419         if (parseBorderImageRepeat(result)) {
2420             addProperty(propId, result, important);
2421             return true;
2422         }
2423         break;
2424     }
2425     case CSSPropertyBorderImageSlice:
2426     case CSSPropertyWebkitMaskBoxImageSlice: {
2427         RefPtr<CSSBorderImageSliceValue> result;
2428         if (parseBorderImageSlice(propId, result)) {
2429             addProperty(propId, result, important);
2430             return true;
2431         }
2432         break;
2433     }
2434     case CSSPropertyBorderImageWidth:
2435     case CSSPropertyWebkitMaskBoxImageWidth: {
2436         RefPtr<CSSPrimitiveValue> result;
2437         if (parseBorderImageWidth(result)) {
2438             addProperty(propId, result, important);
2439             return true;
2440         }
2441         break;
2442     }
2443     case CSSPropertyBorderTopRightRadius:
2444     case CSSPropertyBorderTopLeftRadius:
2445     case CSSPropertyBorderBottomLeftRadius:
2446     case CSSPropertyBorderBottomRightRadius: {
2447         if (num != 1 && num != 2)
2448             return false;
2449         validPrimitive = validateUnit(valueWithCalculation, FLength | FPercent | FNonNeg);
2450         if (!validPrimitive)
2451             return false;
2452         RefPtr<CSSPrimitiveValue> parsedValue1 = createPrimitiveNumericValue(valueWithCalculation);
2453         RefPtr<CSSPrimitiveValue> parsedValue2;
2454         if (num == 2) {
2455             ValueWithCalculation nextValueWithCalculation(*m_valueList->next());
2456             validPrimitive = validateUnit(nextValueWithCalculation, FLength | FPercent | FNonNeg);
2457             if (!validPrimitive)
2458                 return false;
2459             parsedValue2 = createPrimitiveNumericValue(nextValueWithCalculation);
2460         } else
2461             parsedValue2 = parsedValue1;
2462
2463         addProperty(propId, createPrimitiveValuePair(parsedValue1.release(), parsedValue2.release()), important);
2464         return true;
2465     }
2466     case CSSPropertyTabSize:
2467         validPrimitive = validateUnit(valueWithCalculation, FInteger | FNonNeg);
2468         break;
2469     case CSSPropertyWebkitAspectRatio:
2470         return parseAspectRatio(important);
2471     case CSSPropertyBorderRadius:
2472     case CSSPropertyWebkitBorderRadius:
2473         return parseBorderRadius(propId, important);
2474     case CSSPropertyOutlineOffset:
2475         validPrimitive = validateUnit(valueWithCalculation, FLength);
2476         break;
2477     case CSSPropertyTextShadow: // CSS2 property, dropped in CSS2.1, back in CSS3, so treat as CSS3
2478     case CSSPropertyBoxShadow:
2479     case CSSPropertyWebkitBoxShadow:
2480         if (id == CSSValueNone)
2481             validPrimitive = true;
2482         else {
2483             RefPtr<CSSValueList> shadowValueList = parseShadow(*m_valueList, propId);
2484             if (shadowValueList) {
2485                 addProperty(propId, shadowValueList.release(), important);
2486                 m_valueList->next();
2487                 return true;
2488             }
2489             return false;
2490         }
2491         break;
2492     case CSSPropertyWebkitInitialLetter: {
2493         if (id == CSSValueNormal)
2494             validPrimitive = true;
2495         else {
2496             if (num != 1 && num != 2)
2497                 return false;
2498             validPrimitive = validateUnit(valueWithCalculation, FPositiveInteger);
2499             if (!validPrimitive)
2500                 return false;
2501             RefPtr<CSSPrimitiveValue> height = createPrimitiveNumericValue(valueWithCalculation);
2502             RefPtr<CSSPrimitiveValue> position;
2503             if (num == 2) {
2504                 ValueWithCalculation nextValueWithCalculation(*m_valueList->next());
2505                 validPrimitive = validateUnit(nextValueWithCalculation, FPositiveInteger);
2506                 if (!validPrimitive)
2507                     return false;
2508                 position = createPrimitiveNumericValue(nextValueWithCalculation);
2509             } else
2510                 position = height;
2511             addProperty(propId, createPrimitiveValuePair(position.release(), height.release()), important);
2512             return true;
2513         }
2514         break;
2515     }
2516     case CSSPropertyWebkitBoxReflect:
2517         if (id == CSSValueNone)
2518             validPrimitive = true;
2519         else
2520             return parseReflect(propId, important);
2521         break;
2522     case CSSPropertyOpacity:
2523         validPrimitive = validateUnit(valueWithCalculation, FNumber);
2524         break;
2525     case CSSPropertyWebkitBoxFlex:
2526         validPrimitive = validateUnit(valueWithCalculation, FNumber);
2527         break;
2528     case CSSPropertyWebkitBoxFlexGroup:
2529         validPrimitive = validateUnit(valueWithCalculation, FInteger | FNonNeg, CSSStrictMode);
2530         break;
2531     case CSSPropertyWebkitBoxOrdinalGroup:
2532         validPrimitive = validateUnit(valueWithCalculation, FInteger | FNonNeg, CSSStrictMode) && valueWithCalculation.value().fValue;
2533         break;
2534     case CSSPropertyWebkitFilter:
2535 #if ENABLE(FILTERS_LEVEL_2)
2536     case CSSPropertyWebkitBackdropFilter:
2537 #endif
2538         if (id == CSSValueNone)
2539             validPrimitive = true;
2540         else {
2541             RefPtr<CSSValue> currValue;
2542             if (!parseFilter(*m_valueList, currValue))
2543                 return false;
2544             addProperty(propId, currValue, important);
2545             return true;
2546         }
2547         break;
2548 #if ENABLE(CSS_COMPOSITING)
2549     case CSSPropertyMixBlendMode:
2550         if (cssCompositingEnabled())
2551             validPrimitive = true;
2552         break;
2553     case CSSPropertyIsolation:
2554         if (cssCompositingEnabled())
2555             validPrimitive = true;
2556         break;
2557 #endif
2558     case CSSPropertyFlex: {
2559         ShorthandScope scope(this, propId);
2560         if (id == CSSValueNone) {
2561             addProperty(CSSPropertyFlexGrow, cssValuePool().createValue(0, CSSPrimitiveValue::CSS_NUMBER), important);
2562             addProperty(CSSPropertyFlexShrink, cssValuePool().createValue(0, CSSPrimitiveValue::CSS_NUMBER), important);
2563             addProperty(CSSPropertyFlexBasis, cssValuePool().createIdentifierValue(CSSValueAuto), important);
2564             return true;
2565         }
2566         return parseFlex(*m_valueList, important);
2567     }
2568     case CSSPropertyFlexBasis:
2569         // FIXME: Support intrinsic dimensions too.
2570         if (id == CSSValueAuto)
2571             validPrimitive = true;
2572         else
2573             validPrimitive = (!id && validateUnit(valueWithCalculation, FLength | FPercent | FNonNeg));
2574         break;
2575     case CSSPropertyFlexGrow:
2576     case CSSPropertyFlexShrink:
2577         validPrimitive = validateUnit(valueWithCalculation, FNumber | FNonNeg);
2578         break;
2579     case CSSPropertyOrder:
2580         if (validateUnit(valueWithCalculation, FInteger, CSSStrictMode)) {
2581             // We restrict the smallest value to int min + 2 because we use int min and int min + 1 as special values in a hash set.
2582             double result = std::max<double>(std::numeric_limits<int>::min() + 2, parsedDouble(valueWithCalculation));
2583             parsedValue = cssValuePool().createValue(result, CSSPrimitiveValue::CSS_NUMBER);
2584             m_valueList->next();
2585         }
2586         break;
2587     case CSSPropertyWebkitMarquee:
2588         return parseShorthand(propId, webkitMarqueeShorthand(), important);
2589     case CSSPropertyWebkitMarqueeIncrement:
2590         if (id == CSSValueSmall || id == CSSValueLarge || id == CSSValueMedium)
2591             validPrimitive = true;
2592         else
2593             validPrimitive = validateUnit(valueWithCalculation, FLength | FPercent);
2594         break;
2595     case CSSPropertyWebkitMarqueeRepetition:
2596         if (id == CSSValueInfinite)
2597             validPrimitive = true;
2598         else
2599             validPrimitive = validateUnit(valueWithCalculation, FInteger | FNonNeg);
2600         break;
2601     case CSSPropertyWebkitMarqueeSpeed:
2602         if (id == CSSValueNormal || id == CSSValueSlow || id == CSSValueFast)
2603             validPrimitive = true;
2604         else
2605             validPrimitive = validateUnit(valueWithCalculation, FTime | FInteger | FNonNeg);
2606         break;
2607 #if ENABLE(CSS_REGIONS)
2608     case CSSPropertyWebkitFlowInto:
2609         if (!cssRegionsEnabled())
2610             return false;
2611         return parseFlowThread(propId, important);
2612     case CSSPropertyWebkitFlowFrom:
2613         if (!cssRegionsEnabled())
2614             return false;
2615         return parseRegionThread(propId, important);
2616 #endif
2617     case CSSPropertyTransform:
2618         if (id == CSSValueNone)
2619             validPrimitive = true;
2620         else {
2621             RefPtr<CSSValue> transformValue = parseTransform();
2622             if (transformValue) {
2623                 addProperty(propId, transformValue.release(), important);
2624                 return true;
2625             }
2626             return false;
2627         }
2628         break;
2629     case CSSPropertyTransformOrigin:
2630     case CSSPropertyTransformOriginX:
2631     case CSSPropertyTransformOriginY:
2632     case CSSPropertyTransformOriginZ: {
2633         RefPtr<CSSValue> val1;
2634         RefPtr<CSSValue> val2;
2635         RefPtr<CSSValue> val3;
2636         CSSPropertyID propId1, propId2, propId3;
2637         if (parseTransformOrigin(propId, propId1, propId2, propId3, val1, val2, val3)) {
2638             addProperty(propId1, val1.release(), important);
2639             if (val2)
2640                 addProperty(propId2, val2.release(), important);
2641             if (val3)
2642                 addProperty(propId3, val3.release(), important);
2643             return true;
2644         }
2645         return false;
2646     }
2647     case CSSPropertyPerspective:
2648         if (id == CSSValueNone)
2649             validPrimitive = true;
2650         else {
2651             // Accepting valueless numbers is a quirk of the -webkit prefixed version of the property.
2652             if (validateUnit(valueWithCalculation, FNumber | FLength | FNonNeg)) {
2653                 RefPtr<CSSValue> val = createPrimitiveNumericValue(valueWithCalculation);
2654                 if (val) {
2655                     addProperty(propId, val.release(), important);
2656                     return true;
2657                 }
2658                 return false;
2659             }
2660         }
2661         break;
2662     case CSSPropertyPerspectiveOrigin:
2663     case CSSPropertyPerspectiveOriginX:
2664     case CSSPropertyPerspectiveOriginY: {
2665         RefPtr<CSSValue> val1;
2666         RefPtr<CSSValue> val2;
2667         CSSPropertyID propId1, propId2;
2668         if (parsePerspectiveOrigin(propId, propId1, propId2, val1, val2)) {
2669             addProperty(propId1, val1.release(), important);
2670             if (val2)
2671                 addProperty(propId2, val2.release(), important);
2672             return true;
2673         }
2674         return false;
2675     }
2676     case CSSPropertyAnimationDelay:
2677     case CSSPropertyAnimationDirection:
2678     case CSSPropertyAnimationDuration:
2679     case CSSPropertyAnimationFillMode:
2680     case CSSPropertyAnimationName:
2681     case CSSPropertyAnimationPlayState:
2682     case CSSPropertyAnimationIterationCount:
2683     case CSSPropertyAnimationTimingFunction:
2684     case CSSPropertyWebkitAnimationDelay:
2685     case CSSPropertyWebkitAnimationDirection:
2686     case CSSPropertyWebkitAnimationDuration:
2687     case CSSPropertyWebkitAnimationFillMode:
2688     case CSSPropertyWebkitAnimationName:
2689     case CSSPropertyWebkitAnimationPlayState:
2690     case CSSPropertyWebkitAnimationIterationCount:
2691     case CSSPropertyWebkitAnimationTimingFunction:
2692 #if ENABLE(CSS_ANIMATIONS_LEVEL_2)
2693     case CSSPropertyWebkitAnimationTrigger:
2694 #endif
2695     case CSSPropertyTransitionDelay:
2696     case CSSPropertyTransitionDuration:
2697     case CSSPropertyTransitionTimingFunction:
2698     case CSSPropertyTransitionProperty:
2699     case CSSPropertyWebkitTransitionDelay:
2700     case CSSPropertyWebkitTransitionDuration:
2701     case CSSPropertyWebkitTransitionTimingFunction:
2702     case CSSPropertyWebkitTransitionProperty: {
2703         RefPtr<CSSValue> val;
2704         AnimationParseContext context;
2705         if (parseAnimationProperty(propId, val, context)) {
2706             addPropertyWithPrefixingVariant(propId, val.release(), important);
2707             return true;
2708         }
2709         return false;
2710     }
2711     case CSSPropertyJustifyContent:
2712         parsedValue = parseContentDistributionOverflowPosition();
2713         break;
2714     case CSSPropertyJustifySelf:
2715         return parseItemPositionOverflowPosition(propId, important);
2716     case CSSPropertyJustifyItems:
2717         if (parseLegacyPosition(propId, important))
2718             return true;
2719         m_valueList->setCurrentIndex(0);
2720         return parseItemPositionOverflowPosition(propId, important);
2721 #if ENABLE(CSS_GRID_LAYOUT)
2722     case CSSPropertyWebkitGridAutoColumns:
2723     case CSSPropertyWebkitGridAutoRows:
2724         parsedValue = parseGridTrackSize(*m_valueList);
2725         break;
2726
2727     case CSSPropertyWebkitGridTemplateColumns:
2728     case CSSPropertyWebkitGridTemplateRows:
2729         parsedValue = parseGridTrackList();
2730         break;
2731
2732     case CSSPropertyWebkitGridColumnStart:
2733     case CSSPropertyWebkitGridColumnEnd:
2734     case CSSPropertyWebkitGridRowStart:
2735     case CSSPropertyWebkitGridRowEnd:
2736         parsedValue = parseGridPosition();
2737         break;
2738
2739     case CSSPropertyWebkitGridColumn:
2740     case CSSPropertyWebkitGridRow: {
2741         return parseGridItemPositionShorthand(propId, important);
2742     }
2743
2744     case CSSPropertyWebkitGridTemplate:
2745         return parseGridTemplateShorthand(important);
2746
2747     case CSSPropertyWebkitGrid:
2748         return parseGridShorthand(important);
2749
2750     case CSSPropertyWebkitGridArea:
2751         return parseGridAreaShorthand(important);
2752
2753     case CSSPropertyWebkitGridTemplateAreas:
2754         parsedValue = parseGridTemplateAreas();
2755         break;
2756     case CSSPropertyWebkitGridAutoFlow:
2757         parsedValue = parseGridAutoFlow(*m_valueList);
2758         break;
2759 #endif /* ENABLE(CSS_GRID_LAYOUT) */
2760     case CSSPropertyWebkitMarginCollapse: {
2761         if (num == 1) {
2762             ShorthandScope scope(this, CSSPropertyWebkitMarginCollapse);
2763             if (!parseValue(webkitMarginCollapseShorthand().properties()[0], important))
2764                 return false;
2765             CSSValue* value = m_parsedProperties.last().value();
2766             addProperty(webkitMarginCollapseShorthand().properties()[1], value, important);
2767             return true;
2768         }
2769         else if (num == 2) {
2770             ShorthandScope scope(this, CSSPropertyWebkitMarginCollapse);
2771             if (!parseValue(webkitMarginCollapseShorthand().properties()[0], important) || !parseValue(webkitMarginCollapseShorthand().properties()[1], important))
2772                 return false;
2773             return true;
2774         }
2775         return false;
2776     }
2777     case CSSPropertyTextLineThroughWidth:
2778     case CSSPropertyTextOverlineWidth:
2779     case CSSPropertyTextUnderlineWidth:
2780         if (id == CSSValueAuto || id == CSSValueNormal || id == CSSValueThin ||
2781             id == CSSValueMedium || id == CSSValueThick)
2782             validPrimitive = true;
2783         else
2784             validPrimitive = !id && validateUnit(valueWithCalculation, FNumber | FLength | FPercent);
2785         break;
2786     case CSSPropertyColumnCount:
2787         parsedValue = parseColumnCount();
2788         break;
2789     case CSSPropertyColumnGap: // normal | <length>
2790         if (id == CSSValueNormal)
2791             validPrimitive = true;
2792         else
2793             validPrimitive = validateUnit(valueWithCalculation, FLength | FNonNeg);
2794         break;
2795     case CSSPropertyWebkitColumnAxis:
2796         if (id == CSSValueHorizontal || id == CSSValueVertical || id == CSSValueAuto)
2797             validPrimitive = true;
2798         break;
2799     case CSSPropertyColumnProgression:
2800         if (id == CSSValueNormal || id == CSSValueReverse)
2801             validPrimitive = true;
2802         break;
2803     case CSSPropertyColumnSpan: // none | all | 1 (will be dropped in the unprefixed property)
2804         if (id == CSSValueAll || id == CSSValueNone)
2805             validPrimitive = true;
2806         else if (validateUnit(valueWithCalculation, FNumber | FNonNeg) && parsedDouble(valueWithCalculation) == 1) {
2807             addProperty(CSSPropertyColumnSpan, cssValuePool().createValue(1, CSSPrimitiveValue::CSS_NUMBER), important);
2808             return true;
2809         }
2810         break;
2811     case CSSPropertyColumnWidth: // auto | <length>
2812         parsedValue = parseColumnWidth();
2813         break;
2814     // End of CSS3 properties
2815
2816     // Apple specific properties.  These will never be standardized and are purely to
2817     // support custom WebKit-based Apple applications.
2818     case CSSPropertyWebkitLineClamp:
2819         // When specifying number of lines, don't allow 0 as a valid value
2820         // When specifying either type of unit, require non-negative integers
2821         validPrimitive = (!id && (valueWithCalculation.value().unit == CSSPrimitiveValue::CSS_PERCENTAGE || valueWithCalculation.value().fValue) && validateUnit(valueWithCalculation, FInteger | FPercent | FNonNeg, CSSQuirksMode));
2822         break;
2823 #if ENABLE(IOS_TEXT_AUTOSIZING)
2824     case CSSPropertyWebkitTextSizeAdjust:
2825         if (id == CSSValueAuto || id == CSSValueNone)
2826             validPrimitive = true;
2827         else {
2828             // FIXME: Handle multilength case where we allow relative units.
2829             validPrimitive = (!id && validateUnit(valueWithCalculation, FPercent | FNonNeg, CSSStrictMode));
2830         }
2831         break;
2832 #endif
2833
2834     case CSSPropertyWebkitFontSizeDelta:           // <length>
2835         validPrimitive = validateUnit(valueWithCalculation, FLength);
2836         break;
2837
2838     case CSSPropertyWebkitHyphenateCharacter:
2839         if (id == CSSValueAuto || valueWithCalculation.value().unit == CSSPrimitiveValue::CSS_STRING)
2840             validPrimitive = true;
2841         break;
2842
2843     case CSSPropertyWebkitHyphenateLimitBefore:
2844     case CSSPropertyWebkitHyphenateLimitAfter:
2845         if (id == CSSValueAuto || validateUnit(valueWithCalculation, FInteger | FNonNeg, CSSStrictMode))
2846             validPrimitive = true;
2847         break;
2848
2849     case CSSPropertyWebkitHyphenateLimitLines:
2850         if (id == CSSValueNoLimit || validateUnit(valueWithCalculation, FInteger | FNonNeg, CSSStrictMode))
2851             validPrimitive = true;
2852         break;
2853
2854     case CSSPropertyWebkitLineGrid:
2855         if (id == CSSValueNone)
2856             validPrimitive = true;
2857         else if (valueWithCalculation.value().unit == CSSPrimitiveValue::CSS_IDENT) {
2858             String lineGridValue = String(valueWithCalculation.value().string);
2859             if (!lineGridValue.isEmpty()) {
2860                 addProperty(propId, cssValuePool().createValue(lineGridValue, CSSPrimitiveValue::CSS_STRING), important);
2861                 return true;
2862             }
2863         }
2864         break;
2865     case CSSPropertyWebkitLocale:
2866         if (id == CSSValueAuto || valueWithCalculation.value().unit == CSSPrimitiveValue::CSS_STRING)
2867             validPrimitive = true;
2868         break;
2869
2870 #if ENABLE(DASHBOARD_SUPPORT)
2871     case CSSPropertyWebkitDashboardRegion: // <dashboard-region> | <dashboard-region>
2872         if (valueWithCalculation.value().unit == CSSParserValue::Function || id == CSSValueNone)
2873             return parseDashboardRegions(propId, important);
2874         break;
2875 #endif
2876
2877 #if PLATFORM(IOS)
2878     case CSSPropertyWebkitTouchCallout:
2879         if (id == CSSValueDefault || id == CSSValueNone)
2880             validPrimitive = true;
2881         break;
2882 #endif
2883 #if ENABLE(TOUCH_EVENTS)
2884     case CSSPropertyWebkitTapHighlightColor:
2885         if (isValidSystemColorValue(id) || id == CSSValueMenu
2886             || (id >= CSSValueWebkitFocusRingColor && id < CSSValueWebkitText && inQuirksMode())) {
2887             validPrimitive = true;
2888         } else {
2889             parsedValue = parseColor();
2890             if (parsedValue)
2891                 m_valueList->next();
2892         }
2893         break;
2894 #endif
2895     // End Apple-specific properties
2896
2897         /* shorthand properties */
2898     case CSSPropertyBackground: {
2899         // Position must come before color in this array because a plain old "0" is a legal color
2900         // in quirks mode but it's usually the X coordinate of a position.
2901         const CSSPropertyID properties[] = { CSSPropertyBackgroundImage, CSSPropertyBackgroundRepeat,
2902                                    CSSPropertyBackgroundAttachment, CSSPropertyBackgroundPosition, CSSPropertyBackgroundOrigin,
2903                                    CSSPropertyBackgroundClip, CSSPropertyBackgroundColor, CSSPropertyBackgroundSize };
2904         return parseFillShorthand(propId, properties, WTF_ARRAY_LENGTH(properties), important);
2905     }
2906     case CSSPropertyWebkitMask: {
2907         const CSSPropertyID properties[] = { CSSPropertyWebkitMaskImage, CSSPropertyWebkitMaskSourceType, CSSPropertyWebkitMaskRepeat,
2908             CSSPropertyWebkitMaskPosition, CSSPropertyWebkitMaskOrigin, CSSPropertyWebkitMaskClip, CSSPropertyWebkitMaskSize };
2909         return parseFillShorthand(propId, properties, WTF_ARRAY_LENGTH(properties), important);
2910     }
2911     case CSSPropertyBorder:
2912         // [ 'border-width' || 'border-style' || <color> ] | inherit
2913     {
2914         if (parseShorthand(propId, borderAbridgedShorthand(), important)) {
2915             // The CSS3 Borders and Backgrounds specification says that border also resets border-image. It's as
2916             // though a value of none was specified for the image.
2917             addExpandedPropertyForValue(CSSPropertyBorderImage, cssValuePool().createImplicitInitialValue(), important);
2918             return true;
2919         }
2920         return false;
2921     }
2922     case CSSPropertyBorderTop:
2923         // [ 'border-top-width' || 'border-style' || <color> ] | inherit
2924         return parseShorthand(propId, borderTopShorthand(), important);
2925     case CSSPropertyBorderRight:
2926         // [ 'border-right-width' || 'border-style' || <color> ] | inherit
2927         return parseShorthand(propId, borderRightShorthand(), important);
2928     case CSSPropertyBorderBottom:
2929         // [ 'border-bottom-width' || 'border-style' || <color> ] | inherit
2930         return parseShorthand(propId, borderBottomShorthand(), important);
2931     case CSSPropertyBorderLeft:
2932         // [ 'border-left-width' || 'border-style' || <color> ] | inherit
2933         return parseShorthand(propId, borderLeftShorthand(), important);
2934     case CSSPropertyWebkitBorderStart:
2935         return parseShorthand(propId, webkitBorderStartShorthand(), important);
2936     case CSSPropertyWebkitBorderEnd:
2937         return parseShorthand(propId, webkitBorderEndShorthand(), important);
2938     case CSSPropertyWebkitBorderBefore:
2939         return parseShorthand(propId, webkitBorderBeforeShorthand(), important);
2940     case CSSPropertyWebkitBorderAfter:
2941         return parseShorthand(propId, webkitBorderAfterShorthand(), important);
2942     case CSSPropertyOutline:
2943         // [ 'outline-color' || 'outline-style' || 'outline-width' ] | inherit
2944         return parseShorthand(propId, outlineShorthand(), important);
2945     case CSSPropertyBorderColor:
2946         // <color>{1,4} | inherit
2947         return parse4Values(propId, borderColorShorthand().properties(), important);
2948     case CSSPropertyBorderWidth:
2949         // <border-width>{1,4} | inherit
2950         return parse4Values(propId, borderWidthShorthand().properties(), important);
2951     case CSSPropertyBorderStyle:
2952         // <border-style>{1,4} | inherit
2953         return parse4Values(propId, borderStyleShorthand().properties(), important);
2954     case CSSPropertyMargin:
2955         // <margin-width>{1,4} | inherit
2956         return parse4Values(propId, marginShorthand().properties(), important);
2957     case CSSPropertyPadding:
2958         // <padding-width>{1,4} | inherit
2959         return parse4Values(propId, paddingShorthand().properties(), important);
2960     case CSSPropertyFlexFlow:
2961         return parseShorthand(propId, flexFlowShorthand(), important);
2962     case CSSPropertyFont:
2963         // [ [ 'font-style' || 'font-variant' || 'font-weight' ]? 'font-size' [ / 'line-height' ]?
2964         // 'font-family' ] | caption | icon | menu | message-box | small-caption | status-bar | inherit
2965         if (num == 1 && id >= CSSValueCaption && id <= CSSValueStatusBar) {
2966             parseSystemFont(important);
2967             return true;
2968         }
2969         return parseFont(important);
2970     case CSSPropertyListStyle:
2971         return parseShorthand(propId, listStyleShorthand(), important);
2972     case CSSPropertyColumns:
2973         return parseColumnsShorthand(important);
2974     case CSSPropertyColumnRule:
2975         return parseShorthand(propId, columnRuleShorthand(), important);
2976     case CSSPropertyWebkitTextStroke:
2977         return parseShorthand(propId, webkitTextStrokeShorthand(), important);
2978     case CSSPropertyAnimation:
2979     case CSSPropertyWebkitAnimation:
2980         return parseAnimationShorthand(propId, important);
2981     case CSSPropertyTransition:
2982     case CSSPropertyWebkitTransition:
2983         return parseTransitionShorthand(propId, important);
2984     case CSSPropertyInvalid:
2985         return false;
2986     case CSSPropertyPage:
2987         return parsePage(propId, important);
2988     case CSSPropertyFontStretch:
2989     case CSSPropertyTextLineThrough:
2990     case CSSPropertyTextOverline:
2991     case CSSPropertyTextUnderline:
2992         return false;
2993     // CSS Text Layout Module Level 3: Vertical writing support
2994     case CSSPropertyWebkitTextEmphasis:
2995         return parseShorthand(propId, webkitTextEmphasisShorthand(), important);
2996
2997     case CSSPropertyWebkitTextEmphasisStyle:
2998         return parseTextEmphasisStyle(important);
2999
3000     case CSSPropertyWebkitTextEmphasisPosition:
3001         return parseTextEmphasisPosition(important);
3002
3003     case CSSPropertyWebkitTextOrientation:
3004         // FIXME: For now just support sideways, sideways-right, upright and vertical-right.
3005         if (id == CSSValueSideways || id == CSSValueSidewaysRight || id == CSSValueVerticalRight || id == CSSValueUpright)
3006             validPrimitive = true;
3007         break;
3008
3009     case CSSPropertyWebkitLineBoxContain:
3010         if (id == CSSValueNone)
3011             validPrimitive = true;
3012         else
3013             return parseLineBoxContain(important);
3014         break;
3015     case CSSPropertyWebkitFontFeatureSettings:
3016         if (id == CSSValueNormal)
3017             validPrimitive = true;
3018         else
3019             return parseFontFeatureSettings(important);
3020         break;
3021
3022     case CSSPropertyWebkitFontVariantLigatures:
3023         if (id == CSSValueNormal)
3024             validPrimitive = true;
3025         else
3026             return parseFontVariantLigatures(important);
3027         break;
3028     case CSSPropertyWebkitClipPath:
3029         parsedValue = parseClipPath();
3030         break;
3031 #if ENABLE(CSS_SHAPES)
3032     case CSSPropertyWebkitShapeOutside:
3033         parsedValue = parseShapeProperty(propId);
3034         break;
3035     case CSSPropertyWebkitShapeMargin:
3036         validPrimitive = (RuntimeEnabledFeatures::sharedFeatures().cssShapesEnabled() && !id && validateUnit(valueWithCalculation, FLength | FPercent | FNonNeg));
3037         break;
3038     case CSSPropertyWebkitShapeImageThreshold:
3039         validPrimitive = (RuntimeEnabledFeatures::sharedFeatures().cssShapesEnabled() && !id && validateUnit(valueWithCalculation, FNumber));
3040         break;
3041 #endif
3042 #if ENABLE(CSS_IMAGE_ORIENTATION)
3043     case CSSPropertyImageOrientation:
3044         validPrimitive = !id && validateUnit(valueWithCalculation, FAngle);
3045         break;
3046 #endif
3047 #if ENABLE(CSS_IMAGE_RESOLUTION)
3048     case CSSPropertyImageResolution:
3049         parsedValue = parseImageResolution();
3050         break;
3051 #endif
3052     case CSSPropertyAlignContent:
3053         parsedValue = parseContentDistributionOverflowPosition();
3054         break;
3055     case CSSPropertyAlignSelf:
3056         return parseItemPositionOverflowPosition(propId, important);
3057
3058     case CSSPropertyAlignItems:
3059         return parseItemPositionOverflowPosition(propId, important);
3060     case CSSPropertyBorderBottomStyle:
3061     case CSSPropertyBorderCollapse:
3062     case CSSPropertyBorderLeftStyle:
3063     case CSSPropertyBorderRightStyle:
3064     case CSSPropertyBorderTopStyle:
3065     case CSSPropertyBoxSizing:
3066     case CSSPropertyCaptionSide:
3067     case CSSPropertyClear:
3068     case CSSPropertyDirection:
3069     case CSSPropertyDisplay:
3070     case CSSPropertyEmptyCells:
3071     case CSSPropertyFloat:
3072     case CSSPropertyFontStyle:
3073     case CSSPropertyImageRendering:
3074     case CSSPropertyListStylePosition:
3075     case CSSPropertyListStyleType:
3076     case CSSPropertyObjectFit:
3077     case CSSPropertyOutlineStyle:
3078     case CSSPropertyOverflowWrap:
3079     case CSSPropertyOverflowX:
3080     case CSSPropertyOverflowY:
3081     case CSSPropertyPageBreakAfter:
3082     case CSSPropertyPageBreakBefore:
3083     case CSSPropertyPageBreakInside:
3084     case CSSPropertyPointerEvents:
3085     case CSSPropertyPosition:
3086     case CSSPropertyResize:
3087     case CSSPropertySpeak:
3088     case CSSPropertyTableLayout:
3089     case CSSPropertyTextLineThroughMode:
3090     case CSSPropertyTextLineThroughStyle:
3091     case CSSPropertyTextOverflow:
3092     case CSSPropertyTextOverlineMode:
3093     case CSSPropertyTextOverlineStyle:
3094     case CSSPropertyTextRendering:
3095     case CSSPropertyTextTransform:
3096     case CSSPropertyTextUnderlineMode:
3097     case CSSPropertyTextUnderlineStyle:
3098     case CSSPropertyVisibility:
3099     case CSSPropertyWebkitAppearance:
3100     case CSSPropertyWebkitBackfaceVisibility:
3101     case CSSPropertyWebkitBorderAfterStyle:
3102     case CSSPropertyWebkitBorderBeforeStyle:
3103     case CSSPropertyWebkitBorderEndStyle:
3104     case CSSPropertyWebkitBorderFit:
3105     case CSSPropertyWebkitBorderStartStyle:
3106     case CSSPropertyWebkitBoxAlign:
3107 #if ENABLE(CSS_BOX_DECORATION_BREAK)
3108     case CSSPropertyWebkitBoxDecorationBreak:
3109 #endif
3110     case CSSPropertyWebkitBoxDirection:
3111     case CSSPropertyWebkitBoxLines:
3112     case CSSPropertyWebkitBoxOrient:
3113     case CSSPropertyWebkitBoxPack:
3114     case CSSPropertyWebkitColorCorrection:
3115     case CSSPropertyWebkitColumnBreakAfter:
3116     case CSSPropertyWebkitColumnBreakBefore:
3117     case CSSPropertyWebkitColumnBreakInside:
3118     case CSSPropertyColumnFill:
3119     case CSSPropertyColumnRuleStyle:
3120     case CSSPropertyFlexDirection:
3121     case CSSPropertyFlexWrap:
3122     case CSSPropertyWebkitFontKerning:
3123     case CSSPropertyWebkitFontSmoothing:
3124     case CSSPropertyWebkitHyphens:
3125     case CSSPropertyWebkitLineAlign:
3126     case CSSPropertyWebkitLineBreak:
3127     case CSSPropertyWebkitLineSnap:
3128     case CSSPropertyWebkitMarginAfterCollapse:
3129     case CSSPropertyWebkitMarginBeforeCollapse:
3130     case CSSPropertyWebkitMarginBottomCollapse:
3131     case CSSPropertyWebkitMarginTopCollapse:
3132     case CSSPropertyWebkitMarqueeDirection:
3133     case CSSPropertyWebkitMarqueeStyle:
3134     case CSSPropertyWebkitNbspMode:
3135 #if ENABLE(ACCELERATED_OVERFLOW_SCROLLING)
3136     case CSSPropertyWebkitOverflowScrolling:
3137 #endif
3138     case CSSPropertyWebkitPrintColorAdjust:
3139 #if ENABLE(CSS_REGIONS)
3140     case CSSPropertyWebkitRegionBreakAfter:
3141     case CSSPropertyWebkitRegionBreakBefore:
3142     case CSSPropertyWebkitRegionBreakInside:
3143     case CSSPropertyWebkitRegionFragment:
3144 #endif
3145     case CSSPropertyWebkitRtlOrdering:
3146     case CSSPropertyWebkitRubyPosition:
3147 #if ENABLE(CSS3_TEXT)
3148     case CSSPropertyWebkitTextAlignLast:
3149 #endif // CSS3_TEXT
3150     case CSSPropertyWebkitTextCombine:
3151 #if ENABLE(CSS3_TEXT)
3152     case CSSPropertyWebkitTextJustify:
3153 #endif // CSS3_TEXT
3154     case CSSPropertyWebkitTextSecurity:
3155     case CSSPropertyTransformStyle:
3156     case CSSPropertyWebkitTransformStyle:
3157     case CSSPropertyWebkitUserDrag:
3158     case CSSPropertyWebkitUserModify:
3159     case CSSPropertyWebkitUserSelect:
3160     case CSSPropertyWebkitWritingMode:
3161     case CSSPropertyWhiteSpace:
3162     case CSSPropertyWordBreak:
3163     case CSSPropertyWordWrap:
3164 #if ENABLE(CSS_SCROLL_SNAP)
3165     case CSSPropertyWebkitScrollSnapType:
3166 #endif
3167 #if ENABLE(CSS_TRAILING_WORD)
3168     case CSSPropertyAppleTrailingWord:
3169 #endif
3170         // These properties should be handled before in isValidKeywordPropertyAndValue().
3171         ASSERT_NOT_REACHED();
3172         return false;
3173 #if ENABLE(CSS_DEVICE_ADAPTATION)
3174     // Properties bellow are validated inside parseViewportProperty, because we
3175     // check for parser state inViewportScope. We need to invalidate if someone
3176     // adds them outside a @viewport rule.
3177     case CSSPropertyMaxZoom:
3178     case CSSPropertyMinZoom:
3179     case CSSPropertyOrientation:
3180     case CSSPropertyUserZoom:
3181         validPrimitive = false;
3182         break;
3183 #endif
3184 #if ENABLE(CSS_SCROLL_SNAP)
3185     case CSSPropertyWebkitScrollSnapPointsX:
3186     case CSSPropertyWebkitScrollSnapPointsY:
3187         if (id == CSSValueElements) {
3188             validPrimitive = true;
3189             break;
3190         }
3191         return parseNonElementSnapPoints(propId, important);
3192     case CSSPropertyWebkitScrollSnapDestination: // <length>{2}
3193         return parseScrollSnapDestination(propId, important);
3194     case CSSPropertyWebkitScrollSnapCoordinate:
3195         return parseScrollSnapCoordinate(propId, important);
3196 #endif
3197
3198     default:
3199         return parseSVGValue(propId, important);
3200     }
3201
3202     if (validPrimitive) {
3203         parsedValue = parseValidPrimitive(id, valueWithCalculation);
3204         m_valueList->next();
3205     }
3206
3207     if (parsedValue) {
3208         if (!m_valueList->current() || inShorthand()) {
3209             addProperty(propId, parsedValue.release(), important);
3210             return true;
3211         }
3212     }
3213     return false;
3214 }
3215
3216 void CSSParser::addFillValue(RefPtr<CSSValue>& lval, Ref<CSSValue>&& rval)
3217 {
3218     if (!lval) {
3219         lval = WTF::move(rval);
3220         return;
3221     }
3222
3223     if (lval->isBaseValueList()) {
3224         downcast<CSSValueList>(*lval).append(WTF::move(rval));
3225         return;
3226     }
3227
3228     auto list = CSSValueList::createCommaSeparated();
3229     list.get().append(lval.releaseNonNull());
3230     list.get().append(WTF::move(rval));
3231     lval = WTF::move(list);
3232 }
3233
3234 static bool isContentDistributionKeyword(CSSValueID id)
3235 {
3236     return id == CSSValueSpaceBetween || id == CSSValueSpaceAround
3237         || id == CSSValueSpaceEvenly || id == CSSValueStretch;
3238 }
3239
3240 static bool isContentPositionKeyword(CSSValueID id)
3241 {
3242     return id == CSSValueStart || id == CSSValueEnd || id == CSSValueCenter
3243         || id == CSSValueFlexStart || id == CSSValueFlexEnd
3244         || id == CSSValueLeft || id == CSSValueRight;
3245 }
3246
3247 static inline bool isBaselinePositionKeyword(CSSValueID id)
3248 {
3249     return id == CSSValueBaseline || id == CSSValueLastBaseline;
3250 }
3251
3252 static bool isAlignmentOverflowKeyword(CSSValueID id)
3253 {
3254     return id == CSSValueTrue || id == CSSValueSafe;
3255 }
3256
3257 static bool isItemPositionKeyword(CSSValueID id)
3258 {
3259     return id == CSSValueStart || id == CSSValueEnd || id == CSSValueCenter
3260         || id == CSSValueSelfStart || id == CSSValueSelfEnd || id == CSSValueFlexStart
3261         || id == CSSValueFlexEnd || id == CSSValueLeft || id == CSSValueRight;
3262 }
3263
3264 bool CSSParser::parseLegacyPosition(CSSPropertyID propId, bool important)
3265 {
3266     // [ legacy && [ left | right | center ]
3267
3268     CSSParserValue* value = m_valueList->current();
3269     if (!value)
3270         return false;
3271
3272     if (value->id == CSSValueLegacy) {
3273         value = m_valueList->next();
3274         if (!value)
3275             return false;
3276         if (value->id != CSSValueCenter && value->id != CSSValueLeft && value->id != CSSValueRight)
3277             return false;
3278     } else if (value->id == CSSValueCenter || value->id == CSSValueLeft || value->id == CSSValueRight) {
3279         if (!m_valueList->next() || m_valueList->current()->id != CSSValueLegacy)
3280             return false;
3281     } else
3282         return false;
3283
3284     addProperty(propId, createPrimitiveValuePair(cssValuePool().createIdentifierValue(CSSValueLegacy), cssValuePool().createIdentifierValue(value->id)), important);
3285     return !m_valueList->next();
3286 }
3287
3288 PassRefPtr<CSSValue> CSSParser::parseContentDistributionOverflowPosition()
3289 {
3290     // auto | <baseline-position> | <content-distribution> || [ <overflow-position>? && <content-position> ]
3291     // <baseline-position> = baseline | last-baseline;
3292     // <content-distribution> = space-between | space-around | space-evenly | stretch;
3293     // <content-position> = center | start | end | flex-start | flex-end | left | right;
3294     // <overflow-position> = true | safe
3295
3296     CSSParserValue* value = m_valueList->current();
3297     if (!value)
3298         return nullptr;
3299
3300     // auto | <baseline-position>
3301     if (value->id == CSSValueAuto || isBaselinePositionKeyword(value->id)) {
3302         m_valueList->next();
3303         return CSSContentDistributionValue::create(CSSValueInvalid, value->id, CSSValueInvalid);
3304     }
3305
3306     CSSValueID distribution = CSSValueInvalid;
3307     CSSValueID position = CSSValueInvalid;
3308     CSSValueID overflow = CSSValueInvalid;
3309     while (value) {
3310         if (isContentDistributionKeyword(value->id)) {
3311             if (distribution != CSSValueInvalid)
3312                 return nullptr;
3313             distribution = value->id;
3314         } else if (isContentPositionKeyword(value->id)) {
3315             if (position != CSSValueInvalid)
3316                 return nullptr;
3317             position = value->id;
3318         } else if (isAlignmentOverflowKeyword(value->id)) {
3319             if (overflow != CSSValueInvalid)
3320                 return nullptr;
3321             overflow = value->id;
3322         } else
3323             return nullptr;
3324         value = m_valueList->next();
3325     }
3326
3327     // The grammar states that we should have at least <content-distribution> or
3328     // <content-position> ( <content-distribution> || <content-position> ).
3329     if (position == CSSValueInvalid && distribution == CSSValueInvalid)
3330         return nullptr;
3331
3332     // The grammar states that <overflow-position> must be associated to <content-position>.
3333     if (overflow != CSSValueInvalid && position == CSSValueInvalid)
3334         return nullptr;
3335
3336     return CSSContentDistributionValue::create(distribution, position, overflow);
3337 }
3338
3339 bool CSSParser::parseItemPositionOverflowPosition(CSSPropertyID propId, bool important)
3340 {
3341     // auto | stretch | <baseline-position> | [<item-position> && <overflow-position>? ]
3342     // <baseline-position> = baseline | last-baseline;
3343     // <item-position> = center | start | end | self-start | self-end | flex-start | flex-end | left | right;
3344     // <overflow-position> = true | safe
3345
3346     CSSParserValue* value = m_valueList->current();
3347     if (!value)
3348         return false;
3349
3350     if (value->id == CSSValueAuto || value->id == CSSValueStretch || isBaselinePositionKeyword(value->id)) {
3351         if (m_valueList->next())
3352             return false;
3353
3354         addProperty(propId, cssValuePool().createIdentifierValue(value->id), important);
3355         return true;
3356     }
3357
3358     RefPtr<CSSPrimitiveValue> position;
3359     RefPtr<CSSPrimitiveValue> overflowAlignmentKeyword;
3360     if (isItemPositionKeyword(value->id)) {
3361         position = cssValuePool().createIdentifierValue(value->id);
3362         value = m_valueList->next();
3363         if (value) {
3364             if (value->id != CSSValueTrue && value->id != CSSValueSafe)
3365                 return false;
3366             overflowAlignmentKeyword = cssValuePool().createIdentifierValue(value->id);
3367         }
3368     } else if (isAlignmentOverflowKeyword(value->id)) {
3369         overflowAlignmentKeyword = cssValuePool().createIdentifierValue(value->id);
3370         value = m_valueList->next();
3371         if (value && isItemPositionKeyword(value->id))
3372             position = cssValuePool().createIdentifierValue(value->id);
3373         else
3374             return false;
3375     } else
3376         return false;
3377
3378     if (m_valueList->next())
3379         return false;
3380
3381     ASSERT(position);
3382     if (overflowAlignmentKeyword)
3383         addProperty(propId, createPrimitiveValuePair(position.release(), overflowAlignmentKeyword.release()), important);
3384     else
3385         addProperty(propId, position.release(), important);
3386
3387     return true;
3388 }
3389
3390 static bool parseBackgroundClip(CSSParserValue& parserValue, RefPtr<CSSValue>& cssValue)
3391 {
3392     if (parserValue.id == CSSValueBorderBox || parserValue.id == CSSValuePaddingBox
3393         || parserValue.id == CSSValueContentBox || parserValue.id == CSSValueWebkitText) {
3394         cssValue = cssValuePool().createIdentifierValue(parserValue.id);
3395         return true;
3396     }
3397     return false;
3398 }
3399
3400 bool CSSParser::useLegacyBackgroundSizeShorthandBehavior() const
3401 {
3402     return m_context.useLegacyBackgroundSizeShorthandBehavior;
3403 }
3404
3405 #if ENABLE(CSS_SCROLL_SNAP)
3406 bool CSSParser::parseNonElementSnapPoints(CSSPropertyID propId, bool important)
3407 {
3408     RefPtr<CSSValueList> values = CSSValueList::createSpaceSeparated();
3409     while (CSSParserValue* value = m_valueList->current()) {
3410         ValueWithCalculation valueWithCalculation(*value);
3411         if (validateUnit(valueWithCalculation, FPercent | FLength))
3412             values->append(createPrimitiveNumericValue(valueWithCalculation));
3413         else if (value->unit == CSSParserValue::Function
3414             && value->function->args
3415             && value->function->args->size() == 1
3416             && equalIgnoringCase(value->function->name, "repeat(")) {
3417             ValueWithCalculation argumentWithCalculation(*value->function->args.get()->current());
3418             if (validateUnit(argumentWithCalculation, FLength | FPercent)) {
3419                 values->append(cssValuePool().createValue(LengthRepeat::create(createPrimitiveNumericValue(argumentWithCalculation))));
3420                 m_valueList->next();
3421                 if (m_valueList->current())
3422                     return false;
3423                 break;
3424             }
3425         } else
3426             return false;
3427         m_valueList->next();
3428     }
3429     if (values->length()) {
3430         addProperty(propId, values.release(), important);
3431         m_valueList->next();
3432         return true;
3433     }
3434     return false;
3435 }
3436
3437 bool CSSParser::parseScrollSnapPositions(RefPtr<CSSValue>& cssValueX, RefPtr<CSSValue>& cssValueY)
3438 {
3439     cssValueX = parsePositionX(*m_valueList);
3440     if (!cssValueX)
3441         return false;
3442
3443     // Don't accept odd-length lists of positions (must always have an X and a Y):
3444     if (!m_valueList->next())
3445         return false;
3446
3447     cssValueY = parsePositionY(*m_valueList);
3448     if (!cssValueY)
3449         return false;
3450
3451     return true;
3452 }
3453
3454 bool CSSParser::parseScrollSnapDestination(CSSPropertyID propId, bool important)
3455 {
3456     RefPtr<CSSValueList> position = CSSValueList::createSpaceSeparated();
3457     if (m_valueList->size() != 2)
3458         return false;
3459
3460     RefPtr<CSSValue> cssValueX, cssValueY;
3461     if (!parseScrollSnapPositions(cssValueX, cssValueY))
3462         return false;
3463
3464     position->append(cssValueX.releaseNonNull());
3465     position->append(cssValueY.releaseNonNull());
3466     addProperty(propId, position, important);
3467     m_valueList->next();
3468     return true;
3469 }
3470
3471 bool CSSParser::parseScrollSnapCoordinate(CSSPropertyID propId, bool important)
3472 {
3473     RefPtr<CSSValueList> positions = CSSValueList::createSpaceSeparated();
3474     while (m_valueList->current()) {
3475         RefPtr<CSSValue> cssValueX, cssValueY;
3476         if (!parseScrollSnapPositions(cssValueX, cssValueY))
3477             return false;
3478
3479         positions->append(cssValueX.releaseNonNull());
3480         positions->append(cssValueY.releaseNonNull());
3481         m_valueList->next();
3482     }
3483
3484     if (positions->length()) {
3485         addProperty(propId, positions.release(), important);
3486         return true;
3487     }
3488     return false;
3489 }
3490 #endif
3491
3492 const int cMaxFillProperties = 9;
3493
3494 bool CSSParser::parseFillShorthand(CSSPropertyID propId, const CSSPropertyID* properties, int numProperties, bool important)
3495 {
3496     ASSERT(numProperties <= cMaxFillProperties);
3497     if (numProperties > cMaxFillProperties)
3498         return false;
3499
3500     ShorthandScope scope(this, propId);
3501
3502     bool parsedProperty[cMaxFillProperties] = { false };
3503     RefPtr<CSSValue> values[cMaxFillProperties];
3504     RefPtr<CSSValue> clipValue;
3505     RefPtr<CSSValue> positionYValue;
3506     RefPtr<CSSValue> repeatYValue;
3507     bool foundClip = false;
3508     int i;
3509     bool foundPositionCSSProperty = false;
3510
3511     while (m_valueList->current()) {
3512         CSSParserValue& currentValue = *m_valueList->current();
3513         if (currentValue.unit == CSSParserValue::Operator && currentValue.iValue == ',') {
3514             // We hit the end.  Fill in all remaining values with the initial value.
3515             m_valueList->next();
3516             for (i = 0; i < numProperties; ++i) {
3517                 if (properties[i] == CSSPropertyBackgroundColor && parsedProperty[i])
3518                     // Color is not allowed except as the last item in a list for backgrounds.
3519                     // Reject the entire property.
3520                     return false;
3521
3522                 if (!parsedProperty[i] && properties[i] != CSSPropertyBackgroundColor) {
3523                     addFillValue(values[i], cssValuePool().createImplicitInitialValue());
3524                     if (properties[i] == CSSPropertyBackgroundPosition || properties[i] == CSSPropertyWebkitMaskPosition)
3525                         addFillValue(positionYValue, cssValuePool().createImplicitInitialValue());
3526                     if (properties[i] == CSSPropertyBackgroundRepeat || properties[i] == CSSPropertyWebkitMaskRepeat)
3527                         addFillValue(repeatYValue, cssValuePool().createImplicitInitialValue());
3528                     if ((properties[i] == CSSPropertyBackgroundOrigin || properties[i] == CSSPropertyWebkitMaskOrigin) && !parsedProperty[i]) {
3529                         // If background-origin wasn't present, then reset background-clip also.
3530                         addFillValue(clipValue, cssValuePool().createImplicitInitialValue());
3531                     }
3532                 }
3533                 parsedProperty[i] = false;
3534             }
3535             if (!m_valueList->current())
3536                 break;
3537         }
3538
3539         bool sizeCSSPropertyExpected = false;
3540         if (isForwardSlashOperator(currentValue) && foundPositionCSSProperty) {
3541             sizeCSSPropertyExpected = true;
3542             m_valueList->next();
3543         }
3544
3545         foundPositionCSSProperty = false;
3546         bool found = false;
3547         for (i = 0; !found && i < numProperties; ++i) {
3548
3549             if (sizeCSSPropertyExpected && (properties[i] != CSSPropertyBackgroundSize && properties[i] != CSSPropertyWebkitMaskSize))
3550                 continue;
3551             if (!sizeCSSPropertyExpected && (properties[i] == CSSPropertyBackgroundSize || properties[i] == CSSPropertyWebkitMaskSize))
3552                 continue;
3553
3554             if (!parsedProperty[i]) {
3555                 RefPtr<CSSValue> val1;
3556                 RefPtr<CSSValue> val2;
3557                 CSSPropertyID propId1, propId2;
3558                 CSSParserValue& parserValue = *m_valueList->current();
3559
3560                 if (parseFillProperty(properties[i], propId1, propId2, val1, val2)) {
3561                     parsedProperty[i] = found = true;
3562                     addFillValue(values[i], val1.releaseNonNull());
3563                     if (properties[i] == CSSPropertyBackgroundPosition || properties[i] == CSSPropertyWebkitMaskPosition)
3564                         addFillValue(positionYValue, val2.releaseNonNull());
3565                     if (properties[i] == CSSPropertyBackgroundRepeat || properties[i] == CSSPropertyWebkitMaskRepeat)
3566                         addFillValue(repeatYValue, val2.releaseNonNull());
3567                     if (properties[i] == CSSPropertyBackgroundOrigin || properties[i] == CSSPropertyWebkitMaskOrigin) {
3568                         // Reparse the value as a clip, and see if we succeed.
3569                         if (parseBackgroundClip(parserValue, val1))
3570                             addFillValue(clipValue, val1.releaseNonNull()); // The property parsed successfully.
3571                         else
3572                             addFillValue(clipValue, cssValuePool().createImplicitInitialValue()); // Some value was used for origin that is not supported by clip. Just reset clip instead.
3573                     }
3574                     if (properties[i] == CSSPropertyBackgroundClip || properties[i] == CSSPropertyWebkitMaskClip)
3575                         foundClip = true;
3576                     if (properties[i] == CSSPropertyBackgroundPosition || properties[i] == CSSPropertyWebkitMaskPosition)
3577                         foundPositionCSSProperty = true;
3578                 }
3579             }
3580         }
3581
3582         // if we didn't find at least one match, this is an
3583         // invalid shorthand and we have to ignore it
3584         if (!found)
3585             return false;
3586     }
3587
3588     // Now add all of the properties we found.
3589     for (i = 0; i < numProperties; ++i) {
3590         // Fill in any remaining properties with the initial value.
3591         if (!parsedProperty[i]) {
3592             addFillValue(values[i], cssValuePool().createImplicitInitialValue());
3593             if (properties[i] == CSSPropertyBackgroundPosition || properties[i] == CSSPropertyWebkitMaskPosition)
3594                 addFillValue(positionYValue, cssValuePool().createImplicitInitialValue());
3595             if (properties[i] == CSSPropertyBackgroundRepeat || properties[i] == CSSPropertyWebkitMaskRepeat)
3596                 addFillValue(repeatYValue, cssValuePool().createImplicitInitialValue());
3597             if (properties[i] == CSSPropertyBackgroundOrigin || properties[i] == CSSPropertyWebkitMaskOrigin) {
3598                 // If background-origin wasn't present, then reset background-clip also.
3599                 addFillValue(clipValue, cssValuePool().createImplicitInitialValue());
3600             }
3601         }
3602         if (properties[i] == CSSPropertyBackgroundPosition) {
3603             addProperty(CSSPropertyBackgroundPositionX, values[i].release(), important);
3604             // it's OK to call positionYValue.release() since we only see CSSPropertyBackgroundPosition once
3605             addProperty(CSSPropertyBackgroundPositionY, positionYValue.release(), important);
3606         } else if (properties[i] == CSSPropertyWebkitMaskPosition) {
3607             addProperty(CSSPropertyWebkitMaskPositionX, values[i].release(), important);
3608             // it's OK to call positionYValue.release() since we only see CSSPropertyWebkitMaskPosition once
3609             addProperty(CSSPropertyWebkitMaskPositionY, positionYValue.release(), important);
3610         } else if (properties[i] == CSSPropertyBackgroundRepeat) {
3611             addProperty(CSSPropertyBackgroundRepeatX, values[i].release(), important);
3612             // it's OK to call repeatYValue.release() since we only see CSSPropertyBackgroundPosition once
3613             addProperty(CSSPropertyBackgroundRepeatY, repeatYValue.release(), important);
3614         } else if (properties[i] == CSSPropertyWebkitMaskRepeat) {
3615             addProperty(CSSPropertyWebkitMaskRepeatX, values[i].release(), important);
3616             // it's OK to call repeatYValue.release() since we only see CSSPropertyBackgroundPosition once
3617             addProperty(CSSPropertyWebkitMaskRepeatY, repeatYValue.release(), important);
3618         } else if ((properties[i] == CSSPropertyBackgroundClip || properties[i] == CSSPropertyWebkitMaskClip) && !foundClip)
3619             // Value is already set while updating origin
3620             continue;
3621         else if (properties[i] == CSSPropertyBackgroundSize && !parsedProperty[i] && useLegacyBackgroundSizeShorthandBehavior())
3622             continue;
3623         else
3624             addProperty(properties[i], values[i].release(), important);
3625
3626         // Add in clip values when we hit the corresponding origin property.
3627         if (properties[i] == CSSPropertyBackgroundOrigin && !foundClip)
3628             addProperty(CSSPropertyBackgroundClip, clipValue.release(), important);
3629         else if (properties[i] == CSSPropertyWebkitMaskOrigin && !foundClip)
3630             addProperty(CSSPropertyWebkitMaskClip, clipValue.release(), important);
3631     }
3632
3633     return true;
3634 }
3635
3636 void CSSParser::addAnimationValue(RefPtr<CSSValue>& lval, Ref<CSSValue>&& rval)
3637 {
3638     if (!lval) {
3639         lval = WTF::move(rval);
3640         return;
3641     }
3642
3643     if (is<CSSValueList>(*lval)) {
3644         downcast<CSSValueList>(*lval).append(WTF::move(rval));
3645         return;
3646     }
3647
3648     auto list = CSSValueList::createCommaSeparated();
3649     list.get().append(lval.releaseNonNull());
3650     list.get().append(WTF::move(rval));
3651     lval = WTF::move(list);
3652 }
3653
3654 bool CSSParser::parseAnimationShorthand(CSSPropertyID propId, bool important)
3655 {
3656     ASSERT(propId == CSSPropertyAnimation || propId == CSSPropertyWebkitAnimation);
3657
3658     const unsigned numProperties = 7;
3659     const StylePropertyShorthand& shorthand = animationShorthandForParsing(propId);
3660
3661     // The list of properties in the shorthand should be the same
3662     // length as the list with animation name in last position, even though they are
3663     // in a different order.
3664     ASSERT(numProperties == shorthand.length());
3665     ASSERT(numProperties == animationShorthand().length());
3666     ASSERT(numProperties == webkitAnimationShorthand().length());
3667
3668     ShorthandScope scope(this, propId);
3669
3670     bool parsedProperty[numProperties] = { false };
3671     AnimationParseContext context;
3672     RefPtr<CSSValue> values[numProperties];
3673
3674     unsigned i;
3675     while (m_valueList->current()) {
3676         CSSParserValue* val = m_valueList->current();
3677         if (val->unit == CSSParserValue::Operator && val->iValue == ',') {
3678             // We hit the end.  Fill in all remaining values with the initial value.
3679             m_valueList->next();
3680             for (i = 0; i < numProperties; ++i) {
3681                 if (!parsedProperty[i])
3682                     addAnimationValue(values[i], cssValuePool().createImplicitInitialValue());
3683                 parsedProperty[i] = false;
3684             }
3685             if (!m_valueList->current())
3686                 break;
3687             context.commitFirstAnimation();
3688         }
3689
3690         bool found = false;
3691         for (i = 0; i < numProperties; ++i) {
3692             if (!parsedProperty[i]) {
3693                 RefPtr<CSSValue> val;
3694                 if (parseAnimationProperty(shorthand.properties()[i], val, context)) {
3695                     parsedProperty[i] = found = true;
3696                     addAnimationValue(values[i], val.releaseNonNull());
3697                     break;
3698                 }
3699             }
3700
3701             // There are more values to process but 'none' or 'all' were already defined as the animation property, the declaration becomes invalid.
3702             if (!context.animationPropertyKeywordAllowed() && context.hasCommittedFirstAnimation())
3703                 return false;
3704         }
3705
3706         // if we didn't find at least one match, this is an
3707         // invalid shorthand and we have to ignore it
3708         if (!found)
3709             return false;
3710     }
3711
3712     for (i = 0; i < numProperties; ++i) {
3713         // If we didn't find the property, set an intial value.
3714         if (!parsedProperty[i])
3715             addAnimationValue(values[i], cssValuePool().createImplicitInitialValue());
3716
3717         addProperty(shorthand.properties()[i], values[i].release(), important);
3718     }
3719
3720     return true;
3721 }
3722
3723 RefPtr<CSSValue> CSSParser::parseColumnWidth()
3724 {
3725     ValueWithCalculation valueWithCalculation(*m_valueList->current());
3726     CSSValueID id = valueWithCalculation.value().id;
3727     // Always parse this property in strict mode, since it would be ambiguous otherwise when used in the 'columns' shorthand property.
3728     if (id != CSSValueAuto && !(validateUnit(valueWithCalculation, FLength | FNonNeg, CSSStrictMode) && parsedDouble(valueWithCalculation)))
3729         return nullptr;
3730
3731     RefPtr<CSSValue> parsedValue = parseValidPrimitive(id, valueWithCalculation);
3732     m_valueList->next();
3733     return parsedValue;
3734 }
3735
3736 RefPtr<CSSValue> CSSParser::parseColumnCount()
3737 {
3738     ValueWithCalculation valueWithCalculation(*m_valueList->current());
3739     CSSValueID id = valueWithCalculation.value().id;
3740
3741     if (id != CSSValueAuto && !validateUnit(valueWithCalculation, FPositiveInteger, CSSQuirksMode))
3742         return nullptr;
3743
3744     RefPtr<CSSValue> parsedValue = parseValidPrimitive(id, valueWithCalculation);
3745     m_valueList->next();
3746     return parsedValue;
3747 }
3748
3749 bool CSSParser::parseColumnsShorthand(bool important)
3750 {
3751     RefPtr<CSSValue> columnWidth;
3752     RefPtr<CSSValue> columnCount;
3753     bool hasPendingExplicitAuto = false;
3754
3755     for (unsigned propertiesParsed = 0; CSSParserValue* value = m_valueList->current(); propertiesParsed++) {
3756         if (propertiesParsed >= 2)
3757             return false; // Too many values for this shorthand. Invalid declaration.
3758         if (!propertiesParsed && value->id == CSSValueAuto) {
3759             // 'auto' is a valid value for any of the two longhands, and at this point
3760             // we don't know which one(s) it is meant for. We need to see if there are other values first.
3761             m_valueList->next();
3762             hasPendingExplicitAuto = true;
3763         } else {
3764             if (!columnWidth) {
3765                 if ((columnWidth = parseColumnWidth()))
3766                     continue;
3767             }
3768             if (!columnCount) {
3769                 if ((columnCount = parseColumnCount()))
3770                     continue;
3771             }
3772             // If we didn't find at least one match, this is an invalid shorthand and we have to ignore it.
3773             return false;
3774         }
3775     }
3776
3777     // Any unassigned property at this point will become implicit 'auto'.
3778     if (columnWidth)
3779         addProperty(CSSPropertyColumnWidth, columnWidth, important);
3780     else {
3781         addProperty(CSSPropertyColumnWidth, cssValuePool().createIdentifierValue(CSSValueAuto), important, !hasPendingExplicitAuto /* implicit */);
3782         hasPendingExplicitAuto = false;
3783     }
3784
3785     if (columnCount)
3786         addProperty(CSSPropertyColumnCount, columnCount, important);
3787     else
3788         addProperty(CSSPropertyColumnCount, cssValuePool().createIdentifierValue(CSSValueAuto), important, !hasPendingExplicitAuto /* implicit */);
3789
3790     return true;
3791 }
3792
3793 bool CSSParser::parseTransitionShorthand(CSSPropertyID propId, bool important)
3794 {
3795     const unsigned numProperties = 4;
3796     const StylePropertyShorthand& shorthand = shorthandForProperty(propId);
3797     ASSERT(numProperties == shorthand.length());
3798
3799     ShorthandScope scope(this, propId);
3800
3801     bool parsedProperty[numProperties] = { false };
3802     AnimationParseContext context;
3803     RefPtr<CSSValue> values[numProperties];
3804
3805     unsigned i;
3806     while (m_valueList->current()) {
3807         CSSParserValue* val = m_valueList->current();
3808         if (val->unit == CSSParserValue::Operator && val->iValue == ',') {
3809             // We hit the end. Fill in all remaining values with the initial value.
3810             m_valueList->next();
3811             for (i = 0; i < numProperties; ++i) {
3812                 if (!parsedProperty[i])
3813                     addAnimationValue(values[i], cssValuePool().createImplicitInitialValue());
3814                 parsedProperty[i] = false;
3815             }
3816             if (!m_valueList->current())
3817                 break;
3818             context.commitFirstAnimation();
3819         }
3820
3821         bool found = false;
3822         for (i = 0; !found && i < numProperties; ++i) {
3823             if (!parsedProperty[i]) {
3824                 RefPtr<CSSValue> val;
3825                 if (parseAnimationProperty(shorthand.properties()[i], val, context)) {
3826                     parsedProperty[i] = found = true;
3827                     addAnimationValue(values[i], val.releaseNonNull());
3828                 }
3829
3830                 // There are more values to process but 'none' or 'all' were already defined as the animation property, the declaration becomes invalid.
3831                 if (!context.animationPropertyKeywordAllowed() && context.hasCommittedFirstAnimation())
3832                     return false;
3833             }
3834         }
3835
3836         // if we didn't find at least one match, this is an
3837         // invalid shorthand and we have to ignore it
3838         if (!found)
3839             return false;
3840     }
3841
3842     // Fill in any remaining properties with the initial value.
3843     for (i = 0; i < numProperties; ++i) {
3844         if (!parsedProperty[i])
3845             addAnimationValue(values[i], cssValuePool().createImplicitInitialValue());
3846     }
3847
3848     // Now add all of the properties we found.
3849     for (i = 0; i < numProperties; ++i)
3850         addPropertyWithPrefixingVariant(shorthand.properties()[i], values[i].release(), important);
3851
3852     return true;
3853 }
3854
3855 bool CSSParser::parseShorthand(CSSPropertyID propId, const StylePropertyShorthand& shorthand, bool important)
3856 {
3857     // We try to match as many properties as possible
3858     // We set up an array of booleans to mark which property has been found,
3859     // and we try to search for properties until it makes no longer any sense.
3860     ShorthandScope scope(this, propId);
3861
3862     bool found = false;
3863     unsigned propertiesParsed = 0;
3864     bool propertyFound[6]= { false, false, false, false, false, false }; // 6 is enough size.
3865
3866     while (m_valueList->current()) {
3867         found = false;
3868         for (unsigned propIndex = 0; !found && propIndex < shorthand.length(); ++propIndex) {
3869             if (!propertyFound[propIndex] && parseValue(shorthand.properties()[propIndex], important)) {
3870                     propertyFound[propIndex] = found = true;
3871                     propertiesParsed++;
3872             }
3873         }
3874
3875         // if we didn't find at least one match, this is an
3876         // invalid shorthand and we have to ignore it
3877         if (!found)
3878             return false;
3879     }
3880
3881     if (propertiesParsed == shorthand.length())
3882         return true;
3883
3884     // Fill in any remaining properties with the initial value.
3885     ImplicitScope implicitScope(*this, PropertyImplicit);
3886     const StylePropertyShorthand* propertiesForInitialization = shorthand.propertiesForInitialization();
3887     for (unsigned i = 0; i < shorthand.length(); ++i) {
3888         if (propertyFound[i])
3889             continue;
3890
3891         if (propertiesForInitialization) {
3892             const StylePropertyShorthand& initProperties = propertiesForInitialization[i];
3893             for (unsigned propIndex = 0; propIndex < initProperties.length(); ++propIndex)
3894                 addProperty(initProperties.properties()[propIndex], cssValuePool().createImplicitInitialValue(), important);
3895         } else
3896             addProperty(shorthand.properties()[i], cssValuePool().createImplicitInitialValue(), important);
3897     }
3898
3899     return true;
3900 }
3901
3902 bool CSSParser::parse4Values(CSSPropertyID propId, const CSSPropertyID *properties,  bool important)
3903 {
3904     /* From the CSS 2 specs, 8.3
3905      * If there is only one value, it applies to all sides. If there are two values, the top and
3906      * bottom margins are set to the first value and the right and left margins are set to the second.
3907      * If there are three values, the top is set to the first value, the left and right are set to the
3908      * second, and the bottom is set to the third. If there are four values, they apply to the top,
3909      * right, bottom, and left, respectively.
3910      */
3911
3912     unsigned num = inShorthand() ? 1 : m_valueList->size();
3913
3914     ShorthandScope scope(this, propId);
3915
3916     // the order is top, right, bottom, left
3917     switch (num) {
3918         case 1: {
3919             if (!parseValue(properties[0], important))
3920                 return false;
3921             CSSValue* value = m_parsedProperties.last().value();
3922             ImplicitScope implicitScope(*this, PropertyImplicit);
3923             addProperty(properties[1], value, important);
3924             addProperty(properties[2], value, important);
3925             addProperty(properties[3], value, important);
3926             break;
3927         }
3928         case 2: {
3929             if (!parseValue(properties[0], important) || !parseValue(properties[1], important))
3930                 return false;
3931             CSSValue* value = m_parsedProperties[m_parsedProperties.size() - 2].value();
3932             ImplicitScope implicitScope(*this, PropertyImplicit);
3933             addProperty(properties[2], value, important);
3934             value = m_parsedProperties[m_parsedProperties.size() - 2].value();
3935             addProperty(properties[3], value, important);
3936             break;
3937         }
3938         case 3: {
3939             if (!parseValue(properties[0], important) || !parseValue(properties[1], important) || !parseValue(properties[2], important))
3940                 return false;
3941             CSSValue* value = m_parsedProperties[m_parsedProperties.size() - 2].value();
3942             ImplicitScope implicitScope(*this, PropertyImplicit);
3943             addProperty(properties[3], value, important);
3944             break;
3945         }
3946         case 4: {
3947             if (!parseValue(properties[0], important) || !parseValue(properties[1], important) ||
3948                 !parseValue(properties[2], important) || !parseValue(properties[3], important))
3949                 return false;
3950             break;
3951         }
3952         default: {
3953             return false;
3954         }
3955     }
3956
3957     return true;
3958 }
3959
3960 // auto | <identifier>
3961 bool CSSParser::parsePage(CSSPropertyID propId, bool important)
3962 {
3963     ASSERT(propId == CSSPropertyPage);
3964
3965     if (m_valueList->size() != 1)
3966         return false;
3967
3968     CSSParserValue* value = m_valueList->current();
3969     if (!value)
3970         return false;
3971