[CSS Parser] Remove WebkitCSSTransformValue
[WebKit-https.git] / Source / WebCore / css / parser / CSSParserFastPaths.cpp
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Copyright (C) 2016 Apple Inc. All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 //    * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 //    * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
13 // distribution.
14 //    * Neither the name of Google Inc. nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30 #include "config.h"
31 #include "CSSParserFastPaths.h"
32
33 #include "CSSFunctionValue.h"
34 #include "CSSInheritedValue.h"
35 #include "CSSInitialValue.h"
36 #include "CSSParserIdioms.h"
37 #include "CSSPrimitiveValue.h"
38 #include "CSSPropertyParser.h"
39 #include "CSSValueList.h"
40 #include "CSSValuePool.h"
41 #include "HTMLParserIdioms.h"
42 #include "RuntimeEnabledFeatures.h"
43 #include "StyleColor.h"
44 #include "StylePropertyShorthand.h"
45 #include "StyleSheetContents.h"
46
47 namespace WebCore {
48
49 static inline bool isSimpleLengthPropertyID(CSSPropertyID propertyId, bool& acceptsNegativeNumbers)
50 {
51     switch (propertyId) {
52     case CSSPropertyFontSize:
53 #if ENABLE(CSS_GRID_LAYOUT)
54     case CSSPropertyGridColumnGap:
55     case CSSPropertyGridRowGap:
56 #endif
57     case CSSPropertyHeight:
58     case CSSPropertyWidth:
59     case CSSPropertyMinHeight:
60     case CSSPropertyMinWidth:
61     case CSSPropertyPaddingBottom:
62     case CSSPropertyPaddingLeft:
63     case CSSPropertyPaddingRight:
64     case CSSPropertyPaddingTop:
65     case CSSPropertyWebkitLogicalWidth:
66     case CSSPropertyWebkitLogicalHeight:
67     case CSSPropertyWebkitMinLogicalWidth:
68     case CSSPropertyWebkitMinLogicalHeight:
69     case CSSPropertyWebkitPaddingAfter:
70     case CSSPropertyWebkitPaddingBefore:
71     case CSSPropertyWebkitPaddingEnd:
72     case CSSPropertyWebkitPaddingStart:
73     case CSSPropertyShapeMargin:
74         acceptsNegativeNumbers = false;
75         return true;
76     case CSSPropertyBottom:
77     case CSSPropertyCx:
78     case CSSPropertyCy:
79     case CSSPropertyLeft:
80     case CSSPropertyMarginBottom:
81     case CSSPropertyMarginLeft:
82     case CSSPropertyMarginRight:
83     case CSSPropertyMarginTop:
84     case CSSPropertyRight:
85     case CSSPropertyTop:
86     case CSSPropertyWebkitMarginAfter:
87     case CSSPropertyWebkitMarginBefore:
88     case CSSPropertyWebkitMarginEnd:
89     case CSSPropertyWebkitMarginStart:
90     case CSSPropertyX:
91     case CSSPropertyY:
92     case CSSPropertyR:
93     case CSSPropertyRx:
94     case CSSPropertyRy:
95         acceptsNegativeNumbers = true;
96         return true;
97     default:
98         return false;
99     }
100 }
101
102 template <typename CharacterType>
103 static inline bool parseSimpleLength(const CharacterType* characters, unsigned length, CSSPrimitiveValue::UnitType& unit, double& number)
104 {
105     if (length > 2 && (characters[length - 2] | 0x20) == 'p' && (characters[length - 1] | 0x20) == 'x') {
106         length -= 2;
107         unit = CSSPrimitiveValue::UnitType::CSS_PX;
108     } else if (length > 1 && characters[length - 1] == '%') {
109         length -= 1;
110         unit = CSSPrimitiveValue::UnitType::CSS_PERCENTAGE;
111     }
112
113     // We rely on charactersToDouble for validation as well. The function
114     // will set "ok" to "false" if the entire passed-in character range does
115     // not represent a double.
116     bool ok;
117     number = charactersToDouble(characters, length, &ok);
118     if (!ok)
119         return false;
120     return true;
121 }
122
123 static RefPtr<CSSValue> parseSimpleLengthValue(CSSPropertyID propertyId, const String& string, CSSParserMode cssParserMode)
124 {
125     ASSERT(!string.isEmpty());
126     bool acceptsNegativeNumbers = false;
127
128     // In @viewport, width and height are shorthands, not simple length values.
129     if (isCSSViewportParsingEnabledForMode(cssParserMode) || !isSimpleLengthPropertyID(propertyId, acceptsNegativeNumbers))
130         return nullptr;
131
132     unsigned length = string.length();
133     double number;
134     CSSPrimitiveValue::UnitType unit = CSSPrimitiveValue::UnitType::CSS_NUMBER;
135
136     if (string.is8Bit()) {
137         if (!parseSimpleLength(string.characters8(), length, unit, number))
138             return nullptr;
139     } else {
140         if (!parseSimpleLength(string.characters16(), length, unit, number))
141             return nullptr;
142     }
143
144     if (unit == CSSPrimitiveValue::UnitType::CSS_NUMBER) {
145         if (number && cssParserMode != SVGAttributeMode)
146             return nullptr;
147         unit = CSSPrimitiveValue::UnitType::CSS_PX;
148     }
149
150     if (number < 0 && !acceptsNegativeNumbers)
151         return nullptr;
152     if (std::isinf(number))
153         return nullptr;
154
155     return CSSPrimitiveValue::create(number, unit);
156 }
157
158 static inline bool isColorPropertyID(CSSPropertyID propertyId)
159 {
160     switch (propertyId) {
161     case CSSPropertyColor:
162     case CSSPropertyBackgroundColor:
163     case CSSPropertyBorderBottomColor:
164     case CSSPropertyBorderLeftColor:
165     case CSSPropertyBorderRightColor:
166     case CSSPropertyBorderTopColor:
167     case CSSPropertyFill:
168     case CSSPropertyFloodColor:
169     case CSSPropertyLightingColor:
170     case CSSPropertyOutlineColor:
171     case CSSPropertyStopColor:
172     case CSSPropertyStroke:
173     case CSSPropertyWebkitBorderAfterColor:
174     case CSSPropertyWebkitBorderBeforeColor:
175     case CSSPropertyWebkitBorderEndColor:
176     case CSSPropertyWebkitBorderStartColor:
177     case CSSPropertyColumnRuleColor:
178     case CSSPropertyWebkitTextEmphasisColor:
179     case CSSPropertyWebkitTextFillColor:
180     case CSSPropertyWebkitTextStrokeColor:
181     case CSSPropertyWebkitTextDecorationColor:
182         return true;
183     default:
184         return false;
185     }
186 }
187
188 // Returns the number of characters which form a valid double
189 // and are terminated by the given terminator character
190 template <typename CharacterType>
191 static int checkForValidDouble(const CharacterType* string, const CharacterType* end, const char terminator)
192 {
193     int length = end - string;
194     if (length < 1)
195         return 0;
196
197     bool decimalMarkSeen = false;
198     int processedLength = 0;
199
200     for (int i = 0; i < length; ++i) {
201         if (string[i] == terminator) {
202             processedLength = i;
203             break;
204         }
205         if (!isASCIIDigit(string[i])) {
206             if (!decimalMarkSeen && string[i] == '.')
207                 decimalMarkSeen = true;
208             else
209                 return 0;
210         }
211     }
212
213     if (decimalMarkSeen && processedLength == 1)
214         return 0;
215
216     return processedLength;
217 }
218
219 // Returns the number of characters consumed for parsing a valid double
220 // terminated by the given terminator character
221 template <typename CharacterType>
222 static int parseDouble(const CharacterType* string, const CharacterType* end, const char terminator, double& value)
223 {
224     int length = checkForValidDouble(string, end, terminator);
225     if (!length)
226         return 0;
227
228     int position = 0;
229     double localValue = 0;
230
231     // The consumed characters here are guaranteed to be
232     // ASCII digits with or without a decimal mark
233     for (; position < length; ++position) {
234         if (string[position] == '.')
235             break;
236         localValue = localValue * 10 + string[position] - '0';
237     }
238
239     if (++position == length) {
240         value = localValue;
241         return length;
242     }
243
244     double fraction = 0;
245     double scale = 1;
246
247     const double maxScale = 1000000;
248     while (position < length && scale < maxScale) {
249         fraction = fraction * 10 + string[position++] - '0';
250         scale *= 10;
251     }
252
253     value = localValue + fraction / scale;
254     return length;
255 }
256
257 template <typename CharacterType>
258 static bool parseColorIntOrPercentage(const CharacterType*& string, const CharacterType* end, const char terminator, CSSPrimitiveValue::UnitType& expect, int& value)
259 {
260     const CharacterType* current = string;
261     double localValue = 0;
262     bool negative = false;
263     while (current != end && isHTMLSpace<CharacterType>(*current))
264         current++;
265     if (current != end && *current == '-') {
266         negative = true;
267         current++;
268     }
269     if (current == end || !isASCIIDigit(*current))
270         return false;
271     while (current != end && isASCIIDigit(*current)) {
272         double newValue = localValue * 10 + *current++ - '0';
273         if (newValue >= 255) {
274             // Clamp values at 255.
275             localValue = 255;
276             while (current != end && isASCIIDigit(*current))
277                 ++current;
278             break;
279         }
280         localValue = newValue;
281     }
282
283     if (current == end)
284         return false;
285
286     if (expect == CSSPrimitiveValue::UnitType::CSS_NUMBER && (*current == '.' || *current == '%'))
287         return false;
288
289     if (*current == '.') {
290         // We already parsed the integral part, try to parse
291         // the fraction part of the percentage value.
292         double percentage = 0;
293         int numCharactersParsed = parseDouble(current, end, '%', percentage);
294         if (!numCharactersParsed)
295             return false;
296         current += numCharactersParsed;
297         if (*current != '%')
298             return false;
299         localValue += percentage;
300     }
301
302     if (expect == CSSPrimitiveValue::UnitType::CSS_PERCENTAGE && *current != '%')
303         return false;
304
305     if (*current == '%') {
306         expect = CSSPrimitiveValue::UnitType::CSS_PERCENTAGE;
307         localValue = localValue / 100.0 * 256.0;
308         // Clamp values at 255 for percentages over 100%
309         if (localValue > 255)
310             localValue = 255;
311         current++;
312     } else {
313         expect = CSSPrimitiveValue::UnitType::CSS_NUMBER;
314     }
315
316     while (current != end && isHTMLSpace<CharacterType>(*current))
317         current++;
318     if (current == end || *current++ != terminator)
319         return false;
320     // Clamp negative values at zero.
321     value = negative ? 0 : static_cast<int>(localValue);
322     string = current;
323     return true;
324 }
325
326 template <typename CharacterType>
327 static inline bool isTenthAlpha(const CharacterType* string, const int length)
328 {
329     // "0.X"
330     if (length == 3 && string[0] == '0' && string[1] == '.' && isASCIIDigit(string[2]))
331         return true;
332
333     // ".X"
334     if (length == 2 && string[0] == '.' && isASCIIDigit(string[1]))
335         return true;
336
337     return false;
338 }
339
340 template <typename CharacterType>
341 static inline bool parseAlphaValue(const CharacterType*& string, const CharacterType* end, const char terminator, int& value)
342 {
343     while (string != end && isHTMLSpace<CharacterType>(*string))
344         string++;
345
346     bool negative = false;
347
348     if (string != end && *string == '-') {
349         negative = true;
350         string++;
351     }
352
353     value = 0;
354
355     int length = end - string;
356     if (length < 2)
357         return false;
358
359     if (string[length - 1] != terminator || !isASCIIDigit(string[length - 2]))
360         return false;
361
362     if (string[0] != '0' && string[0] != '1' && string[0] != '.') {
363         if (checkForValidDouble(string, end, terminator)) {
364             value = negative ? 0 : 255;
365             string = end;
366             return true;
367         }
368         return false;
369     }
370
371     if (length == 2 && string[0] != '.') {
372         value = !negative && string[0] == '1' ? 255 : 0;
373         string = end;
374         return true;
375     }
376
377     if (isTenthAlpha(string, length - 1)) {
378         static const int tenthAlphaValues[] = { 0, 25, 51, 76, 102, 127, 153, 179, 204, 230 };
379         value = negative ? 0 : tenthAlphaValues[string[length - 2] - '0'];
380         string = end;
381         return true;
382     }
383
384     double alpha = 0;
385     if (!parseDouble(string, end, terminator, alpha))
386         return false;
387     value = negative ? 0 : static_cast<int>(alpha * nextafter(256.0, 0.0));
388     string = end;
389     return true;
390 }
391
392 template <typename CharacterType>
393 static inline bool mightBeRGBA(const CharacterType* characters, unsigned length)
394 {
395     if (length < 5)
396         return false;
397     return characters[4] == '('
398         && isASCIIAlphaCaselessEqual(characters[0], 'r')
399         && isASCIIAlphaCaselessEqual(characters[1], 'g')
400         && isASCIIAlphaCaselessEqual(characters[2], 'b')
401         && isASCIIAlphaCaselessEqual(characters[3], 'a');
402 }
403
404 template <typename CharacterType>
405 static inline bool mightBeRGB(const CharacterType* characters, unsigned length)
406 {
407     if (length < 4)
408         return false;
409     return characters[3] == '('
410         && isASCIIAlphaCaselessEqual(characters[0], 'r')
411         && isASCIIAlphaCaselessEqual(characters[1], 'g')
412         && isASCIIAlphaCaselessEqual(characters[2], 'b');
413 }
414
415 template <typename CharacterType>
416 static Color fastParseColorInternal(const CharacterType* characters, unsigned length, bool quirksMode)
417 {
418     CSSPrimitiveValue::UnitType expect = CSSPrimitiveValue::UnitType::CSS_UNKNOWN;
419
420     if (length >= 4 && characters[0] == '#') {
421         RGBA32 rgb;
422         if (Color::parseHexColor(characters + 1, length - 1, rgb))
423             return Color(rgb);
424     }
425
426     if (quirksMode && (length == 3 || length == 6)) {
427         RGBA32 rgb;
428         if (Color::parseHexColor(characters, length, rgb))
429             return Color(rgb);
430     }
431
432     // Try rgba() syntax.
433     if (mightBeRGBA(characters, length)) {
434         const CharacterType* current = characters + 5;
435         const CharacterType* end = characters + length;
436         int red;
437         int green;
438         int blue;
439         int alpha;
440
441         if (!parseColorIntOrPercentage(current, end, ',', expect, red))
442             return Color();
443         if (!parseColorIntOrPercentage(current, end, ',', expect, green))
444             return Color();
445         if (!parseColorIntOrPercentage(current, end, ',', expect, blue))
446             return Color();
447         if (!parseAlphaValue(current, end, ')', alpha))
448             return Color();
449         if (current != end)
450             return Color();
451         return Color(makeRGBA(red, green, blue, alpha));
452     }
453
454     // Try rgb() syntax.
455     if (mightBeRGB(characters, length)) {
456         const CharacterType* current = characters + 4;
457         const CharacterType* end = characters + length;
458         int red;
459         int green;
460         int blue;
461         if (!parseColorIntOrPercentage(current, end, ',', expect, red))
462             return Color();
463         if (!parseColorIntOrPercentage(current, end, ',', expect, green))
464             return Color();
465         if (!parseColorIntOrPercentage(current, end, ')', expect, blue))
466             return Color();
467         if (current != end)
468             return Color();
469         return Color(makeRGB(red, green, blue));
470     }
471
472     return Color();
473 }
474
475 RefPtr<CSSValue> CSSParserFastPaths::parseColor(const String& string, CSSParserMode parserMode)
476 {
477     ASSERT(!string.isEmpty());
478     CSSValueID valueID = cssValueKeywordID(string);
479     if (StyleColor::isColorKeyword(valueID)) {
480         if (!isValueAllowedInMode(valueID, parserMode))
481             return nullptr;
482         return CSSValuePool::singleton().createIdentifierValue(valueID);
483     }
484
485     bool quirksMode = isQuirksModeBehavior(parserMode);
486
487     // Fast path for hex colors and rgb()/rgba() colors
488     Color color;
489     if (string.is8Bit())
490         color = fastParseColorInternal(string.characters8(), string.length(), quirksMode);
491     else
492         color = fastParseColorInternal(string.characters16(), string.length(), quirksMode);
493     if (!color.isValid())
494         return nullptr;
495     return CSSValuePool::singleton().createColorValue(color);
496 }
497
498 bool CSSParserFastPaths::isValidKeywordPropertyAndValue(CSSPropertyID propertyId, CSSValueID valueID, CSSParserMode parserMode, StyleSheetContents* styleSheetContents)
499 {
500     if (valueID == CSSValueInvalid || !isValueAllowedInMode(valueID, parserMode))
501         return false;
502
503     switch (propertyId) {
504     case CSSPropertyAlignmentBaseline:
505         // auto | baseline | before-edge | text-before-edge | middle |
506         // central | after-edge | text-after-edge | ideographic | alphabetic |
507         // hanging | mathematical
508         return valueID == CSSValueAuto || valueID == CSSValueAlphabetic || valueID == CSSValueBaseline
509             || valueID == CSSValueMiddle || (valueID >= CSSValueBeforeEdge && valueID <= CSSValueMathematical);
510     case CSSPropertyAll:
511         return false; // Only accepts css-wide keywords
512     case CSSPropertyBackgroundRepeatX: // repeat | no-repeat
513     case CSSPropertyBackgroundRepeatY: // repeat | no-repeat
514         return valueID == CSSValueRepeat || valueID == CSSValueNoRepeat;
515     case CSSPropertyBorderCollapse: // collapse | separate
516         return valueID == CSSValueCollapse || valueID == CSSValueSeparate;
517     case CSSPropertyBorderTopStyle: // <border-style>
518     case CSSPropertyBorderRightStyle: // Defined as: none | hidden | dotted | dashed |
519     case CSSPropertyBorderBottomStyle: // solid | double | groove | ridge | inset | outset
520     case CSSPropertyBorderLeftStyle:
521     case CSSPropertyWebkitBorderAfterStyle:
522     case CSSPropertyWebkitBorderBeforeStyle:
523     case CSSPropertyWebkitBorderEndStyle:
524     case CSSPropertyWebkitBorderStartStyle:
525     case CSSPropertyColumnRuleStyle:
526         return valueID >= CSSValueNone && valueID <= CSSValueDouble;
527     case CSSPropertyBoxSizing:
528         return valueID == CSSValueBorderBox || valueID == CSSValueContentBox;
529     case CSSPropertyBufferedRendering:
530         return valueID == CSSValueAuto || valueID == CSSValueDynamic || valueID == CSSValueStatic;
531     case CSSPropertyCaptionSide: // top | bottom | left | right
532         return valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueTop || valueID == CSSValueBottom;
533     case CSSPropertyClear: // none | left | right | both
534         return valueID == CSSValueNone || valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueBoth;
535     case CSSPropertyClipRule:
536     case CSSPropertyFillRule:
537         return valueID == CSSValueNonzero || valueID == CSSValueEvenodd;
538     case CSSPropertyColorInterpolation:
539     case CSSPropertyColorInterpolationFilters:
540         return valueID == CSSValueAuto || valueID == CSSValueSrgb || valueID == CSSValueLinearrgb;
541     case CSSPropertyColorRendering:
542         return valueID == CSSValueAuto || valueID == CSSValueOptimizespeed || valueID == CSSValueOptimizequality;
543     case CSSPropertyDirection: // ltr | rtl
544         return valueID == CSSValueLtr || valueID == CSSValueRtl;
545     case CSSPropertyDisplay:
546         // inline | block | list-item | inline-block | table |
547         // inline-table | table-row-group | table-header-group | table-footer-group | table-row |
548         // table-column-group | table-column | table-cell | table-caption | -webkit-box | -webkit-inline-box | none
549         // flex | inline-flex | -webkit-flex | -webkit-inline-flex | grid | inline-grid
550         return (valueID >= CSSValueInline && valueID <= CSSValueContents) || valueID == CSSValueNone
551 #if ENABLE(CSS_GRID_LAYOUT)
552             || (RuntimeEnabledFeatures::sharedFeatures().isCSSGridLayoutEnabled() && (valueID == CSSValueGrid || valueID == CSSValueInlineGrid))
553 #endif
554         ;
555     case CSSPropertyDominantBaseline:
556         // auto | use-script | no-change | reset-size | ideographic |
557         // alphabetic | hanging | mathematical | central | middle |
558         // text-after-edge | text-before-edge
559         return valueID == CSSValueAuto || valueID == CSSValueAlphabetic || valueID == CSSValueMiddle
560             || (valueID >= CSSValueUseScript && valueID <= CSSValueResetSize)
561             || (valueID >= CSSValueCentral && valueID <= CSSValueMathematical);
562     case CSSPropertyEmptyCells: // show | hide
563         return valueID == CSSValueShow || valueID == CSSValueHide;
564     case CSSPropertyFloat: // left | right | none
565         return valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueNone;
566     case CSSPropertyFontStyle: // normal | italic | oblique
567         return valueID == CSSValueNormal || valueID == CSSValueItalic || valueID == CSSValueOblique;
568     case CSSPropertyFontStretch: // normal | ultra-condensed | extra-condensed | condensed | semi-condensed | semi-expanded | expanded | extra-expanded | ultra-expanded
569         return valueID == CSSValueNormal || (valueID >= CSSValueUltraCondensed && valueID <= CSSValueUltraExpanded);
570     case CSSPropertyImageRendering: // auto | optimizeContrast | pixelated | optimizeSpeed | crispEdges | optimizeQuality | webkit-crispEdges
571         return valueID == CSSValueAuto || valueID == CSSValueOptimizespeed || valueID == CSSValueOptimizequality || valueID == CSSValueWebkitCrispEdges || valueID == CSSValueWebkitOptimizeContrast || valueID == CSSValueCrispEdges || valueID == CSSValuePixelated;
572 #if ENABLE(CSS_COMPOSITING)
573     case CSSPropertyIsolation: // auto | isolate
574         return valueID == CSSValueAuto || valueID == CSSValueIsolate;
575 #endif
576     case CSSPropertyListStylePosition: // inside | outside
577         return valueID == CSSValueInside || valueID == CSSValueOutside;
578     case CSSPropertyListStyleType:
579         // See section CSS_PROP_LIST_STYLE_TYPE of file CSSValueKeywords.in
580         // for the list of supported list-style-types.
581         return (valueID >= CSSValueDisc && valueID <= CSSValueKatakanaIroha) || valueID == CSSValueNone;
582     case CSSPropertyMaskType:
583         return valueID == CSSValueLuminance || valueID == CSSValueAlpha;
584     case CSSPropertyObjectFit:
585         return valueID == CSSValueFill || valueID == CSSValueContain || valueID == CSSValueCover || valueID == CSSValueNone || valueID == CSSValueScaleDown;
586     case CSSPropertyOutlineStyle: // (<border-style> except hidden) | auto
587         return valueID == CSSValueAuto || valueID == CSSValueNone || (valueID >= CSSValueInset && valueID <= CSSValueDouble);
588     // FIXME-NEWPARSER: Support?
589     // case CSSPropertyOverflowAnchor:
590     //    return valueID == CSSValueVisible || valueID == CSSValueNone || valueID == CSSValueAuto;
591     case CSSPropertyOverflowWrap: // normal | break-word
592     case CSSPropertyWordWrap:
593         return valueID == CSSValueNormal || valueID == CSSValueBreakWord;
594     case CSSPropertyOverflowX: // visible | hidden | scroll | auto | overlay
595         return valueID == CSSValueVisible || valueID == CSSValueHidden || valueID == CSSValueScroll || valueID == CSSValueAuto || valueID == CSSValueOverlay;
596     case CSSPropertyOverflowY: // visible | hidden | scroll | auto | overlay | -webkit-paged-x | -webkit-paged-y
597         return valueID == CSSValueVisible || valueID == CSSValueHidden || valueID == CSSValueScroll || valueID == CSSValueAuto || valueID == CSSValueOverlay || valueID == CSSValueWebkitPagedX || valueID == CSSValueWebkitPagedY;
598     case CSSPropertyBreakAfter:
599     case CSSPropertyBreakBefore:
600         return valueID == CSSValueAuto || valueID == CSSValueAvoid || valueID == CSSValueAvoidPage || valueID == CSSValuePage || valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueRecto || valueID == CSSValueVerso || valueID == CSSValueAvoidColumn || valueID == CSSValueColumn
601 #if ENABLE(CSS_REGIONS)
602             || valueID == CSSValueRegion || valueID == CSSValueAvoidRegion
603 #endif
604         ;
605     case CSSPropertyBreakInside:
606         return valueID == CSSValueAuto || valueID == CSSValueAvoid || valueID == CSSValueAvoidPage || valueID == CSSValueAvoidColumn
607 #if ENABLE(CSS_REGIONS)
608             || valueID == CSSValueAvoidRegion
609 #endif
610         ;
611     case CSSPropertyPointerEvents:
612         // none | visiblePainted | visibleFill | visibleStroke | visible |
613         // painted | fill | stroke | auto | all | bounding-box
614         return valueID == CSSValueVisible || valueID == CSSValueNone || valueID == CSSValueAll || valueID == CSSValueAuto || (valueID >= CSSValueVisiblepainted && valueID <= CSSValueStroke);
615     case CSSPropertyPosition: // static | relative | absolute | fixed | sticky
616         return valueID == CSSValueStatic || valueID == CSSValueRelative || valueID == CSSValueAbsolute || valueID == CSSValueFixed || valueID == CSSValueWebkitSticky;
617     case CSSPropertyResize: // none | both | horizontal | vertical | auto
618         return valueID == CSSValueNone || valueID == CSSValueBoth || valueID == CSSValueHorizontal || valueID == CSSValueVertical || valueID == CSSValueAuto;
619     // FIXME-NEWPARSER: Investigate this property.
620     // case CSSPropertyScrollBehavior: // auto | smooth
621     //     ASSERT(RuntimeEnabledFeatures::cssomSmoothScrollEnabled());
622     //   return valueID == CSSValueAuto || valueID == CSSValueSmooth;
623     case CSSPropertyShapeRendering:
624         return valueID == CSSValueAuto || valueID == CSSValueOptimizespeed || valueID == CSSValueCrispedges || valueID == CSSValueGeometricprecision;
625     case CSSPropertySpeak: // none | normal | spell-out | digits | literal-punctuation | no-punctuation
626         return valueID == CSSValueNone || valueID == CSSValueNormal || valueID == CSSValueSpellOut || valueID == CSSValueDigits || valueID == CSSValueLiteralPunctuation || valueID == CSSValueNoPunctuation;
627     case CSSPropertyStrokeLinejoin:
628         return valueID == CSSValueMiter || valueID == CSSValueRound || valueID == CSSValueBevel;
629     case CSSPropertyStrokeLinecap:
630         return valueID == CSSValueButt || valueID == CSSValueRound || valueID == CSSValueSquare;
631     case CSSPropertyTableLayout: // auto | fixed
632         return valueID == CSSValueAuto || valueID == CSSValueFixed;
633     case CSSPropertyTextAlign:
634         return (valueID >= CSSValueWebkitAuto && valueID <= CSSValueWebkitMatchParent) || valueID == CSSValueStart || valueID == CSSValueEnd;
635 #if ENABLE(CSS3_TEXT)
636     case CSSPropertyWebkitTextAlignLast:
637         // auto | start | end | left | right | center | justify
638         return (valueID >= CSSValueLeft && valueID <= CSSValueJustify) || valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueAuto;
639 #endif
640     case CSSPropertyTextAnchor:
641         return valueID == CSSValueStart || valueID == CSSValueMiddle || valueID == CSSValueEnd;
642 // FIXME-NEWPARSER: Support
643 //    case CSSPropertyTextCombineUpright:
644 //        return valueID == CSSValueNone || valueID == CSSValueAll;
645     case CSSPropertyWebkitTextDecorationStyle:
646         // solid | double | dotted | dashed | wavy
647         return valueID == CSSValueSolid || valueID == CSSValueDouble || valueID == CSSValueDotted || valueID == CSSValueDashed || valueID == CSSValueWavy;
648 #if ENABLE(CSS3_TEXT)
649     case CSSPropertyWebkitTextJustify:
650         // auto | none | inter-word | distribute
651         return valueID == CSSValueInterWord || valueID == CSSValueDistribute || valueID == CSSValueAuto || valueID == CSSValueNone;
652 #endif
653     case CSSPropertyWebkitTextOrientation: // mixed | upright | sideways | sideways-right
654         return valueID == CSSValueMixed || valueID == CSSValueUpright || valueID == CSSValueSideways || valueID == CSSValueSidewaysRight;
655     case CSSPropertyTextOverflow: // clip | ellipsis
656         return valueID == CSSValueClip || valueID == CSSValueEllipsis;
657     case CSSPropertyTextRendering: // auto | optimizeSpeed | optimizeLegibility | geometricPrecision
658         return valueID == CSSValueAuto || valueID == CSSValueOptimizespeed || valueID == CSSValueOptimizelegibility || valueID == CSSValueGeometricprecision;
659     case CSSPropertyTextTransform: // capitalize | uppercase | lowercase | none
660         return (valueID >= CSSValueCapitalize && valueID <= CSSValueLowercase) || valueID == CSSValueNone;
661     case CSSPropertyUnicodeBidi:
662         return valueID == CSSValueNormal || valueID == CSSValueEmbed
663             || valueID == CSSValueBidiOverride || valueID == CSSValueWebkitIsolate
664             || valueID == CSSValueWebkitIsolateOverride || valueID == CSSValueWebkitPlaintext;
665     case CSSPropertyVectorEffect:
666         return valueID == CSSValueNone || valueID == CSSValueNonScalingStroke;
667     case CSSPropertyVisibility: // visible | hidden | collapse
668         return valueID == CSSValueVisible || valueID == CSSValueHidden || valueID == CSSValueCollapse;
669     case CSSPropertyWebkitAppearance:
670         return (valueID >= CSSValueCheckbox && valueID <= CSSValueCapsLockIndicator) || valueID == CSSValueNone;
671     case CSSPropertyWebkitBackfaceVisibility:
672         return valueID == CSSValueVisible || valueID == CSSValueHidden;
673 #if ENABLE(CSS_COMPOSITING)
674     case CSSPropertyMixBlendMode:
675         return valueID == CSSValueNormal || valueID == CSSValueMultiply || valueID == CSSValueScreen || valueID == CSSValueOverlay
676             || valueID == CSSValueDarken || valueID == CSSValueLighten || valueID == CSSValueColorDodge || valueID == CSSValueColorBurn
677             || valueID == CSSValueHardLight || valueID == CSSValueSoftLight || valueID == CSSValueDifference || valueID == CSSValueExclusion
678             || valueID == CSSValueHue || valueID == CSSValueSaturation || valueID == CSSValueColor || valueID == CSSValueLuminosity || valueID == CSSValuePlusDarker || valueID == CSSValuePlusLighter;
679 #endif
680     case CSSPropertyWebkitBoxAlign:
681         return valueID == CSSValueStretch || valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueCenter || valueID == CSSValueBaseline;
682 #if ENABLE(CSS_BOX_DECORATION_BREAK)
683     case CSSPropertyWebkitBoxDecorationBreak:
684         return valueID == CSSValueClone || valueID == CSSValueSlice;
685     case CSSPropertyWebkitBoxDirection:
686         return valueID == CSSValueNormal || valueID == CSSValueReverse;
687 #endif
688     case CSSPropertyWebkitBoxLines:
689         return valueID == CSSValueSingle || valueID == CSSValueMultiple;
690     case CSSPropertyWebkitBoxOrient:
691         return valueID == CSSValueHorizontal || valueID == CSSValueVertical || valueID == CSSValueInlineAxis || valueID == CSSValueBlockAxis;
692     case CSSPropertyWebkitBoxPack:
693         return valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueCenter || valueID == CSSValueJustify;
694 #if ENABLE(CURSOR_VISIBILITY)
695     case CSSPropertyWebkitCursorVisibility:
696         return valueID == CSSValueAuto || valueID == CSSValueAutoHide;
697 #endif
698     case CSSPropertyColumnFill:
699         return valueID == CSSValueAuto || valueID == CSSValueBalance;
700     case CSSPropertyWebkitColumnAxis:
701         return valueID == CSSValueHorizontal || valueID == CSSValueVertical || valueID == CSSValueAuto;
702     case CSSPropertyWebkitColumnProgression:
703         return valueID == CSSValueNormal || valueID == CSSValueReverse;
704     case CSSPropertyAlignContent:
705         // FIXME: Per CSS alignment, this property should accept an optional <overflow-position>. We should share this parsing code with 'justify-self'.
706         return valueID == CSSValueFlexStart || valueID == CSSValueFlexEnd || valueID == CSSValueCenter || valueID == CSSValueSpaceBetween || valueID == CSSValueSpaceAround || valueID == CSSValueStretch;
707     case CSSPropertyAlignItems:
708         // FIXME: Per CSS alignment, this property should accept the same arguments as 'justify-self' so we should share its parsing code.
709         return valueID == CSSValueFlexStart || valueID == CSSValueFlexEnd || valueID == CSSValueCenter || valueID == CSSValueBaseline || valueID == CSSValueStretch;
710     case CSSPropertyAlignSelf:
711         // FIXME: Per CSS alignment, this property should accept the same arguments as 'justify-self' so we should share its parsing code.
712         return valueID == CSSValueAuto || valueID == CSSValueFlexStart || valueID == CSSValueFlexEnd || valueID == CSSValueCenter || valueID == CSSValueBaseline || valueID == CSSValueStretch;
713     case CSSPropertyFlexDirection:
714         return valueID == CSSValueRow || valueID == CSSValueRowReverse || valueID == CSSValueColumn || valueID == CSSValueColumnReverse;
715     case CSSPropertyFlexWrap:
716         return valueID == CSSValueNowrap || valueID == CSSValueWrap || valueID == CSSValueWrapReverse;
717     case CSSPropertyWebkitHyphens:
718         return valueID == CSSValueAuto || valueID == CSSValueNone || valueID == CSSValueManual;
719     case CSSPropertyJustifyContent:
720         // FIXME: Per CSS alignment, this property should accept an optional <overflow-position>. We should share this parsing code with 'justify-self'.
721         return valueID == CSSValueFlexStart || valueID == CSSValueFlexEnd || valueID == CSSValueCenter || valueID == CSSValueSpaceBetween || valueID == CSSValueSpaceAround;
722     case CSSPropertyWebkitFontKerning:
723         return valueID == CSSValueAuto || valueID == CSSValueNormal || valueID == CSSValueNone;
724     case CSSPropertyWebkitFontSmoothing:
725         return valueID == CSSValueAuto || valueID == CSSValueNone || valueID == CSSValueAntialiased || valueID == CSSValueSubpixelAntialiased;
726     case CSSPropertyWebkitLineAlign:
727         return valueID == CSSValueNone || valueID == CSSValueEdges;
728     case CSSPropertyWebkitLineBreak: // auto | loose | normal | strict | after-white-space
729         return valueID == CSSValueAuto || valueID == CSSValueLoose || valueID == CSSValueNormal || valueID == CSSValueStrict || valueID == CSSValueAfterWhiteSpace;
730     case CSSPropertyWebkitLineSnap:
731         return valueID == CSSValueNone || valueID == CSSValueBaseline || valueID == CSSValueContain;
732     case CSSPropertyWebkitMarginAfterCollapse:
733     case CSSPropertyWebkitMarginBeforeCollapse:
734     case CSSPropertyWebkitMarginBottomCollapse:
735     case CSSPropertyWebkitMarginTopCollapse:
736         return valueID == CSSValueCollapse || valueID == CSSValueSeparate || valueID == CSSValueDiscard;
737     case CSSPropertyWebkitPrintColorAdjust:
738         return valueID == CSSValueExact || valueID == CSSValueEconomy;
739     case CSSPropertyWebkitRtlOrdering:
740         return valueID == CSSValueLogical || valueID == CSSValueVisual;
741     case CSSPropertyWebkitRubyPosition:
742         return valueID == CSSValueBefore || valueID == CSSValueAfter || valueID == CSSValueInterCharacter;
743     case CSSPropertyWebkitTextCombine:
744         return valueID == CSSValueNone || valueID == CSSValueHorizontal;
745     case CSSPropertyWebkitTextSecurity: // disc | circle | square | none
746         return valueID == CSSValueDisc || valueID == CSSValueCircle || valueID == CSSValueSquare || valueID == CSSValueNone;
747     case CSSPropertyTransformStyle:
748     case CSSPropertyWebkitTransformStyle:
749         return valueID == CSSValueFlat || valueID == CSSValuePreserve3d;
750     case CSSPropertyWebkitUserDrag: // auto | none | element
751         return valueID == CSSValueAuto || valueID == CSSValueNone || valueID == CSSValueElement;
752     case CSSPropertyWebkitUserModify: // read-only | read-write
753         if (valueID == CSSValueReadOnly || valueID == CSSValueReadWrite || valueID == CSSValueReadWritePlaintextOnly) {
754             if (styleSheetContents)
755                 styleSheetContents->parserSetUsesStyleBasedEditability();
756             return true;
757         }
758         return false;
759     case CSSPropertyWebkitUserSelect: // auto | none | text | all
760         if (valueID == CSSValueAuto || valueID == CSSValueNone || valueID == CSSValueText)
761             return true;
762         if (valueID == CSSValueAll) {
763             if (styleSheetContents)
764                 styleSheetContents->parserSetUsesStyleBasedEditability();
765             return true;
766         }
767         return false;
768     case CSSPropertyWritingMode:
769         // Note that horizontal-bt is not supported by the unprefixed version of
770         // the property, only by the -webkit- version.
771         return (valueID >= CSSValueHorizontalTb && valueID <= CSSValueHorizontalBt)
772             || valueID == CSSValueLrTb || valueID == CSSValueRlTb || valueID == CSSValueTbRl
773             || valueID == CSSValueLr || valueID == CSSValueRl || valueID == CSSValueTb;
774     case CSSPropertyWhiteSpace: // normal | pre | nowrap
775         return valueID == CSSValueNormal || valueID == CSSValuePre || valueID == CSSValuePreWrap || valueID == CSSValuePreLine || valueID == CSSValueNowrap;
776     case CSSPropertyWordBreak: // normal | break-all | keep-all | break-word (this is a custom extension)
777         return valueID == CSSValueNormal || valueID == CSSValueBreakAll || valueID == CSSValueKeepAll || valueID == CSSValueBreakWord;
778     case CSSPropertyWebkitBorderFit:
779         return valueID == CSSValueBorder || valueID == CSSValueLines;
780 #if ENABLE(CSS_REGIONS)
781     case CSSPropertyWebkitRegionFragment:
782         return valueID == CSSValueAuto || valueID == CSSValueBreak;
783 #endif
784 #if ENABLE(CSS_SCROLL_SNAP)
785     case CSSPropertyWebkitScrollSnapType: // none | mandatory | proximity
786         return valueID == CSSValueNone || valueID == CSSValueMandatory || valueID == CSSValueProximity;
787 #endif
788 #if ENABLE(TOUCH_EVENTS)
789     case CSSPropertyTouchAction: // auto | manipulation
790         return valueID == CSSValueAuto || valueID == CSSValueManipulation;
791 #endif
792 #if ENABLE(CSS_TRAILING_WORD)
793     case CSSPropertyAppleTrailingWord: // auto | -apple-partially-balanced
794         return valueID == CSSValueAuto || valueID == CSSValueWebkitPartiallyBalanced;
795 #endif
796 #if ENABLE(APPLE_PAY)
797     case CSSPropertyApplePayButtonStyle: // white | white-outline | black
798         return valueID == CSSValueWhite || valueID == CSSValueWhiteOutline || valueID == CSSValueBlack;
799     case CSSPropertyApplePayButtonType: // plain | buy | set-up | donate
800         return valueID == CSSValuePlain || valueID == CSSValueBuy || valueID == CSSValueSetUp || valueID == CSSValueDonate;
801 #endif
802     case CSSPropertyWebkitNbspMode: // normal | space
803         return valueID == CSSValueNormal || valueID == CSSValueSpace;
804     case CSSPropertyWebkitTextZoom:
805         return valueID == CSSValueNormal || valueID == CSSValueReset;
806 #if PLATFORM(IOS)
807     // Apple specific property. These will never be standardized and is purely to
808     // support custom WebKit-based Apple applications.
809     case CSSPropertyWebkitTouchCallout:
810         return valueID == CSSValueDefault || valueID == CSSValueNone;
811 #endif
812     case CSSPropertyWebkitMarqueeDirection:
813         return valueID == CSSValueForwards || valueID == CSSValueBackwards || valueID == CSSValueAhead || valueID == CSSValueReverse || valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueDown
814             || valueID == CSSValueUp || valueID == CSSValueAuto;
815     case CSSPropertyWebkitMarqueeStyle:
816         return valueID == CSSValueNone || valueID == CSSValueSlide || valueID == CSSValueScroll || valueID == CSSValueAlternate;
817     case CSSPropertyFontVariantPosition: // normal | sub | super
818         return valueID == CSSValueNormal || valueID == CSSValueSub || valueID == CSSValueSuper;
819     case CSSPropertyFontVariantCaps: // normal | small-caps | all-small-caps | petite-caps | all-petite-caps | unicase | titling-caps
820         return valueID == CSSValueNormal || valueID == CSSValueSmallCaps || valueID == CSSValueAllSmallCaps || valueID == CSSValuePetiteCaps || valueID == CSSValueAllPetiteCaps || valueID == CSSValueUnicase || valueID == CSSValueTitlingCaps;
821     case CSSPropertyFontVariantAlternates: // We only support the normal and historical-forms values.
822         return valueID == CSSValueNormal || valueID == CSSValueHistoricalForms;
823 #if ENABLE(ACCELERATED_OVERFLOW_SCROLLING)
824     case CSSPropertyWebkitOverflowScrolling:
825         return valueID == CSSValueAuto || valueID == CSSValueTouch;
826 #endif
827     default:
828         ASSERT_NOT_REACHED();
829         return false;
830     }
831 }
832
833 bool CSSParserFastPaths::isKeywordPropertyID(CSSPropertyID propertyId)
834 {
835     switch (propertyId) {
836     case CSSPropertyBorderBottomStyle:
837     case CSSPropertyBorderCollapse:
838     case CSSPropertyBorderLeftStyle:
839     case CSSPropertyBorderRightStyle:
840     case CSSPropertyBorderTopStyle:
841     case CSSPropertyBoxSizing:
842     case CSSPropertyBreakAfter:
843     case CSSPropertyBreakBefore:
844     case CSSPropertyBreakInside:
845     case CSSPropertyCaptionSide:
846     case CSSPropertyClear:
847     case CSSPropertyColumnFill:
848     case CSSPropertyWebkitColumnProgression:
849     case CSSPropertyColumnRuleStyle:
850     case CSSPropertyDirection:
851     case CSSPropertyDisplay:
852     case CSSPropertyEmptyCells:
853     case CSSPropertyFlexDirection:
854     case CSSPropertyFlexWrap:
855     case CSSPropertyFloat:
856     case CSSPropertyFontStretch:
857     case CSSPropertyFontStyle:
858     case CSSPropertyFontVariantAlternates:
859     case CSSPropertyFontVariantCaps:
860     case CSSPropertyFontVariantPosition:
861     case CSSPropertyImageRendering:
862     case CSSPropertyListStylePosition:
863     case CSSPropertyListStyleType:
864     case CSSPropertyObjectFit:
865     case CSSPropertyOutlineStyle:
866     case CSSPropertyOverflowWrap:
867     case CSSPropertyOverflowX:
868     case CSSPropertyOverflowY:
869     case CSSPropertyPointerEvents:
870     case CSSPropertyPosition:
871     case CSSPropertyResize:
872     case CSSPropertySpeak:
873     case CSSPropertyTableLayout:
874     case CSSPropertyTextAlign:
875     case CSSPropertyTextLineThroughMode:
876     case CSSPropertyTextLineThroughStyle:
877     case CSSPropertyTextOverflow:
878     case CSSPropertyTextOverlineMode:
879     case CSSPropertyTextOverlineStyle:
880     case CSSPropertyTextRendering:
881     case CSSPropertyTextTransform:
882     case CSSPropertyTextUnderlineMode:
883     case CSSPropertyTextUnderlineStyle:
884     case CSSPropertyTransformStyle:
885     case CSSPropertyUnicodeBidi:
886     case CSSPropertyVisibility:
887     case CSSPropertyWebkitAppearance:
888     case CSSPropertyWebkitBackfaceVisibility:
889     case CSSPropertyWebkitBorderAfterStyle:
890     case CSSPropertyWebkitBorderBeforeStyle:
891     case CSSPropertyWebkitBorderEndStyle:
892     case CSSPropertyWebkitBorderFit:
893     case CSSPropertyWebkitBorderStartStyle:
894     case CSSPropertyWebkitBoxAlign:
895     case CSSPropertyWebkitBoxDirection:
896     case CSSPropertyWebkitBoxLines:
897     case CSSPropertyWebkitBoxOrient:
898     case CSSPropertyWebkitBoxPack:
899     case CSSPropertyWebkitColumnAxis:
900     case CSSPropertyWebkitFontKerning:
901     case CSSPropertyWebkitFontSmoothing:
902     case CSSPropertyWebkitHyphens:
903     case CSSPropertyWebkitLineAlign:
904     case CSSPropertyWebkitLineBreak:
905     case CSSPropertyWebkitLineSnap:
906     case CSSPropertyWebkitMarginAfterCollapse:
907     case CSSPropertyWebkitMarginBeforeCollapse:
908     case CSSPropertyWebkitMarginBottomCollapse:
909     case CSSPropertyWebkitMarginTopCollapse:
910     case CSSPropertyWebkitMarqueeDirection:
911     case CSSPropertyWebkitMarqueeStyle:
912     case CSSPropertyWebkitNbspMode:
913     case CSSPropertyWebkitPrintColorAdjust:
914     case CSSPropertyWebkitRtlOrdering:
915     case CSSPropertyWebkitRubyPosition:
916     case CSSPropertyWebkitTextCombine:
917     case CSSPropertyWebkitTextDecorationStyle:
918     case CSSPropertyWebkitTextOrientation:
919     case CSSPropertyWebkitTextSecurity:
920     case CSSPropertyWebkitTextZoom:
921     case CSSPropertyWebkitTransformStyle:
922     case CSSPropertyWebkitUserDrag:
923     case CSSPropertyWebkitUserModify:
924     case CSSPropertyWebkitUserSelect:
925     case CSSPropertyWhiteSpace:
926     case CSSPropertyWordBreak:
927     case CSSPropertyWordWrap:
928
929     // SVG CSS properties from SVG 1.1, Appendix N: Property Index.
930     case CSSPropertyAlignmentBaseline:
931     case CSSPropertyBufferedRendering:
932     case CSSPropertyClipRule:
933     case CSSPropertyColorInterpolation:
934     case CSSPropertyColorInterpolationFilters:
935     case CSSPropertyColorRendering:
936     case CSSPropertyDominantBaseline:
937     case CSSPropertyFillRule:
938     case CSSPropertyMaskType:
939     case CSSPropertyShapeRendering:
940     case CSSPropertyStrokeLinecap:
941     case CSSPropertyStrokeLinejoin:
942     case CSSPropertyTextAnchor:
943     case CSSPropertyVectorEffect:
944     case CSSPropertyWritingMode:
945
946     // FIXME-NEWPARSER: Treat all as a keyword property.
947     // case CSSPropertyAll:
948
949     // FIXME-NEWPARSER: Treat the following properties as keyword properties:
950     // case CSSPropertyBackgroundRepeatX:
951     // case CSSPropertyBackgroundRepeatY:
952
953     // FIXME-NEWPARSER: Add the following unprefixed properties:
954     // case CSSPropertyBackfaceVisibility:
955     // case CSSPropertyFontKerning:
956     // case CSSPropertyHyphens:
957     // case CSSPropertyOverflowAnchor:
958     // case CSSPropertyScrollBehavior:
959     // case CSSPropertyScrollSnapType:
960     // case CSSPropertyTextAlignLast:
961     // case CSSPropertyTextCombineUpright:
962     // case CSSPropertyTextDecorationStyle:
963     // case CSSPropertyTextJustify:
964     // case CSSPropertyTextOrientation:
965     // case CSSPropertyUserSelect:
966 #if ENABLE(CSS_TRAILING_WORD)
967     case CSSPropertyAppleTrailingWord:
968 #endif
969 #if ENABLE(CSS_COMPOSITING)
970     case CSSPropertyIsolation:
971     case CSSPropertyMixBlendMode:
972 #endif
973 #if ENABLE(TOUCH_EVENTS)
974     case CSSPropertyTouchAction:
975 #endif
976 #if ENABLE(CSS_BOX_DECORATION_BREAK)
977     case CSSPropertyWebkitBoxDecorationBreak:
978 #endif
979 #if ENABLE(CURSOR_VISIBILITY)
980     case CSSPropertyWebkitCursorVisibility:
981 #endif
982 #if ENABLE(ACCELERATED_OVERFLOW_SCROLLING)
983     case CSSPropertyWebkitOverflowScrolling:
984 #endif
985 #if ENABLE(CSS_REGIONS)
986     case CSSPropertyWebkitRegionFragment:
987 #endif
988 #if ENABLE(CSS3_TEXT)
989     case CSSPropertyWebkitTextAlignLast:
990     case CSSPropertyWebkitTextJustify:
991 #endif
992 #if PLATFORM(IOS)
993     // Apple specific property. This will never be standardized and is purely to
994     // support custom WebKit-based Apple applications.
995     case CSSPropertyWebkitTouchCallout:
996 #endif
997 #if ENABLE(CSS_SCROLL_SNAP)
998     case CSSPropertyWebkitScrollSnapType:
999 #endif
1000 #if ENABLE(APPLE_PAY)
1001     case CSSPropertyApplePayButtonStyle:
1002     case CSSPropertyApplePayButtonType:
1003 #endif
1004         return true;
1005     case CSSPropertyJustifyContent:
1006     case CSSPropertyAlignContent:
1007     case CSSPropertyAlignItems:
1008     case CSSPropertyAlignSelf:
1009 #if ENABLE(CSS_GRID_LAYOUT)
1010         return !RuntimeEnabledFeatures::sharedFeatures().isCSSGridLayoutEnabled();
1011 #else
1012         return true;
1013 #endif
1014     default:
1015         return false;
1016     }
1017 }
1018
1019 static bool isUniversalKeyword(const String& string)
1020 {
1021     // These keywords can be used for all properties.
1022     return equalLettersIgnoringASCIICase(string, "initial")
1023     || equalLettersIgnoringASCIICase(string, "inherit")
1024     || equalLettersIgnoringASCIICase(string, "unset")
1025     || equalLettersIgnoringASCIICase(string, "revert");
1026 }
1027
1028 static RefPtr<CSSValue> parseKeywordValue(CSSPropertyID propertyId, const String& string, CSSParserMode parserMode, StyleSheetContents* styleSheetContents)
1029 {
1030     ASSERT(!string.isEmpty());
1031
1032     if (!CSSParserFastPaths::isKeywordPropertyID(propertyId)) {
1033         // All properties accept the values of "initial" and "inherit".
1034         if (!isUniversalKeyword(string))
1035             return nullptr;
1036
1037         // Parse initial/inherit shorthands using the CSSPropertyParser.
1038         if (shorthandForProperty(propertyId).length())
1039             return nullptr;
1040
1041         // Descriptors do not support css wide keywords.
1042         if (CSSProperty::isDescriptorOnly(propertyId))
1043             return nullptr;
1044     }
1045
1046     CSSValueID valueID = cssValueKeywordID(string);
1047
1048     if (!valueID)
1049         return nullptr;
1050
1051     if (valueID == CSSValueInherit)
1052         return CSSValuePool::singleton().createInheritedValue();
1053     if (valueID == CSSValueInitial)
1054         return CSSValuePool::singleton().createExplicitInitialValue();
1055     if (valueID == CSSValueUnset)
1056         return CSSValuePool::singleton().createUnsetValue();
1057     if (valueID == CSSValueRevert)
1058         return CSSValuePool::singleton().createRevertValue();
1059     
1060     if (CSSParserFastPaths::isValidKeywordPropertyAndValue(propertyId, valueID, parserMode, styleSheetContents))
1061         return CSSPrimitiveValue::createIdentifier(valueID);
1062     return nullptr;
1063 }
1064
1065 template <typename CharType>
1066 static bool parseTransformTranslateArguments(CharType*& pos, CharType* end, unsigned expectedCount, CSSFunctionValue* transformValue)
1067 {
1068     while (expectedCount) {
1069         size_t delimiter = WTF::find(pos, end - pos, expectedCount == 1 ? ')' : ',');
1070         if (delimiter == notFound)
1071             return false;
1072         unsigned argumentLength = static_cast<unsigned>(delimiter);
1073         CSSPrimitiveValue::UnitType unit = CSSPrimitiveValue::UnitType::CSS_NUMBER;
1074         double number;
1075         if (!parseSimpleLength(pos, argumentLength, unit, number))
1076             return false;
1077         if (!number && unit == CSSPrimitiveValue::CSS_NUMBER)
1078             unit = CSSPrimitiveValue::UnitType::CSS_PX;
1079         if (unit == CSSPrimitiveValue::UnitType::CSS_NUMBER || (unit == CSSPrimitiveValue::UnitType::CSS_PERCENTAGE && (transformValue->name() == CSSValueTranslatez || (transformValue->name() == CSSValueTranslate3d && expectedCount == 1))))
1080             return false;
1081         transformValue->append(CSSPrimitiveValue::create(number, unit));
1082         pos += argumentLength + 1;
1083         --expectedCount;
1084     }
1085     return true;
1086 }
1087
1088 template <typename CharType>
1089 static bool parseTransformNumberArguments(CharType*& pos, CharType* end, unsigned expectedCount, CSSFunctionValue* transformValue)
1090 {
1091     while (expectedCount) {
1092         size_t delimiter = WTF::find(pos, end - pos, expectedCount == 1 ? ')' : ',');
1093         if (delimiter == notFound)
1094             return false;
1095         unsigned argumentLength = static_cast<unsigned>(delimiter);
1096         bool ok;
1097         double number = charactersToDouble(pos, argumentLength, &ok);
1098         if (!ok)
1099             return false;
1100         transformValue->append(CSSPrimitiveValue::create(number, CSSPrimitiveValue::UnitType::CSS_NUMBER));
1101         pos += argumentLength + 1;
1102         --expectedCount;
1103     }
1104     return true;
1105 }
1106
1107 static const int kShortestValidTransformStringLength = 12;
1108
1109 template <typename CharType>
1110 static RefPtr<CSSFunctionValue> parseSimpleTransformValue(CharType*& pos, CharType* end)
1111 {
1112     if (end - pos < kShortestValidTransformStringLength)
1113         return nullptr;
1114
1115     const bool isTranslate = toASCIILower(pos[0]) == 't'
1116         && toASCIILower(pos[1]) == 'r'
1117         && toASCIILower(pos[2]) == 'a'
1118         && toASCIILower(pos[3]) == 'n'
1119         && toASCIILower(pos[4]) == 's'
1120         && toASCIILower(pos[5]) == 'l'
1121         && toASCIILower(pos[6]) == 'a'
1122         && toASCIILower(pos[7]) == 't'
1123         && toASCIILower(pos[8]) == 'e';
1124
1125     if (isTranslate) {
1126         CSSValueID transformType;
1127         unsigned expectedArgumentCount = 1;
1128         unsigned argumentStart = 11;
1129         CharType c9 = toASCIILower(pos[9]);
1130         if (c9 == 'x' && pos[10] == '(') {
1131             transformType = CSSValueTranslatex;
1132         } else if (c9 == 'y' && pos[10] == '(') {
1133             transformType = CSSValueTranslatey;
1134         } else if (c9 == 'z' && pos[10] == '(') {
1135             transformType = CSSValueTranslatez;
1136         } else if (c9 == '(') {
1137             transformType = CSSValueTranslate;
1138             expectedArgumentCount = 2;
1139             argumentStart = 10;
1140         } else if (c9 == '3' && toASCIILower(pos[10]) == 'd' && pos[11] == '(') {
1141             transformType = CSSValueTranslate3d;
1142             expectedArgumentCount = 3;
1143             argumentStart = 12;
1144         } else {
1145             return nullptr;
1146         }
1147         pos += argumentStart;
1148         RefPtr<CSSFunctionValue> transformValue = CSSFunctionValue::create(transformType);
1149         if (!parseTransformTranslateArguments(pos, end, expectedArgumentCount, transformValue.get()))
1150             return nullptr;
1151         return transformValue;
1152     }
1153
1154     const bool isMatrix3d = toASCIILower(pos[0]) == 'm'
1155         && toASCIILower(pos[1]) == 'a'
1156         && toASCIILower(pos[2]) == 't'
1157         && toASCIILower(pos[3]) == 'r'
1158         && toASCIILower(pos[4]) == 'i'
1159         && toASCIILower(pos[5]) == 'x'
1160         && pos[6] == '3'
1161         && toASCIILower(pos[7]) == 'd'
1162         && pos[8] == '(';
1163
1164     if (isMatrix3d) {
1165         pos += 9;
1166         RefPtr<CSSFunctionValue> transformValue = CSSFunctionValue::create(CSSValueMatrix3d);
1167         if (!parseTransformNumberArguments(pos, end, 16, transformValue.get()))
1168             return nullptr;
1169         return transformValue;
1170     }
1171
1172     const bool isScale3d = toASCIILower(pos[0]) == 's'
1173         && toASCIILower(pos[1]) == 'c'
1174         && toASCIILower(pos[2]) == 'a'
1175         && toASCIILower(pos[3]) == 'l'
1176         && toASCIILower(pos[4]) == 'e'
1177         && pos[5] == '3'
1178         && toASCIILower(pos[6]) == 'd'
1179         && pos[7] == '(';
1180
1181     if (isScale3d) {
1182         pos += 8;
1183         RefPtr<CSSFunctionValue> transformValue = CSSFunctionValue::create(CSSValueScale3d);
1184         if (!parseTransformNumberArguments(pos, end, 3, transformValue.get()))
1185             return nullptr;
1186         return transformValue;
1187     }
1188
1189     return nullptr;
1190 }
1191
1192 template <typename CharType>
1193 static bool transformCanLikelyUseFastPath(const CharType* chars, unsigned length)
1194 {
1195     // Very fast scan that attempts to reject most transforms that couldn't
1196     // take the fast path. This avoids doing the malloc and string->double
1197     // conversions in parseSimpleTransformValue only to discard them when we
1198     // run into a transform component we don't understand.
1199     unsigned i = 0;
1200     while (i < length) {
1201         if (isCSSSpace(chars[i])) {
1202             ++i;
1203             continue;
1204         }
1205         if (length - i < kShortestValidTransformStringLength)
1206             return false;
1207         switch (toASCIILower(chars[i])) {
1208         case 't':
1209             // translate, translateX, translateY, translateZ, translate3d.
1210             if (toASCIILower(chars[i + 8]) != 'e')
1211                 return false;
1212             i += 9;
1213             break;
1214         case 'm':
1215             // matrix3d.
1216             if (toASCIILower(chars[i + 7]) != 'd')
1217                 return false;
1218             i += 8;
1219             break;
1220         case 's':
1221             // scale3d.
1222             if (toASCIILower(chars[i + 6]) != 'd')
1223                 return false;
1224             i += 7;
1225             break;
1226         default:
1227             // All other things, ex. rotate.
1228             return false;
1229         }
1230         size_t argumentsEnd = WTF::find(chars, length, ')', i);
1231         if (argumentsEnd == notFound)
1232             return false;
1233         // Advance to the end of the arguments.
1234         i = argumentsEnd + 1;
1235     }
1236     return i == length;
1237 }
1238
1239 template <typename CharType>
1240 static RefPtr<CSSValueList> parseSimpleTransformList(const CharType* chars, unsigned length)
1241 {
1242     if (!transformCanLikelyUseFastPath(chars, length))
1243         return nullptr;
1244     const CharType*& pos = chars;
1245     const CharType* end = chars + length;
1246     RefPtr<CSSValueList> transformList;
1247     while (pos < end) {
1248         while (pos < end && isCSSSpace(*pos))
1249             ++pos;
1250         if (pos >= end)
1251             break;
1252         RefPtr<CSSFunctionValue> transformValue = parseSimpleTransformValue(pos, end);
1253         if (!transformValue)
1254             return nullptr;
1255         if (!transformList)
1256             transformList = CSSValueList::createSpaceSeparated();
1257         transformList->append(*transformValue);
1258     }
1259     return transformList;
1260 }
1261
1262 static RefPtr<CSSValue> parseSimpleTransform(CSSPropertyID propertyID, const String& string)
1263 {
1264     ASSERT(!string.isEmpty());
1265
1266     if (propertyID != CSSPropertyTransform)
1267         return nullptr;
1268     if (string.is8Bit())
1269         return parseSimpleTransformList(string.characters8(), string.length());
1270     return parseSimpleTransformList(string.characters16(), string.length());
1271 }
1272
1273 RefPtr<CSSValue> CSSParserFastPaths::maybeParseValue(CSSPropertyID propertyID, const String& string, CSSParserMode parserMode, StyleSheetContents* styleSheetContents)
1274 {
1275     RefPtr<CSSValue> result = parseSimpleLengthValue(propertyID, string, parserMode);
1276     if (result)
1277         return result;
1278     if (isColorPropertyID(propertyID))
1279         return parseColor(string, parserMode);
1280     result = parseKeywordValue(propertyID, string, parserMode, styleSheetContents);
1281     if (result)
1282         return result;
1283     result = parseSimpleTransform(propertyID, string);
1284     if (result)
1285         return result;
1286     return nullptr;
1287 }
1288
1289 } // namespace WebCore