summaryrefslogtreecommitdiffstats
path: root/chromium/third_party/WebKit/Source/core/css/parser/BisonCSSParser-in.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/WebKit/Source/core/css/parser/BisonCSSParser-in.cpp')
-rw-r--r--chromium/third_party/WebKit/Source/core/css/parser/BisonCSSParser-in.cpp2119
1 files changed, 2119 insertions, 0 deletions
diff --git a/chromium/third_party/WebKit/Source/core/css/parser/BisonCSSParser-in.cpp b/chromium/third_party/WebKit/Source/core/css/parser/BisonCSSParser-in.cpp
new file mode 100644
index 00000000000..4b366c75d11
--- /dev/null
+++ b/chromium/third_party/WebKit/Source/core/css/parser/BisonCSSParser-in.cpp
@@ -0,0 +1,2119 @@
+/*
+ * Copyright (C) 2003 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Nicholas Shanks <webkit@nickshanks.com>
+ * Copyright (C) 2008 Eric Seidel <eric@webkit.org>
+ * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
+ * Copyright (C) 2012 Intel Corporation. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "core/css/parser/BisonCSSParser.h"
+
+#include "core/CSSValueKeywords.h"
+#include "core/StylePropertyShorthand.h"
+#include "core/css/CSSArrayFunctionValue.h"
+#include "core/css/CSSAspectRatioValue.h"
+#include "core/css/CSSBasicShapes.h"
+#include "core/css/CSSBorderImage.h"
+#include "core/css/CSSCanvasValue.h"
+#include "core/css/CSSCrossfadeValue.h"
+#include "core/css/CSSCursorImageValue.h"
+#include "core/css/CSSFontFaceSrcValue.h"
+#include "core/css/CSSFontFeatureValue.h"
+#include "core/css/CSSFunctionValue.h"
+#include "core/css/CSSGradientValue.h"
+#include "core/css/CSSGridLineNamesValue.h"
+#include "core/css/CSSGridTemplateAreasValue.h"
+#include "core/css/CSSImageSetValue.h"
+#include "core/css/CSSImageValue.h"
+#include "core/css/CSSInheritedValue.h"
+#include "core/css/CSSInitialValue.h"
+#include "core/css/CSSKeyframeRule.h"
+#include "core/css/CSSKeyframesRule.h"
+#include "core/css/CSSLineBoxContainValue.h"
+#include "core/css/CSSPrimitiveValue.h"
+#include "core/css/CSSPropertySourceData.h"
+#include "core/css/CSSReflectValue.h"
+#include "core/css/CSSSelector.h"
+#include "core/css/CSSShadowValue.h"
+#include "core/css/CSSStyleSheet.h"
+#include "core/css/CSSTimingFunctionValue.h"
+#include "core/css/CSSTransformValue.h"
+#include "core/css/CSSUnicodeRangeValue.h"
+#include "core/css/CSSValueList.h"
+#include "core/css/CSSValuePool.h"
+#include "core/css/Counter.h"
+#include "core/css/HashTools.h"
+#include "core/css/MediaList.h"
+#include "core/css/MediaQueryExp.h"
+#include "core/css/Pair.h"
+#include "core/css/Rect.h"
+#include "core/css/StylePropertySet.h"
+#include "core/css/StyleRule.h"
+#include "core/css/StyleRuleImport.h"
+#include "core/css/StyleSheetContents.h"
+#include "core/css/parser/CSSParserIdioms.h"
+#include "core/dom/Document.h"
+#include "core/frame/FrameConsole.h"
+#include "core/frame/FrameHost.h"
+#include "core/frame/Settings.h"
+#include "core/html/parser/HTMLParserIdioms.h"
+#include "core/inspector/InspectorInstrumentation.h"
+#include "core/rendering/RenderTheme.h"
+#include "platform/FloatConversion.h"
+#include "platform/RuntimeEnabledFeatures.h"
+#include "wtf/BitArray.h"
+#include "wtf/HexNumber.h"
+#include "wtf/text/StringBuffer.h"
+#include "wtf/text/StringBuilder.h"
+#include "wtf/text/StringImpl.h"
+#include "wtf/text/TextEncoding.h"
+#include <limits.h>
+
+#define YYDEBUG 0
+
+#if YYDEBUG > 0
+extern int cssyydebug;
+#endif
+
+int cssyyparse(WebCore::BisonCSSParser*);
+
+using namespace WTF;
+
+namespace WebCore {
+
+static const unsigned INVALID_NUM_PARSED_PROPERTIES = UINT_MAX;
+
+BisonCSSParser::BisonCSSParser(const CSSParserContext& context)
+ : m_context(context)
+ , m_important(false)
+ , m_id(CSSPropertyInvalid)
+ , m_styleSheet(nullptr)
+ , m_supportsCondition(false)
+ , m_selectorListForParseSelector(0)
+ , m_numParsedPropertiesBeforeMarginBox(INVALID_NUM_PARSED_PROPERTIES)
+ , m_hadSyntacticallyValidCSSRule(false)
+ , m_logErrors(false)
+ , m_ignoreErrors(false)
+ , m_defaultNamespace(starAtom)
+ , m_observer(0)
+ , m_source(0)
+ , m_ruleHeaderType(CSSRuleSourceData::UNKNOWN_RULE)
+ , m_allowImportRules(true)
+ , m_allowNamespaceDeclarations(true)
+ , m_inViewport(false)
+ , m_tokenizer(*this)
+{
+#if YYDEBUG > 0
+ cssyydebug = 1;
+#endif
+}
+
+BisonCSSParser::~BisonCSSParser()
+{
+ clearProperties();
+
+ deleteAllValues(m_floatingSelectors);
+ deleteAllValues(m_floatingSelectorVectors);
+ deleteAllValues(m_floatingValueLists);
+ deleteAllValues(m_floatingFunctions);
+}
+
+void BisonCSSParser::setupParser(const char* prefix, unsigned prefixLength, const String& string, const char* suffix, unsigned suffixLength)
+{
+ m_tokenizer.setupTokenizer(prefix, prefixLength, string, suffix, suffixLength);
+ m_ruleHasHeader = true;
+}
+
+void BisonCSSParser::parseSheet(StyleSheetContents* sheet, const String& string, const TextPosition& startPosition, CSSParserObserver* observer, bool logErrors)
+{
+ setStyleSheet(sheet);
+ m_defaultNamespace = starAtom; // Reset the default namespace.
+ TemporaryChange<CSSParserObserver*> scopedObsever(m_observer, observer);
+ m_logErrors = logErrors && sheet->singleOwnerDocument() && !sheet->baseURL().isEmpty() && sheet->singleOwnerDocument()->frameHost();
+ m_ignoreErrors = false;
+ m_tokenizer.m_lineNumber = 0;
+ m_startPosition = startPosition;
+ m_source = &string;
+ m_tokenizer.m_internal = false;
+ setupParser("", string, "");
+ cssyyparse(this);
+ sheet->shrinkToFit();
+ m_source = 0;
+ m_rule = nullptr;
+ m_lineEndings.clear();
+ m_ignoreErrors = false;
+ m_logErrors = false;
+ m_tokenizer.m_internal = true;
+}
+
+PassRefPtrWillBeRawPtr<StyleRuleBase> BisonCSSParser::parseRule(StyleSheetContents* sheet, const String& string)
+{
+ setStyleSheet(sheet);
+ m_allowNamespaceDeclarations = false;
+ setupParser("@-internal-rule ", string, "");
+ cssyyparse(this);
+ return m_rule.release();
+}
+
+PassRefPtrWillBeRawPtr<StyleKeyframe> BisonCSSParser::parseKeyframeRule(StyleSheetContents* sheet, const String& string)
+{
+ setStyleSheet(sheet);
+ setupParser("@-internal-keyframe-rule ", string, "");
+ cssyyparse(this);
+ return m_keyframe.release();
+}
+
+PassOwnPtr<Vector<double> > BisonCSSParser::parseKeyframeKeyList(const String& string)
+{
+ setupParser("@-internal-keyframe-key-list ", string, "");
+ cssyyparse(this);
+ ASSERT(m_valueList);
+ return StyleKeyframe::createKeyList(m_valueList.get());
+}
+
+bool BisonCSSParser::parseSupportsCondition(const String& string)
+{
+ m_supportsCondition = false;
+ setupParser("@-internal-supports-condition ", string, "");
+ cssyyparse(this);
+ return m_supportsCondition;
+}
+
+static inline bool isColorPropertyID(CSSPropertyID propertyId)
+{
+ switch (propertyId) {
+ case CSSPropertyColor:
+ case CSSPropertyBackgroundColor:
+ case CSSPropertyBorderBottomColor:
+ case CSSPropertyBorderLeftColor:
+ case CSSPropertyBorderRightColor:
+ case CSSPropertyBorderTopColor:
+ case CSSPropertyOutlineColor:
+ case CSSPropertyTextLineThroughColor:
+ case CSSPropertyTextOverlineColor:
+ case CSSPropertyTextUnderlineColor:
+ case CSSPropertyWebkitBorderAfterColor:
+ case CSSPropertyWebkitBorderBeforeColor:
+ case CSSPropertyWebkitBorderEndColor:
+ case CSSPropertyWebkitBorderStartColor:
+ case CSSPropertyWebkitColumnRuleColor:
+ case CSSPropertyWebkitTextEmphasisColor:
+ case CSSPropertyWebkitTextFillColor:
+ case CSSPropertyWebkitTextStrokeColor:
+ return true;
+ case CSSPropertyTextDecorationColor:
+ return RuntimeEnabledFeatures::css3TextDecorationsEnabled();
+ default:
+ return false;
+ }
+}
+
+static bool parseColorValue(MutableStylePropertySet* declaration, CSSPropertyID propertyId, const String& string, bool important, CSSParserMode cssParserMode)
+{
+ ASSERT(!string.isEmpty());
+ bool quirksMode = isQuirksModeBehavior(cssParserMode);
+ if (!isColorPropertyID(propertyId))
+ return false;
+ CSSParserString cssString;
+ cssString.init(string);
+ CSSValueID valueID = cssValueKeywordID(cssString);
+ bool validPrimitive = false;
+ if (valueID == CSSValueWebkitText) {
+ validPrimitive = true;
+ } else if (valueID == CSSValueCurrentcolor) {
+ validPrimitive = true;
+ } else if ((valueID >= CSSValueAqua && valueID <= CSSValueWindowtext) || valueID == CSSValueMenu
+ || (quirksMode && valueID >= CSSValueWebkitFocusRingColor && valueID < CSSValueWebkitText)) {
+ validPrimitive = true;
+ }
+
+ if (validPrimitive) {
+ RefPtrWillBeRawPtr<CSSValue> value = cssValuePool().createIdentifierValue(valueID);
+ declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important));
+ return true;
+ }
+ RGBA32 color;
+ if (!CSSPropertyParser::fastParseColor(color, string, !quirksMode && string[0] != '#'))
+ return false;
+ RefPtrWillBeRawPtr<CSSValue> value = cssValuePool().createColorValue(color);
+ declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important));
+ return true;
+}
+
+static inline bool isSimpleLengthPropertyID(CSSPropertyID propertyId, bool& acceptsNegativeNumbers)
+{
+ switch (propertyId) {
+ case CSSPropertyFontSize:
+ case CSSPropertyHeight:
+ case CSSPropertyWidth:
+ case CSSPropertyMinHeight:
+ case CSSPropertyMinWidth:
+ case CSSPropertyPaddingBottom:
+ case CSSPropertyPaddingLeft:
+ case CSSPropertyPaddingRight:
+ case CSSPropertyPaddingTop:
+ case CSSPropertyWebkitLogicalWidth:
+ case CSSPropertyWebkitLogicalHeight:
+ case CSSPropertyWebkitMinLogicalWidth:
+ case CSSPropertyWebkitMinLogicalHeight:
+ case CSSPropertyWebkitPaddingAfter:
+ case CSSPropertyWebkitPaddingBefore:
+ case CSSPropertyWebkitPaddingEnd:
+ case CSSPropertyWebkitPaddingStart:
+ acceptsNegativeNumbers = false;
+ return true;
+ case CSSPropertyShapeMargin:
+ acceptsNegativeNumbers = false;
+ return RuntimeEnabledFeatures::cssShapesEnabled();
+ case CSSPropertyBottom:
+ case CSSPropertyLeft:
+ case CSSPropertyMarginBottom:
+ case CSSPropertyMarginLeft:
+ case CSSPropertyMarginRight:
+ case CSSPropertyMarginTop:
+ case CSSPropertyRight:
+ case CSSPropertyTop:
+ case CSSPropertyWebkitMarginAfter:
+ case CSSPropertyWebkitMarginBefore:
+ case CSSPropertyWebkitMarginEnd:
+ case CSSPropertyWebkitMarginStart:
+ acceptsNegativeNumbers = true;
+ return true;
+ default:
+ return false;
+ }
+}
+
+template <typename CharacterType>
+static inline bool parseSimpleLength(const CharacterType* characters, unsigned length, CSSPrimitiveValue::UnitType& unit, double& number)
+{
+ if (length > 2 && (characters[length - 2] | 0x20) == 'p' && (characters[length - 1] | 0x20) == 'x') {
+ length -= 2;
+ unit = CSSPrimitiveValue::CSS_PX;
+ } else if (length > 1 && characters[length - 1] == '%') {
+ length -= 1;
+ unit = CSSPrimitiveValue::CSS_PERCENTAGE;
+ }
+
+ // We rely on charactersToDouble for validation as well. The function
+ // will set "ok" to "false" if the entire passed-in character range does
+ // not represent a double.
+ bool ok;
+ number = charactersToDouble(characters, length, &ok);
+ return ok;
+}
+
+static bool parseSimpleLengthValue(MutableStylePropertySet* declaration, CSSPropertyID propertyId, const String& string, bool important, CSSParserMode cssParserMode)
+{
+ ASSERT(!string.isEmpty());
+ bool acceptsNegativeNumbers = false;
+
+ // In @viewport, width and height are shorthands, not simple length values.
+ if (isCSSViewportParsingEnabledForMode(cssParserMode) || !isSimpleLengthPropertyID(propertyId, acceptsNegativeNumbers))
+ return false;
+
+ unsigned length = string.length();
+ double number;
+ CSSPrimitiveValue::UnitType unit = CSSPrimitiveValue::CSS_NUMBER;
+
+ if (string.is8Bit()) {
+ if (!parseSimpleLength(string.characters8(), length, unit, number))
+ return false;
+ } else {
+ if (!parseSimpleLength(string.characters16(), length, unit, number))
+ return false;
+ }
+
+ if (unit == CSSPrimitiveValue::CSS_NUMBER) {
+ bool quirksMode = isQuirksModeBehavior(cssParserMode);
+ if (number && !quirksMode)
+ return false;
+ unit = CSSPrimitiveValue::CSS_PX;
+ }
+ if (number < 0 && !acceptsNegativeNumbers)
+ return false;
+
+ RefPtrWillBeRawPtr<CSSValue> value = cssValuePool().createValue(number, unit);
+ declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important));
+ return true;
+}
+
+bool isValidKeywordPropertyAndValue(CSSPropertyID propertyId, CSSValueID valueID, const CSSParserContext& parserContext)
+{
+ if (valueID == CSSValueInvalid)
+ return false;
+
+ switch (propertyId) {
+ case CSSPropertyBackgroundRepeatX: // repeat | no-repeat
+ case CSSPropertyBackgroundRepeatY: // repeat | no-repeat
+ return valueID == CSSValueRepeat || valueID == CSSValueNoRepeat;
+ case CSSPropertyBorderCollapse: // collapse | separate
+ return valueID == CSSValueCollapse || valueID == CSSValueSeparate;
+ case CSSPropertyBorderTopStyle: // <border-style>
+ case CSSPropertyBorderRightStyle: // Defined as: none | hidden | dotted | dashed |
+ case CSSPropertyBorderBottomStyle: // solid | double | groove | ridge | inset | outset
+ case CSSPropertyBorderLeftStyle:
+ case CSSPropertyWebkitBorderAfterStyle:
+ case CSSPropertyWebkitBorderBeforeStyle:
+ case CSSPropertyWebkitBorderEndStyle:
+ case CSSPropertyWebkitBorderStartStyle:
+ case CSSPropertyWebkitColumnRuleStyle:
+ return valueID >= CSSValueNone && valueID <= CSSValueDouble;
+ case CSSPropertyBoxSizing:
+ return valueID == CSSValueBorderBox || valueID == CSSValueContentBox;
+ case CSSPropertyCaptionSide: // top | bottom | left | right
+ return valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueTop || valueID == CSSValueBottom;
+ case CSSPropertyClear: // none | left | right | both
+ return valueID == CSSValueNone || valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueBoth;
+ case CSSPropertyDirection: // ltr | rtl
+ return valueID == CSSValueLtr || valueID == CSSValueRtl;
+ case CSSPropertyDisplay:
+ // inline | block | list-item | inline-block | table |
+ // inline-table | table-row-group | table-header-group | table-footer-group | table-row |
+ // table-column-group | table-column | table-cell | table-caption | -webkit-box | -webkit-inline-box | none
+ // flex | inline-flex | -webkit-flex | -webkit-inline-flex | grid | inline-grid | lazy-block
+ return (valueID >= CSSValueInline && valueID <= CSSValueInlineFlex) || valueID == CSSValueWebkitFlex || valueID == CSSValueWebkitInlineFlex || valueID == CSSValueNone
+ || (RuntimeEnabledFeatures::cssGridLayoutEnabled() && (valueID == CSSValueGrid || valueID == CSSValueInlineGrid));
+ case CSSPropertyEmptyCells: // show | hide
+ return valueID == CSSValueShow || valueID == CSSValueHide;
+ case CSSPropertyFloat: // left | right | none | center (for buggy CSS, maps to none)
+ return valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueNone || valueID == CSSValueCenter;
+ case CSSPropertyFontStyle: // normal | italic | oblique
+ return valueID == CSSValueNormal || valueID == CSSValueItalic || valueID == CSSValueOblique;
+ case CSSPropertyImageRendering: // auto | optimizeContrast
+ return valueID == CSSValueAuto || valueID == CSSValueWebkitOptimizeContrast;
+ case CSSPropertyIsolation: // auto | isolate
+ return RuntimeEnabledFeatures::cssCompositingEnabled()
+ && (valueID == CSSValueAuto || valueID == CSSValueIsolate);
+ case CSSPropertyListStylePosition: // inside | outside
+ return valueID == CSSValueInside || valueID == CSSValueOutside;
+ case CSSPropertyListStyleType:
+ // See section CSS_PROP_LIST_STYLE_TYPE of file CSSValueKeywords.in
+ // for the list of supported list-style-types.
+ return (valueID >= CSSValueDisc && valueID <= CSSValueKatakanaIroha) || valueID == CSSValueNone;
+ case CSSPropertyObjectFit:
+ return RuntimeEnabledFeatures::objectFitPositionEnabled()
+ && (valueID == CSSValueFill || valueID == CSSValueContain || valueID == CSSValueCover || valueID == CSSValueNone || valueID == CSSValueScaleDown);
+ case CSSPropertyOutlineStyle: // (<border-style> except hidden) | auto
+ return valueID == CSSValueAuto || valueID == CSSValueNone || (valueID >= CSSValueInset && valueID <= CSSValueDouble);
+ case CSSPropertyOverflowWrap: // normal | break-word
+ case CSSPropertyWordWrap:
+ return valueID == CSSValueNormal || valueID == CSSValueBreakWord;
+ case CSSPropertyOverflowX: // visible | hidden | scroll | auto | overlay
+ return valueID == CSSValueVisible || valueID == CSSValueHidden || valueID == CSSValueScroll || valueID == CSSValueAuto || valueID == CSSValueOverlay;
+ case CSSPropertyOverflowY: // visible | hidden | scroll | auto | overlay | -webkit-paged-x | -webkit-paged-y
+ return valueID == CSSValueVisible || valueID == CSSValueHidden || valueID == CSSValueScroll || valueID == CSSValueAuto || valueID == CSSValueOverlay || valueID == CSSValueWebkitPagedX || valueID == CSSValueWebkitPagedY;
+ case CSSPropertyPageBreakAfter: // auto | always | avoid | left | right
+ case CSSPropertyPageBreakBefore:
+ case CSSPropertyWebkitColumnBreakAfter:
+ case CSSPropertyWebkitColumnBreakBefore:
+ return valueID == CSSValueAuto || valueID == CSSValueAlways || valueID == CSSValueAvoid || valueID == CSSValueLeft || valueID == CSSValueRight;
+ case CSSPropertyPageBreakInside: // avoid | auto
+ case CSSPropertyWebkitColumnBreakInside:
+ return valueID == CSSValueAuto || valueID == CSSValueAvoid;
+ case CSSPropertyPointerEvents:
+ // none | visiblePainted | visibleFill | visibleStroke | visible |
+ // painted | fill | stroke | auto | all | bounding-box
+ return valueID == CSSValueVisible || valueID == CSSValueNone || valueID == CSSValueAll || valueID == CSSValueAuto || (valueID >= CSSValueVisiblepainted && valueID <= CSSValueBoundingBox);
+ case CSSPropertyPosition: // static | relative | absolute | fixed | sticky
+ return valueID == CSSValueStatic || valueID == CSSValueRelative || valueID == CSSValueAbsolute || valueID == CSSValueFixed
+ || (RuntimeEnabledFeatures::cssStickyPositionEnabled() && valueID == CSSValueSticky);
+ case CSSPropertyResize: // none | both | horizontal | vertical | auto
+ return valueID == CSSValueNone || valueID == CSSValueBoth || valueID == CSSValueHorizontal || valueID == CSSValueVertical || valueID == CSSValueAuto;
+ case CSSPropertyScrollBehavior: // instant | smooth
+ return RuntimeEnabledFeatures::cssomSmoothScrollEnabled()
+ && (valueID == CSSValueInstant || valueID == CSSValueSmooth);
+ case CSSPropertySpeak: // none | normal | spell-out | digits | literal-punctuation | no-punctuation
+ return valueID == CSSValueNone || valueID == CSSValueNormal || valueID == CSSValueSpellOut || valueID == CSSValueDigits || valueID == CSSValueLiteralPunctuation || valueID == CSSValueNoPunctuation;
+ case CSSPropertyTableLayout: // auto | fixed
+ return valueID == CSSValueAuto || valueID == CSSValueFixed;
+ case CSSPropertyTextAlignLast:
+ // auto | start | end | left | right | center | justify
+ return RuntimeEnabledFeatures::css3TextEnabled()
+ && ((valueID >= CSSValueLeft && valueID <= CSSValueJustify) || valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueAuto);
+ case CSSPropertyTextJustify:
+ // auto | none | inter-word | distribute
+ return RuntimeEnabledFeatures::css3TextEnabled()
+ && (valueID == CSSValueInterWord || valueID == CSSValueDistribute || valueID == CSSValueAuto || valueID == CSSValueNone);
+ case CSSPropertyTextLineThroughMode:
+ case CSSPropertyTextOverlineMode:
+ case CSSPropertyTextUnderlineMode:
+ return valueID == CSSValueContinuous || valueID == CSSValueSkipWhiteSpace;
+ case CSSPropertyTextLineThroughStyle:
+ case CSSPropertyTextOverlineStyle:
+ case CSSPropertyTextUnderlineStyle:
+ return valueID == CSSValueNone || valueID == CSSValueSolid || valueID == CSSValueDouble || valueID == CSSValueDashed || valueID == CSSValueDotDash || valueID == CSSValueDotDotDash || valueID == CSSValueWave;
+ case CSSPropertyTextOverflow: // clip | ellipsis
+ return valueID == CSSValueClip || valueID == CSSValueEllipsis;
+ case CSSPropertyTextRendering: // auto | optimizeSpeed | optimizeLegibility | geometricPrecision
+ return valueID == CSSValueAuto || valueID == CSSValueOptimizespeed || valueID == CSSValueOptimizelegibility || valueID == CSSValueGeometricprecision;
+ case CSSPropertyTextTransform: // capitalize | uppercase | lowercase | none
+ return (valueID >= CSSValueCapitalize && valueID <= CSSValueLowercase) || valueID == CSSValueNone;
+ case CSSPropertyTouchActionDelay: // none | script
+ return RuntimeEnabledFeatures::cssTouchActionDelayEnabled()
+ && (valueID == CSSValueScript || valueID == CSSValueNone);
+ case CSSPropertyVisibility: // visible | hidden | collapse
+ return valueID == CSSValueVisible || valueID == CSSValueHidden || valueID == CSSValueCollapse;
+ case CSSPropertyWebkitAppearance:
+ return (valueID >= CSSValueCheckbox && valueID <= CSSValueTextarea) || valueID == CSSValueNone;
+ case CSSPropertyBackfaceVisibility:
+ case CSSPropertyWebkitBackfaceVisibility:
+ return valueID == CSSValueVisible || valueID == CSSValueHidden;
+ case CSSPropertyMixBlendMode:
+ return RuntimeEnabledFeatures::cssCompositingEnabled()
+ && (valueID == CSSValueNormal || valueID == CSSValueMultiply || valueID == CSSValueScreen || valueID == CSSValueOverlay
+ || valueID == CSSValueDarken || valueID == CSSValueLighten || valueID == CSSValueColorDodge || valueID == CSSValueColorBurn
+ || valueID == CSSValueHardLight || valueID == CSSValueSoftLight || valueID == CSSValueDifference || valueID == CSSValueExclusion
+ || valueID == CSSValueHue || valueID == CSSValueSaturation || valueID == CSSValueColor || valueID == CSSValueLuminosity);
+ case CSSPropertyWebkitBorderFit:
+ return valueID == CSSValueBorder || valueID == CSSValueLines;
+ case CSSPropertyWebkitBoxAlign:
+ return valueID == CSSValueStretch || valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueCenter || valueID == CSSValueBaseline;
+ case CSSPropertyWebkitBoxDecorationBreak:
+ return valueID == CSSValueClone || valueID == CSSValueSlice;
+ case CSSPropertyWebkitBoxDirection:
+ return valueID == CSSValueNormal || valueID == CSSValueReverse;
+ case CSSPropertyWebkitBoxLines:
+ return valueID == CSSValueSingle || valueID == CSSValueMultiple;
+ case CSSPropertyWebkitBoxOrient:
+ return valueID == CSSValueHorizontal || valueID == CSSValueVertical || valueID == CSSValueInlineAxis || valueID == CSSValueBlockAxis;
+ case CSSPropertyWebkitBoxPack:
+ return valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueCenter || valueID == CSSValueJustify;
+ case CSSPropertyInternalCallback:
+ // This property is only injected programmatically, not parsed from stylesheets.
+ return false;
+ case CSSPropertyColumnFill:
+ return RuntimeEnabledFeatures::regionBasedColumnsEnabled()
+ && (valueID == CSSValueAuto || valueID == CSSValueBalance);
+ case CSSPropertyAlignContent:
+ // FIXME: Per CSS alignment, this property should accept an optional <overflow-position>. We should share this parsing code with 'justify-self'.
+ return valueID == CSSValueFlexStart || valueID == CSSValueFlexEnd || valueID == CSSValueCenter || valueID == CSSValueSpaceBetween || valueID == CSSValueSpaceAround || valueID == CSSValueStretch;
+ case CSSPropertyAlignItems:
+ // FIXME: Per CSS alignment, this property should accept the same arguments as 'justify-self' so we should share its parsing code.
+ return valueID == CSSValueFlexStart || valueID == CSSValueFlexEnd || valueID == CSSValueCenter || valueID == CSSValueBaseline || valueID == CSSValueStretch;
+ case CSSPropertyAlignSelf:
+ // FIXME: Per CSS alignment, this property should accept the same arguments as 'justify-self' so we should share its parsing code.
+ return valueID == CSSValueAuto || valueID == CSSValueFlexStart || valueID == CSSValueFlexEnd || valueID == CSSValueCenter || valueID == CSSValueBaseline || valueID == CSSValueStretch;
+ case CSSPropertyFlexDirection:
+ return valueID == CSSValueRow || valueID == CSSValueRowReverse || valueID == CSSValueColumn || valueID == CSSValueColumnReverse;
+ case CSSPropertyFlexWrap:
+ return valueID == CSSValueNowrap || valueID == CSSValueWrap || valueID == CSSValueWrapReverse;
+ case CSSPropertyJustifyContent:
+ // FIXME: Per CSS alignment, this property should accept an optional <overflow-position>. We should share this parsing code with 'justify-self'.
+ return valueID == CSSValueFlexStart || valueID == CSSValueFlexEnd || valueID == CSSValueCenter || valueID == CSSValueSpaceBetween || valueID == CSSValueSpaceAround;
+ case CSSPropertyFontKerning:
+ return valueID == CSSValueAuto || valueID == CSSValueNormal || valueID == CSSValueNone;
+ case CSSPropertyWebkitFontSmoothing:
+ return valueID == CSSValueAuto || valueID == CSSValueNone || valueID == CSSValueAntialiased || valueID == CSSValueSubpixelAntialiased;
+ case CSSPropertyGridAutoFlow:
+ return RuntimeEnabledFeatures::cssGridLayoutEnabled()
+ && (valueID == CSSValueNone || valueID == CSSValueRow || valueID == CSSValueColumn);
+ case CSSPropertyWebkitLineBreak: // auto | loose | normal | strict | after-white-space
+ return valueID == CSSValueAuto || valueID == CSSValueLoose || valueID == CSSValueNormal || valueID == CSSValueStrict || valueID == CSSValueAfterWhiteSpace;
+ case CSSPropertyWebkitMarginAfterCollapse:
+ case CSSPropertyWebkitMarginBeforeCollapse:
+ case CSSPropertyWebkitMarginBottomCollapse:
+ case CSSPropertyWebkitMarginTopCollapse:
+ return valueID == CSSValueCollapse || valueID == CSSValueSeparate || valueID == CSSValueDiscard;
+ case CSSPropertyInternalMarqueeDirection:
+ return valueID == CSSValueForwards || valueID == CSSValueBackwards || valueID == CSSValueAhead || valueID == CSSValueReverse || valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueDown
+ || valueID == CSSValueUp || valueID == CSSValueAuto;
+ case CSSPropertyInternalMarqueeStyle:
+ return valueID == CSSValueNone || valueID == CSSValueSlide || valueID == CSSValueScroll || valueID == CSSValueAlternate;
+ case CSSPropertyWebkitPrintColorAdjust:
+ return valueID == CSSValueExact || valueID == CSSValueEconomy;
+ case CSSPropertyWebkitRtlOrdering:
+ return valueID == CSSValueLogical || valueID == CSSValueVisual;
+ case CSSPropertyWebkitRubyPosition:
+ return valueID == CSSValueBefore || valueID == CSSValueAfter;
+ case CSSPropertyWebkitTextCombine:
+ return valueID == CSSValueNone || valueID == CSSValueHorizontal;
+ case CSSPropertyWebkitTextEmphasisPosition:
+ return valueID == CSSValueOver || valueID == CSSValueUnder;
+ case CSSPropertyWebkitTextSecurity: // disc | circle | square | none
+ return valueID == CSSValueDisc || valueID == CSSValueCircle || valueID == CSSValueSquare || valueID == CSSValueNone;
+ case CSSPropertyTransformStyle:
+ case CSSPropertyWebkitTransformStyle:
+ return valueID == CSSValueFlat || valueID == CSSValuePreserve3d;
+ case CSSPropertyWebkitUserDrag: // auto | none | element
+ return valueID == CSSValueAuto || valueID == CSSValueNone || valueID == CSSValueElement;
+ case CSSPropertyWebkitUserModify: // read-only | read-write
+ return valueID == CSSValueReadOnly || valueID == CSSValueReadWrite || valueID == CSSValueReadWritePlaintextOnly;
+ case CSSPropertyWebkitUserSelect: // auto | none | text | all
+ return valueID == CSSValueAuto || valueID == CSSValueNone || valueID == CSSValueText || valueID == CSSValueAll;
+ case CSSPropertyWebkitWrapFlow:
+ return RuntimeEnabledFeatures::cssExclusionsEnabled()
+ && (valueID == CSSValueAuto || valueID == CSSValueBoth || valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueMaximum || valueID == CSSValueClear);
+ case CSSPropertyWebkitWrapThrough:
+ return RuntimeEnabledFeatures::cssExclusionsEnabled()
+ && (valueID == CSSValueWrap || valueID == CSSValueNone);
+ case CSSPropertyWebkitWritingMode:
+ return valueID >= CSSValueHorizontalTb && valueID <= CSSValueHorizontalBt;
+ case CSSPropertyWhiteSpace: // normal | pre | nowrap
+ return valueID == CSSValueNormal || valueID == CSSValuePre || valueID == CSSValuePreWrap || valueID == CSSValuePreLine || valueID == CSSValueNowrap;
+ case CSSPropertyWordBreak: // normal | break-all | break-word (this is a custom extension)
+ return valueID == CSSValueNormal || valueID == CSSValueBreakAll || valueID == CSSValueBreakWord;
+ default:
+ ASSERT_NOT_REACHED();
+ return false;
+ }
+ return false;
+}
+
+bool isKeywordPropertyID(CSSPropertyID propertyId)
+{
+ switch (propertyId) {
+ case CSSPropertyMixBlendMode:
+ case CSSPropertyIsolation:
+ case CSSPropertyBackgroundRepeatX:
+ case CSSPropertyBackgroundRepeatY:
+ case CSSPropertyBorderBottomStyle:
+ case CSSPropertyBorderCollapse:
+ case CSSPropertyBorderLeftStyle:
+ case CSSPropertyBorderRightStyle:
+ case CSSPropertyBorderTopStyle:
+ case CSSPropertyBoxSizing:
+ case CSSPropertyCaptionSide:
+ case CSSPropertyClear:
+ case CSSPropertyDirection:
+ case CSSPropertyDisplay:
+ case CSSPropertyEmptyCells:
+ case CSSPropertyFloat:
+ case CSSPropertyFontStyle:
+ case CSSPropertyImageRendering:
+ case CSSPropertyListStylePosition:
+ case CSSPropertyListStyleType:
+ case CSSPropertyObjectFit:
+ case CSSPropertyOutlineStyle:
+ case CSSPropertyOverflowWrap:
+ case CSSPropertyOverflowX:
+ case CSSPropertyOverflowY:
+ case CSSPropertyPageBreakAfter:
+ case CSSPropertyPageBreakBefore:
+ case CSSPropertyPageBreakInside:
+ case CSSPropertyPointerEvents:
+ case CSSPropertyPosition:
+ case CSSPropertyResize:
+ case CSSPropertyScrollBehavior:
+ case CSSPropertySpeak:
+ case CSSPropertyTableLayout:
+ case CSSPropertyTextAlignLast:
+ case CSSPropertyTextJustify:
+ case CSSPropertyTextLineThroughMode:
+ case CSSPropertyTextLineThroughStyle:
+ case CSSPropertyTextOverflow:
+ case CSSPropertyTextOverlineMode:
+ case CSSPropertyTextOverlineStyle:
+ case CSSPropertyTextRendering:
+ case CSSPropertyTextTransform:
+ case CSSPropertyTextUnderlineMode:
+ case CSSPropertyTextUnderlineStyle:
+ case CSSPropertyTouchActionDelay:
+ case CSSPropertyVisibility:
+ case CSSPropertyWebkitAppearance:
+ case CSSPropertyBackfaceVisibility:
+ case CSSPropertyWebkitBackfaceVisibility:
+ case CSSPropertyWebkitBorderAfterStyle:
+ case CSSPropertyWebkitBorderBeforeStyle:
+ case CSSPropertyWebkitBorderEndStyle:
+ case CSSPropertyWebkitBorderFit:
+ case CSSPropertyWebkitBorderStartStyle:
+ case CSSPropertyWebkitBoxAlign:
+ case CSSPropertyWebkitBoxDecorationBreak:
+ case CSSPropertyWebkitBoxDirection:
+ case CSSPropertyWebkitBoxLines:
+ case CSSPropertyWebkitBoxOrient:
+ case CSSPropertyWebkitBoxPack:
+ case CSSPropertyInternalCallback:
+ case CSSPropertyWebkitColumnBreakAfter:
+ case CSSPropertyWebkitColumnBreakBefore:
+ case CSSPropertyWebkitColumnBreakInside:
+ case CSSPropertyColumnFill:
+ case CSSPropertyWebkitColumnRuleStyle:
+ case CSSPropertyAlignContent:
+ case CSSPropertyFlexDirection:
+ case CSSPropertyFlexWrap:
+ case CSSPropertyJustifyContent:
+ case CSSPropertyFontKerning:
+ case CSSPropertyWebkitFontSmoothing:
+ case CSSPropertyGridAutoFlow:
+ case CSSPropertyWebkitLineBreak:
+ case CSSPropertyWebkitMarginAfterCollapse:
+ case CSSPropertyWebkitMarginBeforeCollapse:
+ case CSSPropertyWebkitMarginBottomCollapse:
+ case CSSPropertyWebkitMarginTopCollapse:
+ case CSSPropertyInternalMarqueeDirection:
+ case CSSPropertyInternalMarqueeStyle:
+ case CSSPropertyWebkitPrintColorAdjust:
+ case CSSPropertyWebkitRtlOrdering:
+ case CSSPropertyWebkitRubyPosition:
+ case CSSPropertyWebkitTextCombine:
+ case CSSPropertyWebkitTextEmphasisPosition:
+ case CSSPropertyWebkitTextSecurity:
+ case CSSPropertyTransformStyle:
+ case CSSPropertyWebkitTransformStyle:
+ case CSSPropertyWebkitUserDrag:
+ case CSSPropertyWebkitUserModify:
+ case CSSPropertyWebkitUserSelect:
+ case CSSPropertyWebkitWrapFlow:
+ case CSSPropertyWebkitWrapThrough:
+ case CSSPropertyWebkitWritingMode:
+ case CSSPropertyWhiteSpace:
+ case CSSPropertyWordBreak:
+ case CSSPropertyWordWrap:
+ return true;
+ case CSSPropertyAlignItems:
+ case CSSPropertyAlignSelf:
+ return !RuntimeEnabledFeatures::cssGridLayoutEnabled();
+ default:
+ return false;
+ }
+}
+
+static bool parseKeywordValue(MutableStylePropertySet* declaration, CSSPropertyID propertyId, const String& string, bool important, const CSSParserContext& parserContext)
+{
+ ASSERT(!string.isEmpty());
+
+ if (!isKeywordPropertyID(propertyId)) {
+ // All properties accept the values of "initial" and "inherit".
+ String lowerCaseString = string.lower();
+ if (lowerCaseString != "initial" && lowerCaseString != "inherit")
+ return false;
+
+ // Parse initial/inherit shorthands using the BisonCSSParser.
+ if (shorthandForProperty(propertyId).length())
+ return false;
+ }
+
+ CSSParserString cssString;
+ cssString.init(string);
+ CSSValueID valueID = cssValueKeywordID(cssString);
+
+ if (!valueID)
+ return false;
+
+ RefPtrWillBeRawPtr<CSSValue> value = nullptr;
+ if (valueID == CSSValueInherit)
+ value = cssValuePool().createInheritedValue();
+ else if (valueID == CSSValueInitial)
+ value = cssValuePool().createExplicitInitialValue();
+ else if (isValidKeywordPropertyAndValue(propertyId, valueID, parserContext))
+ value = cssValuePool().createIdentifierValue(valueID);
+ else
+ return false;
+
+ declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important));
+ return true;
+}
+
+template <typename CharType>
+static bool parseTransformTranslateArguments(CharType*& pos, CharType* end, unsigned expectedCount, CSSTransformValue* transformValue)
+{
+ while (expectedCount) {
+ size_t delimiter = WTF::find(pos, end - pos, expectedCount == 1 ? ')' : ',');
+ if (delimiter == kNotFound)
+ return false;
+ unsigned argumentLength = static_cast<unsigned>(delimiter);
+ CSSPrimitiveValue::UnitType unit = CSSPrimitiveValue::CSS_NUMBER;
+ double number;
+ if (!parseSimpleLength(pos, argumentLength, unit, number))
+ return false;
+ if (unit != CSSPrimitiveValue::CSS_PX && (number || unit != CSSPrimitiveValue::CSS_NUMBER))
+ return false;
+ transformValue->append(cssValuePool().createValue(number, CSSPrimitiveValue::CSS_PX));
+ pos += argumentLength + 1;
+ --expectedCount;
+ }
+ return true;
+}
+
+template <typename CharType>
+static bool parseTransformNumberArguments(CharType*& pos, CharType* end, unsigned expectedCount, CSSTransformValue* transformValue)
+{
+ while (expectedCount) {
+ size_t delimiter = WTF::find(pos, end - pos, expectedCount == 1 ? ')' : ',');
+ if (delimiter == kNotFound)
+ return false;
+ unsigned argumentLength = static_cast<unsigned>(delimiter);
+ bool ok;
+ double number = charactersToDouble(pos, argumentLength, &ok);
+ if (!ok)
+ return false;
+ transformValue->append(cssValuePool().createValue(number, CSSPrimitiveValue::CSS_NUMBER));
+ pos += argumentLength + 1;
+ --expectedCount;
+ }
+ return true;
+}
+
+template <typename CharType>
+static PassRefPtrWillBeRawPtr<CSSTransformValue> parseSimpleTransformValue(CharType*& pos, CharType* end)
+{
+ static const int shortestValidTransformStringLength = 12;
+
+ if (end - pos < shortestValidTransformStringLength)
+ return nullptr;
+
+ const bool isTranslate = toASCIILower(pos[0]) == 't'
+ && toASCIILower(pos[1]) == 'r'
+ && toASCIILower(pos[2]) == 'a'
+ && toASCIILower(pos[3]) == 'n'
+ && toASCIILower(pos[4]) == 's'
+ && toASCIILower(pos[5]) == 'l'
+ && toASCIILower(pos[6]) == 'a'
+ && toASCIILower(pos[7]) == 't'
+ && toASCIILower(pos[8]) == 'e';
+
+ if (isTranslate) {
+ CSSTransformValue::TransformOperationType transformType;
+ unsigned expectedArgumentCount = 1;
+ unsigned argumentStart = 11;
+ CharType c9 = toASCIILower(pos[9]);
+ if (c9 == 'x' && pos[10] == '(') {
+ transformType = CSSTransformValue::TranslateXTransformOperation;
+ } else if (c9 == 'y' && pos[10] == '(') {
+ transformType = CSSTransformValue::TranslateYTransformOperation;
+ } else if (c9 == 'z' && pos[10] == '(') {
+ transformType = CSSTransformValue::TranslateZTransformOperation;
+ } else if (c9 == '(') {
+ transformType = CSSTransformValue::TranslateTransformOperation;
+ expectedArgumentCount = 2;
+ argumentStart = 10;
+ } else if (c9 == '3' && toASCIILower(pos[10]) == 'd' && pos[11] == '(') {
+ transformType = CSSTransformValue::Translate3DTransformOperation;
+ expectedArgumentCount = 3;
+ argumentStart = 12;
+ } else {
+ return nullptr;
+ }
+ pos += argumentStart;
+ RefPtrWillBeRawPtr<CSSTransformValue> transformValue = CSSTransformValue::create(transformType);
+ if (!parseTransformTranslateArguments(pos, end, expectedArgumentCount, transformValue.get()))
+ return nullptr;
+ return transformValue.release();
+ }
+
+ const bool isMatrix3d = toASCIILower(pos[0]) == 'm'
+ && toASCIILower(pos[1]) == 'a'
+ && toASCIILower(pos[2]) == 't'
+ && toASCIILower(pos[3]) == 'r'
+ && toASCIILower(pos[4]) == 'i'
+ && toASCIILower(pos[5]) == 'x'
+ && pos[6] == '3'
+ && toASCIILower(pos[7]) == 'd'
+ && pos[8] == '(';
+
+ if (isMatrix3d) {
+ pos += 9;
+ RefPtrWillBeRawPtr<CSSTransformValue> transformValue = CSSTransformValue::create(CSSTransformValue::Matrix3DTransformOperation);
+ if (!parseTransformNumberArguments(pos, end, 16, transformValue.get()))
+ return nullptr;
+ return transformValue.release();
+ }
+
+ const bool isScale3d = toASCIILower(pos[0]) == 's'
+ && toASCIILower(pos[1]) == 'c'
+ && toASCIILower(pos[2]) == 'a'
+ && toASCIILower(pos[3]) == 'l'
+ && toASCIILower(pos[4]) == 'e'
+ && pos[5] == '3'
+ && toASCIILower(pos[6]) == 'd'
+ && pos[7] == '(';
+
+ if (isScale3d) {
+ pos += 8;
+ RefPtrWillBeRawPtr<CSSTransformValue> transformValue = CSSTransformValue::create(CSSTransformValue::Scale3DTransformOperation);
+ if (!parseTransformNumberArguments(pos, end, 3, transformValue.get()))
+ return nullptr;
+ return transformValue.release();
+ }
+
+ return nullptr;
+}
+
+template <typename CharType>
+static PassRefPtrWillBeRawPtr<CSSValueList> parseSimpleTransformList(CharType*& pos, CharType* end)
+{
+ RefPtrWillBeRawPtr<CSSValueList> transformList = nullptr;
+ while (pos < end) {
+ while (pos < end && isCSSSpace(*pos))
+ ++pos;
+ RefPtrWillBeRawPtr<CSSTransformValue> transformValue = parseSimpleTransformValue(pos, end);
+ if (!transformValue)
+ return nullptr;
+ if (!transformList)
+ transformList = CSSValueList::createSpaceSeparated();
+ transformList->append(transformValue.release());
+ if (pos < end) {
+ if (isCSSSpace(*pos))
+ return nullptr;
+ }
+ }
+ return transformList.release();
+}
+
+static bool parseSimpleTransform(MutableStylePropertySet* properties, CSSPropertyID propertyID, const String& string, bool important)
+{
+ if (propertyID != CSSPropertyTransform && propertyID != CSSPropertyWebkitTransform)
+ return false;
+ if (string.isEmpty())
+ return false;
+ RefPtrWillBeRawPtr<CSSValueList> transformList = nullptr;
+ if (string.is8Bit()) {
+ const LChar* pos = string.characters8();
+ const LChar* end = pos + string.length();
+ transformList = parseSimpleTransformList(pos, end);
+ if (!transformList)
+ return false;
+ } else {
+ const UChar* pos = string.characters16();
+ const UChar* end = pos + string.length();
+ transformList = parseSimpleTransformList(pos, end);
+ if (!transformList)
+ return false;
+ }
+ properties->addParsedProperty(CSSProperty(propertyID, transformList.release(), important));
+ return true;
+}
+
+PassRefPtrWillBeRawPtr<CSSValueList> BisonCSSParser::parseFontFaceValue(const AtomicString& string)
+{
+ if (string.isEmpty())
+ return nullptr;
+ RefPtrWillBeRawPtr<MutableStylePropertySet> dummyStyle = MutableStylePropertySet::create();
+ if (!parseValue(dummyStyle.get(), CSSPropertyFontFamily, string, false, HTMLQuirksMode, 0))
+ return nullptr;
+
+ RefPtrWillBeRawPtr<CSSValue> fontFamily = dummyStyle->getPropertyCSSValue(CSSPropertyFontFamily);
+ if (!fontFamily->isValueList())
+ return nullptr;
+
+ return toCSSValueList(dummyStyle->getPropertyCSSValue(CSSPropertyFontFamily).get());
+}
+
+PassRefPtrWillBeRawPtr<CSSValue> BisonCSSParser::parseAnimationTimingFunctionValue(const String& string)
+{
+ if (string.isEmpty())
+ return nullptr;
+ RefPtrWillBeRawPtr<MutableStylePropertySet> style = MutableStylePropertySet::create();
+ if (!parseValue(style.get(), CSSPropertyTransitionTimingFunction, string, false, HTMLStandardMode, 0))
+ return nullptr;
+
+ RefPtrWillBeRawPtr<CSSValue> value = style->getPropertyCSSValue(CSSPropertyTransitionTimingFunction);
+ if (!value || value->isInitialValue() || value->isInheritedValue())
+ return nullptr;
+ CSSValueList* valueList = toCSSValueList(value.get());
+ if (valueList->length() > 1)
+ return nullptr;
+ return valueList->item(0);
+}
+
+bool BisonCSSParser::parseValue(MutableStylePropertySet* declaration, CSSPropertyID propertyID, const String& string, bool important, const Document& document)
+{
+ ASSERT(!string.isEmpty());
+
+ CSSParserContext context(document, UseCounter::getFrom(&document));
+
+ if (parseSimpleLengthValue(declaration, propertyID, string, important, context.mode()))
+ return true;
+ if (parseColorValue(declaration, propertyID, string, important, context.mode()))
+ return true;
+ if (parseKeywordValue(declaration, propertyID, string, important, context))
+ return true;
+
+ BisonCSSParser parser(context);
+ return parser.parseValue(declaration, propertyID, string, important, static_cast<StyleSheetContents*>(0));
+}
+
+bool BisonCSSParser::parseValue(MutableStylePropertySet* declaration, CSSPropertyID propertyID, const String& string, bool important, CSSParserMode cssParserMode, StyleSheetContents* contextStyleSheet)
+{
+ ASSERT(!string.isEmpty());
+ if (parseSimpleLengthValue(declaration, propertyID, string, important, cssParserMode))
+ return true;
+ if (parseColorValue(declaration, propertyID, string, important, cssParserMode))
+ return true;
+
+ CSSParserContext context(cssParserMode, 0);
+ if (contextStyleSheet) {
+ context = contextStyleSheet->parserContext();
+ context.setMode(cssParserMode);
+ }
+
+ if (parseKeywordValue(declaration, propertyID, string, important, context))
+ return true;
+ if (parseSimpleTransform(declaration, propertyID, string, important))
+ return true;
+
+ BisonCSSParser parser(context);
+ return parser.parseValue(declaration, propertyID, string, important, contextStyleSheet);
+}
+
+bool BisonCSSParser::parseValue(MutableStylePropertySet* declaration, CSSPropertyID propertyID, const String& string, bool important, StyleSheetContents* contextStyleSheet)
+{
+ // FIXME: Check RuntimeCSSEnabled::isPropertyEnabled or isValueEnabledForProperty.
+
+ if (m_context.useCounter())
+ m_context.useCounter()->count(m_context, propertyID);
+
+ setStyleSheet(contextStyleSheet);
+
+ setupParser("@-internal-value ", string, "");
+
+ m_id = propertyID;
+ m_important = important;
+
+ {
+ StyleDeclarationScope scope(this, declaration);
+ cssyyparse(this);
+ }
+
+ m_rule = nullptr;
+ m_id = CSSPropertyInvalid;
+
+ bool ok = false;
+ if (!m_parsedProperties.isEmpty()) {
+ ok = true;
+ declaration->addParsedProperties(m_parsedProperties);
+ clearProperties();
+ }
+
+ return ok;
+}
+
+// The color will only be changed when string contains a valid CSS color, so callers
+// can set it to a default color and ignore the boolean result.
+bool BisonCSSParser::parseColor(RGBA32& color, const String& string, bool strict)
+{
+ // First try creating a color specified by name, rgba(), rgb() or "#" syntax.
+ if (CSSPropertyParser::fastParseColor(color, string, strict))
+ return true;
+
+ BisonCSSParser parser(strictCSSParserContext());
+
+ // In case the fast-path parser didn't understand the color, try the full parser.
+ if (!parser.parseColor(string))
+ return false;
+
+ CSSValue* value = parser.m_parsedProperties.first().value();
+ if (!value->isPrimitiveValue())
+ return false;
+
+ CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
+ if (!primitiveValue->isRGBColor())
+ return false;
+
+ color = primitiveValue->getRGBA32Value();
+ return true;
+}
+
+bool BisonCSSParser::parseColor(const String& string)
+{
+ setupParser("@-internal-decls color:", string, "");
+ cssyyparse(this);
+ m_rule = nullptr;
+
+ return !m_parsedProperties.isEmpty() && m_parsedProperties.first().id() == CSSPropertyColor;
+}
+
+bool BisonCSSParser::parseSystemColor(RGBA32& color, const String& string)
+{
+ CSSParserString cssColor;
+ cssColor.init(string);
+ CSSValueID id = cssValueKeywordID(cssColor);
+ if (!CSSPropertyParser::isSystemColor(id))
+ return false;
+
+ Color parsedColor = RenderTheme::theme().systemColor(id);
+ color = parsedColor.rgb();
+ return true;
+}
+
+void BisonCSSParser::parseSelector(const String& string, CSSSelectorList& selectorList)
+{
+ m_selectorListForParseSelector = &selectorList;
+
+ setupParser("@-internal-selector ", string, "");
+
+ cssyyparse(this);
+
+ m_selectorListForParseSelector = 0;
+}
+
+PassRefPtr<ImmutableStylePropertySet> BisonCSSParser::parseInlineStyleDeclaration(const String& string, Element* element)
+{
+ Document& document = element->document();
+ CSSParserContext context = CSSParserContext(document.elementSheet().contents()->parserContext(), UseCounter::getFrom(&document));
+ context.setMode((element->isHTMLElement() && !document.inQuirksMode()) ? HTMLStandardMode : HTMLQuirksMode);
+ return BisonCSSParser(context).parseDeclaration(string, document.elementSheet().contents());
+}
+
+PassRefPtr<ImmutableStylePropertySet> BisonCSSParser::parseDeclaration(const String& string, StyleSheetContents* contextStyleSheet)
+{
+ setStyleSheet(contextStyleSheet);
+
+ setupParser("@-internal-decls ", string, "");
+ cssyyparse(this);
+ m_rule = nullptr;
+
+ RefPtr<ImmutableStylePropertySet> style = createStylePropertySet();
+ clearProperties();
+ return style.release();
+}
+
+
+bool BisonCSSParser::parseDeclaration(MutableStylePropertySet* declaration, const String& string, CSSParserObserver* observer, StyleSheetContents* contextStyleSheet)
+{
+ setStyleSheet(contextStyleSheet);
+
+ TemporaryChange<CSSParserObserver*> scopedObsever(m_observer, observer);
+
+ setupParser("@-internal-decls ", string, "");
+ if (m_observer) {
+ m_observer->startRuleHeader(CSSRuleSourceData::STYLE_RULE, 0);
+ m_observer->endRuleHeader(1);
+ m_observer->startRuleBody(0);
+ }
+
+ {
+ StyleDeclarationScope scope(this, declaration);
+ cssyyparse(this);
+ }
+
+ m_rule = nullptr;
+
+ bool ok = false;
+ if (!m_parsedProperties.isEmpty()) {
+ ok = true;
+ declaration->addParsedProperties(m_parsedProperties);
+ clearProperties();
+ }
+
+ if (m_observer)
+ m_observer->endRuleBody(string.length(), false);
+
+ return ok;
+}
+
+PassRefPtrWillBeRawPtr<MediaQuerySet> BisonCSSParser::parseMediaQueryList(const String& string)
+{
+ ASSERT(!m_mediaList);
+
+ // can't use { because tokenizer state switches from mediaquery to initial state when it sees { token.
+ // instead insert one " " (which is caught by maybe_space in CSSGrammar.y)
+ setupParser("@-internal-medialist ", string, "");
+ cssyyparse(this);
+
+ ASSERT(m_mediaList);
+ return m_mediaList.release();
+}
+
+static inline void filterProperties(bool important, const WillBeHeapVector<CSSProperty, 256>& input, WillBeHeapVector<CSSProperty, 256>& output, size_t& unusedEntries, BitArray<numCSSProperties>& seenProperties)
+{
+ // Add properties in reverse order so that highest priority definitions are reached first. Duplicate definitions can then be ignored when found.
+ for (int i = input.size() - 1; i >= 0; --i) {
+ const CSSProperty& property = input[i];
+ if (property.isImportant() != important)
+ continue;
+ const unsigned propertyIDIndex = property.id() - firstCSSProperty;
+ if (seenProperties.get(propertyIDIndex))
+ continue;
+ seenProperties.set(propertyIDIndex);
+ output[--unusedEntries] = property;
+ }
+}
+
+PassRefPtr<ImmutableStylePropertySet> BisonCSSParser::createStylePropertySet()
+{
+ BitArray<numCSSProperties> seenProperties;
+ size_t unusedEntries = m_parsedProperties.size();
+ WillBeHeapVector<CSSProperty, 256> results(unusedEntries);
+
+ // Important properties have higher priority, so add them first. Duplicate definitions can then be ignored when found.
+ filterProperties(true, m_parsedProperties, results, unusedEntries, seenProperties);
+ filterProperties(false, m_parsedProperties, results, unusedEntries, seenProperties);
+ if (unusedEntries)
+ results.remove(0, unusedEntries);
+
+ CSSParserMode mode = inViewport() ? CSSViewportRuleMode : m_context.mode();
+
+ return ImmutableStylePropertySet::create(results.data(), results.size(), mode);
+}
+
+void BisonCSSParser::rollbackLastProperties(int num)
+{
+ ASSERT(num >= 0);
+ ASSERT(m_parsedProperties.size() >= static_cast<unsigned>(num));
+ m_parsedProperties.shrink(m_parsedProperties.size() - num);
+}
+
+void BisonCSSParser::clearProperties()
+{
+ m_parsedProperties.clear();
+ m_numParsedPropertiesBeforeMarginBox = INVALID_NUM_PARSED_PROPERTIES;
+}
+
+void BisonCSSParser::setCurrentProperty(CSSPropertyID propId)
+{
+ m_id = propId;
+}
+
+bool BisonCSSParser::parseValue(CSSPropertyID propId, bool important)
+{
+ CSSPropertyParser parser(m_valueList, m_context, m_inViewport, m_important, m_parsedProperties, m_ruleHeaderType);
+ return parser.parseValue(propId, important);
+}
+
+
+class TransformOperationInfo {
+public:
+ TransformOperationInfo(const CSSParserString& name)
+ : m_type(CSSTransformValue::UnknownTransformOperation)
+ , m_argCount(1)
+ , m_allowSingleArgument(false)
+ , m_unit(CSSPropertyParser::FUnknown)
+ {
+ const UChar* characters;
+ unsigned nameLength = name.length();
+
+ const unsigned longestNameLength = 12;
+ UChar characterBuffer[longestNameLength];
+ if (name.is8Bit()) {
+ unsigned length = std::min(longestNameLength, nameLength);
+ const LChar* characters8 = name.characters8();
+ for (unsigned i = 0; i < length; ++i)
+ characterBuffer[i] = characters8[i];
+ characters = characterBuffer;
+ } else
+ characters = name.characters16();
+
+ SWITCH(characters, nameLength) {
+ CASE("skew(") {
+ m_unit = CSSPropertyParser::FAngle;
+ m_type = CSSTransformValue::SkewTransformOperation;
+ m_allowSingleArgument = true;
+ m_argCount = 3;
+ }
+ CASE("scale(") {
+ m_unit = CSSPropertyParser::FNumber;
+ m_type = CSSTransformValue::ScaleTransformOperation;
+ m_allowSingleArgument = true;
+ m_argCount = 3;
+ }
+ CASE("skewx(") {
+ m_unit = CSSPropertyParser::FAngle;
+ m_type = CSSTransformValue::SkewXTransformOperation;
+ }
+ CASE("skewy(") {
+ m_unit = CSSPropertyParser::FAngle;
+ m_type = CSSTransformValue::SkewYTransformOperation;
+ }
+ CASE("matrix(") {
+ m_unit = CSSPropertyParser::FNumber;
+ m_type = CSSTransformValue::MatrixTransformOperation;
+ m_argCount = 11;
+ }
+ CASE("rotate(") {
+ m_unit = CSSPropertyParser::FAngle;
+ m_type = CSSTransformValue::RotateTransformOperation;
+ }
+ CASE("scalex(") {
+ m_unit = CSSPropertyParser::FNumber;
+ m_type = CSSTransformValue::ScaleXTransformOperation;
+ }
+ CASE("scaley(") {
+ m_unit = CSSPropertyParser::FNumber;
+ m_type = CSSTransformValue::ScaleYTransformOperation;
+ }
+ CASE("scalez(") {
+ m_unit = CSSPropertyParser::FNumber;
+ m_type = CSSTransformValue::ScaleZTransformOperation;
+ }
+ CASE("scale3d(") {
+ m_unit = CSSPropertyParser::FNumber;
+ m_type = CSSTransformValue::Scale3DTransformOperation;
+ m_argCount = 5;
+ }
+ CASE("rotatex(") {
+ m_unit = CSSPropertyParser::FAngle;
+ m_type = CSSTransformValue::RotateXTransformOperation;
+ }
+ CASE("rotatey(") {
+ m_unit = CSSPropertyParser::FAngle;
+ m_type = CSSTransformValue::RotateYTransformOperation;
+ }
+ CASE("rotatez(") {
+ m_unit = CSSPropertyParser::FAngle;
+ m_type = CSSTransformValue::RotateZTransformOperation;
+ }
+ CASE("matrix3d(") {
+ m_unit = CSSPropertyParser::FNumber;
+ m_type = CSSTransformValue::Matrix3DTransformOperation;
+ m_argCount = 31;
+ }
+ CASE("rotate3d(") {
+ m_unit = CSSPropertyParser::FNumber;
+ m_type = CSSTransformValue::Rotate3DTransformOperation;
+ m_argCount = 7;
+ }
+ CASE("translate(") {
+ m_unit = CSSPropertyParser::FLength | CSSPropertyParser::FPercent;
+ m_type = CSSTransformValue::TranslateTransformOperation;
+ m_allowSingleArgument = true;
+ m_argCount = 3;
+ }
+ CASE("translatex(") {
+ m_unit = CSSPropertyParser::FLength | CSSPropertyParser::FPercent;
+ m_type = CSSTransformValue::TranslateXTransformOperation;
+ }
+ CASE("translatey(") {
+ m_unit = CSSPropertyParser::FLength | CSSPropertyParser::FPercent;
+ m_type = CSSTransformValue::TranslateYTransformOperation;
+ }
+ CASE("translatez(") {
+ m_unit = CSSPropertyParser::FLength | CSSPropertyParser::FPercent;
+ m_type = CSSTransformValue::TranslateZTransformOperation;
+ }
+ CASE("perspective(") {
+ m_unit = CSSPropertyParser::FNumber;
+ m_type = CSSTransformValue::PerspectiveTransformOperation;
+ }
+ CASE("translate3d(") {
+ m_unit = CSSPropertyParser::FLength | CSSPropertyParser::FPercent;
+ m_type = CSSTransformValue::Translate3DTransformOperation;
+ m_argCount = 5;
+ }
+ }
+ }
+
+ CSSTransformValue::TransformOperationType type() const { return m_type; }
+ unsigned argCount() const { return m_argCount; }
+ CSSPropertyParser::Units unit() const { return m_unit; }
+
+ bool unknown() const { return m_type == CSSTransformValue::UnknownTransformOperation; }
+ bool hasCorrectArgCount(unsigned argCount) { return m_argCount == argCount || (m_allowSingleArgument && argCount == 1); }
+
+private:
+ CSSTransformValue::TransformOperationType m_type;
+ unsigned m_argCount;
+ bool m_allowSingleArgument;
+ CSSPropertyParser::Units m_unit;
+};
+
+PassRefPtrWillBeRawPtr<CSSValueList> CSSPropertyParser::parseTransform(CSSPropertyID propId)
+{
+ if (!m_valueList)
+ return nullptr;
+
+ RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
+ for (CSSParserValue* value = m_valueList->current(); value; value = m_valueList->next()) {
+ RefPtrWillBeRawPtr<CSSValue> parsedTransformValue = parseTransformValue(propId, value);
+ if (!parsedTransformValue)
+ return nullptr;
+
+ list->append(parsedTransformValue.release());
+ }
+
+ return list.release();
+}
+
+PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseTransformValue(CSSPropertyID propId, CSSParserValue *value)
+{
+ if (value->unit != CSSParserValue::Function || !value->function)
+ return nullptr;
+
+ // Every primitive requires at least one argument.
+ CSSParserValueList* args = value->function->args.get();
+ if (!args)
+ return nullptr;
+
+ // See if the specified primitive is one we understand.
+ TransformOperationInfo info(value->function->name);
+ if (info.unknown())
+ return nullptr;
+
+ if (!info.hasCorrectArgCount(args->size()))
+ return nullptr;
+
+ // The transform is a list of functional primitives that specify transform operations.
+ // We collect a list of CSSTransformValues, where each value specifies a single operation.
+
+ // Create the new CSSTransformValue for this operation and add it to our list.
+ RefPtrWillBeRawPtr<CSSTransformValue> transformValue = CSSTransformValue::create(info.type());
+
+ // Snag our values.
+ CSSParserValue* a = args->current();
+ unsigned argNumber = 0;
+ while (a) {
+ CSSPropertyParser::Units unit = info.unit();
+
+ if (info.type() == CSSTransformValue::Rotate3DTransformOperation && argNumber == 3) {
+ // 4th param of rotate3d() is an angle rather than a bare number, validate it as such
+ if (!validUnit(a, FAngle, HTMLStandardMode))
+ return nullptr;
+ } else if (info.type() == CSSTransformValue::Translate3DTransformOperation && argNumber == 2) {
+ // 3rd param of translate3d() cannot be a percentage
+ if (!validUnit(a, FLength, HTMLStandardMode))
+ return nullptr;
+ } else if (info.type() == CSSTransformValue::TranslateZTransformOperation && !argNumber) {
+ // 1st param of translateZ() cannot be a percentage
+ if (!validUnit(a, FLength, HTMLStandardMode))
+ return nullptr;
+ } else if (info.type() == CSSTransformValue::PerspectiveTransformOperation && !argNumber) {
+ // 1st param of perspective() must be a non-negative number (deprecated) or length.
+ if ((propId == CSSPropertyWebkitTransform && !validUnit(a, FNumber | FLength | FNonNeg, HTMLStandardMode))
+ || (propId == CSSPropertyTransform && !validUnit(a, FLength | FNonNeg, HTMLStandardMode)))
+ return nullptr;
+ } else if (!validUnit(a, unit, HTMLStandardMode)) {
+ return nullptr;
+ }
+
+ // Add the value to the current transform operation.
+ transformValue->append(createPrimitiveNumericValue(a));
+
+ a = args->next();
+ if (!a)
+ break;
+ if (a->unit != CSSParserValue::Operator || a->iValue != ',')
+ return nullptr;
+ a = args->next();
+
+ argNumber++;
+ }
+
+ return transformValue.release();
+}
+
+void BisonCSSParser::ensureLineEndings()
+{
+ if (!m_lineEndings)
+ m_lineEndings = lineEndings(*m_source);
+}
+
+CSSParserSelector* BisonCSSParser::createFloatingSelectorWithTagName(const QualifiedName& tagQName)
+{
+ CSSParserSelector* selector = new CSSParserSelector(tagQName);
+ m_floatingSelectors.append(selector);
+ return selector;
+}
+
+CSSParserSelector* BisonCSSParser::createFloatingSelector()
+{
+ CSSParserSelector* selector = new CSSParserSelector;
+ m_floatingSelectors.append(selector);
+ return selector;
+}
+
+PassOwnPtr<CSSParserSelector> BisonCSSParser::sinkFloatingSelector(CSSParserSelector* selector)
+{
+ if (selector) {
+ size_t index = m_floatingSelectors.reverseFind(selector);
+ ASSERT(index != kNotFound);
+ m_floatingSelectors.remove(index);
+ }
+ return adoptPtr(selector);
+}
+
+Vector<OwnPtr<CSSParserSelector> >* BisonCSSParser::createFloatingSelectorVector()
+{
+ Vector<OwnPtr<CSSParserSelector> >* selectorVector = new Vector<OwnPtr<CSSParserSelector> >;
+ m_floatingSelectorVectors.append(selectorVector);
+ return selectorVector;
+}
+
+PassOwnPtr<Vector<OwnPtr<CSSParserSelector> > > BisonCSSParser::sinkFloatingSelectorVector(Vector<OwnPtr<CSSParserSelector> >* selectorVector)
+{
+ if (selectorVector) {
+ size_t index = m_floatingSelectorVectors.reverseFind(selectorVector);
+ ASSERT(index != kNotFound);
+ m_floatingSelectorVectors.remove(index);
+ }
+ return adoptPtr(selectorVector);
+}
+
+CSSParserValueList* BisonCSSParser::createFloatingValueList()
+{
+ CSSParserValueList* list = new CSSParserValueList;
+ m_floatingValueLists.append(list);
+ return list;
+}
+
+PassOwnPtr<CSSParserValueList> BisonCSSParser::sinkFloatingValueList(CSSParserValueList* list)
+{
+ if (list) {
+ size_t index = m_floatingValueLists.reverseFind(list);
+ ASSERT(index != kNotFound);
+ m_floatingValueLists.remove(index);
+ }
+ return adoptPtr(list);
+}
+
+CSSParserFunction* BisonCSSParser::createFloatingFunction()
+{
+ CSSParserFunction* function = new CSSParserFunction;
+ m_floatingFunctions.append(function);
+ return function;
+}
+
+CSSParserFunction* BisonCSSParser::createFloatingFunction(const CSSParserString& name, PassOwnPtr<CSSParserValueList> args)
+{
+ CSSParserFunction* function = createFloatingFunction();
+ function->name = name;
+ function->args = args;
+ return function;
+}
+
+PassOwnPtr<CSSParserFunction> BisonCSSParser::sinkFloatingFunction(CSSParserFunction* function)
+{
+ if (function) {
+ size_t index = m_floatingFunctions.reverseFind(function);
+ ASSERT(index != kNotFound);
+ m_floatingFunctions.remove(index);
+ }
+ return adoptPtr(function);
+}
+
+CSSParserValue& BisonCSSParser::sinkFloatingValue(CSSParserValue& value)
+{
+ if (value.unit == CSSParserValue::Function) {
+ size_t index = m_floatingFunctions.reverseFind(value.function);
+ ASSERT(index != kNotFound);
+ m_floatingFunctions.remove(index);
+ }
+ return value;
+}
+
+MediaQueryExp* BisonCSSParser::createFloatingMediaQueryExp(const AtomicString& mediaFeature, CSSParserValueList* values)
+{
+ m_floatingMediaQueryExp = MediaQueryExp::createIfValid(mediaFeature, values);
+ return m_floatingMediaQueryExp.get();
+}
+
+PassOwnPtrWillBeRawPtr<MediaQueryExp> BisonCSSParser::sinkFloatingMediaQueryExp(MediaQueryExp* expression)
+{
+ ASSERT_UNUSED(expression, expression == m_floatingMediaQueryExp);
+ return m_floatingMediaQueryExp.release();
+}
+
+WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp> >* BisonCSSParser::createFloatingMediaQueryExpList()
+{
+ m_floatingMediaQueryExpList = adoptPtrWillBeNoop(new WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp> >);
+ return m_floatingMediaQueryExpList.get();
+}
+
+PassOwnPtrWillBeRawPtr<WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp> > > BisonCSSParser::sinkFloatingMediaQueryExpList(WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp> >* list)
+{
+ ASSERT_UNUSED(list, list == m_floatingMediaQueryExpList);
+ return m_floatingMediaQueryExpList.release();
+}
+
+MediaQuery* BisonCSSParser::createFloatingMediaQuery(MediaQuery::Restrictor restrictor, const AtomicString& mediaType, PassOwnPtrWillBeRawPtr<WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp> > > expressions)
+{
+ m_floatingMediaQuery = adoptPtrWillBeNoop(new MediaQuery(restrictor, mediaType, expressions));
+ return m_floatingMediaQuery.get();
+}
+
+MediaQuery* BisonCSSParser::createFloatingMediaQuery(PassOwnPtrWillBeRawPtr<WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp> > > expressions)
+{
+ return createFloatingMediaQuery(MediaQuery::None, AtomicString("all", AtomicString::ConstructFromLiteral), expressions);
+}
+
+MediaQuery* BisonCSSParser::createFloatingNotAllQuery()
+{
+ return createFloatingMediaQuery(MediaQuery::Not, AtomicString("all", AtomicString::ConstructFromLiteral), sinkFloatingMediaQueryExpList(createFloatingMediaQueryExpList()));
+}
+
+PassOwnPtrWillBeRawPtr<MediaQuery> BisonCSSParser::sinkFloatingMediaQuery(MediaQuery* query)
+{
+ ASSERT_UNUSED(query, query == m_floatingMediaQuery);
+ return m_floatingMediaQuery.release();
+}
+
+WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> >* BisonCSSParser::createFloatingKeyframeVector()
+{
+ m_floatingKeyframeVector = adoptPtrWillBeNoop(new WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> >());
+ return m_floatingKeyframeVector.get();
+}
+
+PassOwnPtrWillBeRawPtr<WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> > > BisonCSSParser::sinkFloatingKeyframeVector(WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> >* keyframeVector)
+{
+ ASSERT_UNUSED(keyframeVector, m_floatingKeyframeVector == keyframeVector);
+ return m_floatingKeyframeVector.release();
+}
+
+MediaQuerySet* BisonCSSParser::createMediaQuerySet()
+{
+ RefPtrWillBeRawPtr<MediaQuerySet> queries = MediaQuerySet::create();
+ MediaQuerySet* result = queries.get();
+ m_parsedMediaQuerySets.append(queries.release());
+ return result;
+}
+
+StyleRuleBase* BisonCSSParser::createImportRule(const CSSParserString& url, MediaQuerySet* media)
+{
+ if (!media || !m_allowImportRules)
+ return 0;
+ RefPtrWillBeRawPtr<StyleRuleImport> rule = StyleRuleImport::create(url, media);
+ StyleRuleImport* result = rule.get();
+ m_parsedRules.append(rule.release());
+ return result;
+}
+
+StyleRuleBase* BisonCSSParser::createMediaRule(MediaQuerySet* media, RuleList* rules)
+{
+ m_allowImportRules = m_allowNamespaceDeclarations = false;
+ RefPtrWillBeRawPtr<StyleRuleMedia> rule = nullptr;
+ if (rules) {
+ rule = StyleRuleMedia::create(media ? media : MediaQuerySet::create().get(), *rules);
+ } else {
+ RuleList emptyRules;
+ rule = StyleRuleMedia::create(media ? media : MediaQuerySet::create().get(), emptyRules);
+ }
+ StyleRuleMedia* result = rule.get();
+ m_parsedRules.append(rule.release());
+ return result;
+}
+
+StyleRuleBase* BisonCSSParser::createSupportsRule(bool conditionIsSupported, RuleList* rules)
+{
+ m_allowImportRules = m_allowNamespaceDeclarations = false;
+
+ RefPtrWillBeRawPtr<CSSRuleSourceData> data = popSupportsRuleData();
+ RefPtrWillBeRawPtr<StyleRuleSupports> rule = nullptr;
+ String conditionText;
+ unsigned conditionOffset = data->ruleHeaderRange.start + 9;
+ unsigned conditionLength = data->ruleHeaderRange.length() - 9;
+
+ if (m_tokenizer.is8BitSource())
+ conditionText = String(m_tokenizer.m_dataStart8.get() + conditionOffset, conditionLength).stripWhiteSpace();
+ else
+ conditionText = String(m_tokenizer.m_dataStart16.get() + conditionOffset, conditionLength).stripWhiteSpace();
+
+ if (rules) {
+ rule = StyleRuleSupports::create(conditionText, conditionIsSupported, *rules);
+ } else {
+ RuleList emptyRules;
+ rule = StyleRuleSupports::create(conditionText, conditionIsSupported, emptyRules);
+ }
+
+ StyleRuleSupports* result = rule.get();
+ m_parsedRules.append(rule.release());
+
+ return result;
+}
+
+void BisonCSSParser::markSupportsRuleHeaderStart()
+{
+ if (!m_supportsRuleDataStack)
+ m_supportsRuleDataStack = adoptPtrWillBeNoop(new RuleSourceDataList());
+
+ RefPtrWillBeRawPtr<CSSRuleSourceData> data = CSSRuleSourceData::create(CSSRuleSourceData::SUPPORTS_RULE);
+ data->ruleHeaderRange.start = m_tokenizer.tokenStartOffset();
+ m_supportsRuleDataStack->append(data);
+}
+
+void BisonCSSParser::markSupportsRuleHeaderEnd()
+{
+ ASSERT(m_supportsRuleDataStack && !m_supportsRuleDataStack->isEmpty());
+
+ if (m_tokenizer.is8BitSource())
+ m_supportsRuleDataStack->last()->ruleHeaderRange.end = m_tokenizer.tokenStart<LChar>() - m_tokenizer.m_dataStart8.get();
+ else
+ m_supportsRuleDataStack->last()->ruleHeaderRange.end = m_tokenizer.tokenStart<UChar>() - m_tokenizer.m_dataStart16.get();
+}
+
+PassRefPtrWillBeRawPtr<CSSRuleSourceData> BisonCSSParser::popSupportsRuleData()
+{
+ ASSERT(m_supportsRuleDataStack && !m_supportsRuleDataStack->isEmpty());
+ RefPtrWillBeRawPtr<CSSRuleSourceData> data = m_supportsRuleDataStack->last();
+ m_supportsRuleDataStack->removeLast();
+ return data.release();
+}
+
+BisonCSSParser::RuleList* BisonCSSParser::createRuleList()
+{
+ OwnPtrWillBeRawPtr<RuleList> list = adoptPtrWillBeNoop(new RuleList);
+ RuleList* listPtr = list.get();
+
+ m_parsedRuleLists.append(list.release());
+ return listPtr;
+}
+
+BisonCSSParser::RuleList* BisonCSSParser::appendRule(RuleList* ruleList, StyleRuleBase* rule)
+{
+ if (rule) {
+ if (!ruleList)
+ ruleList = createRuleList();
+ ruleList->append(rule);
+ }
+ return ruleList;
+}
+
+template <typename CharacterType>
+ALWAYS_INLINE static void makeLower(const CharacterType* input, CharacterType* output, unsigned length)
+{
+ // FIXME: If we need Unicode lowercasing here, then we probably want the real kind
+ // that can potentially change the length of the string rather than the character
+ // by character kind. If we don't need Unicode lowercasing, it would be good to
+ // simplify this function.
+
+ if (charactersAreAllASCII(input, length)) {
+ // Fast case for all-ASCII.
+ for (unsigned i = 0; i < length; i++)
+ output[i] = toASCIILower(input[i]);
+ } else {
+ for (unsigned i = 0; i < length; i++)
+ output[i] = Unicode::toLower(input[i]);
+ }
+}
+
+void BisonCSSParser::tokenToLowerCase(CSSParserString& token)
+{
+ // Since it's our internal token, we know that we created it out
+ // of our writable work buffers. Therefore the const_cast is just
+ // ugly and not a potential crash.
+ size_t length = token.length();
+ if (token.is8Bit()) {
+ makeLower(token.characters8(), const_cast<LChar*>(token.characters8()), length);
+ } else {
+ makeLower(token.characters16(), const_cast<UChar*>(token.characters16()), length);
+ }
+}
+
+void BisonCSSParser::endInvalidRuleHeader()
+{
+ if (m_ruleHeaderType == CSSRuleSourceData::UNKNOWN_RULE)
+ return;
+
+ CSSParserLocation location;
+ location.lineNumber = m_tokenizer.m_lineNumber;
+ location.offset = m_ruleHeaderStartOffset;
+ if (m_tokenizer.is8BitSource())
+ location.token.init(m_tokenizer.m_dataStart8.get() + m_ruleHeaderStartOffset, 0);
+ else
+ location.token.init(m_tokenizer.m_dataStart16.get() + m_ruleHeaderStartOffset, 0);
+
+ reportError(location, m_ruleHeaderType == CSSRuleSourceData::STYLE_RULE ? InvalidSelectorCSSError : InvalidRuleCSSError);
+
+ endRuleHeader();
+}
+
+void BisonCSSParser::reportError(const CSSParserLocation&, CSSParserError)
+{
+ // FIXME: error reporting temporatily disabled.
+}
+
+bool BisonCSSParser::isLoggingErrors()
+{
+ return m_logErrors && !m_ignoreErrors;
+}
+
+void BisonCSSParser::logError(const String& message, const CSSParserLocation& location)
+{
+ unsigned lineNumberInStyleSheet;
+ unsigned columnNumber = 0;
+ if (InspectorInstrumentation::hasFrontends()) {
+ ensureLineEndings();
+ TextPosition tokenPosition = TextPosition::fromOffsetAndLineEndings(location.offset, *m_lineEndings);
+ lineNumberInStyleSheet = tokenPosition.m_line.zeroBasedInt();
+ columnNumber = (lineNumberInStyleSheet ? 0 : m_startPosition.m_column.zeroBasedInt()) + tokenPosition.m_column.zeroBasedInt();
+ } else {
+ lineNumberInStyleSheet = location.lineNumber;
+ }
+ FrameConsole& console = m_styleSheet->singleOwnerDocument()->frame()->console();
+ console.addMessage(CSSMessageSource, WarningMessageLevel, message, m_styleSheet->baseURL().string(), lineNumberInStyleSheet + m_startPosition.m_line.zeroBasedInt() + 1, columnNumber + 1);
+}
+
+StyleRuleKeyframes* BisonCSSParser::createKeyframesRule(const String& name, PassOwnPtrWillBeRawPtr<WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> > > popKeyframes, bool isPrefixed)
+{
+ OwnPtrWillBeRawPtr<WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> > > keyframes = popKeyframes;
+ m_allowImportRules = m_allowNamespaceDeclarations = false;
+ RefPtrWillBeRawPtr<StyleRuleKeyframes> rule = StyleRuleKeyframes::create();
+ for (size_t i = 0; i < keyframes->size(); ++i)
+ rule->parserAppendKeyframe(keyframes->at(i));
+ rule->setName(name);
+ rule->setVendorPrefixed(isPrefixed);
+ StyleRuleKeyframes* rulePtr = rule.get();
+ m_parsedRules.append(rule.release());
+ return rulePtr;
+}
+
+static void recordSelectorStats(const CSSParserContext& context, const CSSSelectorList& selectorList)
+{
+ if (!context.useCounter())
+ return;
+
+ for (const CSSSelector* selector = selectorList.first(); selector; selector = CSSSelectorList::next(*selector)) {
+ for (const CSSSelector* current = selector; current ; current = current->tagHistory()) {
+ UseCounter::Feature feature = UseCounter::NumberOfFeatures;
+ switch (current->pseudoType()) {
+ case CSSSelector::PseudoUnresolved:
+ feature = UseCounter::CSSSelectorPseudoUnresolved;
+ break;
+ case CSSSelector::PseudoShadow:
+ feature = UseCounter::CSSSelectorPseudoShadow;
+ break;
+ case CSSSelector::PseudoContent:
+ feature = UseCounter::CSSSelectorPseudoContent;
+ break;
+ case CSSSelector::PseudoHost:
+ feature = UseCounter::CSSSelectorPseudoHost;
+ break;
+ case CSSSelector::PseudoHostContext:
+ feature = UseCounter::CSSSelectorPseudoHostContext;
+ break;
+ default:
+ break;
+ }
+ if (feature != UseCounter::NumberOfFeatures)
+ context.useCounter()->count(feature);
+ if (current->relation() == CSSSelector::ShadowDeep)
+ context.useCounter()->count(UseCounter::CSSDeepCombinator);
+ if (current->selectorList())
+ recordSelectorStats(context, *current->selectorList());
+ }
+ }
+}
+
+StyleRuleBase* BisonCSSParser::createStyleRule(Vector<OwnPtr<CSSParserSelector> >* selectors)
+{
+ StyleRule* result = 0;
+ if (selectors) {
+ m_allowImportRules = m_allowNamespaceDeclarations = false;
+ RefPtrWillBeRawPtr<StyleRule> rule = StyleRule::create();
+ rule->parserAdoptSelectorVector(*selectors);
+ rule->setProperties(createStylePropertySet());
+ result = rule.get();
+ m_parsedRules.append(rule.release());
+ recordSelectorStats(m_context, result->selectorList());
+ }
+ clearProperties();
+ return result;
+}
+
+StyleRuleBase* BisonCSSParser::createFontFaceRule()
+{
+ m_allowImportRules = m_allowNamespaceDeclarations = false;
+ for (unsigned i = 0; i < m_parsedProperties.size(); ++i) {
+ CSSProperty& property = m_parsedProperties[i];
+ if (property.id() == CSSPropertyFontVariant && property.value()->isPrimitiveValue())
+ property.wrapValueInCommaSeparatedList();
+ else if (property.id() == CSSPropertyFontFamily && (!property.value()->isValueList() || toCSSValueList(property.value())->length() != 1)) {
+ // Unlike font-family property, font-family descriptor in @font-face rule
+ // has to be a value list with exactly one family name. It cannot have a
+ // have 'initial' value and cannot 'inherit' from parent.
+ // See http://dev.w3.org/csswg/css3-fonts/#font-family-desc
+ clearProperties();
+ return 0;
+ }
+ }
+ RefPtrWillBeRawPtr<StyleRuleFontFace> rule = StyleRuleFontFace::create();
+ rule->setProperties(createStylePropertySet());
+ clearProperties();
+ StyleRuleFontFace* result = rule.get();
+ m_parsedRules.append(rule.release());
+ if (m_styleSheet)
+ m_styleSheet->setHasFontFaceRule(true);
+ return result;
+}
+
+void BisonCSSParser::addNamespace(const AtomicString& prefix, const AtomicString& uri)
+{
+ if (!m_styleSheet || !m_allowNamespaceDeclarations)
+ return;
+ m_allowImportRules = false;
+ m_styleSheet->parserAddNamespace(prefix, uri);
+ if (prefix.isEmpty() && !uri.isNull())
+ m_defaultNamespace = uri;
+}
+
+QualifiedName BisonCSSParser::determineNameInNamespace(const AtomicString& prefix, const AtomicString& localName)
+{
+ if (!m_styleSheet)
+ return QualifiedName(prefix, localName, m_defaultNamespace);
+ return QualifiedName(prefix, localName, m_styleSheet->determineNamespace(prefix));
+}
+
+CSSParserSelector* BisonCSSParser::rewriteSpecifiersWithNamespaceIfNeeded(CSSParserSelector* specifiers)
+{
+ if (m_defaultNamespace != starAtom || specifiers->crossesTreeScopes())
+ return rewriteSpecifiersWithElementName(nullAtom, starAtom, specifiers, /*tagIsForNamespaceRule*/true);
+ return specifiers;
+}
+
+CSSParserSelector* BisonCSSParser::rewriteSpecifiersWithElementName(const AtomicString& namespacePrefix, const AtomicString& elementName, CSSParserSelector* specifiers, bool tagIsForNamespaceRule)
+{
+ AtomicString determinedNamespace = namespacePrefix != nullAtom && m_styleSheet ? m_styleSheet->determineNamespace(namespacePrefix) : m_defaultNamespace;
+ QualifiedName tag(namespacePrefix, elementName, determinedNamespace);
+
+ if (specifiers->crossesTreeScopes())
+ return rewriteSpecifiersWithElementNameForCustomPseudoElement(tag, elementName, specifiers, tagIsForNamespaceRule);
+
+ if (specifiers->isContentPseudoElement())
+ return rewriteSpecifiersWithElementNameForContentPseudoElement(tag, elementName, specifiers, tagIsForNamespaceRule);
+
+ // *:host never matches, so we can't discard the * otherwise we can't tell the
+ // difference between *:host and just :host.
+ if (tag == anyQName() && !specifiers->hasHostPseudoSelector())
+ return specifiers;
+ if (specifiers->pseudoType() != CSSSelector::PseudoCue)
+ specifiers->prependTagSelector(tag, tagIsForNamespaceRule);
+ return specifiers;
+}
+
+CSSParserSelector* BisonCSSParser::rewriteSpecifiersWithElementNameForCustomPseudoElement(const QualifiedName& tag, const AtomicString& elementName, CSSParserSelector* specifiers, bool tagIsForNamespaceRule)
+{
+ if (m_context.useCounter() && specifiers->pseudoType() == CSSSelector::PseudoUserAgentCustomElement)
+ m_context.useCounter()->count(UseCounter::CSSPseudoElementUserAgentCustomPseudo);
+
+ CSSParserSelector* lastShadowPseudo = specifiers;
+ CSSParserSelector* history = specifiers;
+ while (history->tagHistory()) {
+ history = history->tagHistory();
+ if (history->crossesTreeScopes() || history->hasShadowPseudo())
+ lastShadowPseudo = history;
+ }
+
+ if (lastShadowPseudo->tagHistory()) {
+ if (tag != anyQName())
+ lastShadowPseudo->tagHistory()->prependTagSelector(tag, tagIsForNamespaceRule);
+ return specifiers;
+ }
+
+ // For shadow-ID pseudo-elements to be correctly matched, the ShadowPseudo combinator has to be used.
+ // We therefore create a new Selector with that combinator here in any case, even if matching any (host) element in any namespace (i.e. '*').
+ OwnPtr<CSSParserSelector> elementNameSelector = adoptPtr(new CSSParserSelector(tag));
+ lastShadowPseudo->setTagHistory(elementNameSelector.release());
+ lastShadowPseudo->setRelation(CSSSelector::ShadowPseudo);
+ return specifiers;
+}
+
+CSSParserSelector* BisonCSSParser::rewriteSpecifiersWithElementNameForContentPseudoElement(const QualifiedName& tag, const AtomicString& elementName, CSSParserSelector* specifiers, bool tagIsForNamespaceRule)
+{
+ CSSParserSelector* last = specifiers;
+ CSSParserSelector* history = specifiers;
+ while (history->tagHistory()) {
+ history = history->tagHistory();
+ if (history->isContentPseudoElement() || history->relationIsAffectedByPseudoContent())
+ last = history;
+ }
+
+ if (last->tagHistory()) {
+ if (tag != anyQName())
+ last->tagHistory()->prependTagSelector(tag, tagIsForNamespaceRule);
+ return specifiers;
+ }
+
+ // For shadow-ID pseudo-elements to be correctly matched, the ShadowPseudo combinator has to be used.
+ // We therefore create a new Selector with that combinator here in any case, even if matching any (host) element in any namespace (i.e. '*').
+ OwnPtr<CSSParserSelector> elementNameSelector = adoptPtr(new CSSParserSelector(tag));
+ last->setTagHistory(elementNameSelector.release());
+ last->setRelation(CSSSelector::SubSelector);
+ return specifiers;
+}
+
+CSSParserSelector* BisonCSSParser::rewriteSpecifiers(CSSParserSelector* specifiers, CSSParserSelector* newSpecifier)
+{
+ if (newSpecifier->crossesTreeScopes()) {
+ // Unknown pseudo element always goes at the top of selector chain.
+ newSpecifier->appendTagHistory(CSSSelector::ShadowPseudo, sinkFloatingSelector(specifiers));
+ return newSpecifier;
+ }
+ if (newSpecifier->isContentPseudoElement()) {
+ newSpecifier->appendTagHistory(CSSSelector::SubSelector, sinkFloatingSelector(specifiers));
+ return newSpecifier;
+ }
+ if (specifiers->crossesTreeScopes()) {
+ // Specifiers for unknown pseudo element go right behind it in the chain.
+ specifiers->insertTagHistory(CSSSelector::SubSelector, sinkFloatingSelector(newSpecifier), CSSSelector::ShadowPseudo);
+ return specifiers;
+ }
+ if (specifiers->isContentPseudoElement()) {
+ specifiers->insertTagHistory(CSSSelector::SubSelector, sinkFloatingSelector(newSpecifier), CSSSelector::SubSelector);
+ return specifiers;
+ }
+ specifiers->appendTagHistory(CSSSelector::SubSelector, sinkFloatingSelector(newSpecifier));
+ return specifiers;
+}
+
+StyleRuleBase* BisonCSSParser::createPageRule(PassOwnPtr<CSSParserSelector> pageSelector)
+{
+ // FIXME: Margin at-rules are ignored.
+ m_allowImportRules = m_allowNamespaceDeclarations = false;
+ StyleRulePage* pageRule = 0;
+ if (pageSelector) {
+ RefPtrWillBeRawPtr<StyleRulePage> rule = StyleRulePage::create();
+ Vector<OwnPtr<CSSParserSelector> > selectorVector;
+ selectorVector.append(pageSelector);
+ rule->parserAdoptSelectorVector(selectorVector);
+ rule->setProperties(createStylePropertySet());
+ pageRule = rule.get();
+ m_parsedRules.append(rule.release());
+ }
+ clearProperties();
+ return pageRule;
+}
+
+StyleRuleBase* BisonCSSParser::createMarginAtRule(CSSSelector::MarginBoxType /* marginBox */)
+{
+ // FIXME: Implement margin at-rule here, using:
+ // - marginBox: margin box
+ // - m_parsedProperties: properties at [m_numParsedPropertiesBeforeMarginBox, m_parsedProperties.size()] are for this at-rule.
+ // 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.
+
+ endDeclarationsForMarginBox();
+ return 0; // until this method is implemented.
+}
+
+void BisonCSSParser::startDeclarationsForMarginBox()
+{
+ m_numParsedPropertiesBeforeMarginBox = m_parsedProperties.size();
+}
+
+void BisonCSSParser::endDeclarationsForMarginBox()
+{
+ rollbackLastProperties(m_parsedProperties.size() - m_numParsedPropertiesBeforeMarginBox);
+ m_numParsedPropertiesBeforeMarginBox = INVALID_NUM_PARSED_PROPERTIES;
+}
+
+StyleKeyframe* BisonCSSParser::createKeyframe(CSSParserValueList* keys)
+{
+ OwnPtr<Vector<double> > keyVector = StyleKeyframe::createKeyList(keys);
+ if (keyVector->isEmpty())
+ return 0;
+
+ RefPtrWillBeRawPtr<StyleKeyframe> keyframe = StyleKeyframe::create();
+ keyframe->setKeys(keyVector.release());
+ keyframe->setProperties(createStylePropertySet());
+
+ clearProperties();
+
+ StyleKeyframe* keyframePtr = keyframe.get();
+ m_parsedKeyframes.append(keyframe.release());
+ return keyframePtr;
+}
+
+void BisonCSSParser::invalidBlockHit()
+{
+ if (m_styleSheet && !m_hadSyntacticallyValidCSSRule)
+ m_styleSheet->setHasSyntacticallyValidCSSHeader(false);
+}
+
+void BisonCSSParser::startRule()
+{
+ if (!m_observer)
+ return;
+
+ ASSERT(m_ruleHasHeader);
+ m_ruleHasHeader = false;
+}
+
+void BisonCSSParser::endRule(bool valid)
+{
+ if (!m_observer)
+ return;
+
+ if (m_ruleHasHeader)
+ m_observer->endRuleBody(m_tokenizer.safeUserStringTokenOffset(), !valid);
+ m_ruleHasHeader = true;
+}
+
+void BisonCSSParser::startRuleHeader(CSSRuleSourceData::Type ruleType)
+{
+ resumeErrorLogging();
+ m_ruleHeaderType = ruleType;
+ m_ruleHeaderStartOffset = m_tokenizer.safeUserStringTokenOffset();
+ m_ruleHeaderStartLineNumber = m_tokenizer.m_tokenStartLineNumber;
+ if (m_observer) {
+ ASSERT(!m_ruleHasHeader);
+ m_observer->startRuleHeader(ruleType, m_ruleHeaderStartOffset);
+ m_ruleHasHeader = true;
+ }
+}
+
+void BisonCSSParser::endRuleHeader()
+{
+ ASSERT(m_ruleHeaderType != CSSRuleSourceData::UNKNOWN_RULE);
+ m_ruleHeaderType = CSSRuleSourceData::UNKNOWN_RULE;
+ if (m_observer) {
+ ASSERT(m_ruleHasHeader);
+ m_observer->endRuleHeader(m_tokenizer.safeUserStringTokenOffset());
+ }
+}
+
+void BisonCSSParser::startSelector()
+{
+ if (m_observer)
+ m_observer->startSelector(m_tokenizer.safeUserStringTokenOffset());
+}
+
+void BisonCSSParser::endSelector()
+{
+ if (m_observer)
+ m_observer->endSelector(m_tokenizer.safeUserStringTokenOffset());
+}
+
+void BisonCSSParser::startRuleBody()
+{
+ if (m_observer)
+ m_observer->startRuleBody(m_tokenizer.safeUserStringTokenOffset());
+}
+
+void BisonCSSParser::startProperty()
+{
+ resumeErrorLogging();
+ if (m_observer)
+ m_observer->startProperty(m_tokenizer.safeUserStringTokenOffset());
+}
+
+void BisonCSSParser::endProperty(bool isImportantFound, bool isPropertyParsed, CSSParserError errorType)
+{
+ m_id = CSSPropertyInvalid;
+ if (m_observer)
+ m_observer->endProperty(isImportantFound, isPropertyParsed, m_tokenizer.safeUserStringTokenOffset(), errorType);
+}
+
+void BisonCSSParser::startEndUnknownRule()
+{
+ if (m_observer)
+ m_observer->startEndUnknownRule();
+}
+
+StyleRuleBase* BisonCSSParser::createViewportRule()
+{
+ // Allow @viewport rules from UA stylesheets even if the feature is disabled.
+ if (!RuntimeEnabledFeatures::cssViewportEnabled() && !isUASheetBehavior(m_context.mode()))
+ return 0;
+
+ m_allowImportRules = m_allowNamespaceDeclarations = false;
+
+ RefPtrWillBeRawPtr<StyleRuleViewport> rule = StyleRuleViewport::create();
+
+ rule->setProperties(createStylePropertySet());
+ clearProperties();
+
+ StyleRuleViewport* result = rule.get();
+ m_parsedRules.append(rule.release());
+
+ return result;
+}
+
+}