Move parseFontFaceDescriptor to CSSPropertyParser.cpp
[chromium-blink-merge.git] / third_party / WebKit / Source / core / dom / NodeIterator.cpp
blob4d0fb7c60aeb8de550ded8d5a8d73257a2b26159
1 /*
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.
25 #include "config.h"
26 #include "core/dom/NodeIterator.h"
28 #include "bindings/core/v8/ExceptionState.h"
29 #include "core/dom/Document.h"
30 #include "core/dom/ExceptionCode.h"
31 #include "core/dom/NodeTraversal.h"
33 namespace blink {
35 NodeIterator::NodePointer::NodePointer()
39 NodeIterator::NodePointer::NodePointer(PassRefPtrWillBeRawPtr<Node> n, bool b)
40 : node(n)
41 , isPointerBeforeNode(b)
45 void NodeIterator::NodePointer::clear()
47 node.clear();
50 bool NodeIterator::NodePointer::moveToNext(Node* root)
52 if (!node)
53 return false;
54 if (isPointerBeforeNode) {
55 isPointerBeforeNode = false;
56 return true;
58 node = NodeTraversal::next(*node, root);
59 return node;
62 bool NodeIterator::NodePointer::moveToPrevious(Node* root)
64 if (!node)
65 return false;
66 if (!isPointerBeforeNode) {
67 isPointerBeforeNode = true;
68 return true;
70 node = NodeTraversal::previous(*node, root);
71 return node;
74 NodeIterator::NodeIterator(PassRefPtrWillBeRawPtr<Node> rootNode, unsigned whatToShow, PassRefPtrWillBeRawPtr<NodeFilter> filter)
75 : NodeIteratorBase(rootNode, whatToShow, filter)
76 , m_referenceNode(root(), true)
78 root()->document().attachNodeIterator(this);
81 #if !ENABLE(OILPAN)
82 NodeIterator::~NodeIterator()
84 root()->document().detachNodeIterator(this);
86 #endif
88 PassRefPtrWillBeRawPtr<Node> NodeIterator::nextNode(ExceptionState& exceptionState)
90 RefPtrWillBeRawPtr<Node> result = nullptr;
92 m_candidateNode = m_referenceNode;
93 while (m_candidateNode.moveToNext(root())) {
94 // NodeIterators treat the DOM tree as a flat list of nodes.
95 // In other words, FILTER_REJECT does not pass over descendants
96 // of the rejected node. Hence, FILTER_REJECT is the same as FILTER_SKIP.
97 RefPtrWillBeRawPtr<Node> provisionalResult = m_candidateNode.node;
98 bool nodeWasAccepted = acceptNode(provisionalResult.get(), exceptionState) == NodeFilter::FILTER_ACCEPT;
99 if (exceptionState.hadException())
100 break;
101 if (nodeWasAccepted) {
102 m_referenceNode = m_candidateNode;
103 result = provisionalResult.release();
104 break;
108 m_candidateNode.clear();
109 return result.release();
112 PassRefPtrWillBeRawPtr<Node> NodeIterator::previousNode(ExceptionState& exceptionState)
114 RefPtrWillBeRawPtr<Node> result = nullptr;
116 m_candidateNode = m_referenceNode;
117 while (m_candidateNode.moveToPrevious(root())) {
118 // NodeIterators treat the DOM tree as a flat list of nodes.
119 // In other words, FILTER_REJECT does not pass over descendants
120 // of the rejected node. Hence, FILTER_REJECT is the same as FILTER_SKIP.
121 RefPtrWillBeRawPtr<Node> provisionalResult = m_candidateNode.node;
122 bool nodeWasAccepted = acceptNode(provisionalResult.get(), exceptionState) == NodeFilter::FILTER_ACCEPT;
123 if (exceptionState.hadException())
124 break;
125 if (nodeWasAccepted) {
126 m_referenceNode = m_candidateNode;
127 result = provisionalResult.release();
128 break;
132 m_candidateNode.clear();
133 return result.release();
136 void NodeIterator::detach()
138 // This is now a no-op as per the DOM specification.
141 void NodeIterator::nodeWillBeRemoved(Node& removedNode)
143 updateForNodeRemoval(removedNode, m_candidateNode);
144 updateForNodeRemoval(removedNode, m_referenceNode);
147 void NodeIterator::updateForNodeRemoval(Node& removedNode, NodePointer& referenceNode) const
149 ASSERT(root()->document() == removedNode.document());
151 // Iterator is not affected if the removed node is the reference node and is the root.
152 // or if removed node is not the reference node, or the ancestor of the reference node.
153 if (!removedNode.isDescendantOf(root()))
154 return;
155 bool willRemoveReferenceNode = removedNode == referenceNode.node.get();
156 bool willRemoveReferenceNodeAncestor = referenceNode.node && referenceNode.node->isDescendantOf(&removedNode);
157 if (!willRemoveReferenceNode && !willRemoveReferenceNodeAncestor)
158 return;
160 if (referenceNode.isPointerBeforeNode) {
161 Node* node = NodeTraversal::next(removedNode, root());
162 if (node) {
163 // Move out from under the node being removed if the new reference
164 // node is a descendant of the node being removed.
165 while (node && node->isDescendantOf(&removedNode))
166 node = NodeTraversal::next(*node, root());
167 if (node)
168 referenceNode.node = node;
169 } else {
170 node = NodeTraversal::previous(removedNode, root());
171 if (node) {
172 // Move out from under the node being removed if the reference node is
173 // a descendant of the node being removed.
174 if (willRemoveReferenceNodeAncestor) {
175 while (node && node->isDescendantOf(&removedNode))
176 node = NodeTraversal::previous(*node, root());
178 if (node) {
179 // Removing last node.
180 // Need to move the pointer after the node preceding the
181 // new reference node.
182 referenceNode.node = node;
183 referenceNode.isPointerBeforeNode = false;
187 } else {
188 Node* node = NodeTraversal::previous(removedNode, root());
189 if (node) {
190 // Move out from under the node being removed if the reference node is
191 // a descendant of the node being removed.
192 if (willRemoveReferenceNodeAncestor) {
193 while (node && node->isDescendantOf(&removedNode))
194 node = NodeTraversal::previous(*node, root());
196 if (node)
197 referenceNode.node = node;
198 } else {
199 // FIXME: This branch doesn't appear to have any LayoutTests.
200 node = NodeTraversal::next(removedNode, root());
201 // Move out from under the node being removed if the reference node is
202 // a descendant of the node being removed.
203 if (willRemoveReferenceNodeAncestor) {
204 while (node && node->isDescendantOf(&removedNode))
205 node = NodeTraversal::previous(*node, root());
207 if (node)
208 referenceNode.node = node;
213 DEFINE_TRACE(NodeIterator)
215 visitor->trace(m_referenceNode);
216 visitor->trace(m_candidateNode);
217 NodeIteratorBase::trace(visitor);
220 } // namespace blink