2 * Copyright (C) 2003 Lars Knoll (knoll@kde.org)
3 * Copyright (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com)
4 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved.
5 * Copyright (C) 2007 Nicholas Shanks <webkit@nickshanks.com>
6 * Copyright (C) 2008 Eric Seidel <eric@webkit.org>
7 * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
8 * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
9 * Copyright (C) 2012 Intel Corporation. All rights reserved.
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.
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.
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.
28 #include "core/css/parser/BisonCSSParser.h"
30 #include "CSSValueKeywords.h"
31 #include "RuntimeEnabledFeatures.h"
32 #include "StylePropertyShorthand.h"
33 #include "core/css/CSSArrayFunctionValue.h"
34 #include "core/css/CSSAspectRatioValue.h"
35 #include "core/css/CSSBasicShapes.h"
36 #include "core/css/CSSBorderImage.h"
37 #include "core/css/CSSCanvasValue.h"
38 #include "core/css/CSSCrossfadeValue.h"
39 #include "core/css/CSSCursorImageValue.h"
40 #include "core/css/CSSFontFaceSrcValue.h"
41 #include "core/css/CSSFontFeatureValue.h"
42 #include "core/css/CSSFunctionValue.h"
43 #include "core/css/CSSGradientValue.h"
44 #include "core/css/CSSGridLineNamesValue.h"
45 #include "core/css/CSSGridTemplateAreasValue.h"
46 #include "core/css/CSSImageSetValue.h"
47 #include "core/css/CSSImageValue.h"
48 #include "core/css/CSSInheritedValue.h"
49 #include "core/css/CSSInitialValue.h"
50 #include "core/css/CSSKeyframeRule.h"
51 #include "core/css/CSSKeyframesRule.h"
52 #include "core/css/CSSLineBoxContainValue.h"
53 #include "core/css/CSSPrimitiveValue.h"
54 #include "core/css/CSSPropertySourceData.h"
55 #include "core/css/CSSReflectValue.h"
56 #include "core/css/CSSSVGDocumentValue.h"
57 #include "core/css/CSSSelector.h"
58 #include "core/css/CSSShadowValue.h"
59 #include "core/css/CSSStyleSheet.h"
60 #include "core/css/CSSTimingFunctionValue.h"
61 #include "core/css/CSSTransformValue.h"
62 #include "core/css/CSSUnicodeRangeValue.h"
63 #include "core/css/CSSValueList.h"
64 #include "core/css/CSSValuePool.h"
65 #include "core/css/Counter.h"
66 #include "core/css/HashTools.h"
67 #include "core/css/MediaList.h"
68 #include "core/css/MediaQueryExp.h"
69 #include "core/css/Pair.h"
70 #include "core/css/Rect.h"
71 #include "core/css/StylePropertySet.h"
72 #include "core/css/StyleRule.h"
73 #include "core/css/StyleRuleImport.h"
74 #include "core/css/StyleSheetContents.h"
75 #include "core/css/parser/CSSParserIdioms.h"
76 #include "core/dom/Document.h"
77 #include "core/frame/FrameConsole.h"
78 #include "core/frame/FrameHost.h"
79 #include "core/frame/Settings.h"
80 #include "core/html/parser/HTMLParserIdioms.h"
81 #include "core/inspector/InspectorInstrumentation.h"
82 #include "core/rendering/RenderTheme.h"
83 #include "core/svg/SVGParserUtilities.h"
84 #include "platform/FloatConversion.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"
96 extern int cssyydebug;
99 int cssyyparse(WebCore::BisonCSSParser*);
106 static const unsigned INVALID_NUM_PARSED_PROPERTIES = UINT_MAX;
108 BisonCSSParser::BisonCSSParser(const CSSParserContext& context)
111 , m_id(CSSPropertyInvalid)
112 , m_styleSheet(nullptr)
113 , m_supportsCondition(false)
114 , m_selectorListForParseSelector(0)
115 , m_numParsedPropertiesBeforeMarginBox(INVALID_NUM_PARSED_PROPERTIES)
116 , m_hasFontFaceOnlyValues(false)
117 , m_hadSyntacticallyValidCSSRule(false)
119 , m_ignoreErrors(false)
120 , m_defaultNamespace(starAtom)
123 , m_ruleHeaderType(CSSRuleSourceData::UNKNOWN_RULE)
124 , m_allowImportRules(true)
125 , m_allowNamespaceDeclarations(true)
126 , m_inViewport(false)
134 BisonCSSParser::~BisonCSSParser()
138 deleteAllValues(m_floatingSelectors);
139 deleteAllValues(m_floatingSelectorVectors);
140 deleteAllValues(m_floatingValueLists);
141 deleteAllValues(m_floatingFunctions);
144 void BisonCSSParser::setupParser(const char* prefix, unsigned prefixLength, const String& string, const char* suffix, unsigned suffixLength)
146 m_tokenizer.setupTokenizer(prefix, prefixLength, string, suffix, suffixLength);
147 m_ruleHasHeader = true;
150 void BisonCSSParser::parseSheet(StyleSheetContents* sheet, const String& string, const TextPosition& startPosition, CSSParserObserver* observer, bool logErrors)
152 setStyleSheet(sheet);
153 m_defaultNamespace = starAtom; // Reset the default namespace.
154 TemporaryChange<CSSParserObserver*> scopedObsever(m_observer, observer);
155 m_logErrors = logErrors && sheet->singleOwnerDocument() && !sheet->baseURL().isEmpty() && sheet->singleOwnerDocument()->frameHost();
156 m_ignoreErrors = false;
157 m_tokenizer.m_lineNumber = 0;
158 m_startPosition = startPosition;
160 m_tokenizer.m_internal = false;
161 setupParser("", string, "");
163 sheet->shrinkToFit();
166 m_lineEndings.clear();
167 m_ignoreErrors = false;
169 m_tokenizer.m_internal = true;
172 PassRefPtrWillBeRawPtr<StyleRuleBase> BisonCSSParser::parseRule(StyleSheetContents* sheet, const String& string)
174 setStyleSheet(sheet);
175 m_allowNamespaceDeclarations = false;
176 setupParser("@-internal-rule ", string, "");
178 return m_rule.release();
181 PassRefPtrWillBeRawPtr<StyleKeyframe> BisonCSSParser::parseKeyframeRule(StyleSheetContents* sheet, const String& string)
183 setStyleSheet(sheet);
184 setupParser("@-internal-keyframe-rule ", string, "");
186 return m_keyframe.release();
189 PassOwnPtr<Vector<double> > BisonCSSParser::parseKeyframeKeyList(const String& string)
191 setupParser("@-internal-keyframe-key-list ", string, "");
194 return StyleKeyframe::createKeyList(m_valueList.get());
197 bool BisonCSSParser::parseSupportsCondition(const String& string)
199 m_supportsCondition = false;
200 setupParser("@-internal-supports-condition ", string, "");
202 return m_supportsCondition;
205 static inline bool isColorPropertyID(CSSPropertyID propertyId)
207 switch (propertyId) {
208 case CSSPropertyColor:
209 case CSSPropertyBackgroundColor:
210 case CSSPropertyBorderBottomColor:
211 case CSSPropertyBorderLeftColor:
212 case CSSPropertyBorderRightColor:
213 case CSSPropertyBorderTopColor:
214 case CSSPropertyOutlineColor:
215 case CSSPropertyTextLineThroughColor:
216 case CSSPropertyTextOverlineColor:
217 case CSSPropertyTextUnderlineColor:
218 case CSSPropertyWebkitBorderAfterColor:
219 case CSSPropertyWebkitBorderBeforeColor:
220 case CSSPropertyWebkitBorderEndColor:
221 case CSSPropertyWebkitBorderStartColor:
222 case CSSPropertyWebkitColumnRuleColor:
223 case CSSPropertyWebkitTextEmphasisColor:
224 case CSSPropertyWebkitTextFillColor:
225 case CSSPropertyWebkitTextStrokeColor:
227 case CSSPropertyTextDecorationColor:
228 return RuntimeEnabledFeatures::css3TextDecorationsEnabled();
234 static bool parseColorValue(MutableStylePropertySet* declaration, CSSPropertyID propertyId, const String& string, bool important, CSSParserMode cssParserMode)
236 ASSERT(!string.isEmpty());
237 bool quirksMode = isQuirksModeBehavior(cssParserMode);
238 if (!isColorPropertyID(propertyId))
240 CSSParserString cssString;
241 cssString.init(string);
242 CSSValueID valueID = cssValueKeywordID(cssString);
243 bool validPrimitive = false;
244 if (valueID == CSSValueWebkitText) {
245 validPrimitive = true;
246 } else if (valueID == CSSValueCurrentcolor) {
247 validPrimitive = true;
248 } else if ((valueID >= CSSValueAqua && valueID <= CSSValueWindowtext) || valueID == CSSValueMenu
249 || (quirksMode && valueID >= CSSValueWebkitFocusRingColor && valueID < CSSValueWebkitText)) {
250 validPrimitive = true;
253 if (validPrimitive) {
254 RefPtrWillBeRawPtr<CSSValue> value = cssValuePool().createIdentifierValue(valueID);
255 declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important));
259 if (!CSSPropertyParser::fastParseColor(color, string, !quirksMode && string[0] != '#'))
261 RefPtrWillBeRawPtr<CSSValue> value = cssValuePool().createColorValue(color);
262 declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important));
266 static inline bool isSimpleLengthPropertyID(CSSPropertyID propertyId, bool& acceptsNegativeNumbers)
268 switch (propertyId) {
269 case CSSPropertyFontSize:
270 case CSSPropertyHeight:
271 case CSSPropertyWidth:
272 case CSSPropertyMinHeight:
273 case CSSPropertyMinWidth:
274 case CSSPropertyPaddingBottom:
275 case CSSPropertyPaddingLeft:
276 case CSSPropertyPaddingRight:
277 case CSSPropertyPaddingTop:
278 case CSSPropertyWebkitLogicalWidth:
279 case CSSPropertyWebkitLogicalHeight:
280 case CSSPropertyWebkitMinLogicalWidth:
281 case CSSPropertyWebkitMinLogicalHeight:
282 case CSSPropertyWebkitPaddingAfter:
283 case CSSPropertyWebkitPaddingBefore:
284 case CSSPropertyWebkitPaddingEnd:
285 case CSSPropertyWebkitPaddingStart:
286 acceptsNegativeNumbers = false;
288 case CSSPropertyShapeMargin:
289 acceptsNegativeNumbers = false;
290 return RuntimeEnabledFeatures::cssShapesEnabled();
291 case CSSPropertyBottom:
292 case CSSPropertyLeft:
293 case CSSPropertyMarginBottom:
294 case CSSPropertyMarginLeft:
295 case CSSPropertyMarginRight:
296 case CSSPropertyMarginTop:
297 case CSSPropertyRight:
299 case CSSPropertyWebkitMarginAfter:
300 case CSSPropertyWebkitMarginBefore:
301 case CSSPropertyWebkitMarginEnd:
302 case CSSPropertyWebkitMarginStart:
303 acceptsNegativeNumbers = true;
310 template <typename CharacterType>
311 static inline bool parseSimpleLength(const CharacterType* characters, unsigned length, CSSPrimitiveValue::UnitTypes& unit, double& number)
313 if (length > 2 && (characters[length - 2] | 0x20) == 'p' && (characters[length - 1] | 0x20) == 'x') {
315 unit = CSSPrimitiveValue::CSS_PX;
316 } else if (length > 1 && characters[length - 1] == '%') {
318 unit = CSSPrimitiveValue::CSS_PERCENTAGE;
321 // We rely on charactersToDouble for validation as well. The function
322 // will set "ok" to "false" if the entire passed-in character range does
323 // not represent a double.
325 number = charactersToDouble(characters, length, &ok);
329 static bool parseSimpleLengthValue(MutableStylePropertySet* declaration, CSSPropertyID propertyId, const String& string, bool important, CSSParserMode cssParserMode)
331 ASSERT(!string.isEmpty());
332 bool acceptsNegativeNumbers = false;
334 // In @viewport, width and height are shorthands, not simple length values.
335 if (isCSSViewportParsingEnabledForMode(cssParserMode) || !isSimpleLengthPropertyID(propertyId, acceptsNegativeNumbers))
338 unsigned length = string.length();
340 CSSPrimitiveValue::UnitTypes unit = CSSPrimitiveValue::CSS_NUMBER;
342 if (string.is8Bit()) {
343 if (!parseSimpleLength(string.characters8(), length, unit, number))
346 if (!parseSimpleLength(string.characters16(), length, unit, number))
350 if (unit == CSSPrimitiveValue::CSS_NUMBER) {
351 bool quirksMode = isQuirksModeBehavior(cssParserMode);
352 if (number && !quirksMode)
354 unit = CSSPrimitiveValue::CSS_PX;
356 if (number < 0 && !acceptsNegativeNumbers)
359 RefPtrWillBeRawPtr<CSSValue> value = cssValuePool().createValue(number, unit);
360 declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important));
364 bool isValidKeywordPropertyAndValue(CSSPropertyID propertyId, int valueID, const CSSParserContext& parserContext)
369 switch (propertyId) {
370 case CSSPropertyBackgroundRepeatX: // repeat | no-repeat | inherit
371 case CSSPropertyBackgroundRepeatY: // repeat | no-repeat | inherit
372 if (valueID == CSSValueRepeat || valueID == CSSValueNoRepeat)
375 case CSSPropertyBorderCollapse: // collapse | separate | inherit
376 if (valueID == CSSValueCollapse || valueID == CSSValueSeparate)
379 case CSSPropertyBorderTopStyle: // <border-style> | inherit
380 case CSSPropertyBorderRightStyle: // Defined as: none | hidden | dotted | dashed |
381 case CSSPropertyBorderBottomStyle: // solid | double | groove | ridge | inset | outset
382 case CSSPropertyBorderLeftStyle:
383 case CSSPropertyWebkitBorderAfterStyle:
384 case CSSPropertyWebkitBorderBeforeStyle:
385 case CSSPropertyWebkitBorderEndStyle:
386 case CSSPropertyWebkitBorderStartStyle:
387 case CSSPropertyWebkitColumnRuleStyle:
388 if (valueID >= CSSValueNone && valueID <= CSSValueDouble)
391 case CSSPropertyBoxSizing:
392 if (valueID == CSSValueBorderBox || valueID == CSSValueContentBox)
395 case CSSPropertyCaptionSide: // top | bottom | left | right | inherit
396 if (valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueTop || valueID == CSSValueBottom)
399 case CSSPropertyClear: // none | left | right | both | inherit
400 if (valueID == CSSValueNone || valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueBoth)
403 case CSSPropertyDirection: // ltr | rtl | inherit
404 if (valueID == CSSValueLtr || valueID == CSSValueRtl)
407 case CSSPropertyDisplay:
408 // inline | block | list-item | inline-block | table |
409 // inline-table | table-row-group | table-header-group | table-footer-group | table-row |
410 // table-column-group | table-column | table-cell | table-caption | -webkit-box | -webkit-inline-box | none | inherit
411 // flex | inline-flex | -webkit-flex | -webkit-inline-flex | grid | inline-grid | lazy-block
412 if ((valueID >= CSSValueInline && valueID <= CSSValueInlineFlex) || valueID == CSSValueWebkitFlex || valueID == CSSValueWebkitInlineFlex || valueID == CSSValueNone)
414 if (valueID == CSSValueGrid || valueID == CSSValueInlineGrid)
415 return RuntimeEnabledFeatures::cssGridLayoutEnabled();
418 case CSSPropertyEmptyCells: // show | hide | inherit
419 if (valueID == CSSValueShow || valueID == CSSValueHide)
422 case CSSPropertyFloat: // left | right | none | center (for buggy CSS, maps to none)
423 if (valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueNone || valueID == CSSValueCenter)
426 case CSSPropertyFontStyle: // normal | italic | oblique | inherit
427 if (valueID == CSSValueNormal || valueID == CSSValueItalic || valueID == CSSValueOblique)
430 case CSSPropertyImageRendering: // auto | optimizeContrast
431 if (valueID == CSSValueAuto || valueID == CSSValueWebkitOptimizeContrast)
434 case CSSPropertyIsolation: // auto | isolate
435 if (valueID == CSSValueAuto || valueID == CSSValueIsolate)
436 return RuntimeEnabledFeatures::cssCompositingEnabled();
438 case CSSPropertyListStylePosition: // inside | outside | inherit
439 if (valueID == CSSValueInside || valueID == CSSValueOutside)
442 case CSSPropertyListStyleType:
443 // See section CSS_PROP_LIST_STYLE_TYPE of file CSSValueKeywords.in
444 // for the list of supported list-style-types.
445 if ((valueID >= CSSValueDisc && valueID <= CSSValueKatakanaIroha) || valueID == CSSValueNone)
448 case CSSPropertyObjectFit:
449 if (RuntimeEnabledFeatures::objectFitPositionEnabled()) {
450 if (valueID == CSSValueFill || valueID == CSSValueContain || valueID == CSSValueCover || valueID == CSSValueNone || valueID == CSSValueScaleDown)
454 case CSSPropertyOutlineStyle: // (<border-style> except hidden) | auto | inherit
455 if (valueID == CSSValueAuto || valueID == CSSValueNone || (valueID >= CSSValueInset && valueID <= CSSValueDouble))
458 case CSSPropertyOverflowWrap: // normal | break-word
459 case CSSPropertyWordWrap:
460 if (valueID == CSSValueNormal || valueID == CSSValueBreakWord)
463 case CSSPropertyOverflowX: // visible | hidden | scroll | auto | overlay | inherit
464 if (valueID == CSSValueVisible || valueID == CSSValueHidden || valueID == CSSValueScroll || valueID == CSSValueAuto || valueID == CSSValueOverlay)
467 case CSSPropertyOverflowY: // visible | hidden | scroll | auto | overlay | inherit | -webkit-paged-x | -webkit-paged-y
468 if (valueID == CSSValueVisible || valueID == CSSValueHidden || valueID == CSSValueScroll || valueID == CSSValueAuto || valueID == CSSValueOverlay || valueID == CSSValueWebkitPagedX || valueID == CSSValueWebkitPagedY)
471 case CSSPropertyPageBreakAfter: // auto | always | avoid | left | right | inherit
472 case CSSPropertyPageBreakBefore:
473 case CSSPropertyWebkitColumnBreakAfter:
474 case CSSPropertyWebkitColumnBreakBefore:
475 if (valueID == CSSValueAuto || valueID == CSSValueAlways || valueID == CSSValueAvoid || valueID == CSSValueLeft || valueID == CSSValueRight)
478 case CSSPropertyPageBreakInside: // avoid | auto | inherit
479 case CSSPropertyWebkitColumnBreakInside:
480 if (valueID == CSSValueAuto || valueID == CSSValueAvoid)
483 case CSSPropertyPointerEvents:
484 // none | visiblePainted | visibleFill | visibleStroke | visible |
485 // painted | fill | stroke | auto | all | bounding-box | inherit
486 if (valueID == CSSValueVisible || valueID == CSSValueNone || valueID == CSSValueAll || valueID == CSSValueAuto || (valueID >= CSSValueVisiblepainted && valueID <= CSSValueBoundingBox))
489 case CSSPropertyPosition: // static | relative | absolute | fixed | sticky | inherit
490 if (valueID == CSSValueStatic || valueID == CSSValueRelative || valueID == CSSValueAbsolute || valueID == CSSValueFixed
491 || (RuntimeEnabledFeatures::cssStickyPositionEnabled() && valueID == CSSValueSticky))
494 case CSSPropertyResize: // none | both | horizontal | vertical | auto
495 if (valueID == CSSValueNone || valueID == CSSValueBoth || valueID == CSSValueHorizontal || valueID == CSSValueVertical || valueID == CSSValueAuto)
498 case CSSPropertyScrollBehavior: // instant | smooth
499 if (valueID == CSSValueInstant || valueID == CSSValueSmooth)
500 return RuntimeEnabledFeatures::cssomSmoothScrollEnabled();
501 case CSSPropertySpeak: // none | normal | spell-out | digits | literal-punctuation | no-punctuation | inherit
502 if (valueID == CSSValueNone || valueID == CSSValueNormal || valueID == CSSValueSpellOut || valueID == CSSValueDigits || valueID == CSSValueLiteralPunctuation || valueID == CSSValueNoPunctuation)
505 case CSSPropertyTableLayout: // auto | fixed | inherit
506 if (valueID == CSSValueAuto || valueID == CSSValueFixed)
509 case CSSPropertyTextAlignLast:
510 // auto | start | end | left | right | center | justify
511 if (RuntimeEnabledFeatures::css3TextEnabled()
512 && ((valueID >= CSSValueLeft && valueID <= CSSValueJustify) || valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueAuto))
515 case CSSPropertyTextJustify:
516 // auto | none | inter-word | distribute
517 if (RuntimeEnabledFeatures::css3TextEnabled()
518 && (valueID == CSSValueInterWord || valueID == CSSValueDistribute || valueID == CSSValueAuto || valueID == CSSValueNone))
521 case CSSPropertyTextLineThroughMode:
522 case CSSPropertyTextOverlineMode:
523 case CSSPropertyTextUnderlineMode:
524 if (valueID == CSSValueContinuous || valueID == CSSValueSkipWhiteSpace)
527 case CSSPropertyTextLineThroughStyle:
528 case CSSPropertyTextOverlineStyle:
529 case CSSPropertyTextUnderlineStyle:
530 if (valueID == CSSValueNone || valueID == CSSValueSolid || valueID == CSSValueDouble || valueID == CSSValueDashed || valueID == CSSValueDotDash || valueID == CSSValueDotDotDash || valueID == CSSValueWave)
533 case CSSPropertyTextOverflow: // clip | ellipsis
534 if (valueID == CSSValueClip || valueID == CSSValueEllipsis)
537 case CSSPropertyTextRendering: // auto | optimizeSpeed | optimizeLegibility | geometricPrecision
538 if (valueID == CSSValueAuto || valueID == CSSValueOptimizespeed || valueID == CSSValueOptimizelegibility || valueID == CSSValueGeometricprecision)
541 case CSSPropertyTextTransform: // capitalize | uppercase | lowercase | none | inherit
542 if ((valueID >= CSSValueCapitalize && valueID <= CSSValueLowercase) || valueID == CSSValueNone)
545 case CSSPropertyTouchActionDelay: // none | script
546 if (RuntimeEnabledFeatures::cssTouchActionDelayEnabled() && (valueID == CSSValueScript || valueID == CSSValueNone))
549 case CSSPropertyVisibility: // visible | hidden | collapse | inherit
550 if (valueID == CSSValueVisible || valueID == CSSValueHidden || valueID == CSSValueCollapse)
553 case CSSPropertyWebkitAppearance:
554 if ((valueID >= CSSValueCheckbox && valueID <= CSSValueTextarea) || valueID == CSSValueNone)
557 case CSSPropertyBackfaceVisibility:
558 case CSSPropertyWebkitBackfaceVisibility:
559 if (valueID == CSSValueVisible || valueID == CSSValueHidden)
562 case CSSPropertyMixBlendMode:
563 if (RuntimeEnabledFeatures::cssCompositingEnabled() && (valueID == CSSValueNormal || valueID == CSSValueMultiply || valueID == CSSValueScreen
564 || valueID == CSSValueOverlay || valueID == CSSValueDarken || valueID == CSSValueLighten || valueID == CSSValueColorDodge
565 || valueID == CSSValueColorBurn || valueID == CSSValueHardLight || valueID == CSSValueSoftLight || valueID == CSSValueDifference
566 || valueID == CSSValueExclusion || valueID == CSSValueHue || valueID == CSSValueSaturation || valueID == CSSValueColor
567 || valueID == CSSValueLuminosity))
570 case CSSPropertyWebkitBorderFit:
571 if (valueID == CSSValueBorder || valueID == CSSValueLines)
574 case CSSPropertyWebkitBoxAlign:
575 if (valueID == CSSValueStretch || valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueCenter || valueID == CSSValueBaseline)
578 case CSSPropertyWebkitBoxDecorationBreak:
579 if (valueID == CSSValueClone || valueID == CSSValueSlice)
582 case CSSPropertyWebkitBoxDirection:
583 if (valueID == CSSValueNormal || valueID == CSSValueReverse)
586 case CSSPropertyWebkitBoxLines:
587 if (valueID == CSSValueSingle || valueID == CSSValueMultiple)
590 case CSSPropertyWebkitBoxOrient:
591 if (valueID == CSSValueHorizontal || valueID == CSSValueVertical || valueID == CSSValueInlineAxis || valueID == CSSValueBlockAxis)
594 case CSSPropertyWebkitBoxPack:
595 if (valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueCenter || valueID == CSSValueJustify)
598 case CSSPropertyInternalCallback:
599 // This property is only injected programmatically, not parsed from stylesheets.
601 case CSSPropertyColumnFill:
602 if (RuntimeEnabledFeatures::regionBasedColumnsEnabled()) {
603 if (valueID == CSSValueAuto || valueID == CSSValueBalance)
607 case CSSPropertyAlignContent:
608 // FIXME: Per CSS alignment, this property should accept an optional <overflow-position>. We should share this parsing code with 'justify-self'.
609 if (valueID == CSSValueFlexStart || valueID == CSSValueFlexEnd || valueID == CSSValueCenter || valueID == CSSValueSpaceBetween || valueID == CSSValueSpaceAround || valueID == CSSValueStretch)
612 case CSSPropertyAlignItems:
613 // FIXME: Per CSS alignment, this property should accept the same arguments as 'justify-self' so we should share its parsing code.
614 if (valueID == CSSValueFlexStart || valueID == CSSValueFlexEnd || valueID == CSSValueCenter || valueID == CSSValueBaseline || valueID == CSSValueStretch)
617 case CSSPropertyAlignSelf:
618 // FIXME: Per CSS alignment, this property should accept the same arguments as 'justify-self' so we should share its parsing code.
619 if (valueID == CSSValueAuto || valueID == CSSValueFlexStart || valueID == CSSValueFlexEnd || valueID == CSSValueCenter || valueID == CSSValueBaseline || valueID == CSSValueStretch)
622 case CSSPropertyFlexDirection:
623 if (valueID == CSSValueRow || valueID == CSSValueRowReverse || valueID == CSSValueColumn || valueID == CSSValueColumnReverse)
626 case CSSPropertyFlexWrap:
627 if (valueID == CSSValueNowrap || valueID == CSSValueWrap || valueID == CSSValueWrapReverse)
630 case CSSPropertyJustifyContent:
631 // FIXME: Per CSS alignment, this property should accept an optional <overflow-position>. We should share this parsing code with 'justify-self'.
632 if (valueID == CSSValueFlexStart || valueID == CSSValueFlexEnd || valueID == CSSValueCenter || valueID == CSSValueSpaceBetween || valueID == CSSValueSpaceAround)
635 case CSSPropertyFontKerning:
636 if (valueID == CSSValueAuto || valueID == CSSValueNormal || valueID == CSSValueNone)
639 case CSSPropertyWebkitFontSmoothing:
640 if (valueID == CSSValueAuto || valueID == CSSValueNone || valueID == CSSValueAntialiased || valueID == CSSValueSubpixelAntialiased)
643 case CSSPropertyGridAutoFlow:
644 if (valueID == CSSValueNone || valueID == CSSValueRow || valueID == CSSValueColumn)
645 return RuntimeEnabledFeatures::cssGridLayoutEnabled();
647 case CSSPropertyWebkitLineBreak: // auto | loose | normal | strict | after-white-space
648 if (valueID == CSSValueAuto || valueID == CSSValueLoose || valueID == CSSValueNormal || valueID == CSSValueStrict || valueID == CSSValueAfterWhiteSpace)
651 case CSSPropertyWebkitMarginAfterCollapse:
652 case CSSPropertyWebkitMarginBeforeCollapse:
653 case CSSPropertyWebkitMarginBottomCollapse:
654 case CSSPropertyWebkitMarginTopCollapse:
655 if (valueID == CSSValueCollapse || valueID == CSSValueSeparate || valueID == CSSValueDiscard)
658 case CSSPropertyInternalMarqueeDirection:
659 if (valueID == CSSValueForwards || valueID == CSSValueBackwards || valueID == CSSValueAhead || valueID == CSSValueReverse || valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueDown
660 || valueID == CSSValueUp || valueID == CSSValueAuto)
663 case CSSPropertyInternalMarqueeStyle:
664 if (valueID == CSSValueNone || valueID == CSSValueSlide || valueID == CSSValueScroll || valueID == CSSValueAlternate)
667 case CSSPropertyWebkitPrintColorAdjust:
668 if (valueID == CSSValueExact || valueID == CSSValueEconomy)
671 case CSSPropertyWebkitRtlOrdering:
672 if (valueID == CSSValueLogical || valueID == CSSValueVisual)
676 case CSSPropertyWebkitRubyPosition:
677 if (valueID == CSSValueBefore || valueID == CSSValueAfter)
681 case CSSPropertyWebkitTextCombine:
682 if (valueID == CSSValueNone || valueID == CSSValueHorizontal)
685 case CSSPropertyWebkitTextEmphasisPosition:
686 if (valueID == CSSValueOver || valueID == CSSValueUnder)
689 case CSSPropertyWebkitTextSecurity:
690 // disc | circle | square | none | inherit
691 if (valueID == CSSValueDisc || valueID == CSSValueCircle || valueID == CSSValueSquare || valueID == CSSValueNone)
694 case CSSPropertyTransformStyle:
695 case CSSPropertyWebkitTransformStyle:
696 if (valueID == CSSValueFlat || valueID == CSSValuePreserve3d)
699 case CSSPropertyWebkitUserDrag: // auto | none | element
700 if (valueID == CSSValueAuto || valueID == CSSValueNone || valueID == CSSValueElement)
703 case CSSPropertyWebkitUserModify: // read-only | read-write
704 if (valueID == CSSValueReadOnly || valueID == CSSValueReadWrite || valueID == CSSValueReadWritePlaintextOnly)
707 case CSSPropertyWebkitUserSelect: // auto | none | text | all
708 if (valueID == CSSValueAuto || valueID == CSSValueNone || valueID == CSSValueText || valueID == CSSValueAll)
711 case CSSPropertyWebkitWrapFlow:
712 if (!RuntimeEnabledFeatures::cssExclusionsEnabled())
714 if (valueID == CSSValueAuto || valueID == CSSValueBoth || valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueMaximum || valueID == CSSValueClear)
717 case CSSPropertyWebkitWrapThrough:
718 if (!RuntimeEnabledFeatures::cssExclusionsEnabled())
720 if (valueID == CSSValueWrap || valueID == CSSValueNone)
723 case CSSPropertyWebkitWritingMode:
724 if (valueID >= CSSValueHorizontalTb && valueID <= CSSValueHorizontalBt)
727 case CSSPropertyWhiteSpace: // normal | pre | nowrap | inherit
728 if (valueID == CSSValueNormal || valueID == CSSValuePre || valueID == CSSValuePreWrap || valueID == CSSValuePreLine || valueID == CSSValueNowrap)
731 case CSSPropertyWordBreak: // normal | break-all | break-word (this is a custom extension)
732 if (valueID == CSSValueNormal || valueID == CSSValueBreakAll || valueID == CSSValueBreakWord)
736 ASSERT_NOT_REACHED();
742 bool isKeywordPropertyID(CSSPropertyID propertyId)
744 switch (propertyId) {
745 case CSSPropertyMixBlendMode:
746 case CSSPropertyIsolation:
747 case CSSPropertyBackgroundRepeatX:
748 case CSSPropertyBackgroundRepeatY:
749 case CSSPropertyBorderBottomStyle:
750 case CSSPropertyBorderCollapse:
751 case CSSPropertyBorderLeftStyle:
752 case CSSPropertyBorderRightStyle:
753 case CSSPropertyBorderTopStyle:
754 case CSSPropertyBoxSizing:
755 case CSSPropertyCaptionSide:
756 case CSSPropertyClear:
757 case CSSPropertyDirection:
758 case CSSPropertyDisplay:
759 case CSSPropertyEmptyCells:
760 case CSSPropertyFloat:
761 case CSSPropertyFontStyle:
762 case CSSPropertyImageRendering:
763 case CSSPropertyListStylePosition:
764 case CSSPropertyListStyleType:
765 case CSSPropertyObjectFit:
766 case CSSPropertyOutlineStyle:
767 case CSSPropertyOverflowWrap:
768 case CSSPropertyOverflowX:
769 case CSSPropertyOverflowY:
770 case CSSPropertyPageBreakAfter:
771 case CSSPropertyPageBreakBefore:
772 case CSSPropertyPageBreakInside:
773 case CSSPropertyPointerEvents:
774 case CSSPropertyPosition:
775 case CSSPropertyResize:
776 case CSSPropertyScrollBehavior:
777 case CSSPropertySpeak:
778 case CSSPropertyTableLayout:
779 case CSSPropertyTextAlignLast:
780 case CSSPropertyTextJustify:
781 case CSSPropertyTextLineThroughMode:
782 case CSSPropertyTextLineThroughStyle:
783 case CSSPropertyTextOverflow:
784 case CSSPropertyTextOverlineMode:
785 case CSSPropertyTextOverlineStyle:
786 case CSSPropertyTextRendering:
787 case CSSPropertyTextTransform:
788 case CSSPropertyTextUnderlineMode:
789 case CSSPropertyTextUnderlineStyle:
790 case CSSPropertyTouchActionDelay:
791 case CSSPropertyVisibility:
792 case CSSPropertyWebkitAppearance:
793 case CSSPropertyBackfaceVisibility:
794 case CSSPropertyWebkitBackfaceVisibility:
795 case CSSPropertyWebkitBorderAfterStyle:
796 case CSSPropertyWebkitBorderBeforeStyle:
797 case CSSPropertyWebkitBorderEndStyle:
798 case CSSPropertyWebkitBorderFit:
799 case CSSPropertyWebkitBorderStartStyle:
800 case CSSPropertyWebkitBoxAlign:
801 case CSSPropertyWebkitBoxDecorationBreak:
802 case CSSPropertyWebkitBoxDirection:
803 case CSSPropertyWebkitBoxLines:
804 case CSSPropertyWebkitBoxOrient:
805 case CSSPropertyWebkitBoxPack:
806 case CSSPropertyInternalCallback:
807 case CSSPropertyWebkitColumnBreakAfter:
808 case CSSPropertyWebkitColumnBreakBefore:
809 case CSSPropertyWebkitColumnBreakInside:
810 case CSSPropertyColumnFill:
811 case CSSPropertyWebkitColumnRuleStyle:
812 case CSSPropertyAlignContent:
813 case CSSPropertyFlexDirection:
814 case CSSPropertyFlexWrap:
815 case CSSPropertyJustifyContent:
816 case CSSPropertyFontKerning:
817 case CSSPropertyWebkitFontSmoothing:
818 case CSSPropertyGridAutoFlow:
819 case CSSPropertyWebkitLineBreak:
820 case CSSPropertyWebkitMarginAfterCollapse:
821 case CSSPropertyWebkitMarginBeforeCollapse:
822 case CSSPropertyWebkitMarginBottomCollapse:
823 case CSSPropertyWebkitMarginTopCollapse:
824 case CSSPropertyInternalMarqueeDirection:
825 case CSSPropertyInternalMarqueeStyle:
826 case CSSPropertyWebkitPrintColorAdjust:
827 case CSSPropertyWebkitRtlOrdering:
828 case CSSPropertyWebkitRubyPosition:
829 case CSSPropertyWebkitTextCombine:
830 case CSSPropertyWebkitTextEmphasisPosition:
831 case CSSPropertyWebkitTextSecurity:
832 case CSSPropertyTransformStyle:
833 case CSSPropertyWebkitTransformStyle:
834 case CSSPropertyWebkitUserDrag:
835 case CSSPropertyWebkitUserModify:
836 case CSSPropertyWebkitUserSelect:
837 case CSSPropertyWebkitWrapFlow:
838 case CSSPropertyWebkitWrapThrough:
839 case CSSPropertyWebkitWritingMode:
840 case CSSPropertyWhiteSpace:
841 case CSSPropertyWordBreak:
842 case CSSPropertyWordWrap:
844 case CSSPropertyAlignItems:
845 case CSSPropertyAlignSelf:
846 return !RuntimeEnabledFeatures::cssGridLayoutEnabled();
852 static bool parseKeywordValue(MutableStylePropertySet* declaration, CSSPropertyID propertyId, const String& string, bool important, const CSSParserContext& parserContext)
854 ASSERT(!string.isEmpty());
856 if (!isKeywordPropertyID(propertyId)) {
857 // All properties accept the values of "initial" and "inherit".
858 String lowerCaseString = string.lower();
859 if (lowerCaseString != "initial" && lowerCaseString != "inherit")
862 // Parse initial/inherit shorthands using the BisonCSSParser.
863 if (shorthandForProperty(propertyId).length())
867 CSSParserString cssString;
868 cssString.init(string);
869 CSSValueID valueID = cssValueKeywordID(cssString);
874 RefPtrWillBeRawPtr<CSSValue> value = nullptr;
875 if (valueID == CSSValueInherit)
876 value = cssValuePool().createInheritedValue();
877 else if (valueID == CSSValueInitial)
878 value = cssValuePool().createExplicitInitialValue();
879 else if (isValidKeywordPropertyAndValue(propertyId, valueID, parserContext))
880 value = cssValuePool().createIdentifierValue(valueID);
884 declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important));
888 template <typename CharType>
889 static bool parseTransformTranslateArguments(CharType*& pos, CharType* end, unsigned expectedCount, CSSTransformValue* transformValue)
891 while (expectedCount) {
892 size_t delimiter = WTF::find(pos, end - pos, expectedCount == 1 ? ')' : ',');
893 if (delimiter == kNotFound)
895 unsigned argumentLength = static_cast<unsigned>(delimiter);
896 CSSPrimitiveValue::UnitTypes unit = CSSPrimitiveValue::CSS_NUMBER;
898 if (!parseSimpleLength(pos, argumentLength, unit, number))
900 if (unit != CSSPrimitiveValue::CSS_PX && (number || unit != CSSPrimitiveValue::CSS_NUMBER))
902 transformValue->append(cssValuePool().createValue(number, CSSPrimitiveValue::CSS_PX));
903 pos += argumentLength + 1;
909 template <typename CharType>
910 static bool parseTransformNumberArguments(CharType*& pos, CharType* end, unsigned expectedCount, CSSTransformValue* transformValue)
912 while (expectedCount) {
913 size_t delimiter = WTF::find(pos, end - pos, expectedCount == 1 ? ')' : ',');
914 if (delimiter == kNotFound)
916 unsigned argumentLength = static_cast<unsigned>(delimiter);
918 double number = charactersToDouble(pos, argumentLength, &ok);
921 transformValue->append(cssValuePool().createValue(number, CSSPrimitiveValue::CSS_NUMBER));
922 pos += argumentLength + 1;
928 template <typename CharType>
929 static PassRefPtrWillBeRawPtr<CSSTransformValue> parseSimpleTransformValue(CharType*& pos, CharType* end)
931 static const int shortestValidTransformStringLength = 12;
933 if (end - pos < shortestValidTransformStringLength)
936 const bool isTranslate = toASCIILower(pos[0]) == 't'
937 && toASCIILower(pos[1]) == 'r'
938 && toASCIILower(pos[2]) == 'a'
939 && toASCIILower(pos[3]) == 'n'
940 && toASCIILower(pos[4]) == 's'
941 && toASCIILower(pos[5]) == 'l'
942 && toASCIILower(pos[6]) == 'a'
943 && toASCIILower(pos[7]) == 't'
944 && toASCIILower(pos[8]) == 'e';
947 CSSTransformValue::TransformOperationType transformType;
948 unsigned expectedArgumentCount = 1;
949 unsigned argumentStart = 11;
950 CharType c9 = toASCIILower(pos[9]);
951 if (c9 == 'x' && pos[10] == '(') {
952 transformType = CSSTransformValue::TranslateXTransformOperation;
953 } else if (c9 == 'y' && pos[10] == '(') {
954 transformType = CSSTransformValue::TranslateYTransformOperation;
955 } else if (c9 == 'z' && pos[10] == '(') {
956 transformType = CSSTransformValue::TranslateZTransformOperation;
957 } else if (c9 == '(') {
958 transformType = CSSTransformValue::TranslateTransformOperation;
959 expectedArgumentCount = 2;
961 } else if (c9 == '3' && toASCIILower(pos[10]) == 'd' && pos[11] == '(') {
962 transformType = CSSTransformValue::Translate3DTransformOperation;
963 expectedArgumentCount = 3;
968 pos += argumentStart;
969 RefPtrWillBeRawPtr<CSSTransformValue> transformValue = CSSTransformValue::create(transformType);
970 if (!parseTransformTranslateArguments(pos, end, expectedArgumentCount, transformValue.get()))
972 return transformValue.release();
975 const bool isMatrix3d = toASCIILower(pos[0]) == 'm'
976 && toASCIILower(pos[1]) == 'a'
977 && toASCIILower(pos[2]) == 't'
978 && toASCIILower(pos[3]) == 'r'
979 && toASCIILower(pos[4]) == 'i'
980 && toASCIILower(pos[5]) == 'x'
982 && toASCIILower(pos[7]) == 'd'
987 RefPtrWillBeRawPtr<CSSTransformValue> transformValue = CSSTransformValue::create(CSSTransformValue::Matrix3DTransformOperation);
988 if (!parseTransformNumberArguments(pos, end, 16, transformValue.get()))
990 return transformValue.release();
993 const bool isScale3d = toASCIILower(pos[0]) == 's'
994 && toASCIILower(pos[1]) == 'c'
995 && toASCIILower(pos[2]) == 'a'
996 && toASCIILower(pos[3]) == 'l'
997 && toASCIILower(pos[4]) == 'e'
999 && toASCIILower(pos[6]) == 'd'
1004 RefPtrWillBeRawPtr<CSSTransformValue> transformValue = CSSTransformValue::create(CSSTransformValue::Scale3DTransformOperation);
1005 if (!parseTransformNumberArguments(pos, end, 3, transformValue.get()))
1007 return transformValue.release();
1013 template <typename CharType>
1014 static PassRefPtrWillBeRawPtr<CSSValueList> parseSimpleTransformList(CharType*& pos, CharType* end)
1016 RefPtrWillBeRawPtr<CSSValueList> transformList = nullptr;
1018 while (pos < end && isCSSSpace(*pos))
1020 RefPtrWillBeRawPtr<CSSTransformValue> transformValue = parseSimpleTransformValue(pos, end);
1021 if (!transformValue)
1024 transformList = CSSValueList::createSpaceSeparated();
1025 transformList->append(transformValue.release());
1027 if (isCSSSpace(*pos))
1031 return transformList.release();
1034 static bool parseSimpleTransform(MutableStylePropertySet* properties, CSSPropertyID propertyID, const String& string, bool important)
1036 if (propertyID != CSSPropertyTransform && propertyID != CSSPropertyWebkitTransform)
1038 if (string.isEmpty())
1040 RefPtrWillBeRawPtr<CSSValueList> transformList = nullptr;
1041 if (string.is8Bit()) {
1042 const LChar* pos = string.characters8();
1043 const LChar* end = pos + string.length();
1044 transformList = parseSimpleTransformList(pos, end);
1048 const UChar* pos = string.characters16();
1049 const UChar* end = pos + string.length();
1050 transformList = parseSimpleTransformList(pos, end);
1054 properties->addParsedProperty(CSSProperty(propertyID, transformList.release(), important));
1058 PassRefPtrWillBeRawPtr<CSSValueList> BisonCSSParser::parseFontFaceValue(const AtomicString& string)
1060 if (string.isEmpty())
1062 RefPtrWillBeRawPtr<MutableStylePropertySet> dummyStyle = MutableStylePropertySet::create();
1063 if (!parseValue(dummyStyle.get(), CSSPropertyFontFamily, string, false, HTMLQuirksMode, 0))
1066 RefPtrWillBeRawPtr<CSSValue> fontFamily = dummyStyle->getPropertyCSSValue(CSSPropertyFontFamily);
1067 if (!fontFamily->isValueList())
1070 return toCSSValueList(dummyStyle->getPropertyCSSValue(CSSPropertyFontFamily).get());
1073 PassRefPtrWillBeRawPtr<CSSValue> BisonCSSParser::parseAnimationTimingFunctionValue(const String& string)
1075 if (string.isEmpty())
1077 RefPtrWillBeRawPtr<MutableStylePropertySet> style = MutableStylePropertySet::create();
1078 if (!parseValue(style.get(), CSSPropertyTransitionTimingFunction, string, false, HTMLStandardMode, 0))
1081 return style->getPropertyCSSValue(CSSPropertyTransitionTimingFunction);
1084 bool BisonCSSParser::parseValue(MutableStylePropertySet* declaration, CSSPropertyID propertyID, const String& string, bool important, const Document& document)
1086 ASSERT(!string.isEmpty());
1088 CSSParserContext context(document, UseCounter::getFrom(&document));
1090 if (parseSimpleLengthValue(declaration, propertyID, string, important, context.mode()))
1092 if (parseColorValue(declaration, propertyID, string, important, context.mode()))
1094 if (parseKeywordValue(declaration, propertyID, string, important, context))
1097 BisonCSSParser parser(context);
1098 return parser.parseValue(declaration, propertyID, string, important, static_cast<StyleSheetContents*>(0));
1101 bool BisonCSSParser::parseValue(MutableStylePropertySet* declaration, CSSPropertyID propertyID, const String& string, bool important, CSSParserMode cssParserMode, StyleSheetContents* contextStyleSheet)
1103 ASSERT(!string.isEmpty());
1104 if (parseSimpleLengthValue(declaration, propertyID, string, important, cssParserMode))
1106 if (parseColorValue(declaration, propertyID, string, important, cssParserMode))
1109 CSSParserContext context(cssParserMode, 0);
1110 if (contextStyleSheet) {
1111 context = contextStyleSheet->parserContext();
1112 context.setMode(cssParserMode);
1115 if (parseKeywordValue(declaration, propertyID, string, important, context))
1117 if (parseSimpleTransform(declaration, propertyID, string, important))
1120 BisonCSSParser parser(context);
1121 return parser.parseValue(declaration, propertyID, string, important, contextStyleSheet);
1124 bool BisonCSSParser::parseValue(MutableStylePropertySet* declaration, CSSPropertyID propertyID, const String& string, bool important, StyleSheetContents* contextStyleSheet)
1126 // FIXME: Check RuntimeCSSEnabled::isPropertyEnabled or isValueEnabledForProperty.
1128 if (m_context.useCounter())
1129 m_context.useCounter()->count(m_context, propertyID);
1131 setStyleSheet(contextStyleSheet);
1133 setupParser("@-internal-value ", string, "");
1136 m_important = important;
1139 StyleDeclarationScope scope(this, declaration);
1144 m_id = CSSPropertyInvalid;
1147 if (m_hasFontFaceOnlyValues)
1148 deleteFontFaceOnlyValues();
1149 if (!m_parsedProperties.isEmpty()) {
1151 declaration->addParsedProperties(m_parsedProperties);
1158 // The color will only be changed when string contains a valid CSS color, so callers
1159 // can set it to a default color and ignore the boolean result.
1160 bool BisonCSSParser::parseColor(RGBA32& color, const String& string, bool strict)
1162 // First try creating a color specified by name, rgba(), rgb() or "#" syntax.
1163 if (CSSPropertyParser::fastParseColor(color, string, strict))
1166 BisonCSSParser parser(strictCSSParserContext());
1168 // In case the fast-path parser didn't understand the color, try the full parser.
1169 if (!parser.parseColor(string))
1172 CSSValue* value = parser.m_parsedProperties.first().value();
1173 if (!value->isPrimitiveValue())
1176 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
1177 if (!primitiveValue->isRGBColor())
1180 color = primitiveValue->getRGBA32Value();
1184 bool BisonCSSParser::parseColor(const String& string)
1186 setupParser("@-internal-decls color:", string, "");
1190 return !m_parsedProperties.isEmpty() && m_parsedProperties.first().id() == CSSPropertyColor;
1193 bool BisonCSSParser::parseSystemColor(RGBA32& color, const String& string)
1195 CSSParserString cssColor;
1196 cssColor.init(string);
1197 CSSValueID id = cssValueKeywordID(cssColor);
1198 if (!CSSPropertyParser::isSystemColor(id))
1201 Color parsedColor = RenderTheme::theme().systemColor(id);
1202 color = parsedColor.rgb();
1206 void BisonCSSParser::parseSelector(const String& string, CSSSelectorList& selectorList)
1208 m_selectorListForParseSelector = &selectorList;
1210 setupParser("@-internal-selector ", string, "");
1214 m_selectorListForParseSelector = 0;
1217 PassRefPtr<ImmutableStylePropertySet> BisonCSSParser::parseInlineStyleDeclaration(const String& string, Element* element)
1219 Document& document = element->document();
1220 CSSParserContext context = CSSParserContext(document.elementSheet().contents()->parserContext(), UseCounter::getFrom(&document));
1221 context.setMode((element->isHTMLElement() && !document.inQuirksMode()) ? HTMLStandardMode : HTMLQuirksMode);
1222 return BisonCSSParser(context).parseDeclaration(string, document.elementSheet().contents());
1225 PassRefPtr<ImmutableStylePropertySet> BisonCSSParser::parseDeclaration(const String& string, StyleSheetContents* contextStyleSheet)
1227 setStyleSheet(contextStyleSheet);
1229 setupParser("@-internal-decls ", string, "");
1233 if (m_hasFontFaceOnlyValues)
1234 deleteFontFaceOnlyValues();
1236 RefPtr<ImmutableStylePropertySet> style = createStylePropertySet();
1238 return style.release();
1242 bool BisonCSSParser::parseDeclaration(MutableStylePropertySet* declaration, const String& string, CSSParserObserver* observer, StyleSheetContents* contextStyleSheet)
1244 setStyleSheet(contextStyleSheet);
1246 TemporaryChange<CSSParserObserver*> scopedObsever(m_observer, observer);
1248 setupParser("@-internal-decls ", string, "");
1250 m_observer->startRuleHeader(CSSRuleSourceData::STYLE_RULE, 0);
1251 m_observer->endRuleHeader(1);
1252 m_observer->startRuleBody(0);
1256 StyleDeclarationScope scope(this, declaration);
1263 if (m_hasFontFaceOnlyValues)
1264 deleteFontFaceOnlyValues();
1265 if (!m_parsedProperties.isEmpty()) {
1267 declaration->addParsedProperties(m_parsedProperties);
1272 m_observer->endRuleBody(string.length(), false);
1277 PassRefPtrWillBeRawPtr<MediaQuerySet> BisonCSSParser::parseMediaQueryList(const String& string)
1279 ASSERT(!m_mediaList);
1281 // can't use { because tokenizer state switches from mediaquery to initial state when it sees { token.
1282 // instead insert one " " (which is caught by maybe_space in CSSGrammar.y)
1283 setupParser("@-internal-medialist ", string, "");
1286 ASSERT(m_mediaList);
1287 return m_mediaList.release();
1290 static inline void filterProperties(bool important, const WillBeHeapVector<CSSProperty, 256>& input, WillBeHeapVector<CSSProperty, 256>& output, size_t& unusedEntries, BitArray<numCSSProperties>& seenProperties)
1292 // Add properties in reverse order so that highest priority definitions are reached first. Duplicate definitions can then be ignored when found.
1293 for (int i = input.size() - 1; i >= 0; --i) {
1294 const CSSProperty& property = input[i];
1295 if (property.isImportant() != important)
1297 const unsigned propertyIDIndex = property.id() - firstCSSProperty;
1298 if (seenProperties.get(propertyIDIndex))
1300 seenProperties.set(propertyIDIndex);
1301 output[--unusedEntries] = property;
1305 PassRefPtr<ImmutableStylePropertySet> BisonCSSParser::createStylePropertySet()
1307 BitArray<numCSSProperties> seenProperties;
1308 size_t unusedEntries = m_parsedProperties.size();
1309 WillBeHeapVector<CSSProperty, 256> results(unusedEntries);
1311 // Important properties have higher priority, so add them first. Duplicate definitions can then be ignored when found.
1312 filterProperties(true, m_parsedProperties, results, unusedEntries, seenProperties);
1313 filterProperties(false, m_parsedProperties, results, unusedEntries, seenProperties);
1315 results.remove(0, unusedEntries);
1317 CSSParserMode mode = inViewport() ? CSSViewportRuleMode : m_context.mode();
1319 return ImmutableStylePropertySet::create(results.data(), results.size(), mode);
1322 void BisonCSSParser::rollbackLastProperties(int num)
1325 ASSERT(m_parsedProperties.size() >= static_cast<unsigned>(num));
1326 m_parsedProperties.shrink(m_parsedProperties.size() - num);
1329 void BisonCSSParser::clearProperties()
1331 m_parsedProperties.clear();
1332 m_numParsedPropertiesBeforeMarginBox = INVALID_NUM_PARSED_PROPERTIES;
1333 m_hasFontFaceOnlyValues = false;
1336 void BisonCSSParser::setCurrentProperty(CSSPropertyID propId)
1341 bool BisonCSSParser::parseValue(CSSPropertyID propId, bool important)
1343 CSSPropertyParser parser(m_valueList, m_context, m_inViewport, m_important, m_parsedProperties, m_hasFontFaceOnlyValues);
1344 return parser.parseValue(propId, important);
1348 class TransformOperationInfo {
1350 TransformOperationInfo(const CSSParserString& name)
1351 : m_type(CSSTransformValue::UnknownTransformOperation)
1353 , m_allowSingleArgument(false)
1354 , m_unit(CSSPropertyParser::FUnknown)
1356 const UChar* characters;
1357 unsigned nameLength = name.length();
1359 const unsigned longestNameLength = 12;
1360 UChar characterBuffer[longestNameLength];
1361 if (name.is8Bit()) {
1362 unsigned length = std::min(longestNameLength, nameLength);
1363 const LChar* characters8 = name.characters8();
1364 for (unsigned i = 0; i < length; ++i)
1365 characterBuffer[i] = characters8[i];
1366 characters = characterBuffer;
1368 characters = name.characters16();
1370 SWITCH(characters, nameLength) {
1372 m_unit = CSSPropertyParser::FAngle;
1373 m_type = CSSTransformValue::SkewTransformOperation;
1374 m_allowSingleArgument = true;
1378 m_unit = CSSPropertyParser::FNumber;
1379 m_type = CSSTransformValue::ScaleTransformOperation;
1380 m_allowSingleArgument = true;
1384 m_unit = CSSPropertyParser::FAngle;
1385 m_type = CSSTransformValue::SkewXTransformOperation;
1388 m_unit = CSSPropertyParser::FAngle;
1389 m_type = CSSTransformValue::SkewYTransformOperation;
1392 m_unit = CSSPropertyParser::FNumber;
1393 m_type = CSSTransformValue::MatrixTransformOperation;
1397 m_unit = CSSPropertyParser::FAngle;
1398 m_type = CSSTransformValue::RotateTransformOperation;
1401 m_unit = CSSPropertyParser::FNumber;
1402 m_type = CSSTransformValue::ScaleXTransformOperation;
1405 m_unit = CSSPropertyParser::FNumber;
1406 m_type = CSSTransformValue::ScaleYTransformOperation;
1409 m_unit = CSSPropertyParser::FNumber;
1410 m_type = CSSTransformValue::ScaleZTransformOperation;
1413 m_unit = CSSPropertyParser::FNumber;
1414 m_type = CSSTransformValue::Scale3DTransformOperation;
1418 m_unit = CSSPropertyParser::FAngle;
1419 m_type = CSSTransformValue::RotateXTransformOperation;
1422 m_unit = CSSPropertyParser::FAngle;
1423 m_type = CSSTransformValue::RotateYTransformOperation;
1426 m_unit = CSSPropertyParser::FAngle;
1427 m_type = CSSTransformValue::RotateZTransformOperation;
1430 m_unit = CSSPropertyParser::FNumber;
1431 m_type = CSSTransformValue::Matrix3DTransformOperation;
1435 m_unit = CSSPropertyParser::FNumber;
1436 m_type = CSSTransformValue::Rotate3DTransformOperation;
1439 CASE("translate(") {
1440 m_unit = CSSPropertyParser::FLength | CSSPropertyParser::FPercent;
1441 m_type = CSSTransformValue::TranslateTransformOperation;
1442 m_allowSingleArgument = true;
1445 CASE("translatex(") {
1446 m_unit = CSSPropertyParser::FLength | CSSPropertyParser::FPercent;
1447 m_type = CSSTransformValue::TranslateXTransformOperation;
1449 CASE("translatey(") {
1450 m_unit = CSSPropertyParser::FLength | CSSPropertyParser::FPercent;
1451 m_type = CSSTransformValue::TranslateYTransformOperation;
1453 CASE("translatez(") {
1454 m_unit = CSSPropertyParser::FLength | CSSPropertyParser::FPercent;
1455 m_type = CSSTransformValue::TranslateZTransformOperation;
1457 CASE("perspective(") {
1458 m_unit = CSSPropertyParser::FNumber;
1459 m_type = CSSTransformValue::PerspectiveTransformOperation;
1461 CASE("translate3d(") {
1462 m_unit = CSSPropertyParser::FLength | CSSPropertyParser::FPercent;
1463 m_type = CSSTransformValue::Translate3DTransformOperation;
1469 CSSTransformValue::TransformOperationType type() const { return m_type; }
1470 unsigned argCount() const { return m_argCount; }
1471 CSSPropertyParser::Units unit() const { return m_unit; }
1473 bool unknown() const { return m_type == CSSTransformValue::UnknownTransformOperation; }
1474 bool hasCorrectArgCount(unsigned argCount) { return m_argCount == argCount || (m_allowSingleArgument && argCount == 1); }
1477 CSSTransformValue::TransformOperationType m_type;
1478 unsigned m_argCount;
1479 bool m_allowSingleArgument;
1480 CSSPropertyParser::Units m_unit;
1483 PassRefPtrWillBeRawPtr<CSSValueList> CSSPropertyParser::parseTransform(CSSPropertyID propId)
1488 RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
1489 for (CSSParserValue* value = m_valueList->current(); value; value = m_valueList->next()) {
1490 RefPtrWillBeRawPtr<CSSValue> parsedTransformValue = parseTransformValue(propId, value);
1491 if (!parsedTransformValue)
1494 list->append(parsedTransformValue.release());
1497 return list.release();
1500 PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseTransformValue(CSSPropertyID propId, CSSParserValue *value)
1502 if (value->unit != CSSParserValue::Function || !value->function)
1505 // Every primitive requires at least one argument.
1506 CSSParserValueList* args = value->function->args.get();
1510 // See if the specified primitive is one we understand.
1511 TransformOperationInfo info(value->function->name);
1515 if (!info.hasCorrectArgCount(args->size()))
1518 // The transform is a list of functional primitives that specify transform operations.
1519 // We collect a list of CSSTransformValues, where each value specifies a single operation.
1521 // Create the new CSSTransformValue for this operation and add it to our list.
1522 RefPtrWillBeRawPtr<CSSTransformValue> transformValue = CSSTransformValue::create(info.type());
1525 CSSParserValue* a = args->current();
1526 unsigned argNumber = 0;
1528 CSSPropertyParser::Units unit = info.unit();
1530 if (info.type() == CSSTransformValue::Rotate3DTransformOperation && argNumber == 3) {
1531 // 4th param of rotate3d() is an angle rather than a bare number, validate it as such
1532 if (!validUnit(a, FAngle, HTMLStandardMode))
1534 } else if (info.type() == CSSTransformValue::Translate3DTransformOperation && argNumber == 2) {
1535 // 3rd param of translate3d() cannot be a percentage
1536 if (!validUnit(a, FLength, HTMLStandardMode))
1538 } else if (info.type() == CSSTransformValue::TranslateZTransformOperation && !argNumber) {
1539 // 1st param of translateZ() cannot be a percentage
1540 if (!validUnit(a, FLength, HTMLStandardMode))
1542 } else if (info.type() == CSSTransformValue::PerspectiveTransformOperation && !argNumber) {
1543 // 1st param of perspective() must be a non-negative number (deprecated) or length.
1544 if ((propId == CSSPropertyWebkitTransform && !validUnit(a, FNumber | FLength | FNonNeg, HTMLStandardMode))
1545 || (propId == CSSPropertyTransform && !validUnit(a, FLength | FNonNeg, HTMLStandardMode)))
1547 } else if (!validUnit(a, unit, HTMLStandardMode)) {
1551 // Add the value to the current transform operation.
1552 transformValue->append(createPrimitiveNumericValue(a));
1557 if (a->unit != CSSParserValue::Operator || a->iValue != ',')
1564 return transformValue.release();
1567 void BisonCSSParser::ensureLineEndings()
1570 m_lineEndings = lineEndings(*m_source);
1573 CSSParserSelector* BisonCSSParser::createFloatingSelectorWithTagName(const QualifiedName& tagQName)
1575 CSSParserSelector* selector = new CSSParserSelector(tagQName);
1576 m_floatingSelectors.append(selector);
1580 CSSParserSelector* BisonCSSParser::createFloatingSelector()
1582 CSSParserSelector* selector = new CSSParserSelector;
1583 m_floatingSelectors.append(selector);
1587 PassOwnPtr<CSSParserSelector> BisonCSSParser::sinkFloatingSelector(CSSParserSelector* selector)
1590 size_t index = m_floatingSelectors.reverseFind(selector);
1591 ASSERT(index != kNotFound);
1592 m_floatingSelectors.remove(index);
1594 return adoptPtr(selector);
1597 Vector<OwnPtr<CSSParserSelector> >* BisonCSSParser::createFloatingSelectorVector()
1599 Vector<OwnPtr<CSSParserSelector> >* selectorVector = new Vector<OwnPtr<CSSParserSelector> >;
1600 m_floatingSelectorVectors.append(selectorVector);
1601 return selectorVector;
1604 PassOwnPtr<Vector<OwnPtr<CSSParserSelector> > > BisonCSSParser::sinkFloatingSelectorVector(Vector<OwnPtr<CSSParserSelector> >* selectorVector)
1606 if (selectorVector) {
1607 size_t index = m_floatingSelectorVectors.reverseFind(selectorVector);
1608 ASSERT(index != kNotFound);
1609 m_floatingSelectorVectors.remove(index);
1611 return adoptPtr(selectorVector);
1614 CSSParserValueList* BisonCSSParser::createFloatingValueList()
1616 CSSParserValueList* list = new CSSParserValueList;
1617 m_floatingValueLists.append(list);
1621 PassOwnPtr<CSSParserValueList> BisonCSSParser::sinkFloatingValueList(CSSParserValueList* list)
1624 size_t index = m_floatingValueLists.reverseFind(list);
1625 ASSERT(index != kNotFound);
1626 m_floatingValueLists.remove(index);
1628 return adoptPtr(list);
1631 CSSParserFunction* BisonCSSParser::createFloatingFunction()
1633 CSSParserFunction* function = new CSSParserFunction;
1634 m_floatingFunctions.append(function);
1638 CSSParserFunction* BisonCSSParser::createFloatingFunction(const CSSParserString& name, PassOwnPtr<CSSParserValueList> args)
1640 CSSParserFunction* function = createFloatingFunction();
1641 function->name = name;
1642 function->args = args;
1646 PassOwnPtr<CSSParserFunction> BisonCSSParser::sinkFloatingFunction(CSSParserFunction* function)
1649 size_t index = m_floatingFunctions.reverseFind(function);
1650 ASSERT(index != kNotFound);
1651 m_floatingFunctions.remove(index);
1653 return adoptPtr(function);
1656 CSSParserValue& BisonCSSParser::sinkFloatingValue(CSSParserValue& value)
1658 if (value.unit == CSSParserValue::Function) {
1659 size_t index = m_floatingFunctions.reverseFind(value.function);
1660 ASSERT(index != kNotFound);
1661 m_floatingFunctions.remove(index);
1666 MediaQueryExp* BisonCSSParser::createFloatingMediaQueryExp(const AtomicString& mediaFeature, CSSParserValueList* values)
1668 m_floatingMediaQueryExp = MediaQueryExp::createIfValid(mediaFeature, values);
1669 return m_floatingMediaQueryExp.get();
1672 PassOwnPtrWillBeRawPtr<MediaQueryExp> BisonCSSParser::sinkFloatingMediaQueryExp(MediaQueryExp* expression)
1674 ASSERT_UNUSED(expression, expression == m_floatingMediaQueryExp);
1675 return m_floatingMediaQueryExp.release();
1678 WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp> >* BisonCSSParser::createFloatingMediaQueryExpList()
1680 m_floatingMediaQueryExpList = adoptPtrWillBeNoop(new WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp> >);
1681 return m_floatingMediaQueryExpList.get();
1684 PassOwnPtrWillBeRawPtr<WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp> > > BisonCSSParser::sinkFloatingMediaQueryExpList(WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp> >* list)
1686 ASSERT_UNUSED(list, list == m_floatingMediaQueryExpList);
1687 return m_floatingMediaQueryExpList.release();
1690 MediaQuery* BisonCSSParser::createFloatingMediaQuery(MediaQuery::Restrictor restrictor, const AtomicString& mediaType, PassOwnPtrWillBeRawPtr<WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp> > > expressions)
1692 m_floatingMediaQuery = adoptPtrWillBeNoop(new MediaQuery(restrictor, mediaType, expressions));
1693 return m_floatingMediaQuery.get();
1696 MediaQuery* BisonCSSParser::createFloatingMediaQuery(PassOwnPtrWillBeRawPtr<WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp> > > expressions)
1698 return createFloatingMediaQuery(MediaQuery::None, AtomicString("all", AtomicString::ConstructFromLiteral), expressions);
1701 MediaQuery* BisonCSSParser::createFloatingNotAllQuery()
1703 return createFloatingMediaQuery(MediaQuery::Not, AtomicString("all", AtomicString::ConstructFromLiteral), sinkFloatingMediaQueryExpList(createFloatingMediaQueryExpList()));
1706 PassOwnPtrWillBeRawPtr<MediaQuery> BisonCSSParser::sinkFloatingMediaQuery(MediaQuery* query)
1708 ASSERT_UNUSED(query, query == m_floatingMediaQuery);
1709 return m_floatingMediaQuery.release();
1712 WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> >* BisonCSSParser::createFloatingKeyframeVector()
1714 m_floatingKeyframeVector = adoptPtrWillBeNoop(new WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> >());
1715 return m_floatingKeyframeVector.get();
1718 PassOwnPtrWillBeRawPtr<WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> > > BisonCSSParser::sinkFloatingKeyframeVector(WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> >* keyframeVector)
1720 ASSERT_UNUSED(keyframeVector, m_floatingKeyframeVector == keyframeVector);
1721 return m_floatingKeyframeVector.release();
1724 MediaQuerySet* BisonCSSParser::createMediaQuerySet()
1726 RefPtrWillBeRawPtr<MediaQuerySet> queries = MediaQuerySet::create();
1727 MediaQuerySet* result = queries.get();
1728 m_parsedMediaQuerySets.append(queries.release());
1732 StyleRuleBase* BisonCSSParser::createImportRule(const CSSParserString& url, MediaQuerySet* media)
1734 if (!media || !m_allowImportRules)
1736 RefPtrWillBeRawPtr<StyleRuleImport> rule = StyleRuleImport::create(url, media);
1737 StyleRuleImport* result = rule.get();
1738 m_parsedRules.append(rule.release());
1742 StyleRuleBase* BisonCSSParser::createMediaRule(MediaQuerySet* media, RuleList* rules)
1744 m_allowImportRules = m_allowNamespaceDeclarations = false;
1745 RefPtrWillBeRawPtr<StyleRuleMedia> rule = nullptr;
1747 rule = StyleRuleMedia::create(media ? media : MediaQuerySet::create().get(), *rules);
1749 RuleList emptyRules;
1750 rule = StyleRuleMedia::create(media ? media : MediaQuerySet::create().get(), emptyRules);
1752 StyleRuleMedia* result = rule.get();
1753 m_parsedRules.append(rule.release());
1757 StyleRuleBase* BisonCSSParser::createSupportsRule(bool conditionIsSupported, RuleList* rules)
1759 m_allowImportRules = m_allowNamespaceDeclarations = false;
1761 RefPtrWillBeRawPtr<CSSRuleSourceData> data = popSupportsRuleData();
1762 RefPtrWillBeRawPtr<StyleRuleSupports> rule = nullptr;
1763 String conditionText;
1764 unsigned conditionOffset = data->ruleHeaderRange.start + 9;
1765 unsigned conditionLength = data->ruleHeaderRange.length() - 9;
1767 if (m_tokenizer.is8BitSource())
1768 conditionText = String(m_tokenizer.m_dataStart8.get() + conditionOffset, conditionLength).stripWhiteSpace();
1770 conditionText = String(m_tokenizer.m_dataStart16.get() + conditionOffset, conditionLength).stripWhiteSpace();
1773 rule = StyleRuleSupports::create(conditionText, conditionIsSupported, *rules);
1775 RuleList emptyRules;
1776 rule = StyleRuleSupports::create(conditionText, conditionIsSupported, emptyRules);
1779 StyleRuleSupports* result = rule.get();
1780 m_parsedRules.append(rule.release());
1785 void BisonCSSParser::markSupportsRuleHeaderStart()
1787 if (!m_supportsRuleDataStack)
1788 m_supportsRuleDataStack = adoptPtrWillBeNoop(new RuleSourceDataList());
1790 RefPtrWillBeRawPtr<CSSRuleSourceData> data = CSSRuleSourceData::create(CSSRuleSourceData::SUPPORTS_RULE);
1791 data->ruleHeaderRange.start = m_tokenizer.tokenStartOffset();
1792 m_supportsRuleDataStack->append(data);
1795 void BisonCSSParser::markSupportsRuleHeaderEnd()
1797 ASSERT(m_supportsRuleDataStack && !m_supportsRuleDataStack->isEmpty());
1799 if (m_tokenizer.is8BitSource())
1800 m_supportsRuleDataStack->last()->ruleHeaderRange.end = m_tokenizer.tokenStart<LChar>() - m_tokenizer.m_dataStart8.get();
1802 m_supportsRuleDataStack->last()->ruleHeaderRange.end = m_tokenizer.tokenStart<UChar>() - m_tokenizer.m_dataStart16.get();
1805 PassRefPtrWillBeRawPtr<CSSRuleSourceData> BisonCSSParser::popSupportsRuleData()
1807 ASSERT(m_supportsRuleDataStack && !m_supportsRuleDataStack->isEmpty());
1808 RefPtrWillBeRawPtr<CSSRuleSourceData> data = m_supportsRuleDataStack->last();
1809 m_supportsRuleDataStack->removeLast();
1810 return data.release();
1813 BisonCSSParser::RuleList* BisonCSSParser::createRuleList()
1815 OwnPtrWillBeRawPtr<RuleList> list = adoptPtrWillBeNoop(new RuleList);
1816 RuleList* listPtr = list.get();
1818 m_parsedRuleLists.append(list.release());
1822 BisonCSSParser::RuleList* BisonCSSParser::appendRule(RuleList* ruleList, StyleRuleBase* rule)
1826 ruleList = createRuleList();
1827 ruleList->append(rule);
1832 template <typename CharacterType>
1833 ALWAYS_INLINE static void makeLower(const CharacterType* input, CharacterType* output, unsigned length)
1835 // FIXME: If we need Unicode lowercasing here, then we probably want the real kind
1836 // that can potentially change the length of the string rather than the character
1837 // by character kind. If we don't need Unicode lowercasing, it would be good to
1838 // simplify this function.
1840 if (charactersAreAllASCII(input, length)) {
1841 // Fast case for all-ASCII.
1842 for (unsigned i = 0; i < length; i++)
1843 output[i] = toASCIILower(input[i]);
1845 for (unsigned i = 0; i < length; i++)
1846 output[i] = Unicode::toLower(input[i]);
1850 void BisonCSSParser::tokenToLowerCase(CSSParserString& token)
1852 // Since it's our internal token, we know that we created it out
1853 // of our writable work buffers. Therefore the const_cast is just
1854 // ugly and not a potential crash.
1855 size_t length = token.length();
1856 if (token.is8Bit()) {
1857 makeLower(token.characters8(), const_cast<LChar*>(token.characters8()), length);
1859 makeLower(token.characters16(), const_cast<UChar*>(token.characters16()), length);
1863 void BisonCSSParser::endInvalidRuleHeader()
1865 if (m_ruleHeaderType == CSSRuleSourceData::UNKNOWN_RULE)
1868 CSSParserLocation location;
1869 location.lineNumber = m_tokenizer.m_lineNumber;
1870 location.offset = m_ruleHeaderStartOffset;
1871 if (m_tokenizer.is8BitSource())
1872 location.token.init(m_tokenizer.m_dataStart8.get() + m_ruleHeaderStartOffset, 0);
1874 location.token.init(m_tokenizer.m_dataStart16.get() + m_ruleHeaderStartOffset, 0);
1876 reportError(location, m_ruleHeaderType == CSSRuleSourceData::STYLE_RULE ? InvalidSelectorCSSError : InvalidRuleCSSError);
1881 void BisonCSSParser::reportError(const CSSParserLocation&, CSSParserError)
1883 // FIXME: error reporting temporatily disabled.
1886 bool BisonCSSParser::isLoggingErrors()
1888 return m_logErrors && !m_ignoreErrors;
1891 void BisonCSSParser::logError(const String& message, const CSSParserLocation& location)
1893 unsigned lineNumberInStyleSheet;
1894 unsigned columnNumber = 0;
1895 if (InspectorInstrumentation::hasFrontends()) {
1896 ensureLineEndings();
1897 TextPosition tokenPosition = TextPosition::fromOffsetAndLineEndings(location.offset, *m_lineEndings);
1898 lineNumberInStyleSheet = tokenPosition.m_line.zeroBasedInt();
1899 columnNumber = (lineNumberInStyleSheet ? 0 : m_startPosition.m_column.zeroBasedInt()) + tokenPosition.m_column.zeroBasedInt();
1901 lineNumberInStyleSheet = location.lineNumber;
1903 FrameConsole& console = m_styleSheet->singleOwnerDocument()->frame()->console();
1904 console.addMessage(CSSMessageSource, WarningMessageLevel, message, m_styleSheet->baseURL().string(), lineNumberInStyleSheet + m_startPosition.m_line.zeroBasedInt() + 1, columnNumber + 1);
1907 StyleRuleKeyframes* BisonCSSParser::createKeyframesRule(const String& name, PassOwnPtrWillBeRawPtr<WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> > > popKeyframes, bool isPrefixed)
1909 OwnPtrWillBeRawPtr<WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> > > keyframes = popKeyframes;
1910 m_allowImportRules = m_allowNamespaceDeclarations = false;
1911 RefPtrWillBeRawPtr<StyleRuleKeyframes> rule = StyleRuleKeyframes::create();
1912 for (size_t i = 0; i < keyframes->size(); ++i)
1913 rule->parserAppendKeyframe(keyframes->at(i));
1914 rule->setName(name);
1915 rule->setVendorPrefixed(isPrefixed);
1916 StyleRuleKeyframes* rulePtr = rule.get();
1917 m_parsedRules.append(rule.release());
1921 StyleRuleBase* BisonCSSParser::createStyleRule(Vector<OwnPtr<CSSParserSelector> >* selectors)
1923 StyleRule* result = 0;
1925 m_allowImportRules = m_allowNamespaceDeclarations = false;
1926 RefPtrWillBeRawPtr<StyleRule> rule = StyleRule::create();
1927 rule->parserAdoptSelectorVector(*selectors);
1928 if (m_hasFontFaceOnlyValues)
1929 deleteFontFaceOnlyValues();
1930 rule->setProperties(createStylePropertySet());
1931 result = rule.get();
1932 m_parsedRules.append(rule.release());
1938 StyleRuleBase* BisonCSSParser::createFontFaceRule()
1940 m_allowImportRules = m_allowNamespaceDeclarations = false;
1941 for (unsigned i = 0; i < m_parsedProperties.size(); ++i) {
1942 CSSProperty& property = m_parsedProperties[i];
1943 if (property.id() == CSSPropertyFontVariant && property.value()->isPrimitiveValue())
1944 property.wrapValueInCommaSeparatedList();
1945 else if (property.id() == CSSPropertyFontFamily && (!property.value()->isValueList() || toCSSValueList(property.value())->length() != 1)) {
1946 // Unlike font-family property, font-family descriptor in @font-face rule
1947 // has to be a value list with exactly one family name. It cannot have a
1948 // have 'initial' value and cannot 'inherit' from parent.
1949 // See http://dev.w3.org/csswg/css3-fonts/#font-family-desc
1954 RefPtrWillBeRawPtr<StyleRuleFontFace> rule = StyleRuleFontFace::create();
1955 rule->setProperties(createStylePropertySet());
1957 StyleRuleFontFace* result = rule.get();
1958 m_parsedRules.append(rule.release());
1960 m_styleSheet->setHasFontFaceRule(true);
1964 void BisonCSSParser::addNamespace(const AtomicString& prefix, const AtomicString& uri)
1966 if (!m_styleSheet || !m_allowNamespaceDeclarations)
1968 m_allowImportRules = false;
1969 m_styleSheet->parserAddNamespace(prefix, uri);
1970 if (prefix.isEmpty() && !uri.isNull())
1971 m_defaultNamespace = uri;
1974 QualifiedName BisonCSSParser::determineNameInNamespace(const AtomicString& prefix, const AtomicString& localName)
1977 return QualifiedName(prefix, localName, m_defaultNamespace);
1978 return QualifiedName(prefix, localName, m_styleSheet->determineNamespace(prefix));
1981 CSSParserSelector* BisonCSSParser::rewriteSpecifiersWithNamespaceIfNeeded(CSSParserSelector* specifiers)
1983 if (m_defaultNamespace != starAtom || specifiers->crossesTreeScopes())
1984 return rewriteSpecifiersWithElementName(nullAtom, starAtom, specifiers, /*tagIsForNamespaceRule*/true);
1988 CSSParserSelector* BisonCSSParser::rewriteSpecifiersWithElementName(const AtomicString& namespacePrefix, const AtomicString& elementName, CSSParserSelector* specifiers, bool tagIsForNamespaceRule)
1990 AtomicString determinedNamespace = namespacePrefix != nullAtom && m_styleSheet ? m_styleSheet->determineNamespace(namespacePrefix) : m_defaultNamespace;
1991 QualifiedName tag(namespacePrefix, elementName, determinedNamespace);
1993 if (specifiers->crossesTreeScopes())
1994 return rewriteSpecifiersWithElementNameForCustomPseudoElement(tag, elementName, specifiers, tagIsForNamespaceRule);
1996 if (specifiers->isContentPseudoElement())
1997 return rewriteSpecifiersWithElementNameForContentPseudoElement(tag, elementName, specifiers, tagIsForNamespaceRule);
1999 // *:host never matches, so we can't discard the * otherwise we can't tell the
2000 // difference between *:host and just :host.
2001 if (tag == anyQName() && !specifiers->hasHostPseudoSelector())
2003 if (specifiers->pseudoType() != CSSSelector::PseudoCue)
2004 specifiers->prependTagSelector(tag, tagIsForNamespaceRule);
2008 CSSParserSelector* BisonCSSParser::rewriteSpecifiersWithElementNameForCustomPseudoElement(const QualifiedName& tag, const AtomicString& elementName, CSSParserSelector* specifiers, bool tagIsForNamespaceRule)
2010 if (m_context.useCounter() && specifiers->pseudoType() == CSSSelector::PseudoUserAgentCustomElement)
2011 m_context.useCounter()->count(UseCounter::CSSPseudoElementUserAgentCustomPseudo);
2013 CSSParserSelector* lastShadowPseudo = specifiers;
2014 CSSParserSelector* history = specifiers;
2015 while (history->tagHistory()) {
2016 history = history->tagHistory();
2017 if (history->crossesTreeScopes() || history->hasShadowPseudo())
2018 lastShadowPseudo = history;
2021 if (lastShadowPseudo->tagHistory()) {
2022 if (tag != anyQName())
2023 lastShadowPseudo->tagHistory()->prependTagSelector(tag, tagIsForNamespaceRule);
2027 // For shadow-ID pseudo-elements to be correctly matched, the ShadowPseudo combinator has to be used.
2028 // We therefore create a new Selector with that combinator here in any case, even if matching any (host) element in any namespace (i.e. '*').
2029 OwnPtr<CSSParserSelector> elementNameSelector = adoptPtr(new CSSParserSelector(tag));
2030 lastShadowPseudo->setTagHistory(elementNameSelector.release());
2031 lastShadowPseudo->setRelation(CSSSelector::ShadowPseudo);
2035 CSSParserSelector* BisonCSSParser::rewriteSpecifiersWithElementNameForContentPseudoElement(const QualifiedName& tag, const AtomicString& elementName, CSSParserSelector* specifiers, bool tagIsForNamespaceRule)
2037 CSSParserSelector* last = specifiers;
2038 CSSParserSelector* history = specifiers;
2039 while (history->tagHistory()) {
2040 history = history->tagHistory();
2041 if (history->isContentPseudoElement() || history->relationIsAffectedByPseudoContent())
2045 if (last->tagHistory()) {
2046 if (tag != anyQName())
2047 last->tagHistory()->prependTagSelector(tag, tagIsForNamespaceRule);
2051 // For shadow-ID pseudo-elements to be correctly matched, the ShadowPseudo combinator has to be used.
2052 // We therefore create a new Selector with that combinator here in any case, even if matching any (host) element in any namespace (i.e. '*').
2053 OwnPtr<CSSParserSelector> elementNameSelector = adoptPtr(new CSSParserSelector(tag));
2054 last->setTagHistory(elementNameSelector.release());
2055 last->setRelation(CSSSelector::SubSelector);
2059 CSSParserSelector* BisonCSSParser::rewriteSpecifiers(CSSParserSelector* specifiers, CSSParserSelector* newSpecifier)
2061 if (newSpecifier->crossesTreeScopes()) {
2062 // Unknown pseudo element always goes at the top of selector chain.
2063 newSpecifier->appendTagHistory(CSSSelector::ShadowPseudo, sinkFloatingSelector(specifiers));
2064 return newSpecifier;
2066 if (newSpecifier->isContentPseudoElement()) {
2067 newSpecifier->appendTagHistory(CSSSelector::SubSelector, sinkFloatingSelector(specifiers));
2068 return newSpecifier;
2070 if (specifiers->crossesTreeScopes()) {
2071 // Specifiers for unknown pseudo element go right behind it in the chain.
2072 specifiers->insertTagHistory(CSSSelector::SubSelector, sinkFloatingSelector(newSpecifier), CSSSelector::ShadowPseudo);
2075 if (specifiers->isContentPseudoElement()) {
2076 specifiers->insertTagHistory(CSSSelector::SubSelector, sinkFloatingSelector(newSpecifier), CSSSelector::SubSelector);
2079 specifiers->appendTagHistory(CSSSelector::SubSelector, sinkFloatingSelector(newSpecifier));
2083 StyleRuleBase* BisonCSSParser::createPageRule(PassOwnPtr<CSSParserSelector> pageSelector)
2085 // FIXME: Margin at-rules are ignored.
2086 m_allowImportRules = m_allowNamespaceDeclarations = false;
2087 StyleRulePage* pageRule = 0;
2089 RefPtrWillBeRawPtr<StyleRulePage> rule = StyleRulePage::create();
2090 Vector<OwnPtr<CSSParserSelector> > selectorVector;
2091 selectorVector.append(pageSelector);
2092 rule->parserAdoptSelectorVector(selectorVector);
2093 rule->setProperties(createStylePropertySet());
2094 pageRule = rule.get();
2095 m_parsedRules.append(rule.release());
2101 StyleRuleBase* BisonCSSParser::createMarginAtRule(CSSSelector::MarginBoxType /* marginBox */)
2103 // FIXME: Implement margin at-rule here, using:
2104 // - marginBox: margin box
2105 // - m_parsedProperties: properties at [m_numParsedPropertiesBeforeMarginBox, m_parsedProperties.size()] are for this at-rule.
2106 // 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.
2108 endDeclarationsForMarginBox();
2109 return 0; // until this method is implemented.
2112 void BisonCSSParser::startDeclarationsForMarginBox()
2114 m_numParsedPropertiesBeforeMarginBox = m_parsedProperties.size();
2117 void BisonCSSParser::endDeclarationsForMarginBox()
2119 rollbackLastProperties(m_parsedProperties.size() - m_numParsedPropertiesBeforeMarginBox);
2120 m_numParsedPropertiesBeforeMarginBox = INVALID_NUM_PARSED_PROPERTIES;
2123 void BisonCSSParser::deleteFontFaceOnlyValues()
2125 ASSERT(m_hasFontFaceOnlyValues);
2126 for (unsigned i = 0; i < m_parsedProperties.size();) {
2127 CSSProperty& property = m_parsedProperties[i];
2128 if (property.id() == CSSPropertyFontVariant && property.value()->isValueList()) {
2129 m_parsedProperties.remove(i);
2136 StyleKeyframe* BisonCSSParser::createKeyframe(CSSParserValueList* keys)
2138 OwnPtr<Vector<double> > keyVector = StyleKeyframe::createKeyList(keys);
2139 if (keyVector->isEmpty())
2142 RefPtrWillBeRawPtr<StyleKeyframe> keyframe = StyleKeyframe::create();
2143 keyframe->setKeys(keyVector.release());
2144 keyframe->setProperties(createStylePropertySet());
2148 StyleKeyframe* keyframePtr = keyframe.get();
2149 m_parsedKeyframes.append(keyframe.release());
2153 void BisonCSSParser::invalidBlockHit()
2155 if (m_styleSheet && !m_hadSyntacticallyValidCSSRule)
2156 m_styleSheet->setHasSyntacticallyValidCSSHeader(false);
2159 void BisonCSSParser::startRule()
2164 ASSERT(m_ruleHasHeader);
2165 m_ruleHasHeader = false;
2168 void BisonCSSParser::endRule(bool valid)
2173 if (m_ruleHasHeader)
2174 m_observer->endRuleBody(m_tokenizer.safeUserStringTokenOffset(), !valid);
2175 m_ruleHasHeader = true;
2178 void BisonCSSParser::startRuleHeader(CSSRuleSourceData::Type ruleType)
2180 resumeErrorLogging();
2181 m_ruleHeaderType = ruleType;
2182 m_ruleHeaderStartOffset = m_tokenizer.safeUserStringTokenOffset();
2183 m_ruleHeaderStartLineNumber = m_tokenizer.m_tokenStartLineNumber;
2185 ASSERT(!m_ruleHasHeader);
2186 m_observer->startRuleHeader(ruleType, m_ruleHeaderStartOffset);
2187 m_ruleHasHeader = true;
2191 void BisonCSSParser::endRuleHeader()
2193 ASSERT(m_ruleHeaderType != CSSRuleSourceData::UNKNOWN_RULE);
2194 m_ruleHeaderType = CSSRuleSourceData::UNKNOWN_RULE;
2196 ASSERT(m_ruleHasHeader);
2197 m_observer->endRuleHeader(m_tokenizer.safeUserStringTokenOffset());
2201 void BisonCSSParser::startSelector()
2204 m_observer->startSelector(m_tokenizer.safeUserStringTokenOffset());
2207 void BisonCSSParser::endSelector()
2210 m_observer->endSelector(m_tokenizer.safeUserStringTokenOffset());
2213 void BisonCSSParser::startRuleBody()
2216 m_observer->startRuleBody(m_tokenizer.safeUserStringTokenOffset());
2219 void BisonCSSParser::startProperty()
2221 resumeErrorLogging();
2223 m_observer->startProperty(m_tokenizer.safeUserStringTokenOffset());
2226 void BisonCSSParser::endProperty(bool isImportantFound, bool isPropertyParsed, CSSParserError errorType)
2228 m_id = CSSPropertyInvalid;
2230 m_observer->endProperty(isImportantFound, isPropertyParsed, m_tokenizer.safeUserStringTokenOffset(), errorType);
2233 void BisonCSSParser::startEndUnknownRule()
2236 m_observer->startEndUnknownRule();
2239 StyleRuleBase* BisonCSSParser::createViewportRule()
2241 // Allow @viewport rules from UA stylesheets even if the feature is disabled.
2242 if (!RuntimeEnabledFeatures::cssViewportEnabled() && !isUASheetBehavior(m_context.mode()))
2245 m_allowImportRules = m_allowNamespaceDeclarations = false;
2247 RefPtrWillBeRawPtr<StyleRuleViewport> rule = StyleRuleViewport::create();
2249 rule->setProperties(createStylePropertySet());
2252 StyleRuleViewport* result = rule.get();
2253 m_parsedRules.append(rule.release());