1/*
2 * Copyright (C) 2008, 2009, 2010, 2014, 2016 Apple Inc. All rights reserved.
3 * Copyright (C) 2008 David Smith <catfish.man@gmail.com>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 *
20 */
21
22#pragma once
23
24#include "CustomElementReactionQueue.h"
25#include "DOMTokenList.h"
26#include "DatasetDOMStringMap.h"
27#include "IntersectionObserver.h"
28#include "NamedNodeMap.h"
29#include "NodeRareData.h"
30#include "PseudoElement.h"
31#include "RenderElement.h"
32#include "ResizeObserver.h"
33#include "ShadowRoot.h"
34#include "StylePropertyMap.h"
35
36namespace WebCore {
37
38inline IntSize defaultMinimumSizeForResizing()
39{
40 return IntSize(LayoutUnit::max(), LayoutUnit::max());
41}
42
43class ElementRareData : public NodeRareData {
44public:
45 explicit ElementRareData(RenderElement*);
46 ~ElementRareData();
47
48 void setBeforePseudoElement(RefPtr<PseudoElement>&&);
49 void setAfterPseudoElement(RefPtr<PseudoElement>&&);
50
51 PseudoElement* beforePseudoElement() const { return m_beforePseudoElement.get(); }
52 PseudoElement* afterPseudoElement() const { return m_afterPseudoElement.get(); }
53
54 void resetComputedStyle();
55 void resetStyleRelations();
56
57 int tabIndex() const { return m_tabIndex; }
58 void setTabIndexExplicitly(int index) { m_tabIndex = index; m_tabIndexWasSetExplicitly = true; }
59 bool tabIndexSetExplicitly() const { return m_tabIndexWasSetExplicitly; }
60 void clearTabIndexExplicitly() { m_tabIndex = 0; m_tabIndexWasSetExplicitly = false; }
61
62 bool styleAffectedByActive() const { return m_styleAffectedByActive; }
63 void setStyleAffectedByActive(bool value) { m_styleAffectedByActive = value; }
64
65 bool styleAffectedByEmpty() const { return m_styleAffectedByEmpty; }
66 void setStyleAffectedByEmpty(bool value) { m_styleAffectedByEmpty = value; }
67
68 bool styleAffectedByFocusWithin() const { return m_styleAffectedByFocusWithin; }
69 void setStyleAffectedByFocusWithin(bool value) { m_styleAffectedByFocusWithin = value; }
70
71#if ENABLE(FULLSCREEN_API)
72 bool containsFullScreenElement() { return m_containsFullScreenElement; }
73 void setContainsFullScreenElement(bool value) { m_containsFullScreenElement = value; }
74#endif
75
76 bool childrenAffectedByDrag() const { return m_childrenAffectedByDrag; }
77 void setChildrenAffectedByDrag(bool value) { m_childrenAffectedByDrag = value; }
78
79 bool childrenAffectedByLastChildRules() const { return m_childrenAffectedByLastChildRules; }
80 void setChildrenAffectedByLastChildRules(bool value) { m_childrenAffectedByLastChildRules = value; }
81 bool childrenAffectedByForwardPositionalRules() const { return m_childrenAffectedByForwardPositionalRules; }
82 void setChildrenAffectedByForwardPositionalRules(bool value) { m_childrenAffectedByForwardPositionalRules = value; }
83 bool descendantsAffectedByForwardPositionalRules() const { return m_descendantsAffectedByForwardPositionalRules; }
84 void setDescendantsAffectedByForwardPositionalRules(bool value) { m_descendantsAffectedByForwardPositionalRules = value; }
85 bool childrenAffectedByBackwardPositionalRules() const { return m_childrenAffectedByBackwardPositionalRules; }
86 void setChildrenAffectedByBackwardPositionalRules(bool value) { m_childrenAffectedByBackwardPositionalRules = value; }
87 bool descendantsAffectedByBackwardPositionalRules() const { return m_descendantsAffectedByBackwardPositionalRules; }
88 void setDescendantsAffectedByBackwardPositionalRules(bool value) { m_descendantsAffectedByBackwardPositionalRules = value; }
89 bool childrenAffectedByPropertyBasedBackwardPositionalRules() const { return m_childrenAffectedByPropertyBasedBackwardPositionalRules; }
90 void setChildrenAffectedByPropertyBasedBackwardPositionalRules(bool value) { m_childrenAffectedByPropertyBasedBackwardPositionalRules = value; }
91
92 unsigned childIndex() const { return m_childIndex; }
93 void setChildIndex(unsigned index) { m_childIndex = index; }
94 static ptrdiff_t childIndexMemoryOffset() { return OBJECT_OFFSETOF(ElementRareData, m_childIndex); }
95
96 void clearShadowRoot() { m_shadowRoot = nullptr; }
97 ShadowRoot* shadowRoot() const { return m_shadowRoot.get(); }
98 void setShadowRoot(RefPtr<ShadowRoot>&& shadowRoot) { m_shadowRoot = WTFMove(shadowRoot); }
99
100 CustomElementReactionQueue* customElementReactionQueue() { return m_customElementReactionQueue.get(); }
101 void setCustomElementReactionQueue(std::unique_ptr<CustomElementReactionQueue>&& queue) { m_customElementReactionQueue = WTFMove(queue); }
102
103 NamedNodeMap* attributeMap() const { return m_attributeMap.get(); }
104 void setAttributeMap(std::unique_ptr<NamedNodeMap> attributeMap) { m_attributeMap = WTFMove(attributeMap); }
105
106 RenderStyle* computedStyle() const { return m_computedStyle.get(); }
107 void setComputedStyle(std::unique_ptr<RenderStyle> computedStyle) { m_computedStyle = WTFMove(computedStyle); }
108
109 DOMTokenList* classList() const { return m_classList.get(); }
110 void setClassList(std::unique_ptr<DOMTokenList> classList) { m_classList = WTFMove(classList); }
111
112 DatasetDOMStringMap* dataset() const { return m_dataset.get(); }
113 void setDataset(std::unique_ptr<DatasetDOMStringMap> dataset) { m_dataset = WTFMove(dataset); }
114
115 LayoutSize minimumSizeForResizing() const { return m_minimumSizeForResizing; }
116 void setMinimumSizeForResizing(LayoutSize size) { m_minimumSizeForResizing = size; }
117
118 IntPoint savedLayerScrollPosition() const { return m_savedLayerScrollPosition; }
119 void setSavedLayerScrollPosition(IntPoint position) { m_savedLayerScrollPosition = position; }
120
121 bool hasPendingResources() const { return m_hasPendingResources; }
122 void setHasPendingResources(bool has) { m_hasPendingResources = has; }
123
124 bool hasCSSAnimation() const { return m_hasCSSAnimation; }
125 void setHasCSSAnimation(bool value) { m_hasCSSAnimation = value; }
126
127 bool hasElementIdentifier() const { return m_hasElementIdentifier; }
128 void setHasElementIdentifier(bool value) { m_hasElementIdentifier = value; }
129
130#if ENABLE(INTERSECTION_OBSERVER)
131 IntersectionObserverData* intersectionObserverData() { return m_intersectionObserverData.get(); }
132 void setIntersectionObserverData(std::unique_ptr<IntersectionObserverData>&& data) { m_intersectionObserverData = WTFMove(data); }
133#endif
134
135#if ENABLE(RESIZE_OBSERVER)
136 ResizeObserverData* resizeObserverData() { return m_resizeObserverData.get(); }
137 void setResizeObserverData(std::unique_ptr<ResizeObserverData>&& data) { m_resizeObserverData = WTFMove(data); }
138#endif
139
140#if ENABLE(CSS_TYPED_OM)
141 StylePropertyMap* attributeStyleMap() { return m_attributeStyleMap.get(); }
142 void setAttributeStyleMap(Ref<StylePropertyMap>&& map) { m_attributeStyleMap = WTFMove(map); }
143#endif
144
145#if DUMP_NODE_STATISTICS
146 OptionSet<UseType> useTypes() const
147 {
148 auto result = NodeRareData::useTypes();
149 if (m_tabIndexWasSetExplicitly)
150 result.add(UseType::TabIndex);
151 if (m_styleAffectedByActive || m_styleAffectedByEmpty || m_styleAffectedByFocusWithin || m_childrenAffectedByHover
152 || m_childrenAffectedByDrag || m_childrenAffectedByLastChildRules || m_childrenAffectedByForwardPositionalRules
153 || m_descendantsAffectedByForwardPositionalRules || m_childrenAffectedByBackwardPositionalRules
154 || m_descendantsAffectedByBackwardPositionalRules || m_childrenAffectedByPropertyBasedBackwardPositionalRules)
155 result.add(UseType::StyleFlags);
156 if (m_minimumSizeForResizing != defaultMinimumSizeForResizing())
157 result.add(UseType::MinimumSize);
158 if (!m_savedLayerScrollPosition.isZero())
159 result.add(UseType::ScrollingPosition);
160 if (m_computedStyle)
161 result.add(UseType::ComputedStyle);
162 if (m_dataset)
163 result.add(UseType::Dataset);
164 if (m_classList)
165 result.add(UseType::ClassList);
166 if (m_shadowRoot)
167 result.add(UseType::ShadowRoot);
168 if (m_customElementReactionQueue)
169 result.add(UseType::CustomElementQueue);
170 if (m_attributeMap)
171 result.add(UseType::AttributeMap);
172 if (m_intersectionObserverData)
173 result.add(UseType::InteractionObserver);
174#if ENABLE(RESIZE_OBSERVER)
175 if (m_resizeObserverData)
176 result.add(UseType::ResizeObserver);
177#endif
178 if (m_beforePseudoElement || m_afterPseudoElement)
179 result.add(UseType::PseudoElements);
180 return result;
181 }
182#endif
183
184private:
185 int m_tabIndex;
186 unsigned short m_childIndex;
187 unsigned m_tabIndexWasSetExplicitly : 1;
188 unsigned m_styleAffectedByActive : 1;
189 unsigned m_styleAffectedByEmpty : 1;
190 unsigned m_styleAffectedByFocusWithin : 1;
191#if ENABLE(FULLSCREEN_API)
192 unsigned m_containsFullScreenElement : 1;
193#endif
194 unsigned m_hasPendingResources : 1;
195 unsigned m_hasCSSAnimation : 1;
196 unsigned m_hasElementIdentifier : 1;
197 unsigned m_childrenAffectedByHover : 1;
198 unsigned m_childrenAffectedByDrag : 1;
199 // Bits for dynamic child matching.
200 // We optimize for :first-child and :last-child. The other positional child selectors like nth-child or
201 // *-child-of-type, we will just give up and re-evaluate whenever children change at all.
202 unsigned m_childrenAffectedByLastChildRules : 1;
203 unsigned m_childrenAffectedByForwardPositionalRules : 1;
204 unsigned m_descendantsAffectedByForwardPositionalRules : 1;
205 unsigned m_childrenAffectedByBackwardPositionalRules : 1;
206 unsigned m_descendantsAffectedByBackwardPositionalRules : 1;
207 unsigned m_childrenAffectedByPropertyBasedBackwardPositionalRules : 1;
208
209 LayoutSize m_minimumSizeForResizing;
210 IntPoint m_savedLayerScrollPosition;
211 std::unique_ptr<RenderStyle> m_computedStyle;
212
213 std::unique_ptr<DatasetDOMStringMap> m_dataset;
214 std::unique_ptr<DOMTokenList> m_classList;
215 RefPtr<ShadowRoot> m_shadowRoot;
216 std::unique_ptr<CustomElementReactionQueue> m_customElementReactionQueue;
217 std::unique_ptr<NamedNodeMap> m_attributeMap;
218#if ENABLE(INTERSECTION_OBSERVER)
219 std::unique_ptr<IntersectionObserverData> m_intersectionObserverData;
220#endif
221
222#if ENABLE(RESIZE_OBSERVER)
223 std::unique_ptr<ResizeObserverData> m_resizeObserverData;
224#endif
225
226 RefPtr<PseudoElement> m_beforePseudoElement;
227 RefPtr<PseudoElement> m_afterPseudoElement;
228
229#if ENABLE(CSS_TYPED_OM)
230 RefPtr<StylePropertyMap> m_attributeStyleMap;
231#endif
232
233 void releasePseudoElement(PseudoElement*);
234};
235
236inline ElementRareData::ElementRareData(RenderElement* renderer)
237 : NodeRareData(renderer)
238 , m_tabIndex(0)
239 , m_childIndex(0)
240 , m_tabIndexWasSetExplicitly(false)
241 , m_styleAffectedByActive(false)
242 , m_styleAffectedByEmpty(false)
243 , m_styleAffectedByFocusWithin(false)
244#if ENABLE(FULLSCREEN_API)
245 , m_containsFullScreenElement(false)
246#endif
247 , m_hasPendingResources(false)
248 , m_hasCSSAnimation(false)
249 , m_hasElementIdentifier(false)
250 , m_childrenAffectedByHover(false)
251 , m_childrenAffectedByDrag(false)
252 , m_childrenAffectedByLastChildRules(false)
253 , m_childrenAffectedByForwardPositionalRules(false)
254 , m_descendantsAffectedByForwardPositionalRules(false)
255 , m_childrenAffectedByBackwardPositionalRules(false)
256 , m_descendantsAffectedByBackwardPositionalRules(false)
257 , m_childrenAffectedByPropertyBasedBackwardPositionalRules(false)
258 , m_minimumSizeForResizing(defaultMinimumSizeForResizing())
259{
260}
261
262inline ElementRareData::~ElementRareData()
263{
264 ASSERT(!m_shadowRoot);
265 ASSERT(!m_beforePseudoElement);
266 ASSERT(!m_afterPseudoElement);
267}
268
269inline void ElementRareData::setBeforePseudoElement(RefPtr<PseudoElement>&& pseudoElement)
270{
271 ASSERT(!m_beforePseudoElement || !pseudoElement);
272 m_beforePseudoElement = WTFMove(pseudoElement);
273}
274
275inline void ElementRareData::setAfterPseudoElement(RefPtr<PseudoElement>&& pseudoElement)
276{
277 ASSERT(!m_afterPseudoElement || !pseudoElement);
278 m_afterPseudoElement = WTFMove(pseudoElement);
279}
280
281inline void ElementRareData::resetComputedStyle()
282{
283 m_computedStyle = nullptr;
284}
285
286inline void ElementRareData::resetStyleRelations()
287{
288 setStyleAffectedByEmpty(false);
289 setStyleAffectedByFocusWithin(false);
290 setChildIndex(0);
291 setStyleAffectedByActive(false);
292 setChildrenAffectedByDrag(false);
293 setChildrenAffectedByLastChildRules(false);
294 setChildrenAffectedByForwardPositionalRules(false);
295 setDescendantsAffectedByForwardPositionalRules(false);
296 setChildrenAffectedByBackwardPositionalRules(false);
297 setDescendantsAffectedByBackwardPositionalRules(false);
298 setChildrenAffectedByPropertyBasedBackwardPositionalRules(false);
299}
300
301} // namespace WebCore
302