LCOV - code coverage report
Current view: top level - dom/base - NodeIterator.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 134 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 28 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13