2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * Copyright (C) 2000 Frederik Holljen (frederik.holljen@hig.no)
4 * Copyright (C) 2001 Peter Kelly (pmk@post.com)
5 * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
6 * Copyright (C) 2004, 2008 Apple Inc. All rights reserved.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
18 * You should have received a copy of the GNU Library General Public License
19 * along with this library; see the file COPYING.LIB. If not, write to
20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
26 #include "core/dom/TreeWalker.h"
28 #include "bindings/core/v8/ExceptionMessages.h"
29 #include "bindings/core/v8/ExceptionState.h"
30 #include "core/dom/ContainerNode.h"
31 #include "core/dom/ExceptionCode.h"
32 #include "core/dom/NodeTraversal.h"
36 TreeWalker::TreeWalker(PassRefPtrWillBeRawPtr
<Node
> rootNode
, unsigned whatToShow
, PassRefPtrWillBeRawPtr
<NodeFilter
> filter
)
37 : NodeIteratorBase(rootNode
, whatToShow
, filter
)
42 void TreeWalker::setCurrentNode(PassRefPtrWillBeRawPtr
<Node
> node
, ExceptionState
& exceptionState
)
45 exceptionState
.throwDOMException(NotSupportedError
, ExceptionMessages::argumentNullOrIncorrectType(1, "Node"));
51 inline Node
* TreeWalker::setCurrent(PassRefPtrWillBeRawPtr
<Node
> node
)
54 return m_current
.get();
57 Node
* TreeWalker::parentNode(ExceptionState
& exceptionState
)
59 RefPtrWillBeRawPtr
<Node
> node
= m_current
;
60 while (node
!= root()) {
61 node
= node
->parentNode();
64 unsigned acceptNodeResult
= acceptNode(node
.get(), exceptionState
);
65 if (exceptionState
.hadException())
67 if (acceptNodeResult
== NodeFilter::FILTER_ACCEPT
)
68 return setCurrent(node
.release());
73 Node
* TreeWalker::firstChild(ExceptionState
& exceptionState
)
75 for (RefPtrWillBeRawPtr
<Node
> node
= m_current
->firstChild(); node
; ) {
76 unsigned acceptNodeResult
= acceptNode(node
.get(), exceptionState
);
77 if (exceptionState
.hadException())
79 switch (acceptNodeResult
) {
80 case NodeFilter::FILTER_ACCEPT
:
81 m_current
= node
.release();
82 return m_current
.get();
83 case NodeFilter::FILTER_SKIP
:
84 if (node
->hasChildren()) {
85 node
= node
->firstChild();
89 case NodeFilter::FILTER_REJECT
:
93 if (node
->nextSibling()) {
94 node
= node
->nextSibling();
97 ContainerNode
* parent
= node
->parentNode();
98 if (!parent
|| parent
== root() || parent
== m_current
)
106 Node
* TreeWalker::lastChild(ExceptionState
& exceptionState
)
108 for (RefPtrWillBeRawPtr
<Node
> node
= m_current
->lastChild(); node
; ) {
109 unsigned acceptNodeResult
= acceptNode(node
.get(), exceptionState
);
110 if (exceptionState
.hadException())
112 switch (acceptNodeResult
) {
113 case NodeFilter::FILTER_ACCEPT
:
114 m_current
= node
.release();
115 return m_current
.get();
116 case NodeFilter::FILTER_SKIP
:
117 if (node
->lastChild()) {
118 node
= node
->lastChild();
122 case NodeFilter::FILTER_REJECT
:
126 if (node
->previousSibling()) {
127 node
= node
->previousSibling();
130 ContainerNode
* parent
= node
->parentNode();
131 if (!parent
|| parent
== root() || parent
== m_current
)
139 Node
* TreeWalker::previousSibling(ExceptionState
& exceptionState
)
141 RefPtrWillBeRawPtr
<Node
> node
= m_current
;
145 for (RefPtrWillBeRawPtr
<Node
> sibling
= node
->previousSibling(); sibling
; ) {
146 unsigned acceptNodeResult
= acceptNode(sibling
.get(), exceptionState
);
147 if (exceptionState
.hadException())
149 switch (acceptNodeResult
) {
150 case NodeFilter::FILTER_ACCEPT
:
151 m_current
= sibling
.release();
152 return m_current
.get();
153 case NodeFilter::FILTER_SKIP
:
154 if (sibling
->lastChild()) {
155 sibling
= sibling
->lastChild();
160 case NodeFilter::FILTER_REJECT
:
163 sibling
= sibling
->previousSibling();
165 node
= node
->parentNode();
166 if (!node
|| node
== root())
168 unsigned acceptNodeResult
= acceptNode(node
.get(), exceptionState
);
169 if (exceptionState
.hadException())
171 if (acceptNodeResult
== NodeFilter::FILTER_ACCEPT
)
176 Node
* TreeWalker::nextSibling(ExceptionState
& exceptionState
)
178 RefPtrWillBeRawPtr
<Node
> node
= m_current
;
182 for (RefPtrWillBeRawPtr
<Node
> sibling
= node
->nextSibling(); sibling
; ) {
183 unsigned acceptNodeResult
= acceptNode(sibling
.get(), exceptionState
);
184 if (exceptionState
.hadException())
186 switch (acceptNodeResult
) {
187 case NodeFilter::FILTER_ACCEPT
:
188 m_current
= sibling
.release();
189 return m_current
.get();
190 case NodeFilter::FILTER_SKIP
:
191 if (sibling
->hasChildren()) {
192 sibling
= sibling
->firstChild();
197 case NodeFilter::FILTER_REJECT
:
200 sibling
= sibling
->nextSibling();
202 node
= node
->parentNode();
203 if (!node
|| node
== root())
205 unsigned acceptNodeResult
= acceptNode(node
.get(), exceptionState
);
206 if (exceptionState
.hadException())
208 if (acceptNodeResult
== NodeFilter::FILTER_ACCEPT
)
213 Node
* TreeWalker::previousNode(ExceptionState
& exceptionState
)
215 RefPtrWillBeRawPtr
<Node
> node
= m_current
;
216 while (node
!= root()) {
217 while (Node
* previousSibling
= node
->previousSibling()) {
218 node
= previousSibling
;
219 unsigned acceptNodeResult
= acceptNode(node
.get(), exceptionState
);
220 if (exceptionState
.hadException())
222 if (acceptNodeResult
== NodeFilter::FILTER_REJECT
)
224 while (Node
* lastChild
= node
->lastChild()) {
226 acceptNodeResult
= acceptNode(node
.get(), exceptionState
);
227 if (exceptionState
.hadException())
229 if (acceptNodeResult
== NodeFilter::FILTER_REJECT
)
232 if (acceptNodeResult
== NodeFilter::FILTER_ACCEPT
) {
233 m_current
= node
.release();
234 return m_current
.get();
239 ContainerNode
* parent
= node
->parentNode();
243 unsigned acceptNodeResult
= acceptNode(node
.get(), exceptionState
);
244 if (exceptionState
.hadException())
246 if (acceptNodeResult
== NodeFilter::FILTER_ACCEPT
)
247 return setCurrent(node
.release());
252 Node
* TreeWalker::nextNode(ExceptionState
& exceptionState
)
254 RefPtrWillBeRawPtr
<Node
> node
= m_current
;
256 while (Node
* firstChild
= node
->firstChild()) {
258 unsigned acceptNodeResult
= acceptNode(node
.get(), exceptionState
);
259 if (exceptionState
.hadException())
261 if (acceptNodeResult
== NodeFilter::FILTER_ACCEPT
)
262 return setCurrent(node
.release());
263 if (acceptNodeResult
== NodeFilter::FILTER_REJECT
)
266 while (Node
* nextSibling
= NodeTraversal::nextSkippingChildren(*node
, root())) {
268 unsigned acceptNodeResult
= acceptNode(node
.get(), exceptionState
);
269 if (exceptionState
.hadException())
271 if (acceptNodeResult
== NodeFilter::FILTER_ACCEPT
)
272 return setCurrent(node
.release());
273 if (acceptNodeResult
== NodeFilter::FILTER_SKIP
)
279 DEFINE_TRACE(TreeWalker
)
281 visitor
->trace(m_current
);
282 NodeIteratorBase::trace(visitor
);