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