| 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 |