Add modern API for overriding the page's specified viewport configuration
[WebKit-https.git] / Source / WebCore / css / StyleProperties.h
index e1b42c4..e8572e2 100644 (file)
  * Boston, MA 02110-1301, USA.
  */
 
-#ifndef StyleProperties_h
-#define StyleProperties_h
+#pragma once
 
-#include "CSSParserMode.h"
-#include "CSSPrimitiveValue.h"
+#include "CSSParserContext.h"
+#include "CSSParserTokenRange.h"
 #include "CSSProperty.h"
-#include "CSSPropertyNames.h"
 #include "CSSValueKeywords.h"
 #include <memory>
-#include <wtf/ListHashSet.h>
+#include <wtf/Function.h>
+#include <wtf/TypeCasts.h>
 #include <wtf/Vector.h>
 #include <wtf/text/WTFString.h>
 
 namespace WebCore {
 
-class CSSRule;
+class CSSDeferredParser;
 class CSSStyleDeclaration;
-class ComputedStyleExtractor;
+class CachedResource;
+class Color;
 class ImmutableStyleProperties;
-class URL;
 class MutableStyleProperties;
 class PropertySetCSSStyleDeclaration;
 class StyledElement;
 class StylePropertyShorthand;
 class StyleSheetContents;
 
-class StyleProperties : public RefCounted<StyleProperties> {
-    friend class PropertyReference;
+enum StylePropertiesType { ImmutablePropertiesType, MutablePropertiesType, DeferredPropertiesType };
+    
+class StylePropertiesBase : public RefCounted<StylePropertiesBase> {
 public:
     // Override RefCounted's deref() to ensure operator delete is called on
     // the appropriate subclass type.
     void deref();
+    
+    StylePropertiesType type() const { return static_cast<StylePropertiesType>(m_type); }
 
+    CSSParserMode cssParserMode() const { return static_cast<CSSParserMode>(m_cssParserMode); }
+
+protected:
+    StylePropertiesBase(CSSParserMode cssParserMode, StylePropertiesType type)
+        : m_cssParserMode(cssParserMode)
+        , m_type(type)
+        , m_arraySize(0)
+    { }
+    
+    StylePropertiesBase(CSSParserMode cssParserMode, unsigned immutableArraySize)
+        : m_cssParserMode(cssParserMode)
+        , m_type(ImmutablePropertiesType)
+        , m_arraySize(immutableArraySize)
+    { }
+    
+    unsigned m_cssParserMode : 3;
+    mutable unsigned m_type : 2;
+    unsigned m_arraySize : 27;
+};
+
+class StyleProperties : public StylePropertiesBase {
+    friend class PropertyReference;
+public:
     class PropertyReference {
     public:
-        PropertyReference(const StyleProperties& propertySet, unsigned index)
-            : m_propertySet(propertySet)
-            , m_index(index)
-        {
-        }
+        PropertyReference(const StylePropertyMetadata& metadata, const CSSValue* value)
+            : m_metadata(metadata)
+            , m_value(value)
+        { }
 
-        CSSPropertyID id() const { return static_cast<CSSPropertyID>(propertyMetadata().m_propertyID); }
-        CSSPropertyID shorthandID() const { return propertyMetadata().shorthandID(); }
+        CSSPropertyID id() const { return static_cast<CSSPropertyID>(m_metadata.m_propertyID); }
+        CSSPropertyID shorthandID() const { return m_metadata.shorthandID(); }
 
-        bool isImportant() const { return propertyMetadata().m_important; }
-        bool isInherited() const { return propertyMetadata().m_inherited; }
-        bool isImplicit() const { return propertyMetadata().m_implicit; }
+        bool isImportant() const { return m_metadata.m_important; }
+        bool isInherited() const { return m_metadata.m_inherited; }
+        bool isImplicit() const { return m_metadata.m_implicit; }
 
         String cssName() const;
         String cssText() const;
 
-        const CSSValue* value() const { return propertyValue(); }
+        const CSSValue* value() const { return m_value; }
         // FIXME: We should try to remove this mutable overload.
-        CSSValue* value() { return const_cast<CSSValue*>(propertyValue()); }
+        CSSValue* value() { return const_cast<CSSValue*>(m_value); }
 
         // FIXME: Remove this.
-        CSSProperty toCSSProperty() const { return CSSProperty(id(), const_cast<CSSValue*>(propertyValue()), isImportant(), propertyMetadata().m_isSetFromShorthand, propertyMetadata().m_indexInShorthandsVector, isImplicit()); }
-        const StylePropertyMetadata& propertyMetadata() const;
+        CSSProperty toCSSProperty() const { return CSSProperty(id(), const_cast<CSSValue*>(m_value), isImportant(), m_metadata.m_isSetFromShorthand, m_metadata.m_indexInShorthandsVector, isImplicit()); }
 
     private:
-        const CSSValue* propertyValue() const;
-
-        const StyleProperties& m_propertySet;
-        unsigned m_index;
+        const StylePropertyMetadata& m_metadata;
+        const CSSValue* m_value;
     };
 
     unsigned propertyCount() const;
-    bool isEmpty() const;
-    PropertyReference propertyAt(unsigned index) const { return PropertyReference(*this, index); }
+    bool isEmpty() const { return !propertyCount(); }
+    PropertyReference propertyAt(unsigned) const;
+
+    WEBCORE_EXPORT RefPtr<CSSValue> getPropertyCSSValue(CSSPropertyID) const;
+    WEBCORE_EXPORT String getPropertyValue(CSSPropertyID) const;
+
+    WEBCORE_EXPORT Optional<Color> propertyAsColor(CSSPropertyID) const;
+    WEBCORE_EXPORT CSSValueID propertyAsValueID(CSSPropertyID) const;
 
-    PassRefPtr<CSSValue> getPropertyCSSValue(CSSPropertyID) const;
-    String getPropertyValue(CSSPropertyID) const;
     bool propertyIsImportant(CSSPropertyID) const;
     String getPropertyShorthand(CSSPropertyID) const;
     bool isPropertyImplicit(CSSPropertyID) const;
 
-    PassRef<MutableStyleProperties> copyBlockProperties() const;
+    RefPtr<CSSValue> getCustomPropertyCSSValue(const String& propertyName) const;
+    String getCustomPropertyValue(const String& propertyName) const;
+    bool customPropertyIsImportant(const String& propertyName) const;
 
-    CSSParserMode cssParserMode() const { return static_cast<CSSParserMode>(m_cssParserMode); }
-
-    void addSubresourceStyleURLs(ListHashSet<URL>&, StyleSheetContents* contextStyleSheet) const;
+    Ref<MutableStyleProperties> copyBlockProperties() const;
 
-    PassRef<MutableStyleProperties> mutableCopy() const;
-    PassRef<ImmutableStyleProperties> immutableCopyIfNeeded() const;
+    WEBCORE_EXPORT Ref<MutableStyleProperties> mutableCopy() const;
+    Ref<ImmutableStyleProperties> immutableCopyIfNeeded() const;
 
-    PassRef<MutableStyleProperties> copyPropertiesInSet(const CSSPropertyID* set, unsigned length) const;
+    Ref<MutableStyleProperties> copyPropertiesInSet(const CSSPropertyID* set, unsigned length) const;
     
     String asText() const;
 
-    bool isMutable() const { return m_isMutable; }
     bool hasCSSOMWrapper() const;
+    bool isMutable() const { return type() == MutablePropertiesType; }
 
-    bool hasFailedOrCanceledSubresources() const;
+    bool traverseSubresources(const WTF::Function<bool (const CachedResource&)>& handler) const;
 
     static unsigned averageSizeInBytes();
 
@@ -122,49 +147,48 @@ public:
     bool propertyMatches(CSSPropertyID, const CSSValue*) const;
 
 protected:
-    StyleProperties(CSSParserMode cssParserMode)
-        : m_cssParserMode(cssParserMode)
-        , m_isMutable(true)
-        , m_arraySize(0)
+    StyleProperties(CSSParserMode cssParserMode, StylePropertiesType type)
+        : StylePropertiesBase(cssParserMode, type)
     { }
 
     StyleProperties(CSSParserMode cssParserMode, unsigned immutableArraySize)
-        : m_cssParserMode(cssParserMode)
-        , m_isMutable(false)
-        , m_arraySize(immutableArraySize)
+        : StylePropertiesBase(cssParserMode, immutableArraySize)
     { }
 
     int findPropertyIndex(CSSPropertyID) const;
+    int findCustomPropertyIndex(const String& propertyName) const;
 
-    unsigned m_cssParserMode : 2;
-    mutable unsigned m_isMutable : 1;
-    unsigned m_arraySize : 29;
-    
 private:
     String getShorthandValue(const StylePropertyShorthand&) const;
     String getCommonValue(const StylePropertyShorthand&) const;
-    enum CommonValueMode { OmitUncommonValues, ReturnNullOnUncommonValues };
-    String borderPropertyValue(CommonValueMode) const;
+    String getAlignmentShorthandValue(const StylePropertyShorthand&) const;
+    String borderPropertyValue(const StylePropertyShorthand&, const StylePropertyShorthand&, const StylePropertyShorthand&) const;
     String getLayeredShorthandValue(const StylePropertyShorthand&) const;
+    String get2Values(const StylePropertyShorthand&) const;
     String get4Values(const StylePropertyShorthand&) const;
     String borderSpacingValue(const StylePropertyShorthand&) const;
     String fontValue() const;
     void appendFontLonghandValueIfExplicit(CSSPropertyID, StringBuilder& result, String& value) const;
-
+    
+    RefPtr<CSSValue> getPropertyCSSValueInternal(CSSPropertyID) const;
+    
     friend class PropertySetCSSStyleDeclaration;
 };
 
-class ImmutableStyleProperties : public StyleProperties {
+class ImmutableStyleProperties final : public StyleProperties {
 public:
-    ~ImmutableStyleProperties();
-    static PassRef<ImmutableStyleProperties> create(const CSSProperty* properties, unsigned count, CSSParserMode);
+    WEBCORE_EXPORT ~ImmutableStyleProperties();
+    static Ref<ImmutableStyleProperties> create(const CSSProperty* properties, unsigned count, CSSParserMode);
 
     unsigned propertyCount() const { return m_arraySize; }
+    bool isEmpty() const { return !propertyCount(); }
+    PropertyReference propertyAt(unsigned index) const;
 
     const CSSValue** valueArray() const;
     const StylePropertyMetadata* metadataArray() const;
     int findPropertyIndex(CSSPropertyID) const;
-
+    int findCustomPropertyIndex(const String& propertyName) const;
+    
     void* m_storage;
 
 private:
@@ -181,48 +205,53 @@ inline const StylePropertyMetadata* ImmutableStyleProperties::metadataArray() co
     return reinterpret_cast_ptr<const StylePropertyMetadata*>(&reinterpret_cast_ptr<const char*>(&(this->m_storage))[m_arraySize * sizeof(CSSValue*)]);
 }
 
-class MutableStyleProperties : public StyleProperties {
+class MutableStyleProperties final : public StyleProperties {
 public:
-    static PassRef<MutableStyleProperties> create(CSSParserMode = CSSQuirksMode);
-    static PassRef<MutableStyleProperties> create(const CSSProperty* properties, unsigned count);
+    WEBCORE_EXPORT static Ref<MutableStyleProperties> create(CSSParserMode = HTMLQuirksMode);
+    static Ref<MutableStyleProperties> create(const CSSProperty* properties, unsigned count);
 
-    ~MutableStyleProperties();
+    WEBCORE_EXPORT ~MutableStyleProperties();
 
     unsigned propertyCount() const { return m_propertyVector.size(); }
+    bool isEmpty() const { return !propertyCount(); }
+    PropertyReference propertyAt(unsigned index) const;
 
     PropertySetCSSStyleDeclaration* cssStyleDeclaration();
 
-    void addParsedProperties(const Vector<CSSProperty>&);
-    void addParsedProperty(const CSSProperty&);
+    bool addParsedProperties(const ParsedPropertyVector&);
+    bool addParsedProperty(const CSSProperty&);
 
     // These expand shorthand properties into multiple properties.
-    bool setProperty(CSSPropertyID, const String& value, bool important = false, StyleSheetContents* contextStyleSheet = 0);
-    void setProperty(CSSPropertyID, PassRefPtr<CSSValue>, bool important = false);
+    bool setProperty(CSSPropertyID, const String& value, bool important, CSSParserContext);
+    bool setProperty(CSSPropertyID, const String& value, bool important = false);
+    void setProperty(CSSPropertyID, RefPtr<CSSValue>&&, bool important = false);
 
     // These do not. FIXME: This is too messy, we can do better.
     bool setProperty(CSSPropertyID, CSSValueID identifier, bool important = false);
     bool setProperty(CSSPropertyID, CSSPropertyID identifier, bool important = false);
-    void appendPrefixingVariantProperty(const CSSProperty&);
-    void setPrefixingVariantProperty(const CSSProperty&);
-    void setProperty(const CSSProperty&, CSSProperty* slot = 0);
+    bool setProperty(const CSSProperty&, CSSProperty* slot = nullptr);
 
-    bool removeProperty(CSSPropertyID, String* returnText = 0);
-    void removePrefixedOrUnprefixedProperty(CSSPropertyID);
+    bool removeProperty(CSSPropertyID, String* returnText = nullptr);
     void removeBlockProperties();
     bool removePropertiesInSet(const CSSPropertyID* set, unsigned length);
 
     void mergeAndOverrideOnConflict(const StyleProperties&);
 
     void clear();
-    void parseDeclaration(const String& styleDeclaration, StyleSheetContents* contextStyleSheet);
+    bool parseDeclaration(const String& styleDeclaration, CSSParserContext);
 
-    CSSStyleDeclaration* ensureCSSStyleDeclaration();
-    CSSStyleDeclaration* ensureInlineCSSStyleDeclaration(StyledElement* parentElement);
+    WEBCORE_EXPORT CSSStyleDeclaration& ensureCSSStyleDeclaration();
+    CSSStyleDeclaration& ensureInlineCSSStyleDeclaration(StyledElement& parentElement);
 
     int findPropertyIndex(CSSPropertyID) const;
-
+    int findCustomPropertyIndex(const String& propertyName) const;
+    
     Vector<CSSProperty, 4> m_propertyVector;
 
+    // Methods for querying and altering CSS custom properties.
+    bool setCustomProperty(const Document*, const String& propertyName, const String& value, bool important, CSSParserContext);
+    bool removeCustomProperty(const String& propertyName, String* returnText = nullptr);
+
 private:
     explicit MutableStyleProperties(CSSParserMode);
     explicit MutableStyleProperties(const StyleProperties&);
@@ -230,69 +259,92 @@ private:
 
     bool removeShorthandProperty(CSSPropertyID);
     CSSProperty* findCSSPropertyWithID(CSSPropertyID);
+    CSSProperty* findCustomCSSPropertyWithName(const String&);
     std::unique_ptr<PropertySetCSSStyleDeclaration> m_cssomWrapper;
 
     friend class StyleProperties;
 };
 
-TYPE_CASTS_BASE(MutableStyleProperties, StyleProperties, set, set->isMutable(), set.isMutable());
-
-inline MutableStyleProperties* toMutableStyleProperties(const RefPtr<StyleProperties>& set)
-{
-    return toMutableStyleProperties(set.get());
-}
+class DeferredStyleProperties final : public StylePropertiesBase {
+public:
+    WEBCORE_EXPORT ~DeferredStyleProperties();
+    static Ref<DeferredStyleProperties> create(const CSSParserTokenRange&, CSSDeferredParser&);
 
-TYPE_CASTS_BASE(ImmutableStyleProperties, StyleProperties, set, !set->isMutable(), !set.isMutable());
+    Ref<ImmutableStyleProperties> parseDeferredProperties();
+    
+private:
+    DeferredStyleProperties(const CSSParserTokenRange&, CSSDeferredParser&);
+    
+    Vector<CSSParserToken> m_tokens;
+    Ref<CSSDeferredParser> m_parser;
+};
 
-inline ImmutableStyleProperties* toImmutableStyleProperties(const RefPtr<StyleProperties>& set)
+inline ImmutableStyleProperties::PropertyReference ImmutableStyleProperties::propertyAt(unsigned index) const
 {
-    return toImmutableStyleProperties(set.get());
+    return PropertyReference(metadataArray()[index], valueArray()[index]);
 }
 
-inline const StylePropertyMetadata& StyleProperties::PropertyReference::propertyMetadata() const
+inline MutableStyleProperties::PropertyReference MutableStyleProperties::propertyAt(unsigned index) const
 {
-    if (m_propertySet.isMutable())
-        return static_cast<const MutableStyleProperties&>(m_propertySet).m_propertyVector.at(m_index).metadata();
-    return static_cast<const ImmutableStyleProperties&>(m_propertySet).metadataArray()[m_index];
+    const CSSProperty& property = m_propertyVector[index];
+    return PropertyReference(property.metadata(), property.value());
 }
 
-inline const CSSValue* StyleProperties::PropertyReference::propertyValue() const
+inline StyleProperties::PropertyReference StyleProperties::propertyAt(unsigned index) const
 {
-    if (m_propertySet.isMutable())
-        return static_cast<const MutableStyleProperties&>(m_propertySet).m_propertyVector.at(m_index).value();
-    return static_cast<const ImmutableStyleProperties&>(m_propertySet).valueArray()[m_index];
+    if (is<MutableStyleProperties>(*this))
+        return downcast<MutableStyleProperties>(*this).propertyAt(index);
+    return downcast<ImmutableStyleProperties>(*this).propertyAt(index);
 }
 
 inline unsigned StyleProperties::propertyCount() const
 {
-    if (m_isMutable)
-        return static_cast<const MutableStyleProperties*>(this)->m_propertyVector.size();
-    return m_arraySize;
-}
-
-inline bool StyleProperties::isEmpty() const
-{
-    return !propertyCount();
+    if (is<MutableStyleProperties>(*this))
+        return downcast<MutableStyleProperties>(*this).propertyCount();
+    return downcast<ImmutableStyleProperties>(*this).propertyCount();
 }
 
-inline void StyleProperties::deref()
+inline void StylePropertiesBase::deref()
 {
     if (!derefBase())
         return;
 
-    if (m_isMutable)
-        delete static_cast<MutableStyleProperties*>(this);
+    if (is<MutableStyleProperties>(*this))
+        delete downcast<MutableStyleProperties>(this);
+    else if (is<ImmutableStyleProperties>(*this))
+        delete downcast<ImmutableStyleProperties>(this);
     else
-        delete static_cast<ImmutableStyleProperties*>(this);
+        delete downcast<DeferredStyleProperties>(this);
 }
 
 inline int StyleProperties::findPropertyIndex(CSSPropertyID propertyID) const
 {
-    if (m_isMutable)
-        return toMutableStyleProperties(this)->findPropertyIndex(propertyID);
-    return toImmutableStyleProperties(this)->findPropertyIndex(propertyID);
+    if (is<MutableStyleProperties>(*this))
+        return downcast<MutableStyleProperties>(*this).findPropertyIndex(propertyID);
+    return downcast<ImmutableStyleProperties>(*this).findPropertyIndex(propertyID);
+}
+
+inline int StyleProperties::findCustomPropertyIndex(const String& propertyName) const
+{
+    if (is<MutableStyleProperties>(*this))
+        return downcast<MutableStyleProperties>(*this).findCustomPropertyIndex(propertyName);
+    return downcast<ImmutableStyleProperties>(*this).findCustomPropertyIndex(propertyName);
 }
 
 } // namespace WebCore
 
-#endif // StyleProperties_h
+SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::StyleProperties)
+    static bool isType(const WebCore::StylePropertiesBase& set) { return set.type() != WebCore::DeferredPropertiesType; }
+SPECIALIZE_TYPE_TRAITS_END()
+
+SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::MutableStyleProperties)
+    static bool isType(const WebCore::StylePropertiesBase& set) { return set.type() == WebCore::MutablePropertiesType; }
+SPECIALIZE_TYPE_TRAITS_END()
+
+SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::ImmutableStyleProperties)
+    static bool isType(const WebCore::StylePropertiesBase& set) { return set.type() == WebCore::ImmutablePropertiesType; }
+SPECIALIZE_TYPE_TRAITS_END()
+
+SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::DeferredStyleProperties)
+    static bool isType(const WebCore::StylePropertiesBase& set) { return set.type() == WebCore::DeferredPropertiesType; }
+SPECIALIZE_TYPE_TRAITS_END()