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