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 26 matching lines...) Expand all Loading... | |
37 #include "platform/heap/Handle.h" | 37 #include "platform/heap/Handle.h" |
38 #include "wtf/text/AtomicString.h" | 38 #include "wtf/text/AtomicString.h" |
39 | 39 |
40 namespace WebCore { | 40 namespace WebCore { |
41 | 41 |
42 class Attr; | 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 { | 47 class AttributeCollection { |
Inactive
2014/06/26 22:16:40
Ok, I'll move this to a separate file since it is
| |
48 public: | 48 public: |
49 typedef const Attribute* const_iterator; | 49 typedef const Attribute* const_iterator; |
50 | 50 |
51 AttributeCollection(const Attribute* array, unsigned size) | 51 AttributeCollection(const Attribute* array, unsigned size) |
52 : m_array(array) | 52 : m_array(array) |
53 , m_size(size) | 53 , m_size(size) |
54 { } | 54 { } |
55 | 55 |
56 const Attribute& operator[](unsigned index) const { return at(index); } | |
57 const Attribute& at(unsigned index) const | |
58 { | |
59 RELEASE_ASSERT(index < m_size); | |
60 return m_array[index]; | |
61 } | |
62 | |
63 const Attribute* get(const QualifiedName&) const; | |
64 const Attribute* get(const AtomicString& name, bool shouldIgnoreCase) const; | |
65 size_t find(const QualifiedName&, bool shouldIgnoreCase = false) const; | |
66 size_t find(const AtomicString& name, bool shouldIgnoreCase) const; | |
67 size_t find(Attr*) const; | |
esprehn
2014/06/26 22:03:58
We're going to have to be really careful here, ori
Inactive
2014/06/26 22:16:40
To be fair, they were called getAttributeItem() /
| |
68 | |
56 const_iterator begin() const { return m_array; } | 69 const_iterator begin() const { return m_array; } |
57 const_iterator end() const { return m_array + m_size; } | 70 const_iterator end() const { return m_array + m_size; } |
58 | 71 |
59 unsigned size() const { return m_size; } | 72 unsigned size() const { return m_size; } |
73 bool isEmpty() const { return !m_size; } | |
60 | 74 |
61 private: | 75 private: |
76 size_t findSlowCase(const AtomicString& name, bool shouldIgnoreAttributeCase ) const; | |
77 | |
62 const Attribute* m_array; | 78 const Attribute* m_array; |
63 unsigned m_size; | 79 unsigned m_size; |
64 }; | 80 }; |
65 | 81 |
66 // ElementData represents very common, but not necessarily unique to an element, | 82 // ElementData represents very common, but not necessarily unique to an element, |
67 // data such as attributes, inline style, and parsed class names and ids. | 83 // data such as attributes, inline style, and parsed class names and ids. |
68 class ElementData : public RefCountedWillBeGarbageCollectedFinalized<ElementData > { | 84 class ElementData : public RefCountedWillBeGarbageCollectedFinalized<ElementData > { |
69 WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED; | 85 WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED; |
70 public: | 86 public: |
71 #if ENABLE(OILPAN) | 87 #if ENABLE(OILPAN) |
(...skipping 10 matching lines...) Expand all Loading... | |
82 void setClass(const AtomicString& className, bool shouldFoldCase) const { m_ classNames.set(className, shouldFoldCase); } | 98 void setClass(const AtomicString& className, bool shouldFoldCase) const { m_ classNames.set(className, shouldFoldCase); } |
83 const SpaceSplitString& classNames() const { return m_classNames; } | 99 const SpaceSplitString& classNames() const { return m_classNames; } |
84 | 100 |
85 const AtomicString& idForStyleResolution() const { return m_idForStyleResolu tion; } | 101 const AtomicString& idForStyleResolution() const { return m_idForStyleResolu tion; } |
86 void setIdForStyleResolution(const AtomicString& newId) const { m_idForStyle Resolution = newId; } | 102 void setIdForStyleResolution(const AtomicString& newId) const { m_idForStyle Resolution = newId; } |
87 | 103 |
88 const StylePropertySet* inlineStyle() const { return m_inlineStyle.get(); } | 104 const StylePropertySet* inlineStyle() const { return m_inlineStyle.get(); } |
89 | 105 |
90 const StylePropertySet* presentationAttributeStyle() const; | 106 const StylePropertySet* presentationAttributeStyle() const; |
91 | 107 |
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; | 108 AttributeCollection attributes() const; |
97 | 109 |
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(); } | 110 bool hasID() const { return !m_idForStyleResolution.isNull(); } |
105 bool hasClass() const { return !m_classNames.isNull(); } | 111 bool hasClass() const { return !m_classNames.isNull(); } |
106 | 112 |
107 bool isEquivalent(const ElementData* other) const; | 113 bool isEquivalent(const ElementData* other) const; |
108 | 114 |
109 bool isUnique() const { return m_isUnique; } | 115 bool isUnique() const { return m_isUnique; } |
110 | 116 |
111 void traceAfterDispatch(Visitor*); | 117 void traceAfterDispatch(Visitor*); |
112 void trace(Visitor*); | 118 void trace(Visitor*); |
113 | 119 |
(...skipping 16 matching lines...) Expand all Loading... | |
130 private: | 136 private: |
131 friend class Element; | 137 friend class Element; |
132 friend class ShareableElementData; | 138 friend class ShareableElementData; |
133 friend class UniqueElementData; | 139 friend class UniqueElementData; |
134 friend class SVGElement; | 140 friend class SVGElement; |
135 | 141 |
136 #if !ENABLE(OILPAN) | 142 #if !ENABLE(OILPAN) |
137 void destroy(); | 143 void destroy(); |
138 #endif | 144 #endif |
139 | 145 |
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; | 146 PassRefPtrWillBeRawPtr<UniqueElementData> makeUniqueCopy() const; |
145 }; | 147 }; |
146 | 148 |
147 #if COMPILER(MSVC) | 149 #if COMPILER(MSVC) |
148 #pragma warning(push) | 150 #pragma warning(push) |
149 #pragma warning(disable: 4200) // Disable "zero-sized array in struct/union" war ning | 151 #pragma warning(disable: 4200) // Disable "zero-sized array in struct/union" war ning |
150 #endif | 152 #endif |
151 | 153 |
152 // SharableElementData is managed by ElementDataCache and is produced by | 154 // SharableElementData is managed by ElementDataCache and is produced by |
153 // the parser during page load for elements that have identical attributes. This | 155 // 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 | 168 // Add support for placement new as ShareableElementData is not allocated |
167 // with a fixed size. Instead the allocated memory size is computed based on | 169 // 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 | 170 // the number of attributes. This requires us to use Heap::allocate directly |
169 // with the computed size and subsequently call placement new with the | 171 // with the computed size and subsequently call placement new with the |
170 // allocated memory address. | 172 // allocated memory address. |
171 void* operator new(std::size_t, void* location) | 173 void* operator new(std::size_t, void* location) |
172 { | 174 { |
173 return location; | 175 return location; |
174 } | 176 } |
175 | 177 |
178 AttributeCollection attributes() const; | |
179 | |
176 Attribute m_attributeArray[0]; | 180 Attribute m_attributeArray[0]; |
177 }; | 181 }; |
178 | 182 |
179 #if COMPILER(MSVC) | 183 #if COMPILER(MSVC) |
180 #pragma warning(pop) | 184 #pragma warning(pop) |
181 #endif | 185 #endif |
182 | 186 |
183 // UniqueElementData is created when an element needs to mutate its attributes | 187 // 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 | 188 // 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 | 189 // 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 | 190 // attributes. For example populating the m_inlineStyle from the style attribute |
187 // doesn't require a UniqueElementData as all elements with the same style | 191 // doesn't require a UniqueElementData as all elements with the same style |
188 // attribute will have the same inline style. | 192 // attribute will have the same inline style. |
189 class UniqueElementData FINAL : public ElementData { | 193 class UniqueElementData FINAL : public ElementData { |
190 public: | 194 public: |
191 static PassRefPtrWillBeRawPtr<UniqueElementData> create(); | 195 static PassRefPtrWillBeRawPtr<UniqueElementData> create(); |
192 PassRefPtrWillBeRawPtr<ShareableElementData> makeShareableCopy() const; | 196 PassRefPtrWillBeRawPtr<ShareableElementData> makeShareableCopy() const; |
193 | 197 |
194 // These functions do no error/duplicate checking. | 198 // These functions do no error/duplicate checking. |
195 void appendAttribute(const QualifiedName&, const AtomicString&); | 199 void appendAttribute(const QualifiedName&, const AtomicString&); |
196 void removeAttributeAt(size_t index); | 200 void removeAttributeAt(size_t index); |
197 | 201 |
202 AttributeCollection attributes() const; | |
203 | |
198 Attribute& attributeAt(unsigned index); | 204 Attribute& attributeAt(unsigned index); |
199 Attribute* findAttributeByName(const QualifiedName&); | 205 Attribute* findAttributeByName(const QualifiedName&); |
200 | 206 |
201 UniqueElementData(); | 207 UniqueElementData(); |
202 explicit UniqueElementData(const ShareableElementData&); | 208 explicit UniqueElementData(const ShareableElementData&); |
203 explicit UniqueElementData(const UniqueElementData&); | 209 explicit UniqueElementData(const UniqueElementData&); |
204 | 210 |
205 void traceAfterDispatch(Visitor*); | 211 void traceAfterDispatch(Visitor*); |
206 | 212 |
207 // FIXME: We might want to support sharing element data for elements with | 213 // FIXME: We might want to support sharing element data for elements with |
208 // presentation attribute style. Lots of table cells likely have the same | 214 // presentation attribute style. Lots of table cells likely have the same |
209 // attributes. Most modern pages don't use presentation attributes though | 215 // attributes. Most modern pages don't use presentation attributes though |
210 // so this might not make sense. | 216 // so this might not make sense. |
211 mutable RefPtrWillBeMember<StylePropertySet> m_presentationAttributeStyle; | 217 mutable RefPtrWillBeMember<StylePropertySet> m_presentationAttributeStyle; |
212 Vector<Attribute, 4> m_attributeVector; | 218 Vector<Attribute, 4> m_attributeVector; |
213 }; | 219 }; |
214 | 220 |
215 #if !ENABLE(OILPAN) | 221 #if !ENABLE(OILPAN) |
216 inline void ElementData::deref() | 222 inline void ElementData::deref() |
217 { | 223 { |
218 if (!derefBase()) | 224 if (!derefBase()) |
219 return; | 225 return; |
220 destroy(); | 226 destroy(); |
221 } | 227 } |
222 #endif | 228 #endif |
223 | 229 |
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 | 230 inline const StylePropertySet* ElementData::presentationAttributeStyle() const |
232 { | 231 { |
233 if (!m_isUnique) | 232 if (!m_isUnique) |
234 return 0; | 233 return 0; |
235 return static_cast<const UniqueElementData*>(this)->m_presentationAttributeS tyle.get(); | 234 return static_cast<const UniqueElementData*>(this)->m_presentationAttributeS tyle.get(); |
236 } | 235 } |
237 | 236 |
238 inline const Attribute* ElementData::findAttributeByName(const AtomicString& nam e, bool shouldIgnoreAttributeCase) const | 237 inline const Attribute* AttributeCollection::get(const AtomicString& name, bool shouldIgnoreCase) const |
239 { | 238 { |
240 size_t index = findAttributeIndexByName(name, shouldIgnoreAttributeCase); | 239 size_t index = find(name, shouldIgnoreCase); |
241 if (index != kNotFound) | 240 return index != kNotFound ? &at(index) : 0; |
242 return &attributeAt(index); | |
243 return 0; | |
244 } | 241 } |
245 | 242 |
246 inline const Attribute* ElementData::attributeBase() const | 243 inline size_t AttributeCollection::find(const QualifiedName& name, bool shouldIg noreCase) const |
247 { | 244 { |
248 if (m_isUnique) | 245 const_iterator end = this->end(); |
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; | 246 unsigned index = 0; |
258 for (AttributeCollection::const_iterator it = attributes.begin(); it != end; ++it, ++index) { | 247 for (const_iterator it = begin(); it != end; ++it, ++index) { |
259 if (it->name().matchesPossiblyIgnoringCase(name, shouldIgnoreCase)) | 248 if (it->name().matchesPossiblyIgnoringCase(name, shouldIgnoreCase)) |
260 return index; | 249 return index; |
261 } | 250 } |
262 return kNotFound; | 251 return kNotFound; |
263 } | 252 } |
264 | 253 |
265 // We use a boolean parameter instead of calling shouldIgnoreAttributeCase so th at the caller | 254 // 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). | 255 // 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 | 256 inline size_t AttributeCollection::find(const AtomicString& name, bool shouldIgn oreCase) const |
268 { | 257 { |
269 bool doSlowCheck = shouldIgnoreAttributeCase; | 258 bool doSlowCheck = shouldIgnoreCase; |
270 | 259 |
271 // Optimize for the case where the attribute exists and its name exactly mat ches. | 260 // Optimize for the case where the attribute exists and its name exactly mat ches. |
272 AttributeCollection attributes = this->attributes(); | 261 const_iterator end = this->end(); |
273 AttributeCollection::const_iterator end = attributes.end(); | |
274 unsigned index = 0; | 262 unsigned index = 0; |
275 for (AttributeCollection::const_iterator it = attributes.begin(); it != end; ++it, ++index) { | 263 for (const_iterator it = begin(); it != end; ++it, ++index) { |
276 // FIXME: Why check the prefix? Namespaces should be all that matter. | 264 // FIXME: Why check the prefix? Namespaces should be all that matter. |
277 // Most attributes (all of HTML and CSS) have no namespace. | 265 // Most attributes (all of HTML and CSS) have no namespace. |
278 if (!it->name().hasPrefix()) { | 266 if (!it->name().hasPrefix()) { |
279 if (name == it->localName()) | 267 if (name == it->localName()) |
280 return index; | 268 return index; |
281 } else { | 269 } else { |
282 doSlowCheck = true; | 270 doSlowCheck = true; |
283 } | 271 } |
284 } | 272 } |
285 | 273 |
286 if (doSlowCheck) | 274 if (doSlowCheck) |
287 return findAttributeIndexByNameSlowCase(name, shouldIgnoreAttributeCase) ; | 275 return findSlowCase(name, shouldIgnoreCase); |
288 return kNotFound; | 276 return kNotFound; |
289 } | 277 } |
290 | 278 |
291 inline AttributeCollection ElementData::attributes() const | 279 inline AttributeCollection ElementData::attributes() const |
292 { | 280 { |
293 if (isUnique()) { | 281 if (isUnique()) |
294 const Vector<Attribute, 4>& attributeVector = static_cast<const UniqueEl ementData*>(this)->m_attributeVector; | 282 return static_cast<const UniqueElementData*>(this)->attributes(); |
295 return AttributeCollection(attributeVector.data(), attributeVector.size( )); | 283 return static_cast<const ShareableElementData*>(this)->attributes(); |
296 } | |
297 return AttributeCollection(static_cast<const ShareableElementData*>(this)->m _attributeArray, m_arraySize); | |
298 } | 284 } |
299 | 285 |
300 inline const Attribute* ElementData::findAttributeByName(const QualifiedName& na me) const | 286 inline AttributeCollection ShareableElementData::attributes() const |
301 { | 287 { |
302 AttributeCollection attributes = this->attributes(); | 288 return AttributeCollection(m_attributeArray, m_arraySize); |
303 AttributeCollection::const_iterator end = attributes.end(); | 289 } |
304 for (AttributeCollection::const_iterator it = attributes.begin(); it != end; ++it) { | 290 |
291 inline AttributeCollection UniqueElementData::attributes() const | |
292 { | |
293 return AttributeCollection(m_attributeVector.data(), m_attributeVector.size( )); | |
294 } | |
295 | |
296 inline const Attribute* AttributeCollection::get(const QualifiedName& name) cons t | |
297 { | |
298 const_iterator end = this->end(); | |
299 for (const_iterator it = begin(); it != end; ++it) { | |
305 if (it->name().matches(name)) | 300 if (it->name().matches(name)) |
306 return it; | 301 return it; |
307 } | 302 } |
308 return 0; | 303 return 0; |
309 } | 304 } |
310 | 305 |
311 inline const Attribute& ElementData::attributeAt(unsigned index) const | |
312 { | |
313 RELEASE_ASSERT(index < attributeCount()); | |
314 ASSERT(attributeBase() + index); | |
315 return *(attributeBase() + index); | |
316 } | |
317 | |
318 inline void UniqueElementData::appendAttribute(const QualifiedName& attributeNam e, const AtomicString& value) | 306 inline void UniqueElementData::appendAttribute(const QualifiedName& attributeNam e, const AtomicString& value) |
319 { | 307 { |
320 m_attributeVector.append(Attribute(attributeName, value)); | 308 m_attributeVector.append(Attribute(attributeName, value)); |
321 } | 309 } |
322 | 310 |
323 inline void UniqueElementData::removeAttributeAt(size_t index) | 311 inline void UniqueElementData::removeAttributeAt(size_t index) |
324 { | 312 { |
325 m_attributeVector.remove(index); | 313 m_attributeVector.remove(index); |
326 } | 314 } |
327 | 315 |
328 inline Attribute& UniqueElementData::attributeAt(unsigned index) | 316 inline Attribute& UniqueElementData::attributeAt(unsigned index) |
329 { | 317 { |
330 return m_attributeVector.at(index); | 318 return m_attributeVector.at(index); |
331 } | 319 } |
332 | 320 |
333 } // namespace WebCore | 321 } // namespace WebCore |
334 | 322 |
335 #endif // ElementData_h | 323 #endif // ElementData_h |
OLD | NEW |