diff options
Diffstat (limited to 'Source/WebCore/css/StyleProperties.cpp')
-rw-r--r-- | Source/WebCore/css/StyleProperties.cpp | 814 |
1 files changed, 465 insertions, 349 deletions
diff --git a/Source/WebCore/css/StyleProperties.cpp b/Source/WebCore/css/StyleProperties.cpp index bb3570f73..ea1f9f109 100644 --- a/Source/WebCore/css/StyleProperties.cpp +++ b/Source/WebCore/css/StyleProperties.cpp @@ -24,13 +24,17 @@ #include "StyleProperties.h" #include "CSSComputedStyleDeclaration.h" +#include "CSSCustomPropertyValue.h" +#include "CSSDeferredParser.h" #include "CSSParser.h" +#include "CSSPendingSubstitutionValue.h" #include "CSSValueKeywords.h" #include "CSSValueList.h" #include "CSSValuePool.h" #include "Document.h" #include "PropertySetCSSStyleDeclaration.h" #include "StylePropertyShorthand.h" +#include "StylePropertyShorthandFunctions.h" #include "StyleSheetContents.h" #include <bitset> #include <wtf/text/StringBuilder.h> @@ -50,32 +54,30 @@ static size_t sizeForImmutableStylePropertiesWithPropertyCount(unsigned count) static bool isInitialOrInherit(const String& value) { - DEFINE_STATIC_LOCAL(String, initial, ("initial")); - DEFINE_STATIC_LOCAL(String, inherit, ("inherit")); - return value.length() == 7 && (value == initial || value == inherit); + return value.length() == 7 && (value == "initial" || value == "inherit"); } -PassRef<ImmutableStyleProperties> ImmutableStyleProperties::create(const CSSProperty* properties, unsigned count, CSSParserMode cssParserMode) +Ref<ImmutableStyleProperties> ImmutableStyleProperties::create(const CSSProperty* properties, unsigned count, CSSParserMode cssParserMode) { void* slot = WTF::fastMalloc(sizeForImmutableStylePropertiesWithPropertyCount(count)); return adoptRef(*new (NotNull, slot) ImmutableStyleProperties(properties, count, cssParserMode)); } -PassRef<ImmutableStyleProperties> StyleProperties::immutableCopyIfNeeded() const +Ref<ImmutableStyleProperties> StyleProperties::immutableCopyIfNeeded() const { - if (!isMutable()) - return static_cast<ImmutableStyleProperties&>(const_cast<StyleProperties&>(*this)); - const MutableStyleProperties& mutableThis = static_cast<const MutableStyleProperties&>(*this); + if (is<ImmutableStyleProperties>(*this)) + return downcast<ImmutableStyleProperties>(const_cast<StyleProperties&>(*this)); + const MutableStyleProperties& mutableThis = downcast<MutableStyleProperties>(*this); return ImmutableStyleProperties::create(mutableThis.m_propertyVector.data(), mutableThis.m_propertyVector.size(), cssParserMode()); } MutableStyleProperties::MutableStyleProperties(CSSParserMode cssParserMode) - : StyleProperties(cssParserMode) + : StyleProperties(cssParserMode, MutablePropertiesType) { } MutableStyleProperties::MutableStyleProperties(const CSSProperty* properties, unsigned length) - : StyleProperties(CSSStrictMode) + : StyleProperties(HTMLStandardMode, MutablePropertiesType) { m_propertyVector.reserveInitialCapacity(length); for (unsigned i = 0; i < length; ++i) @@ -106,14 +108,17 @@ ImmutableStyleProperties::~ImmutableStyleProperties() } MutableStyleProperties::MutableStyleProperties(const StyleProperties& other) - : StyleProperties(other.cssParserMode()) + : StyleProperties(other.cssParserMode(), MutablePropertiesType) { - if (other.isMutable()) - m_propertyVector = static_cast<const MutableStyleProperties&>(other).m_propertyVector; + ASSERT(other.type() != DeferredPropertiesType); + if (is<MutableStyleProperties>(other)) + m_propertyVector = downcast<MutableStyleProperties>(other).m_propertyVector; else { - m_propertyVector.reserveInitialCapacity(other.propertyCount()); - for (unsigned i = 0; i < other.propertyCount(); ++i) - m_propertyVector.uncheckedAppend(other.propertyAt(i).toCSSProperty()); + const auto& immutableOther = downcast<ImmutableStyleProperties>(other); + unsigned propertyCount = immutableOther.propertyCount(); + m_propertyVector.reserveInitialCapacity(propertyCount); + for (unsigned i = 0; i < propertyCount; ++i) + m_propertyVector.uncheckedAppend(immutableOther.propertyAt(i).toCSSProperty()); } } @@ -123,8 +128,21 @@ String StyleProperties::getPropertyValue(CSSPropertyID propertyID) const if (value) return value->cssText(); + const StylePropertyShorthand& shorthand = shorthandForProperty(propertyID); + if (shorthand.length()) { + RefPtr<CSSValue> value = getPropertyCSSValueInternal(shorthand.properties()[0]); + if (!value) + return String(); + if (value->isPendingSubstitutionValue()) + return downcast<CSSPendingSubstitutionValue>(*value).shorthandValue()->cssText(); + } + // Shorthand and 4-values properties switch (propertyID) { + case CSSPropertyAll: + return getCommonValue(allShorthand()); + case CSSPropertyAnimation: + return getLayeredShorthandValue(animationShorthand()); case CSSPropertyBorderSpacing: return borderSpacingValue(borderSpacingShorthand()); case CSSPropertyBackgroundPosition: @@ -151,20 +169,24 @@ String StyleProperties::getPropertyValue(CSSPropertyID propertyID) const return get4Values(borderWidthShorthand()); case CSSPropertyBorderStyle: return get4Values(borderStyleShorthand()); - case CSSPropertyWebkitColumnRule: - return getShorthandValue(webkitColumnRuleShorthand()); - case CSSPropertyWebkitColumns: - return getShorthandValue(webkitColumnsShorthand()); - case CSSPropertyWebkitFlex: - return getShorthandValue(webkitFlexShorthand()); - case CSSPropertyWebkitFlexFlow: - return getShorthandValue(webkitFlexFlowShorthand()); - case CSSPropertyWebkitGridArea: - return getShorthandValue(webkitGridAreaShorthand()); - case CSSPropertyWebkitGridColumn: - return getShorthandValue(webkitGridColumnShorthand()); - case CSSPropertyWebkitGridRow: - return getShorthandValue(webkitGridRowShorthand()); + case CSSPropertyColumnRule: + return getShorthandValue(columnRuleShorthand()); + case CSSPropertyColumns: + return getShorthandValue(columnsShorthand()); + case CSSPropertyFlex: + return getShorthandValue(flexShorthand()); + case CSSPropertyFlexFlow: + return getShorthandValue(flexFlowShorthand()); + case CSSPropertyGridArea: + return getShorthandValue(gridAreaShorthand()); + case CSSPropertyGridTemplate: + return getShorthandValue(gridTemplateShorthand()); + case CSSPropertyGrid: + return getShorthandValue(gridShorthand()); + case CSSPropertyGridColumn: + return getShorthandValue(gridColumnShorthand()); + case CSSPropertyGridRow: + return getShorthandValue(gridRowShorthand()); case CSSPropertyFont: return fontValue(); case CSSPropertyMargin: @@ -191,31 +213,41 @@ String StyleProperties::getPropertyValue(CSSPropertyID propertyID) const return getShorthandValue(webkitTextEmphasisShorthand()); case CSSPropertyWebkitTextStroke: return getShorthandValue(webkitTextStrokeShorthand()); - case CSSPropertyWebkitTransformOrigin: - return getShorthandValue(webkitTransformOriginShorthand()); - case CSSPropertyWebkitTransition: - return getLayeredShorthandValue(webkitTransitionShorthand()); - case CSSPropertyWebkitAnimation: - return getLayeredShorthandValue(webkitAnimationShorthand()); -#if ENABLE(SVG) + case CSSPropertyPerspectiveOrigin: + return getShorthandValue(perspectiveOriginShorthand()); + case CSSPropertyTransformOrigin: + return getShorthandValue(transformOriginShorthand()); case CSSPropertyMarker: { - RefPtr<CSSValue> value = getPropertyCSSValue(CSSPropertyMarkerStart); + RefPtr<CSSValue> value = getPropertyCSSValueInternal(CSSPropertyMarkerStart); if (value) return value->cssText(); return String(); } -#endif case CSSPropertyBorderRadius: return get4Values(borderRadiusShorthand()); +#if ENABLE(CSS_SCROLL_SNAP) + case CSSPropertyScrollSnapMargin: + return get4Values(scrollSnapMarginShorthand()); + case CSSPropertyScrollPadding: + return get4Values(scrollPaddingShorthand()); +#endif default: return String(); } } +String StyleProperties::getCustomPropertyValue(const String& propertyName) const +{ + RefPtr<CSSValue> value = getCustomPropertyCSSValue(propertyName); + if (value) + return value->cssText(); + return String(); +} + String StyleProperties::borderSpacingValue(const StylePropertyShorthand& shorthand) const { - RefPtr<CSSValue> horizontalValue = getPropertyCSSValue(shorthand.properties()[0]); - RefPtr<CSSValue> verticalValue = getPropertyCSSValue(shorthand.properties()[1]); + RefPtr<CSSValue> horizontalValue = getPropertyCSSValueInternal(shorthand.properties()[0]); + RefPtr<CSSValue> verticalValue = getPropertyCSSValueInternal(shorthand.properties()[1]); // While standard border-spacing property does not allow specifying border-spacing-vertical without // specifying border-spacing-horizontal <http://www.w3.org/TR/CSS21/tables.html#separated-borders>, @@ -246,7 +278,7 @@ void StyleProperties::appendFontLonghandValueIfExplicit(CSSPropertyID propertyID case CSSPropertyFontStyle: break; // No prefix. case CSSPropertyFontFamily: - case CSSPropertyFontVariant: + case CSSPropertyFontVariantCaps: case CSSPropertyFontWeight: prefix = ' '; break; @@ -280,7 +312,7 @@ String StyleProperties::fontValue() const String commonValue = fontSizeProperty.value()->cssText(); StringBuilder result; appendFontLonghandValueIfExplicit(CSSPropertyFontStyle, result, commonValue); - appendFontLonghandValueIfExplicit(CSSPropertyFontVariant, result, commonValue); + appendFontLonghandValueIfExplicit(CSSPropertyFontVariantCaps, result, commonValue); appendFontLonghandValueIfExplicit(CSSPropertyFontWeight, result, commonValue); if (!result.isEmpty()) result.append(' '); @@ -358,13 +390,17 @@ String StyleProperties::getLayeredShorthandValue(const StylePropertyShorthand& s size_t numLayers = 0; for (unsigned i = 0; i < size; ++i) { - values[i] = getPropertyCSSValue(shorthand.properties()[i]); - if (values[i]) { - if (values[i]->isBaseValueList()) - numLayers = std::max(toCSSValueList(values[i].get())->length(), numLayers); - else - numLayers = std::max<size_t>(1U, numLayers); + values[i] = getPropertyCSSValueInternal(shorthand.properties()[i]); + if (!values[i]) { + // We don't have all longhand properties defined as required for the shorthand + // property and thus should not serialize to a shorthand value. See spec at + // http://www.w3.org/TR/cssom-1/#serialize-a-css-declaration-block. + return String(); } + if (values[i]->isBaseValueList()) + numLayers = std::max(downcast<CSSValueList>(*values[i]).length(), numLayers); + else + numLayers = std::max<size_t>(1U, numLayers); } String commonValue; @@ -382,16 +418,16 @@ String StyleProperties::getLayeredShorthandValue(const StylePropertyShorthand& s RefPtr<CSSValue> value; if (values[j]) { if (values[j]->isBaseValueList()) - value = toCSSValueList(values[j].get())->item(i); + value = downcast<CSSValueList>(*values[j]).item(i); else { value = values[j]; // Color only belongs in the last layer. if (shorthand.properties()[j] == CSSPropertyBackgroundColor) { if (i != numLayers - 1) - value = 0; + value = nullptr; } else if (i) // Other singletons only belong in the first layer. - value = 0; + value = nullptr; } } @@ -406,27 +442,29 @@ String StyleProperties::getLayeredShorthandValue(const StylePropertyShorthand& s || (j < size - 1 && shorthand.properties()[j + 1] == CSSPropertyWebkitMaskRepeatY && value)) { RefPtr<CSSValue> yValue; RefPtr<CSSValue> nextValue = values[j + 1]; - if (nextValue->isValueList()) - yValue = toCSSValueList(nextValue.get())->itemWithoutBoundsCheck(i); - else - yValue = nextValue; + if (nextValue) { + if (is<CSSValueList>(*nextValue)) + yValue = downcast<CSSValueList>(*nextValue).itemWithoutBoundsCheck(i); + else + yValue = nextValue; - if (!value->isPrimitiveValue() || !yValue->isPrimitiveValue()) - continue; + if (!is<CSSPrimitiveValue>(*value) || !is<CSSPrimitiveValue>(*yValue)) + continue; - CSSValueID xId = toCSSPrimitiveValue(value.get())->getValueID(); - CSSValueID yId = toCSSPrimitiveValue(yValue.get())->getValueID(); - if (xId != yId) { - if (xId == CSSValueRepeat && yId == CSSValueNoRepeat) { - useRepeatXShorthand = true; + CSSValueID xId = downcast<CSSPrimitiveValue>(*value).valueID(); + CSSValueID yId = downcast<CSSPrimitiveValue>(*yValue).valueID(); + if (xId != yId) { + if (xId == CSSValueRepeat && yId == CSSValueNoRepeat) { + useRepeatXShorthand = true; + ++j; + } else if (xId == CSSValueNoRepeat && yId == CSSValueRepeat) { + useRepeatYShorthand = true; + continue; + } + } else { + useSingleWordShorthand = true; ++j; - } else if (xId == CSSValueNoRepeat && yId == CSSValueRepeat) { - useRepeatYShorthand = true; - continue; } - } else { - useSingleWordShorthand = true; - ++j; } } } @@ -494,7 +532,7 @@ String StyleProperties::getShorthandValue(const StylePropertyShorthand& shorthan StringBuilder result; for (unsigned i = 0; i < shorthand.length(); ++i) { if (!isPropertyImplicit(shorthand.properties()[i])) { - RefPtr<CSSValue> value = getPropertyCSSValue(shorthand.properties()[i]); + RefPtr<CSSValue> value = getPropertyCSSValueInternal(shorthand.properties()[i]); if (!value) return String(); String valueText = value->cssText(); @@ -523,10 +561,10 @@ String StyleProperties::getCommonValue(const StylePropertyShorthand& shorthand) String res; bool lastPropertyWasImportant = false; for (unsigned i = 0; i < shorthand.length(); ++i) { - RefPtr<CSSValue> value = getPropertyCSSValue(shorthand.properties()[i]); - // FIXME: CSSInitialValue::cssText should generate the right value. + RefPtr<CSSValue> value = getPropertyCSSValueInternal(shorthand.properties()[i]); if (!value) return String(); + // FIXME: CSSInitialValue::cssText should generate the right value. String text = value->cssText(); if (text.isNull()) return String(); @@ -571,11 +609,24 @@ String StyleProperties::borderPropertyValue(CommonValueMode valueMode) const return result.isEmpty() ? String() : result.toString(); } -PassRefPtr<CSSValue> StyleProperties::getPropertyCSSValue(CSSPropertyID propertyID) const +RefPtr<CSSValue> StyleProperties::getPropertyCSSValue(CSSPropertyID propertyID) const +{ + return getPropertyCSSValueInternal(propertyID); +} + +RefPtr<CSSValue> StyleProperties::getPropertyCSSValueInternal(CSSPropertyID propertyID) const { int foundPropertyIndex = findPropertyIndex(propertyID); if (foundPropertyIndex == -1) - return 0; + return nullptr; + return propertyAt(foundPropertyIndex).value(); +} + +RefPtr<CSSValue> StyleProperties::getCustomPropertyCSSValue(const String& propertyName) const +{ + int foundPropertyIndex = findCustomPropertyIndex(propertyName); + if (foundPropertyIndex == -1) + return nullptr; return propertyAt(foundPropertyIndex).value(); } @@ -585,14 +636,7 @@ bool MutableStyleProperties::removeShorthandProperty(CSSPropertyID propertyID) if (!shorthand.length()) return false; - bool ret = removePropertiesInSet(shorthand.properties(), shorthand.length()); - - CSSPropertyID prefixingVariant = prefixingVariantForPropertyId(propertyID); - if (prefixingVariant == propertyID) - return ret; - - StylePropertyShorthand shorthandPrefixingVariant = shorthandForProperty(prefixingVariant); - return removePropertiesInSet(shorthandPrefixingVariant.properties(), shorthandPrefixingVariant.length()); + return removePropertiesInSet(shorthand.properties(), shorthand.length()); } bool MutableStyleProperties::removeProperty(CSSPropertyID propertyID, String* returnText) @@ -600,14 +644,14 @@ bool MutableStyleProperties::removeProperty(CSSPropertyID propertyID, String* re if (removeShorthandProperty(propertyID)) { // FIXME: Return an equivalent shorthand when possible. if (returnText) - *returnText = ""; + *returnText = emptyString(); return true; } int foundPropertyIndex = findPropertyIndex(propertyID); if (foundPropertyIndex == -1) { if (returnText) - *returnText = ""; + *returnText = emptyString(); return false; } @@ -618,17 +662,26 @@ bool MutableStyleProperties::removeProperty(CSSPropertyID propertyID, String* re // and sweeping them when the vector grows too big. m_propertyVector.remove(foundPropertyIndex); - removePrefixedOrUnprefixedProperty(propertyID); - return true; } -void MutableStyleProperties::removePrefixedOrUnprefixedProperty(CSSPropertyID propertyID) +bool MutableStyleProperties::removeCustomProperty(const String& propertyName, String* returnText) { - int foundPropertyIndex = findPropertyIndex(prefixingVariantForPropertyId(propertyID)); - if (foundPropertyIndex == -1) - return; + int foundPropertyIndex = findCustomPropertyIndex(propertyName); + if (foundPropertyIndex == -1) { + if (returnText) + *returnText = emptyString(); + return false; + } + + if (returnText) + *returnText = propertyAt(foundPropertyIndex).value()->cssText(); + + // A more efficient removal strategy would involve marking entries as empty + // and sweeping them when the vector grows too big. m_propertyVector.remove(foundPropertyIndex); + + return true; } bool StyleProperties::propertyIsImportant(CSSPropertyID propertyID) const @@ -648,6 +701,14 @@ bool StyleProperties::propertyIsImportant(CSSPropertyID propertyID) const return true; } +bool StyleProperties::customPropertyIsImportant(const String& propertyName) const +{ + int foundPropertyIndex = findCustomPropertyIndex(propertyName); + if (foundPropertyIndex != -1) + return propertyAt(foundPropertyIndex).isImportant(); + return false; +} + String StyleProperties::getPropertyShorthand(CSSPropertyID propertyID) const { int foundPropertyIndex = findPropertyIndex(propertyID); @@ -664,110 +725,122 @@ bool StyleProperties::isPropertyImplicit(CSSPropertyID propertyID) const return propertyAt(foundPropertyIndex).isImplicit(); } -bool MutableStyleProperties::setProperty(CSSPropertyID propertyID, const String& value, bool important, StyleSheetContents* contextStyleSheet) +bool MutableStyleProperties::setProperty(CSSPropertyID propertyID, const String& value, bool important, CSSParserContext parserContext) { // Setting the value to an empty string just removes the property in both IE and Gecko. // Setting it to null seems to produce less consistent results, but we treat it just the same. if (value.isEmpty()) return removeProperty(propertyID); + parserContext.mode = cssParserMode(); + // When replacing an existing property value, this moves the property to the end of the list. // Firefox preserves the position, and MSIE moves the property to the beginning. - return CSSParser::parseValue(this, propertyID, value, important, cssParserMode(), contextStyleSheet); + return CSSParser::parseValue(*this, propertyID, value, important, parserContext) == CSSParser::ParseResult::Changed; } -void MutableStyleProperties::setProperty(CSSPropertyID propertyID, PassRefPtr<CSSValue> prpValue, bool important) +bool MutableStyleProperties::setProperty(CSSPropertyID propertyID, const String& value, bool important) +{ + CSSParserContext parserContext(cssParserMode()); + return setProperty(propertyID, value, important, parserContext); +} + +bool MutableStyleProperties::setCustomProperty(const String& propertyName, const String& value, bool important, CSSParserContext parserContext) +{ + // Setting the value to an empty string just removes the property in both IE and Gecko. + // Setting it to null seems to produce less consistent results, but we treat it just the same. + if (value.isEmpty()) + return removeCustomProperty(propertyName); + + parserContext.mode = cssParserMode(); + // When replacing an existing property value, this moves the property to the end of the list. + // Firefox preserves the position, and MSIE moves the property to the beginning. + return CSSParser::parseCustomPropertyValue(*this, propertyName, value, important, parserContext) == CSSParser::ParseResult::Changed; +} + +void MutableStyleProperties::setProperty(CSSPropertyID propertyID, RefPtr<CSSValue>&& value, bool important) { StylePropertyShorthand shorthand = shorthandForProperty(propertyID); if (!shorthand.length()) { - setProperty(CSSProperty(propertyID, prpValue, important)); + setProperty(CSSProperty(propertyID, WTFMove(value), important)); return; } removePropertiesInSet(shorthand.properties(), shorthand.length()); - RefPtr<CSSValue> value = prpValue; for (unsigned i = 0; i < shorthand.length(); ++i) - m_propertyVector.append(CSSProperty(shorthand.properties()[i], value, important)); + m_propertyVector.append(CSSProperty(shorthand.properties()[i], value.copyRef(), important)); } -void MutableStyleProperties::setProperty(const CSSProperty& property, CSSProperty* slot) +bool MutableStyleProperties::setProperty(const CSSProperty& property, CSSProperty* slot) { if (!removeShorthandProperty(property.id())) { - CSSProperty* toReplace = slot ? slot : findCSSPropertyWithID(property.id()); + CSSProperty* toReplace = slot; + if (!slot) { + if (property.id() == CSSPropertyCustom) { + if (property.value()) + toReplace = findCustomCSSPropertyWithName(downcast<CSSCustomPropertyValue>(*property.value()).name()); + } else + toReplace = findCSSPropertyWithID(property.id()); + } + if (toReplace) { + if (*toReplace == property) + return false; + *toReplace = property; - setPrefixingVariantProperty(property); - return; + return true; } } - appendPrefixingVariantProperty(property); -} - -static unsigned getIndexInShorthandVectorForPrefixingVariant(const CSSProperty& property, CSSPropertyID prefixingVariant) -{ - if (!property.isSetFromShorthand()) - return 0; - CSSPropertyID prefixedShorthand = prefixingVariantForPropertyId(property.shorthandID()); - return indexOfShorthandForLonghand(prefixedShorthand, matchingShorthandsForLonghand(prefixingVariant)); -} - -void MutableStyleProperties::appendPrefixingVariantProperty(const CSSProperty& property) -{ m_propertyVector.append(property); - CSSPropertyID prefixingVariant = prefixingVariantForPropertyId(property.id()); - if (prefixingVariant == property.id()) - return; - - m_propertyVector.append(CSSProperty(prefixingVariant, property.value(), property.isImportant(), property.isSetFromShorthand(), getIndexInShorthandVectorForPrefixingVariant(property, prefixingVariant), property.metadata().m_implicit)); -} - -void MutableStyleProperties::setPrefixingVariantProperty(const CSSProperty& property) -{ - CSSPropertyID prefixingVariant = prefixingVariantForPropertyId(property.id()); - CSSProperty* toReplace = findCSSPropertyWithID(prefixingVariant); - if (toReplace && prefixingVariant != property.id()) - *toReplace = CSSProperty(prefixingVariant, property.value(), property.isImportant(), property.isSetFromShorthand(), getIndexInShorthandVectorForPrefixingVariant(property, prefixingVariant), property.metadata().m_implicit); + return true; } bool MutableStyleProperties::setProperty(CSSPropertyID propertyID, CSSValueID identifier, bool important) { - setProperty(CSSProperty(propertyID, cssValuePool().createIdentifierValue(identifier), important)); - return true; + return setProperty(CSSProperty(propertyID, CSSValuePool::singleton().createIdentifierValue(identifier), important)); } bool MutableStyleProperties::setProperty(CSSPropertyID propertyID, CSSPropertyID identifier, bool important) { - setProperty(CSSProperty(propertyID, cssValuePool().createIdentifierValue(identifier), important)); - return true; + return setProperty(CSSProperty(propertyID, CSSValuePool::singleton().createIdentifierValue(identifier), important)); } -void MutableStyleProperties::parseDeclaration(const String& styleDeclaration, StyleSheetContents* contextStyleSheet) +bool MutableStyleProperties::parseDeclaration(const String& styleDeclaration, CSSParserContext context) { + auto oldProperties = WTFMove(m_propertyVector); m_propertyVector.clear(); - CSSParserContext context(cssParserMode()); - if (contextStyleSheet) { - context = contextStyleSheet->parserContext(); - context.mode = cssParserMode(); - } + context.mode = cssParserMode(); + CSSParser parser(context); - parser.parseDeclaration(this, styleDeclaration, 0, contextStyleSheet); + parser.parseDeclaration(*this, styleDeclaration); + + // We could do better. Just changing property order does not require style invalidation. + return oldProperties != m_propertyVector; } -void MutableStyleProperties::addParsedProperties(const Vector<CSSProperty>& properties) +bool MutableStyleProperties::addParsedProperties(const ParsedPropertyVector& properties) { + bool anyChanged = false; m_propertyVector.reserveCapacity(m_propertyVector.size() + properties.size()); - for (unsigned i = 0; i < properties.size(); ++i) - addParsedProperty(properties[i]); + for (const auto& property : properties) { + if (addParsedProperty(property)) + anyChanged = true; + } + + return anyChanged; } -void MutableStyleProperties::addParsedProperty(const CSSProperty& property) +bool MutableStyleProperties::addParsedProperty(const CSSProperty& property) { - // Only add properties that have no !important counterpart present - if (!propertyIsImportant(property.id()) || property.isImportant()) - setProperty(property); + if (property.id() == CSSPropertyCustom) { + if ((property.value() && !customPropertyIsImportant(downcast<CSSCustomPropertyValue>(*property.value()).name())) || property.isImportant()) + return setProperty(property); + return false; + } + return setProperty(property); } String StyleProperties::asText() const @@ -790,146 +863,167 @@ String StyleProperties::asText() const CSSPropertyID shorthandPropertyID = CSSPropertyInvalid; CSSPropertyID borderFallbackShorthandProperty = CSSPropertyInvalid; String value; - - switch (propertyID) { - case CSSPropertyBackgroundPositionX: - positionXPropertyIndex = n; - continue; - case CSSPropertyBackgroundPositionY: - positionYPropertyIndex = n; - continue; - case CSSPropertyBackgroundRepeatX: - repeatXPropertyIndex = n; - continue; - case CSSPropertyBackgroundRepeatY: - repeatYPropertyIndex = n; - continue; - case CSSPropertyBorderTopWidth: - case CSSPropertyBorderRightWidth: - case CSSPropertyBorderBottomWidth: - case CSSPropertyBorderLeftWidth: - if (!borderFallbackShorthandProperty) - borderFallbackShorthandProperty = CSSPropertyBorderWidth; - FALLTHROUGH; - case CSSPropertyBorderTopStyle: - case CSSPropertyBorderRightStyle: - case CSSPropertyBorderBottomStyle: - case CSSPropertyBorderLeftStyle: - if (!borderFallbackShorthandProperty) - borderFallbackShorthandProperty = CSSPropertyBorderStyle; - FALLTHROUGH; - case CSSPropertyBorderTopColor: - case CSSPropertyBorderRightColor: - case CSSPropertyBorderBottomColor: - case CSSPropertyBorderLeftColor: - if (!borderFallbackShorthandProperty) - borderFallbackShorthandProperty = CSSPropertyBorderColor; - - // FIXME: Deal with cases where only some of border-(top|right|bottom|left) are specified. - if (!shorthandPropertyAppeared.test(CSSPropertyBorder - firstCSSProperty)) { - value = borderPropertyValue(ReturnNullOnUncommonValues); - if (value.isNull()) - shorthandPropertyAppeared.set(CSSPropertyBorder - firstCSSProperty); - else + + if (property.value() && property.value()->isPendingSubstitutionValue()) { + auto& substitutionValue = downcast<CSSPendingSubstitutionValue>(*property.value()); + shorthandPropertyID = substitutionValue.shorthandPropertyId(); + value = substitutionValue.shorthandValue()->cssText(); + } else { + switch (propertyID) { + case CSSPropertyAnimationName: + case CSSPropertyAnimationDuration: + case CSSPropertyAnimationTimingFunction: + case CSSPropertyAnimationDelay: + case CSSPropertyAnimationIterationCount: + case CSSPropertyAnimationDirection: + case CSSPropertyAnimationFillMode: + case CSSPropertyAnimationPlayState: + shorthandPropertyID = CSSPropertyAnimation; + break; + case CSSPropertyBackgroundPositionX: + positionXPropertyIndex = n; + continue; + case CSSPropertyBackgroundPositionY: + positionYPropertyIndex = n; + continue; + case CSSPropertyBackgroundRepeatX: + repeatXPropertyIndex = n; + continue; + case CSSPropertyBackgroundRepeatY: + repeatYPropertyIndex = n; + continue; + case CSSPropertyBorderTopWidth: + case CSSPropertyBorderRightWidth: + case CSSPropertyBorderBottomWidth: + case CSSPropertyBorderLeftWidth: + if (!borderFallbackShorthandProperty) + borderFallbackShorthandProperty = CSSPropertyBorderWidth; + FALLTHROUGH; + case CSSPropertyBorderTopStyle: + case CSSPropertyBorderRightStyle: + case CSSPropertyBorderBottomStyle: + case CSSPropertyBorderLeftStyle: + if (!borderFallbackShorthandProperty) + borderFallbackShorthandProperty = CSSPropertyBorderStyle; + FALLTHROUGH; + case CSSPropertyBorderTopColor: + case CSSPropertyBorderRightColor: + case CSSPropertyBorderBottomColor: + case CSSPropertyBorderLeftColor: + if (!borderFallbackShorthandProperty) + borderFallbackShorthandProperty = CSSPropertyBorderColor; + + // FIXME: Deal with cases where only some of border-(top|right|bottom|left) are specified. + ASSERT(CSSPropertyBorder - firstCSSProperty < shorthandPropertyAppeared.size()); + if (!shorthandPropertyAppeared[CSSPropertyBorder - firstCSSProperty]) { + value = borderPropertyValue(ReturnNullOnUncommonValues); + if (value.isNull()) + shorthandPropertyAppeared.set(CSSPropertyBorder - firstCSSProperty); + else + shorthandPropertyID = CSSPropertyBorder; + } else if (shorthandPropertyUsed[CSSPropertyBorder - firstCSSProperty]) shorthandPropertyID = CSSPropertyBorder; - } else if (shorthandPropertyUsed.test(CSSPropertyBorder - firstCSSProperty)) - shorthandPropertyID = CSSPropertyBorder; - if (!shorthandPropertyID) - shorthandPropertyID = borderFallbackShorthandProperty; - break; - case CSSPropertyWebkitBorderHorizontalSpacing: - case CSSPropertyWebkitBorderVerticalSpacing: - shorthandPropertyID = CSSPropertyBorderSpacing; - break; - case CSSPropertyFontFamily: - case CSSPropertyLineHeight: - case CSSPropertyFontSize: - case CSSPropertyFontStyle: - case CSSPropertyFontVariant: - case CSSPropertyFontWeight: - // Don't use CSSPropertyFont because old UAs can't recognize them but are important for editing. - break; - case CSSPropertyListStyleType: - case CSSPropertyListStylePosition: - case CSSPropertyListStyleImage: - shorthandPropertyID = CSSPropertyListStyle; - break; - case CSSPropertyMarginTop: - case CSSPropertyMarginRight: - case CSSPropertyMarginBottom: - case CSSPropertyMarginLeft: - shorthandPropertyID = CSSPropertyMargin; - break; - case CSSPropertyOutlineWidth: - case CSSPropertyOutlineStyle: - case CSSPropertyOutlineColor: - shorthandPropertyID = CSSPropertyOutline; - break; - case CSSPropertyOverflowX: - case CSSPropertyOverflowY: - shorthandPropertyID = CSSPropertyOverflow; - break; - case CSSPropertyPaddingTop: - case CSSPropertyPaddingRight: - case CSSPropertyPaddingBottom: - case CSSPropertyPaddingLeft: - shorthandPropertyID = CSSPropertyPadding; - break; - case CSSPropertyTransitionProperty: - case CSSPropertyTransitionDuration: - case CSSPropertyTransitionTimingFunction: - case CSSPropertyTransitionDelay: - shorthandPropertyID = CSSPropertyTransition; - break; - case CSSPropertyWebkitAnimationName: - case CSSPropertyWebkitAnimationDuration: - case CSSPropertyWebkitAnimationTimingFunction: - case CSSPropertyWebkitAnimationDelay: - case CSSPropertyWebkitAnimationIterationCount: - case CSSPropertyWebkitAnimationDirection: - case CSSPropertyWebkitAnimationFillMode: - shorthandPropertyID = CSSPropertyWebkitAnimation; - break; - case CSSPropertyWebkitFlexDirection: - case CSSPropertyWebkitFlexWrap: - shorthandPropertyID = CSSPropertyWebkitFlexFlow; - break; - case CSSPropertyWebkitFlexBasis: - case CSSPropertyWebkitFlexGrow: - case CSSPropertyWebkitFlexShrink: - shorthandPropertyID = CSSPropertyWebkitFlex; - break; - case CSSPropertyWebkitMaskPositionX: - case CSSPropertyWebkitMaskPositionY: - case CSSPropertyWebkitMaskRepeatX: - case CSSPropertyWebkitMaskRepeatY: - case CSSPropertyWebkitMaskImage: - case CSSPropertyWebkitMaskRepeat: - case CSSPropertyWebkitMaskPosition: - case CSSPropertyWebkitMaskClip: - case CSSPropertyWebkitMaskOrigin: - shorthandPropertyID = CSSPropertyWebkitMask; - break; - case CSSPropertyWebkitTransformOriginX: - case CSSPropertyWebkitTransformOriginY: - case CSSPropertyWebkitTransformOriginZ: - shorthandPropertyID = CSSPropertyWebkitTransformOrigin; - break; - case CSSPropertyWebkitTransitionProperty: - case CSSPropertyWebkitTransitionDuration: - case CSSPropertyWebkitTransitionTimingFunction: - case CSSPropertyWebkitTransitionDelay: - shorthandPropertyID = CSSPropertyWebkitTransition; - break; - default: - break; + if (!shorthandPropertyID) + shorthandPropertyID = borderFallbackShorthandProperty; + break; + case CSSPropertyWebkitBorderHorizontalSpacing: + case CSSPropertyWebkitBorderVerticalSpacing: + shorthandPropertyID = CSSPropertyBorderSpacing; + break; + case CSSPropertyFontFamily: + case CSSPropertyLineHeight: + case CSSPropertyFontSize: + case CSSPropertyFontStyle: + case CSSPropertyFontVariantCaps: + case CSSPropertyFontWeight: + // Don't use CSSPropertyFont because old UAs can't recognize them but are important for editing. + break; + case CSSPropertyListStyleType: + case CSSPropertyListStylePosition: + case CSSPropertyListStyleImage: + shorthandPropertyID = CSSPropertyListStyle; + break; + case CSSPropertyMarginTop: + case CSSPropertyMarginRight: + case CSSPropertyMarginBottom: + case CSSPropertyMarginLeft: + shorthandPropertyID = CSSPropertyMargin; + break; + case CSSPropertyOutlineWidth: + case CSSPropertyOutlineStyle: + case CSSPropertyOutlineColor: + shorthandPropertyID = CSSPropertyOutline; + break; + case CSSPropertyOverflowX: + case CSSPropertyOverflowY: + shorthandPropertyID = CSSPropertyOverflow; + break; + case CSSPropertyPaddingTop: + case CSSPropertyPaddingRight: + case CSSPropertyPaddingBottom: + case CSSPropertyPaddingLeft: + shorthandPropertyID = CSSPropertyPadding; + break; +#if ENABLE(CSS_SCROLL_SNAP) + case CSSPropertyScrollPaddingTop: + case CSSPropertyScrollPaddingRight: + case CSSPropertyScrollPaddingBottom: + case CSSPropertyScrollPaddingLeft: + shorthandPropertyID = CSSPropertyScrollPadding; + break; + case CSSPropertyScrollSnapMarginTop: + case CSSPropertyScrollSnapMarginRight: + case CSSPropertyScrollSnapMarginBottom: + case CSSPropertyScrollSnapMarginLeft: + shorthandPropertyID = CSSPropertyScrollSnapMargin; + break; +#endif + case CSSPropertyTransitionProperty: + case CSSPropertyTransitionDuration: + case CSSPropertyTransitionTimingFunction: + case CSSPropertyTransitionDelay: + shorthandPropertyID = CSSPropertyTransition; + break; + case CSSPropertyFlexDirection: + case CSSPropertyFlexWrap: + shorthandPropertyID = CSSPropertyFlexFlow; + break; + case CSSPropertyFlexBasis: + case CSSPropertyFlexGrow: + case CSSPropertyFlexShrink: + shorthandPropertyID = CSSPropertyFlex; + break; + case CSSPropertyWebkitMaskPositionX: + case CSSPropertyWebkitMaskPositionY: + case CSSPropertyWebkitMaskRepeatX: + case CSSPropertyWebkitMaskRepeatY: + case CSSPropertyWebkitMaskImage: + case CSSPropertyWebkitMaskRepeat: + case CSSPropertyWebkitMaskPosition: + case CSSPropertyWebkitMaskClip: + case CSSPropertyWebkitMaskOrigin: + shorthandPropertyID = CSSPropertyWebkitMask; + break; + case CSSPropertyPerspectiveOriginX: + case CSSPropertyPerspectiveOriginY: + shorthandPropertyID = CSSPropertyPerspectiveOrigin; + break; + case CSSPropertyTransformOriginX: + case CSSPropertyTransformOriginY: + case CSSPropertyTransformOriginZ: + shorthandPropertyID = CSSPropertyTransformOrigin; + break; + default: + break; + } } unsigned shortPropertyIndex = shorthandPropertyID - firstCSSProperty; if (shorthandPropertyID) { - if (shorthandPropertyUsed.test(shortPropertyIndex)) + ASSERT(shortPropertyIndex < shorthandPropertyUsed.size()); + if (shorthandPropertyUsed[shortPropertyIndex]) continue; - if (!shorthandPropertyAppeared.test(shortPropertyIndex) && value.isNull()) + if (!shorthandPropertyAppeared[shortPropertyIndex] && value.isNull()) value = getPropertyValue(shorthandPropertyID); shorthandPropertyAppeared.set(shortPropertyIndex); } @@ -940,12 +1034,17 @@ String StyleProperties::asText() const } else value = property.value()->cssText(); - if (value == "initial" && !CSSProperty::isInheritedProperty(propertyID)) + if (propertyID != CSSPropertyCustom && value == "initial" && !CSSProperty::isInheritedProperty(propertyID)) continue; if (numDecls++) result.append(' '); - result.append(getPropertyName(propertyID)); + + if (propertyID == CSSPropertyCustom) + result.append(downcast<CSSCustomPropertyValue>(*property.value()).name()); + else + result.append(getPropertyName(propertyID)); + result.appendLiteral(": "); result.append(value); if (property.isImportant()) @@ -1024,7 +1123,7 @@ String StyleProperties::asText() const bool StyleProperties::hasCSSOMWrapper() const { - return m_isMutable && static_cast<const MutableStyleProperties*>(this)->m_cssomWrapper; + return is<MutableStyleProperties>(*this) && downcast<MutableStyleProperties>(*this).m_cssomWrapper; } void MutableStyleProperties::mergeAndOverrideOnConflict(const StyleProperties& other) @@ -1034,18 +1133,11 @@ void MutableStyleProperties::mergeAndOverrideOnConflict(const StyleProperties& o addParsedProperty(other.propertyAt(i).toCSSProperty()); } -void StyleProperties::addSubresourceStyleURLs(ListHashSet<URL>& urls, StyleSheetContents* contextStyleSheet) const -{ - unsigned size = propertyCount(); - for (unsigned i = 0; i < size; ++i) - propertyAt(i).value()->addSubresourceStyleURLs(urls, contextStyleSheet); -} - -bool StyleProperties::hasFailedOrCanceledSubresources() const +bool StyleProperties::traverseSubresources(const std::function<bool (const CachedResource&)>& handler) const { unsigned size = propertyCount(); for (unsigned i = 0; i < size; ++i) { - if (propertyAt(i).value()->hasFailedOrCanceledSubresources()) + if (propertyAt(i).value()->traverseSubresources(handler)) return true; } return false; @@ -1057,15 +1149,15 @@ static const CSSPropertyID blockProperties[] = { CSSPropertyOrphans, CSSPropertyOverflow, // This can be also be applied to replaced elements CSSPropertyWebkitAspectRatio, - CSSPropertyWebkitColumnCount, - CSSPropertyWebkitColumnGap, - CSSPropertyWebkitColumnRuleColor, - CSSPropertyWebkitColumnRuleStyle, - CSSPropertyWebkitColumnRuleWidth, + CSSPropertyColumnCount, + CSSPropertyColumnGap, + CSSPropertyColumnRuleColor, + CSSPropertyColumnRuleStyle, + CSSPropertyColumnRuleWidth, CSSPropertyWebkitColumnBreakBefore, CSSPropertyWebkitColumnBreakAfter, CSSPropertyWebkitColumnBreakInside, - CSSPropertyWebkitColumnWidth, + CSSPropertyColumnWidth, CSSPropertyPageBreakAfter, CSSPropertyPageBreakBefore, CSSPropertyPageBreakInside, @@ -1090,7 +1182,7 @@ void MutableStyleProperties::clear() const unsigned numBlockProperties = WTF_ARRAY_LENGTH(blockProperties); -PassRef<MutableStyleProperties> StyleProperties::copyBlockProperties() const +Ref<MutableStyleProperties> StyleProperties::copyBlockProperties() const { return copyPropertiesInSet(blockProperties, numBlockProperties); } @@ -1110,23 +1202,10 @@ bool MutableStyleProperties::removePropertiesInSet(const CSSPropertyID* set, uns for (unsigned i = 0; i < length; ++i) toRemove.add(set[i]); - Vector<CSSProperty> newProperties; - newProperties.reserveInitialCapacity(m_propertyVector.size()); - - unsigned size = m_propertyVector.size(); - for (unsigned n = 0; n < size; ++n) { - const CSSProperty& property = m_propertyVector.at(n); + return m_propertyVector.removeAllMatching([&toRemove] (const CSSProperty& property) { // Not quite sure if the isImportant test is needed but it matches the existing behavior. - if (!property.isImportant()) { - if (toRemove.contains(property.id())) - continue; - } - newProperties.append(property); - } - - bool changed = newProperties.size() != m_propertyVector.size(); - m_propertyVector = newProperties; - return changed; + return !property.isImportant() && toRemove.contains(property.id()); + }) > 0; } int ImmutableStyleProperties::findPropertyIndex(CSSPropertyID propertyID) const @@ -1155,6 +1234,40 @@ int MutableStyleProperties::findPropertyIndex(CSSPropertyID propertyID) const return -1; } +int ImmutableStyleProperties::findCustomPropertyIndex(const String& propertyName) const +{ + // Convert the propertyID into an uint16_t to compare it with the metadata's m_propertyID to avoid + // the compiler converting it to an int multiple times in the loop. + for (int n = m_arraySize - 1 ; n >= 0; --n) { + if (metadataArray()[n].m_propertyID == CSSPropertyCustom) { + // We found a custom property. See if the name matches. + if (!valueArray()[n]) + continue; + if (downcast<CSSCustomPropertyValue>(*valueArray()[n]).name() == propertyName) + return n; + } + } + + return -1; +} + +int MutableStyleProperties::findCustomPropertyIndex(const String& propertyName) const +{ + // Convert the propertyID into an uint16_t to compare it with the metadata's m_propertyID to avoid + // the compiler converting it to an int multiple times in the loop. + for (int n = m_propertyVector.size() - 1 ; n >= 0; --n) { + if (m_propertyVector.at(n).metadata().m_propertyID == CSSPropertyCustom) { + // We found a custom property. See if the name matches. + if (!m_propertyVector.at(n).value()) + continue; + if (downcast<CSSCustomPropertyValue>(*m_propertyVector.at(n).value()).name() == propertyName) + return n; + } + } + + return -1; +} + CSSProperty* MutableStyleProperties::findCSSPropertyWithID(CSSPropertyID propertyID) { int foundPropertyIndex = findPropertyIndex(propertyID); @@ -1163,6 +1276,14 @@ CSSProperty* MutableStyleProperties::findCSSPropertyWithID(CSSPropertyID propert return &m_propertyVector.at(foundPropertyIndex); } +CSSProperty* MutableStyleProperties::findCustomCSSPropertyWithName(const String& propertyName) +{ + int foundPropertyIndex = findCustomPropertyIndex(propertyName); + if (foundPropertyIndex == -1) + return 0; + return &m_propertyVector.at(foundPropertyIndex); +} + bool StyleProperties::propertyMatches(CSSPropertyID propertyID, const CSSValue* propertyValue) const { int foundPropertyIndex = findPropertyIndex(propertyID); @@ -1171,47 +1292,18 @@ bool StyleProperties::propertyMatches(CSSPropertyID propertyID, const CSSValue* return propertyAt(foundPropertyIndex).value()->equals(*propertyValue); } -void MutableStyleProperties::removeEquivalentProperties(const StyleProperties* style) -{ - Vector<CSSPropertyID> propertiesToRemove; - unsigned size = m_propertyVector.size(); - for (unsigned i = 0; i < size; ++i) { - PropertyReference property = propertyAt(i); - if (style->propertyMatches(property.id(), property.value())) - propertiesToRemove.append(property.id()); - } - // FIXME: This should use mass removal. - for (unsigned i = 0; i < propertiesToRemove.size(); ++i) - removeProperty(propertiesToRemove[i]); -} - -void MutableStyleProperties::removeEquivalentProperties(const ComputedStyleExtractor* computedStyle) -{ - Vector<CSSPropertyID> propertiesToRemove; - unsigned size = m_propertyVector.size(); - for (unsigned i = 0; i < size; ++i) { - PropertyReference property = propertyAt(i); - if (computedStyle->propertyMatches(property.id(), property.value())) - propertiesToRemove.append(property.id()); - } - // FIXME: This should use mass removal. - for (unsigned i = 0; i < propertiesToRemove.size(); ++i) - removeProperty(propertiesToRemove[i]); -} - -PassRef<MutableStyleProperties> StyleProperties::mutableCopy() const +Ref<MutableStyleProperties> StyleProperties::mutableCopy() const { return adoptRef(*new MutableStyleProperties(*this)); } -PassRef<MutableStyleProperties> StyleProperties::copyPropertiesInSet(const CSSPropertyID* set, unsigned length) const +Ref<MutableStyleProperties> StyleProperties::copyPropertiesInSet(const CSSPropertyID* set, unsigned length) const { Vector<CSSProperty, 256> list; list.reserveInitialCapacity(length); for (unsigned i = 0; i < length; ++i) { - RefPtr<CSSValue> value = getPropertyCSSValue(set[i]); - if (value) - list.append(CSSProperty(set[i], value.release(), false)); + if (auto value = getPropertyCSSValueInternal(set[i])) + list.uncheckedAppend(CSSProperty(set[i], WTFMove(value), false)); } return MutableStyleProperties::create(list.data(), list.size()); } @@ -1261,18 +1353,20 @@ void StyleProperties::showStyle() } #endif -PassRef<MutableStyleProperties> MutableStyleProperties::create(CSSParserMode cssParserMode) +Ref<MutableStyleProperties> MutableStyleProperties::create(CSSParserMode cssParserMode) { return adoptRef(*new MutableStyleProperties(cssParserMode)); } -PassRef<MutableStyleProperties> MutableStyleProperties::create(const CSSProperty* properties, unsigned count) +Ref<MutableStyleProperties> MutableStyleProperties::create(const CSSProperty* properties, unsigned count) { return adoptRef(*new MutableStyleProperties(properties, count)); } String StyleProperties::PropertyReference::cssName() const { + if (id() == CSSPropertyCustom) + return downcast<CSSCustomPropertyValue>(*value()).name(); return getPropertyNameString(id()); } @@ -1281,12 +1375,34 @@ String StyleProperties::PropertyReference::cssText() const StringBuilder result; result.append(cssName()); result.appendLiteral(": "); - result.append(propertyValue()->cssText()); + result.append(m_value->cssText()); if (isImportant()) result.appendLiteral(" !important"); result.append(';'); return result.toString(); } + +Ref<DeferredStyleProperties> DeferredStyleProperties::create(const CSSParserTokenRange& tokenRange, CSSDeferredParser& parser) +{ + return adoptRef(*new DeferredStyleProperties(tokenRange, parser)); +} +DeferredStyleProperties::DeferredStyleProperties(const CSSParserTokenRange& range, CSSDeferredParser& parser) + : StylePropertiesBase(parser.mode(), DeferredPropertiesType) + , m_parser(parser) +{ + size_t length = range.end() - range.begin(); + m_tokens.reserveCapacity(length); + m_tokens.append(range.begin(), length); +} + +DeferredStyleProperties::~DeferredStyleProperties() +{ +} + +Ref<ImmutableStyleProperties> DeferredStyleProperties::parseDeferredProperties() +{ + return m_parser->parseDeclaration(m_tokens); +} } // namespace WebCore |