diff options
Diffstat (limited to 'Source/WebCore/css/CSSParser.cpp')
-rw-r--r-- | Source/WebCore/css/CSSParser.cpp | 379 |
1 files changed, 299 insertions, 80 deletions
diff --git a/Source/WebCore/css/CSSParser.cpp b/Source/WebCore/css/CSSParser.cpp index 380765b24..39fb630ed 100644 --- a/Source/WebCore/css/CSSParser.cpp +++ b/Source/WebCore/css/CSSParser.cpp @@ -51,6 +51,9 @@ #include "CSSValueKeywords.h" #include "CSSValueList.h" #include "CSSValuePool.h" +#if ENABLE(CSS_VARIABLES) +#include "CSSVariableValue.h" +#endif #include "CSSWrapShapes.h" #include "Counter.h" #include "Document.h" @@ -235,12 +238,12 @@ CSSParser::CSSParser(const CSSParserContext& context) , m_hasFontFaceOnlyValues(false) , m_hadSyntacticallyValidCSSRule(false) , m_defaultNamespace(starAtom) + , m_parsedTextPrefixLength(0) , m_inStyleRuleOrDeclaration(false) , m_selectorListRange(0, 0) , m_ruleBodyRange(0, 0) , m_propertyRange(UINT_MAX, UINT_MAX) - , m_ruleRangeMap(0) - , m_currentRuleData(0) + , m_ruleSourceDataResult(0) , m_parsingMode(NormalMode) , m_currentCharacter(0) , m_tokenStart(0) @@ -285,15 +288,16 @@ void CSSParserString::lower() void CSSParser::setupParser(const char* prefix, const String& string, const char* suffix) { - int length = string.length() + strlen(prefix) + strlen(suffix) + 1; + m_parsedTextPrefixLength = strlen(prefix); + int length = string.length() + m_parsedTextPrefixLength + strlen(suffix) + 1; m_dataStart = adoptArrayPtr(new UChar[length]); - for (unsigned i = 0; i < strlen(prefix); i++) + for (unsigned i = 0; i < m_parsedTextPrefixLength; i++) m_dataStart[i] = prefix[i]; - memcpy(m_dataStart.get() + strlen(prefix), string.characters(), string.length() * sizeof(UChar)); + memcpy(m_dataStart.get() + m_parsedTextPrefixLength, string.characters(), string.length() * sizeof(UChar)); - unsigned start = strlen(prefix) + string.length(); + unsigned start = m_parsedTextPrefixLength + string.length(); unsigned end = start + strlen(suffix); for (unsigned i = start; i < end; i++) m_dataStart[i] = suffix[i - start]; @@ -304,21 +308,19 @@ void CSSParser::setupParser(const char* prefix, const String& string, const char resetRuleBodyMarks(); } -void CSSParser::parseSheet(StyleSheetContents* sheet, const String& string, int startLineNumber, StyleRuleRangeMap* ruleRangeMap) +void CSSParser::parseSheet(StyleSheetContents* sheet, const String& string, int startLineNumber, RuleSourceDataList* ruleSourceDataResult) { setStyleSheet(sheet); m_defaultNamespace = starAtom; // Reset the default namespace. - m_ruleRangeMap = ruleRangeMap; - if (ruleRangeMap) { - m_currentRuleData = CSSRuleSourceData::create(); - m_currentRuleData->styleSourceData = CSSStyleSourceData::create(); - } + if (ruleSourceDataResult) + m_currentRuleDataStack = adoptPtr(new RuleSourceDataList()); + m_ruleSourceDataResult = ruleSourceDataResult; m_lineNumber = startLineNumber; setupParser("", string, ""); cssyyparse(this); - m_ruleRangeMap = 0; - m_currentRuleData = 0; + m_currentRuleDataStack.clear(); + m_ruleSourceDataResult = 0; m_rule = 0; } @@ -664,10 +666,12 @@ static inline bool isValidKeywordPropertyAndValue(CSSPropertyID propertyId, int if (valueID == CSSValueStretch || valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueCenter || valueID == CSSValueBaseline) return true; break; +#if ENABLE(CSS_BOX_DECORATION_BREAK) case CSSPropertyWebkitBoxDecorationBreak: if (valueID == CSSValueClone || valueID == CSSValueSlice) return true; break; +#endif case CSSPropertyWebkitBoxDirection: if (valueID == CSSValueNormal || valueID == CSSValueReverse) return true; @@ -689,30 +693,30 @@ static inline bool isValidKeywordPropertyAndValue(CSSPropertyID propertyId, int return true; break; #if ENABLE(CSS3_FLEXBOX) + case CSSPropertyWebkitAlignContent: + if (valueID == CSSValueFlexStart || valueID == CSSValueFlexEnd || valueID == CSSValueCenter || valueID == CSSValueSpaceBetween || valueID == CSSValueSpaceAround || valueID == CSSValueStretch) + return true; + break; case CSSPropertyWebkitAlignItems: - if (valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueCenter || valueID == CSSValueBaseline || valueID == CSSValueStretch) + if (valueID == CSSValueFlexStart || valueID == CSSValueFlexEnd || valueID == CSSValueCenter || valueID == CSSValueBaseline || valueID == CSSValueStretch) return true; break; case CSSPropertyWebkitAlignSelf: - if (valueID == CSSValueAuto || valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueCenter || valueID == CSSValueBaseline || valueID == CSSValueStretch) + if (valueID == CSSValueAuto || valueID == CSSValueFlexStart || valueID == CSSValueFlexEnd || valueID == CSSValueCenter || valueID == CSSValueBaseline || valueID == CSSValueStretch) return true; break; case CSSPropertyWebkitFlexDirection: if (valueID == CSSValueRow || valueID == CSSValueRowReverse || valueID == CSSValueColumn || valueID == CSSValueColumnReverse) return true; break; - case CSSPropertyWebkitFlexLinePack: - if (valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueCenter || valueID == CSSValueSpaceBetween || valueID == CSSValueSpaceAround || valueID == CSSValueStretch) - return true; - break; - case CSSPropertyWebkitFlexPack: - if (valueID == CSSValueStart || valueID == CSSValueEnd || valueID == CSSValueCenter || valueID == CSSValueSpaceBetween || valueID == CSSValueSpaceAround) - return true; - break; case CSSPropertyWebkitFlexWrap: if (valueID == CSSValueNone || valueID == CSSValueWrap || valueID == CSSValueWrapReverse) return true; break; + case CSSPropertyWebkitJustifyContent: + if (valueID == CSSValueFlexStart || valueID == CSSValueFlexEnd || valueID == CSSValueCenter || valueID == CSSValueSpaceBetween || valueID == CSSValueSpaceAround) + return true; + break; #endif case CSSPropertyWebkitFontKerning: if (valueID == CSSValueAuto || valueID == CSSValueNormal || valueID == CSSValueNone) @@ -754,10 +758,6 @@ static inline bool isValidKeywordPropertyAndValue(CSSPropertyID propertyId, int if (valueID == CSSValueNone || valueID == CSSValueSlide || valueID == CSSValueScroll || valueID == CSSValueAlternate) return true; break; - case CSSPropertyWebkitMatchNearestMailBlockquoteColor: // normal | match - if (valueID == CSSValueNormal || valueID == CSSValueMatch) - return true; - break; case CSSPropertyWebkitNbspMode: // normal | space if (valueID == CSSValueNormal || valueID == CSSValueSpace) return true; @@ -909,7 +909,9 @@ static inline bool isKeywordPropertyID(CSSPropertyID propertyId) case CSSPropertyWebkitBorderFit: case CSSPropertyWebkitBorderStartStyle: case CSSPropertyWebkitBoxAlign: +#if ENABLE(CSS_BOX_DECORATION_BREAK) case CSSPropertyWebkitBoxDecorationBreak: +#endif case CSSPropertyWebkitBoxDirection: case CSSPropertyWebkitBoxLines: case CSSPropertyWebkitBoxOrient: @@ -920,12 +922,12 @@ static inline bool isKeywordPropertyID(CSSPropertyID propertyId) case CSSPropertyWebkitColumnBreakInside: case CSSPropertyWebkitColumnRuleStyle: #if ENABLE(CSS3_FLEXBOX) + case CSSPropertyWebkitAlignContent: case CSSPropertyWebkitAlignItems: case CSSPropertyWebkitAlignSelf: case CSSPropertyWebkitFlexDirection: - case CSSPropertyWebkitFlexLinePack: - case CSSPropertyWebkitFlexPack: case CSSPropertyWebkitFlexWrap: + case CSSPropertyWebkitJustifyContent: #endif case CSSPropertyWebkitFontKerning: case CSSPropertyWebkitFontSmoothing: @@ -939,7 +941,6 @@ static inline bool isKeywordPropertyID(CSSPropertyID propertyId) case CSSPropertyWebkitMarginTopCollapse: case CSSPropertyWebkitMarqueeDirection: case CSSPropertyWebkitMarqueeStyle: - case CSSPropertyWebkitMatchNearestMailBlockquoteColor: case CSSPropertyWebkitNbspMode: #if ENABLE(OVERFLOW_SCROLLING) case CSSPropertyWebkitOverflowScrolling: @@ -1119,16 +1120,19 @@ void CSSParser::parseSelector(const String& string, CSSSelectorList& selectorLis m_selectorListForParseSelector = 0; } -bool CSSParser::parseDeclaration(StylePropertySet* declaration, const String& string, RefPtr<CSSStyleSourceData>* styleSourceData, StyleSheetContents* contextStyleSheet) +bool CSSParser::parseDeclaration(StylePropertySet* declaration, const String& string, PassRefPtr<CSSStyleSourceData> prpStyleSourceData, StyleSheetContents* contextStyleSheet) { // Length of the "@-webkit-decls{" prefix. static const unsigned prefixLength = 15; setStyleSheet(contextStyleSheet); + RefPtr<CSSStyleSourceData> styleSourceData = prpStyleSourceData; if (styleSourceData) { - m_currentRuleData = CSSRuleSourceData::create(); - m_currentRuleData->styleSourceData = CSSStyleSourceData::create(); + m_currentRuleDataStack = adoptPtr(new RuleSourceDataList()); + RefPtr<CSSRuleSourceData> data = CSSRuleSourceData::create(); + data->styleSourceData = styleSourceData; + m_currentRuleDataStack->append(data); m_inStyleRuleOrDeclaration = true; } @@ -1145,20 +1149,22 @@ bool CSSParser::parseDeclaration(StylePropertySet* declaration, const String& st clearProperties(); } - if (m_currentRuleData) { - m_currentRuleData->styleSourceData->styleBodyRange.start = 0; - m_currentRuleData->styleSourceData->styleBodyRange.end = string.length(); - for (Vector<CSSPropertySourceData>::iterator it = m_currentRuleData->styleSourceData->propertyData.begin(), endIt = m_currentRuleData->styleSourceData->propertyData.end(); it != endIt; ++it) { - (*it).range.start -= prefixLength; - (*it).range.end -= prefixLength; - } - } - if (styleSourceData) { - *styleSourceData = m_currentRuleData->styleSourceData.release(); - m_currentRuleData = 0; + ASSERT(!m_currentRuleDataStack->isEmpty()); + CSSRuleSourceData* ruleData = m_currentRuleDataStack->last().get(); + ruleData->styleSourceData->styleBodyRange.start = 0; + ruleData->styleSourceData->styleBodyRange.end = string.length(); + for (size_t i = 0, size = ruleData->styleSourceData->propertyData.size(); i < size; ++i) { + CSSPropertySourceData& propertyData = ruleData->styleSourceData->propertyData.at(i); + propertyData.range.start -= prefixLength; + propertyData.range.end -= prefixLength; + } + fixUnparsedPropertyRanges(ruleData); + + m_currentRuleDataStack.clear(); m_inStyleRuleOrDeclaration = false; } + return ok; } @@ -1177,13 +1183,27 @@ PassOwnPtr<MediaQuery> CSSParser::parseMediaQuery(const String& string) return m_mediaQuery.release(); } +#if ENABLE(CSS_VARIABLES) +static inline void filterProperties(bool important, const CSSParser::ParsedPropertyVector& input, Vector<CSSProperty, 256>& output, size_t& unusedEntries, BitArray<numCSSProperties>& seenProperties, HashSet<AtomicString>& seenVariables) +#else static inline void filterProperties(bool important, const CSSParser::ParsedPropertyVector& input, Vector<CSSProperty, 256>& output, size_t& unusedEntries, BitArray<numCSSProperties>& seenProperties) +#endif { // Add properties in reverse order so that highest priority definitions are reached first. Duplicate definitions can then be ignored when found. for (int i = input.size() - 1; i >= 0; --i) { const CSSProperty& property = input[i]; if (property.isImportant() != important) continue; +#if ENABLE(CSS_VARIABLES) + if (property.id() == CSSPropertyVariable) { + const AtomicString& name = static_cast<CSSVariableValue*>(property.value())->name(); + if (seenVariables.contains(name)) + continue; + seenVariables.add(name); + output[--unusedEntries] = property; + continue; + } +#endif const unsigned propertyIDIndex = property.id() - firstCSSProperty; if (seenProperties.get(propertyIDIndex)) continue; @@ -1199,9 +1219,14 @@ PassRefPtr<StylePropertySet> CSSParser::createStylePropertySet() Vector<CSSProperty, 256> results(unusedEntries); // Important properties have higher priority, so add them first. Duplicate definitions can then be ignored when found. +#if ENABLE(CSS_VARIABLES) + HashSet<AtomicString> seenVariables; + filterProperties(true, m_parsedProperties, results, unusedEntries, seenProperties, seenVariables); + filterProperties(false, m_parsedProperties, results, unusedEntries, seenProperties, seenVariables); +#else filterProperties(true, m_parsedProperties, results, unusedEntries, seenProperties); filterProperties(false, m_parsedProperties, results, unusedEntries, seenProperties); - +#endif if (unusedEntries) results.remove(0, unusedEntries); @@ -1297,6 +1322,12 @@ bool CSSParser::validUnit(CSSParserValue* value, Units unitflags, CSSParserMode bool b = false; switch (value->unit) { +#if ENABLE(CSS_VARIABLES) + case CSSPrimitiveValue::CSS_VARIABLE_NAME: + // Variables are checked at the point they are dereferenced because unit type is not available here. + b = true; + break; +#endif case CSSPrimitiveValue::CSS_NUMBER: b = (unitflags & FNumber); if (!b && shouldAcceptUnitLessValues(value, unitflags, cssParserMode)) { @@ -1335,6 +1366,13 @@ bool CSSParser::validUnit(CSSParserValue* value, Units unitflags, CSSParserMode case CSSPrimitiveValue::CSS_TURN: b = (unitflags & FAngle); break; +#if ENABLE(CSS_IMAGE_RESOLUTION) + case CSSPrimitiveValue::CSS_DPPX: + case CSSPrimitiveValue::CSS_DPI: + case CSSPrimitiveValue::CSS_DPCM: + b = (unitflags & FResolution); + break; +#endif case CSSPrimitiveValue::CSS_HZ: case CSSPrimitiveValue::CSS_KHZ: case CSSPrimitiveValue::CSS_DIMENSION: @@ -1348,14 +1386,26 @@ bool CSSParser::validUnit(CSSParserValue* value, Units unitflags, CSSParserMode inline PassRefPtr<CSSPrimitiveValue> CSSParser::createPrimitiveNumericValue(CSSParserValue* value) { +#if ENABLE(CSS_VARIABLES) + if (value->unit == CSSPrimitiveValue::CSS_VARIABLE_NAME) + return CSSPrimitiveValue::create(value->string, CSSPrimitiveValue::CSS_VARIABLE_NAME); +#endif + if (m_parsedCalculation) { ASSERT(isCalculation(value)); return CSSPrimitiveValue::create(m_parsedCalculation.release()); } +#if ENABLE(CSS_IMAGE_RESOLUTION) + ASSERT((value->unit >= CSSPrimitiveValue::CSS_NUMBER && value->unit <= CSSPrimitiveValue::CSS_KHZ) + || (value->unit >= CSSPrimitiveValue::CSS_TURN && value->unit <= CSSPrimitiveValue::CSS_REMS) + || (value->unit >= CSSPrimitiveValue::CSS_VW && value->unit <= CSSPrimitiveValue::CSS_VMIN) + || (value->unit >= CSSPrimitiveValue::CSS_DPPX && value->unit <= CSSPrimitiveValue::CSS_DPCM)); +#else ASSERT((value->unit >= CSSPrimitiveValue::CSS_NUMBER && value->unit <= CSSPrimitiveValue::CSS_KHZ) || (value->unit >= CSSPrimitiveValue::CSS_TURN && value->unit <= CSSPrimitiveValue::CSS_REMS) || (value->unit >= CSSPrimitiveValue::CSS_VW && value->unit <= CSSPrimitiveValue::CSS_VMIN)); +#endif return cssValuePool().createValue(value->fValue, static_cast<CSSPrimitiveValue::UnitTypes>(value->unit)); } @@ -1410,6 +1460,14 @@ static int unitFromString(CSSParserValue* value) return CSSPrimitiveValue::CSS_VH; if (equal(value->string, "vmin")) return CSSPrimitiveValue::CSS_VMIN; +#if ENABLE(CSS_IMAGE_RESOLUTION) + if (equal(value->string, "dppx")) + return CSSPrimitiveValue::CSS_DPPX; + if (equal(value->string, "dpi")) + return CSSPrimitiveValue::CSS_DPI; + if (equal(value->string, "dpcm")) + return CSSPrimitiveValue::CSS_DPCM; +#endif return 0; } @@ -1463,6 +1521,10 @@ inline PassRefPtr<CSSPrimitiveValue> CSSParser::parseValidPrimitive(int identifi return createPrimitiveNumericValue(value); if (value->unit >= CSSPrimitiveValue::CSS_VW && value->unit <= CSSPrimitiveValue::CSS_VMIN) return createPrimitiveNumericValue(value); +#if ENABLE(CSS_IMAGE_RESOLUTION) + if (value->unit >= CSSPrimitiveValue::CSS_DPPX && value->unit <= CSSPrimitiveValue::CSS_DPCM) + return createPrimitiveNumericValue(value); +#endif if (value->unit >= CSSParserValue::Q_EMS) return CSSPrimitiveValue::createAllowingMarginQuirk(value->fValue, CSSPrimitiveValue::CSS_EMS); if (isCalculation(value)) @@ -1506,6 +1568,14 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important) return true; } +#if ENABLE(CSS_VARIABLES) + if (!id && value->unit == CSSPrimitiveValue::CSS_VARIABLE_NAME && num == 1) { + addProperty(propId, CSSPrimitiveValue::create(value->string, CSSPrimitiveValue::CSS_VARIABLE_NAME), important); + m_valueList->next(); + return true; + } +#endif + if (isKeywordPropertyID(propId)) { if (!isValidKeywordPropertyAndValue(propId, id, m_context)) return false; @@ -1578,8 +1648,8 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important) } case CSSPropertyTextAlign: - // left | right | center | justify | webkit_left | webkit_right | webkit_center | webkit_match_parent | - // start | end | <string> | inherit + // left | right | center | justify | -webkit-left | -webkit-right | -webkit-center | -webkit-match-parent + // | start | end | <string> | inherit | -webkit-auto (converted to start) if ((id >= CSSValueWebkitAuto && id <= CSSValueWebkitMatchParent) || id == CSSValueStart || id == CSSValueEnd || value->unit == CSSPrimitiveValue::CSS_STRING) validPrimitive = true; @@ -2071,9 +2141,11 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important) validPrimitive = validUnit(value, FNumber); break; case CSSPropertyWebkitBoxFlexGroup: - case CSSPropertyWebkitBoxOrdinalGroup: validPrimitive = validUnit(value, FInteger | FNonNeg, CSSStrictMode); break; + case CSSPropertyWebkitBoxOrdinalGroup: + validPrimitive = validUnit(value, FInteger | FNonNeg, CSSStrictMode) && value->fValue; + break; #if ENABLE(CSS_FILTERS) case CSSPropertyWebkitFilter: if (id == CSSValueNone) @@ -2096,12 +2168,7 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important) parsedValue = parseFlex(m_valueList.get()); break; case CSSPropertyWebkitOrder: - if (validUnit(value, FInteger, CSSStrictMode)) { - // We restrict the smallest value to int min + 2 because we use int min and int min + 1 as special values in a hash set. - parsedValue = cssValuePool().createValue(max(static_cast<double>(std::numeric_limits<int>::min() + 2), value->fValue), - static_cast<CSSPrimitiveValue::UnitTypes>(value->unit)); - m_valueList->next(); - } + validPrimitive = validUnit(value, FNumber); break; #endif case CSSPropertyWebkitMarquee: @@ -2268,6 +2335,10 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important) if (id == CSSValueHorizontal || id == CSSValueVertical || id == CSSValueAuto) validPrimitive = true; break; + case CSSPropertyWebkitColumnProgression: + if (id == CSSValueNormal || id == CSSValueReverse) + validPrimitive = true; + break; case CSSPropertyWebkitColumnSpan: // all | 1 if (id == CSSValueAll) validPrimitive = true; @@ -2498,6 +2569,14 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important) case CSSPropertyWebkitWrap: return RuntimeEnabledFeatures::cssExclusionsEnabled() && parseShorthand(propId, webkitWrapShorthand(), important); #endif +#if ENABLE(CSS_IMAGE_RESOLUTION) + case CSSPropertyImageResolution: + parsedValue = parseImageResolution(m_valueList.get()); + if (!parsedValue) + return false; + m_valueList->next(); + break; +#endif case CSSPropertyBorderBottomStyle: case CSSPropertyBorderCollapse: case CSSPropertyBorderLeftStyle: @@ -2543,7 +2622,9 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important) case CSSPropertyWebkitBorderFit: case CSSPropertyWebkitBorderStartStyle: case CSSPropertyWebkitBoxAlign: +#if ENABLE(CSS_BOX_DECORATION_BREAK) case CSSPropertyWebkitBoxDecorationBreak: +#endif case CSSPropertyWebkitBoxDirection: case CSSPropertyWebkitBoxLines: case CSSPropertyWebkitBoxOrient: @@ -2554,12 +2635,12 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important) case CSSPropertyWebkitColumnBreakInside: case CSSPropertyWebkitColumnRuleStyle: #if ENABLE(CSS3_FLEXBOX) + case CSSPropertyWebkitAlignContent: case CSSPropertyWebkitAlignItems: case CSSPropertyWebkitAlignSelf: case CSSPropertyWebkitFlexDirection: - case CSSPropertyWebkitFlexLinePack: - case CSSPropertyWebkitFlexPack: case CSSPropertyWebkitFlexWrap: + case CSSPropertyWebkitJustifyContent: #endif case CSSPropertyWebkitFontKerning: case CSSPropertyWebkitFontSmoothing: @@ -2573,7 +2654,6 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important) case CSSPropertyWebkitMarginTopCollapse: case CSSPropertyWebkitMarqueeDirection: case CSSPropertyWebkitMarqueeStyle: - case CSSPropertyWebkitMatchNearestMailBlockquoteColor: case CSSPropertyWebkitNbspMode: #if ENABLE(OVERFLOW_SCROLLING) case CSSPropertyWebkitOverflowScrolling: @@ -2796,6 +2876,19 @@ bool CSSParser::parseFillShorthand(CSSPropertyID propId, const CSSPropertyID* pr return true; } +#if ENABLE(CSS_VARIABLES) +void CSSParser::storeVariableDeclaration(const CSSParserString& name, PassOwnPtr<CSSParserValueList> value, bool important) +{ + StringBuilder builder; + for (unsigned i = 0, size = value->size(); i < size; i++) { + if (i) + builder.append(' '); + builder.append(value->valueAt(i)->createCSSValue()->cssText()); + } + addProperty(CSSPropertyVariable, CSSVariableValue::create(name, builder.toString()), important, false); +} +#endif + void CSSParser::addAnimationValue(RefPtr<CSSValue>& lval, PassRefPtr<CSSValue> rval) { if (lval) { @@ -5595,9 +5688,9 @@ PassRefPtr<CSSValue> CSSParser::parseFlex(CSSParserValueList* args) } if (positiveFlex == unsetValue) - positiveFlex = 1; + positiveFlex = 0; if (negativeFlex == unsetValue) - negativeFlex = positiveFlex ? 1 : 0; + negativeFlex = 1; if (!preferredSize) preferredSize = cssValuePool().createValue(0, CSSPrimitiveValue::CSS_PX); @@ -5845,7 +5938,7 @@ public: BorderImageSliceParseContext(CSSParser* parser) : m_parser(parser) , m_allowNumber(true) - , m_allowFill(false) + , m_allowFill(true) , m_allowFinalCommit(false) , m_fill(false) { } @@ -5870,14 +5963,10 @@ public: } m_allowNumber = !m_left; - m_allowFill = true; m_allowFinalCommit = true; } - void commitFill() { m_fill = true; m_allowFill = false; m_allowNumber = false; } - - void setAllowFinalCommit() { m_allowFinalCommit = true; } - void setTop(PassRefPtr<CSSPrimitiveValue> val) { m_top = val; } + void commitFill() { m_fill = true; m_allowFill = false; m_allowNumber = !m_top; } PassRefPtr<CSSBorderImageSliceValue> commitBorderImageSlice() { @@ -6793,6 +6882,31 @@ bool CSSParser::parseCanvas(CSSParserValueList* valueList, RefPtr<CSSValue>& can return true; } +#if ENABLE(CSS_IMAGE_RESOLUTION) +PassRefPtr<CSSValue> CSSParser::parseImageResolution(CSSParserValueList* valueList) +{ + RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); + bool haveResolution = false; + bool haveFromImage = false; + + CSSParserValue* value = valueList->current(); + while (value) { + if (!haveFromImage && value->id == CSSValueFromImage) { + list->append(cssValuePool().createIdentifierValue(value->id)); + haveFromImage = true; + } else if (!haveResolution && validUnit(value, FResolution | FNonNeg) && value->fValue > 0) { + list->append(createPrimitiveNumericValue(value)); + haveResolution = true; + } else + return 0; + value = m_valueList->next(); + } + if (!list->length()) + return 0; + return list; +} +#endif + #if ENABLE(CSS_IMAGE_SET) PassRefPtr<CSSValue> CSSParser::parseImageSet(CSSParserValueList* valueList) { @@ -8270,6 +8384,20 @@ inline void CSSParser::detectNumberToken(UChar* type, int length) case 'd': if (length == 3 && isASCIIAlphaCaselessEqual(type[1], 'e') && isASCIIAlphaCaselessEqual(type[2], 'g')) m_token = DEGS; +#if ENABLE(CSS_IMAGE_RESOLUTION) + else if (length > 2 && isASCIIAlphaCaselessEqual(type[1], 'p')) { + if (length == 4) { + // There is a discussion about the name of this unit on www-style. + // Keep this compile time guard in place until that is resolved. + // http://lists.w3.org/Archives/Public/www-style/2012May/0915.html + if (isASCIIAlphaCaselessEqual(type[2], 'p') && isASCIIAlphaCaselessEqual(type[3], 'x')) + m_token = DPPX; + else if (isASCIIAlphaCaselessEqual(type[2], 'c') && isASCIIAlphaCaselessEqual(type[3], 'm')) + m_token = DPCM; + } else if (length == 3 && isASCIIAlphaCaselessEqual(type[2], 'i')) + m_token = DPI; + } +#endif return; case 'e': @@ -8371,6 +8499,10 @@ inline void CSSParser::detectDashToken(int length) m_token = MINFUNCTION; else if (isASCIIAlphaCaselessEqual(name[10], 'x') && isEqualToCSSIdentifier(name + 1, "webkit-ma")) m_token = MAXFUNCTION; +#if ENABLE(CSS_VARIABLES) + else if (isASCIIAlphaCaselessEqual(name[10], 'r') && isEqualToCSSIdentifier(name + 1, "webkit-va")) + m_token = VARFUNCTION; +#endif } else if (length == 12 && isEqualToCSSIdentifier(name + 1, "webkit-calc")) m_token = CALCFUNCTION; } @@ -8709,6 +8841,16 @@ restartAfterComment: } case CharacterDash: +#if ENABLE(CSS_VARIABLES) + if (m_currentCharacter[10] == '-' && isEqualToCSSIdentifier(m_currentCharacter, "webkit-var") && isIdentifierStartAfterDash(m_currentCharacter + 11)) { + // handle variable declarations + m_currentCharacter += 11; + parseIdentifier(result, hasEscape); + m_token = VAR_DEFINITION; + yylval->string.characters = m_tokenStart; + yylval->string.length = result - m_tokenStart; + } else +#endif if (isIdentifierStartAfterDash(m_currentCharacter)) { --m_currentCharacter; parseIdentifier(result, hasEscape); @@ -9121,6 +9263,27 @@ CSSParser::RuleList* CSSParser::createRuleList() return listPtr; } +void CSSParser::addNewRuleToSourceTree(PassRefPtr<CSSRuleSourceData> rule) +{ + // Precondition: (isExtractingSourceData()). + if (!m_ruleSourceDataResult) + return; + + // FIXME: This temporarily builds a flat style rule data list, to avoid the client code breakage. + m_ruleSourceDataResult->append(rule); +} + +PassRefPtr<CSSRuleSourceData> CSSParser::popRuleData() +{ + if (!m_ruleSourceDataResult) + return 0; + + ASSERT(!m_currentRuleDataStack->isEmpty()); + RefPtr<CSSRuleSourceData> data = m_currentRuleDataStack->last(); + m_currentRuleDataStack->removeLast(); + return data.release(); +} + StyleRuleKeyframes* CSSParser::createKeyframesRule() { m_allowImportRules = m_allowNamespaceDeclarations = false; @@ -9143,18 +9306,19 @@ StyleRuleBase* CSSParser::createStyleRule(Vector<OwnPtr<CSSParserSelector> >* se rule->setProperties(createStylePropertySet()); result = rule.get(); m_parsedRules.append(rule.release()); - if (m_ruleRangeMap) { - ASSERT(m_currentRuleData); - m_currentRuleData->styleSourceData->styleBodyRange = m_ruleBodyRange; - m_currentRuleData->selectorListRange = m_selectorListRange; - m_ruleRangeMap->set(result, m_currentRuleData.release()); - m_currentRuleData = CSSRuleSourceData::create(); - m_currentRuleData->styleSourceData = CSSStyleSourceData::create(); + if (isExtractingSourceData()) { + RefPtr<CSSRuleSourceData> currentRuleData = popRuleData(); + currentRuleData->styleSourceData->styleBodyRange = m_ruleBodyRange; + currentRuleData->selectorListRange = m_selectorListRange; + fixUnparsedPropertyRanges(currentRuleData.get()); + addNewRuleToSourceTree(currentRuleData.release()); m_inStyleRuleOrDeclaration = false; } } - resetSelectorListMarks(); - resetRuleBodyMarks(); + if (isExtractingSourceData()) { + resetSelectorListMarks(); + resetRuleBodyMarks(); + } clearProperties(); return result; } @@ -9213,7 +9377,7 @@ void CSSParser::updateSpecifiersWithElementName(const AtomicString& namespacePre CSSParserSelector* history = specifiers; while (history->tagHistory()) { history = history->tagHistory(); - if (history->hasShadowDescendant()) + if (history->isUnknownPseudoElement() || history->hasShadowDescendant()) lastShadowDescendant = history; } @@ -9360,14 +9524,61 @@ void CSSParser::updateLastMediaLine(MediaQuerySet* media) media->setLastLine(m_lineNumber); } +void CSSParser::fixUnparsedPropertyRanges(CSSRuleSourceData* ruleData) +{ + Vector<CSSPropertySourceData>& propertyData = ruleData->styleSourceData->propertyData; + unsigned size = propertyData.size(); + if (!size) + return; + + unsigned styleStart = ruleData->styleSourceData->styleBodyRange.start; + const UChar* characters = m_dataStart.get() + m_parsedTextPrefixLength; + CSSPropertySourceData* nextData = &(propertyData.at(0)); + for (unsigned i = 0; i < size; ++i) { + CSSPropertySourceData* currentData = nextData; + nextData = i < size - 1 ? &(propertyData.at(i + 1)) : 0; + + if (currentData->parsedOk) + continue; + if (currentData->range.end > 0 && characters[styleStart + currentData->range.end - 1] == ';') + continue; + + unsigned propertyEndInStyleSheet; + if (!nextData) + propertyEndInStyleSheet = ruleData->styleSourceData->styleBodyRange.end - 1; + else + propertyEndInStyleSheet = styleStart + nextData->range.start - 1; + + while (isHTMLSpace(characters[propertyEndInStyleSheet])) + --propertyEndInStyleSheet; + + // propertyEndInStyleSheet points at the last property text character. + unsigned newPropertyEnd = propertyEndInStyleSheet - styleStart + 1; // Exclusive of the last property text character. + if (currentData->range.end != newPropertyEnd) { + currentData->range.end = newPropertyEnd; + unsigned valueStartInStyleSheet = styleStart + currentData->range.start + currentData->name.length(); + while (valueStartInStyleSheet < propertyEndInStyleSheet && characters[valueStartInStyleSheet] != ':') + ++valueStartInStyleSheet; + if (valueStartInStyleSheet < propertyEndInStyleSheet) + ++valueStartInStyleSheet; // Shift past the ':'. + while (valueStartInStyleSheet < propertyEndInStyleSheet && isHTMLSpace(characters[valueStartInStyleSheet])) + ++valueStartInStyleSheet; + // Need to exclude the trailing ';' from the property value. + currentData->value = String(characters + valueStartInStyleSheet, propertyEndInStyleSheet - valueStartInStyleSheet + (characters[propertyEndInStyleSheet] == ';' ? 0 : 1)); + } + } +} + void CSSParser::markSelectorListStart() { + if (!isExtractingSourceData()) + return; m_selectorListRange.start = m_tokenStart - m_dataStart.get(); } void CSSParser::markSelectorListEnd() { - if (!m_currentRuleData) + if (!isExtractingSourceData()) return; UChar* listEnd = m_tokenStart; while (listEnd > m_dataStart.get() + 1) { @@ -9377,10 +9588,15 @@ void CSSParser::markSelectorListEnd() break; } m_selectorListRange.end = listEnd - m_dataStart.get(); + RefPtr<CSSRuleSourceData> data = CSSRuleSourceData::create(); + data->styleSourceData = CSSStyleSourceData::create(); + m_currentRuleDataStack->append(data); } void CSSParser::markRuleBodyStart() { + if (!isExtractingSourceData()) + return; unsigned offset = m_tokenStart - m_dataStart.get(); if (*m_tokenStart == '{') ++offset; // Skip the rule body opening brace. @@ -9391,6 +9607,8 @@ void CSSParser::markRuleBodyStart() void CSSParser::markRuleBodyEnd() { + if (!isExtractingSourceData()) + return; unsigned offset = m_tokenStart - m_dataStart.get(); if (offset > m_ruleBodyRange.end) m_ruleBodyRange.end = offset; @@ -9407,11 +9625,12 @@ void CSSParser::markPropertyEnd(bool isImportantFound, bool isPropertyParsed) { if (!m_inStyleRuleOrDeclaration) return; + unsigned offset = m_tokenStart - m_dataStart.get(); if (*m_tokenStart == ';') // Include semicolon into the property text. ++offset; m_propertyRange.end = offset; - if (m_propertyRange.start != UINT_MAX && m_currentRuleData) { + if (m_propertyRange.start != UINT_MAX && !m_currentRuleDataStack->isEmpty()) { // This stuff is only executed when the style data retrieval is requested by client. const unsigned start = m_propertyRange.start; const unsigned end = m_propertyRange.end; @@ -9425,10 +9644,10 @@ void CSSParser::markPropertyEnd(bool isImportantFound, bool isPropertyParsed) String name = propertyString.left(colonIndex).stripWhiteSpace(); String value = propertyString.substring(colonIndex + 1, propertyString.length()).stripWhiteSpace(); // The property range is relative to the declaration start offset. - m_currentRuleData->styleSourceData->propertyData.append( + m_currentRuleDataStack->last()->styleSourceData->propertyData.append( CSSPropertySourceData(name, value, isImportantFound, isPropertyParsed, SourceRange(start - m_ruleBodyRange.start, end - m_ruleBodyRange.start))); } - resetPropertyMarks(); + resetPropertyRange(); } static CSSPropertyID cssPropertyID(const UChar* propertyName, unsigned length) |