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