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 "core/CSSValueKeywords.h"
31 #include "core/StylePropertyShorthand.h"
32 #include "core/css/CSSAspectRatioValue.h"
33 #include "core/css/CSSBasicShapes.h"
34 #include "core/css/CSSBorderImage.h"
35 #include "core/css/CSSCanvasValue.h"
36 #include "core/css/CSSCrossfadeValue.h"
37 #include "core/css/CSSCursorImageValue.h"
38 #include "core/css/CSSFontFaceSrcValue.h"
39 #include "core/css/CSSFontFeatureValue.h"
40 #include "core/css/CSSFunctionValue.h"
41 #include "core/css/CSSGradientValue.h"
42 #include "core/css/CSSGridLineNamesValue.h"
43 #include "core/css/CSSGridTemplateAreasValue.h"
44 #include "core/css/CSSImageSetValue.h"
45 #include "core/css/CSSImageValue.h"
46 #include "core/css/CSSInheritedValue.h"
47 #include "core/css/CSSInitialValue.h"
48 #include "core/css/CSSKeyframeRule.h"
49 #include "core/css/CSSKeyframesRule.h"
50 #include "core/css/CSSLineBoxContainValue.h"
51 #include "core/css/CSSPrimitiveValue.h"
52 #include "core/css/CSSPropertySourceData.h"
53 #include "core/css/CSSReflectValue.h"
54 #include "core/css/CSSSelector.h"
55 #include "core/css/CSSShadowValue.h"
56 #include "core/css/CSSStyleSheet.h"
57 #include "core/css/CSSTimingFunctionValue.h"
58 #include "core/css/CSSTransformValue.h"
59 #include "core/css/CSSUnicodeRangeValue.h"
60 #include "core/css/CSSValueList.h"
61 #include "core/css/CSSValuePool.h"
62 #include "core/css/Counter.h"
63 #include "core/css/HashTools.h"
64 #include "core/css/MediaList.h"
65 #include "core/css/MediaQueryExp.h"
66 #include "core/css/Pair.h"
67 #include "core/css/Rect.h"
68 #include "core/css/StylePropertySet.h"
69 #include "core/css/StyleRule.h"
70 #include "core/css/StyleRuleImport.h"
71 #include "core/css/StyleSheetContents.h"
72 #include "core/css/parser/CSSParserIdioms.h"
73 #include "core/dom/Document.h"
74 #include "core/frame/FrameConsole.h"
75 #include "core/frame/FrameHost.h"
76 #include "core/frame/Settings.h"
77 #include "core/frame/UseCounter.h"
78 #include "core/html/parser/HTMLParserIdioms.h"
79 #include "core/inspector/ConsoleMessage.h"
80 #include "core/inspector/InspectorInstrumentation.h"
81 #include "core/rendering/RenderTheme.h"
82 #include "platform/FloatConversion.h"
83 #include "platform/RuntimeEnabledFeatures.h"
84 #include "wtf/BitArray.h"
85 #include "wtf/HexNumber.h"
86 #include "wtf/text/StringBuffer.h"
87 #include "wtf/text/StringBuilder.h"
88 #include "wtf/text/StringImpl.h"
89 #include "wtf/text/TextEncoding.h"
95 extern int cssyydebug;
98 int cssyyparse(blink::BisonCSSParser*);
104 static const unsigned INVALID_NUM_PARSED_PROPERTIES = UINT_MAX;
106 BisonCSSParser::BisonCSSParser(const CSSParserContext& context)
109 , m_id(CSSPropertyInvalid)
110 , m_styleSheet(nullptr)
111 , m_supportsCondition(false)
112 , m_selectorListForParseSelector(0)
113 , m_numParsedPropertiesBeforeMarginBox(INVALID_NUM_PARSED_PROPERTIES)
114 , m_hadSyntacticallyValidCSSRule(false)
116 , m_ignoreErrors(false)
117 , m_defaultNamespace(starAtom)
120 , m_ruleHeaderType(CSSRuleSourceData::UNKNOWN_RULE)
121 , m_allowImportRules(true)
122 , m_allowNamespaceDeclarations(true)
123 , m_inViewport(false)
131 BisonCSSParser::~BisonCSSParser()
135 deleteAllValues(m_floatingSelectors);
136 deleteAllValues(m_floatingSelectorVectors);
137 deleteAllValues(m_floatingValueLists);
138 deleteAllValues(m_floatingFunctions);
141 void BisonCSSParser::setupParser(const char* prefix, unsigned prefixLength, const String& string, const char* suffix, unsigned suffixLength)
143 m_tokenizer.setupTokenizer(prefix, prefixLength, string, suffix, suffixLength);
144 m_ruleHasHeader = true;
147 void BisonCSSParser::parseSheet(StyleSheetContents* sheet, const String& string, const TextPosition& startPosition, CSSParserObserver* observer, bool logErrors)
149 setStyleSheet(sheet);
150 m_defaultNamespace = starAtom; // Reset the default namespace.
151 TemporaryChange<CSSParserObserver*> scopedObsever(m_observer, observer);
152 m_logErrors = logErrors && sheet->singleOwnerDocument() && !sheet->baseURL().isEmpty() && sheet->singleOwnerDocument()->frameHost();
153 m_ignoreErrors = false;
154 m_tokenizer.m_lineNumber = 0;
155 m_startPosition = startPosition;
157 m_tokenizer.m_internal = false;
158 setupParser("", string, "");
160 sheet->shrinkToFit();
163 m_lineEndings.clear();
164 m_ignoreErrors = false;
166 m_tokenizer.m_internal = true;
169 PassRefPtrWillBeRawPtr<StyleRuleBase> BisonCSSParser::parseRule(StyleSheetContents* sheet, const String& string)
171 setStyleSheet(sheet);
172 m_allowNamespaceDeclarations = false;
173 setupParser("@-internal-rule ", string, "");
175 return m_rule.release();
178 PassRefPtrWillBeRawPtr<StyleKeyframe> BisonCSSParser::parseKeyframeRule(StyleSheetContents* sheet, const String& string)
180 setStyleSheet(sheet);
181 setupParser("@-internal-keyframe-rule ", string, "");
183 return m_keyframe.release();
186 PassOwnPtr<Vector<double> > BisonCSSParser::parseKeyframeKeyList(const String& string)
188 setupParser("@-internal-keyframe-key-list ", string, "");
191 return StyleKeyframe::createKeyList(m_valueList.get());
194 bool BisonCSSParser::parseSupportsCondition(const String& string)
196 m_supportsCondition = false;
197 setupParser("@-internal-supports-condition ", string, "");
199 return m_supportsCondition;
202 static inline bool isColorPropertyID(CSSPropertyID propertyId)
204 switch (propertyId) {
205 case CSSPropertyColor:
206 case CSSPropertyBackgroundColor:
207 case CSSPropertyBorderBottomColor:
208 case CSSPropertyBorderLeftColor:
209 case CSSPropertyBorderRightColor:
210 case CSSPropertyBorderTopColor:
211 case CSSPropertyOutlineColor:
212 case CSSPropertyWebkitBorderAfterColor:
213 case CSSPropertyWebkitBorderBeforeColor:
214 case CSSPropertyWebkitBorderEndColor:
215 case CSSPropertyWebkitBorderStartColor:
216 case CSSPropertyWebkitColumnRuleColor:
217 case CSSPropertyWebkitTextEmphasisColor:
218 case CSSPropertyWebkitTextFillColor:
219 case CSSPropertyWebkitTextStrokeColor:
221 case CSSPropertyTextDecorationColor:
222 return RuntimeEnabledFeatures::css3TextDecorationsEnabled();
228 static bool parseColorValue(MutableStylePropertySet* declaration, CSSPropertyID propertyId, const String& string, bool important, CSSParserMode cssParserMode)
230 ASSERT(!string.isEmpty());
231 bool quirksMode = isQuirksModeBehavior(cssParserMode);
232 if (!isColorPropertyID(propertyId))
234 CSSParserString cssString;
235 cssString.init(string);
236 CSSValueID valueID = cssValueKeywordID(cssString);
237 bool validPrimitive = false;
238 if (valueID == CSSValueWebkitText) {
239 validPrimitive = true;
240 } else if (valueID == CSSValueCurrentcolor) {
241 validPrimitive = true;
242 } else if ((valueID >= CSSValueAqua && valueID <= CSSValueWindowtext) || valueID == CSSValueMenu
243 || (quirksMode && valueID >= CSSValueWebkitFocusRingColor && valueID < CSSValueWebkitText)) {
244 validPrimitive = true;
247 if (validPrimitive) {
248 RefPtrWillBeRawPtr<CSSValue> value = cssValuePool().createIdentifierValue(valueID);
249 declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important));
253 if (!CSSPropertyParser::fastParseColor(color, string, !quirksMode && string[0] != '#'))
255 RefPtrWillBeRawPtr<CSSValue> value = cssValuePool().createColorValue(color);
256 declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important));
260 static inline bool isSimpleLengthPropertyID(CSSPropertyID propertyId, bool& acceptsNegativeNumbers)
262 switch (propertyId) {
263 case CSSPropertyFontSize:
264 case CSSPropertyHeight:
265 case CSSPropertyWidth:
266 case CSSPropertyMinHeight:
267 case CSSPropertyMinWidth:
268 case CSSPropertyPaddingBottom:
269 case CSSPropertyPaddingLeft:
270 case CSSPropertyPaddingRight:
271 case CSSPropertyPaddingTop:
272 case CSSPropertyWebkitLogicalWidth:
273 case CSSPropertyWebkitLogicalHeight:
274 case CSSPropertyWebkitMinLogicalWidth:
275 case CSSPropertyWebkitMinLogicalHeight:
276 case CSSPropertyWebkitPaddingAfter:
277 case CSSPropertyWebkitPaddingBefore:
278 case CSSPropertyWebkitPaddingEnd:
279 case CSSPropertyWebkitPaddingStart:
280 acceptsNegativeNumbers = false;
282 case CSSPropertyShapeMargin:
283 acceptsNegativeNumbers = false;
285 case CSSPropertyBottom:
286 case CSSPropertyLeft:
287 case CSSPropertyMarginBottom:
288 case CSSPropertyMarginLeft:
289 case CSSPropertyMarginRight:
290 case CSSPropertyMarginTop:
291 case CSSPropertyRight:
293 case CSSPropertyWebkitMarginAfter:
294 case CSSPropertyWebkitMarginBefore:
295 case CSSPropertyWebkitMarginEnd:
296 case CSSPropertyWebkitMarginStart:
297 acceptsNegativeNumbers = true;
304 template <typename CharacterType>
305 static inline bool parseSimpleLength(const CharacterType* characters, unsigned length, CSSPrimitiveValue::UnitType& unit, double& number)
307 if (length > 2 && (characters[length - 2] | 0x20) == 'p' && (characters[length - 1] | 0x20) == 'x') {
309 unit = CSSPrimitiveValue::CSS_PX;
310 } else if (length > 1 && characters[length - 1] == '%') {
312 unit = CSSPrimitiveValue::CSS_PERCENTAGE;
315 // We rely on charactersToDouble for validation as well. The function
316 // will set "ok" to "false" if the entire passed-in character range does
317 // not represent a double.
319 number = charactersToDouble(characters, length, &ok);
323 static bool parseSimpleLengthValue(MutableStylePropertySet* declaration, CSSPropertyID propertyId, const String& string, bool important, CSSParserMode cssParserMode)
325 ASSERT(!string.isEmpty());
326 bool acceptsNegativeNumbers = false;
328 // In @viewport, width and height are shorthands, not simple length values.
329 if (isCSSViewportParsingEnabledForMode(cssParserMode) || !isSimpleLengthPropertyID(propertyId, acceptsNegativeNumbers))
332 unsigned length = string.length();
334 CSSPrimitiveValue::UnitType unit = CSSPrimitiveValue::CSS_NUMBER;
336 if (string.is8Bit()) {
337 if (!parseSimpleLength(string.characters8(), length, unit, number))
340 if (!parseSimpleLength(string.characters16(), length, unit, number))
344 if (unit == CSSPrimitiveValue::CSS_NUMBER) {
345 bool quirksMode = isQuirksModeBehavior(cssParserMode);
346 if (number && !quirksMode)
348 unit = CSSPrimitiveValue::CSS_PX;
350 if (number < 0 && !acceptsNegativeNumbers)
353 RefPtrWillBeRawPtr<CSSValue> value = cssValuePool().createValue(number, unit);
354 declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important));
358 bool isValidKeywordPropertyAndValue(CSSPropertyID propertyId, CSSValueID valueID, const CSSParserContext& parserContext)
360 if (valueID == CSSValueInvalid)
363 switch (propertyId) {
364 case CSSPropertyBackgroundRepeatX: // repeat | no-repeat
365 case CSSPropertyBackgroundRepeatY: // repeat | no-repeat
366 return valueID == CSSValueRepeat || valueID == CSSValueNoRepeat;
367 case CSSPropertyBorderCollapse: // collapse | separate
368 return valueID == CSSValueCollapse || valueID == CSSValueSeparate;
369 case CSSPropertyBorderTopStyle: // <border-style>
370 case CSSPropertyBorderRightStyle: // Defined as: none | hidden | dotted | dashed |
371 case CSSPropertyBorderBottomStyle: // solid | double | groove | ridge | inset | outset
372 case CSSPropertyBorderLeftStyle:
373 case CSSPropertyWebkitBorderAfterStyle:
374 case CSSPropertyWebkitBorderBeforeStyle:
375 case CSSPropertyWebkitBorderEndStyle:
376 case CSSPropertyWebkitBorderStartStyle:
377 case CSSPropertyWebkitColumnRuleStyle:
378 return valueID >= CSSValueNone && valueID <= CSSValueDouble;
379 case CSSPropertyBoxSizing:
380 return valueID == CSSValueBorderBox || valueID == CSSValueContentBox;
381 case CSSPropertyCaptionSide: // top | bottom | left | right
382 return valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueTop || valueID == CSSValueBottom;
383 case CSSPropertyClear: // none | left | right | both
384 return valueID == CSSValueNone || valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueBoth;
385 case CSSPropertyDirection: // ltr | rtl
386 return valueID == CSSValueLtr || valueID == CSSValueRtl;
387 case CSSPropertyDisplay:
388 // inline | block | list-item | inline-block | table |
389 // inline-table | table-row-group | table-header-group | table-footer-group | table-row |
390 // table-column-group | table-column | table-cell | table-caption | -webkit-box | -webkit-inline-box | none
391 // flex | inline-flex | -webkit-flex | -webkit-inline-flex | grid | inline-grid
392 return (valueID >= CSSValueInline && valueID <= CSSValueInlineFlex) || valueID == CSSValueWebkitFlex || valueID == CSSValueWebkitInlineFlex || valueID == CSSValueNone
393 || (RuntimeEnabledFeatures::cssGridLayoutEnabled() && (valueID == CSSValueGrid || valueID == CSSValueInlineGrid));
394 case CSSPropertyEmptyCells: // show | hide
395 return valueID == CSSValueShow || valueID == CSSValueHide;
396 case CSSPropertyFloat: // left | right | none | center (for buggy CSS, maps to none)
397 return valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueNone || valueID == CSSValueCenter;
398 case CSSPropertyFontStyle: // normal | italic | oblique
399 return valueID == CSSValueNormal || valueID == CSSValueItalic || valueID == CSSValueOblique;
400 case CSSPropertyFontStretch: // normal | ultra-condensed | extra-condensed | condensed | semi-condensed | semi-expanded | expanded | extra-expanded | ultra-expanded
401 return valueID == CSSValueNormal || valueID == CSSValueUltraCondensed || valueID == CSSValueExtraCondensed || valueID == CSSValueCondensed || valueID == CSSValueSemiCondensed || valueID == CSSValueSemiExpanded || valueID == CSSValueExpanded || valueID == CSSValueExtraExpanded || valueID == CSSValueUltraExpanded;
402 case CSSPropertyImageRendering: // auto | optimizeContrast | pixelated
403 return valueID == CSSValueAuto || valueID == CSSValueWebkitOptimizeContrast || (RuntimeEnabledFeatures::imageRenderingPixelatedEnabled() && valueID == CSSValuePixelated);
404 case CSSPropertyIsolation: // auto | isolate
405 return RuntimeEnabledFeatures::cssCompositingEnabled()
406 && (valueID == CSSValueAuto || valueID == CSSValueIsolate);
407 case CSSPropertyListStylePosition: // inside | outside
408 return valueID == CSSValueInside || valueID == CSSValueOutside;
409 case CSSPropertyListStyleType:
410 // See section CSS_PROP_LIST_STYLE_TYPE of file CSSValueKeywords.in
411 // for the list of supported list-style-types.
412 return (valueID >= CSSValueDisc && valueID <= CSSValueKatakanaIroha) || valueID == CSSValueNone;
413 case CSSPropertyObjectFit:
414 return RuntimeEnabledFeatures::objectFitPositionEnabled()
415 && (valueID == CSSValueFill || valueID == CSSValueContain || valueID == CSSValueCover || valueID == CSSValueNone || valueID == CSSValueScaleDown);
416 case CSSPropertyOutlineStyle: // (<border-style> except hidden) | auto
417 return valueID == CSSValueAuto || valueID == CSSValueNone || (valueID >= CSSValueInset && valueID <= CSSValueDouble);
418 case CSSPropertyOverflowWrap: // normal | break-word
419 case CSSPropertyWordWrap:
420 return valueID == CSSValueNormal || valueID == CSSValueBreakWord;
421 case CSSPropertyOverflowX: // visible | hidden | scroll | auto | overlay
422 return valueID == CSSValueVisible || valueID == CSSValueHidden || valueID == CSSValueScroll || valueID == CSSValueAuto || valueID == CSSValueOverlay;
423 case CSSPropertyOverflowY: // visible | hidden | scroll | auto | overlay | -webkit-paged-x | -webkit-paged-y
424 return valueID == CSSValueVisible || valueID == CSSValueHidden || valueID == CSSValueScroll || valueID == CSSValueAuto || valueID == CSSValueOverlay || valueID == CSSValueWebkitPagedX || valueID == CSSValueWebkitPagedY;
425 case CSSPropertyPageBreakAfter: // auto | always | avoid | left | right
426 case CSSPropertyPageBreakBefore:
427 case CSSPropertyWebkitColumnBreakAfter:
428 case CSSPropertyWebkitColumnBreakBefore:
429 return valueID == CSSValueAuto || valueID == CSSValueAlways || valueID == CSSValueAvoid || valueID == CSSValueLeft || valueID == CSSValueRight;
430 case CSSPropertyPageBreakInside: // avoid | auto
431 case CSSPropertyWebkitColumnBreakInside:
432 return valueID == CSSValueAuto || valueID == CSSValueAvoid;
433 case CSSPropertyPointerEvents:
434 // none | visiblePainted | visibleFill | visibleStroke | visible |
435 // painted | fill | stroke | auto | all | bounding-box
436 return valueID == CSSValueVisible || valueID == CSSValueNone || valueID == CSSValueAll || valueID == CSSValueAuto || (valueID >= CSSValueVisiblepainted && valueID <= CSSValueBoundingBox);
437 case CSSPropertyPosition: // static | relative | absolute | fixed
438 return valueID == CSSValueStatic || valueID == CSSValueRelative || valueID == CSSValueAbsolute || valueID == CSSValueFixed;
439 case CSSPropertyResize: // none | both | horizontal | vertical | auto
440 return valueID == CSSValueNone || valueID == CSSValueBoth || valueID == CSSValueHorizontal || valueID == CSSValueVertical || valueID == CSSValueAuto;
441 case CSSPropertyScrollBehavior: // instant | smooth
442 return RuntimeEnabledFeatures::cssomSmoothScrollEnabled()
443 && (valueID == CSSValueInstant || valueID == CSSValueSmooth);
444 case CSSPropertySpeak: // none | normal | spell-out | digits | literal-punctuation | no-punctuation
445 return valueID == CSSValueNone || valueID == CSSValueNormal || valueID == CSSValueSpellOut || valueID == CSSValueDigits || valueID == CSSValueLiteralPunctuation || valueID == CSSValueNoPunctuation;
446 case CSSPropertyTableLayout: // auto | fixed
447 return valueID == CSSValueAuto || valueID == CSSValueFixed;
448 case CSSPropertyTextAlignLast:
449 // auto | start | end | left | right | center | justify
450 return RuntimeEnabledFeatures::css3TextEnabled()
451 && ((valueID >= CSSValueLeft && valueID <= CSSValueJustify) || valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueAuto);
452 case CSSPropertyTextJustify:
453 // auto | none | inter-word | distribute
454 return RuntimeEnabledFeatures::css3TextEnabled()
455 && (valueID == CSSValueInterWord || valueID == CSSValueDistribute || valueID == CSSValueAuto || valueID == CSSValueNone);
456 case CSSPropertyTextOverflow: // clip | ellipsis
457 return valueID == CSSValueClip || valueID == CSSValueEllipsis;
458 case CSSPropertyTextRendering: // auto | optimizeSpeed | optimizeLegibility | geometricPrecision
459 return valueID == CSSValueAuto || valueID == CSSValueOptimizespeed || valueID == CSSValueOptimizelegibility || valueID == CSSValueGeometricprecision;
460 case CSSPropertyTextTransform: // capitalize | uppercase | lowercase | none
461 return (valueID >= CSSValueCapitalize && valueID <= CSSValueLowercase) || valueID == CSSValueNone;
462 case CSSPropertyTouchActionDelay: // none | script
463 return RuntimeEnabledFeatures::cssTouchActionDelayEnabled()
464 && (valueID == CSSValueScript || valueID == CSSValueNone);
465 case CSSPropertyVisibility: // visible | hidden | collapse
466 return valueID == CSSValueVisible || valueID == CSSValueHidden || valueID == CSSValueCollapse;
467 case CSSPropertyWebkitAppearance:
468 return (valueID >= CSSValueCheckbox && valueID <= CSSValueTextarea) || valueID == CSSValueNone;
469 case CSSPropertyBackfaceVisibility:
470 case CSSPropertyWebkitBackfaceVisibility:
471 return valueID == CSSValueVisible || valueID == CSSValueHidden;
472 case CSSPropertyMixBlendMode:
473 return RuntimeEnabledFeatures::cssCompositingEnabled()
474 && (valueID == CSSValueNormal || valueID == CSSValueMultiply || valueID == CSSValueScreen || valueID == CSSValueOverlay
475 || valueID == CSSValueDarken || valueID == CSSValueLighten || valueID == CSSValueColorDodge || valueID == CSSValueColorBurn
476 || valueID == CSSValueHardLight || valueID == CSSValueSoftLight || valueID == CSSValueDifference || valueID == CSSValueExclusion
477 || valueID == CSSValueHue || valueID == CSSValueSaturation || valueID == CSSValueColor || valueID == CSSValueLuminosity);
478 case CSSPropertyWebkitBorderFit:
479 return valueID == CSSValueBorder || valueID == CSSValueLines;
480 case CSSPropertyWebkitBoxAlign:
481 return valueID == CSSValueStretch || valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueCenter || valueID == CSSValueBaseline;
482 case CSSPropertyWebkitBoxDecorationBreak:
483 return valueID == CSSValueClone || valueID == CSSValueSlice;
484 case CSSPropertyWebkitBoxDirection:
485 return valueID == CSSValueNormal || valueID == CSSValueReverse;
486 case CSSPropertyWebkitBoxLines:
487 return valueID == CSSValueSingle || valueID == CSSValueMultiple;
488 case CSSPropertyWebkitBoxOrient:
489 return valueID == CSSValueHorizontal || valueID == CSSValueVertical || valueID == CSSValueInlineAxis || valueID == CSSValueBlockAxis;
490 case CSSPropertyWebkitBoxPack:
491 return valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueCenter || valueID == CSSValueJustify;
492 case CSSPropertyInternalCallback:
493 // This property is only injected programmatically, not parsed from stylesheets.
495 case CSSPropertyColumnFill:
496 return RuntimeEnabledFeatures::regionBasedColumnsEnabled()
497 && (valueID == CSSValueAuto || valueID == CSSValueBalance);
498 case CSSPropertyAlignContent:
499 // FIXME: Per CSS alignment, this property should accept an optional <overflow-position>. We should share this parsing code with 'justify-self'.
500 return valueID == CSSValueFlexStart || valueID == CSSValueFlexEnd || valueID == CSSValueCenter || valueID == CSSValueSpaceBetween || valueID == CSSValueSpaceAround || valueID == CSSValueStretch;
501 case CSSPropertyAlignItems:
502 // FIXME: Per CSS alignment, this property should accept the same arguments as 'justify-self' so we should share its parsing code.
503 return valueID == CSSValueFlexStart || valueID == CSSValueFlexEnd || valueID == CSSValueCenter || valueID == CSSValueBaseline || valueID == CSSValueStretch;
504 case CSSPropertyAlignSelf:
505 // FIXME: Per CSS alignment, this property should accept the same arguments as 'justify-self' so we should share its parsing code.
506 return valueID == CSSValueAuto || valueID == CSSValueFlexStart || valueID == CSSValueFlexEnd || valueID == CSSValueCenter || valueID == CSSValueBaseline || valueID == CSSValueStretch;
507 case CSSPropertyFlexDirection:
508 return valueID == CSSValueRow || valueID == CSSValueRowReverse || valueID == CSSValueColumn || valueID == CSSValueColumnReverse;
509 case CSSPropertyFlexWrap:
510 return valueID == CSSValueNowrap || valueID == CSSValueWrap || valueID == CSSValueWrapReverse;
511 case CSSPropertyJustifyContent:
512 // FIXME: Per CSS alignment, this property should accept an optional <overflow-position>. We should share this parsing code with 'justify-self'.
513 return valueID == CSSValueFlexStart || valueID == CSSValueFlexEnd || valueID == CSSValueCenter || valueID == CSSValueSpaceBetween || valueID == CSSValueSpaceAround;
514 case CSSPropertyFontKerning:
515 return valueID == CSSValueAuto || valueID == CSSValueNormal || valueID == CSSValueNone;
516 case CSSPropertyWebkitFontSmoothing:
517 return valueID == CSSValueAuto || valueID == CSSValueNone || valueID == CSSValueAntialiased || valueID == CSSValueSubpixelAntialiased;
518 case CSSPropertyWebkitLineBreak: // auto | loose | normal | strict | after-white-space
519 return valueID == CSSValueAuto || valueID == CSSValueLoose || valueID == CSSValueNormal || valueID == CSSValueStrict || valueID == CSSValueAfterWhiteSpace;
520 case CSSPropertyWebkitMarginAfterCollapse:
521 case CSSPropertyWebkitMarginBeforeCollapse:
522 case CSSPropertyWebkitMarginBottomCollapse:
523 case CSSPropertyWebkitMarginTopCollapse:
524 return valueID == CSSValueCollapse || valueID == CSSValueSeparate || valueID == CSSValueDiscard;
525 case CSSPropertyInternalMarqueeDirection:
526 return valueID == CSSValueForwards || valueID == CSSValueBackwards || valueID == CSSValueAhead || valueID == CSSValueReverse || valueID == CSSValueLeft || valueID == CSSValueRight || valueID == CSSValueDown
527 || valueID == CSSValueUp || valueID == CSSValueAuto;
528 case CSSPropertyInternalMarqueeStyle:
529 return valueID == CSSValueNone || valueID == CSSValueSlide || valueID == CSSValueScroll || valueID == CSSValueAlternate;
530 case CSSPropertyWebkitPrintColorAdjust:
531 return valueID == CSSValueExact || valueID == CSSValueEconomy;
532 case CSSPropertyWebkitRtlOrdering:
533 return valueID == CSSValueLogical || valueID == CSSValueVisual;
534 case CSSPropertyWebkitRubyPosition:
535 return valueID == CSSValueBefore || valueID == CSSValueAfter;
536 case CSSPropertyWebkitTextCombine:
537 return valueID == CSSValueNone || valueID == CSSValueHorizontal;
538 case CSSPropertyWebkitTextEmphasisPosition:
539 return valueID == CSSValueOver || valueID == CSSValueUnder;
540 case CSSPropertyWebkitTextSecurity: // disc | circle | square | none
541 return valueID == CSSValueDisc || valueID == CSSValueCircle || valueID == CSSValueSquare || valueID == CSSValueNone;
542 case CSSPropertyTransformStyle:
543 case CSSPropertyWebkitTransformStyle:
544 return valueID == CSSValueFlat || valueID == CSSValuePreserve3d;
545 case CSSPropertyWebkitUserDrag: // auto | none | element
546 return valueID == CSSValueAuto || valueID == CSSValueNone || valueID == CSSValueElement;
547 case CSSPropertyWebkitUserModify: // read-only | read-write
548 return valueID == CSSValueReadOnly || valueID == CSSValueReadWrite || valueID == CSSValueReadWritePlaintextOnly;
549 case CSSPropertyWebkitUserSelect: // auto | none | text | all
550 return valueID == CSSValueAuto || valueID == CSSValueNone || valueID == CSSValueText || valueID == CSSValueAll;
551 case CSSPropertyWebkitWritingMode:
552 return valueID >= CSSValueHorizontalTb && valueID <= CSSValueHorizontalBt;
553 case CSSPropertyWhiteSpace: // normal | pre | nowrap
554 return valueID == CSSValueNormal || valueID == CSSValuePre || valueID == CSSValuePreWrap || valueID == CSSValuePreLine || valueID == CSSValueNowrap;
555 case CSSPropertyWordBreak: // normal | break-all | break-word (this is a custom extension)
556 return valueID == CSSValueNormal || valueID == CSSValueBreakAll || valueID == CSSValueBreakWord;
558 ASSERT_NOT_REACHED();
564 bool isKeywordPropertyID(CSSPropertyID propertyId)
566 switch (propertyId) {
567 case CSSPropertyMixBlendMode:
568 case CSSPropertyIsolation:
569 case CSSPropertyBackgroundRepeatX:
570 case CSSPropertyBackgroundRepeatY:
571 case CSSPropertyBorderBottomStyle:
572 case CSSPropertyBorderCollapse:
573 case CSSPropertyBorderLeftStyle:
574 case CSSPropertyBorderRightStyle:
575 case CSSPropertyBorderTopStyle:
576 case CSSPropertyBoxSizing:
577 case CSSPropertyCaptionSide:
578 case CSSPropertyClear:
579 case CSSPropertyDirection:
580 case CSSPropertyDisplay:
581 case CSSPropertyEmptyCells:
582 case CSSPropertyFloat:
583 case CSSPropertyFontStyle:
584 case CSSPropertyFontStretch:
585 case CSSPropertyImageRendering:
586 case CSSPropertyListStylePosition:
587 case CSSPropertyListStyleType:
588 case CSSPropertyObjectFit:
589 case CSSPropertyOutlineStyle:
590 case CSSPropertyOverflowWrap:
591 case CSSPropertyOverflowX:
592 case CSSPropertyOverflowY:
593 case CSSPropertyPageBreakAfter:
594 case CSSPropertyPageBreakBefore:
595 case CSSPropertyPageBreakInside:
596 case CSSPropertyPointerEvents:
597 case CSSPropertyPosition:
598 case CSSPropertyResize:
599 case CSSPropertyScrollBehavior:
600 case CSSPropertySpeak:
601 case CSSPropertyTableLayout:
602 case CSSPropertyTextAlignLast:
603 case CSSPropertyTextJustify:
604 case CSSPropertyTextOverflow:
605 case CSSPropertyTextRendering:
606 case CSSPropertyTextTransform:
607 case CSSPropertyTouchActionDelay:
608 case CSSPropertyVisibility:
609 case CSSPropertyWebkitAppearance:
610 case CSSPropertyBackfaceVisibility:
611 case CSSPropertyWebkitBackfaceVisibility:
612 case CSSPropertyWebkitBorderAfterStyle:
613 case CSSPropertyWebkitBorderBeforeStyle:
614 case CSSPropertyWebkitBorderEndStyle:
615 case CSSPropertyWebkitBorderFit:
616 case CSSPropertyWebkitBorderStartStyle:
617 case CSSPropertyWebkitBoxAlign:
618 case CSSPropertyWebkitBoxDecorationBreak:
619 case CSSPropertyWebkitBoxDirection:
620 case CSSPropertyWebkitBoxLines:
621 case CSSPropertyWebkitBoxOrient:
622 case CSSPropertyWebkitBoxPack:
623 case CSSPropertyInternalCallback:
624 case CSSPropertyWebkitColumnBreakAfter:
625 case CSSPropertyWebkitColumnBreakBefore:
626 case CSSPropertyWebkitColumnBreakInside:
627 case CSSPropertyColumnFill:
628 case CSSPropertyWebkitColumnRuleStyle:
629 case CSSPropertyAlignContent:
630 case CSSPropertyFlexDirection:
631 case CSSPropertyFlexWrap:
632 case CSSPropertyJustifyContent:
633 case CSSPropertyFontKerning:
634 case CSSPropertyWebkitFontSmoothing:
635 case CSSPropertyWebkitLineBreak:
636 case CSSPropertyWebkitMarginAfterCollapse:
637 case CSSPropertyWebkitMarginBeforeCollapse:
638 case CSSPropertyWebkitMarginBottomCollapse:
639 case CSSPropertyWebkitMarginTopCollapse:
640 case CSSPropertyInternalMarqueeDirection:
641 case CSSPropertyInternalMarqueeStyle:
642 case CSSPropertyWebkitPrintColorAdjust:
643 case CSSPropertyWebkitRtlOrdering:
644 case CSSPropertyWebkitRubyPosition:
645 case CSSPropertyWebkitTextCombine:
646 case CSSPropertyWebkitTextEmphasisPosition:
647 case CSSPropertyWebkitTextSecurity:
648 case CSSPropertyTransformStyle:
649 case CSSPropertyWebkitTransformStyle:
650 case CSSPropertyWebkitUserDrag:
651 case CSSPropertyWebkitUserModify:
652 case CSSPropertyWebkitUserSelect:
653 case CSSPropertyWebkitWritingMode:
654 case CSSPropertyWhiteSpace:
655 case CSSPropertyWordBreak:
656 case CSSPropertyWordWrap:
658 case CSSPropertyAlignItems:
659 case CSSPropertyAlignSelf:
660 return !RuntimeEnabledFeatures::cssGridLayoutEnabled();
666 static bool parseKeywordValue(MutableStylePropertySet* declaration, CSSPropertyID propertyId, const String& string, bool important, const CSSParserContext& parserContext)
668 ASSERT(!string.isEmpty());
670 if (!isKeywordPropertyID(propertyId)) {
671 // All properties accept the values of "initial" and "inherit".
672 String lowerCaseString = string.lower();
673 if (lowerCaseString != "initial" && lowerCaseString != "inherit")
676 // Parse initial/inherit shorthands using the BisonCSSParser.
677 if (shorthandForProperty(propertyId).length())
681 CSSParserString cssString;
682 cssString.init(string);
683 CSSValueID valueID = cssValueKeywordID(cssString);
688 RefPtrWillBeRawPtr<CSSValue> value = nullptr;
689 if (valueID == CSSValueInherit)
690 value = cssValuePool().createInheritedValue();
691 else if (valueID == CSSValueInitial)
692 value = cssValuePool().createExplicitInitialValue();
693 else if (isValidKeywordPropertyAndValue(propertyId, valueID, parserContext))
694 value = cssValuePool().createIdentifierValue(valueID);
698 declaration->addParsedProperty(CSSProperty(propertyId, value.release(), important));
702 template <typename CharType>
703 static bool parseTransformTranslateArguments(CharType*& pos, CharType* end, unsigned expectedCount, CSSTransformValue* transformValue)
705 while (expectedCount) {
706 size_t delimiter = WTF::find(pos, end - pos, expectedCount == 1 ? ')' : ',');
707 if (delimiter == kNotFound)
709 unsigned argumentLength = static_cast<unsigned>(delimiter);
710 CSSPrimitiveValue::UnitType unit = CSSPrimitiveValue::CSS_NUMBER;
712 if (!parseSimpleLength(pos, argumentLength, unit, number))
714 if (unit != CSSPrimitiveValue::CSS_PX && (number || unit != CSSPrimitiveValue::CSS_NUMBER))
716 transformValue->append(cssValuePool().createValue(number, CSSPrimitiveValue::CSS_PX));
717 pos += argumentLength + 1;
723 template <typename CharType>
724 static bool parseTransformNumberArguments(CharType*& pos, CharType* end, unsigned expectedCount, CSSTransformValue* transformValue)
726 while (expectedCount) {
727 size_t delimiter = WTF::find(pos, end - pos, expectedCount == 1 ? ')' : ',');
728 if (delimiter == kNotFound)
730 unsigned argumentLength = static_cast<unsigned>(delimiter);
732 double number = charactersToDouble(pos, argumentLength, &ok);
735 transformValue->append(cssValuePool().createValue(number, CSSPrimitiveValue::CSS_NUMBER));
736 pos += argumentLength + 1;
742 template <typename CharType>
743 static PassRefPtrWillBeRawPtr<CSSTransformValue> parseSimpleTransformValue(CharType*& pos, CharType* end)
745 static const int shortestValidTransformStringLength = 12;
747 if (end - pos < shortestValidTransformStringLength)
750 const bool isTranslate = toASCIILower(pos[0]) == 't'
751 && toASCIILower(pos[1]) == 'r'
752 && toASCIILower(pos[2]) == 'a'
753 && toASCIILower(pos[3]) == 'n'
754 && toASCIILower(pos[4]) == 's'
755 && toASCIILower(pos[5]) == 'l'
756 && toASCIILower(pos[6]) == 'a'
757 && toASCIILower(pos[7]) == 't'
758 && toASCIILower(pos[8]) == 'e';
761 CSSTransformValue::TransformOperationType transformType;
762 unsigned expectedArgumentCount = 1;
763 unsigned argumentStart = 11;
764 CharType c9 = toASCIILower(pos[9]);
765 if (c9 == 'x' && pos[10] == '(') {
766 transformType = CSSTransformValue::TranslateXTransformOperation;
767 } else if (c9 == 'y' && pos[10] == '(') {
768 transformType = CSSTransformValue::TranslateYTransformOperation;
769 } else if (c9 == 'z' && pos[10] == '(') {
770 transformType = CSSTransformValue::TranslateZTransformOperation;
771 } else if (c9 == '(') {
772 transformType = CSSTransformValue::TranslateTransformOperation;
773 expectedArgumentCount = 2;
775 } else if (c9 == '3' && toASCIILower(pos[10]) == 'd' && pos[11] == '(') {
776 transformType = CSSTransformValue::Translate3DTransformOperation;
777 expectedArgumentCount = 3;
782 pos += argumentStart;
783 RefPtrWillBeRawPtr<CSSTransformValue> transformValue = CSSTransformValue::create(transformType);
784 if (!parseTransformTranslateArguments(pos, end, expectedArgumentCount, transformValue.get()))
786 return transformValue.release();
789 const bool isMatrix3d = toASCIILower(pos[0]) == 'm'
790 && toASCIILower(pos[1]) == 'a'
791 && toASCIILower(pos[2]) == 't'
792 && toASCIILower(pos[3]) == 'r'
793 && toASCIILower(pos[4]) == 'i'
794 && toASCIILower(pos[5]) == 'x'
796 && toASCIILower(pos[7]) == 'd'
801 RefPtrWillBeRawPtr<CSSTransformValue> transformValue = CSSTransformValue::create(CSSTransformValue::Matrix3DTransformOperation);
802 if (!parseTransformNumberArguments(pos, end, 16, transformValue.get()))
804 return transformValue.release();
807 const bool isScale3d = toASCIILower(pos[0]) == 's'
808 && toASCIILower(pos[1]) == 'c'
809 && toASCIILower(pos[2]) == 'a'
810 && toASCIILower(pos[3]) == 'l'
811 && toASCIILower(pos[4]) == 'e'
813 && toASCIILower(pos[6]) == 'd'
818 RefPtrWillBeRawPtr<CSSTransformValue> transformValue = CSSTransformValue::create(CSSTransformValue::Scale3DTransformOperation);
819 if (!parseTransformNumberArguments(pos, end, 3, transformValue.get()))
821 return transformValue.release();
827 template <typename CharType>
828 static PassRefPtrWillBeRawPtr<CSSValueList> parseSimpleTransformList(CharType*& pos, CharType* end)
830 RefPtrWillBeRawPtr<CSSValueList> transformList = nullptr;
832 while (pos < end && isCSSSpace(*pos))
834 RefPtrWillBeRawPtr<CSSTransformValue> transformValue = parseSimpleTransformValue(pos, end);
838 transformList = CSSValueList::createSpaceSeparated();
839 transformList->append(transformValue.release());
841 if (isCSSSpace(*pos))
845 return transformList.release();
848 static bool parseSimpleTransform(MutableStylePropertySet* properties, CSSPropertyID propertyID, const String& string, bool important)
850 if (propertyID != CSSPropertyTransform && propertyID != CSSPropertyWebkitTransform)
852 if (string.isEmpty())
854 RefPtrWillBeRawPtr<CSSValueList> transformList = nullptr;
855 if (string.is8Bit()) {
856 const LChar* pos = string.characters8();
857 const LChar* end = pos + string.length();
858 transformList = parseSimpleTransformList(pos, end);
862 const UChar* pos = string.characters16();
863 const UChar* end = pos + string.length();
864 transformList = parseSimpleTransformList(pos, end);
868 properties->addParsedProperty(CSSProperty(propertyID, transformList.release(), important));
872 PassRefPtrWillBeRawPtr<CSSValueList> BisonCSSParser::parseFontFaceValue(const AtomicString& string)
874 if (string.isEmpty())
876 RefPtrWillBeRawPtr<MutableStylePropertySet> dummyStyle = MutableStylePropertySet::create();
877 if (!parseValue(dummyStyle.get(), CSSPropertyFontFamily, string, false, HTMLQuirksMode, 0))
880 RefPtrWillBeRawPtr<CSSValue> fontFamily = dummyStyle->getPropertyCSSValue(CSSPropertyFontFamily);
881 if (!fontFamily->isValueList())
884 return toCSSValueList(dummyStyle->getPropertyCSSValue(CSSPropertyFontFamily).get());
887 PassRefPtrWillBeRawPtr<CSSValue> BisonCSSParser::parseAnimationTimingFunctionValue(const String& string)
889 if (string.isEmpty())
891 RefPtrWillBeRawPtr<MutableStylePropertySet> style = MutableStylePropertySet::create();
892 if (!parseValue(style.get(), CSSPropertyTransitionTimingFunction, string, false, HTMLStandardMode, 0))
895 RefPtrWillBeRawPtr<CSSValue> value = style->getPropertyCSSValue(CSSPropertyTransitionTimingFunction);
896 if (!value || value->isInitialValue() || value->isInheritedValue())
898 CSSValueList* valueList = toCSSValueList(value.get());
899 if (valueList->length() > 1)
901 return valueList->item(0);
904 bool BisonCSSParser::parseValue(MutableStylePropertySet* declaration, CSSPropertyID propertyID, const String& string, bool important, const Document& document)
906 ASSERT(!string.isEmpty());
908 CSSParserContext context(document, UseCounter::getFrom(&document));
910 if (parseSimpleLengthValue(declaration, propertyID, string, important, context.mode()))
912 if (parseColorValue(declaration, propertyID, string, important, context.mode()))
914 if (parseKeywordValue(declaration, propertyID, string, important, context))
917 BisonCSSParser parser(context);
918 return parser.parseValue(declaration, propertyID, string, important, static_cast<StyleSheetContents*>(0));
921 bool BisonCSSParser::parseValue(MutableStylePropertySet* declaration, CSSPropertyID propertyID, const String& string, bool important, CSSParserMode cssParserMode, StyleSheetContents* contextStyleSheet)
923 ASSERT(!string.isEmpty());
924 if (parseSimpleLengthValue(declaration, propertyID, string, important, cssParserMode))
926 if (parseColorValue(declaration, propertyID, string, important, cssParserMode))
929 CSSParserContext context(cssParserMode, 0);
930 if (contextStyleSheet) {
931 context = contextStyleSheet->parserContext();
932 context.setMode(cssParserMode);
935 if (parseKeywordValue(declaration, propertyID, string, important, context))
937 if (parseSimpleTransform(declaration, propertyID, string, important))
940 BisonCSSParser parser(context);
941 return parser.parseValue(declaration, propertyID, string, important, contextStyleSheet);
944 bool BisonCSSParser::parseValue(MutableStylePropertySet* declaration, CSSPropertyID propertyID, const String& string, bool important, StyleSheetContents* contextStyleSheet)
946 // FIXME: Check RuntimeCSSEnabled::isPropertyEnabled or isValueEnabledForProperty.
948 if (m_context.useCounter())
949 m_context.useCounter()->count(m_context, propertyID);
951 setStyleSheet(contextStyleSheet);
953 setupParser("@-internal-value ", string, "");
956 m_important = important;
959 StyleDeclarationScope scope(this, declaration);
964 m_id = CSSPropertyInvalid;
967 if (!m_parsedProperties.isEmpty()) {
969 declaration->addParsedProperties(m_parsedProperties);
976 // The color will only be changed when string contains a valid CSS color, so callers
977 // can set it to a default color and ignore the boolean result.
978 bool BisonCSSParser::parseColor(RGBA32& color, const String& string, bool strict)
980 // First try creating a color specified by name, rgba(), rgb() or "#" syntax.
981 if (CSSPropertyParser::fastParseColor(color, string, strict))
984 BisonCSSParser parser(strictCSSParserContext());
986 // In case the fast-path parser didn't understand the color, try the full parser.
987 if (!parser.parseColor(string))
990 CSSValue* value = parser.m_parsedProperties.first().value();
991 if (!value->isPrimitiveValue())
994 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
995 if (!primitiveValue->isRGBColor())
998 color = primitiveValue->getRGBA32Value();
1002 StyleColor BisonCSSParser::colorFromRGBColorString(const String& colorString)
1004 // FIXME: Rework css parser so it is more SVG aware.
1006 if (parseColor(color, colorString.stripWhiteSpace()))
1007 return StyleColor(color);
1008 // FIXME: This branch catches the string currentColor, but we should error if we have an illegal color value.
1009 return StyleColor::currentColor();
1012 bool BisonCSSParser::parseColor(const String& string)
1014 setupParser("@-internal-decls color:", string, "");
1018 return !m_parsedProperties.isEmpty() && m_parsedProperties.first().id() == CSSPropertyColor;
1021 bool BisonCSSParser::parseSystemColor(RGBA32& color, const String& string)
1023 CSSParserString cssColor;
1024 cssColor.init(string);
1025 CSSValueID id = cssValueKeywordID(cssColor);
1026 if (!CSSPropertyParser::isSystemColor(id))
1029 Color parsedColor = RenderTheme::theme().systemColor(id);
1030 color = parsedColor.rgb();
1034 void BisonCSSParser::parseSelector(const String& string, CSSSelectorList& selectorList)
1036 m_selectorListForParseSelector = &selectorList;
1038 setupParser("@-internal-selector ", string, "");
1042 m_selectorListForParseSelector = 0;
1045 PassRefPtrWillBeRawPtr<ImmutableStylePropertySet> BisonCSSParser::parseInlineStyleDeclaration(const String& string, Element* element)
1047 Document& document = element->document();
1048 CSSParserContext context = CSSParserContext(document.elementSheet().contents()->parserContext(), UseCounter::getFrom(&document));
1049 context.setMode((element->isHTMLElement() && !document.inQuirksMode()) ? HTMLStandardMode : HTMLQuirksMode);
1050 return BisonCSSParser(context).parseDeclaration(string, document.elementSheet().contents());
1053 PassRefPtrWillBeRawPtr<ImmutableStylePropertySet> BisonCSSParser::parseDeclaration(const String& string, StyleSheetContents* contextStyleSheet)
1055 setStyleSheet(contextStyleSheet);
1057 setupParser("@-internal-decls ", string, "");
1061 RefPtrWillBeRawPtr<ImmutableStylePropertySet> style = createStylePropertySet();
1063 return style.release();
1067 bool BisonCSSParser::parseDeclaration(MutableStylePropertySet* declaration, const String& string, CSSParserObserver* observer, StyleSheetContents* contextStyleSheet)
1069 setStyleSheet(contextStyleSheet);
1071 TemporaryChange<CSSParserObserver*> scopedObsever(m_observer, observer);
1073 setupParser("@-internal-decls ", string, "");
1075 m_observer->startRuleHeader(CSSRuleSourceData::STYLE_RULE, 0);
1076 m_observer->endRuleHeader(1);
1077 m_observer->startRuleBody(0);
1081 StyleDeclarationScope scope(this, declaration);
1088 if (!m_parsedProperties.isEmpty()) {
1090 declaration->addParsedProperties(m_parsedProperties);
1095 m_observer->endRuleBody(string.length(), false);
1100 PassRefPtrWillBeRawPtr<MediaQuerySet> BisonCSSParser::parseMediaQueryList(const String& string)
1102 ASSERT(!m_mediaList);
1104 // can't use { because tokenizer state switches from mediaquery to initial state when it sees { token.
1105 // instead insert one " " (which is caught by maybe_space in CSSGrammar.y)
1106 setupParser("@-internal-medialist ", string, "");
1109 ASSERT(m_mediaList);
1110 return m_mediaList.release();
1113 bool BisonCSSParser::parseAttributeMatchType(CSSSelector::AttributeMatchType& matchType, const String& string)
1115 if (!RuntimeEnabledFeatures::cssAttributeCaseSensitivityEnabled() && !isUASheetBehavior(m_context.mode()))
1117 if (string == "i") {
1118 matchType = CSSSelector::CaseInsensitive;
1124 static inline void filterProperties(bool important, const WillBeHeapVector<CSSProperty, 256>& input, WillBeHeapVector<CSSProperty, 256>& output, size_t& unusedEntries, BitArray<numCSSProperties>& seenProperties)
1126 // Add properties in reverse order so that highest priority definitions are reached first. Duplicate definitions can then be ignored when found.
1127 for (int i = input.size() - 1; i >= 0; --i) {
1128 const CSSProperty& property = input[i];
1129 if (property.isImportant() != important)
1131 const unsigned propertyIDIndex = property.id() - firstCSSProperty;
1132 if (seenProperties.get(propertyIDIndex))
1134 seenProperties.set(propertyIDIndex);
1135 output[--unusedEntries] = property;
1139 PassRefPtrWillBeRawPtr<ImmutableStylePropertySet> BisonCSSParser::createStylePropertySet()
1141 BitArray<numCSSProperties> seenProperties;
1142 size_t unusedEntries = m_parsedProperties.size();
1143 WillBeHeapVector<CSSProperty, 256> results(unusedEntries);
1145 // Important properties have higher priority, so add them first. Duplicate definitions can then be ignored when found.
1146 filterProperties(true, m_parsedProperties, results, unusedEntries, seenProperties);
1147 filterProperties(false, m_parsedProperties, results, unusedEntries, seenProperties);
1149 results.remove(0, unusedEntries);
1151 CSSParserMode mode = inViewport() ? CSSViewportRuleMode : m_context.mode();
1153 return ImmutableStylePropertySet::create(results.data(), results.size(), mode);
1156 void BisonCSSParser::rollbackLastProperties(int num)
1159 ASSERT(m_parsedProperties.size() >= static_cast<unsigned>(num));
1160 m_parsedProperties.shrink(m_parsedProperties.size() - num);
1163 void BisonCSSParser::clearProperties()
1165 m_parsedProperties.clear();
1166 m_numParsedPropertiesBeforeMarginBox = INVALID_NUM_PARSED_PROPERTIES;
1169 void BisonCSSParser::setCurrentProperty(CSSPropertyID propId)
1174 bool BisonCSSParser::parseValue(CSSPropertyID propId, bool important)
1176 CSSPropertyParser parser(m_valueList, m_context, m_inViewport, m_important, m_parsedProperties, m_ruleHeaderType);
1177 return parser.parseValue(propId, important);
1181 class TransformOperationInfo {
1183 TransformOperationInfo(const CSSParserString& name)
1184 : m_type(CSSTransformValue::UnknownTransformOperation)
1186 , m_allowSingleArgument(false)
1187 , m_unit(CSSPropertyParser::FUnknown)
1189 const UChar* characters;
1190 unsigned nameLength = name.length();
1192 const unsigned longestNameLength = 12;
1193 UChar characterBuffer[longestNameLength];
1194 if (name.is8Bit()) {
1195 unsigned length = std::min(longestNameLength, nameLength);
1196 const LChar* characters8 = name.characters8();
1197 for (unsigned i = 0; i < length; ++i)
1198 characterBuffer[i] = characters8[i];
1199 characters = characterBuffer;
1201 characters = name.characters16();
1203 SWITCH(characters, nameLength) {
1205 m_unit = CSSPropertyParser::FAngle;
1206 m_type = CSSTransformValue::SkewTransformOperation;
1207 m_allowSingleArgument = true;
1211 m_unit = CSSPropertyParser::FNumber;
1212 m_type = CSSTransformValue::ScaleTransformOperation;
1213 m_allowSingleArgument = true;
1217 m_unit = CSSPropertyParser::FAngle;
1218 m_type = CSSTransformValue::SkewXTransformOperation;
1221 m_unit = CSSPropertyParser::FAngle;
1222 m_type = CSSTransformValue::SkewYTransformOperation;
1225 m_unit = CSSPropertyParser::FNumber;
1226 m_type = CSSTransformValue::MatrixTransformOperation;
1230 m_unit = CSSPropertyParser::FAngle;
1231 m_type = CSSTransformValue::RotateTransformOperation;
1234 m_unit = CSSPropertyParser::FNumber;
1235 m_type = CSSTransformValue::ScaleXTransformOperation;
1238 m_unit = CSSPropertyParser::FNumber;
1239 m_type = CSSTransformValue::ScaleYTransformOperation;
1242 m_unit = CSSPropertyParser::FNumber;
1243 m_type = CSSTransformValue::ScaleZTransformOperation;
1246 m_unit = CSSPropertyParser::FNumber;
1247 m_type = CSSTransformValue::Scale3DTransformOperation;
1251 m_unit = CSSPropertyParser::FAngle;
1252 m_type = CSSTransformValue::RotateXTransformOperation;
1255 m_unit = CSSPropertyParser::FAngle;
1256 m_type = CSSTransformValue::RotateYTransformOperation;
1259 m_unit = CSSPropertyParser::FAngle;
1260 m_type = CSSTransformValue::RotateZTransformOperation;
1263 m_unit = CSSPropertyParser::FNumber;
1264 m_type = CSSTransformValue::Matrix3DTransformOperation;
1268 m_unit = CSSPropertyParser::FNumber;
1269 m_type = CSSTransformValue::Rotate3DTransformOperation;
1272 CASE("translate(") {
1273 m_unit = CSSPropertyParser::FLength | CSSPropertyParser::FPercent;
1274 m_type = CSSTransformValue::TranslateTransformOperation;
1275 m_allowSingleArgument = true;
1278 CASE("translatex(") {
1279 m_unit = CSSPropertyParser::FLength | CSSPropertyParser::FPercent;
1280 m_type = CSSTransformValue::TranslateXTransformOperation;
1282 CASE("translatey(") {
1283 m_unit = CSSPropertyParser::FLength | CSSPropertyParser::FPercent;
1284 m_type = CSSTransformValue::TranslateYTransformOperation;
1286 CASE("translatez(") {
1287 m_unit = CSSPropertyParser::FLength | CSSPropertyParser::FPercent;
1288 m_type = CSSTransformValue::TranslateZTransformOperation;
1290 CASE("perspective(") {
1291 m_unit = CSSPropertyParser::FNumber;
1292 m_type = CSSTransformValue::PerspectiveTransformOperation;
1294 CASE("translate3d(") {
1295 m_unit = CSSPropertyParser::FLength | CSSPropertyParser::FPercent;
1296 m_type = CSSTransformValue::Translate3DTransformOperation;
1302 CSSTransformValue::TransformOperationType type() const { return m_type; }
1303 unsigned argCount() const { return m_argCount; }
1304 CSSPropertyParser::Units unit() const { return m_unit; }
1306 bool unknown() const { return m_type == CSSTransformValue::UnknownTransformOperation; }
1307 bool hasCorrectArgCount(unsigned argCount) { return m_argCount == argCount || (m_allowSingleArgument && argCount == 1); }
1310 CSSTransformValue::TransformOperationType m_type;
1311 unsigned m_argCount;
1312 bool m_allowSingleArgument;
1313 CSSPropertyParser::Units m_unit;
1316 PassRefPtrWillBeRawPtr<CSSValueList> CSSPropertyParser::parseTransform(CSSPropertyID propId)
1321 RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
1322 for (CSSParserValue* value = m_valueList->current(); value; value = m_valueList->next()) {
1323 RefPtrWillBeRawPtr<CSSValue> parsedTransformValue = parseTransformValue(propId, value);
1324 if (!parsedTransformValue)
1327 list->append(parsedTransformValue.release());
1330 return list.release();
1333 PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseTransformValue(CSSPropertyID propId, CSSParserValue *value)
1335 if (value->unit != CSSParserValue::Function || !value->function)
1338 // Every primitive requires at least one argument.
1339 CSSParserValueList* args = value->function->args.get();
1343 // See if the specified primitive is one we understand.
1344 TransformOperationInfo info(value->function->name);
1348 if (!info.hasCorrectArgCount(args->size()))
1351 // The transform is a list of functional primitives that specify transform operations.
1352 // We collect a list of CSSTransformValues, where each value specifies a single operation.
1354 // Create the new CSSTransformValue for this operation and add it to our list.
1355 RefPtrWillBeRawPtr<CSSTransformValue> transformValue = CSSTransformValue::create(info.type());
1358 CSSParserValue* a = args->current();
1359 unsigned argNumber = 0;
1361 CSSPropertyParser::Units unit = info.unit();
1363 if (info.type() == CSSTransformValue::Rotate3DTransformOperation && argNumber == 3) {
1364 // 4th param of rotate3d() is an angle rather than a bare number, validate it as such
1365 if (!validUnit(a, FAngle, HTMLStandardMode))
1367 } else if (info.type() == CSSTransformValue::Translate3DTransformOperation && argNumber == 2) {
1368 // 3rd param of translate3d() cannot be a percentage
1369 if (!validUnit(a, FLength, HTMLStandardMode))
1371 } else if (info.type() == CSSTransformValue::TranslateZTransformOperation && !argNumber) {
1372 // 1st param of translateZ() cannot be a percentage
1373 if (!validUnit(a, FLength, HTMLStandardMode))
1375 } else if (info.type() == CSSTransformValue::PerspectiveTransformOperation && !argNumber) {
1376 // 1st param of perspective() must be a non-negative number (deprecated) or length.
1377 if ((propId == CSSPropertyWebkitTransform && !validUnit(a, FNumber | FLength | FNonNeg, HTMLStandardMode))
1378 || (propId == CSSPropertyTransform && !validUnit(a, FLength | FNonNeg, HTMLStandardMode)))
1380 } else if (!validUnit(a, unit, HTMLStandardMode)) {
1384 // Add the value to the current transform operation.
1385 transformValue->append(createPrimitiveNumericValue(a));
1390 if (a->unit != CSSParserValue::Operator || a->iValue != ',')
1397 return transformValue.release();
1400 void BisonCSSParser::ensureLineEndings()
1403 m_lineEndings = lineEndings(*m_source);
1406 CSSParserSelector* BisonCSSParser::createFloatingSelectorWithTagName(const QualifiedName& tagQName)
1408 CSSParserSelector* selector = new CSSParserSelector(tagQName);
1409 m_floatingSelectors.append(selector);
1413 CSSParserSelector* BisonCSSParser::createFloatingSelector()
1415 CSSParserSelector* selector = new CSSParserSelector;
1416 m_floatingSelectors.append(selector);
1420 PassOwnPtr<CSSParserSelector> BisonCSSParser::sinkFloatingSelector(CSSParserSelector* selector)
1423 size_t index = m_floatingSelectors.reverseFind(selector);
1424 ASSERT(index != kNotFound);
1425 m_floatingSelectors.remove(index);
1427 return adoptPtr(selector);
1430 Vector<OwnPtr<CSSParserSelector> >* BisonCSSParser::createFloatingSelectorVector()
1432 Vector<OwnPtr<CSSParserSelector> >* selectorVector = new Vector<OwnPtr<CSSParserSelector> >;
1433 m_floatingSelectorVectors.append(selectorVector);
1434 return selectorVector;
1437 PassOwnPtr<Vector<OwnPtr<CSSParserSelector> > > BisonCSSParser::sinkFloatingSelectorVector(Vector<OwnPtr<CSSParserSelector> >* selectorVector)
1439 if (selectorVector) {
1440 size_t index = m_floatingSelectorVectors.reverseFind(selectorVector);
1441 ASSERT(index != kNotFound);
1442 m_floatingSelectorVectors.remove(index);
1444 return adoptPtr(selectorVector);
1447 CSSParserValueList* BisonCSSParser::createFloatingValueList()
1449 CSSParserValueList* list = new CSSParserValueList;
1450 m_floatingValueLists.append(list);
1454 PassOwnPtr<CSSParserValueList> BisonCSSParser::sinkFloatingValueList(CSSParserValueList* list)
1457 size_t index = m_floatingValueLists.reverseFind(list);
1458 ASSERT(index != kNotFound);
1459 m_floatingValueLists.remove(index);
1461 return adoptPtr(list);
1464 CSSParserFunction* BisonCSSParser::createFloatingFunction()
1466 CSSParserFunction* function = new CSSParserFunction;
1467 m_floatingFunctions.append(function);
1471 CSSParserFunction* BisonCSSParser::createFloatingFunction(const CSSParserString& name, PassOwnPtr<CSSParserValueList> args)
1473 CSSParserFunction* function = createFloatingFunction();
1474 function->name = name;
1475 function->args = args;
1479 PassOwnPtr<CSSParserFunction> BisonCSSParser::sinkFloatingFunction(CSSParserFunction* function)
1482 size_t index = m_floatingFunctions.reverseFind(function);
1483 ASSERT(index != kNotFound);
1484 m_floatingFunctions.remove(index);
1486 return adoptPtr(function);
1489 CSSParserValue& BisonCSSParser::sinkFloatingValue(CSSParserValue& value)
1491 if (value.unit == CSSParserValue::Function) {
1492 size_t index = m_floatingFunctions.reverseFind(value.function);
1493 ASSERT(index != kNotFound);
1494 m_floatingFunctions.remove(index);
1499 MediaQueryExp* BisonCSSParser::createFloatingMediaQueryExp(const AtomicString& mediaFeature, CSSParserValueList* values)
1501 m_floatingMediaQueryExp = MediaQueryExp::createIfValid(mediaFeature, values);
1502 return m_floatingMediaQueryExp.get();
1505 PassOwnPtrWillBeRawPtr<MediaQueryExp> BisonCSSParser::sinkFloatingMediaQueryExp(MediaQueryExp* expression)
1507 ASSERT_UNUSED(expression, expression == m_floatingMediaQueryExp);
1508 return m_floatingMediaQueryExp.release();
1511 WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp> >* BisonCSSParser::createFloatingMediaQueryExpList()
1513 m_floatingMediaQueryExpList = adoptPtrWillBeNoop(new WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp> >);
1514 return m_floatingMediaQueryExpList.get();
1517 PassOwnPtrWillBeRawPtr<WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp> > > BisonCSSParser::sinkFloatingMediaQueryExpList(WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp> >* list)
1519 ASSERT_UNUSED(list, list == m_floatingMediaQueryExpList);
1520 return m_floatingMediaQueryExpList.release();
1523 MediaQuery* BisonCSSParser::createFloatingMediaQuery(MediaQuery::Restrictor restrictor, const AtomicString& mediaType, PassOwnPtrWillBeRawPtr<WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp> > > expressions)
1525 m_floatingMediaQuery = adoptPtrWillBeNoop(new MediaQuery(restrictor, mediaType, expressions));
1526 return m_floatingMediaQuery.get();
1529 MediaQuery* BisonCSSParser::createFloatingMediaQuery(PassOwnPtrWillBeRawPtr<WillBeHeapVector<OwnPtrWillBeMember<MediaQueryExp> > > expressions)
1531 return createFloatingMediaQuery(MediaQuery::None, AtomicString("all", AtomicString::ConstructFromLiteral), expressions);
1534 MediaQuery* BisonCSSParser::createFloatingNotAllQuery()
1536 return createFloatingMediaQuery(MediaQuery::Not, AtomicString("all", AtomicString::ConstructFromLiteral), sinkFloatingMediaQueryExpList(createFloatingMediaQueryExpList()));
1539 PassOwnPtrWillBeRawPtr<MediaQuery> BisonCSSParser::sinkFloatingMediaQuery(MediaQuery* query)
1541 ASSERT_UNUSED(query, query == m_floatingMediaQuery);
1542 return m_floatingMediaQuery.release();
1545 WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> >* BisonCSSParser::createFloatingKeyframeVector()
1547 m_floatingKeyframeVector = adoptPtrWillBeNoop(new WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> >());
1548 return m_floatingKeyframeVector.get();
1551 PassOwnPtrWillBeRawPtr<WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> > > BisonCSSParser::sinkFloatingKeyframeVector(WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> >* keyframeVector)
1553 ASSERT_UNUSED(keyframeVector, m_floatingKeyframeVector == keyframeVector);
1554 return m_floatingKeyframeVector.release();
1557 MediaQuerySet* BisonCSSParser::createMediaQuerySet()
1559 RefPtrWillBeRawPtr<MediaQuerySet> queries = MediaQuerySet::create();
1560 MediaQuerySet* result = queries.get();
1561 m_parsedMediaQuerySets.append(queries.release());
1565 StyleRuleBase* BisonCSSParser::createImportRule(const CSSParserString& url, MediaQuerySet* media)
1567 if (!media || !m_allowImportRules)
1569 RefPtrWillBeRawPtr<StyleRuleImport> rule = StyleRuleImport::create(url, media);
1570 StyleRuleImport* result = rule.get();
1571 m_parsedRules.append(rule.release());
1575 StyleRuleBase* BisonCSSParser::createMediaRule(MediaQuerySet* media, RuleList* rules)
1577 m_allowImportRules = m_allowNamespaceDeclarations = false;
1578 RefPtrWillBeRawPtr<StyleRuleMedia> rule = nullptr;
1580 rule = StyleRuleMedia::create(media ? media : MediaQuerySet::create().get(), *rules);
1582 RuleList emptyRules;
1583 rule = StyleRuleMedia::create(media ? media : MediaQuerySet::create().get(), emptyRules);
1585 StyleRuleMedia* result = rule.get();
1586 m_parsedRules.append(rule.release());
1590 StyleRuleBase* BisonCSSParser::createSupportsRule(bool conditionIsSupported, RuleList* rules)
1592 m_allowImportRules = m_allowNamespaceDeclarations = false;
1594 RefPtrWillBeRawPtr<CSSRuleSourceData> data = popSupportsRuleData();
1595 RefPtrWillBeRawPtr<StyleRuleSupports> rule = nullptr;
1596 String conditionText;
1597 unsigned conditionOffset = data->ruleHeaderRange.start + 9;
1598 unsigned conditionLength = data->ruleHeaderRange.length() - 9;
1600 if (m_tokenizer.is8BitSource())
1601 conditionText = String(m_tokenizer.m_dataStart8.get() + conditionOffset, conditionLength).stripWhiteSpace();
1603 conditionText = String(m_tokenizer.m_dataStart16.get() + conditionOffset, conditionLength).stripWhiteSpace();
1606 rule = StyleRuleSupports::create(conditionText, conditionIsSupported, *rules);
1608 RuleList emptyRules;
1609 rule = StyleRuleSupports::create(conditionText, conditionIsSupported, emptyRules);
1612 StyleRuleSupports* result = rule.get();
1613 m_parsedRules.append(rule.release());
1618 void BisonCSSParser::markSupportsRuleHeaderStart()
1620 if (!m_supportsRuleDataStack)
1621 m_supportsRuleDataStack = adoptPtrWillBeNoop(new RuleSourceDataList());
1623 RefPtrWillBeRawPtr<CSSRuleSourceData> data = CSSRuleSourceData::create(CSSRuleSourceData::SUPPORTS_RULE);
1624 data->ruleHeaderRange.start = m_tokenizer.tokenStartOffset();
1625 m_supportsRuleDataStack->append(data);
1628 void BisonCSSParser::markSupportsRuleHeaderEnd()
1630 ASSERT(m_supportsRuleDataStack && !m_supportsRuleDataStack->isEmpty());
1632 if (m_tokenizer.is8BitSource())
1633 m_supportsRuleDataStack->last()->ruleHeaderRange.end = m_tokenizer.tokenStart<LChar>() - m_tokenizer.m_dataStart8.get();
1635 m_supportsRuleDataStack->last()->ruleHeaderRange.end = m_tokenizer.tokenStart<UChar>() - m_tokenizer.m_dataStart16.get();
1638 PassRefPtrWillBeRawPtr<CSSRuleSourceData> BisonCSSParser::popSupportsRuleData()
1640 ASSERT(m_supportsRuleDataStack && !m_supportsRuleDataStack->isEmpty());
1641 RefPtrWillBeRawPtr<CSSRuleSourceData> data = m_supportsRuleDataStack->last();
1642 m_supportsRuleDataStack->removeLast();
1643 return data.release();
1646 BisonCSSParser::RuleList* BisonCSSParser::createRuleList()
1648 OwnPtrWillBeRawPtr<RuleList> list = adoptPtrWillBeNoop(new RuleList);
1649 RuleList* listPtr = list.get();
1651 m_parsedRuleLists.append(list.release());
1655 BisonCSSParser::RuleList* BisonCSSParser::appendRule(RuleList* ruleList, StyleRuleBase* rule)
1659 ruleList = createRuleList();
1660 ruleList->append(rule);
1665 template <typename CharacterType>
1666 ALWAYS_INLINE static void makeLower(const CharacterType* input, CharacterType* output, unsigned length)
1668 // FIXME: If we need Unicode lowercasing here, then we probably want the real kind
1669 // that can potentially change the length of the string rather than the character
1670 // by character kind. If we don't need Unicode lowercasing, it would be good to
1671 // simplify this function.
1673 if (charactersAreAllASCII(input, length)) {
1674 // Fast case for all-ASCII.
1675 for (unsigned i = 0; i < length; i++)
1676 output[i] = toASCIILower(input[i]);
1678 for (unsigned i = 0; i < length; i++)
1679 output[i] = Unicode::toLower(input[i]);
1683 void BisonCSSParser::tokenToLowerCase(CSSParserString& token)
1685 // Since it's our internal token, we know that we created it out
1686 // of our writable work buffers. Therefore the const_cast is just
1687 // ugly and not a potential crash.
1688 size_t length = token.length();
1689 if (token.is8Bit()) {
1690 makeLower(token.characters8(), const_cast<LChar*>(token.characters8()), length);
1692 makeLower(token.characters16(), const_cast<UChar*>(token.characters16()), length);
1696 void BisonCSSParser::endInvalidRuleHeader()
1698 if (m_ruleHeaderType == CSSRuleSourceData::UNKNOWN_RULE)
1701 CSSParserLocation location;
1702 location.lineNumber = m_tokenizer.m_lineNumber;
1703 location.offset = m_ruleHeaderStartOffset;
1704 if (m_tokenizer.is8BitSource())
1705 location.token.init(m_tokenizer.m_dataStart8.get() + m_ruleHeaderStartOffset, 0);
1707 location.token.init(m_tokenizer.m_dataStart16.get() + m_ruleHeaderStartOffset, 0);
1709 reportError(location, m_ruleHeaderType == CSSRuleSourceData::STYLE_RULE ? InvalidSelectorCSSError : InvalidRuleCSSError);
1714 void BisonCSSParser::reportError(const CSSParserLocation&, CSSParserError)
1716 // FIXME: error reporting temporatily disabled.
1719 bool BisonCSSParser::isLoggingErrors()
1721 return m_logErrors && !m_ignoreErrors;
1724 void BisonCSSParser::logError(const String& message, const CSSParserLocation& location)
1726 unsigned lineNumberInStyleSheet;
1727 unsigned columnNumber = 0;
1728 if (InspectorInstrumentation::hasFrontends()) {
1729 ensureLineEndings();
1730 TextPosition tokenPosition = TextPosition::fromOffsetAndLineEndings(location.offset, *m_lineEndings);
1731 lineNumberInStyleSheet = tokenPosition.m_line.zeroBasedInt();
1732 columnNumber = (lineNumberInStyleSheet ? 0 : m_startPosition.m_column.zeroBasedInt()) + tokenPosition.m_column.zeroBasedInt();
1734 lineNumberInStyleSheet = location.lineNumber;
1736 FrameConsole& console = m_styleSheet->singleOwnerDocument()->frame()->console();
1737 console.addMessage(ConsoleMessage::create(CSSMessageSource, WarningMessageLevel, message, m_styleSheet->baseURL().string(), lineNumberInStyleSheet + m_startPosition.m_line.zeroBasedInt() + 1, columnNumber + 1));
1740 StyleRuleKeyframes* BisonCSSParser::createKeyframesRule(const String& name, PassOwnPtrWillBeRawPtr<WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> > > popKeyframes, bool isPrefixed)
1742 OwnPtrWillBeRawPtr<WillBeHeapVector<RefPtrWillBeMember<StyleKeyframe> > > keyframes = popKeyframes;
1743 m_allowImportRules = m_allowNamespaceDeclarations = false;
1744 RefPtrWillBeRawPtr<StyleRuleKeyframes> rule = StyleRuleKeyframes::create();
1745 for (size_t i = 0; i < keyframes->size(); ++i)
1746 rule->parserAppendKeyframe(keyframes->at(i));
1747 rule->setName(name);
1748 rule->setVendorPrefixed(isPrefixed);
1749 StyleRuleKeyframes* rulePtr = rule.get();
1750 m_parsedRules.append(rule.release());
1754 static void recordSelectorStats(const CSSParserContext& context, const CSSSelectorList& selectorList)
1756 if (!context.useCounter())
1759 for (const CSSSelector* selector = selectorList.first(); selector; selector = CSSSelectorList::next(*selector)) {
1760 for (const CSSSelector* current = selector; current ; current = current->tagHistory()) {
1761 UseCounter::Feature feature = UseCounter::NumberOfFeatures;
1762 switch (current->pseudoType()) {
1763 case CSSSelector::PseudoUnresolved:
1764 feature = UseCounter::CSSSelectorPseudoUnresolved;
1766 case CSSSelector::PseudoShadow:
1767 feature = UseCounter::CSSSelectorPseudoShadow;
1769 case CSSSelector::PseudoContent:
1770 feature = UseCounter::CSSSelectorPseudoContent;
1772 case CSSSelector::PseudoHost:
1773 feature = UseCounter::CSSSelectorPseudoHost;
1775 case CSSSelector::PseudoHostContext:
1776 feature = UseCounter::CSSSelectorPseudoHostContext;
1781 if (feature != UseCounter::NumberOfFeatures)
1782 context.useCounter()->count(feature);
1783 if (current->relation() == CSSSelector::ShadowDeep)
1784 context.useCounter()->count(UseCounter::CSSDeepCombinator);
1785 if (current->selectorList())
1786 recordSelectorStats(context, *current->selectorList());
1791 StyleRuleBase* BisonCSSParser::createStyleRule(Vector<OwnPtr<CSSParserSelector> >* selectors)
1793 StyleRule* result = 0;
1795 m_allowImportRules = m_allowNamespaceDeclarations = false;
1796 RefPtrWillBeRawPtr<StyleRule> rule = StyleRule::create();
1797 rule->parserAdoptSelectorVector(*selectors);
1798 rule->setProperties(createStylePropertySet());
1799 result = rule.get();
1800 m_parsedRules.append(rule.release());
1801 recordSelectorStats(m_context, result->selectorList());
1807 StyleRuleBase* BisonCSSParser::createFontFaceRule()
1809 m_allowImportRules = m_allowNamespaceDeclarations = false;
1810 for (unsigned i = 0; i < m_parsedProperties.size(); ++i) {
1811 CSSProperty& property = m_parsedProperties[i];
1812 if (property.id() == CSSPropertyFontVariant && property.value()->isPrimitiveValue())
1813 property.wrapValueInCommaSeparatedList();
1814 else if (property.id() == CSSPropertyFontFamily && (!property.value()->isValueList() || toCSSValueList(property.value())->length() != 1)) {
1815 // Unlike font-family property, font-family descriptor in @font-face rule
1816 // has to be a value list with exactly one family name. It cannot have a
1817 // have 'initial' value and cannot 'inherit' from parent.
1818 // See http://dev.w3.org/csswg/css3-fonts/#font-family-desc
1823 RefPtrWillBeRawPtr<StyleRuleFontFace> rule = StyleRuleFontFace::create();
1824 rule->setProperties(createStylePropertySet());
1826 StyleRuleFontFace* result = rule.get();
1827 m_parsedRules.append(rule.release());
1829 m_styleSheet->setHasFontFaceRule(true);
1833 void BisonCSSParser::addNamespace(const AtomicString& prefix, const AtomicString& uri)
1835 if (!m_styleSheet || !m_allowNamespaceDeclarations)
1837 m_allowImportRules = false;
1838 m_styleSheet->parserAddNamespace(prefix, uri);
1839 if (prefix.isEmpty() && !uri.isNull())
1840 m_defaultNamespace = uri;
1843 QualifiedName BisonCSSParser::determineNameInNamespace(const AtomicString& prefix, const AtomicString& localName)
1846 return QualifiedName(prefix, localName, m_defaultNamespace);
1847 return QualifiedName(prefix, localName, m_styleSheet->determineNamespace(prefix));
1850 CSSParserSelector* BisonCSSParser::rewriteSpecifiersWithNamespaceIfNeeded(CSSParserSelector* specifiers)
1852 if (m_defaultNamespace != starAtom || specifiers->crossesTreeScopes())
1853 return rewriteSpecifiersWithElementName(nullAtom, starAtom, specifiers, /*tagIsForNamespaceRule*/true);
1857 CSSParserSelector* BisonCSSParser::rewriteSpecifiersWithElementName(const AtomicString& namespacePrefix, const AtomicString& elementName, CSSParserSelector* specifiers, bool tagIsForNamespaceRule)
1859 AtomicString determinedNamespace = namespacePrefix != nullAtom && m_styleSheet ? m_styleSheet->determineNamespace(namespacePrefix) : m_defaultNamespace;
1860 QualifiedName tag(namespacePrefix, elementName, determinedNamespace);
1862 if (specifiers->crossesTreeScopes())
1863 return rewriteSpecifiersWithElementNameForCustomPseudoElement(tag, elementName, specifiers, tagIsForNamespaceRule);
1865 if (specifiers->isContentPseudoElement())
1866 return rewriteSpecifiersWithElementNameForContentPseudoElement(tag, elementName, specifiers, tagIsForNamespaceRule);
1868 // *:host never matches, so we can't discard the * otherwise we can't tell the
1869 // difference between *:host and just :host.
1870 if (tag == anyQName() && !specifiers->hasHostPseudoSelector())
1872 if (specifiers->pseudoType() != CSSSelector::PseudoCue)
1873 specifiers->prependTagSelector(tag, tagIsForNamespaceRule);
1877 CSSParserSelector* BisonCSSParser::rewriteSpecifiersWithElementNameForCustomPseudoElement(const QualifiedName& tag, const AtomicString& elementName, CSSParserSelector* specifiers, bool tagIsForNamespaceRule)
1879 if (m_context.useCounter() && specifiers->pseudoType() == CSSSelector::PseudoUserAgentCustomElement)
1880 m_context.useCounter()->count(UseCounter::CSSPseudoElementUserAgentCustomPseudo);
1882 CSSParserSelector* lastShadowPseudo = specifiers;
1883 CSSParserSelector* history = specifiers;
1884 while (history->tagHistory()) {
1885 history = history->tagHistory();
1886 if (history->crossesTreeScopes() || history->hasShadowPseudo())
1887 lastShadowPseudo = history;
1890 if (lastShadowPseudo->tagHistory()) {
1891 if (tag != anyQName())
1892 lastShadowPseudo->tagHistory()->prependTagSelector(tag, tagIsForNamespaceRule);
1896 // For shadow-ID pseudo-elements to be correctly matched, the ShadowPseudo combinator has to be used.
1897 // We therefore create a new Selector with that combinator here in any case, even if matching any (host) element in any namespace (i.e. '*').
1898 OwnPtr<CSSParserSelector> elementNameSelector = adoptPtr(new CSSParserSelector(tag));
1899 lastShadowPseudo->setTagHistory(elementNameSelector.release());
1900 lastShadowPseudo->setRelation(CSSSelector::ShadowPseudo);
1904 CSSParserSelector* BisonCSSParser::rewriteSpecifiersWithElementNameForContentPseudoElement(const QualifiedName& tag, const AtomicString& elementName, CSSParserSelector* specifiers, bool tagIsForNamespaceRule)
1906 CSSParserSelector* last = specifiers;
1907 CSSParserSelector* history = specifiers;
1908 while (history->tagHistory()) {
1909 history = history->tagHistory();
1910 if (history->isContentPseudoElement() || history->relationIsAffectedByPseudoContent())
1914 if (last->tagHistory()) {
1915 if (tag != anyQName())
1916 last->tagHistory()->prependTagSelector(tag, tagIsForNamespaceRule);
1920 // For shadow-ID pseudo-elements to be correctly matched, the ShadowPseudo combinator has to be used.
1921 // We therefore create a new Selector with that combinator here in any case, even if matching any (host) element in any namespace (i.e. '*').
1922 OwnPtr<CSSParserSelector> elementNameSelector = adoptPtr(new CSSParserSelector(tag));
1923 last->setTagHistory(elementNameSelector.release());
1924 last->setRelation(CSSSelector::SubSelector);
1928 CSSParserSelector* BisonCSSParser::rewriteSpecifiers(CSSParserSelector* specifiers, CSSParserSelector* newSpecifier)
1930 if (newSpecifier->crossesTreeScopes()) {
1931 // Unknown pseudo element always goes at the top of selector chain.
1932 newSpecifier->appendTagHistory(CSSSelector::ShadowPseudo, sinkFloatingSelector(specifiers));
1933 return newSpecifier;
1935 if (newSpecifier->isContentPseudoElement()) {
1936 newSpecifier->appendTagHistory(CSSSelector::SubSelector, sinkFloatingSelector(specifiers));
1937 return newSpecifier;
1939 if (specifiers->crossesTreeScopes()) {
1940 // Specifiers for unknown pseudo element go right behind it in the chain.
1941 specifiers->insertTagHistory(CSSSelector::SubSelector, sinkFloatingSelector(newSpecifier), CSSSelector::ShadowPseudo);
1944 if (specifiers->isContentPseudoElement()) {
1945 specifiers->insertTagHistory(CSSSelector::SubSelector, sinkFloatingSelector(newSpecifier), CSSSelector::SubSelector);
1948 specifiers->appendTagHistory(CSSSelector::SubSelector, sinkFloatingSelector(newSpecifier));
1952 StyleRuleBase* BisonCSSParser::createPageRule(PassOwnPtr<CSSParserSelector> pageSelector)
1954 // FIXME: Margin at-rules are ignored.
1955 m_allowImportRules = m_allowNamespaceDeclarations = false;
1956 StyleRulePage* pageRule = 0;
1958 RefPtrWillBeRawPtr<StyleRulePage> rule = StyleRulePage::create();
1959 Vector<OwnPtr<CSSParserSelector> > selectorVector;
1960 selectorVector.append(pageSelector);
1961 rule->parserAdoptSelectorVector(selectorVector);
1962 rule->setProperties(createStylePropertySet());
1963 pageRule = rule.get();
1964 m_parsedRules.append(rule.release());
1970 StyleRuleBase* BisonCSSParser::createMarginAtRule(CSSSelector::MarginBoxType /* marginBox */)
1972 // FIXME: Implement margin at-rule here, using:
1973 // - marginBox: margin box
1974 // - m_parsedProperties: properties at [m_numParsedPropertiesBeforeMarginBox, m_parsedProperties.size()] are for this at-rule.
1975 // Don't forget to also update the action for page symbol in CSSGrammar.y such that margin at-rule data is cleared if page_selector is invalid.
1977 endDeclarationsForMarginBox();
1978 return 0; // until this method is implemented.
1981 void BisonCSSParser::startDeclarationsForMarginBox()
1983 m_numParsedPropertiesBeforeMarginBox = m_parsedProperties.size();
1986 void BisonCSSParser::endDeclarationsForMarginBox()
1988 rollbackLastProperties(m_parsedProperties.size() - m_numParsedPropertiesBeforeMarginBox);
1989 m_numParsedPropertiesBeforeMarginBox = INVALID_NUM_PARSED_PROPERTIES;
1992 StyleKeyframe* BisonCSSParser::createKeyframe(CSSParserValueList* keys)
1994 OwnPtr<Vector<double> > keyVector = StyleKeyframe::createKeyList(keys);
1995 if (keyVector->isEmpty())
1998 RefPtrWillBeRawPtr<StyleKeyframe> keyframe = StyleKeyframe::create();
1999 keyframe->setKeys(keyVector.release());
2000 keyframe->setProperties(createStylePropertySet());
2004 StyleKeyframe* keyframePtr = keyframe.get();
2005 m_parsedKeyframes.append(keyframe.release());
2009 void BisonCSSParser::invalidBlockHit()
2011 if (m_styleSheet && !m_hadSyntacticallyValidCSSRule)
2012 m_styleSheet->setHasSyntacticallyValidCSSHeader(false);
2015 void BisonCSSParser::startRule()
2020 ASSERT(m_ruleHasHeader);
2021 m_ruleHasHeader = false;
2024 void BisonCSSParser::endRule(bool valid)
2029 if (m_ruleHasHeader)
2030 m_observer->endRuleBody(m_tokenizer.safeUserStringTokenOffset(), !valid);
2031 m_ruleHasHeader = true;
2034 void BisonCSSParser::startRuleHeader(CSSRuleSourceData::Type ruleType)
2036 resumeErrorLogging();
2037 m_ruleHeaderType = ruleType;
2038 m_ruleHeaderStartOffset = m_tokenizer.safeUserStringTokenOffset();
2039 m_ruleHeaderStartLineNumber = m_tokenizer.m_tokenStartLineNumber;
2041 ASSERT(!m_ruleHasHeader);
2042 m_observer->startRuleHeader(ruleType, m_ruleHeaderStartOffset);
2043 m_ruleHasHeader = true;
2047 void BisonCSSParser::endRuleHeader()
2049 ASSERT(m_ruleHeaderType != CSSRuleSourceData::UNKNOWN_RULE);
2050 m_ruleHeaderType = CSSRuleSourceData::UNKNOWN_RULE;
2052 ASSERT(m_ruleHasHeader);
2053 m_observer->endRuleHeader(m_tokenizer.safeUserStringTokenOffset());
2057 void BisonCSSParser::startSelector()
2060 m_observer->startSelector(m_tokenizer.safeUserStringTokenOffset());
2063 void BisonCSSParser::endSelector()
2066 m_observer->endSelector(m_tokenizer.safeUserStringTokenOffset());
2069 void BisonCSSParser::startRuleBody()
2072 m_observer->startRuleBody(m_tokenizer.safeUserStringTokenOffset());
2075 void BisonCSSParser::startProperty()
2077 resumeErrorLogging();
2079 m_observer->startProperty(m_tokenizer.safeUserStringTokenOffset());
2082 void BisonCSSParser::endProperty(bool isImportantFound, bool isPropertyParsed, CSSParserError errorType)
2084 m_id = CSSPropertyInvalid;
2086 m_observer->endProperty(isImportantFound, isPropertyParsed, m_tokenizer.safeUserStringTokenOffset(), errorType);
2089 void BisonCSSParser::startEndUnknownRule()
2092 m_observer->startEndUnknownRule();
2095 StyleRuleBase* BisonCSSParser::createViewportRule()
2097 // Allow @viewport rules from UA stylesheets even if the feature is disabled.
2098 if (!RuntimeEnabledFeatures::cssViewportEnabled() && !isUASheetBehavior(m_context.mode()))
2101 m_allowImportRules = m_allowNamespaceDeclarations = false;
2103 RefPtrWillBeRawPtr<StyleRuleViewport> rule = StyleRuleViewport::create();
2105 rule->setProperties(createStylePropertySet());
2108 StyleRuleViewport* result = rule.get();
2109 m_parsedRules.append(rule.release());