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 ComposedTreeWalker_h
28 #define ComposedTreeWalker_h
30 #include "core/dom/NodeRenderingTraversal.h"
31 #include "core/dom/shadow/InsertionPoint.h"
32 #include "core/dom/shadow/ShadowRoot.h"
38 // FIXME: Make some functions inline to optimise the performance.
39 // https://bugs.webkit.org/show_bug.cgi?id=82702
40 class ComposedTreeWalker {
43 typedef NodeRenderingTraversal::ParentDetails ParentTraversalDetails;
46 CanStartFromShadowBoundary,
47 CannotStartFromShadowBoundary
50 ComposedTreeWalker(const Node*, StartPolicy = CannotStartFromShadowBoundary);
52 Node* get() const { return const_cast<Node*>(m_node.get()); }
58 void previousSibling();
65 Node* traverseParent(const Node*, ParentTraversalDetails* = 0) const;
68 ComposedTreeWalker(const Node*, ParentTraversalDetails*);
70 enum TraversalDirection {
71 TraversalDirectionForward,
72 TraversalDirectionBackward
75 void assertPrecondition() const
79 ASSERT(!m_node->isShadowRoot());
80 ASSERT(!isActiveInsertionPoint(*m_node));
84 void assertPostcondition() const
92 static Node* traverseNode(const Node*, TraversalDirection);
93 static Node* traverseLightChildren(const Node*, TraversalDirection);
95 Node* traverseFirstChild(const Node*) const;
96 Node* traverseLastChild(const Node*) const;
97 Node* traverseChild(const Node*, TraversalDirection) const;
99 static Node* traverseNextSibling(const Node*);
100 static Node* traversePreviousSibling(const Node*);
102 static Node* traverseSiblingOrBackToInsertionPoint(const Node*, TraversalDirection);
103 static Node* traverseSiblingInCurrentTree(const Node*, TraversalDirection);
105 static Node* traverseSiblings(const Node*, TraversalDirection);
106 static Node* traverseDistributedNodes(const Node*, const InsertionPoint*, TraversalDirection);
108 static Node* traverseBackToYoungerShadowRoot(const Node*, TraversalDirection);
110 Node* traverseParentOrHost(const Node*) const;
112 RawPtrWillBeMember<const Node> m_node;
115 inline ComposedTreeWalker::ComposedTreeWalker(const Node* node, StartPolicy startPolicy)
119 if (m_node && startPolicy == CannotStartFromShadowBoundary)
120 assertPrecondition();
124 inline void ComposedTreeWalker::parent()
126 assertPrecondition();
127 m_node = traverseParent(m_node);
128 assertPostcondition();
131 inline void ComposedTreeWalker::nextSibling()
133 assertPrecondition();
134 m_node = traverseSiblingOrBackToInsertionPoint(m_node, TraversalDirectionForward);
135 assertPostcondition();
138 inline void ComposedTreeWalker::previousSibling()
140 assertPrecondition();
141 m_node = traverseSiblingOrBackToInsertionPoint(m_node, TraversalDirectionBackward);
142 assertPostcondition();
145 inline void ComposedTreeWalker::next()
147 assertPrecondition();
148 if (Node* next = traverseFirstChild(m_node)) {
152 if (Node* sibling = traverseNextSibling(m_node)) {
156 m_node = traverseParent(m_node);
159 assertPostcondition();
162 inline void ComposedTreeWalker::previous()
164 assertPrecondition();
165 if (Node* previous = traversePreviousSibling(m_node)) {
166 while (Node* child = traverseLastChild(previous))
172 assertPostcondition();
175 inline void ComposedTreeWalker::firstChild()
177 assertPrecondition();
178 m_node = traverseChild(m_node, TraversalDirectionForward);
179 assertPostcondition();
182 inline void ComposedTreeWalker::lastChild()
184 assertPrecondition();
185 m_node = traverseLastChild(m_node);
186 assertPostcondition();
189 inline Node* ComposedTreeWalker::traverseNextSibling(const Node* node)
192 return traverseSiblingOrBackToInsertionPoint(node, TraversalDirectionForward);
195 inline Node* ComposedTreeWalker::traversePreviousSibling(const Node* node)
198 return traverseSiblingOrBackToInsertionPoint(node, TraversalDirectionBackward);
201 inline Node* ComposedTreeWalker::traverseFirstChild(const Node* node) const
204 return traverseChild(node, TraversalDirectionForward);
207 inline Node* ComposedTreeWalker::traverseLastChild(const Node* node) const
210 return traverseChild(node, TraversalDirectionBackward);