Element Traversal is not just Elements anymore
[WebKit-https.git] / Source / WebCore / dom / ContainerNode.h
1 /*
2  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
4  *           (C) 2001 Dirk Mueller (mueller@kde.org)
5  * Copyright (C) 2004-2015 Apple Inc. All rights reserved.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public License
18  * along with this library; see the file COPYING.LIB.  If not, write to
19  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  *
22  */
23
24 #ifndef ContainerNode_h
25 #define ContainerNode_h
26
27 #include "ExceptionCodePlaceholder.h"
28 #include "Node.h"
29
30 namespace WebCore {
31
32 class QualifiedName;
33 class RenderElement;
34
35 typedef void (*NodeCallback)(Node&, unsigned);
36
37 namespace Private { 
38     template<class GenericNode, class GenericNodeContainer>
39     void addChildNodesToDeletionQueue(GenericNode*& head, GenericNode*& tail, GenericNodeContainer&);
40 };
41
42 class NoEventDispatchAssertion {
43 public:
44     NoEventDispatchAssertion()
45     {
46 #if !ASSERT_DISABLED
47         if (!isMainThread())
48             return;
49         ++s_count;
50 #endif
51     }
52
53     NoEventDispatchAssertion(const NoEventDispatchAssertion&)
54         : NoEventDispatchAssertion()
55     {
56     }
57
58     ~NoEventDispatchAssertion()
59     {
60 #if !ASSERT_DISABLED
61         if (!isMainThread())
62             return;
63         ASSERT(s_count);
64         s_count--;
65 #endif
66     }
67
68     static bool isEventDispatchForbidden()
69     {
70 #if ASSERT_DISABLED
71         return false;
72 #else
73         return isMainThread() && s_count;
74 #endif
75     }
76
77 #if !ASSERT_DISABLED
78
79 private:
80     WEBCORE_EXPORT static unsigned s_count;
81
82 #endif
83 };
84
85 class ContainerNode : public Node {
86 public:
87     virtual ~ContainerNode();
88
89     Node* firstChild() const { return m_firstChild; }
90     static ptrdiff_t firstChildMemoryOffset() { return OBJECT_OFFSETOF(ContainerNode, m_firstChild); }
91     Node* lastChild() const { return m_lastChild; }
92     bool hasChildNodes() const { return m_firstChild; }
93     bool hasOneChild() const { return m_firstChild && !m_firstChild->nextSibling(); }
94
95     bool directChildNeedsStyleRecalc() const { return getFlag(DirectChildNeedsStyleRecalcFlag); }
96     void setDirectChildNeedsStyleRecalc() { setFlag(DirectChildNeedsStyleRecalcFlag); }
97
98     WEBCORE_EXPORT unsigned countChildNodes() const;
99     WEBCORE_EXPORT Node* traverseToChildAt(unsigned) const;
100
101     bool insertBefore(PassRefPtr<Node> newChild, Node* refChild, ExceptionCode& = ASSERT_NO_EXCEPTION);
102     bool replaceChild(PassRefPtr<Node> newChild, Node* oldChild, ExceptionCode& = ASSERT_NO_EXCEPTION);
103     WEBCORE_EXPORT bool removeChild(Node* child, ExceptionCode& = ASSERT_NO_EXCEPTION);
104     WEBCORE_EXPORT bool appendChild(PassRefPtr<Node> newChild, ExceptionCode& = ASSERT_NO_EXCEPTION);
105
106     // These methods are only used during parsing.
107     // They don't send DOM mutation events or handle reparenting.
108     // However, arbitrary code may be run by beforeload handlers.
109     void parserAppendChild(PassRefPtr<Node>);
110     void parserRemoveChild(Node&);
111     void parserInsertBefore(PassRefPtr<Node> newChild, Node* refChild);
112
113     void removeChildren();
114     void takeAllChildrenFrom(ContainerNode*);
115
116     void cloneChildNodes(ContainerNode* clone);
117
118     enum ChildChangeType { ElementInserted, ElementRemoved, TextInserted, TextRemoved, TextChanged, AllChildrenRemoved, NonContentsChildChanged };
119     enum ChildChangeSource { ChildChangeSourceParser, ChildChangeSourceAPI };
120     struct ChildChange {
121         ChildChangeType type;
122         Element* previousSiblingElement;
123         Element* nextSiblingElement;
124         ChildChangeSource source;
125     };
126     virtual void childrenChanged(const ChildChange&);
127
128     void disconnectDescendantFrames();
129
130     using Node::setAttributeEventListener;
131     void setAttributeEventListener(const AtomicString& eventType, const QualifiedName& attributeName, const AtomicString& value);
132
133     RenderElement* renderer() const;
134
135     // Return a bounding box in absolute coordinates enclosing this node and all its descendants.
136     // This gives the area within which events may get handled by a hander registered on this node.
137     virtual LayoutRect absoluteEventHandlerBounds(bool& /* includesFixedPositionElements */) { return LayoutRect(); }
138
139     Element* querySelector(const String& selectors, ExceptionCode&);
140     RefPtr<NodeList> querySelectorAll(const String& selectors, ExceptionCode&);
141
142     RefPtr<NodeList> getElementsByTagName(const AtomicString&);
143     RefPtr<NodeList> getElementsByTagNameNS(const AtomicString& namespaceURI, const AtomicString& localName);
144     RefPtr<NodeList> getElementsByName(const String& elementName);
145     RefPtr<NodeList> getElementsByClassName(const AtomicString& classNames);
146     RefPtr<RadioNodeList> radioNodeList(const AtomicString&);
147
148     // From the ParentNode interface - https://dom.spec.whatwg.org/#interface-parentnode
149     Element* firstElementChild() const;
150     Element* lastElementChild() const;
151     unsigned childElementCount() const;
152
153 protected:
154     explicit ContainerNode(Document&, ConstructionType = CreateContainer);
155
156     template<class GenericNode, class GenericNodeContainer>
157     friend void appendChildToContainer(GenericNode* child, GenericNodeContainer&);
158
159     template<class GenericNode, class GenericNodeContainer>
160     friend void Private::addChildNodesToDeletionQueue(GenericNode*& head, GenericNode*& tail, GenericNodeContainer&);
161
162     void removeDetachedChildren();
163     void setFirstChild(Node* child) { m_firstChild = child; }
164     void setLastChild(Node* child) { m_lastChild = child; }
165
166 private:
167     void removeBetween(Node* previousChild, Node* nextChild, Node& oldChild);
168     void insertBeforeCommon(Node& nextChild, Node& oldChild);
169
170     void notifyChildInserted(Node& child, ChildChangeSource);
171     void notifyChildRemoved(Node& child, Node* previousSibling, Node* nextSibling, ChildChangeSource);
172
173     void updateTreeAfterInsertion(Node& child);
174
175     bool isContainerNode() const = delete;
176
177     void willRemoveChild(Node& child);
178
179     Node* m_firstChild;
180     Node* m_lastChild;
181 };
182
183 inline ContainerNode::ContainerNode(Document& document, ConstructionType type)
184     : Node(document, type)
185     , m_firstChild(0)
186     , m_lastChild(0)
187 {
188 }
189
190 inline unsigned Node::countChildNodes() const
191 {
192     if (!is<ContainerNode>(*this))
193         return 0;
194     return downcast<ContainerNode>(*this).countChildNodes();
195 }
196
197 inline Node* Node::traverseToChildAt(unsigned index) const
198 {
199     if (!is<ContainerNode>(*this))
200         return nullptr;
201     return downcast<ContainerNode>(*this).traverseToChildAt(index);
202 }
203
204 inline Node* Node::firstChild() const
205 {
206     if (!is<ContainerNode>(*this))
207         return nullptr;
208     return downcast<ContainerNode>(*this).firstChild();
209 }
210
211 inline Node* Node::lastChild() const
212 {
213     if (!is<ContainerNode>(*this))
214         return nullptr;
215     return downcast<ContainerNode>(*this).lastChild();
216 }
217
218 inline Node* Node::highestAncestor() const
219 {
220     Node* node = const_cast<Node*>(this);
221     Node* highest = node;
222     for (; node; node = node->parentNode())
223         highest = node;
224     return highest;
225 }
226
227 inline bool Node::needsNodeRenderingTraversalSlowPath() const
228 {
229     if (getFlag(NeedsNodeRenderingTraversalSlowPathFlag))
230         return true;
231     ContainerNode* parent = parentOrShadowHostNode();
232     return parent && parent->getFlag(NeedsNodeRenderingTraversalSlowPathFlag);
233 }
234
235 inline bool Node::isTreeScope() const
236 {
237     return &treeScope().rootNode() == this;
238 }
239
240 // This constant controls how much buffer is initially allocated
241 // for a Node Vector that is used to store child Nodes of a given Node.
242 // FIXME: Optimize the value.
243 const int initialNodeVectorSize = 11;
244 typedef Vector<Ref<Node>, initialNodeVectorSize> NodeVector;
245
246 inline void getChildNodes(Node& node, NodeVector& nodes)
247 {
248     ASSERT(nodes.isEmpty());
249     for (Node* child = node.firstChild(); child; child = child->nextSibling())
250         nodes.append(*child);
251 }
252
253 class ChildNodesLazySnapshot {
254     WTF_MAKE_NONCOPYABLE(ChildNodesLazySnapshot);
255     WTF_MAKE_FAST_ALLOCATED;
256 public:
257     explicit ChildNodesLazySnapshot(Node& parentNode)
258         : m_currentNode(parentNode.firstChild())
259         , m_currentIndex(0)
260         , m_hasSnapshot(false)
261     {
262         m_nextSnapshot = latestSnapshot;
263         latestSnapshot = this;
264     }
265
266     ALWAYS_INLINE ~ChildNodesLazySnapshot()
267     {
268         latestSnapshot = m_nextSnapshot;
269     }
270
271     // Returns 0 if there is no next Node.
272     RefPtr<Node> nextNode()
273     {
274         if (LIKELY(!hasSnapshot())) {
275             RefPtr<Node> node = m_currentNode.release();
276             if (node)
277                 m_currentNode = node->nextSibling();
278             return node.release();
279         }
280         if (m_currentIndex >= m_snapshot.size())
281             return 0;
282         return m_snapshot[m_currentIndex++];
283     }
284
285     void takeSnapshot()
286     {
287         if (hasSnapshot())
288             return;
289         m_hasSnapshot = true;
290         Node* node = m_currentNode.get();
291         while (node) {
292             m_snapshot.append(node);
293             node = node->nextSibling();
294         }
295     }
296
297     ChildNodesLazySnapshot* nextSnapshot() { return m_nextSnapshot; }
298     bool hasSnapshot() { return m_hasSnapshot; }
299
300     static void takeChildNodesLazySnapshot()
301     {
302         ChildNodesLazySnapshot* snapshot = latestSnapshot;
303         while (snapshot && !snapshot->hasSnapshot()) {
304             snapshot->takeSnapshot();
305             snapshot = snapshot->nextSnapshot();
306         }
307     }
308
309 private:
310     static ChildNodesLazySnapshot* latestSnapshot;
311
312     RefPtr<Node> m_currentNode;
313     unsigned m_currentIndex;
314     bool m_hasSnapshot;
315     Vector<RefPtr<Node>> m_snapshot; // Lazily instantiated.
316     ChildNodesLazySnapshot* m_nextSnapshot;
317 };
318
319 } // namespace WebCore
320
321 SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::ContainerNode)
322     static bool isType(const WebCore::Node& node) { return node.isContainerNode(); }
323 SPECIALIZE_TYPE_TRAITS_END()
324
325 #endif // ContainerNode_h