2 * Copyright (C) 2012 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Neither the name of Google Inc. nor the names of its
11 * contributors may be used to endorse or promote products derived from
12 * this software without specific prior written permission.
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
18 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
20 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 #ifndef ComposedTreeTraversal_h
28 #define ComposedTreeTraversal_h
30 #include "core/CoreExport.h"
31 #include "core/dom/Document.h"
32 #include "core/dom/LayoutTreeBuilderTraversal.h"
33 #include "core/dom/shadow/InsertionPoint.h"
34 #include "core/dom/shadow/ShadowRoot.h"
35 #include "wtf/Allocator.h"
42 // Composed tree version of |NodeTraversal|.
44 // None of member functions takes a |ShadowRoot| or an active insertion point,
45 // e.g. roughly speaking <content> and <shadow> in the shadow tree, see
46 // |InsertionPoint::isActive()| for details of active insertion points, since
47 // they aren't appeared in the composed tree. |assertPrecondition()| and
48 // |assertPostCondition()| check this condition.
50 // FIXME: Make some functions inline to optimise the performance.
51 // https://bugs.webkit.org/show_bug.cgi?id=82702
52 class CORE_EXPORT ComposedTreeTraversal
{
53 STATIC_ONLY(ComposedTreeTraversal
);
55 typedef LayoutTreeBuilderTraversal::ParentDetails ParentTraversalDetails
;
57 static Node
* next(const Node
&);
58 static Node
* next(const Node
&, const Node
* stayWithin
);
59 static Node
* previous(const Node
&);
61 static Node
* firstChild(const Node
&);
62 static Node
* lastChild(const Node
&);
63 static bool hasChildren(const Node
&);
65 static ContainerNode
* parent(const Node
&, ParentTraversalDetails
* = 0);
66 static Element
* parentElement(const Node
&);
68 static Node
* nextSibling(const Node
&);
69 static Node
* previousSibling(const Node
&);
71 // Returns a child node at |index|. If |index| is greater than or equal to
72 // the children, this function returns |nullptr|.
73 static Node
* childAt(const Node
&, unsigned index
);
75 // Composed tree version of |NodeTraversal::nextSkippingChildren()|. This
76 // function is similar to |next()| but skips child nodes of a specified
78 static Node
* nextSkippingChildren(const Node
&);
79 static Node
* nextSkippingChildren(const Node
&, const Node
* stayWithin
);
81 // Composed tree version of |NodeTraversal::previousSkippingChildren()|
82 // similar to |previous()| but skipping child nodes of the specified node.
83 static Node
* previousSkippingChildren(const Node
&);
85 // Like previous, but visits parents before their children.
86 static Node
* previousPostOrder(const Node
&, const Node
* stayWithin
= nullptr);
88 // Composed tree version of |Node::isDescendantOf(other)|. This function
89 // returns true if |other| contains |node|, otherwise returns
90 // false. If |other| is |node|, this function returns false.
91 static bool isDescendantOf(const Node
& /*node*/, const Node
& other
);
93 static bool contains(const ContainerNode
& container
, const Node
& node
)
95 assertPrecondition(container
);
96 assertPrecondition(node
);
97 return container
== node
|| isDescendantOf(node
, container
);
100 static bool containsIncludingPseudoElement(const ContainerNode
&, const Node
&);
102 // Returns a common ancestor of |nodeA| and |nodeB| if exists, otherwise
103 // returns |nullptr|.
104 static Node
* commonAncestor(const Node
& nodeA
, const Node
& nodeB
);
106 // Composed tree version of |Node::nodeIndex()|. This function returns a
107 // zero base position number of the specified node in child nodes list, or
108 // zero if the specified node has no parent.
109 static unsigned index(const Node
&);
111 // Composed tree version of |ContainerNode::countChildren()|. This function
112 // returns the number of the child nodes of the specified node in the
114 static unsigned countChildren(const Node
&);
116 static Node
* lastWithin(const Node
&);
117 static Node
& lastWithinOrSelf(const Node
&);
120 enum TraversalDirection
{
121 TraversalDirectionForward
,
122 TraversalDirectionBackward
125 static void assertPrecondition(const Node
& node
)
128 ASSERT(!node
.needsDistributionRecalc());
129 ASSERT(node
.canParticipateInComposedTree());
133 static void assertPostcondition(const Node
* node
)
137 assertPrecondition(*node
);
141 static Node
* traverseNode(const Node
&, TraversalDirection
);
142 static Node
* traverseLightChildren(const Node
&, TraversalDirection
);
144 static Node
* traverseNext(const Node
&);
145 static Node
* traverseNext(const Node
&, const Node
* stayWithin
);
146 static Node
* traverseNextSkippingChildren(const Node
&, const Node
* stayWithin
);
147 static Node
* traversePrevious(const Node
&);
149 static Node
* traverseFirstChild(const Node
&);
150 static Node
* traverseLastChild(const Node
&);
151 static Node
* traverseChild(const Node
&, TraversalDirection
);
153 static ContainerNode
* traverseParent(const Node
&, ParentTraversalDetails
* = 0);
155 static Node
* traverseNextSibling(const Node
&);
156 static Node
* traversePreviousSibling(const Node
&);
158 static Node
* traverseSiblingOrBackToInsertionPoint(const Node
&, TraversalDirection
);
159 static Node
* traverseSiblingInCurrentTree(const Node
&, TraversalDirection
);
161 static Node
* traverseSiblings(const Node
*, TraversalDirection
);
162 static Node
* traverseDistributedNodes(const Node
*, const InsertionPoint
&, TraversalDirection
);
164 static Node
* traverseBackToYoungerShadowRoot(const Node
&, TraversalDirection
);
166 static ContainerNode
* traverseParentOrHost(const Node
&);
167 static Node
* traverseNextAncestorSibling(const Node
&);
168 static Node
* traversePreviousAncestorSibling(const Node
&);
171 inline ContainerNode
* ComposedTreeTraversal::parent(const Node
& node
, ParentTraversalDetails
* details
)
173 assertPrecondition(node
);
174 ContainerNode
* result
= traverseParent(node
, details
);
175 assertPostcondition(result
);
179 inline Element
* ComposedTreeTraversal::parentElement(const Node
& node
)
181 ContainerNode
* parent
= ComposedTreeTraversal::parent(node
);
182 return parent
&& parent
->isElementNode() ? toElement(parent
) : nullptr;
185 inline Node
* ComposedTreeTraversal::nextSibling(const Node
& node
)
187 assertPrecondition(node
);
188 Node
* result
= traverseSiblingOrBackToInsertionPoint(node
, TraversalDirectionForward
);
189 assertPostcondition(result
);
193 inline Node
* ComposedTreeTraversal::previousSibling(const Node
& node
)
195 assertPrecondition(node
);
196 Node
* result
= traverseSiblingOrBackToInsertionPoint(node
, TraversalDirectionBackward
);
197 assertPostcondition(result
);
201 inline Node
* ComposedTreeTraversal::next(const Node
& node
)
203 assertPrecondition(node
);
204 Node
* result
= traverseNext(node
);
205 assertPostcondition(result
);
209 inline Node
* ComposedTreeTraversal::next(const Node
& node
, const Node
* stayWithin
)
211 assertPrecondition(node
);
212 Node
* result
= traverseNext(node
, stayWithin
);
213 assertPostcondition(result
);
217 inline Node
* ComposedTreeTraversal::nextSkippingChildren(const Node
& node
, const Node
* stayWithin
)
219 assertPrecondition(node
);
220 Node
* result
= traverseNextSkippingChildren(node
, stayWithin
);
221 assertPostcondition(result
);
225 inline Node
* ComposedTreeTraversal::traverseNext(const Node
& node
)
227 if (Node
* next
= traverseFirstChild(node
))
229 for (const Node
* next
= &node
; next
; next
= traverseParent(*next
)) {
230 if (Node
* sibling
= traverseNextSibling(*next
))
236 inline Node
* ComposedTreeTraversal::traverseNext(const Node
& node
, const Node
* stayWithin
)
238 if (Node
* next
= traverseFirstChild(node
))
240 return traverseNextSkippingChildren(node
, stayWithin
);
243 inline Node
* ComposedTreeTraversal::traverseNextSkippingChildren(const Node
& node
, const Node
* stayWithin
)
245 for (const Node
* next
= &node
; next
; next
= traverseParent(*next
)) {
246 if (next
== stayWithin
)
248 if (Node
* sibling
= traverseNextSibling(*next
))
254 inline Node
* ComposedTreeTraversal::previous(const Node
& node
)
256 assertPrecondition(node
);
257 Node
* result
= traversePrevious(node
);
258 assertPostcondition(result
);
262 inline Node
* ComposedTreeTraversal::traversePrevious(const Node
& node
)
264 if (Node
* previous
= traversePreviousSibling(node
)) {
265 while (Node
* child
= traverseLastChild(*previous
))
269 return traverseParent(node
);
272 inline Node
* ComposedTreeTraversal::firstChild(const Node
& node
)
274 assertPrecondition(node
);
275 Node
* result
= traverseChild(node
, TraversalDirectionForward
);
276 assertPostcondition(result
);
280 inline Node
* ComposedTreeTraversal::lastChild(const Node
& node
)
282 assertPrecondition(node
);
283 Node
* result
= traverseLastChild(node
);
284 assertPostcondition(result
);
288 inline bool ComposedTreeTraversal::hasChildren(const Node
& node
)
290 return firstChild(node
);
293 inline Node
* ComposedTreeTraversal::traverseNextSibling(const Node
& node
)
295 return traverseSiblingOrBackToInsertionPoint(node
, TraversalDirectionForward
);
298 inline Node
* ComposedTreeTraversal::traversePreviousSibling(const Node
& node
)
300 return traverseSiblingOrBackToInsertionPoint(node
, TraversalDirectionBackward
);
303 inline Node
* ComposedTreeTraversal::traverseFirstChild(const Node
& node
)
305 return traverseChild(node
, TraversalDirectionForward
);
308 inline Node
* ComposedTreeTraversal::traverseLastChild(const Node
& node
)
310 return traverseChild(node
, TraversalDirectionBackward
);