• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
clearClass()62     void clearClass() const { m_classNames.clear(); }
setClass(const AtomicString & className,bool shouldFoldCase)63     void setClass(const AtomicString& className, bool shouldFoldCase) const { m_classNames.set(className, shouldFoldCase); }
classNames()64     const SpaceSplitString& classNames() const { return m_classNames; }
65 
idForStyleResolution()66     const AtomicString& idForStyleResolution() const { return m_idForStyleResolution; }
setIdForStyleResolution(const AtomicString & newId)67     void setIdForStyleResolution(const AtomicString& newId) const { m_idForStyleResolution = newId; }
68 
inlineStyle()69     const StylePropertySet* inlineStyle() const { return m_inlineStyle.get(); }
70 
71     const StylePropertySet* presentationAttributeStyle() const;
72 
73     AttributeCollection attributes() const;
74 
hasID()75     bool hasID() const { return !m_idForStyleResolution.isNull(); }
hasClass()76     bool hasClass() const { return !m_classNames.isNull(); }
77 
78     bool isEquivalent(const ElementData* other) const;
79 
isUnique()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 
traceAfterDispatch(Visitor * visitor)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.
new(std::size_t,void * location)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)
deref()189 inline void ElementData::deref()
190 {
191     if (!derefBase())
192         return;
193     destroy();
194 }
195 #endif
196 
presentationAttributeStyle()197 inline const StylePropertySet* ElementData::presentationAttributeStyle() const
198 {
199     if (!m_isUnique)
200         return 0;
201     return toUniqueElementData(this)->m_presentationAttributeStyle.get();
202 }
203 
attributes()204 inline AttributeCollection ElementData::attributes() const
205 {
206     if (isUnique())
207         return toUniqueElementData(this)->attributes();
208     return toShareableElementData(this)->attributes();
209 }
210 
attributes()211 inline AttributeCollection ShareableElementData::attributes() const
212 {
213     return AttributeCollection(m_attributeArray, m_arraySize);
214 }
215 
attributes()216 inline AttributeCollection UniqueElementData::attributes() const
217 {
218     return AttributeCollection(m_attributeVector.data(), m_attributeVector.size());
219 }
220 
attributes()221 inline MutableAttributeCollection UniqueElementData::attributes()
222 {
223     return MutableAttributeCollection(m_attributeVector);
224 }
225 
226 } // namespace blink
227 
228 #endif // ElementData_h
229