Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / css / parser / BisonCSSParser-in.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, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 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 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 "core/css/parser/BisonCSSParser.h"
29
30 #include "core/CSSValueKeywords.h"
31 #include "core/StylePropertyShorthand.h"
32 #include "core/css/CSSAspectRatioValue.h"
33 #include "core/css/CSSBasicShapes.h"
34 #include "core/css/CSSBorderImage.h"
35 #include "core/css/CSSCanvasValue.h"
36 #include "core/css/CSSCrossfadeValue.h"
37 #include "core/css/CSSCursorImageValue.h"
38 #include "core/css/CSSFontFaceSrcValue.h"
39 #include "core/css/CSSFontFeatureValue.h"
40 #include "core/css/CSSFunctionValue.h"
41 #include "core/css/CSSGradientValue.h"
42 #include "core/css/CSSGridLineNamesValue.h"
43 #include "core/css/CSSGridTemplateAreasValue.h"
44 #include "core/css/CSSImageSetValue.h"
45 #include "core/css/CSSImageValue.h"
46 #include "core/css/CSSInheritedValue.h"
47 #include "core/css/CSSInitialValue.h"
48 #include "core/css/CSSKeyframeRule.h"
49 #include "core/css/CSSKeyframesRule.h"
50 #include "core/css/CSSLineBoxContainValue.h"
51 #include "core/css/CSSPrimitiveValue.h"
52 #include "core/css/CSSPropertySourceData.h"
53 #include "core/css/CSSReflectValue.h"
54 #include "core/css/CSSSelector.h"
55 #include "core/css/CSSShadowValue.h"
56 #include "core/css/CSSStyleSheet.h"
57 #include "core/css/CSSTimingFunctionValue.h"
58 #include "core/css/CSSTransformValue.h"
59 #include "core/css/CSSUnicodeRangeValue.h"
60 #include "core/css/CSSValueList.h"
61 #include "core/css/CSSValuePool.h"
62 #include "core/css/Counter.h"
63 #include "core/css/HashTools.h"
64 #include "core/css/MediaList.h"
65 #include "core/css/MediaQueryExp.h"
66 #include "core/css/Pair.h"
67 #include "core/css/Rect.h"
68 #include "core/css/StylePropertySet.h"
69 #include "core/css/StyleRule.h"
70 #include "core/css/StyleRuleImport.h"
71 #include "core/css/StyleSheetContents.h"
72 #include "core/css/parser/CSSParserIdioms.h"
73 #include "core/dom/Document.h"
74 #include "core/frame/FrameConsole.h"
75 #include "core/frame/FrameHost.h"
76 #include "core/frame/Settings.h"
77 #include "core/frame/UseCounter.h"
78 #include "core/html/parser/HTMLParserIdioms.h"
79 #include "core/inspector/ConsoleMessage.h"
80 #include "core/inspector/InspectorInstrumentation.h"
81 #include "core/rendering/RenderTheme.h"
82 #include "platform/FloatConversion.h"
83 #include "platform/RuntimeEnabledFeatures.h"
84 #include "wtf/BitArray.h"
85 #include "wtf/HexNumber.h"
86 #include "wtf/text/StringBuffer.h"
87 #include "wtf/text/StringBuilder.h"
88 #include "wtf/text/StringImpl.h"
89 #include "wtf/text/TextEncoding.h"
90 #include <limits.h>
91
92 #define YYDEBUG 0
93
94 #if YYDEBUG > 0
95 extern int cssyydebug;
96 #endif
97
98 int cssyyparse(blink::BisonCSSParser*);
99
100 using namespace WTF;
101
102 namespace blink {
103
104 static const unsigned INVALID_NUM_PARSED_PROPERTIES = UINT_MAX;
105
106 BisonCSSParser::BisonCSSParser(const CSSParserContext& context)
107     : m_context(context)
108     , m_important(false)
109     , m_id(CSSPropertyInvalid)
110     , m_styleSheet(nullptr)
111     , m_supportsCondition(false)
112     , m_selectorListForParseSelector(0)
113     , m_numParsedPropertiesBeforeMarginBox(INVALID_NUM_PARSED_PROPERTIES)
114     , m_hadSyntacticallyValidCSSRule(false)
115     , m_logErrors(false)
116     , m_ignoreErrors(false)
117     , m_defaultNamespace(starAtom)
118     , m_observer(0)
119     , m_source(0)
120     , m_ruleHeaderType(CSSRuleSourceData::UNKNOWN_RULE)
121     , m_allowImportRules(true)
122     , m_allowNamespaceDeclarations(true)
123     , m_inViewport(false)
124     , m_tokenizer(*this)
125 {
126 #if YYDEBUG > 0
127     cssyydebug = 1;
128 #endif
129 }
130
131 BisonCSSParser::~BisonCSSParser()
132 {
133     clearProperties();
134
135     deleteAllValues(m_floatingSelectors);
136     deleteAllValues(m_floatingSelectorVectors);
137     deleteAllValues(m_floatingValueLists);
138     deleteAllValues(m_floatingFunctions);
139 }
140
141 void BisonCSSParser::setupParser(const char* prefix, unsigned prefixLength, const String& string, const char* suffix, unsigned suffixLength)
142 {
143     m_tokenizer.setupTokenizer(prefix, prefixLength, string, suffix, suffixLength);
144     m_ruleHasHeader = true;
145 }
146
147 void BisonCSSParser::parseSheet(StyleSheetContents* sheet, const String& string, const TextPosition& startPosition, CSSParserObserver* observer, bool logErrors)
148 {
149     setStyleSheet(sheet);
150     m_defaultNamespace = starAtom; // Reset the default namespace.
151     TemporaryChange<CSSParserObserver*> scopedObsever(m_observer, observer);
152     m_logErrors = logErrors && sheet->singleOwnerDocument() && !sheet->baseURL().isEmpty() && sheet->singleOwnerDocument()->frameHost();
153     m_ignoreErrors = false;
154     m_tokenizer.m_lineNumber = 0;
155     m_startPosition = startPosition;
156     m_source = &string;
157     m_tokenizer.m_internal = false;
158     setupParser("", string, "");
159     cssyyparse(this);
160     sheet->shrinkToFit();
161     m_source = 0;
162     m_rule = nullptr;
163     m_lineEndings.clear();
164     m_ignoreErrors = false;
165     m_logErrors = false;
166     m_tokenizer.m_internal = true;
167 }
168
169 PassRefPtrWillBeRawPtr<StyleRuleBase> BisonCSSParser::parseRule(StyleSheetContents* sheet, const String& string)
170 {
171     setStyleSheet(sheet);
172     m_allowNamespaceDeclarations = false;
173     setupParser("@-internal-rule ", string, "");
174     cssyyparse(this);
175     return m_rule.release();
176 }
177
178 PassRefPtrWillBeRawPtr<StyleKeyframe> BisonCSSParser::parseKeyframeRule(StyleSheetContents* sheet, const String& string)
179 {
180     setStyleSheet(sheet);
181     setupParser("@-internal-keyframe-rule ", string, "");
182     cssyyparse(this);
183     return m_keyframe.release();
184 }
185
186 PassOwnPtr<Vector<double> > BisonCSSParser::parseKeyframeKeyList(const String& string)
187 {
188     setupParser("@-internal-keyframe-key-list ", string, "");
189     cssyyparse(this);
190     ASSERT(m_valueList);
191     return StyleKeyframe::createKeyList(m_valueList.get());
192 }
193
194 bool BisonCSSParser::parseSupportsCondition(const String& string)
195 {
196     m_supportsCondition = false;
197     setupParser("@-internal-supports-condition ", string, "");
198     cssyyparse(this);
199     return m_supportsCondition;
200 }
201
202 static inline bool isColorPropertyID(CSSPropertyID propertyId)
203 {
204     switch (propertyId) {
205     case CSSPropertyColor:
206     case CSSPropertyBackgroundColor:
207     case CSSPropertyBorderBottomColor:
208     case CSSPropertyBorderLeftColor:
209     case CSSPropertyBorderRightColor:
210     case CSSPropertyBorderTopColor:
211     case CSSPropertyOutlineColor:
212     case CSSPropertyWebkitBorderAfterColor:
213     case CSSPropertyWebkitBorderBeforeColor:
214     case CSSPropertyWebkitBorderEndColor:
215     case CSSPropertyWebkitBorderStartColor:
216     case CSSPropertyWebkitColumnRuleColor:
217     case CSSPropertyWebkitTextEmphasisColor:
218     case CSSPropertyWebkitTextFillColor:
219     case CSSPropertyWebkitTextStrokeColor:
220         return true;
221     case CSSPropertyTextDecorationColor:
222         return RuntimeEnabledFeatures::css3TextDecorationsEnabled();
223     default:
224         return false;
225     }
226 }
227
228 static bool parseColorValue(MutableStylePropertySet* declaration, CSSPropertyID propertyId, const String& string, bool important, CSSParserMode cssParserMode)
229 {
230     ASSERT(!string.isEmpty());
231     bool quirksMode = isQuirksModeBehavior(cssParserMode);
232     if (!isColorPropertyID(propertyId))
233         return false;
234     CSSParserString cssString;
235     cssString.init(string);
236     CSSValueID valueID = cssValueKeywordID(cssString);
237     bool validPrimitive = false;
238     if (valueID == CSSValueWebkitText) {
239         validPrimitive = true;
240     } else if (valueID == CSSValueCurrentcolor) {
241         validPrimitive = true;
242     } else if ((valueID >= CSSValueAqua && valueID <= CSSValueWindowtext) || valueID == CSSValueMenu
243         || (quirksMode && valueID >= CSSValueWebkitFocusRingColor && valueID < CSSValueWebkitText)) {
244         validPrimitive = true;
245     }
246
247     if (validPrimitive) {
248         RefPtrWillBeRawPtr<CSSValue> value = cssValuePool().createIdentifierValue(valueID);
249         declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important));
250         return true;
251     }
252     RGBA32 color;
253     if (!CSSPropertyParser::fastParseColor(color, string, !quirksMode && string[0] != '#'))
254         return false;
255     RefPtrWillBeRawPtr<CSSValue> value = cssValuePool().createColorValue(color);
256     declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important));
257     return true;
258 }
259
260 static inline bool isSimpleLengthPropertyID(CSSPropertyID propertyId, bool& acceptsNegativeNumbers)
261 {
262     switch (propertyId) {
263     case CSSPropertyFontSize:
264     case CSSPropertyHeight:
265     case CSSPropertyWidth:
266     case CSSPropertyMinHeight:
267     case CSSPropertyMinWidth:
268     case CSSPropertyPaddingBottom:
269     case CSSPropertyPaddingLeft:
270     case CSSPropertyPaddingRight:
271     case CSSPropertyPaddingTop:
272     case CSSPropertyWebkitLogicalWidth:
273     case CSSPropertyWebkitLogicalHeight:
274     case CSSPropertyWebkitMinLogicalWidth:
275     case CSSPropertyWebkitMinLogicalHeight:
276     case CSSPropertyWebkitPaddingAfter:
277     case CSSPropertyWebkitPaddingBefore:
278     case CSSPropertyWebkitPaddingEnd:
279     case CSSPropertyWebkitPaddingStart:
280         acceptsNegativeNumbers = false;
281         return true;
282     case CSSPropertyShapeMargin:
283         acceptsNegativeNumbers = false;
284         return true;
285     case CSSPropertyBottom:
286     case CSSPropertyLeft:
287     case CSSPropertyMarginBottom:
288     case CSSPropertyMarginLeft:
289     case CSSPropertyMarginRight:
290     case CSSPropertyMarginTop:
291     case CSSPropertyRight:
292     case CSSPropertyTop:
293     case CSSPropertyWebkitMarginAfter:
294     case CSSPropertyWebkitMarginBefore:
295     case CSSPropertyWebkitMarginEnd:
296     case CSSPropertyWebkitMarginStart:
297         acceptsNegativeNumbers = true;
298         return true;
299     default:
300         return false;
301     }
302 }
303
304 template <typename CharacterType>
305 static inline bool parseSimpleLength(const CharacterType* characters, unsigned length, CSSPrimitiveValue::UnitType& unit, double& number)
306 {
307     if (length > 2 && (characters[length - 2] | 0x20) == 'p' && (characters[length - 1] | 0x20) == 'x') {
308         length -= 2;
309         unit = CSSPrimitiveValue::CSS_PX;
310     } else if (length > 1 && characters[length - 1] == '%') {
311         length -= 1;
312         unit = CSSPrimitiveValue::CSS_PERCENTAGE;
313     }
314
315     // We rely on charactersToDouble for validation as well. The function
316     // will set "ok" to "false" if the entire passed-in character range does
317     // not represent a double.
318     bool ok;
319     number = charactersToDouble(characters, length, &ok);
320     return ok;
321 }
322
323 static bool parseSimpleLengthValue(MutableStylePropertySet* declaration, CSSPropertyID propertyId, const String& string, bool important, CSSParserMode cssParserMode)
324 {
325     ASSERT(!string.isEmpty());
326     bool acceptsNegativeNumbers = false;
327
328     // In @viewport, width and height are shorthands, not simple length values.
329     if (isCSSViewportParsingEnabledForMode(cssParserMode) || !isSimpleLengthPropertyID(propertyId, acceptsNegativeNumbers))
330         return false;
331
332     unsigned length = string.length();
333     double number;
334     CSSPrimitiveValue::UnitType unit = CSSPrimitiveValue::CSS_NUMBER;
335
336     if (string.is8Bit()) {
337         if (!parseSimpleLength(string.characters8(), length, unit, number))
338             return false;
339     } else {
340         if (!parseSimpleLength(string.characters16(), length, unit, number))
341             return false;
342     }
343
344     if (unit == CSSPrimitiveValue::CSS_NUMBER) {
345         bool quirksMode = isQuirksModeBehavior(cssParserMode);
346         if (number && !quirksMode)
347             return false;
348         unit = CSSPrimitiveValue::CSS_PX;
349     }
350     if (number < 0 && !acceptsNegativeNumbers)
351         return false;
352
353     RefPtrWillBeRawPtr<CSSValue> value = cssValuePool().createValue(number, unit);
354     declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important));
355     return true;
356 }
357
358 bool isValidKeywordPropertyAndValue(CSSPropertyID propertyId, CSSValueID valueID, const CSSParserContext& parserContext)
359 {
360     if (valueID == CSSValueInvalid)
361         return false;
362
363     switch (propertyId) {
364     case CSSPropertyBackgroundRepeatX: // repeat | no-repeat
365     case CSSPropertyBackgroundRepeatY: // repeat | no-repeat
366         return valueID == CSSValueRepeat || valueID == CSSValueNoRepeat;
367     case CSSPropertyBorderCollapse: // collapse | separate
368         return valueID == CSSValueCollapse || valueID == CSSValueSeparate;
369     case CSSPropertyBorderTopStyle: // <border-style>
370     case CSSPropertyBorderRightStyle: // Defined as: none | hidden | dotted | dashed |
371     case CSSPropertyBorderBottomStyle: // solid | double | groove | ridge | inset | outset
372     case CSSPropertyBorderLeftStyle:
373     case CSSPropertyWebkitBorderAfterStyle:
374     case CSSPropertyWebkitBorderBeforeStyle:
375     case CSSPropertyWebkitBorderEndStyle:
376     case CSSPropertyWebkitBorderStartStyle:
377     case CSSPropertyWebkitColumnRuleStyle:
378         return valueID >= CSSValueNone && valueID <= CSSValueDouble;
379     case CSSPropertyBoxSizing:
380         return valueID == CSSValueBorderBox || valueID == CSSValueContentBox;
381     case CSSPropertyCaptionSide: // top | bottom | left | right
382         return valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueTop || valueID == CSSValueBottom;
383     case CSSPropertyClear: // none | left | right | both
384         return valueID == CSSValueNone || valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueBoth;
385     case CSSPropertyDirection: // ltr | rtl
386         return valueID == CSSValueLtr || valueID == CSSValueRtl;
387     case CSSPropertyDisplay:
388         // inline | block | list-item | inline-block | table |
389         // inline-table | table-row-group | table-header-group | table-footer-group | table-row |
390         // table-column-group | table-column | table-cell | table-caption | -webkit-box | -webkit-inline-box | none
391         // flex | inline-flex | -webkit-flex | -webkit-inline-flex | grid | inline-grid
392         return (valueID >= CSSValueInline && valueID <= CSSValueInlineFlex) || valueID == CSSValueWebkitFlex || valueID == CSSValueWebkitInlineFlex || valueID == CSSValueNone
393             || (RuntimeEnabledFeatures::cssGridLayoutEnabled() && (valueID == CSSValueGrid || valueID == CSSValueInlineGrid));
394     case CSSPropertyEmptyCells: // show | hide
395         return valueID == CSSValueShow || valueID == CSSValueHide;
396     case CSSPropertyFloat: // left | right | none | center (for buggy CSS, maps to none)
397         return valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueNone || valueID == CSSValueCenter;
398     case CSSPropertyFontStyle: // normal | italic | oblique
399         return valueID == CSSValueNormal || valueID == CSSValueItalic || valueID == CSSValueOblique;
400     case CSSPropertyFontStretch: // normal | ultra-condensed | extra-condensed | condensed | semi-condensed | semi-expanded | expanded | extra-expanded | ultra-expanded
401         return valueID == CSSValueNormal || valueID == CSSValueUltraCondensed || valueID == CSSValueExtraCondensed || valueID == CSSValueCondensed || valueID == CSSValueSemiCondensed || valueID == CSSValueSemiExpanded || valueID == CSSValueExpanded || valueID == CSSValueExtraExpanded || valueID == CSSValueUltraExpanded;
402     case CSSPropertyImageRendering: // auto | optimizeContrast | pixelated
403         return valueID == CSSValueAuto || valueID == CSSValueWebkitOptimizeContrast || (RuntimeEnabledFeatures::imageRenderingPixelatedEnabled() && valueID == CSSValuePixelated);
404     case CSSPropertyIsolation: // auto | isolate
405         return RuntimeEnabledFeatures::cssCompositingEnabled()
406             && (valueID == CSSValueAuto || valueID == CSSValueIsolate);
407     case CSSPropertyListStylePosition: // inside | outside
408         return valueID == CSSValueInside || valueID == CSSValueOutside;
409     case CSSPropertyListStyleType:
410         // See section CSS_PROP_LIST_STYLE_TYPE of file CSSValueKeywords.in
411         // for the list of supported list-style-types.
412         return (valueID >= CSSValueDisc && valueID <= CSSValueKatakanaIroha) || valueID == CSSValueNone;
413     case CSSPropertyObjectFit:
414         return RuntimeEnabledFeatures::objectFitPositionEnabled()
415             && (valueID == CSSValueFill || valueID == CSSValueContain || valueID == CSSValueCover || valueID == CSSValueNone || valueID == CSSValueScaleDown);
416     case CSSPropertyOutlineStyle: // (<border-style> except hidden) | auto
417         return valueID == CSSValueAuto || valueID == CSSValueNone || (valueID >= CSSValueInset && valueID <= CSSValueDouble);
418     case CSSPropertyOverflowWrap: // normal | break-word
419     case CSSPropertyWordWrap:
420         return valueID == CSSValueNormal || valueID == CSSValueBreakWord;
421     case CSSPropertyOverflowX: // visible | hidden | scroll | auto | overlay
422         return valueID == CSSValueVisible || valueID == CSSValueHidden || valueID == CSSValueScroll || valueID == CSSValueAuto || valueID == CSSValueOverlay;
423     case CSSPropertyOverflowY: // visible | hidden | scroll | auto | overlay | -webkit-paged-x | -webkit-paged-y
424         return valueID == CSSValueVisible || valueID == CSSValueHidden || valueID == CSSValueScroll || valueID == CSSValueAuto || valueID == CSSValueOverlay || valueID == CSSValueWebkitPagedX || valueID == CSSValueWebkitPagedY;
425     case CSSPropertyPageBreakAfter: // auto | always | avoid | left | right
426     case CSSPropertyPageBreakBefore:
427     case CSSPropertyWebkitColumnBreakAfter:
428     case CSSPropertyWebkitColumnBreakBefore:
429         return valueID == CSSValueAuto || valueID == CSSValueAlways || valueID == CSSValueAvoid || valueID == CSSValueLeft || valueID == CSSValueRight;
430     case CSSPropertyPageBreakInside: // avoid | auto
431     case CSSPropertyWebkitColumnBreakInside:
432         return valueID == CSSValueAuto || valueID == CSSValueAvoid;
433     case CSSPropertyPointerEvents:
434         // none | visiblePainted | visibleFill | visibleStroke | visible |
435         // painted | fill | stroke | auto | all | bounding-box
436         return valueID == CSSValueVisible || valueID == CSSValueNone || valueID == CSSValueAll || valueID == CSSValueAuto || (valueID >= CSSValueVisiblepainted && valueID <= CSSValueBoundingBox);
437     case CSSPropertyPosition: // static | relative | absolute | fixed
438         return valueID == CSSValueStatic || valueID == CSSValueRelative || valueID == CSSValueAbsolute || valueID == CSSValueFixed;
439     case CSSPropertyResize: // none | both | horizontal | vertical | auto
440         return valueID == CSSValueNone || valueID == CSSValueBoth || valueID == CSSValueHorizontal || valueID == CSSValueVertical || valueID == CSSValueAuto;
441     case CSSPropertyScrollBehavior: // instant | smooth
442         return RuntimeEnabledFeatures::cssomSmoothScrollEnabled()
443             && (valueID == CSSValueInstant || valueID == CSSValueSmooth);
444     case CSSPropertySpeak: // none | normal | spell-out | digits | literal-punctuation | no-punctuation
445         return valueID == CSSValueNone || valueID == CSSValueNormal || valueID == CSSValueSpellOut || valueID == CSSValueDigits || valueID == CSSValueLiteralPunctuation || valueID == CSSValueNoPunctuation;
446     case CSSPropertyTableLayout: // auto | fixed
447         return valueID == CSSValueAuto || valueID == CSSValueFixed;
448     case CSSPropertyTextAlignLast:
449         // auto | start | end | left | right | center | justify
450         return RuntimeEnabledFeatures::css3TextEnabled()
451             && ((valueID >= CSSValueLeft && valueID <= CSSValueJustify) || valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueAuto);
452     case CSSPropertyTextJustify:
453         // auto | none | inter-word | distribute
454         return RuntimeEnabledFeatures::css3TextEnabled()
455             && (valueID == CSSValueInterWord || valueID == CSSValueDistribute || valueID == CSSValueAuto || valueID == CSSValueNone);
456     case CSSPropertyTextOverflow: // clip | ellipsis
457         return valueID == CSSValueClip || valueID == CSSValueEllipsis;
458     case CSSPropertyTextRendering: // auto | optimizeSpeed | optimizeLegibility | geometricPrecision
459         return valueID == CSSValueAuto || valueID == CSSValueOptimizespeed || valueID == CSSValueOptimizelegibility || valueID == CSSValueGeometricprecision;
460     case CSSPropertyTextTransform: // capitalize | uppercase | lowercase | none
461         return (valueID >= CSSValueCapitalize && valueID <= CSSValueLowercase) || valueID == CSSValueNone;
462     case CSSPropertyTouchActionDelay: // none | script
463         return RuntimeEnabledFeatures::cssTouchActionDelayEnabled()
464             && (valueID == CSSValueScript || valueID == CSSValueNone);
465     case CSSPropertyVisibility: // visible | hidden | collapse
466         return valueID == CSSValueVisible || valueID == CSSValueHidden || valueID == CSSValueCollapse;
467     case CSSPropertyWebkitAppearance:
468         return (valueID >= CSSValueCheckbox && valueID <= CSSValueTextarea) || valueID == CSSValueNone;
469     case CSSPropertyBackfaceVisibility:
470     case CSSPropertyWebkitBackfaceVisibility:
471         return valueID == CSSValueVisible || valueID == CSSValueHidden;
472     case CSSPropertyMixBlendMode:
473         return RuntimeEnabledFeatures::cssCompositingEnabled()
474             && (valueID == CSSValueNormal || valueID == CSSValueMultiply || valueID == CSSValueScreen || valueID == CSSValueOverlay
475             || valueID == CSSValueDarken || valueID == CSSValueLighten || valueID == CSSValueColorDodge || valueID == CSSValueColorBurn
476             || valueID == CSSValueHardLight || valueID == CSSValueSoftLight || valueID == CSSValueDifference || valueID == CSSValueExclusion
477             || valueID == CSSValueHue || valueID == CSSValueSaturation || valueID == CSSValueColor || valueID == CSSValueLuminosity);
478     case CSSPropertyWebkitBorderFit:
479         return valueID == CSSValueBorder || valueID == CSSValueLines;
480     case CSSPropertyWebkitBoxAlign:
481         return valueID == CSSValueStretch || valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueCenter || valueID == CSSValueBaseline;
482     case CSSPropertyWebkitBoxDecorationBreak:
483         return valueID == CSSValueClone || valueID == CSSValueSlice;
484     case CSSPropertyWebkitBoxDirection:
485         return valueID == CSSValueNormal || valueID == CSSValueReverse;
486     case CSSPropertyWebkitBoxLines:
487         return valueID == CSSValueSingle || valueID == CSSValueMultiple;
488     case CSSPropertyWebkitBoxOrient:
489         return valueID == CSSValueHorizontal || valueID == CSSValueVertical || valueID == CSSValueInlineAxis || valueID == CSSValueBlockAxis;
490     case CSSPropertyWebkitBoxPack:
491         return valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueCenter || valueID == CSSValueJustify;
492     case CSSPropertyInternalCallback:
493         // This property is only injected programmatically, not parsed from stylesheets.
494         return false;
495     case CSSPropertyColumnFill:
496         return RuntimeEnabledFeatures::regionBasedColumnsEnabled()
497             && (valueID == CSSValueAuto || valueID == CSSValueBalance);
498     case CSSPropertyAlignContent:
499         // FIXME: Per CSS alignment, this property should accept an optional <overflow-position>. We should share this parsing code with 'justify-self'.
500         return valueID == CSSValueFlexStart || valueID == CSSValueFlexEnd || valueID == CSSValueCenter || valueID == CSSValueSpaceBetween || valueID == CSSValueSpaceAround || valueID == CSSValueStretch;
501     case CSSPropertyAlignItems:
502         // FIXME: Per CSS alignment, this property should accept the same arguments as 'justify-self' so we should share its parsing code.
503         return valueID == CSSValueFlexStart || valueID == CSSValueFlexEnd || valueID == CSSValueCenter || valueID == CSSValueBaseline || valueID == CSSValueStretch;
504     case CSSPropertyAlignSelf:
505         // FIXME: Per CSS alignment, this property should accept the same arguments as 'justify-self' so we should share its parsing code.
506         return valueID == CSSValueAuto || valueID == CSSValueFlexStart || valueID == CSSValueFlexEnd || valueID == CSSValueCenter || valueID == CSSValueBaseline || valueID == CSSValueStretch;
507     case CSSPropertyFlexDirection:
508         return valueID == CSSValueRow || valueID == CSSValueRowReverse || valueID == CSSValueColumn || valueID == CSSValueColumnReverse;
509     case CSSPropertyFlexWrap:
510         return valueID == CSSValueNowrap || valueID == CSSValueWrap || valueID == CSSValueWrapReverse;
511     case CSSPropertyJustifyContent:
512         // FIXME: Per CSS alignment, this property should accept an optional <overflow-position>. We should share this parsing code with 'justify-self'.
513         return valueID == CSSValueFlexStart || valueID == CSSValueFlexEnd || valueID == CSSValueCenter || valueID == CSSValueSpaceBetween || valueID == CSSValueSpaceAround;
514     case CSSPropertyFontKerning:
515         return valueID == CSSValueAuto || valueID == CSSValueNormal || valueID == CSSValueNone;
516     case CSSPropertyWebkitFontSmoothing:
517         return valueID == CSSValueAuto || valueID == CSSValueNone || valueID == CSSValueAntialiased || valueID == CSSValueSubpixelAntialiased;
518     case CSSPropertyWebkitLineBreak: // auto | loose | normal | strict | after-white-space
519         return valueID == CSSValueAuto || valueID == CSSValueLoose || valueID == CSSValueNormal || valueID == CSSValueStrict || valueID == CSSValueAfterWhiteSpace;
520     case CSSPropertyWebkitMarginAfterCollapse:
521     case CSSPropertyWebkitMarginBeforeCollapse:
522     case CSSPropertyWebkitMarginBottomCollapse:
523     case CSSPropertyWebkitMarginTopCollapse:
524         return valueID == CSSValueCollapse || valueID == CSSValueSeparate || valueID == CSSValueDiscard;
525     case CSSPropertyInternalMarqueeDirection:
526         return valueID == CSSValueForwards || valueID == CSSValueBackwards || valueID == CSSValueAhead || valueID == CSSValueReverse || valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueDown
527             || valueID == CSSValueUp || valueID == CSSValueAuto;
528     case CSSPropertyInternalMarqueeStyle:
529         return valueID == CSSValueNone || valueID == CSSValueSlide || valueID == CSSValueScroll || valueID == CSSValueAlternate;
530     case CSSPropertyWebkitPrintColorAdjust:
531         return valueID == CSSValueExact || valueID == CSSValueEconomy;
532     case CSSPropertyWebkitRtlOrdering:
533         return valueID == CSSValueLogical || valueID == CSSValueVisual;
534     case CSSPropertyWebkitRubyPosition:
535         return valueID == CSSValueBefore || valueID == CSSValueAfter;
536     case CSSPropertyWebkitTextCombine:
537         return valueID == CSSValueNone || valueID == CSSValueHorizontal;
538     case CSSPropertyWebkitTextEmphasisPosition:
539         return valueID == CSSValueOver || valueID == CSSValueUnder;
540     case CSSPropertyWebkitTextSecurity: // disc | circle | square | none
541         return valueID == CSSValueDisc || valueID == CSSValueCircle || valueID == CSSValueSquare || valueID == CSSValueNone;
542     case CSSPropertyTransformStyle:
543     case CSSPropertyWebkitTransformStyle:
544         return valueID == CSSValueFlat || valueID == CSSValuePreserve3d;
545     case CSSPropertyWebkitUserDrag: // auto | none | element
546         return valueID == CSSValueAuto || valueID == CSSValueNone || valueID == CSSValueElement;
547     case CSSPropertyWebkitUserModify: // read-only | read-write
548         return valueID == CSSValueReadOnly || valueID == CSSValueReadWrite || valueID == CSSValueReadWritePlaintextOnly;
549     case CSSPropertyWebkitUserSelect: // auto | none | text | all
550         return valueID == CSSValueAuto || valueID == CSSValueNone || valueID == CSSValueText || valueID == CSSValueAll;
551     case CSSPropertyWebkitWritingMode:
552         return valueID >= CSSValueHorizontalTb && valueID <= CSSValueHorizontalBt;
553     case CSSPropertyWhiteSpace: // normal | pre | nowrap
554         return valueID == CSSValueNormal || valueID == CSSValuePre || valueID == CSSValuePreWrap || valueID == CSSValuePreLine || valueID == CSSValueNowrap;
555     case CSSPropertyWordBreak: // normal | break-all | break-word (this is a custom extension)
556         return valueID == CSSValueNormal || valueID == CSSValueBreakAll || valueID == CSSValueBreakWord;
557     default:
558         ASSERT_NOT_REACHED();
559         return false;
560     }
561     return false;
562 }
563
564 bool isKeywordPropertyID(CSSPropertyID propertyId)
565 {
566     switch (propertyId) {
567     case CSSPropertyMixBlendMode:
568     case CSSPropertyIsolation:
569     case CSSPropertyBackgroundRepeatX:
570     case CSSPropertyBackgroundRepeatY:
571     case CSSPropertyBorderBottomStyle:
572     case CSSPropertyBorderCollapse:
573     case CSSPropertyBorderLeftStyle:
574     case CSSPropertyBorderRightStyle:
575     case CSSPropertyBorderTopStyle:
576     case CSSPropertyBoxSizing:
577     case CSSPropertyCaptionSide:
578     case CSSPropertyClear:
579     case CSSPropertyDirection:
580     case CSSPropertyDisplay:
581     case CSSPropertyEmptyCells:
582     case CSSPropertyFloat:
583     case CSSPropertyFontStyle:
584     case CSSPropertyFontStretch:
585     case CSSPropertyImageRendering:
586     case CSSPropertyListStylePosition:
587     case CSSPropertyListStyleType:
588     case CSSPropertyObjectFit:
589     case CSSPropertyOutlineStyle:
590     case CSSPropertyOverflowWrap:
591     case CSSPropertyOverflowX:
592     case CSSPropertyOverflowY:
593     case CSSPropertyPageBreakAfter:
594     case CSSPropertyPageBreakBefore:
595     case CSSPropertyPageBreakInside:
596     case CSSPropertyPointerEvents:
597     case CSSPropertyPosition:
598     case CSSPropertyResize:
599     case CSSPropertyScrollBehavior:
600     case CSSPropertySpeak:
601     case CSSPropertyTableLayout:
602     case CSSPropertyTextAlignLast:
603     case CSSPropertyTextJustify:
604     case CSSPropertyTextOverflow:
605     case CSSPropertyTextRendering:
606     case CSSPropertyTextTransform:
607     case CSSPropertyTouchActionDelay:
608     case CSSPropertyVisibility:
609     case CSSPropertyWebkitAppearance:
610     case CSSPropertyBackfaceVisibility:
611     case CSSPropertyWebkitBackfaceVisibility:
612     case CSSPropertyWebkitBorderAfterStyle:
613     case CSSPropertyWebkitBorderBeforeStyle:
614     case CSSPropertyWebkitBorderEndStyle:
615     case CSSPropertyWebkitBorderFit:
616     case CSSPropertyWebkitBorderStartStyle:
617     case CSSPropertyWebkitBoxAlign:
618     case CSSPropertyWebkitBoxDecorationBreak:
619     case CSSPropertyWebkitBoxDirection:
620     case CSSPropertyWebkitBoxLines:
621     case CSSPropertyWebkitBoxOrient:
622     case CSSPropertyWebkitBoxPack:
623     case CSSPropertyInternalCallback:
624     case CSSPropertyWebkitColumnBreakAfter:
625     case CSSPropertyWebkitColumnBreakBefore:
626     case CSSPropertyWebkitColumnBreakInside:
627     case CSSPropertyColumnFill:
628     case CSSPropertyWebkitColumnRuleStyle:
629     case CSSPropertyAlignContent:
630     case CSSPropertyFlexDirection:
631     case CSSPropertyFlexWrap:
632     case CSSPropertyJustifyContent:
633     case CSSPropertyFontKerning:
634     case CSSPropertyWebkitFontSmoothing:
635     case CSSPropertyWebkitLineBreak:
636     case CSSPropertyWebkitMarginAfterCollapse:
637     case CSSPropertyWebkitMarginBeforeCollapse:
638     case CSSPropertyWebkitMarginBottomCollapse:
639     case CSSPropertyWebkitMarginTopCollapse:
640     case CSSPropertyInternalMarqueeDirection:
641     case CSSPropertyInternalMarqueeStyle:
642     case CSSPropertyWebkitPrintColorAdjust:
643     case CSSPropertyWebkitRtlOrdering:
644     case CSSPropertyWebkitRubyPosition:
645     case CSSPropertyWebkitTextCombine:
646     case CSSPropertyWebkitTextEmphasisPosition:
647     case CSSPropertyWebkitTextSecurity:
648     case CSSPropertyTransformStyle:
649     case CSSPropertyWebkitTransformStyle:
650     case CSSPropertyWebkitUserDrag:
651     case CSSPropertyWebkitUserModify:
652     case CSSPropertyWebkitUserSelect:
653     case CSSPropertyWebkitWritingMode:
654     case CSSPropertyWhiteSpace:
655     case CSSPropertyWordBreak:
656     case CSSPropertyWordWrap:
657         return true;
658     case CSSPropertyAlignItems:
659     case CSSPropertyAlignSelf:
660         return !RuntimeEnabledFeatures::cssGridLayoutEnabled();
661     default:
662         return false;
663     }
664 }
665
666 static bool parseKeywordValue(MutableStylePropertySet* declaration, CSSPropertyID propertyId, const String& string, bool important, const CSSParserContext& parserContext)
667 {
668     ASSERT(!string.isEmpty());
669
670     if (!isKeywordPropertyID(propertyId)) {
671         // All properties accept the values of "initial" and "inherit".
672         String lowerCaseString = string.lower();
673         if (lowerCaseString != "initial" && lowerCaseString != "inherit")
674             return false;
675
676         // Parse initial/inherit shorthands using the BisonCSSParser.
677         if (shorthandForProperty(propertyId).length())
678             return false;
679     }
680
681     CSSParserString cssString;
682     cssString.init(string);
683     CSSValueID valueID = cssValueKeywordID(cssString);
684
685     if (!valueID)
686         return false;
687
688     RefPtrWillBeRawPtr<CSSValue> value = nullptr;
689     if (valueID == CSSValueInherit)
690         value = cssValuePool().createInheritedValue();
691     else if (valueID == CSSValueInitial)
692         value = cssValuePool().createExplicitInitialValue();
693     else if (isValidKeywordPropertyAndValue(propertyId, valueID, parserContext))
694         value = cssValuePool().createIdentifierValue(valueID);
695     else
696         return false;
697
698     declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important));
699     return true;
700 }
701
702 template <typename CharType>
703 static bool parseTransformTranslateArguments(CharType*& pos, CharType* end, unsigned expectedCount, CSSTransformValue* transformValue)
704 {
705     while (expectedCount) {
706         size_t delimiter = WTF::find(pos, end - pos, expectedCount == 1 ? ')' : ',');
707         if (delimiter == kNotFound)
708             return false;
709         unsigned argumentLength = static_cast<unsigned>(delimiter);
710         CSSPrimitiveValue::UnitType unit = CSSPrimitiveValue::CSS_NUMBER;
711         double number;
712         if (!parseSimpleLength(pos, argumentLength, unit, number))
713             return false;
714         if (unit != CSSPrimitiveValue::CSS_PX && (number || unit != CSSPrimitiveValue::CSS_NUMBER))
715             return false;
716         transformValue->append(cssValuePool().createValue(number, CSSPrimitiveValue::CSS_PX));
717         pos += argumentLength + 1;
718         --expectedCount;
719     }
720     return true;
721 }
722
723 template <typename CharType>
724 static bool parseTransformNumberArguments(CharType*& pos, CharType* end, unsigned expectedCount, CSSTransformValue* transformValue)
725 {
726     while (expectedCount) {
727         size_t delimiter = WTF::find(pos, end - pos, expectedCount == 1 ? ')' : ',');
728         if (delimiter == kNotFound)
729             return false;
730         unsigned argumentLength = static_cast<unsigned>(delimiter);
731         bool ok;
732         double number = charactersToDouble(pos, argumentLength, &ok);
733         if (!ok)
734             return false;
735         transformValue->append(cssValuePool().createValue(number, CSSPrimitiveValue::CSS_NUMBER));
736         pos += argumentLength + 1;
737         --expectedCount;
738     }
739     return true;
740 }
741
742 template <typename CharType>
743 static PassRefPtrWillBeRawPtr<CSSTransformValue> parseSimpleTransformValue(CharType*& pos, CharType* end)
744 {
745     static const int shortestValidTransformStringLength = 12;
746
747     if (end - pos < shortestValidTransformStringLength)
748         return nullptr;
749
750     const bool isTranslate = toASCIILower(pos[0]) == 't'
751         && toASCIILower(pos[1]) == 'r'
752         && toASCIILower(pos[2]) == 'a'
753         && toASCIILower(pos[3]) == 'n'
754         && toASCIILower(pos[4]) == 's'
755         && toASCIILower(pos[5]) == 'l'
756         && toASCIILower(pos[6]) == 'a'
757         && toASCIILower(pos[7]) == 't'
758         && toASCIILower(pos[8]) == 'e';
759
760     if (isTranslate) {
761         CSSTransformValue::TransformOperationType transformType;
762         unsigned expectedArgumentCount = 1;
763         unsigned argumentStart = 11;
764         CharType c9 = toASCIILower(pos[9]);
765         if (c9 == 'x' && pos[10] == '(') {
766             transformType = CSSTransformValue::TranslateXTransformOperation;
767         } else if (c9 == 'y' && pos[10] == '(') {
768             transformType = CSSTransformValue::TranslateYTransformOperation;
769         } else if (c9 == 'z' && pos[10] == '(') {
770             transformType = CSSTransformValue::TranslateZTransformOperation;
771         } else if (c9 == '(') {
772             transformType = CSSTransformValue::TranslateTransformOperation;
773             expectedArgumentCount = 2;
774             argumentStart = 10;
775         } else if (c9 == '3' && toASCIILower(pos[10]) == 'd' && pos[11] == '(') {
776             transformType = CSSTransformValue::Translate3DTransformOperation;
777             expectedArgumentCount = 3;
778             argumentStart = 12;
779         } else {
780             return nullptr;
781         }
782         pos += argumentStart;
783         RefPtrWillBeRawPtr<CSSTransformValue> transformValue = CSSTransformValue::create(transformType);
784         if (!parseTransformTranslateArguments(pos, end, expectedArgumentCount, transformValue.get()))
785             return nullptr;
786         return transformValue.release();
787     }
788
789     const bool isMatrix3d = toASCIILower(pos[0]) == 'm'
790         && toASCIILower(pos[1]) == 'a'
791         && toASCIILower(pos[2]) == 't'
792         && toASCIILower(pos[3]) == 'r'
793         && toASCIILower(pos[4]) == 'i'
794         && toASCIILower(pos[5]) == 'x'
795         && pos[6] == '3'
796         && toASCIILower(pos[7]) == 'd'
797         && pos[8] == '(';
798
799     if (isMatrix3d) {
800         pos += 9;
801         RefPtrWillBeRawPtr<CSSTransformValue> transformValue = CSSTransformValue::create(CSSTransformValue::Matrix3DTransformOperation);
802         if (!parseTransformNumberArguments(pos, end, 16, transformValue.get()))
803             return nullptr;
804         return transformValue.release();
805     }
806
807     const bool isScale3d = toASCIILower(pos[0]) == 's'
808         && toASCIILower(pos[1]) == 'c'
809         && toASCIILower(pos[2]) == 'a'
810         && toASCIILower(pos[3]) == 'l'
811         && toASCIILower(pos[4]) == 'e'
812         && pos[5] == '3'
813         && toASCIILower(pos[6]) == 'd'
814         && pos[7] == '(';
815
816     if (isScale3d) {
817         pos += 8;
818         RefPtrWillBeRawPtr<CSSTransformValue> transformValue = CSSTransformValue::create(CSSTransformValue::Scale3DTransformOperation);
819         if (!parseTransformNumberArguments(pos, end, 3, transformValue.get()))
820             return nullptr;
821         return transformValue.release();
822     }
823
824     return nullptr;
825 }
826
827 template <typename CharType>
828 static PassRefPtrWillBeRawPtr<CSSValueList> parseSimpleTransformList(CharType*& pos, CharType* end)
829 {
830     RefPtrWillBeRawPtr<CSSValueList> transformList = nullptr;
831     while (pos < end) {
832         while (pos < end && isCSSSpace(*pos))
833             ++pos;
834         RefPtrWillBeRawPtr<CSSTransformValue> transformValue = parseSimpleTransformValue(pos, end);
835         if (!transformValue)
836             return nullptr;
837         if (!transformList)
838             transformList = CSSValueList::createSpaceSeparated();
839         transformList->append(transformValue.release());
840         if (pos < end) {
841             if (isCSSSpace(*pos))
842                 return nullptr;
843         }
844     }
845     return transformList.release();
846 }
847
848 static bool parseSimpleTransform(MutableStylePropertySet* properties, CSSPropertyID propertyID, const String& string, bool important)
849 {
850     if (propertyID != CSSPropertyTransform && propertyID != CSSPropertyWebkitTransform)
851         return false;
852     if (string.isEmpty())
853         return false;
854     RefPtrWillBeRawPtr<CSSValueList> transformList = nullptr;
855     if (string.is8Bit()) {
856         const LChar* pos = string.characters8();
857         const LChar* end = pos + string.length();
858         transformList = parseSimpleTransformList(pos, end);
859         if (!transformList)
860             return false;
861     } else {
862         const UChar* pos = string.characters16();
863         const UChar* end = pos + string.length();
864         transformList = parseSimpleTransformList(pos, end);
865         if (!transformList)
866             return false;
867     }
868     properties->addParsedProperty(CSSProperty(propertyID, transformList.release(), important));
869     return true;
870 }
871
872 PassRefPtrWillBeRawPtr<CSSValueList> BisonCSSParser::parseFontFaceValue(const AtomicString& string)
873 {
874     if (string.isEmpty())
875         return nullptr;
876     RefPtrWillBeRawPtr<MutableStylePropertySet> dummyStyle = MutableStylePropertySet::create();
877     if (!parseValue(dummyStyle.get(), CSSPropertyFontFamily, string, false, HTMLQuirksMode, 0))
878         return nullptr;
879
880     RefPtrWillBeRawPtr<CSSValue> fontFamily = dummyStyle->getPropertyCSSValue(CSSPropertyFontFamily);
881     if (!fontFamily->isValueList())
882         return nullptr;
883
884     return toCSSValueList(dummyStyle->getPropertyCSSValue(CSSPropertyFontFamily).get());
885 }
886
887 PassRefPtrWillBeRawPtr<CSSValue> BisonCSSParser::parseAnimationTimingFunctionValue(const String& string)
888 {
889     if (string.isEmpty())
890         return nullptr;
891     RefPtrWillBeRawPtr<MutableStylePropertySet> style = MutableStylePropertySet::create();
892     if (!parseValue(style.get(), CSSPropertyTransitionTimingFunction, string, false, HTMLStandardMode, 0))
893         return nullptr;
894
895     RefPtrWillBeRawPtr<CSSValue> value = style->getPropertyCSSValue(CSSPropertyTransitionTimingFunction);
896     if (!value || value->isInitialValue() || value->isInheritedValue())
897         return nullptr;
898     CSSValueList* valueList = toCSSValueList(value.get());
899     if (valueList->length() > 1)
900         return nullptr;
901     return valueList->item(0);
902 }
903
904 bool BisonCSSParser::parseValue(MutableStylePropertySet* declaration, CSSPropertyID propertyID, const String& string, bool important, const Document& document)
905 {
906     ASSERT(!string.isEmpty());
907
908     CSSParserContext context(document, UseCounter::getFrom(&document));
909
910     if (parseSimpleLengthValue(declaration, propertyID, string, important, context.mode()))
911         return true;
912     if (parseColorValue(declaration, propertyID, string, important, context.mode()))
913         return true;
914     if (parseKeywordValue(declaration, propertyID, string, important, context))
915         return true;
916
917     BisonCSSParser parser(context);
918     return parser.parseValue(declaration, propertyID, string, important, static_cast<StyleSheetContents*>(0));
919 }
920
921 bool BisonCSSParser::parseValue(MutableStylePropertySet* declaration, CSSPropertyID propertyID, const String& string, bool important, CSSParserMode cssParserMode, StyleSheetContents* contextStyleSheet)
922 {
923     ASSERT(!string.isEmpty());
924     if (parseSimpleLengthValue(declaration, propertyID, string, important, cssParserMode))
925         return true;
926     if (parseColorValue(declaration, propertyID, string, important, cssParserMode))
927         return true;
928
929     CSSParserContext context(cssParserMode, 0);
930     if (contextStyleSheet) {
931         context = contextStyleSheet->parserContext();
932         context.setMode(cssParserMode);
933     }
934
935     if (parseKeywordValue(declaration, propertyID, string, important, context))
936         return true;
937     if (parseSimpleTransform(declaration, propertyID, string, important))
938         return true;
939
940     BisonCSSParser parser(context);
941     return parser.parseValue(declaration, propertyID, string, important, contextStyleSheet);
942 }
943
944 bool BisonCSSParser::parseValue(MutableStylePropertySet* declaration, CSSPropertyID propertyID, const String& string, bool important, StyleSheetContents* contextStyleSheet)
945 {
946     // FIXME: Check RuntimeCSSEnabled::isPropertyEnabled or isValueEnabledForProperty.
947
948     if (m_context.useCounter())
949         m_context.useCounter()->count(m_context, propertyID);
950
951     setStyleSheet(contextStyleSheet);
952
953     setupParser("@-internal-value ", string, "");
954
955     m_id = propertyID;
956     m_important = important;
957
958     {
959         StyleDeclarationScope scope(this, declaration);
960         cssyyparse(this);
961     }
962
963     m_rule = nullptr;
964     m_id = CSSPropertyInvalid;
965
966     bool ok = false;
967     if (!m_parsedProperties.isEmpty()) {
968         ok = true;
969         declaration->addParsedProperties(m_parsedProperties);
970         clearProperties();
971     }
972
973     return ok;
974 }
975
976 // The color will only be changed when string contains a valid CSS color, so callers
977 // can set it to a default color and ignore the boolean result.
978 bool BisonCSSParser::parseColor(RGBA32& color, const String& string, bool strict)
979 {
980     // First try creating a color specified by name, rgba(), rgb() or "#" syntax.
981     if (CSSPropertyParser::fastParseColor(color, string, strict))
982         return true;
983
984     BisonCSSParser parser(strictCSSParserContext());
985
986     // In case the fast-path parser didn't understand the color, try the full parser.
987     if (!parser.parseColor(string))
988         return false;
989
990     CSSValue* value = parser.m_parsedProperties.first().value();
991     if (!value->isPrimitiveValue())
992         return false;
993
994     CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
995     if (!primitiveValue->isRGBColor())
996         return false;
997
998     color = primitiveValue->getRGBA32Value();
999     return true;
1000 }
1001
1002 StyleColor BisonCSSParser::colorFromRGBColorString(const String& colorString)
1003 {
1004     // FIXME: Rework css parser so it is more SVG aware.
1005     RGBA32 color;
1006     if (parseColor(color, colorString.stripWhiteSpace()))
1007         return StyleColor(color);
1008     // FIXME: This branch catches the string currentColor, but we should error if we have an illegal color value.
1009     return StyleColor::currentColor();
1010 }
1011
1012 bool BisonCSSParser::parseColor(const String& string)
1013 {
1014     setupParser("@-internal-decls color:", string, "");
1015     cssyyparse(this);
1016     m_rule = nullptr;
1017
1018     return !m_parsedProperties.isEmpty() && m_parsedProperties.first().id() == CSSPropertyColor;
1019 }
1020
1021 bool BisonCSSParser::parseSystemColor(RGBA32& color, const String& string)
1022 {
1023     CSSParserString cssColor;
1024     cssColor.init(string);
1025     CSSValueID id = cssValueKeywordID(cssColor);
1026     if (!CSSPropertyParser::isSystemColor(id))
1027         return false;
1028
1029     Color parsedColor = RenderTheme::theme().systemColor(id);
1030     color = parsedColor.rgb();
1031     return true;
1032 }
1033
1034 void BisonCSSParser::parseSelector(const String& string, CSSSelectorList& selectorList)
1035 {
1036     m_selectorListForParseSelector = &selectorList;
1037
1038     setupParser("@-internal-selector ", string, "");
1039
1040     cssyyparse(this);
1041
1042     m_selectorListForParseSelector = 0;
1043 }
1044
1045 PassRefPtrWillBeRawPtr<ImmutableStylePropertySet> BisonCSSParser::parseInlineStyleDeclaration(const String& string, Element* element)
1046 {
1047     Document& document = element->document();
1048     CSSParserContext context = CSSParserContext(document.elementSheet().contents()->parserContext(), UseCounter::getFrom(&document));
1049     context.setMode((element->isHTMLElement() && !document.inQuirksMode()) ? HTMLStandardMode : HTMLQuirksMode);
1050     return BisonCSSParser(context).parseDeclaration(string, document.elementSheet().contents());
1051 }
1052
1053 PassRefPtrWillBeRawPtr<ImmutableStylePropertySet> BisonCSSParser::parseDeclaration(const String& string, StyleSheetContents* contextStyleSheet)
1054 {
1055     setStyleSheet(contextStyleSheet);
1056
1057     setupParser("@-internal-decls ", string, "");
1058     cssyyparse(this);
1059     m_rule = nullptr;
1060
1061     RefPtrWillBeRawPtr<ImmutableStylePropertySet> style = createStylePropertySet();
1062     clearProperties();
1063     return style.release();
1064 }
1065
1066
1067 bool BisonCSSParser::parseDeclaration(MutableStylePropertySet* declaration, const String& string, CSSParserObserver* observer, StyleSheetContents* contextStyleSheet)
1068 {
1069     setStyleSheet(contextStyleSheet);
1070
1071     TemporaryChange<CSSParserObserver*> scopedObsever(m_observer, observer);
1072
1073     setupParser("@-internal-decls ", string, "");
1074     if (m_observer) {
1075         m_observer->startRuleHeader(CSSRuleSourceData::STYLE_RULE, 0);
1076         m_observer->endRuleHeader(1);
1077         m_observer->startRuleBody(0);
1078     }
1079
1080     {
1081         StyleDeclarationScope scope(this, declaration);
1082         cssyyparse(this);
1083     }
1084
1085     m_rule = nullptr;
1086
1087     bool ok = false;
1088     if (!m_parsedProperties.isEmpty()) {
1089         ok = true;
1090         declaration->addParsedProperties(m_parsedProperties);
1091         clearProperties();
1092     }
1093
1094     if (m_observer)
1095         m_observer->endRuleBody(string.length(), false);
1096
1097     return ok;
1098 }
1099
1100 PassRefPtrWillBeRawPtr<MediaQuerySet> BisonCSSParser::parseMediaQueryList(const String& string)
1101 {
1102     ASSERT(!m_mediaList);
1103
1104     // can't use { because tokenizer state switches from mediaquery to initial state when it sees { token.
1105     // instead insert one " " (which is caught by maybe_space in CSSGrammar.y)
1106     setupParser("@-internal-medialist ", string, "");
1107     cssyyparse(this);
1108
1109     ASSERT(m_mediaList);
1110     return m_mediaList.release();
1111 }
1112
1113 bool BisonCSSParser::parseAttributeMatchType(CSSSelector::AttributeMatchType& matchType, const String& string)
1114 {
1115     if (!RuntimeEnabledFeatures::cssAttributeCaseSensitivityEnabled() && !isUASheetBehavior(m_context.mode()))
1116         return false;
1117     if (string == "i") {
1118         matchType = CSSSelector::CaseInsensitive;
1119         return true;
1120     }
1121     return false;
1122 }
1123
1124 static inline void filterProperties(bool important, const WillBeHeapVector<CSSProperty, 256>& input, WillBeHeapVector<CSSProperty, 256>& output, size_t& unusedEntries, BitArray<numCSSProperties>& seenProperties)
1125 {
1126     // Add properties in reverse order so that highest priority definitions are reached first. Duplicate definitions can then be ignored when found.
1127     for (int i = input.size() - 1; i >= 0; --i) {
1128         const CSSProperty& property = input[i];
1129         if (property.isImportant() != important)
1130             continue;
1131         const unsigned propertyIDIndex = property.id() - firstCSSProperty;
1132         if (seenProperties.get(propertyIDIndex))
1133             continue;
1134         seenProperties.set(propertyIDIndex);
1135         output[--unusedEntries] = property;
1136     }
1137 }
1138
1139 PassRefPtrWillBeRawPtr<ImmutableStylePropertySet> BisonCSSParser::createStylePropertySet()
1140 {
1141     BitArray<numCSSProperties> seenProperties;
1142     size_t unusedEntries = m_parsedProperties.size();
1143     WillBeHeapVector<CSSProperty, 256> results(unusedEntries);
1144
1145     // Important properties have higher priority, so add them first. Duplicate definitions can then be ignored when found.
1146     filterProperties(true, m_parsedProperties, results, unusedEntries, seenProperties);
1147     filterProperties(false, m_parsedProperties, results, unusedEntries, seenProperties);
1148     if (unusedEntries)
1149         results.remove(0, unusedEntries);
1150
1151     CSSParserMode mode = inViewport() ? CSSViewportRuleMode : m_context.mode();
1152
1153     return ImmutableStylePropertySet::create(results.data(), results.size(), mode);
1154 }
1155
1156 void BisonCSSParser::rollbackLastProperties(int num)
1157 {
1158     ASSERT(num >= 0);
1159     ASSERT(m_parsedProperties.size() >= static_cast<unsigned>(num));
1160     m_parsedProperties.shrink(m_parsedProperties.size() - num);
1161 }
1162
1163 void BisonCSSParser::clearProperties()
1164 {
1165     m_parsedProperties.clear();
1166     m_numParsedPropertiesBeforeMarginBox = INVALID_NUM_PARSED_PROPERTIES;
1167 }
1168
1169 void BisonCSSParser::setCurrentProperty(CSSPropertyID propId)
1170 {
1171     m_id = propId;
1172 }
1173
1174 bool BisonCSSParser::parseValue(CSSPropertyID propId, bool important)
1175 {
1176     CSSPropertyParser parser(m_valueList, m_context, m_inViewport, m_important, m_parsedProperties, m_ruleHeaderType);
1177     return parser.parseValue(propId, important);
1178 }
1179
1180
1181 class TransformOperationInfo {
1182 public:
1183     TransformOperationInfo(const CSSParserString& name)
1184         : m_type(CSSTransformValue::UnknownTransformOperation)
1185         , m_argCount(1)
1186         , m_allowSingleArgument(false)
1187         , m_unit(CSSPropertyParser::FUnknown)
1188     {
1189         const UChar* characters;
1190         unsigned nameLength = name.length();
1191
1192         const unsigned longestNameLength = 12;
1193         UChar characterBuffer[longestNameLength];
1194         if (name.is8Bit()) {
1195             unsigned length = std::min(longestNameLength, nameLength);
1196             const LChar* characters8 = name.characters8();
1197             for (unsigned i = 0; i < length; ++i)
1198                 characterBuffer[i] = characters8[i];
1199             characters = characterBuffer;
1200         } else
1201             characters = name.characters16();
1202
1203         SWITCH(characters, nameLength) {
1204             CASE("skew(") {
1205                 m_unit = CSSPropertyParser::FAngle;
1206                 m_type = CSSTransformValue::SkewTransformOperation;
1207                 m_allowSingleArgument = true;
1208                 m_argCount = 3;
1209             }
1210             CASE("scale(") {
1211                 m_unit = CSSPropertyParser::FNumber;
1212                 m_type = CSSTransformValue::ScaleTransformOperation;
1213                 m_allowSingleArgument = true;
1214                 m_argCount = 3;
1215             }
1216             CASE("skewx(") {
1217                 m_unit = CSSPropertyParser::FAngle;
1218                 m_type = CSSTransformValue::SkewXTransformOperation;
1219             }
1220             CASE("skewy(") {
1221                 m_unit = CSSPropertyParser::FAngle;
1222                 m_type = CSSTransformValue::SkewYTransformOperation;
1223             }
1224             CASE("matrix(") {
1225                 m_unit = CSSPropertyParser::FNumber;
1226                 m_type = CSSTransformValue::MatrixTransformOperation;
1227                 m_argCount = 11;
1228             }
1229             CASE("rotate(") {
1230                 m_unit = CSSPropertyParser::FAngle;
1231                 m_type = CSSTransformValue::RotateTransformOperation;
1232             }
1233             CASE("scalex(") {
1234                 m_unit = CSSPropertyParser::FNumber;
1235                 m_type = CSSTransformValue::ScaleXTransformOperation;
1236             }
1237             CASE("scaley(") {
1238                 m_unit = CSSPropertyParser::FNumber;
1239                 m_type = CSSTransformValue::ScaleYTransformOperation;
1240             }
1241             CASE("scalez(") {
1242                 m_unit = CSSPropertyParser::FNumber;
1243                 m_type = CSSTransformValue::ScaleZTransformOperation;
1244             }
1245             CASE("scale3d(") {
1246                 m_unit = CSSPropertyParser::FNumber;
1247                 m_type = CSSTransformValue::Scale3DTransformOperation;
1248                 m_argCount = 5;
1249             }
1250             CASE("rotatex(") {
1251                 m_unit = CSSPropertyParser::FAngle;
1252                 m_type = CSSTransformValue::RotateXTransformOperation;
1253             }
1254             CASE("rotatey(") {
1255                 m_unit = CSSPropertyParser::FAngle;
1256                 m_type = CSSTransformValue::RotateYTransformOperation;
1257             }
1258             CASE("rotatez(") {
1259                 m_unit = CSSPropertyParser::FAngle;
1260                 m_type = CSSTransformValue::RotateZTransformOperation;
1261             }
1262             CASE("matrix3d(") {
1263                 m_unit = CSSPropertyParser::FNumber;
1264                 m_type = CSSTransformValue::Matrix3DTransformOperation;
1265                 m_argCount = 31;
1266             }
1267             CASE("rotate3d(") {
1268                 m_unit = CSSPropertyParser::FNumber;
1269                 m_type = CSSTransformValue::Rotate3DTransformOperation;
1270                 m_argCount = 7;
1271             }
1272             CASE("translate(") {
1273                 m_unit = CSSPropertyParser::FLength | CSSPropertyParser::FPercent;
1274                 m_type = CSSTransformValue::TranslateTransformOperation;
1275                 m_allowSingleArgument = true;
1276                 m_argCount = 3;
1277             }
1278             CASE("translatex(") {
1279                 m_unit = CSSPropertyParser::FLength | CSSPropertyParser::FPercent;
1280                 m_type = CSSTransformValue::TranslateXTransformOperation;
1281             }
1282             CASE("translatey(") {
1283                 m_unit = CSSPropertyParser::FLength | CSSPropertyParser::FPercent;
1284                 m_type = CSSTransformValue::TranslateYTransformOperation;
1285             }
1286             CASE("translatez(") {
1287                 m_unit = CSSPropertyParser::FLength | CSSPropertyParser::FPercent;
1288                 m_type = CSSTransformValue::TranslateZTransformOperation;
1289             }
1290             CASE("perspective(") {
1291                 m_unit = CSSPropertyParser::FNumber;
1292                 m_type = CSSTransformValue::PerspectiveTransformOperation;
1293             }
1294             CASE("translate3d(") {
1295                 m_unit = CSSPropertyParser::FLength | CSSPropertyParser::FPercent;
1296                 m_type = CSSTransformValue::Translate3DTransformOperation;
1297                 m_argCount = 5;
1298             }
1299         }
1300     }
1301
1302     CSSTransformValue::TransformOperationType type() const { return m_type; }
1303     unsigned argCount() const { return m_argCount; }
1304     CSSPropertyParser::Units unit() const { return m_unit; }
1305
1306     bool unknown() const { return m_type == CSSTransformValue::UnknownTransformOperation; }
1307     bool hasCorrectArgCount(unsigned argCount) { return m_argCount == argCount || (m_allowSingleArgument && argCount == 1); }
1308
1309 private:
1310     CSSTransformValue::TransformOperationType m_type;
1311     unsigned m_argCount;
1312     bool m_allowSingleArgument;
1313     CSSPropertyParser::Units m_unit;
1314 };
1315
1316 PassRefPtrWillBeRawPtr<CSSValueList> CSSPropertyParser::parseTransform(CSSPropertyID propId)
1317 {
1318     if (!m_valueList)
1319         return nullptr;
1320
1321     RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
1322     for (CSSParserValue* value = m_valueList->current(); value; value = m_valueList->next()) {
1323         RefPtrWillBeRawPtr<CSSValue> parsedTransformValue = parseTransformValue(propId, value);
1324         if (!parsedTransformValue)
1325             return nullptr;
1326
1327         list->append(parsedTransformValue.release());
1328     }
1329
1330     return list.release();
1331 }
1332
1333 PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseTransformValue(CSSPropertyID propId, CSSParserValue *value)
1334 {
1335     if (value->unit != CSSParserValue::Function || !value->function)
1336         return nullptr;
1337
1338     // Every primitive requires at least one argument.
1339     CSSParserValueList* args = value->function->args.get();
1340     if (!args)
1341         return nullptr;
1342
1343     // See if the specified primitive is one we understand.
1344     TransformOperationInfo info(value->function->name);
1345     if (info.unknown())
1346         return nullptr;
1347
1348     if (!info.hasCorrectArgCount(args->size()))
1349         return nullptr;
1350
1351     // The transform is a list of functional primitives that specify transform operations.
1352     // We collect a list of CSSTransformValues, where each value specifies a single operation.
1353
1354     // Create the new CSSTransformValue for this operation and add it to our list.
1355     RefPtrWillBeRawPtr<CSSTransformValue> transformValue = CSSTransformValue::create(info.type());
1356
1357     // Snag our values.
1358     CSSParserValue* a = args->current();
1359     unsigned argNumber = 0;
1360     while (a) {
1361         CSSPropertyParser::Units unit = info.unit();
1362
1363         if (info.type() == CSSTransformValue::Rotate3DTransformOperation && argNumber == 3) {
1364             // 4th param of rotate3d() is an angle rather than a bare number, validate it as such
1365             if (!validUnit(a, FAngle, HTMLStandardMode))
1366                 return nullptr;
1367         } else if (info.type() == CSSTransformValue::Translate3DTransformOperation && argNumber == 2) {
1368             // 3rd param of translate3d() cannot be a percentage
1369             if (!validUnit(a, FLength, HTMLStandardMode))
1370                 return nullptr;
1371         } else if (info.type() == CSSTransformValue::TranslateZTransformOperation && !argNumber) {
1372             // 1st param of translateZ() cannot be a percentage
1373             if (!validUnit(a, FLength, HTMLStandardMode))
1374                 return nullptr;
1375         } else if (info.type() == CSSTransformValue::PerspectiveTransformOperation && !argNumber) {
1376             // 1st param of perspective() must be a non-negative number (deprecated) or length.
1377             if ((propId == CSSPropertyWebkitTransform && !validUnit(a, FNumber | FLength | FNonNeg, HTMLStandardMode))
1378                 || (propId == CSSPropertyTransform && !validUnit(a, FLength | FNonNeg, HTMLStandardMode)))
1379                 return nullptr;
1380         } else if (!validUnit(a, unit, HTMLStandardMode)) {
1381             return nullptr;
1382         }
1383
1384         // Add the value to the current transform operation.
1385         transformValue->append(createPrimitiveNumericValue(a));
1386
1387         a = args->next();
1388         if (!a)
1389             break;
1390         if (a->unit != CSSParserValue::Operator || a->iValue != ',')
1391             return nullptr;
1392         a = args->next();
1393
1394         argNumber++;
1395     }
1396
1397     return transformValue.release();
1398 }
1399
1400 void BisonCSSParser::ensureLineEndings()
1401 {
1402     if (!m_lineEndings)
1403         m_lineEndings = lineEndings(*m_source);
1404 }
1405
1406 CSSParserSelector* BisonCSSParser::createFloatingSelectorWithTagName(const QualifiedName& tagQName)
1407 {
1408     CSSParserSelector* selector = new CSSParserSelector(tagQName);
1409     m_floatingSelectors.append(selector);
1410     return selector;
1411 }
1412
1413 CSSParserSelector* BisonCSSParser::createFloatingSelector()
1414 {
1415     CSSParserSelector* selector = new CSSParserSelector;
1416     m_floatingSelectors.append(selector);
1417     return selector;
1418 }
1419
1420 PassOwnPtr<CSSParserSelector> BisonCSSParser::sinkFloatingSelector(CSSParserSelector* selector)
1421 {
1422     if (selector) {
1423         size_t index = m_floatingSelectors.reverseFind(selector);
1424         ASSERT(index != kNotFound);
1425         m_floatingSelectors.remove(index);
1426     }
1427     return adoptPtr(selector);
1428 }
1429
1430 Vector<OwnPtr<CSSParserSelector> >* BisonCSSParser::createFloatingSelectorVector()
1431 {
1432     Vector<OwnPtr<CSSParserSelector> >* selectorVector = new Vector<OwnPtr<CSSParserSelector> >;
1433     m_floatingSelectorVectors.append(selectorVector);
1434     return selectorVector;
1435 }
1436
1437 PassOwnPtr<Vector<OwnPtr<CSSParserSelector> > > BisonCSSParser::sinkFloatingSelectorVector(Vector<OwnPtr<CSSParserSelector> >* selectorVector)
1438 {
1439     if (selectorVector) {
1440         size_t index = m_floatingSelectorVectors.reverseFind(selectorVector);
1441         ASSERT(index != kNotFound);
1442         m_floatingSelectorVectors.remove(index);
1443     }
1444     return adoptPtr(selectorVector);
1445 }
1446
1447 CSSParserValueList* BisonCSSParser::createFloatingValueList()
1448 {
1449     CSSParserValueList* list = new CSSParserValueList;
1450     m_floatingValueLists.append(list);
1451     return list;
1452 }
1453
1454 PassOwnPtr<CSSParserValueList> BisonCSSParser::sinkFloatingValueList(CSSParserValueList* list)
1455 {
1456     if (list) {
1457         size_t index = m_floatingValueLists.reverseFind(list);
1458         ASSERT(index != kNotFound);
1459         m_floatingValueLists.remove(index);
1460     }
1461     return adoptPtr(list);
1462 }
1463
1464 CSSParserFunction* BisonCSSParser::createFloatingFunction()
1465 {
1466     CSSParserFunction* function = new CSSParserFunction;
1467     m_floatingFunctions.append(function);
1468     return function;
1469 }
1470
1471 CSSParserFunction* BisonCSSParser::createFloatingFunction(const CSSParserString& name, PassOwnPtr<CSSParserValueList> args)
1472 {
1473     CSSParserFunction* function = createFloatingFunction();
1474     function->name = name;
1475     function->args = args;
1476     return function;
1477 }
1478
1479 PassOwnPtr<CSSParserFunction> BisonCSSParser::sinkFloatingFunction(CSSParserFunction* function)
1480 {
1481     if (function) {
1482         size_t index = m_floatingFunctions.reverseFind(function);
1483         ASSERT(index != kNotFound);
1484         m_floatingFunctions.remove(index);
1485     }
1486     return adoptPtr(function);
1487 }
1488
1489 CSSParserValue& BisonCSSParser::sinkFloatingValue(CSSParserValue& value)
1490 {
1491     if (value.unit == CSSParserValue::Function) {
1492         size_t index = m_floatingFunctions.reverseFind(value.function);
1493         ASSERT(index != kNotFound);
1494         m_floatingFunctions.remove(index);
1495     }
1496     return value;
1497 }
1498
1499 MediaQueryExp* BisonCSSParser::createFloatingMediaQueryExp(const AtomicString& mediaFeature, CSSParserValueList* values)
1500 {
1501     m_floatingMediaQueryExp = MediaQueryExp::createIfValid(mediaFeature, values);
1502     return m_floatingMediaQueryExp.get();
1503 }
1504
1505 PassOwnPtrWillBeRawPtr<MediaQueryExp> BisonCSSParser::sinkFloatingMediaQueryExp(MediaQueryExp* expression)
1506 {
1507     ASSERT_UNUSED(expression, expression == m_floatingMediaQueryExp);
1508     return m_floatingMediaQueryExp.release();
1509 }
1510
1511 WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp> >* BisonCSSParser::createFloatingMediaQueryExpList()
1512 {
1513     m_floatingMediaQueryExpList = adoptPtrWillBeNoop(new WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp> >);
1514     return m_floatingMediaQueryExpList.get();
1515 }
1516
1517 PassOwnPtrWillBeRawPtr<WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp> > > BisonCSSParser::sinkFloatingMediaQueryExpList(WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp> >* list)
1518 {
1519     ASSERT_UNUSED(list, list == m_floatingMediaQueryExpList);
1520     return m_floatingMediaQueryExpList.release();
1521 }
1522
1523 MediaQuery* BisonCSSParser::createFloatingMediaQuery(MediaQuery::Restrictor restrictor, const AtomicString& mediaType, PassOwnPtrWillBeRawPtr<WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp> > > expressions)
1524 {
1525     m_floatingMediaQuery = adoptPtrWillBeNoop(new MediaQuery(restrictor, mediaType, expressions));
1526     return m_floatingMediaQuery.get();
1527 }
1528
1529 MediaQuery* BisonCSSParser::createFloatingMediaQuery(PassOwnPtrWillBeRawPtr<WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp> > > expressions)
1530 {
1531     return createFloatingMediaQuery(MediaQuery::None, AtomicString("all", AtomicString::ConstructFromLiteral), expressions);
1532 }
1533
1534 MediaQuery* BisonCSSParser::createFloatingNotAllQuery()
1535 {
1536     return createFloatingMediaQuery(MediaQuery::Not, AtomicString("all", AtomicString::ConstructFromLiteral), sinkFloatingMediaQueryExpList(createFloatingMediaQueryExpList()));
1537 }
1538
1539 PassOwnPtrWillBeRawPtr<MediaQuery> BisonCSSParser::sinkFloatingMediaQuery(MediaQuery* query)
1540 {
1541     ASSERT_UNUSED(query, query == m_floatingMediaQuery);
1542     return m_floatingMediaQuery.release();
1543 }
1544
1545 WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> >* BisonCSSParser::createFloatingKeyframeVector()
1546 {
1547     m_floatingKeyframeVector = adoptPtrWillBeNoop(new WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> >());
1548     return m_floatingKeyframeVector.get();
1549 }
1550
1551 PassOwnPtrWillBeRawPtr<WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> > > BisonCSSParser::sinkFloatingKeyframeVector(WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> >* keyframeVector)
1552 {
1553     ASSERT_UNUSED(keyframeVector, m_floatingKeyframeVector == keyframeVector);
1554     return m_floatingKeyframeVector.release();
1555 }
1556
1557 MediaQuerySet* BisonCSSParser::createMediaQuerySet()
1558 {
1559     RefPtrWillBeRawPtr<MediaQuerySet> queries = MediaQuerySet::create();
1560     MediaQuerySet* result = queries.get();
1561     m_parsedMediaQuerySets.append(queries.release());
1562     return result;
1563 }
1564
1565 StyleRuleBase* BisonCSSParser::createImportRule(const CSSParserString& url, MediaQuerySet* media)
1566 {
1567     if (!media || !m_allowImportRules)
1568         return 0;
1569     RefPtrWillBeRawPtr<StyleRuleImport> rule = StyleRuleImport::create(url, media);
1570     StyleRuleImport* result = rule.get();
1571     m_parsedRules.append(rule.release());
1572     return result;
1573 }
1574
1575 StyleRuleBase* BisonCSSParser::createMediaRule(MediaQuerySet* media, RuleList* rules)
1576 {
1577     m_allowImportRules = m_allowNamespaceDeclarations = false;
1578     RefPtrWillBeRawPtr<StyleRuleMedia> rule = nullptr;
1579     if (rules) {
1580         rule = StyleRuleMedia::create(media ? media : MediaQuerySet::create().get(), *rules);
1581     } else {
1582         RuleList emptyRules;
1583         rule = StyleRuleMedia::create(media ? media : MediaQuerySet::create().get(), emptyRules);
1584     }
1585     StyleRuleMedia* result = rule.get();
1586     m_parsedRules.append(rule.release());
1587     return result;
1588 }
1589
1590 StyleRuleBase* BisonCSSParser::createSupportsRule(bool conditionIsSupported, RuleList* rules)
1591 {
1592     m_allowImportRules = m_allowNamespaceDeclarations = false;
1593
1594     RefPtrWillBeRawPtr<CSSRuleSourceData> data = popSupportsRuleData();
1595     RefPtrWillBeRawPtr<StyleRuleSupports> rule = nullptr;
1596     String conditionText;
1597     unsigned conditionOffset = data->ruleHeaderRange.start + 9;
1598     unsigned conditionLength = data->ruleHeaderRange.length() - 9;
1599
1600     if (m_tokenizer.is8BitSource())
1601         conditionText = String(m_tokenizer.m_dataStart8.get() + conditionOffset, conditionLength).stripWhiteSpace();
1602     else
1603         conditionText = String(m_tokenizer.m_dataStart16.get() + conditionOffset, conditionLength).stripWhiteSpace();
1604
1605     if (rules) {
1606         rule = StyleRuleSupports::create(conditionText, conditionIsSupported, *rules);
1607     } else {
1608         RuleList emptyRules;
1609         rule = StyleRuleSupports::create(conditionText, conditionIsSupported, emptyRules);
1610     }
1611
1612     StyleRuleSupports* result = rule.get();
1613     m_parsedRules.append(rule.release());
1614
1615     return result;
1616 }
1617
1618 void BisonCSSParser::markSupportsRuleHeaderStart()
1619 {
1620     if (!m_supportsRuleDataStack)
1621         m_supportsRuleDataStack = adoptPtrWillBeNoop(new RuleSourceDataList());
1622
1623     RefPtrWillBeRawPtr<CSSRuleSourceData> data = CSSRuleSourceData::create(CSSRuleSourceData::SUPPORTS_RULE);
1624     data->ruleHeaderRange.start = m_tokenizer.tokenStartOffset();
1625     m_supportsRuleDataStack->append(data);
1626 }
1627
1628 void BisonCSSParser::markSupportsRuleHeaderEnd()
1629 {
1630     ASSERT(m_supportsRuleDataStack && !m_supportsRuleDataStack->isEmpty());
1631
1632     if (m_tokenizer.is8BitSource())
1633         m_supportsRuleDataStack->last()->ruleHeaderRange.end = m_tokenizer.tokenStart<LChar>() - m_tokenizer.m_dataStart8.get();
1634     else
1635         m_supportsRuleDataStack->last()->ruleHeaderRange.end = m_tokenizer.tokenStart<UChar>() - m_tokenizer.m_dataStart16.get();
1636 }
1637
1638 PassRefPtrWillBeRawPtr<CSSRuleSourceData> BisonCSSParser::popSupportsRuleData()
1639 {
1640     ASSERT(m_supportsRuleDataStack && !m_supportsRuleDataStack->isEmpty());
1641     RefPtrWillBeRawPtr<CSSRuleSourceData> data = m_supportsRuleDataStack->last();
1642     m_supportsRuleDataStack->removeLast();
1643     return data.release();
1644 }
1645
1646 BisonCSSParser::RuleList* BisonCSSParser::createRuleList()
1647 {
1648     OwnPtrWillBeRawPtr<RuleList> list = adoptPtrWillBeNoop(new RuleList);
1649     RuleList* listPtr = list.get();
1650
1651     m_parsedRuleLists.append(list.release());
1652     return listPtr;
1653 }
1654
1655 BisonCSSParser::RuleList* BisonCSSParser::appendRule(RuleList* ruleList, StyleRuleBase* rule)
1656 {
1657     if (rule) {
1658         if (!ruleList)
1659             ruleList = createRuleList();
1660         ruleList->append(rule);
1661     }
1662     return ruleList;
1663 }
1664
1665 template <typename CharacterType>
1666 ALWAYS_INLINE static void makeLower(const CharacterType* input, CharacterType* output, unsigned length)
1667 {
1668     // FIXME: If we need Unicode lowercasing here, then we probably want the real kind
1669     // that can potentially change the length of the string rather than the character
1670     // by character kind. If we don't need Unicode lowercasing, it would be good to
1671     // simplify this function.
1672
1673     if (charactersAreAllASCII(input, length)) {
1674         // Fast case for all-ASCII.
1675         for (unsigned i = 0; i < length; i++)
1676             output[i] = toASCIILower(input[i]);
1677     } else {
1678         for (unsigned i = 0; i < length; i++)
1679             output[i] = Unicode::toLower(input[i]);
1680     }
1681 }
1682
1683 void BisonCSSParser::tokenToLowerCase(CSSParserString& token)
1684 {
1685     // Since it's our internal token, we know that we created it out
1686     // of our writable work buffers. Therefore the const_cast is just
1687     // ugly and not a potential crash.
1688     size_t length = token.length();
1689     if (token.is8Bit()) {
1690         makeLower(token.characters8(), const_cast<LChar*>(token.characters8()), length);
1691     } else {
1692         makeLower(token.characters16(), const_cast<UChar*>(token.characters16()), length);
1693     }
1694 }
1695
1696 void BisonCSSParser::endInvalidRuleHeader()
1697 {
1698     if (m_ruleHeaderType == CSSRuleSourceData::UNKNOWN_RULE)
1699         return;
1700
1701     CSSParserLocation location;
1702     location.lineNumber = m_tokenizer.m_lineNumber;
1703     location.offset = m_ruleHeaderStartOffset;
1704     if (m_tokenizer.is8BitSource())
1705         location.token.init(m_tokenizer.m_dataStart8.get() + m_ruleHeaderStartOffset, 0);
1706     else
1707         location.token.init(m_tokenizer.m_dataStart16.get() + m_ruleHeaderStartOffset, 0);
1708
1709     reportError(location, m_ruleHeaderType == CSSRuleSourceData::STYLE_RULE ? InvalidSelectorCSSError : InvalidRuleCSSError);
1710
1711     endRuleHeader();
1712 }
1713
1714 void BisonCSSParser::reportError(const CSSParserLocation&, CSSParserError)
1715 {
1716     // FIXME: error reporting temporatily disabled.
1717 }
1718
1719 bool BisonCSSParser::isLoggingErrors()
1720 {
1721     return m_logErrors && !m_ignoreErrors;
1722 }
1723
1724 void BisonCSSParser::logError(const String& message, const CSSParserLocation& location)
1725 {
1726     unsigned lineNumberInStyleSheet;
1727     unsigned columnNumber = 0;
1728     if (InspectorInstrumentation::hasFrontends()) {
1729         ensureLineEndings();
1730         TextPosition tokenPosition = TextPosition::fromOffsetAndLineEndings(location.offset, *m_lineEndings);
1731         lineNumberInStyleSheet = tokenPosition.m_line.zeroBasedInt();
1732         columnNumber = (lineNumberInStyleSheet ? 0 : m_startPosition.m_column.zeroBasedInt()) + tokenPosition.m_column.zeroBasedInt();
1733     } else {
1734         lineNumberInStyleSheet = location.lineNumber;
1735     }
1736     FrameConsole& console = m_styleSheet->singleOwnerDocument()->frame()->console();
1737     console.addMessage(ConsoleMessage::create(CSSMessageSource, WarningMessageLevel, message, m_styleSheet->baseURL().string(), lineNumberInStyleSheet + m_startPosition.m_line.zeroBasedInt() + 1, columnNumber + 1));
1738 }
1739
1740 StyleRuleKeyframes* BisonCSSParser::createKeyframesRule(const String& name, PassOwnPtrWillBeRawPtr<WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> > > popKeyframes, bool isPrefixed)
1741 {
1742     OwnPtrWillBeRawPtr<WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> > > keyframes = popKeyframes;
1743     m_allowImportRules = m_allowNamespaceDeclarations = false;
1744     RefPtrWillBeRawPtr<StyleRuleKeyframes> rule = StyleRuleKeyframes::create();
1745     for (size_t i = 0; i < keyframes->size(); ++i)
1746         rule->parserAppendKeyframe(keyframes->at(i));
1747     rule->setName(name);
1748     rule->setVendorPrefixed(isPrefixed);
1749     StyleRuleKeyframes* rulePtr = rule.get();
1750     m_parsedRules.append(rule.release());
1751     return rulePtr;
1752 }
1753
1754 static void recordSelectorStats(const CSSParserContext& context, const CSSSelectorList& selectorList)
1755 {
1756     if (!context.useCounter())
1757         return;
1758
1759     for (const CSSSelector* selector = selectorList.first(); selector; selector = CSSSelectorList::next(*selector)) {
1760         for (const CSSSelector* current = selector; current ; current = current->tagHistory()) {
1761             UseCounter::Feature feature = UseCounter::NumberOfFeatures;
1762             switch (current->pseudoType()) {
1763             case CSSSelector::PseudoUnresolved:
1764                 feature = UseCounter::CSSSelectorPseudoUnresolved;
1765                 break;
1766             case CSSSelector::PseudoShadow:
1767                 feature = UseCounter::CSSSelectorPseudoShadow;
1768                 break;
1769             case CSSSelector::PseudoContent:
1770                 feature = UseCounter::CSSSelectorPseudoContent;
1771                 break;
1772             case CSSSelector::PseudoHost:
1773                 feature = UseCounter::CSSSelectorPseudoHost;
1774                 break;
1775             case CSSSelector::PseudoHostContext:
1776                 feature = UseCounter::CSSSelectorPseudoHostContext;
1777                 break;
1778             default:
1779                 break;
1780             }
1781             if (feature != UseCounter::NumberOfFeatures)
1782                 context.useCounter()->count(feature);
1783             if (current->relation() == CSSSelector::ShadowDeep)
1784                 context.useCounter()->count(UseCounter::CSSDeepCombinator);
1785             if (current->selectorList())
1786                 recordSelectorStats(context, *current->selectorList());
1787         }
1788     }
1789 }
1790
1791 StyleRuleBase* BisonCSSParser::createStyleRule(Vector<OwnPtr<CSSParserSelector> >* selectors)
1792 {
1793     StyleRule* result = 0;
1794     if (selectors) {
1795         m_allowImportRules = m_allowNamespaceDeclarations = false;
1796         RefPtrWillBeRawPtr<StyleRule> rule = StyleRule::create();
1797         rule->parserAdoptSelectorVector(*selectors);
1798         rule->setProperties(createStylePropertySet());
1799         result = rule.get();
1800         m_parsedRules.append(rule.release());
1801         recordSelectorStats(m_context, result->selectorList());
1802     }
1803     clearProperties();
1804     return result;
1805 }
1806
1807 StyleRuleBase* BisonCSSParser::createFontFaceRule()
1808 {
1809     m_allowImportRules = m_allowNamespaceDeclarations = false;
1810     for (unsigned i = 0; i < m_parsedProperties.size(); ++i) {
1811         CSSProperty& property = m_parsedProperties[i];
1812         if (property.id() == CSSPropertyFontVariant && property.value()->isPrimitiveValue())
1813             property.wrapValueInCommaSeparatedList();
1814         else if (property.id() == CSSPropertyFontFamily && (!property.value()->isValueList() || toCSSValueList(property.value())->length() != 1)) {
1815             // Unlike font-family property, font-family descriptor in @font-face rule
1816             // has to be a value list with exactly one family name. It cannot have a
1817             // have 'initial' value and cannot 'inherit' from parent.
1818             // See http://dev.w3.org/csswg/css3-fonts/#font-family-desc
1819             clearProperties();
1820             return 0;
1821         }
1822     }
1823     RefPtrWillBeRawPtr<StyleRuleFontFace> rule = StyleRuleFontFace::create();
1824     rule->setProperties(createStylePropertySet());
1825     clearProperties();
1826     StyleRuleFontFace* result = rule.get();
1827     m_parsedRules.append(rule.release());
1828     if (m_styleSheet)
1829         m_styleSheet->setHasFontFaceRule(true);
1830     return result;
1831 }
1832
1833 void BisonCSSParser::addNamespace(const AtomicString& prefix, const AtomicString& uri)
1834 {
1835     if (!m_styleSheet || !m_allowNamespaceDeclarations)
1836         return;
1837     m_allowImportRules = false;
1838     m_styleSheet->parserAddNamespace(prefix, uri);
1839     if (prefix.isEmpty() && !uri.isNull())
1840         m_defaultNamespace = uri;
1841 }
1842
1843 QualifiedName BisonCSSParser::determineNameInNamespace(const AtomicString& prefix, const AtomicString& localName)
1844 {
1845     if (!m_styleSheet)
1846         return QualifiedName(prefix, localName, m_defaultNamespace);
1847     return QualifiedName(prefix, localName, m_styleSheet->determineNamespace(prefix));
1848 }
1849
1850 CSSParserSelector* BisonCSSParser::rewriteSpecifiersWithNamespaceIfNeeded(CSSParserSelector* specifiers)
1851 {
1852     if (m_defaultNamespace != starAtom || specifiers->crossesTreeScopes())
1853         return rewriteSpecifiersWithElementName(nullAtom, starAtom, specifiers, /*tagIsForNamespaceRule*/true);
1854     return specifiers;
1855 }
1856
1857 CSSParserSelector* BisonCSSParser::rewriteSpecifiersWithElementName(const AtomicString& namespacePrefix, const AtomicString& elementName, CSSParserSelector* specifiers, bool tagIsForNamespaceRule)
1858 {
1859     AtomicString determinedNamespace = namespacePrefix != nullAtom && m_styleSheet ? m_styleSheet->determineNamespace(namespacePrefix) : m_defaultNamespace;
1860     QualifiedName tag(namespacePrefix, elementName, determinedNamespace);
1861
1862     if (specifiers->crossesTreeScopes())
1863         return rewriteSpecifiersWithElementNameForCustomPseudoElement(tag, elementName, specifiers, tagIsForNamespaceRule);
1864
1865     if (specifiers->isContentPseudoElement())
1866         return rewriteSpecifiersWithElementNameForContentPseudoElement(tag, elementName, specifiers, tagIsForNamespaceRule);
1867
1868     // *:host never matches, so we can't discard the * otherwise we can't tell the
1869     // difference between *:host and just :host.
1870     if (tag == anyQName() && !specifiers->hasHostPseudoSelector())
1871         return specifiers;
1872     if (specifiers->pseudoType() != CSSSelector::PseudoCue)
1873         specifiers->prependTagSelector(tag, tagIsForNamespaceRule);
1874     return specifiers;
1875 }
1876
1877 CSSParserSelector* BisonCSSParser::rewriteSpecifiersWithElementNameForCustomPseudoElement(const QualifiedName& tag, const AtomicString& elementName, CSSParserSelector* specifiers, bool tagIsForNamespaceRule)
1878 {
1879     if (m_context.useCounter() && specifiers->pseudoType() == CSSSelector::PseudoUserAgentCustomElement)
1880         m_context.useCounter()->count(UseCounter::CSSPseudoElementUserAgentCustomPseudo);
1881
1882     CSSParserSelector* lastShadowPseudo = specifiers;
1883     CSSParserSelector* history = specifiers;
1884     while (history->tagHistory()) {
1885         history = history->tagHistory();
1886         if (history->crossesTreeScopes() || history->hasShadowPseudo())
1887             lastShadowPseudo = history;
1888     }
1889
1890     if (lastShadowPseudo->tagHistory()) {
1891         if (tag != anyQName())
1892             lastShadowPseudo->tagHistory()->prependTagSelector(tag, tagIsForNamespaceRule);
1893         return specifiers;
1894     }
1895
1896     // For shadow-ID pseudo-elements to be correctly matched, the ShadowPseudo combinator has to be used.
1897     // We therefore create a new Selector with that combinator here in any case, even if matching any (host) element in any namespace (i.e. '*').
1898     OwnPtr<CSSParserSelector> elementNameSelector = adoptPtr(new CSSParserSelector(tag));
1899     lastShadowPseudo->setTagHistory(elementNameSelector.release());
1900     lastShadowPseudo->setRelation(CSSSelector::ShadowPseudo);
1901     return specifiers;
1902 }
1903
1904 CSSParserSelector* BisonCSSParser::rewriteSpecifiersWithElementNameForContentPseudoElement(const QualifiedName& tag, const AtomicString& elementName, CSSParserSelector* specifiers, bool tagIsForNamespaceRule)
1905 {
1906     CSSParserSelector* last = specifiers;
1907     CSSParserSelector* history = specifiers;
1908     while (history->tagHistory()) {
1909         history = history->tagHistory();
1910         if (history->isContentPseudoElement() || history->relationIsAffectedByPseudoContent())
1911             last = history;
1912     }
1913
1914     if (last->tagHistory()) {
1915         if (tag != anyQName())
1916             last->tagHistory()->prependTagSelector(tag, tagIsForNamespaceRule);
1917         return specifiers;
1918     }
1919
1920     // For shadow-ID pseudo-elements to be correctly matched, the ShadowPseudo combinator has to be used.
1921     // We therefore create a new Selector with that combinator here in any case, even if matching any (host) element in any namespace (i.e. '*').
1922     OwnPtr<CSSParserSelector> elementNameSelector = adoptPtr(new CSSParserSelector(tag));
1923     last->setTagHistory(elementNameSelector.release());
1924     last->setRelation(CSSSelector::SubSelector);
1925     return specifiers;
1926 }
1927
1928 CSSParserSelector* BisonCSSParser::rewriteSpecifiers(CSSParserSelector* specifiers, CSSParserSelector* newSpecifier)
1929 {
1930     if (newSpecifier->crossesTreeScopes()) {
1931         // Unknown pseudo element always goes at the top of selector chain.
1932         newSpecifier->appendTagHistory(CSSSelector::ShadowPseudo, sinkFloatingSelector(specifiers));
1933         return newSpecifier;
1934     }
1935     if (newSpecifier->isContentPseudoElement()) {
1936         newSpecifier->appendTagHistory(CSSSelector::SubSelector, sinkFloatingSelector(specifiers));
1937         return newSpecifier;
1938     }
1939     if (specifiers->crossesTreeScopes()) {
1940         // Specifiers for unknown pseudo element go right behind it in the chain.
1941         specifiers->insertTagHistory(CSSSelector::SubSelector, sinkFloatingSelector(newSpecifier), CSSSelector::ShadowPseudo);
1942         return specifiers;
1943     }
1944     if (specifiers->isContentPseudoElement()) {
1945         specifiers->insertTagHistory(CSSSelector::SubSelector, sinkFloatingSelector(newSpecifier), CSSSelector::SubSelector);
1946         return specifiers;
1947     }
1948     specifiers->appendTagHistory(CSSSelector::SubSelector, sinkFloatingSelector(newSpecifier));
1949     return specifiers;
1950 }
1951
1952 StyleRuleBase* BisonCSSParser::createPageRule(PassOwnPtr<CSSParserSelector> pageSelector)
1953 {
1954     // FIXME: Margin at-rules are ignored.
1955     m_allowImportRules = m_allowNamespaceDeclarations = false;
1956     StyleRulePage* pageRule = 0;
1957     if (pageSelector) {
1958         RefPtrWillBeRawPtr<StyleRulePage> rule = StyleRulePage::create();
1959         Vector<OwnPtr<CSSParserSelector> > selectorVector;
1960         selectorVector.append(pageSelector);
1961         rule->parserAdoptSelectorVector(selectorVector);
1962         rule->setProperties(createStylePropertySet());
1963         pageRule = rule.get();
1964         m_parsedRules.append(rule.release());
1965     }
1966     clearProperties();
1967     return pageRule;
1968 }
1969
1970 StyleRuleBase* BisonCSSParser::createMarginAtRule(CSSSelector::MarginBoxType /* marginBox */)
1971 {
1972     // FIXME: Implement margin at-rule here, using:
1973     //        - marginBox: margin box
1974     //        - m_parsedProperties: properties at [m_numParsedPropertiesBeforeMarginBox, m_parsedProperties.size()] are for this at-rule.
1975     // Don't forget to also update the action for page symbol in CSSGrammar.y such that margin at-rule data is cleared if page_selector is invalid.
1976
1977     endDeclarationsForMarginBox();
1978     return 0; // until this method is implemented.
1979 }
1980
1981 void BisonCSSParser::startDeclarationsForMarginBox()
1982 {
1983     m_numParsedPropertiesBeforeMarginBox = m_parsedProperties.size();
1984 }
1985
1986 void BisonCSSParser::endDeclarationsForMarginBox()
1987 {
1988     rollbackLastProperties(m_parsedProperties.size() - m_numParsedPropertiesBeforeMarginBox);
1989     m_numParsedPropertiesBeforeMarginBox = INVALID_NUM_PARSED_PROPERTIES;
1990 }
1991
1992 StyleKeyframe* BisonCSSParser::createKeyframe(CSSParserValueList* keys)
1993 {
1994     OwnPtr<Vector<double> > keyVector = StyleKeyframe::createKeyList(keys);
1995     if (keyVector->isEmpty())
1996         return 0;
1997
1998     RefPtrWillBeRawPtr<StyleKeyframe> keyframe = StyleKeyframe::create();
1999     keyframe->setKeys(keyVector.release());
2000     keyframe->setProperties(createStylePropertySet());
2001
2002     clearProperties();
2003
2004     StyleKeyframe* keyframePtr = keyframe.get();
2005     m_parsedKeyframes.append(keyframe.release());
2006     return keyframePtr;
2007 }
2008
2009 void BisonCSSParser::invalidBlockHit()
2010 {
2011     if (m_styleSheet && !m_hadSyntacticallyValidCSSRule)
2012         m_styleSheet->setHasSyntacticallyValidCSSHeader(false);
2013 }
2014
2015 void BisonCSSParser::startRule()
2016 {
2017     if (!m_observer)
2018         return;
2019
2020     ASSERT(m_ruleHasHeader);
2021     m_ruleHasHeader = false;
2022 }
2023
2024 void BisonCSSParser::endRule(bool valid)
2025 {
2026     if (!m_observer)
2027         return;
2028
2029     if (m_ruleHasHeader)
2030         m_observer->endRuleBody(m_tokenizer.safeUserStringTokenOffset(), !valid);
2031     m_ruleHasHeader = true;
2032 }
2033
2034 void BisonCSSParser::startRuleHeader(CSSRuleSourceData::Type ruleType)
2035 {
2036     resumeErrorLogging();
2037     m_ruleHeaderType = ruleType;
2038     m_ruleHeaderStartOffset = m_tokenizer.safeUserStringTokenOffset();
2039     m_ruleHeaderStartLineNumber = m_tokenizer.m_tokenStartLineNumber;
2040     if (m_observer) {
2041         ASSERT(!m_ruleHasHeader);
2042         m_observer->startRuleHeader(ruleType, m_ruleHeaderStartOffset);
2043         m_ruleHasHeader = true;
2044     }
2045 }
2046
2047 void BisonCSSParser::endRuleHeader()
2048 {
2049     ASSERT(m_ruleHeaderType != CSSRuleSourceData::UNKNOWN_RULE);
2050     m_ruleHeaderType = CSSRuleSourceData::UNKNOWN_RULE;
2051     if (m_observer) {
2052         ASSERT(m_ruleHasHeader);
2053         m_observer->endRuleHeader(m_tokenizer.safeUserStringTokenOffset());
2054     }
2055 }
2056
2057 void BisonCSSParser::startSelector()
2058 {
2059     if (m_observer)
2060         m_observer->startSelector(m_tokenizer.safeUserStringTokenOffset());
2061 }
2062
2063 void BisonCSSParser::endSelector()
2064 {
2065     if (m_observer)
2066         m_observer->endSelector(m_tokenizer.safeUserStringTokenOffset());
2067 }
2068
2069 void BisonCSSParser::startRuleBody()
2070 {
2071     if (m_observer)
2072         m_observer->startRuleBody(m_tokenizer.safeUserStringTokenOffset());
2073 }
2074
2075 void BisonCSSParser::startProperty()
2076 {
2077     resumeErrorLogging();
2078     if (m_observer)
2079         m_observer->startProperty(m_tokenizer.safeUserStringTokenOffset());
2080 }
2081
2082 void BisonCSSParser::endProperty(bool isImportantFound, bool isPropertyParsed, CSSParserError errorType)
2083 {
2084     m_id = CSSPropertyInvalid;
2085     if (m_observer)
2086         m_observer->endProperty(isImportantFound, isPropertyParsed, m_tokenizer.safeUserStringTokenOffset(), errorType);
2087 }
2088
2089 void BisonCSSParser::startEndUnknownRule()
2090 {
2091     if (m_observer)
2092         m_observer->startEndUnknownRule();
2093 }
2094
2095 StyleRuleBase* BisonCSSParser::createViewportRule()
2096 {
2097     // Allow @viewport rules from UA stylesheets even if the feature is disabled.
2098     if (!RuntimeEnabledFeatures::cssViewportEnabled() && !isUASheetBehavior(m_context.mode()))
2099         return 0;
2100
2101     m_allowImportRules = m_allowNamespaceDeclarations = false;
2102
2103     RefPtrWillBeRawPtr<StyleRuleViewport> rule = StyleRuleViewport::create();
2104
2105     rule->setProperties(createStylePropertySet());
2106     clearProperties();
2107
2108     StyleRuleViewport* result = rule.get();
2109     m_parsedRules.append(rule.release());
2110
2111     return result;
2112 }
2113
2114 }