Index: Source/core/css/parser/CSSPropertyParser.cpp |
diff --git a/Source/core/css/parser/CSSPropertyParser.cpp b/Source/core/css/parser/CSSPropertyParser.cpp |
index 3ed4a660864f74fb5a0cb1082f61716d827093d0..d08862af53cf57c0a7509af8f5495f06444435a7 100644 |
--- a/Source/core/css/parser/CSSPropertyParser.cpp |
+++ b/Source/core/css/parser/CSSPropertyParser.cpp |
@@ -998,15 +998,8 @@ bool CSSPropertyParser::parseValue(CSSPropertyID unresolvedProperty, bool import |
case CSSPropertyBoxShadow: |
if (id == CSSValueNone) |
validPrimitive = true; |
- else { |
- RefPtrWillBeRawPtr<CSSValueList> shadowValueList = parseShadow(m_valueList, propId); |
- if (shadowValueList) { |
- addProperty(propId, shadowValueList.release(), important); |
- m_valueList->next(); |
- return true; |
- } |
- return false; |
- } |
+ else |
+ parsedValue = parseShadow(m_valueList, propId); |
break; |
case CSSPropertyWebkitBoxReflect: |
if (id == CSSValueNone) |
@@ -5116,175 +5109,87 @@ bool CSSPropertyParser::parseColorFromValue(const CSSParserValue* value, RGBA32& |
return true; |
} |
-// This class tracks parsing state for shadow values. If it goes out of scope (e.g., due to an early return) |
-// without the allowBreak bit being set, then it will clean up all of the objects and destroy them. |
-class ShadowParseContext { |
- STACK_ALLOCATED(); |
-public: |
- ShadowParseContext(CSSPropertyID prop) |
- : property(prop) |
- , allowX(true) |
- , allowY(false) |
- , allowBlur(false) |
- , allowSpread(false) |
- , allowColor(true) |
- , allowStyle(prop == CSSPropertyBoxShadow) |
- , allowBreak(true) |
- { |
- } |
- |
- bool allowLength() { return allowX || allowY || allowBlur || allowSpread; } |
- |
- void commitValue() |
- { |
- // Handle the ,, case gracefully by doing nothing. |
- if (x || y || blur || spread || color || style) { |
- if (!values) |
- values = CSSValueList::createCommaSeparated(); |
- |
- // Construct the current shadow value and add it to the list. |
- values->append(CSSShadowValue::create(x.release(), y.release(), blur.release(), spread.release(), style.release(), color.release())); |
- } |
- |
- // Now reset for the next shadow value. |
- x = nullptr; |
- y = nullptr; |
- blur = nullptr; |
- spread = nullptr; |
- style = nullptr; |
- color = nullptr; |
- |
- allowX = true; |
- allowColor = true; |
- allowBreak = true; |
- allowY = false; |
- allowBlur = false; |
- allowSpread = false; |
- allowStyle = property == CSSPropertyBoxShadow; |
- } |
- |
- void commitLength(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> val) |
- { |
- if (allowX) { |
- x = val; |
- allowX = false; |
- allowY = true; |
- allowColor = false; |
- allowStyle = false; |
- allowBreak = false; |
- } else if (allowY) { |
- y = val; |
- allowY = false; |
- allowBlur = true; |
- allowColor = true; |
- allowStyle = property == CSSPropertyBoxShadow; |
- allowBreak = true; |
- } else if (allowBlur) { |
- blur = val; |
- allowBlur = false; |
- allowSpread = property == CSSPropertyBoxShadow; |
- } else if (allowSpread) { |
- spread = val; |
- allowSpread = false; |
- } |
- } |
- |
- void commitColor(PassRefPtrWillBeRawPtr<CSSPrimitiveValue> val) |
- { |
- color = val; |
- allowColor = false; |
- if (allowX) { |
- allowStyle = false; |
- allowBreak = false; |
- } else { |
- allowBlur = false; |
- allowSpread = false; |
- allowStyle = property == CSSPropertyBoxShadow; |
- } |
- } |
- |
- void commitStyle(CSSParserValue* v) |
- { |
- style = cssValuePool().createIdentifierValue(v->id); |
- allowStyle = false; |
- if (allowX) |
- allowBreak = false; |
- else { |
- allowBlur = false; |
- allowSpread = false; |
- allowColor = false; |
- } |
+PassRefPtrWillBeRawPtr<CSSValueList> CSSPropertyParser::parseShadow(CSSParserValueList* valueList, CSSPropertyID propID) |
+{ |
+ RefPtrWillBeRawPtr<CSSValueList> shadowValueList = CSSValueList::createCommaSeparated(); |
+ const bool isBoxShadowProperty = propID == CSSPropertyBoxShadow; |
+ while (RefPtrWillBeRawPtr<CSSShadowValue> shadowValue = parseSingleShadow(valueList, isBoxShadowProperty, isBoxShadowProperty)) { |
+ shadowValueList->append(shadowValue); |
+ if (!valueList->current()) |
+ break; |
+ if (!consumeComma(valueList)) |
+ return nullptr; |
} |
+ if (shadowValueList->length() == 0) |
+ return nullptr; |
+ return shadowValueList; |
+} |
- CSSPropertyID property; |
- |
- RefPtrWillBeMember<CSSValueList> values; |
- RefPtrWillBeMember<CSSPrimitiveValue> x; |
- RefPtrWillBeMember<CSSPrimitiveValue> y; |
- RefPtrWillBeMember<CSSPrimitiveValue> blur; |
- RefPtrWillBeMember<CSSPrimitiveValue> spread; |
+PassRefPtrWillBeRawPtr<CSSShadowValue> CSSPropertyParser::parseSingleShadow(CSSParserValueList* valueList, bool allowInset, bool allowSpread) |
+{ |
RefPtrWillBeMember<CSSPrimitiveValue> style; |
RefPtrWillBeMember<CSSPrimitiveValue> color; |
+ Vector<RefPtrWillBeRawPtr<CSSPrimitiveValue>, 4> lengths; |
- bool allowX; |
- bool allowY; |
- bool allowBlur; |
- bool allowSpread; |
- bool allowColor; |
- bool allowStyle; // inset or not. |
- bool allowBreak; |
-}; |
+ CSSParserValue* val = valueList->current(); |
+ if (!val) |
+ return nullptr; |
+ if (val->id == CSSValueInset) { |
+ if (!allowInset) |
+ return nullptr; |
+ style = cssValuePool().createIdentifierValue(val->id); |
+ val = valueList->next(); |
+ if (!val) |
+ return nullptr; |
+ } |
+ if ((color = parseColor(val))) |
+ val = valueList->next(); |
-PassRefPtrWillBeRawPtr<CSSValueList> CSSPropertyParser::parseShadow(CSSParserValueList* valueList, CSSPropertyID propId) |
-{ |
- ShadowParseContext context(propId); |
- for (CSSParserValue* val = valueList->current(); val; val = valueList->next()) { |
- // Check for a comma break first. |
- if (val->m_unit == CSSParserValue::Operator) { |
- if (val->iValue != ',' || !context.allowBreak) { |
- // Other operators aren't legal or we aren't done with the current shadow |
- // value. Treat as invalid. |
- return nullptr; |
- } |
- // The value is good. Commit it. |
- context.commitValue(); |
- } else if (validUnit(val, FLength, HTMLStandardMode)) { |
- // We required a length and didn't get one. Invalid. |
- if (!context.allowLength()) |
- return nullptr; |
+ if (!val || !validUnit(val, FLength, HTMLStandardMode)) |
+ return nullptr; |
+ lengths.append(createPrimitiveNumericValue(val)); |
+ val = valueList->next(); |
- // Blur radius must be non-negative. |
- if (context.allowBlur && (m_parsedCalculation ? m_parsedCalculation->isNegative() : !validUnit(val, FLength | FNonNeg, HTMLStandardMode))) |
- return nullptr; |
+ if (!val || !validUnit(val, FLength, HTMLStandardMode)) |
+ return nullptr; |
+ lengths.append(createPrimitiveNumericValue(val)); |
+ val = valueList->next(); |
- // A length is allowed here. Construct the value and add it. |
- RefPtrWillBeRawPtr<CSSPrimitiveValue> length = createPrimitiveNumericValue(val); |
- context.commitLength(length.release()); |
- } else if (val->id == CSSValueInset) { |
- if (!context.allowStyle) |
+ if (val && validUnit(val, FLength, HTMLStandardMode)) { |
+ // Blur radius must be non-negative. |
+ if (m_parsedCalculation ? m_parsedCalculation->isNegative() : !validUnit(val, FLength | FNonNeg, HTMLStandardMode)) { |
+ m_parsedCalculation.release(); |
+ return nullptr; |
+ } |
+ lengths.append(createPrimitiveNumericValue(val)); |
+ val = valueList->next(); |
+ if (val && validUnit(val, FLength, HTMLStandardMode)) { |
+ if (!allowSpread) |
return nullptr; |
+ lengths.append(createPrimitiveNumericValue(val)); |
+ val = valueList->next(); |
+ } |
+ } |
- context.commitStyle(val); |
- } else { |
- if (!context.allowColor) |
+ if (val) { |
+ if (RefPtrWillBeMember<CSSPrimitiveValue> colorValue = parseColor(val)) { |
+ if (color) |
return nullptr; |
- |
- // The only other type of value that's ok is a color value. |
- RefPtrWillBeRawPtr<CSSPrimitiveValue> parsedColor = parseColor(val); |
- if (!parsedColor) |
+ color = colorValue; |
+ val = valueList->next(); |
+ } |
+ if (val && val->id == CSSValueInset) { |
+ if (!allowInset || style) |
return nullptr; |
- |
- context.commitColor(parsedColor.release()); |
+ style = cssValuePool().createIdentifierValue(val->id); |
+ val = valueList->next(); |
} |
} |
- |
- if (context.allowBreak) { |
- context.commitValue(); |
- if (context.values && context.values->length()) |
- return context.values.release(); |
- } |
- |
- return nullptr; |
+ unsigned lengthsSeen = lengths.size(); |
+ return CSSShadowValue::create(lengths.at(0), lengths.at(1), |
+ lengthsSeen > 2 ? lengths.at(2) : nullptr, |
+ lengthsSeen > 3 ? lengths.at(3) : nullptr, |
+ style.release(), color.release()); |
} |
PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseReflect() |
@@ -6932,11 +6837,10 @@ PassRefPtrWillBeRawPtr<CSSFunctionValue> CSSPropertyParser::parseBuiltinFilterAr |
} |
case CSSValueDropShadow: { |
// drop-shadow() takes a single shadow. |
- RefPtrWillBeRawPtr<CSSValueList> shadowValueList = parseShadow(args, CSSPropertyWebkitFilter); |
- if (!shadowValueList || shadowValueList->length() != 1) |
+ RefPtrWillBeRawPtr<CSSShadowValue> shadowValue = parseSingleShadow(args, false, true); |
+ if (!shadowValue) |
return nullptr; |
- |
- filterValue->append((shadowValueList.release())->item(0)); |
+ filterValue->append(shadowValue.release()); |
break; |
} |
default: |