• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2013 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *     * Neither the name of Google Inc. nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #include "config.h"
32 #include "core/dom/ElementData.h"
33 
34 #include "core/css/StylePropertySet.h"
35 #include "core/dom/Attr.h"
36 #include "core/dom/QualifiedName.h"
37 #include "wtf/Vector.h"
38 
39 namespace WebCore {
40 
41 struct SameSizeAsElementData : public RefCounted<SameSizeAsElementData> {
42     unsigned bitfield;
43     void* refPtrs[3];
44 };
45 
46 COMPILE_ASSERT(sizeof(ElementData) == sizeof(SameSizeAsElementData), element_attribute_data_should_stay_small);
47 
sizeForShareableElementDataWithAttributeCount(unsigned count)48 static size_t sizeForShareableElementDataWithAttributeCount(unsigned count)
49 {
50     return sizeof(ShareableElementData) + sizeof(Attribute) * count;
51 }
52 
ElementData()53 ElementData::ElementData()
54     : m_isUnique(true)
55     , m_arraySize(0)
56     , m_presentationAttributeStyleIsDirty(false)
57     , m_styleAttributeIsDirty(false)
58     , m_animatedSVGAttributesAreDirty(false)
59 {
60 }
61 
ElementData(unsigned arraySize)62 ElementData::ElementData(unsigned arraySize)
63     : m_isUnique(false)
64     , m_arraySize(arraySize)
65     , m_presentationAttributeStyleIsDirty(false)
66     , m_styleAttributeIsDirty(false)
67     , m_animatedSVGAttributesAreDirty(false)
68 {
69 }
70 
ElementData(const ElementData & other,bool isUnique)71 ElementData::ElementData(const ElementData& other, bool isUnique)
72     : m_isUnique(isUnique)
73     , m_arraySize(isUnique ? 0 : other.attributeCount())
74     , m_presentationAttributeStyleIsDirty(other.m_presentationAttributeStyleIsDirty)
75     , m_styleAttributeIsDirty(other.m_styleAttributeIsDirty)
76     , m_animatedSVGAttributesAreDirty(other.m_animatedSVGAttributesAreDirty)
77     , m_classNames(other.m_classNames)
78     , m_idForStyleResolution(other.m_idForStyleResolution)
79 {
80     // NOTE: The inline style is copied by the subclass copy constructor since we don't know what to do with it here.
81 }
82 
destroy()83 void ElementData::destroy()
84 {
85     if (m_isUnique)
86         delete static_cast<UniqueElementData*>(this);
87     else
88         delete static_cast<ShareableElementData*>(this);
89 }
90 
makeUniqueCopy() const91 PassRefPtr<UniqueElementData> ElementData::makeUniqueCopy() const
92 {
93     if (isUnique())
94         return adoptRef(new UniqueElementData(static_cast<const UniqueElementData&>(*this)));
95     return adoptRef(new UniqueElementData(static_cast<const ShareableElementData&>(*this)));
96 }
97 
isEquivalent(const ElementData * other) const98 bool ElementData::isEquivalent(const ElementData* other) const
99 {
100     if (!other)
101         return !hasAttributes();
102 
103     AttributeCollection attributes = this->attributes();
104     if (attributes.size() != other->attributeCount())
105         return false;
106 
107     AttributeCollection::const_iterator end = attributes.end();
108     for (AttributeCollection::const_iterator it = attributes.begin(); it != end; ++it) {
109         const Attribute* otherAttr = other->findAttributeByName(it->name());
110         if (!otherAttr || it->value() != otherAttr->value())
111             return false;
112     }
113     return true;
114 }
115 
findAttrNodeIndex(Attr * attr) const116 size_t ElementData::findAttrNodeIndex(Attr* attr) const
117 {
118     // This relies on the fact that Attr's QualifiedName == the Attribute's name.
119     AttributeCollection attributes = this->attributes();
120     AttributeCollection::const_iterator end = attributes.end();
121     unsigned index = 0;
122     for (AttributeCollection::const_iterator it = attributes.begin(); it != end; ++it, ++index) {
123         if (it->name() == attr->qualifiedName())
124             return index;
125     }
126     return kNotFound;
127 }
128 
findAttributeIndexByNameSlowCase(const AtomicString & name,bool shouldIgnoreAttributeCase) const129 size_t ElementData::findAttributeIndexByNameSlowCase(const AtomicString& name, bool shouldIgnoreAttributeCase) const
130 {
131     // Continue to checking case-insensitively and/or full namespaced names if necessary:
132     AttributeCollection attributes = this->attributes();
133     AttributeCollection::const_iterator end = attributes.end();
134     unsigned index = 0;
135     for (AttributeCollection::const_iterator it = attributes.begin(); it != end; ++it, ++index) {
136         // FIXME: Why check the prefix? Namespace is all that should matter
137         // and all HTML/SVG attributes have a null namespace!
138         if (!it->name().hasPrefix()) {
139             if (shouldIgnoreAttributeCase && equalIgnoringCase(name, it->localName()))
140                 return index;
141         } else {
142             // FIXME: Would be faster to do this comparison without calling toString, which
143             // generates a temporary string by concatenation. But this branch is only reached
144             // if the attribute name has a prefix, which is rare in HTML.
145             if (equalPossiblyIgnoringCase(name, it->name().toString(), shouldIgnoreAttributeCase))
146                 return index;
147         }
148     }
149     return kNotFound;
150 }
151 
ShareableElementData(const Vector<Attribute> & attributes)152 ShareableElementData::ShareableElementData(const Vector<Attribute>& attributes)
153     : ElementData(attributes.size())
154 {
155     for (unsigned i = 0; i < m_arraySize; ++i)
156         new (&m_attributeArray[i]) Attribute(attributes[i]);
157 }
158 
~ShareableElementData()159 ShareableElementData::~ShareableElementData()
160 {
161     for (unsigned i = 0; i < m_arraySize; ++i)
162         m_attributeArray[i].~Attribute();
163 }
164 
ShareableElementData(const UniqueElementData & other)165 ShareableElementData::ShareableElementData(const UniqueElementData& other)
166     : ElementData(other, false)
167 {
168     ASSERT(!other.m_presentationAttributeStyle);
169 
170     if (other.m_inlineStyle) {
171         m_inlineStyle = other.m_inlineStyle->immutableCopyIfNeeded();
172     }
173 
174     for (unsigned i = 0; i < m_arraySize; ++i)
175         new (&m_attributeArray[i]) Attribute(other.m_attributeVector.at(i));
176 }
177 
createWithAttributes(const Vector<Attribute> & attributes)178 PassRefPtr<ShareableElementData> ShareableElementData::createWithAttributes(const Vector<Attribute>& attributes)
179 {
180     void* slot = WTF::fastMalloc(sizeForShareableElementDataWithAttributeCount(attributes.size()));
181     return adoptRef(new (slot) ShareableElementData(attributes));
182 }
183 
UniqueElementData()184 UniqueElementData::UniqueElementData()
185 {
186 }
187 
UniqueElementData(const UniqueElementData & other)188 UniqueElementData::UniqueElementData(const UniqueElementData& other)
189     : ElementData(other, true)
190     , m_presentationAttributeStyle(other.m_presentationAttributeStyle)
191     , m_attributeVector(other.m_attributeVector)
192 {
193     m_inlineStyle = other.m_inlineStyle ? other.m_inlineStyle->mutableCopy() : nullptr;
194 }
195 
UniqueElementData(const ShareableElementData & other)196 UniqueElementData::UniqueElementData(const ShareableElementData& other)
197     : ElementData(other, true)
198 {
199     // An ShareableElementData should never have a mutable inline StylePropertySet attached.
200     ASSERT(!other.m_inlineStyle || !other.m_inlineStyle->isMutable());
201     m_inlineStyle = other.m_inlineStyle;
202 
203     unsigned length = other.attributeCount();
204     m_attributeVector.reserveCapacity(length);
205     for (unsigned i = 0; i < length; ++i)
206         m_attributeVector.uncheckedAppend(other.m_attributeArray[i]);
207 }
208 
create()209 PassRefPtr<UniqueElementData> UniqueElementData::create()
210 {
211     return adoptRef(new UniqueElementData);
212 }
213 
makeShareableCopy() const214 PassRefPtr<ShareableElementData> UniqueElementData::makeShareableCopy() const
215 {
216     void* slot = WTF::fastMalloc(sizeForShareableElementDataWithAttributeCount(m_attributeVector.size()));
217     return adoptRef(new (slot) ShareableElementData(*this));
218 }
219 
findAttributeByName(const QualifiedName & name)220 Attribute* UniqueElementData::findAttributeByName(const QualifiedName& name)
221 {
222     unsigned length = m_attributeVector.size();
223     for (unsigned i = 0; i < length; ++i) {
224         if (m_attributeVector.at(i).name().matches(name))
225             return &m_attributeVector.at(i);
226     }
227     return 0;
228 }
229 
230 } // namespace WebCore
231