content/base/src/NodeIterator.cpp

Thu, 15 Jan 2015 21:03:48 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 21:03:48 +0100
branch
TOR_BUG_9701
changeset 11
deefc01c0e14
permissions
-rw-r--r--

Integrate friendly tips from Tor colleagues to make (or not) 4.5 alpha 3;
This includes removal of overloaded (but unused) methods, and addition of
a overlooked call to DataStruct::SetData(nsISupports, uint32_t, bool.)

michael@0 1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
michael@0 2 *
michael@0 3 * This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 /*
michael@0 8 * Implementation of DOM Traversal's nsIDOMNodeIterator
michael@0 9 */
michael@0 10
michael@0 11 #include "mozilla/dom/NodeIterator.h"
michael@0 12
michael@0 13 #include "nsIDOMNode.h"
michael@0 14 #include "nsError.h"
michael@0 15
michael@0 16 #include "nsIContent.h"
michael@0 17 #include "nsIDocument.h"
michael@0 18 #include "nsContentUtils.h"
michael@0 19 #include "nsCOMPtr.h"
michael@0 20 #include "mozilla/dom/NodeIteratorBinding.h"
michael@0 21
michael@0 22 namespace mozilla {
michael@0 23 namespace dom {
michael@0 24
michael@0 25 /*
michael@0 26 * NodePointer implementation
michael@0 27 */
michael@0 28 NodeIterator::NodePointer::NodePointer(nsINode *aNode, bool aBeforeNode) :
michael@0 29 mNode(aNode),
michael@0 30 mBeforeNode(aBeforeNode)
michael@0 31 {
michael@0 32 }
michael@0 33
michael@0 34 bool NodeIterator::NodePointer::MoveToNext(nsINode *aRoot)
michael@0 35 {
michael@0 36 if (!mNode)
michael@0 37 return false;
michael@0 38
michael@0 39 if (mBeforeNode) {
michael@0 40 mBeforeNode = false;
michael@0 41 return true;
michael@0 42 }
michael@0 43
michael@0 44 nsINode* child = mNode->GetFirstChild();
michael@0 45 if (child) {
michael@0 46 mNode = child;
michael@0 47 return true;
michael@0 48 }
michael@0 49
michael@0 50 return MoveForward(aRoot, mNode);
michael@0 51 }
michael@0 52
michael@0 53 bool NodeIterator::NodePointer::MoveToPrevious(nsINode *aRoot)
michael@0 54 {
michael@0 55 if (!mNode)
michael@0 56 return false;
michael@0 57
michael@0 58 if (!mBeforeNode) {
michael@0 59 mBeforeNode = true;
michael@0 60 return true;
michael@0 61 }
michael@0 62
michael@0 63 if (mNode == aRoot)
michael@0 64 return false;
michael@0 65
michael@0 66 MoveBackward(mNode->GetParentNode(), mNode->GetPreviousSibling());
michael@0 67
michael@0 68 return true;
michael@0 69 }
michael@0 70
michael@0 71 void NodeIterator::NodePointer::AdjustAfterRemoval(nsINode *aRoot,
michael@0 72 nsINode *aContainer,
michael@0 73 nsIContent *aChild,
michael@0 74 nsIContent *aPreviousSibling)
michael@0 75 {
michael@0 76 // If mNode is null or the root there is nothing to do.
michael@0 77 if (!mNode || mNode == aRoot)
michael@0 78 return;
michael@0 79
michael@0 80 // check if ancestor was removed
michael@0 81 if (!nsContentUtils::ContentIsDescendantOf(mNode, aChild))
michael@0 82 return;
michael@0 83
michael@0 84 if (mBeforeNode) {
michael@0 85
michael@0 86 // Try the next sibling
michael@0 87 nsINode *nextSibling = aPreviousSibling ? aPreviousSibling->GetNextSibling()
michael@0 88 : aContainer->GetFirstChild();
michael@0 89
michael@0 90 if (nextSibling) {
michael@0 91 mNode = nextSibling;
michael@0 92 return;
michael@0 93 }
michael@0 94
michael@0 95 // Next try siblings of ancestors
michael@0 96 if (MoveForward(aRoot, aContainer))
michael@0 97 return;
michael@0 98
michael@0 99 // No suitable node was found so try going backwards
michael@0 100 mBeforeNode = false;
michael@0 101 }
michael@0 102
michael@0 103 MoveBackward(aContainer, aPreviousSibling);
michael@0 104 }
michael@0 105
michael@0 106 bool NodeIterator::NodePointer::MoveForward(nsINode *aRoot, nsINode *aNode)
michael@0 107 {
michael@0 108 while (1) {
michael@0 109 if (aNode == aRoot)
michael@0 110 break;
michael@0 111
michael@0 112 nsINode *sibling = aNode->GetNextSibling();
michael@0 113 if (sibling) {
michael@0 114 mNode = sibling;
michael@0 115 return true;
michael@0 116 }
michael@0 117 aNode = aNode->GetParentNode();
michael@0 118 }
michael@0 119
michael@0 120 return false;
michael@0 121 }
michael@0 122
michael@0 123 void NodeIterator::NodePointer::MoveBackward(nsINode *aParent, nsINode *aNode)
michael@0 124 {
michael@0 125 if (aNode) {
michael@0 126 do {
michael@0 127 mNode = aNode;
michael@0 128 aNode = aNode->GetLastChild();
michael@0 129 } while (aNode);
michael@0 130 } else {
michael@0 131 mNode = aParent;
michael@0 132 }
michael@0 133 }
michael@0 134
michael@0 135 /*
michael@0 136 * Factories, constructors and destructors
michael@0 137 */
michael@0 138
michael@0 139 NodeIterator::NodeIterator(nsINode *aRoot,
michael@0 140 uint32_t aWhatToShow,
michael@0 141 const NodeFilterHolder &aFilter) :
michael@0 142 nsTraversal(aRoot, aWhatToShow, aFilter),
michael@0 143 mPointer(mRoot, true)
michael@0 144 {
michael@0 145 aRoot->AddMutationObserver(this);
michael@0 146 }
michael@0 147
michael@0 148 NodeIterator::~NodeIterator()
michael@0 149 {
michael@0 150 /* destructor code */
michael@0 151 if (mRoot)
michael@0 152 mRoot->RemoveMutationObserver(this);
michael@0 153 }
michael@0 154
michael@0 155 /*
michael@0 156 * nsISupports and cycle collection stuff
michael@0 157 */
michael@0 158
michael@0 159 NS_IMPL_CYCLE_COLLECTION_CLASS(NodeIterator)
michael@0 160
michael@0 161 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(NodeIterator)
michael@0 162 if (tmp->mRoot)
michael@0 163 tmp->mRoot->RemoveMutationObserver(tmp);
michael@0 164 NS_IMPL_CYCLE_COLLECTION_UNLINK(mRoot)
michael@0 165 NS_IMPL_CYCLE_COLLECTION_UNLINK(mFilter)
michael@0 166 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
michael@0 167 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(NodeIterator)
michael@0 168 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRoot)
michael@0 169 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFilter)
michael@0 170 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
michael@0 171
michael@0 172 // QueryInterface implementation for NodeIterator
michael@0 173 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(NodeIterator)
michael@0 174 NS_INTERFACE_MAP_ENTRY(nsIDOMNodeIterator)
michael@0 175 NS_INTERFACE_MAP_ENTRY(nsIMutationObserver)
michael@0 176 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMNodeIterator)
michael@0 177 NS_INTERFACE_MAP_END
michael@0 178
michael@0 179 NS_IMPL_CYCLE_COLLECTING_ADDREF(NodeIterator)
michael@0 180 NS_IMPL_CYCLE_COLLECTING_RELEASE(NodeIterator)
michael@0 181
michael@0 182 /* readonly attribute nsIDOMNode root; */
michael@0 183 NS_IMETHODIMP NodeIterator::GetRoot(nsIDOMNode * *aRoot)
michael@0 184 {
michael@0 185 NS_ADDREF(*aRoot = Root()->AsDOMNode());
michael@0 186 return NS_OK;
michael@0 187 }
michael@0 188
michael@0 189 /* readonly attribute unsigned long whatToShow; */
michael@0 190 NS_IMETHODIMP NodeIterator::GetWhatToShow(uint32_t *aWhatToShow)
michael@0 191 {
michael@0 192 *aWhatToShow = WhatToShow();
michael@0 193 return NS_OK;
michael@0 194 }
michael@0 195
michael@0 196 /* readonly attribute nsIDOMNodeFilter filter; */
michael@0 197 NS_IMETHODIMP NodeIterator::GetFilter(nsIDOMNodeFilter **aFilter)
michael@0 198 {
michael@0 199 NS_ENSURE_ARG_POINTER(aFilter);
michael@0 200
michael@0 201 *aFilter = mFilter.ToXPCOMCallback().take();
michael@0 202
michael@0 203 return NS_OK;
michael@0 204 }
michael@0 205
michael@0 206 /* nsIDOMNode nextNode () raises (DOMException); */
michael@0 207 NS_IMETHODIMP NodeIterator::NextNode(nsIDOMNode **_retval)
michael@0 208 {
michael@0 209 return ImplNodeGetter(&NodeIterator::NextNode, _retval);
michael@0 210 }
michael@0 211
michael@0 212 /* nsIDOMNode previousNode () raises (DOMException); */
michael@0 213 NS_IMETHODIMP NodeIterator::PreviousNode(nsIDOMNode **_retval)
michael@0 214 {
michael@0 215 return ImplNodeGetter(&NodeIterator::PreviousNode, _retval);
michael@0 216 }
michael@0 217
michael@0 218 already_AddRefed<nsINode>
michael@0 219 NodeIterator::NextOrPrevNode(NodePointer::MoveToMethodType aMove,
michael@0 220 ErrorResult& aResult)
michael@0 221 {
michael@0 222 if (mInAcceptNode) {
michael@0 223 aResult.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
michael@0 224 return nullptr;
michael@0 225 }
michael@0 226
michael@0 227 mWorkingPointer = mPointer;
michael@0 228
michael@0 229 struct AutoClear {
michael@0 230 NodePointer* mPtr;
michael@0 231 AutoClear(NodePointer* ptr) : mPtr(ptr) {}
michael@0 232 ~AutoClear() { mPtr->Clear(); }
michael@0 233 } ac(&mWorkingPointer);
michael@0 234
michael@0 235 while ((mWorkingPointer.*aMove)(mRoot)) {
michael@0 236 nsCOMPtr<nsINode> testNode = mWorkingPointer.mNode;
michael@0 237 int16_t filtered = TestNode(testNode, aResult);
michael@0 238 if (aResult.Failed()) {
michael@0 239 return nullptr;
michael@0 240 }
michael@0 241
michael@0 242 if (filtered == nsIDOMNodeFilter::FILTER_ACCEPT) {
michael@0 243 mPointer = mWorkingPointer;
michael@0 244 return testNode.forget();
michael@0 245 }
michael@0 246 }
michael@0 247
michael@0 248 return nullptr;
michael@0 249 }
michael@0 250
michael@0 251 /* void detach (); */
michael@0 252 NS_IMETHODIMP NodeIterator::Detach(void)
michael@0 253 {
michael@0 254 if (mRoot) {
michael@0 255 mRoot->OwnerDoc()->WarnOnceAbout(nsIDocument::eNodeIteratorDetach);
michael@0 256 }
michael@0 257 return NS_OK;
michael@0 258 }
michael@0 259
michael@0 260 /* readonly attribute nsIDOMNode referenceNode; */
michael@0 261 NS_IMETHODIMP NodeIterator::GetReferenceNode(nsIDOMNode * *aRefNode)
michael@0 262 {
michael@0 263 nsCOMPtr<nsIDOMNode> node(do_QueryInterface(GetReferenceNode()));
michael@0 264 node.forget(aRefNode);
michael@0 265 return NS_OK;
michael@0 266 }
michael@0 267
michael@0 268 /* readonly attribute boolean pointerBeforeReferenceNode; */
michael@0 269 NS_IMETHODIMP NodeIterator::GetPointerBeforeReferenceNode(bool *aBeforeNode)
michael@0 270 {
michael@0 271 *aBeforeNode = PointerBeforeReferenceNode();
michael@0 272 return NS_OK;
michael@0 273 }
michael@0 274
michael@0 275 /*
michael@0 276 * nsIMutationObserver interface
michael@0 277 */
michael@0 278
michael@0 279 void NodeIterator::ContentRemoved(nsIDocument *aDocument,
michael@0 280 nsIContent *aContainer,
michael@0 281 nsIContent *aChild,
michael@0 282 int32_t aIndexInContainer,
michael@0 283 nsIContent *aPreviousSibling)
michael@0 284 {
michael@0 285 nsINode *container = NODE_FROM(aContainer, aDocument);
michael@0 286
michael@0 287 mPointer.AdjustAfterRemoval(mRoot, container, aChild, aPreviousSibling);
michael@0 288 mWorkingPointer.AdjustAfterRemoval(mRoot, container, aChild, aPreviousSibling);
michael@0 289 }
michael@0 290
michael@0 291 JSObject*
michael@0 292 NodeIterator::WrapObject(JSContext *cx)
michael@0 293 {
michael@0 294 return NodeIteratorBinding::Wrap(cx, this);
michael@0 295 }
michael@0 296
michael@0 297 } // namespace dom
michael@0 298 } // namespace mozilla

mercurial