1 | /* |
2 | * Copyright (C) 2013, 2014 Apple 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 |
6 | * are met: |
7 | * 1. Redistributions of source code must retain the above copyright |
8 | * notice, this list of conditions and the following disclaimer. |
9 | * 2. Redistributions in binary form must reproduce the above copyright |
10 | * notice, this list of conditions and the following disclaimer in the |
11 | * documentation and/or other materials provided with the distribution. |
12 | * |
13 | * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY |
14 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
15 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
16 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR |
17 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
18 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
19 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
20 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
21 | * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
23 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
24 | */ |
25 | |
26 | #include "config.h" |
27 | #include "ElementData.h" |
28 | |
29 | #include "Attr.h" |
30 | #include "HTMLNames.h" |
31 | #include "StyleProperties.h" |
32 | #include "XMLNames.h" |
33 | |
34 | namespace WebCore { |
35 | |
36 | void ElementData::destroy() |
37 | { |
38 | if (is<UniqueElementData>(*this)) |
39 | delete downcast<UniqueElementData>(this); |
40 | else |
41 | delete downcast<ShareableElementData>(this); |
42 | } |
43 | |
44 | ElementData::ElementData() |
45 | : m_arraySizeAndFlags(s_flagIsUnique) |
46 | { |
47 | } |
48 | |
49 | ElementData::ElementData(unsigned arraySize) |
50 | : m_arraySizeAndFlags(arraySize << s_flagCount) |
51 | { |
52 | } |
53 | |
54 | struct SameSizeAsElementData : public RefCounted<SameSizeAsElementData> { |
55 | unsigned bitfield; |
56 | void* refPtrs[3]; |
57 | }; |
58 | |
59 | COMPILE_ASSERT(sizeof(ElementData) == sizeof(SameSizeAsElementData), element_attribute_data_should_stay_small); |
60 | |
61 | static size_t sizeForShareableElementDataWithAttributeCount(unsigned count) |
62 | { |
63 | return sizeof(ShareableElementData) + sizeof(Attribute) * count; |
64 | } |
65 | |
66 | Ref<ShareableElementData> ShareableElementData::createWithAttributes(const Vector<Attribute>& attributes) |
67 | { |
68 | void* slot = WTF::fastMalloc(sizeForShareableElementDataWithAttributeCount(attributes.size())); |
69 | return adoptRef(*new (NotNull, slot) ShareableElementData(attributes)); |
70 | } |
71 | |
72 | Ref<UniqueElementData> UniqueElementData::create() |
73 | { |
74 | return adoptRef(*new UniqueElementData); |
75 | } |
76 | |
77 | ShareableElementData::ShareableElementData(const Vector<Attribute>& attributes) |
78 | : ElementData(attributes.size()) |
79 | { |
80 | unsigned attributeArraySize = arraySize(); |
81 | for (unsigned i = 0; i < attributeArraySize; ++i) |
82 | new (NotNull, &m_attributeArray[i]) Attribute(attributes[i]); |
83 | } |
84 | |
85 | ShareableElementData::~ShareableElementData() |
86 | { |
87 | unsigned attributeArraySize = arraySize(); |
88 | for (unsigned i = 0; i < attributeArraySize; ++i) |
89 | m_attributeArray[i].~Attribute(); |
90 | } |
91 | |
92 | ShareableElementData::ShareableElementData(const UniqueElementData& other) |
93 | : ElementData(other, false) |
94 | { |
95 | ASSERT(!other.m_presentationAttributeStyle); |
96 | |
97 | if (other.m_inlineStyle) { |
98 | ASSERT(!other.m_inlineStyle->hasCSSOMWrapper()); |
99 | m_inlineStyle = other.m_inlineStyle->immutableCopyIfNeeded(); |
100 | } |
101 | |
102 | unsigned attributeArraySize = arraySize(); |
103 | for (unsigned i = 0; i < attributeArraySize; ++i) |
104 | new (NotNull, &m_attributeArray[i]) Attribute(other.m_attributeVector.at(i)); |
105 | } |
106 | |
107 | inline uint32_t ElementData::arraySizeAndFlagsFromOther(const ElementData& other, bool isUnique) |
108 | { |
109 | if (isUnique) { |
110 | // Set isUnique and ignore arraySize. |
111 | return (other.m_arraySizeAndFlags | s_flagIsUnique) & s_flagsMask; |
112 | } |
113 | // Clear isUnique and set arraySize. |
114 | return (other.m_arraySizeAndFlags & (s_flagsMask & ~s_flagIsUnique)) | other.length() << s_flagCount; |
115 | } |
116 | |
117 | ElementData::ElementData(const ElementData& other, bool isUnique) |
118 | : m_arraySizeAndFlags(ElementData::arraySizeAndFlagsFromOther(other, isUnique)) |
119 | , m_classNames(other.m_classNames) |
120 | , m_idForStyleResolution(other.m_idForStyleResolution) |
121 | { |
122 | // NOTE: The inline style is copied by the subclass copy constructor since we don't know what to do with it here. |
123 | } |
124 | |
125 | UniqueElementData::UniqueElementData() |
126 | { |
127 | } |
128 | |
129 | UniqueElementData::UniqueElementData(const UniqueElementData& other) |
130 | : ElementData(other, true) |
131 | , m_presentationAttributeStyle(other.m_presentationAttributeStyle) |
132 | , m_attributeVector(other.m_attributeVector) |
133 | { |
134 | if (other.m_inlineStyle) |
135 | m_inlineStyle = other.m_inlineStyle->mutableCopy(); |
136 | } |
137 | |
138 | UniqueElementData::UniqueElementData(const ShareableElementData& other) |
139 | : ElementData(other, true) |
140 | { |
141 | // An ShareableElementData should never have a mutable inline StyleProperties attached. |
142 | ASSERT(!other.m_inlineStyle || !other.m_inlineStyle->isMutable()); |
143 | m_inlineStyle = other.m_inlineStyle; |
144 | |
145 | unsigned otherLength = other.length(); |
146 | m_attributeVector.reserveCapacity(otherLength); |
147 | for (unsigned i = 0; i < otherLength; ++i) |
148 | m_attributeVector.uncheckedAppend(other.m_attributeArray[i]); |
149 | } |
150 | |
151 | Ref<UniqueElementData> ElementData::makeUniqueCopy() const |
152 | { |
153 | if (isUnique()) |
154 | return adoptRef(*new UniqueElementData(static_cast<const UniqueElementData&>(*this))); |
155 | return adoptRef(*new UniqueElementData(static_cast<const ShareableElementData&>(*this))); |
156 | } |
157 | |
158 | Ref<ShareableElementData> UniqueElementData::makeShareableCopy() const |
159 | { |
160 | void* slot = WTF::fastMalloc(sizeForShareableElementDataWithAttributeCount(m_attributeVector.size())); |
161 | return adoptRef(*new (NotNull, slot) ShareableElementData(*this)); |
162 | } |
163 | |
164 | bool ElementData::isEquivalent(const ElementData* other) const |
165 | { |
166 | if (!other) |
167 | return isEmpty(); |
168 | |
169 | if (length() != other->length()) |
170 | return false; |
171 | |
172 | for (const Attribute& attribute : attributesIterator()) { |
173 | const Attribute* otherAttr = other->findAttributeByName(attribute.name()); |
174 | if (!otherAttr || attribute.value() != otherAttr->value()) |
175 | return false; |
176 | } |
177 | |
178 | return true; |
179 | } |
180 | |
181 | Attribute* UniqueElementData::findAttributeByName(const QualifiedName& name) |
182 | { |
183 | for (auto& attribute : m_attributeVector) { |
184 | if (attribute.name().matches(name)) |
185 | return &attribute; |
186 | } |
187 | return nullptr; |
188 | } |
189 | |
190 | const Attribute* ElementData::findLanguageAttribute() const |
191 | { |
192 | ASSERT(XMLNames::langAttr->localName() == HTMLNames::langAttr->localName()); |
193 | |
194 | const Attribute* attributes = attributeBase(); |
195 | // Spec: xml:lang takes precedence over html:lang -- http://www.w3.org/TR/xhtml1/#C_7 |
196 | const Attribute* languageAttribute = nullptr; |
197 | for (unsigned i = 0, count = length(); i < count; ++i) { |
198 | const QualifiedName& name = attributes[i].name(); |
199 | if (name.localName() != HTMLNames::langAttr->localName()) |
200 | continue; |
201 | if (name.namespaceURI() == XMLNames::langAttr->namespaceURI()) |
202 | return &attributes[i]; |
203 | if (name.namespaceURI() == HTMLNames::langAttr->namespaceURI()) |
204 | languageAttribute = &attributes[i]; |
205 | } |
206 | return languageAttribute; |
207 | } |
208 | |
209 | } |
210 | |
211 | |