• 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.length())
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 isEmpty();
102 
103     unsigned len = length();
104     if (len != other->length())
105         return false;
106 
107     for (unsigned i = 0; i < len; i++) {
108         const Attribute* attribute = attributeItem(i);
109         const Attribute* otherAttr = other->getAttributeItem(attribute->name());
110         if (!otherAttr || attribute->value() != otherAttr->value())
111             return false;
112     }
113 
114     return true;
115 }
116 
getAttrIndex(Attr * attr) const117 size_t ElementData::getAttrIndex(Attr* attr) const
118 {
119     // This relies on the fact that Attr's QualifiedName == the Attribute's name.
120     for (unsigned i = 0; i < length(); ++i) {
121         if (attributeItem(i)->name() == attr->qualifiedName())
122             return i;
123     }
124     return kNotFound;
125 }
126 
getAttributeItemIndexSlowCase(const AtomicString & name,bool shouldIgnoreAttributeCase) const127 size_t ElementData::getAttributeItemIndexSlowCase(const AtomicString& name, bool shouldIgnoreAttributeCase) const
128 {
129     // Continue to checking case-insensitively and/or full namespaced names if necessary:
130     for (unsigned i = 0; i < length(); ++i) {
131         const Attribute* attribute = attributeItem(i);
132         // FIXME: Why check the prefix? Namespace is all that should matter
133         // and all HTML/SVG attributes have a null namespace!
134         if (!attribute->name().hasPrefix()) {
135             if (shouldIgnoreAttributeCase && equalIgnoringCase(name, attribute->localName()))
136                 return i;
137         } else {
138             // FIXME: Would be faster to do this comparison without calling toString, which
139             // generates a temporary string by concatenation. But this branch is only reached
140             // if the attribute name has a prefix, which is rare in HTML.
141             if (equalPossiblyIgnoringCase(name, attribute->name().toString(), shouldIgnoreAttributeCase))
142                 return i;
143         }
144     }
145     return kNotFound;
146 }
147 
ShareableElementData(const Vector<Attribute> & attributes)148 ShareableElementData::ShareableElementData(const Vector<Attribute>& attributes)
149     : ElementData(attributes.size())
150 {
151     for (unsigned i = 0; i < m_arraySize; ++i)
152         new (&m_attributeArray[i]) Attribute(attributes[i]);
153 }
154 
~ShareableElementData()155 ShareableElementData::~ShareableElementData()
156 {
157     for (unsigned i = 0; i < m_arraySize; ++i)
158         m_attributeArray[i].~Attribute();
159 }
160 
ShareableElementData(const UniqueElementData & other)161 ShareableElementData::ShareableElementData(const UniqueElementData& other)
162     : ElementData(other, false)
163 {
164     ASSERT(!other.m_presentationAttributeStyle);
165 
166     if (other.m_inlineStyle) {
167         ASSERT(!other.m_inlineStyle->hasCSSOMWrapper());
168         m_inlineStyle = other.m_inlineStyle->immutableCopyIfNeeded();
169     }
170 
171     for (unsigned i = 0; i < m_arraySize; ++i)
172         new (&m_attributeArray[i]) Attribute(other.m_attributeVector.at(i));
173 }
174 
createWithAttributes(const Vector<Attribute> & attributes)175 PassRefPtr<ShareableElementData> ShareableElementData::createWithAttributes(const Vector<Attribute>& attributes)
176 {
177     void* slot = WTF::fastMalloc(sizeForShareableElementDataWithAttributeCount(attributes.size()));
178     return adoptRef(new (slot) ShareableElementData(attributes));
179 }
180 
UniqueElementData()181 UniqueElementData::UniqueElementData()
182 {
183 }
184 
UniqueElementData(const UniqueElementData & other)185 UniqueElementData::UniqueElementData(const UniqueElementData& other)
186     : ElementData(other, true)
187     , m_presentationAttributeStyle(other.m_presentationAttributeStyle)
188     , m_attributeVector(other.m_attributeVector)
189 {
190     m_inlineStyle = other.m_inlineStyle ? other.m_inlineStyle->mutableCopy() : 0;
191 }
192 
UniqueElementData(const ShareableElementData & other)193 UniqueElementData::UniqueElementData(const ShareableElementData& other)
194     : ElementData(other, true)
195 {
196     // An ShareableElementData should never have a mutable inline StylePropertySet attached.
197     ASSERT(!other.m_inlineStyle || !other.m_inlineStyle->isMutable());
198     m_inlineStyle = other.m_inlineStyle;
199 
200     m_attributeVector.reserveCapacity(other.length());
201     for (unsigned i = 0; i < other.length(); ++i)
202         m_attributeVector.uncheckedAppend(other.m_attributeArray[i]);
203 }
204 
create()205 PassRefPtr<UniqueElementData> UniqueElementData::create()
206 {
207     return adoptRef(new UniqueElementData);
208 }
209 
makeShareableCopy() const210 PassRefPtr<ShareableElementData> UniqueElementData::makeShareableCopy() const
211 {
212     void* slot = WTF::fastMalloc(sizeForShareableElementDataWithAttributeCount(m_attributeVector.size()));
213     return adoptRef(new (slot) ShareableElementData(*this));
214 }
215 
getAttributeItem(const QualifiedName & name)216 Attribute* UniqueElementData::getAttributeItem(const QualifiedName& name)
217 {
218     for (unsigned i = 0; i < length(); ++i) {
219         if (m_attributeVector.at(i).name().matches(name))
220             return &m_attributeVector.at(i);
221     }
222     return 0;
223 }
224 
225 } // namespace WebCore
226