OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 Google Inc. All rights reserved. |
3 * Copyright (C) 2014 Apple Inc. All rights reserved. | 3 * Copyright (C) 2014 Apple Inc. All rights reserved. |
4 * | 4 * |
5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
6 * modification, are permitted provided that the following conditions are | 6 * modification, are permitted provided that the following conditions are |
7 * met: | 7 * met: |
8 * | 8 * |
9 * * Redistributions of source code must retain the above copyright | 9 * * Redistributions of source code must retain the above copyright |
10 * notice, this list of conditions and the following disclaimer. | 10 * notice, this list of conditions and the following disclaimer. |
(...skipping 15 matching lines...) Expand all Loading... |
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 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. | 29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
30 */ | 30 */ |
31 | 31 |
32 #ifndef ElementData_h | 32 #ifndef ElementData_h |
33 #define ElementData_h | 33 #define ElementData_h |
34 | 34 |
35 #include "core/dom/Attribute.h" | 35 #include "core/dom/Attribute.h" |
| 36 #include "core/dom/AttributeCollection.h" |
36 #include "core/dom/SpaceSplitString.h" | 37 #include "core/dom/SpaceSplitString.h" |
37 #include "platform/heap/Handle.h" | 38 #include "platform/heap/Handle.h" |
38 #include "wtf/text/AtomicString.h" | 39 #include "wtf/text/AtomicString.h" |
39 | 40 |
40 namespace WebCore { | 41 namespace WebCore { |
41 | 42 |
42 class Attr; | |
43 class ShareableElementData; | 43 class ShareableElementData; |
44 class StylePropertySet; | 44 class StylePropertySet; |
45 class UniqueElementData; | 45 class UniqueElementData; |
46 | 46 |
47 class AttributeCollection { | |
48 public: | |
49 typedef const Attribute* const_iterator; | |
50 | |
51 AttributeCollection(const Attribute* array, unsigned size) | |
52 : m_array(array) | |
53 , m_size(size) | |
54 { } | |
55 | |
56 const_iterator begin() const { return m_array; } | |
57 const_iterator end() const { return m_array + m_size; } | |
58 | |
59 unsigned size() const { return m_size; } | |
60 | |
61 private: | |
62 const Attribute* m_array; | |
63 unsigned m_size; | |
64 }; | |
65 | |
66 // ElementData represents very common, but not necessarily unique to an element, | 47 // ElementData represents very common, but not necessarily unique to an element, |
67 // data such as attributes, inline style, and parsed class names and ids. | 48 // data such as attributes, inline style, and parsed class names and ids. |
68 class ElementData : public RefCountedWillBeGarbageCollectedFinalized<ElementData
> { | 49 class ElementData : public RefCountedWillBeGarbageCollectedFinalized<ElementData
> { |
69 WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED; | 50 WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED; |
70 public: | 51 public: |
71 #if ENABLE(OILPAN) | 52 #if ENABLE(OILPAN) |
72 // Override GarbageCollectedFinalized's finalizeGarbageCollectedObject to | 53 // Override GarbageCollectedFinalized's finalizeGarbageCollectedObject to |
73 // dispatch to the correct subclass destructor. | 54 // dispatch to the correct subclass destructor. |
74 void finalizeGarbageCollectedObject(); | 55 void finalizeGarbageCollectedObject(); |
75 #else | 56 #else |
76 // Override RefCounted's deref() to ensure operator delete is called on | 57 // Override RefCounted's deref() to ensure operator delete is called on |
77 // the appropriate subclass type. | 58 // the appropriate subclass type. |
78 void deref(); | 59 void deref(); |
79 #endif | 60 #endif |
80 | 61 |
81 void clearClass() const { m_classNames.clear(); } | 62 void clearClass() const { m_classNames.clear(); } |
82 void setClass(const AtomicString& className, bool shouldFoldCase) const { m_
classNames.set(className, shouldFoldCase); } | 63 void setClass(const AtomicString& className, bool shouldFoldCase) const { m_
classNames.set(className, shouldFoldCase); } |
83 const SpaceSplitString& classNames() const { return m_classNames; } | 64 const SpaceSplitString& classNames() const { return m_classNames; } |
84 | 65 |
85 const AtomicString& idForStyleResolution() const { return m_idForStyleResolu
tion; } | 66 const AtomicString& idForStyleResolution() const { return m_idForStyleResolu
tion; } |
86 void setIdForStyleResolution(const AtomicString& newId) const { m_idForStyle
Resolution = newId; } | 67 void setIdForStyleResolution(const AtomicString& newId) const { m_idForStyle
Resolution = newId; } |
87 | 68 |
88 const StylePropertySet* inlineStyle() const { return m_inlineStyle.get(); } | 69 const StylePropertySet* inlineStyle() const { return m_inlineStyle.get(); } |
89 | 70 |
90 const StylePropertySet* presentationAttributeStyle() const; | 71 const StylePropertySet* presentationAttributeStyle() const; |
91 | 72 |
92 // This is not a trivial getter and its return value should be cached for pe
rformance. | |
93 size_t attributeCount() const; | |
94 bool hasAttributes() const { return !!attributeCount(); } | |
95 | |
96 AttributeCollection attributes() const; | 73 AttributeCollection attributes() const; |
97 | 74 |
98 const Attribute& attributeAt(unsigned index) const; | |
99 const Attribute* findAttributeByName(const QualifiedName&) const; | |
100 size_t findAttributeIndexByName(const QualifiedName&, bool shouldIgnoreCase
= false) const; | |
101 size_t findAttributeIndexByName(const AtomicString& name, bool shouldIgnoreA
ttributeCase) const; | |
102 size_t findAttrNodeIndex(Attr*) const; | |
103 | |
104 bool hasID() const { return !m_idForStyleResolution.isNull(); } | 75 bool hasID() const { return !m_idForStyleResolution.isNull(); } |
105 bool hasClass() const { return !m_classNames.isNull(); } | 76 bool hasClass() const { return !m_classNames.isNull(); } |
106 | 77 |
107 bool isEquivalent(const ElementData* other) const; | 78 bool isEquivalent(const ElementData* other) const; |
108 | 79 |
109 bool isUnique() const { return m_isUnique; } | 80 bool isUnique() const { return m_isUnique; } |
110 | 81 |
111 void traceAfterDispatch(Visitor*); | 82 void traceAfterDispatch(Visitor*); |
112 void trace(Visitor*); | 83 void trace(Visitor*); |
113 | 84 |
(...skipping 16 matching lines...) Expand all Loading... |
130 private: | 101 private: |
131 friend class Element; | 102 friend class Element; |
132 friend class ShareableElementData; | 103 friend class ShareableElementData; |
133 friend class UniqueElementData; | 104 friend class UniqueElementData; |
134 friend class SVGElement; | 105 friend class SVGElement; |
135 | 106 |
136 #if !ENABLE(OILPAN) | 107 #if !ENABLE(OILPAN) |
137 void destroy(); | 108 void destroy(); |
138 #endif | 109 #endif |
139 | 110 |
140 const Attribute* attributeBase() const; | |
141 const Attribute* findAttributeByName(const AtomicString& name, bool shouldIg
noreAttributeCase) const; | |
142 size_t findAttributeIndexByNameSlowCase(const AtomicString& name, bool shoul
dIgnoreAttributeCase) const; | |
143 | |
144 PassRefPtrWillBeRawPtr<UniqueElementData> makeUniqueCopy() const; | 111 PassRefPtrWillBeRawPtr<UniqueElementData> makeUniqueCopy() const; |
145 }; | 112 }; |
146 | 113 |
147 #if COMPILER(MSVC) | 114 #if COMPILER(MSVC) |
148 #pragma warning(push) | 115 #pragma warning(push) |
149 #pragma warning(disable: 4200) // Disable "zero-sized array in struct/union" war
ning | 116 #pragma warning(disable: 4200) // Disable "zero-sized array in struct/union" war
ning |
150 #endif | 117 #endif |
151 | 118 |
152 // SharableElementData is managed by ElementDataCache and is produced by | 119 // SharableElementData is managed by ElementDataCache and is produced by |
153 // the parser during page load for elements that have identical attributes. This | 120 // the parser during page load for elements that have identical attributes. This |
(...skipping 12 matching lines...) Expand all Loading... |
166 // Add support for placement new as ShareableElementData is not allocated | 133 // Add support for placement new as ShareableElementData is not allocated |
167 // with a fixed size. Instead the allocated memory size is computed based on | 134 // with a fixed size. Instead the allocated memory size is computed based on |
168 // the number of attributes. This requires us to use Heap::allocate directly | 135 // the number of attributes. This requires us to use Heap::allocate directly |
169 // with the computed size and subsequently call placement new with the | 136 // with the computed size and subsequently call placement new with the |
170 // allocated memory address. | 137 // allocated memory address. |
171 void* operator new(std::size_t, void* location) | 138 void* operator new(std::size_t, void* location) |
172 { | 139 { |
173 return location; | 140 return location; |
174 } | 141 } |
175 | 142 |
| 143 AttributeCollection attributes() const; |
| 144 |
176 Attribute m_attributeArray[0]; | 145 Attribute m_attributeArray[0]; |
177 }; | 146 }; |
178 | 147 |
179 #if COMPILER(MSVC) | 148 #if COMPILER(MSVC) |
180 #pragma warning(pop) | 149 #pragma warning(pop) |
181 #endif | 150 #endif |
182 | 151 |
183 // UniqueElementData is created when an element needs to mutate its attributes | 152 // UniqueElementData is created when an element needs to mutate its attributes |
184 // or gains presentation attribute style (ex. width="10"). It does not need to | 153 // or gains presentation attribute style (ex. width="10"). It does not need to |
185 // be created to fill in values in the ElementData that are derived from | 154 // be created to fill in values in the ElementData that are derived from |
186 // attributes. For example populating the m_inlineStyle from the style attribute | 155 // attributes. For example populating the m_inlineStyle from the style attribute |
187 // doesn't require a UniqueElementData as all elements with the same style | 156 // doesn't require a UniqueElementData as all elements with the same style |
188 // attribute will have the same inline style. | 157 // attribute will have the same inline style. |
189 class UniqueElementData FINAL : public ElementData { | 158 class UniqueElementData FINAL : public ElementData { |
190 public: | 159 public: |
191 static PassRefPtrWillBeRawPtr<UniqueElementData> create(); | 160 static PassRefPtrWillBeRawPtr<UniqueElementData> create(); |
192 PassRefPtrWillBeRawPtr<ShareableElementData> makeShareableCopy() const; | 161 PassRefPtrWillBeRawPtr<ShareableElementData> makeShareableCopy() const; |
193 | 162 |
194 // These functions do no error/duplicate checking. | 163 // These functions do no error/duplicate checking. |
195 void appendAttribute(const QualifiedName&, const AtomicString&); | 164 void appendAttribute(const QualifiedName&, const AtomicString&); |
196 void removeAttributeAt(size_t index); | 165 void removeAttributeAt(size_t index); |
197 | 166 |
| 167 AttributeCollection attributes() const; |
| 168 |
198 Attribute& attributeAt(unsigned index); | 169 Attribute& attributeAt(unsigned index); |
199 Attribute* findAttributeByName(const QualifiedName&); | 170 Attribute* findAttributeByName(const QualifiedName&); |
200 | 171 |
201 UniqueElementData(); | 172 UniqueElementData(); |
202 explicit UniqueElementData(const ShareableElementData&); | 173 explicit UniqueElementData(const ShareableElementData&); |
203 explicit UniqueElementData(const UniqueElementData&); | 174 explicit UniqueElementData(const UniqueElementData&); |
204 | 175 |
205 void traceAfterDispatch(Visitor*); | 176 void traceAfterDispatch(Visitor*); |
206 | 177 |
207 // FIXME: We might want to support sharing element data for elements with | 178 // FIXME: We might want to support sharing element data for elements with |
208 // presentation attribute style. Lots of table cells likely have the same | 179 // presentation attribute style. Lots of table cells likely have the same |
209 // attributes. Most modern pages don't use presentation attributes though | 180 // attributes. Most modern pages don't use presentation attributes though |
210 // so this might not make sense. | 181 // so this might not make sense. |
211 mutable RefPtrWillBeMember<StylePropertySet> m_presentationAttributeStyle; | 182 mutable RefPtrWillBeMember<StylePropertySet> m_presentationAttributeStyle; |
212 Vector<Attribute, 4> m_attributeVector; | 183 Vector<Attribute, 4> m_attributeVector; |
213 }; | 184 }; |
214 | 185 |
215 #if !ENABLE(OILPAN) | 186 #if !ENABLE(OILPAN) |
216 inline void ElementData::deref() | 187 inline void ElementData::deref() |
217 { | 188 { |
218 if (!derefBase()) | 189 if (!derefBase()) |
219 return; | 190 return; |
220 destroy(); | 191 destroy(); |
221 } | 192 } |
222 #endif | 193 #endif |
223 | 194 |
224 inline size_t ElementData::attributeCount() const | |
225 { | |
226 if (isUnique()) | |
227 return static_cast<const UniqueElementData*>(this)->m_attributeVector.si
ze(); | |
228 return m_arraySize; | |
229 } | |
230 | |
231 inline const StylePropertySet* ElementData::presentationAttributeStyle() const | 195 inline const StylePropertySet* ElementData::presentationAttributeStyle() const |
232 { | 196 { |
233 if (!m_isUnique) | 197 if (!m_isUnique) |
234 return 0; | 198 return 0; |
235 return static_cast<const UniqueElementData*>(this)->m_presentationAttributeS
tyle.get(); | 199 return static_cast<const UniqueElementData*>(this)->m_presentationAttributeS
tyle.get(); |
236 } | 200 } |
237 | 201 |
238 inline const Attribute* ElementData::findAttributeByName(const AtomicString& nam
e, bool shouldIgnoreAttributeCase) const | |
239 { | |
240 size_t index = findAttributeIndexByName(name, shouldIgnoreAttributeCase); | |
241 if (index != kNotFound) | |
242 return &attributeAt(index); | |
243 return 0; | |
244 } | |
245 | |
246 inline const Attribute* ElementData::attributeBase() const | |
247 { | |
248 if (m_isUnique) | |
249 return static_cast<const UniqueElementData*>(this)->m_attributeVector.be
gin(); | |
250 return static_cast<const ShareableElementData*>(this)->m_attributeArray; | |
251 } | |
252 | |
253 inline size_t ElementData::findAttributeIndexByName(const QualifiedName& name, b
ool shouldIgnoreCase) const | |
254 { | |
255 AttributeCollection attributes = this->attributes(); | |
256 AttributeCollection::const_iterator end = attributes.end(); | |
257 unsigned index = 0; | |
258 for (AttributeCollection::const_iterator it = attributes.begin(); it != end;
++it, ++index) { | |
259 if (it->name().matchesPossiblyIgnoringCase(name, shouldIgnoreCase)) | |
260 return index; | |
261 } | |
262 return kNotFound; | |
263 } | |
264 | |
265 // We use a boolean parameter instead of calling shouldIgnoreAttributeCase so th
at the caller | |
266 // can tune the behavior (hasAttribute is case sensitive whereas getAttribute is
not). | |
267 inline size_t ElementData::findAttributeIndexByName(const AtomicString& name, bo
ol shouldIgnoreAttributeCase) const | |
268 { | |
269 bool doSlowCheck = shouldIgnoreAttributeCase; | |
270 | |
271 // Optimize for the case where the attribute exists and its name exactly mat
ches. | |
272 AttributeCollection attributes = this->attributes(); | |
273 AttributeCollection::const_iterator end = attributes.end(); | |
274 unsigned index = 0; | |
275 for (AttributeCollection::const_iterator it = attributes.begin(); it != end;
++it, ++index) { | |
276 // FIXME: Why check the prefix? Namespaces should be all that matter. | |
277 // Most attributes (all of HTML and CSS) have no namespace. | |
278 if (!it->name().hasPrefix()) { | |
279 if (name == it->localName()) | |
280 return index; | |
281 } else { | |
282 doSlowCheck = true; | |
283 } | |
284 } | |
285 | |
286 if (doSlowCheck) | |
287 return findAttributeIndexByNameSlowCase(name, shouldIgnoreAttributeCase)
; | |
288 return kNotFound; | |
289 } | |
290 | |
291 inline AttributeCollection ElementData::attributes() const | 202 inline AttributeCollection ElementData::attributes() const |
292 { | 203 { |
293 if (isUnique()) { | 204 if (isUnique()) |
294 const Vector<Attribute, 4>& attributeVector = static_cast<const UniqueEl
ementData*>(this)->m_attributeVector; | 205 return static_cast<const UniqueElementData*>(this)->attributes(); |
295 return AttributeCollection(attributeVector.data(), attributeVector.size(
)); | 206 return static_cast<const ShareableElementData*>(this)->attributes(); |
296 } | |
297 return AttributeCollection(static_cast<const ShareableElementData*>(this)->m
_attributeArray, m_arraySize); | |
298 } | 207 } |
299 | 208 |
300 inline const Attribute* ElementData::findAttributeByName(const QualifiedName& na
me) const | 209 inline AttributeCollection ShareableElementData::attributes() const |
301 { | 210 { |
302 AttributeCollection attributes = this->attributes(); | 211 return AttributeCollection(m_attributeArray, m_arraySize); |
303 AttributeCollection::const_iterator end = attributes.end(); | |
304 for (AttributeCollection::const_iterator it = attributes.begin(); it != end;
++it) { | |
305 if (it->name().matches(name)) | |
306 return it; | |
307 } | |
308 return 0; | |
309 } | 212 } |
310 | 213 |
311 inline const Attribute& ElementData::attributeAt(unsigned index) const | 214 inline AttributeCollection UniqueElementData::attributes() const |
312 { | 215 { |
313 RELEASE_ASSERT(index < attributeCount()); | 216 return AttributeCollection(m_attributeVector.data(), m_attributeVector.size(
)); |
314 ASSERT(attributeBase() + index); | |
315 return *(attributeBase() + index); | |
316 } | 217 } |
317 | 218 |
318 inline void UniqueElementData::appendAttribute(const QualifiedName& attributeNam
e, const AtomicString& value) | 219 inline void UniqueElementData::appendAttribute(const QualifiedName& attributeNam
e, const AtomicString& value) |
319 { | 220 { |
320 m_attributeVector.append(Attribute(attributeName, value)); | 221 m_attributeVector.append(Attribute(attributeName, value)); |
321 } | 222 } |
322 | 223 |
323 inline void UniqueElementData::removeAttributeAt(size_t index) | 224 inline void UniqueElementData::removeAttributeAt(size_t index) |
324 { | 225 { |
325 m_attributeVector.remove(index); | 226 m_attributeVector.remove(index); |
326 } | 227 } |
327 | 228 |
328 inline Attribute& UniqueElementData::attributeAt(unsigned index) | 229 inline Attribute& UniqueElementData::attributeAt(unsigned index) |
329 { | 230 { |
330 return m_attributeVector.at(index); | 231 return m_attributeVector.at(index); |
331 } | 232 } |
332 | 233 |
333 } // namespace WebCore | 234 } // namespace WebCore |
334 | 235 |
335 #endif // ElementData_h | 236 #endif // ElementData_h |
OLD | NEW |