1 /* 2 * Copyright (C) 1999 Lars Knoll (knoll (at) kde.org) 3 * Copyright (C) 2000 Frederik Holljen (frederik.holljen (at) hig.no) 4 * Copyright (C) 2001 Peter Kelly (pmk (at) post.com) 5 * Copyright (C) 2006 Samuel Weinig (sam.weinig (at) gmail.com) 6 * Copyright (C) 2004, 2008 Apple Inc. All rights reserved. 7 * 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. 12 * 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. 17 * 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. 22 * 23 */ 24 25 #include "config.h" 26 #include "core/dom/TreeWalker.h" 27 28 #include "bindings/v8/ExceptionMessages.h" 29 #include "bindings/v8/ExceptionState.h" 30 #include "core/dom/ContainerNode.h" 31 #include "core/dom/ExceptionCode.h" 32 #include "core/dom/NodeTraversal.h" 33 34 namespace WebCore { 35 36 TreeWalker::TreeWalker(PassRefPtrWillBeRawPtr<Node> rootNode, unsigned whatToShow, PassRefPtrWillBeRawPtr<NodeFilter> filter) 37 : NodeIteratorBase(rootNode, whatToShow, filter) 38 , m_current(root()) 39 { 40 ScriptWrappable::init(this); 41 } 42 43 void TreeWalker::setCurrentNode(PassRefPtrWillBeRawPtr<Node> node, ExceptionState& exceptionState) 44 { 45 if (!node) { 46 exceptionState.throwDOMException(NotSupportedError, ExceptionMessages::argumentNullOrIncorrectType(1, "Node")); 47 return; 48 } 49 m_current = node; 50 } 51 52 inline Node* TreeWalker::setCurrent(PassRefPtrWillBeRawPtr<Node> node) 53 { 54 m_current = node; 55 return m_current.get(); 56 } 57 58 Node* TreeWalker::parentNode(ExceptionState& exceptionState) 59 { 60 RefPtrWillBeRawPtr<Node> node = m_current; 61 while (node != root()) { 62 node = node->parentNode(); 63 if (!node) 64 return 0; 65 short acceptNodeResult = acceptNode(node.get(), exceptionState); 66 if (exceptionState.hadException()) 67 return 0; 68 if (acceptNodeResult == NodeFilter::FILTER_ACCEPT) 69 return setCurrent(node.release()); 70 } 71 return 0; 72 } 73 74 Node* TreeWalker::firstChild(ExceptionState& exceptionState) 75 { 76 for (RefPtrWillBeRawPtr<Node> node = m_current->firstChild(); node; ) { 77 short acceptNodeResult = acceptNode(node.get(), exceptionState); 78 if (exceptionState.hadException()) 79 return 0; 80 switch (acceptNodeResult) { 81 case NodeFilter::FILTER_ACCEPT: 82 m_current = node.release(); 83 return m_current.get(); 84 case NodeFilter::FILTER_SKIP: 85 if (node->firstChild()) { 86 node = node->firstChild(); 87 continue; 88 } 89 break; 90 case NodeFilter::FILTER_REJECT: 91 break; 92 } 93 do { 94 if (node->nextSibling()) { 95 node = node->nextSibling(); 96 break; 97 } 98 ContainerNode* parent = node->parentNode(); 99 if (!parent || parent == root() || parent == m_current) 100 return 0; 101 node = parent; 102 } while (node); 103 } 104 return 0; 105 } 106 107 Node* TreeWalker::lastChild(ExceptionState& exceptionState) 108 { 109 for (RefPtrWillBeRawPtr<Node> node = m_current->lastChild(); node; ) { 110 short acceptNodeResult = acceptNode(node.get(), exceptionState); 111 if (exceptionState.hadException()) 112 return 0; 113 switch (acceptNodeResult) { 114 case NodeFilter::FILTER_ACCEPT: 115 m_current = node.release(); 116 return m_current.get(); 117 case NodeFilter::FILTER_SKIP: 118 if (node->lastChild()) { 119 node = node->lastChild(); 120 continue; 121 } 122 break; 123 case NodeFilter::FILTER_REJECT: 124 break; 125 } 126 do { 127 if (node->previousSibling()) { 128 node = node->previousSibling(); 129 break; 130 } 131 ContainerNode* parent = node->parentNode(); 132 if (!parent || parent == root() || parent == m_current) 133 return 0; 134 node = parent; 135 } while (node); 136 } 137 return 0; 138 } 139 140 Node* TreeWalker::previousSibling(ExceptionState& exceptionState) 141 { 142 RefPtrWillBeRawPtr<Node> node = m_current; 143 if (node == root()) 144 return 0; 145 while (1) { 146 for (RefPtrWillBeRawPtr<Node> sibling = node->previousSibling(); sibling; ) { 147 short acceptNodeResult = acceptNode(sibling.get(), exceptionState); 148 if (exceptionState.hadException()) 149 return 0; 150 switch (acceptNodeResult) { 151 case NodeFilter::FILTER_ACCEPT: 152 m_current = sibling.release(); 153 return m_current.get(); 154 case NodeFilter::FILTER_SKIP: 155 if (sibling->lastChild()) { 156 sibling = sibling->lastChild(); 157 node = sibling; 158 continue; 159 } 160 break; 161 case NodeFilter::FILTER_REJECT: 162 break; 163 } 164 sibling = sibling->previousSibling(); 165 } 166 node = node->parentNode(); 167 if (!node || node == root()) 168 return 0; 169 short acceptNodeResult = acceptNode(node.get(), exceptionState); 170 if (exceptionState.hadException()) 171 return 0; 172 if (acceptNodeResult == NodeFilter::FILTER_ACCEPT) 173 return 0; 174 } 175 } 176 177 Node* TreeWalker::nextSibling(ExceptionState& exceptionState) 178 { 179 RefPtrWillBeRawPtr<Node> node = m_current; 180 if (node == root()) 181 return 0; 182 while (1) { 183 for (RefPtrWillBeRawPtr<Node> sibling = node->nextSibling(); sibling; ) { 184 short acceptNodeResult = acceptNode(sibling.get(), exceptionState); 185 if (exceptionState.hadException()) 186 return 0; 187 switch (acceptNodeResult) { 188 case NodeFilter::FILTER_ACCEPT: 189 m_current = sibling.release(); 190 return m_current.get(); 191 case NodeFilter::FILTER_SKIP: 192 if (sibling->firstChild()) { 193 sibling = sibling->firstChild(); 194 node = sibling; 195 continue; 196 } 197 break; 198 case NodeFilter::FILTER_REJECT: 199 break; 200 } 201 sibling = sibling->nextSibling(); 202 } 203 node = node->parentNode(); 204 if (!node || node == root()) 205 return 0; 206 short acceptNodeResult = acceptNode(node.get(), exceptionState); 207 if (exceptionState.hadException()) 208 return 0; 209 if (acceptNodeResult == NodeFilter::FILTER_ACCEPT) 210 return 0; 211 } 212 } 213 214 Node* TreeWalker::previousNode(ExceptionState& exceptionState) 215 { 216 RefPtrWillBeRawPtr<Node> node = m_current; 217 while (node != root()) { 218 while (Node* previousSibling = node->previousSibling()) { 219 node = previousSibling; 220 short acceptNodeResult = acceptNode(node.get(), exceptionState); 221 if (exceptionState.hadException()) 222 return 0; 223 if (acceptNodeResult == NodeFilter::FILTER_REJECT) 224 continue; 225 while (Node* lastChild = node->lastChild()) { 226 node = lastChild; 227 acceptNodeResult = acceptNode(node.get(), exceptionState); 228 if (exceptionState.hadException()) 229 return 0; 230 if (acceptNodeResult == NodeFilter::FILTER_REJECT) 231 break; 232 } 233 if (acceptNodeResult == NodeFilter::FILTER_ACCEPT) { 234 m_current = node.release(); 235 return m_current.get(); 236 } 237 } 238 if (node == root()) 239 return 0; 240 ContainerNode* parent = node->parentNode(); 241 if (!parent) 242 return 0; 243 node = parent; 244 short acceptNodeResult = acceptNode(node.get(), exceptionState); 245 if (exceptionState.hadException()) 246 return 0; 247 if (acceptNodeResult == NodeFilter::FILTER_ACCEPT) 248 return setCurrent(node.release()); 249 } 250 return 0; 251 } 252 253 Node* TreeWalker::nextNode(ExceptionState& exceptionState) 254 { 255 RefPtrWillBeRawPtr<Node> node = m_current; 256 Children: 257 while (Node* firstChild = node->firstChild()) { 258 node = firstChild; 259 short acceptNodeResult = acceptNode(node.get(), exceptionState); 260 if (exceptionState.hadException()) 261 return 0; 262 if (acceptNodeResult == NodeFilter::FILTER_ACCEPT) 263 return setCurrent(node.release()); 264 if (acceptNodeResult == NodeFilter::FILTER_REJECT) 265 break; 266 } 267 while (Node* nextSibling = NodeTraversal::nextSkippingChildren(*node, root())) { 268 node = nextSibling; 269 short acceptNodeResult = acceptNode(node.get(), exceptionState); 270 if (exceptionState.hadException()) 271 return 0; 272 if (acceptNodeResult == NodeFilter::FILTER_ACCEPT) 273 return setCurrent(node.release()); 274 if (acceptNodeResult == NodeFilter::FILTER_SKIP) 275 goto Children; 276 } 277 return 0; 278 } 279 280 void TreeWalker::trace(Visitor* visitor) 281 { 282 visitor->trace(m_current); 283 NodeIteratorBase::trace(visitor); 284 } 285 286 } // namespace WebCore 287