Replace WTF::move with WTFMove
[WebKit-https.git] / Source / WebCore / dom / NodeIterator.cpp
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.
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 "NodeIterator.h"
27
28 #include "Document.h"
29 #include "ExceptionCode.h"
30 #include "NodeTraversal.h"
31
32 #include <runtime/JSCJSValueInlines.h>
33
34 namespace WebCore {
35
36 NodeIterator::NodePointer::NodePointer()
37 {
38 }
39
40 NodeIterator::NodePointer::NodePointer(PassRefPtr<Node> n, bool b)
41     : node(n)
42     , isPointerBeforeNode(b)
43 {
44 }
45
46 void NodeIterator::NodePointer::clear()
47 {
48     node = nullptr;
49 }
50
51 bool NodeIterator::NodePointer::moveToNext(Node* root)
52 {
53     if (!node)
54         return false;
55     if (isPointerBeforeNode) {
56         isPointerBeforeNode = false;
57         return true;
58     }
59     node = NodeTraversal::next(*node, root);
60     return node;
61 }
62
63 bool NodeIterator::NodePointer::moveToPrevious(Node* root)
64 {
65     if (!node)
66         return false;
67     if (!isPointerBeforeNode) {
68         isPointerBeforeNode = true;
69         return true;
70     }
71     if (node == root) {
72         node = nullptr;
73         return false;
74     }
75     node = NodeTraversal::previous(*node);
76     return node;
77 }
78
79 NodeIterator::NodeIterator(PassRefPtr<Node> rootNode, unsigned long whatToShow, RefPtr<NodeFilter>&& filter)
80     : NodeIteratorBase(*rootNode, whatToShow, WTFMove(filter))
81     , m_referenceNode(root(), true)
82 {
83     root()->document().attachNodeIterator(this);
84 }
85
86 NodeIterator::~NodeIterator()
87 {
88     root()->document().detachNodeIterator(this);
89 }
90
91 RefPtr<Node> NodeIterator::nextNode()
92 {
93     RefPtr<Node> result;
94
95     m_candidateNode = m_referenceNode;
96     while (m_candidateNode.moveToNext(root())) {
97         // NodeIterators treat the DOM tree as a flat list of nodes.
98         // In other words, FILTER_REJECT does not pass over descendants
99         // of the rejected node. Hence, FILTER_REJECT is the same as FILTER_SKIP.
100         RefPtr<Node> provisionalResult = m_candidateNode.node;
101         bool nodeWasAccepted = acceptNode(provisionalResult.get()) == NodeFilter::FILTER_ACCEPT;
102         if (nodeWasAccepted) {
103             m_referenceNode = m_candidateNode;
104             result = provisionalResult.release();
105             break;
106         }
107     }
108
109     m_candidateNode.clear();
110     return result;
111 }
112
113 RefPtr<Node> NodeIterator::previousNode()
114 {
115     RefPtr<Node> result;
116
117     m_candidateNode = m_referenceNode;
118     while (m_candidateNode.moveToPrevious(root())) {
119         // NodeIterators treat the DOM tree as a flat list of nodes.
120         // In other words, FILTER_REJECT does not pass over descendants
121         // of the rejected node. Hence, FILTER_REJECT is the same as FILTER_SKIP.
122         RefPtr<Node> provisionalResult = m_candidateNode.node;
123         bool nodeWasAccepted = acceptNode(provisionalResult.get()) == NodeFilter::FILTER_ACCEPT;
124         if (nodeWasAccepted) {
125             m_referenceNode = m_candidateNode;
126             result = provisionalResult.release();
127             break;
128         }
129     }
130
131     m_candidateNode.clear();
132     return result;
133 }
134
135 void NodeIterator::detach()
136 {
137     // This is now a no-op as per the DOM specification.
138 }
139
140 void NodeIterator::nodeWillBeRemoved(Node& removedNode)
141 {
142     updateForNodeRemoval(removedNode, m_candidateNode);
143     updateForNodeRemoval(removedNode, m_referenceNode);
144 }
145
146 void NodeIterator::updateForNodeRemoval(Node& removedNode, NodePointer& referenceNode) const
147 {
148     ASSERT(&root()->document() == &removedNode.document());
149
150     // Iterator is not affected if the removed node is the reference node and is the root.
151     // or if removed node is not the reference node, or the ancestor of the reference node.
152     if (!removedNode.isDescendantOf(root()))
153         return;
154     bool willRemoveReferenceNode = &removedNode == referenceNode.node;
155     bool willRemoveReferenceNodeAncestor = referenceNode.node && referenceNode.node->isDescendantOf(&removedNode);
156     if (!willRemoveReferenceNode && !willRemoveReferenceNodeAncestor)
157         return;
158
159     if (referenceNode.isPointerBeforeNode) {
160         Node* node = NodeTraversal::next(removedNode, root());
161         if (node) {
162             // Move out from under the node being removed if the new reference
163             // node is a descendant of the node being removed.
164             while (node && node->isDescendantOf(&removedNode))
165                 node = NodeTraversal::next(*node, root());
166             if (node)
167                 referenceNode.node = node;
168         } else {
169             node = NodeTraversal::previous(removedNode);
170             if (node) {
171                 // Move out from under the node being removed if the reference node is
172                 // a descendant of the node being removed.
173                 if (willRemoveReferenceNodeAncestor) {
174                     while (node && node->isDescendantOf(&removedNode))
175                         node = NodeTraversal::previous(*node);
176                 }
177                 if (node) {
178                     // Removing last node.
179                     // Need to move the pointer after the node preceding the 
180                     // new reference node.
181                     referenceNode.node = node;
182                     referenceNode.isPointerBeforeNode = false;
183                 }
184             }
185         }
186     } else {
187         Node* node = NodeTraversal::previous(removedNode);
188         if (node) {
189             // Move out from under the node being removed if the reference node is
190             // a descendant of the node being removed.
191             if (willRemoveReferenceNodeAncestor) {
192                 while (node && node->isDescendantOf(&removedNode))
193                     node = NodeTraversal::previous(*node);
194             }
195             if (node)
196                 referenceNode.node = node;
197         } else {
198             // FIXME: This branch doesn't appear to have any LayoutTests.
199             node = NodeTraversal::next(removedNode, root());
200             // Move out from under the node being removed if the reference node is
201             // a descendant of the node being removed.
202             if (willRemoveReferenceNodeAncestor) {
203                 while (node && node->isDescendantOf(&removedNode))
204                     node = NodeTraversal::previous(*node);
205             }
206             if (node)
207                 referenceNode.node = node;
208         }
209     }
210 }
211
212
213 } // namespace WebCore