Home | History | Annotate | Download | only in dom
      1 /*
      2  * Copyright (C) 2013 Google Inc. All rights reserved.
      3  * Copyright (C) 2014 Apple Inc. All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions are
      7  * met:
      8  *
      9  *     * Redistributions of source code must retain the above copyright
     10  * notice, this list of conditions and the following disclaimer.
     11  *     * Redistributions in binary form must reproduce the above
     12  * copyright notice, this list of conditions and the following disclaimer
     13  * in the documentation and/or other materials provided with the
     14  * distribution.
     15  *     * Neither the name of Google Inc. nor the names of its
     16  * contributors may be used to endorse or promote products derived from
     17  * this software without specific prior written permission.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     22  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     23  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     25  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     29  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 #ifndef ElementData_h
     33 #define ElementData_h
     34 
     35 #include "core/dom/Attribute.h"
     36 #include "core/dom/AttributeCollection.h"
     37 #include "core/dom/SpaceSplitString.h"
     38 #include "platform/heap/Handle.h"
     39 #include "wtf/text/AtomicString.h"
     40 
     41 namespace blink {
     42 
     43 class ShareableElementData;
     44 class StylePropertySet;
     45 class UniqueElementData;
     46 
     47 // ElementData represents very common, but not necessarily unique to an element,
     48 // data such as attributes, inline style, and parsed class names and ids.
     49 class ElementData : public RefCountedWillBeGarbageCollectedFinalized<ElementData> {
     50     WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED;
     51 public:
     52 #if ENABLE(OILPAN)
     53     // Override GarbageCollectedFinalized's finalizeGarbageCollectedObject to
     54     // dispatch to the correct subclass destructor.
     55     void finalizeGarbageCollectedObject();
     56 #else
     57     // Override RefCounted's deref() to ensure operator delete is called on
     58     // the appropriate subclass type.
     59     void deref();
     60 #endif
     61 
     62     void clearClass() const { m_classNames.clear(); }
     63     void setClass(const AtomicString& className, bool shouldFoldCase) const { m_classNames.set(className, shouldFoldCase); }
     64     const SpaceSplitString& classNames() const { return m_classNames; }
     65 
     66     const AtomicString& idForStyleResolution() const { return m_idForStyleResolution; }
     67     void setIdForStyleResolution(const AtomicString& newId) const { m_idForStyleResolution = newId; }
     68 
     69     const StylePropertySet* inlineStyle() const { return m_inlineStyle.get(); }
     70 
     71     const StylePropertySet* presentationAttributeStyle() const;
     72 
     73     AttributeCollection attributes() const;
     74 
     75     bool hasID() const { return !m_idForStyleResolution.isNull(); }
     76     bool hasClass() const { return !m_classNames.isNull(); }
     77 
     78     bool isEquivalent(const ElementData* other) const;
     79 
     80     bool isUnique() const { return m_isUnique; }
     81 
     82     void traceAfterDispatch(Visitor*);
     83     void trace(Visitor*);
     84 
     85 protected:
     86     ElementData();
     87     explicit ElementData(unsigned arraySize);
     88     ElementData(const ElementData&, bool isUnique);
     89 
     90     // Keep the type in a bitfield instead of using virtual destructors to avoid adding a vtable.
     91     unsigned m_isUnique : 1;
     92     unsigned m_arraySize : 28;
     93     mutable unsigned m_presentationAttributeStyleIsDirty : 1;
     94     mutable unsigned m_styleAttributeIsDirty : 1;
     95     mutable unsigned m_animatedSVGAttributesAreDirty : 1;
     96 
     97     mutable RefPtrWillBeMember<StylePropertySet> m_inlineStyle;
     98     mutable SpaceSplitString m_classNames;
     99     mutable AtomicString m_idForStyleResolution;
    100 
    101 private:
    102     friend class Element;
    103     friend class ShareableElementData;
    104     friend class UniqueElementData;
    105     friend class SVGElement;
    106 
    107 #if !ENABLE(OILPAN)
    108     void destroy();
    109 #endif
    110 
    111     PassRefPtrWillBeRawPtr<UniqueElementData> makeUniqueCopy() const;
    112 };
    113 
    114 #define DEFINE_ELEMENT_DATA_TYPE_CASTS(thisType,  pointerPredicate, referencePredicate) \
    115     template<typename T> inline thisType* to##thisType(const RefPtr<T>& data) { return to##thisType(data.get()); } \
    116     DEFINE_TYPE_CASTS(thisType, ElementData, data, pointerPredicate, referencePredicate)
    117 
    118 #if COMPILER(MSVC)
    119 #pragma warning(push)
    120 #pragma warning(disable: 4200) // Disable "zero-sized array in struct/union" warning
    121 #endif
    122 
    123 // SharableElementData is managed by ElementDataCache and is produced by
    124 // the parser during page load for elements that have identical attributes. This
    125 // is a memory optimization since it's very common for many elements to have
    126 // duplicate sets of attributes (ex. the same classes).
    127 class ShareableElementData FINAL : public ElementData {
    128 public:
    129     static PassRefPtrWillBeRawPtr<ShareableElementData> createWithAttributes(const Vector<Attribute>&);
    130 
    131     explicit ShareableElementData(const Vector<Attribute>&);
    132     explicit ShareableElementData(const UniqueElementData&);
    133     ~ShareableElementData();
    134 
    135     void traceAfterDispatch(Visitor* visitor) { ElementData::traceAfterDispatch(visitor); }
    136 
    137     // Add support for placement new as ShareableElementData is not allocated
    138     // with a fixed size. Instead the allocated memory size is computed based on
    139     // the number of attributes. This requires us to use Heap::allocate directly
    140     // with the computed size and subsequently call placement new with the
    141     // allocated memory address.
    142     void* operator new(std::size_t, void* location)
    143     {
    144         return location;
    145     }
    146 
    147     AttributeCollection attributes() const;
    148 
    149     Attribute m_attributeArray[0];
    150 };
    151 
    152 DEFINE_ELEMENT_DATA_TYPE_CASTS(ShareableElementData, !data->isUnique(), !data.isUnique());
    153 
    154 #if COMPILER(MSVC)
    155 #pragma warning(pop)
    156 #endif
    157 
    158 // UniqueElementData is created when an element needs to mutate its attributes
    159 // or gains presentation attribute style (ex. width="10"). It does not need to
    160 // be created to fill in values in the ElementData that are derived from
    161 // attributes. For example populating the m_inlineStyle from the style attribute
    162 // doesn't require a UniqueElementData as all elements with the same style
    163 // attribute will have the same inline style.
    164 class UniqueElementData FINAL : public ElementData {
    165 public:
    166     static PassRefPtrWillBeRawPtr<UniqueElementData> create();
    167     PassRefPtrWillBeRawPtr<ShareableElementData> makeShareableCopy() const;
    168 
    169     MutableAttributeCollection attributes();
    170     AttributeCollection attributes() const;
    171 
    172     UniqueElementData();
    173     explicit UniqueElementData(const ShareableElementData&);
    174     explicit UniqueElementData(const UniqueElementData&);
    175 
    176     void traceAfterDispatch(Visitor*);
    177 
    178     // FIXME: We might want to support sharing element data for elements with
    179     // presentation attribute style. Lots of table cells likely have the same
    180     // attributes. Most modern pages don't use presentation attributes though
    181     // so this might not make sense.
    182     mutable RefPtrWillBeMember<StylePropertySet> m_presentationAttributeStyle;
    183     AttributeVector m_attributeVector;
    184 };
    185 
    186 DEFINE_ELEMENT_DATA_TYPE_CASTS(UniqueElementData, data->isUnique(), data.isUnique());
    187 
    188 #if !ENABLE(OILPAN)
    189 inline void ElementData::deref()
    190 {
    191     if (!derefBase())
    192         return;
    193     destroy();
    194 }
    195 #endif
    196 
    197 inline const StylePropertySet* ElementData::presentationAttributeStyle() const
    198 {
    199     if (!m_isUnique)
    200         return 0;
    201     return toUniqueElementData(this)->m_presentationAttributeStyle.get();
    202 }
    203 
    204 inline AttributeCollection ElementData::attributes() const
    205 {
    206     if (isUnique())
    207         return toUniqueElementData(this)->attributes();
    208     return toShareableElementData(this)->attributes();
    209 }
    210 
    211 inline AttributeCollection ShareableElementData::attributes() const
    212 {
    213     return AttributeCollection(m_attributeArray, m_arraySize);
    214 }
    215 
    216 inline AttributeCollection UniqueElementData::attributes() const
    217 {
    218     return AttributeCollection(m_attributeVector.data(), m_attributeVector.size());
    219 }
    220 
    221 inline MutableAttributeCollection UniqueElementData::attributes()
    222 {
    223     return MutableAttributeCollection(m_attributeVector);
    224 }
    225 
    226 } // namespace blink
    227 
    228 #endif // ElementData_h
    229