| Index: Source/core/css/parser/CSSPropertyParser.cpp
|
| diff --git a/Source/core/css/parser/CSSPropertyParser.cpp b/Source/core/css/parser/CSSPropertyParser.cpp
|
| index c6f5aad7a5aa07919e4cd6151a26c37b92ef4b8e..4c4a35831317a2a576e69bd69131b7fd358b34af 100644
|
| --- a/Source/core/css/parser/CSSPropertyParser.cpp
|
| +++ b/Source/core/css/parser/CSSPropertyParser.cpp
|
| @@ -123,39 +123,6 @@ static PassRefPtrWillBeRawPtr<CSSPrimitiveValue> createPrimitiveValuePair(PassRe
|
| return cssValuePool().createValue(Pair::create(first, second, identicalValuesPolicy));
|
| }
|
|
|
| -class AnimationParseContext {
|
| -public:
|
| - AnimationParseContext()
|
| - : m_animationPropertyKeywordAllowed(true)
|
| - , m_firstAnimationCommitted(false)
|
| - {
|
| - }
|
| -
|
| - void commitFirstAnimation()
|
| - {
|
| - m_firstAnimationCommitted = true;
|
| - }
|
| -
|
| - bool hasCommittedFirstAnimation() const
|
| - {
|
| - return m_firstAnimationCommitted;
|
| - }
|
| -
|
| - void commitAnimationPropertyKeyword()
|
| - {
|
| - m_animationPropertyKeywordAllowed = false;
|
| - }
|
| -
|
| - bool animationPropertyKeywordAllowed() const
|
| - {
|
| - return m_animationPropertyKeywordAllowed;
|
| - }
|
| -
|
| -private:
|
| - bool m_animationPropertyKeywordAllowed;
|
| - bool m_firstAnimationCommitted;
|
| -};
|
| -
|
| CSSPropertyParser::CSSPropertyParser(OwnPtr<CSSParserValueList>& valueList,
|
| const CSSParserContext& context, bool inViewport, bool savedImportant,
|
| WillBeHeapVector<CSSProperty, 256>& parsedProperties,
|
| @@ -1221,9 +1188,7 @@ bool CSSPropertyParser::parseValue(CSSPropertyID propId, bool important)
|
| case CSSPropertyWebkitTransitionDuration:
|
| case CSSPropertyWebkitTransitionTimingFunction:
|
| case CSSPropertyWebkitTransitionProperty: {
|
| - RefPtrWillBeRawPtr<CSSValue> val = nullptr;
|
| - AnimationParseContext context;
|
| - if (parseAnimationProperty(propId, val, context)) {
|
| + if (RefPtrWillBeRawPtr<CSSValueList> val = parseAnimationPropertyList(propId)) {
|
| addPropertyWithPrefixingVariant(propId, val.release(), important);
|
| return true;
|
| }
|
| @@ -1847,21 +1812,19 @@ bool CSSPropertyParser::parseFillShorthand(CSSPropertyID propId, const CSSProper
|
| return true;
|
| }
|
|
|
| -void CSSPropertyParser::addAnimationValue(RefPtrWillBeRawPtr<CSSValue>& lval, PassRefPtrWillBeRawPtr<CSSValue> rval)
|
| +static bool isValidTransitionPropertyList(CSSValueList* value)
|
| {
|
| - if (lval) {
|
| - if (lval->isValueList())
|
| - toCSSValueList(lval.get())->append(rval);
|
| - else {
|
| - PassRefPtrWillBeRawPtr<CSSValue> oldVal(lval.release());
|
| - PassRefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
|
| - list->append(oldVal);
|
| - list->append(rval);
|
| - lval = list;
|
| - }
|
| + if (value->length() < 2)
|
| + return true;
|
| + for (CSSValueListIterator i = value; i.hasMore(); i.advance()) {
|
| + // FIXME: Shorthand parsing shouldn't add initial to the list since it won't round-trip
|
| + if (i.value()->isInitialValue())
|
| + continue;
|
| + CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(i.value());
|
| + if (primitiveValue->isValueID() && primitiveValue->getValueID() == CSSValueNone)
|
| + return false;
|
| }
|
| - else
|
| - lval = rval;
|
| + return true;
|
| }
|
|
|
| bool CSSPropertyParser::parseAnimationShorthand(CSSPropertyID propId, bool important)
|
| @@ -1878,38 +1841,32 @@ bool CSSPropertyParser::parseAnimationShorthand(CSSPropertyID propId, bool impor
|
| ShorthandScope scope(this, propId);
|
|
|
| bool parsedProperty[numProperties] = { false };
|
| - AnimationParseContext context;
|
| - RefPtrWillBeRawPtr<CSSValue> values[numProperties];
|
| -#if ENABLE(OILPAN)
|
| - // Zero initialize the array of raw pointers.
|
| - memset(&values, 0, sizeof(values));
|
| -#endif
|
| + RefPtrWillBeRawPtr<CSSValueList> values[numProperties];
|
| + for (size_t i = 0; i < numProperties; ++i)
|
| + values[i] = CSSValueList::createCommaSeparated();
|
|
|
| - unsigned i;
|
| while (m_valueList->current()) {
|
| CSSParserValue* val = m_valueList->current();
|
| if (val->unit == CSSParserValue::Operator && val->iValue == ',') {
|
| - // We hit the end. Fill in all remaining values with the initial value.
|
| + // We hit the end. Fill in all remaining values with the initial value.
|
| m_valueList->next();
|
| - for (i = 0; i < numProperties; ++i) {
|
| + for (size_t i = 0; i < numProperties; ++i) {
|
| if (!parsedProperty[i])
|
| - addAnimationValue(values[i], cssValuePool().createImplicitInitialValue());
|
| + values[i]->append(cssValuePool().createImplicitInitialValue());
|
| parsedProperty[i] = false;
|
| }
|
| if (!m_valueList->current())
|
| break;
|
| - context.commitFirstAnimation();
|
| }
|
|
|
| bool found = false;
|
| - for (i = 0; i < numProperties; ++i) {
|
| - if (!parsedProperty[i]) {
|
| - RefPtrWillBeRawPtr<CSSValue> val = nullptr;
|
| - if (parseAnimationProperty(animationProperties.properties()[i], val, context)) {
|
| - parsedProperty[i] = found = true;
|
| - addAnimationValue(values[i], val.release());
|
| - break;
|
| - }
|
| + for (size_t i = 0; i < numProperties; ++i) {
|
| + if (parsedProperty[i])
|
| + continue;
|
| + if (RefPtrWillBeRawPtr<CSSValue> val = parseAnimationProperty(animationProperties.properties()[i])) {
|
| + parsedProperty[i] = found = true;
|
| + values[i]->append(val.release());
|
| + break;
|
| }
|
| }
|
|
|
| @@ -1919,10 +1876,10 @@ bool CSSPropertyParser::parseAnimationShorthand(CSSPropertyID propId, bool impor
|
| return false;
|
| }
|
|
|
| - for (i = 0; i < numProperties; ++i) {
|
| + for (size_t i = 0; i < numProperties; ++i) {
|
| // If we didn't find the property, set an intial value.
|
| if (!parsedProperty[i])
|
| - addAnimationValue(values[i], cssValuePool().createImplicitInitialValue());
|
| + values[i]->append(cssValuePool().createImplicitInitialValue());
|
|
|
| if (RuntimeEnabledFeatures::cssAnimationUnprefixedEnabled())
|
| addPropertyWithPrefixingVariant(animationProperties.properties()[i], values[i].release(), important);
|
| @@ -1942,41 +1899,32 @@ bool CSSPropertyParser::parseTransitionShorthand(CSSPropertyID propId, bool impo
|
| ShorthandScope scope(this, propId);
|
|
|
| bool parsedProperty[numProperties] = { false };
|
| - AnimationParseContext context;
|
| - RefPtrWillBeRawPtr<CSSValue> values[numProperties];
|
| -#if ENABLE(OILPAN)
|
| - // Zero initialize the array of raw pointers.
|
| - memset(&values, 0, sizeof(values));
|
| -#endif
|
| + RefPtrWillBeRawPtr<CSSValueList> values[numProperties];
|
| + for (size_t i = 0; i < numProperties; ++i)
|
| + values[i] = CSSValueList::createCommaSeparated();
|
|
|
| - unsigned i;
|
| while (m_valueList->current()) {
|
| CSSParserValue* val = m_valueList->current();
|
| if (val->unit == CSSParserValue::Operator && val->iValue == ',') {
|
| // We hit the end. Fill in all remaining values with the initial value.
|
| m_valueList->next();
|
| - for (i = 0; i < numProperties; ++i) {
|
| + for (size_t i = 0; i < numProperties; ++i) {
|
| if (!parsedProperty[i])
|
| - addAnimationValue(values[i], cssValuePool().createImplicitInitialValue());
|
| + values[i]->append(cssValuePool().createImplicitInitialValue());
|
| parsedProperty[i] = false;
|
| }
|
| if (!m_valueList->current())
|
| break;
|
| - context.commitFirstAnimation();
|
| }
|
|
|
| bool found = false;
|
| - for (i = 0; !found && i < numProperties; ++i) {
|
| - if (!parsedProperty[i]) {
|
| - RefPtrWillBeRawPtr<CSSValue> val = nullptr;
|
| - if (parseAnimationProperty(shorthand.properties()[i], val, context)) {
|
| - parsedProperty[i] = found = true;
|
| - addAnimationValue(values[i], val.release());
|
| - }
|
| -
|
| - // There are more values to process but 'none' or 'all' were already defined as the animation property, the declaration becomes invalid.
|
| - if (!context.animationPropertyKeywordAllowed() && context.hasCommittedFirstAnimation())
|
| - return false;
|
| + for (size_t i = 0; i < numProperties; ++i) {
|
| + if (parsedProperty[i])
|
| + continue;
|
| + if (RefPtrWillBeRawPtr<CSSValue> val = parseAnimationProperty(shorthand.properties()[i])) {
|
| + parsedProperty[i] = found = true;
|
| + values[i]->append(val.release());
|
| + break;
|
| }
|
| }
|
|
|
| @@ -1986,15 +1934,16 @@ bool CSSPropertyParser::parseTransitionShorthand(CSSPropertyID propId, bool impo
|
| return false;
|
| }
|
|
|
| - // Fill in any remaining properties with the initial value.
|
| - for (i = 0; i < numProperties; ++i) {
|
| - if (!parsedProperty[i])
|
| - addAnimationValue(values[i], cssValuePool().createImplicitInitialValue());
|
| - }
|
| + ASSERT(shorthand.properties()[0] == CSSPropertyTransitionProperty || shorthand.properties()[0] == CSSPropertyWebkitTransitionProperty);
|
| + if (!isValidTransitionPropertyList(values[0].get()))
|
| + return false;
|
|
|
| - // Now add all of the properties we found.
|
| - for (i = 0; i < numProperties; i++)
|
| + // Fill in any remaining properties with the initial value and add
|
| + for (size_t i = 0; i < numProperties; ++i) {
|
| + if (!parsedProperty[i])
|
| + values[i]->append(cssValuePool().createImplicitInitialValue());
|
| addPropertyWithPrefixingVariant(shorthand.properties()[i], values[i].release(), important);
|
| + }
|
|
|
| return true;
|
| }
|
| @@ -3119,7 +3068,7 @@ PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseAnimationPlayState()
|
| return nullptr;
|
| }
|
|
|
| -PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseAnimationProperty(AnimationParseContext& context)
|
| +PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseAnimationProperty()
|
| {
|
| CSSParserValue* value = m_valueList->current();
|
| if (value->unit != CSSPrimitiveValue::CSS_IDENT)
|
| @@ -3129,10 +3078,8 @@ PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseAnimationProperty(Anima
|
| return cssValuePool().createIdentifierValue(result);
|
| if (equalIgnoringCase(value, "all"))
|
| return cssValuePool().createIdentifierValue(CSSValueAll);
|
| - if (equalIgnoringCase(value, "none")) {
|
| - context.commitAnimationPropertyKeyword();
|
| + if (equalIgnoringCase(value, "none"))
|
| return cssValuePool().createIdentifierValue(CSSValueNone);
|
| - }
|
| return nullptr;
|
| }
|
|
|
| @@ -3252,123 +3199,81 @@ PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseAnimationTimingFunction
|
| return nullptr;
|
| }
|
|
|
| -bool CSSPropertyParser::parseAnimationProperty(CSSPropertyID propId, RefPtrWillBeRawPtr<CSSValue>& result, AnimationParseContext& context)
|
| +PassRefPtrWillBeRawPtr<CSSValue> CSSPropertyParser::parseAnimationProperty(CSSPropertyID propId)
|
| {
|
| - RefPtrWillBeRawPtr<CSSValueList> values = nullptr;
|
| - CSSParserValue* val;
|
| RefPtrWillBeRawPtr<CSSValue> value = nullptr;
|
| - bool allowComma = false;
|
| + switch (propId) {
|
| + case CSSPropertyAnimationDelay:
|
| + case CSSPropertyWebkitAnimationDelay:
|
| + case CSSPropertyTransitionDelay:
|
| + case CSSPropertyWebkitTransitionDelay:
|
| + value = parseAnimationDelay();
|
| + break;
|
| + case CSSPropertyAnimationDirection:
|
| + case CSSPropertyWebkitAnimationDirection:
|
| + value = parseAnimationDirection();
|
| + break;
|
| + case CSSPropertyAnimationDuration:
|
| + case CSSPropertyWebkitAnimationDuration:
|
| + case CSSPropertyTransitionDuration:
|
| + case CSSPropertyWebkitTransitionDuration:
|
| + value = parseAnimationDuration();
|
| + break;
|
| + case CSSPropertyAnimationFillMode:
|
| + case CSSPropertyWebkitAnimationFillMode:
|
| + value = parseAnimationFillMode();
|
| + break;
|
| + case CSSPropertyAnimationIterationCount:
|
| + case CSSPropertyWebkitAnimationIterationCount:
|
| + value = parseAnimationIterationCount();
|
| + break;
|
| + case CSSPropertyAnimationName:
|
| + case CSSPropertyWebkitAnimationName:
|
| + value = parseAnimationName();
|
| + break;
|
| + case CSSPropertyAnimationPlayState:
|
| + case CSSPropertyWebkitAnimationPlayState:
|
| + value = parseAnimationPlayState();
|
| + break;
|
| + case CSSPropertyTransitionProperty:
|
| + case CSSPropertyWebkitTransitionProperty:
|
| + value = parseAnimationProperty();
|
| + break;
|
| + case CSSPropertyAnimationTimingFunction:
|
| + case CSSPropertyWebkitAnimationTimingFunction:
|
| + case CSSPropertyTransitionTimingFunction:
|
| + case CSSPropertyWebkitTransitionTimingFunction:
|
| + value = parseAnimationTimingFunction();
|
| + break;
|
| + default:
|
| + ASSERT_NOT_REACHED();
|
| + return nullptr;
|
| + }
|
|
|
| - result = nullptr;
|
| + if (value)
|
| + m_valueList->next();
|
| + return value.release();
|
| +}
|
|
|
| - while ((val = m_valueList->current())) {
|
| - RefPtrWillBeRawPtr<CSSValue> currValue = nullptr;
|
| - if (allowComma) {
|
| - if (!isComma(val))
|
| - return false;
|
| +PassRefPtrWillBeRawPtr<CSSValueList> CSSPropertyParser::parseAnimationPropertyList(CSSPropertyID propId)
|
| +{
|
| + RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
|
| + while (m_valueList->current()) {
|
| + RefPtrWillBeRawPtr<CSSValue> value = parseAnimationProperty(propId);
|
| + if (!value)
|
| + return nullptr;
|
| + list->append(value.release());
|
| + if (CSSParserValue* parserValue = m_valueList->current()) {
|
| + if (!isComma(parserValue))
|
| + return nullptr;
|
| m_valueList->next();
|
| - allowComma = false;
|
| + ASSERT(m_valueList->current());
|
| }
|
| - else {
|
| - switch (propId) {
|
| - case CSSPropertyAnimationDelay:
|
| - case CSSPropertyWebkitAnimationDelay:
|
| - case CSSPropertyTransitionDelay:
|
| - case CSSPropertyWebkitTransitionDelay:
|
| - currValue = parseAnimationDelay();
|
| - if (currValue)
|
| - m_valueList->next();
|
| - break;
|
| - case CSSPropertyAnimationDirection:
|
| - case CSSPropertyWebkitAnimationDirection:
|
| - currValue = parseAnimationDirection();
|
| - if (currValue)
|
| - m_valueList->next();
|
| - break;
|
| - case CSSPropertyAnimationDuration:
|
| - case CSSPropertyWebkitAnimationDuration:
|
| - case CSSPropertyTransitionDuration:
|
| - case CSSPropertyWebkitTransitionDuration:
|
| - currValue = parseAnimationDuration();
|
| - if (currValue)
|
| - m_valueList->next();
|
| - break;
|
| - case CSSPropertyAnimationFillMode:
|
| - case CSSPropertyWebkitAnimationFillMode:
|
| - currValue = parseAnimationFillMode();
|
| - if (currValue)
|
| - m_valueList->next();
|
| - break;
|
| - case CSSPropertyAnimationIterationCount:
|
| - case CSSPropertyWebkitAnimationIterationCount:
|
| - currValue = parseAnimationIterationCount();
|
| - if (currValue)
|
| - m_valueList->next();
|
| - break;
|
| - case CSSPropertyAnimationName:
|
| - case CSSPropertyWebkitAnimationName:
|
| - currValue = parseAnimationName();
|
| - if (currValue)
|
| - m_valueList->next();
|
| - break;
|
| - case CSSPropertyAnimationPlayState:
|
| - case CSSPropertyWebkitAnimationPlayState:
|
| - currValue = parseAnimationPlayState();
|
| - if (currValue)
|
| - m_valueList->next();
|
| - break;
|
| - case CSSPropertyTransitionProperty:
|
| - case CSSPropertyWebkitTransitionProperty:
|
| - currValue = parseAnimationProperty(context);
|
| - if (value && !context.animationPropertyKeywordAllowed())
|
| - return false;
|
| - if (currValue)
|
| - m_valueList->next();
|
| - break;
|
| - case CSSPropertyAnimationTimingFunction:
|
| - case CSSPropertyWebkitAnimationTimingFunction:
|
| - case CSSPropertyTransitionTimingFunction:
|
| - case CSSPropertyWebkitTransitionTimingFunction:
|
| - currValue = parseAnimationTimingFunction();
|
| - if (currValue)
|
| - m_valueList->next();
|
| - break;
|
| - default:
|
| - ASSERT_NOT_REACHED();
|
| - return false;
|
| - }
|
| -
|
| - if (!currValue)
|
| - return false;
|
| -
|
| - if (value && !values) {
|
| - values = CSSValueList::createCommaSeparated();
|
| - values->append(value.release());
|
| - }
|
| -
|
| - if (values)
|
| - values->append(currValue.release());
|
| - else
|
| - value = currValue.release();
|
| -
|
| - allowComma = true;
|
| - }
|
| -
|
| - // When parsing the 'transition' shorthand property, we let it handle building up the lists for all
|
| - // properties.
|
| - if (inShorthand())
|
| - break;
|
| - }
|
| -
|
| - if (values && values->length()) {
|
| - result = values.release();
|
| - return true;
|
| }
|
| - if (value) {
|
| - result = value.release();
|
| - return true;
|
| - }
|
| - return false;
|
| + if ((propId == CSSPropertyTransitionProperty || propId == CSSPropertyWebkitTransitionProperty) && !isValidTransitionPropertyList(list.get()))
|
| + return nullptr;
|
| + ASSERT(list->length());
|
| + return list.release();
|
| }
|
|
|
| static inline bool isCSSWideKeyword(CSSParserValue& value)
|
|
|