LCOV - code coverage report
Current view: top level - dom/xslt/xpath - XPathResult.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 149 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 23 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             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #include "XPathResult.h"
       7             : #include "txExprResult.h"
       8             : #include "txNodeSet.h"
       9             : #include "nsError.h"
      10             : #include "mozilla/dom/Attr.h"
      11             : #include "mozilla/dom/Element.h"
      12             : #include "nsDOMClassInfoID.h"
      13             : #include "nsIDOMNode.h"
      14             : #include "nsIDOMDocument.h"
      15             : #include "nsDOMString.h"
      16             : #include "txXPathTreeWalker.h"
      17             : #include "nsCycleCollectionParticipant.h"
      18             : #include "mozilla/dom/XPathResultBinding.h"
      19             : 
      20             : namespace mozilla {
      21             : namespace dom {
      22             : 
      23           0 : XPathResult::XPathResult(nsINode* aParent)
      24             :     : mParent(aParent),
      25             :       mDocument(nullptr),
      26             :       mCurrentPos(0),
      27             :       mResultType(ANY_TYPE),
      28             :       mInvalidIteratorState(true),
      29             :       mBooleanResult(false),
      30           0 :       mNumberResult(0)
      31             : {
      32           0 : }
      33             : 
      34           0 : XPathResult::XPathResult(const XPathResult &aResult)
      35             :     : mParent(aResult.mParent),
      36             :       mResult(aResult.mResult),
      37             :       mResultNodes(aResult.mResultNodes),
      38             :       mDocument(aResult.mDocument),
      39             :       mContextNode(aResult.mContextNode),
      40             :       mCurrentPos(0),
      41           0 :       mResultType(aResult.mResultType),
      42           0 :       mInvalidIteratorState(aResult.mInvalidIteratorState)
      43             : {
      44           0 :     if (mDocument) {
      45           0 :         mDocument->AddMutationObserver(this);
      46             :     }
      47           0 : }
      48             : 
      49           0 : XPathResult::~XPathResult()
      50             : {
      51           0 :     RemoveObserver();
      52           0 : }
      53             : 
      54             : NS_IMPL_CYCLE_COLLECTION_CLASS(XPathResult)
      55             : 
      56           0 : NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(XPathResult)
      57           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(XPathResult)
      58           0 :     NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
      59           0 :     NS_IMPL_CYCLE_COLLECTION_UNLINK(mParent)
      60             :     {
      61           0 :         tmp->RemoveObserver();
      62             :     }
      63           0 :     NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocument)
      64           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
      65           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(XPathResult)
      66           0 :     NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParent)
      67           0 :     NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocument)
      68           0 :     NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mResultNodes)
      69           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
      70             : 
      71           0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(XPathResult)
      72           0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(XPathResult)
      73             : 
      74           0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(XPathResult)
      75           0 :     NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
      76           0 :     NS_INTERFACE_MAP_ENTRY(nsIMutationObserver)
      77           0 :     NS_INTERFACE_MAP_ENTRY(nsIXPathResult)
      78           0 :     NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPathResult)
      79           0 : NS_INTERFACE_MAP_END
      80             : 
      81             : JSObject*
      82           0 : XPathResult::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
      83             : {
      84           0 :     return XPathResultBinding::Wrap(aCx, this, aGivenProto);
      85             : }
      86             : 
      87             : void
      88           0 : XPathResult::RemoveObserver()
      89             : {
      90           0 :     if (mDocument) {
      91           0 :         mDocument->RemoveMutationObserver(this);
      92             :     }
      93           0 : }
      94             : 
      95             : nsINode*
      96           0 : XPathResult::IterateNext(ErrorResult& aRv)
      97             : {
      98           0 :     if (!isIterator()) {
      99           0 :         aRv.Throw(NS_ERROR_DOM_TYPE_ERR);
     100           0 :         return nullptr;
     101             :     }
     102             : 
     103           0 :     if (mDocument) {
     104           0 :         mDocument->FlushPendingNotifications(FlushType::Content);
     105             :     }
     106             : 
     107           0 :     if (mInvalidIteratorState) {
     108           0 :         aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     109           0 :         return nullptr;
     110             :     }
     111             : 
     112           0 :     return mResultNodes.SafeObjectAt(mCurrentPos++);
     113             : }
     114             : 
     115             : void
     116           0 : XPathResult::NodeWillBeDestroyed(const nsINode* aNode)
     117             : {
     118           0 :     nsCOMPtr<nsIMutationObserver> kungFuDeathGrip(this);
     119             :     // Set to null to avoid unregistring unnecessarily
     120           0 :     mDocument = nullptr;
     121           0 :     Invalidate(aNode->IsNodeOfType(nsINode::eCONTENT) ?
     122           0 :                static_cast<const nsIContent*>(aNode) : nullptr);
     123           0 : }
     124             : 
     125             : void
     126           0 : XPathResult::CharacterDataChanged(nsIDocument* aDocument,
     127             :                                   nsIContent *aContent,
     128             :                                   CharacterDataChangeInfo* aInfo)
     129             : {
     130           0 :     Invalidate(aContent);
     131           0 : }
     132             : 
     133             : void
     134           0 : XPathResult::AttributeChanged(nsIDocument* aDocument,
     135             :                               Element* aElement,
     136             :                               int32_t aNameSpaceID,
     137             :                               nsIAtom* aAttribute,
     138             :                               int32_t aModType,
     139             :                               const nsAttrValue* aOldValue)
     140             : {
     141           0 :     Invalidate(aElement);
     142           0 : }
     143             : 
     144             : void
     145           0 : XPathResult::ContentAppended(nsIDocument* aDocument,
     146             :                              nsIContent* aContainer,
     147             :                              nsIContent* aFirstNewContent,
     148             :                              int32_t aNewIndexInContainer)
     149             : {
     150           0 :     Invalidate(aContainer);
     151           0 : }
     152             : 
     153             : void
     154           0 : XPathResult::ContentInserted(nsIDocument* aDocument,
     155             :                              nsIContent* aContainer,
     156             :                              nsIContent* aChild,
     157             :                              int32_t aIndexInContainer)
     158             : {
     159           0 :     Invalidate(aContainer);
     160           0 : }
     161             : 
     162             : void
     163           0 : XPathResult::ContentRemoved(nsIDocument* aDocument,
     164             :                             nsIContent* aContainer,
     165             :                             nsIContent* aChild,
     166             :                             int32_t aIndexInContainer,
     167             :                             nsIContent* aPreviousSibling)
     168             : {
     169           0 :     Invalidate(aContainer);
     170           0 : }
     171             : 
     172             : nsresult
     173           0 : XPathResult::SetExprResult(txAExprResult* aExprResult, uint16_t aResultType,
     174             :                            nsINode* aContextNode)
     175             : {
     176           0 :     MOZ_ASSERT(aExprResult);
     177             : 
     178           0 :     if ((isSnapshot(aResultType) || isIterator(aResultType) ||
     179           0 :          isNode(aResultType)) &&
     180           0 :         aExprResult->getResultType() != txAExprResult::NODESET) {
     181             :         // The DOM spec doesn't really say what should happen when reusing an
     182             :         // XPathResult and an error is thrown. Let's not touch the XPathResult
     183             :         // in that case.
     184           0 :         return NS_ERROR_DOM_TYPE_ERR;
     185             :     }
     186             : 
     187           0 :     mResultType = aResultType;
     188           0 :     mContextNode = do_GetWeakReference(aContextNode);
     189             : 
     190           0 :     if (mDocument) {
     191           0 :         mDocument->RemoveMutationObserver(this);
     192           0 :         mDocument = nullptr;
     193             :     }
     194             : 
     195           0 :     mResultNodes.Clear();
     196             : 
     197             :     // XXX This will keep the recycler alive, should we clear it?
     198           0 :     mResult = aExprResult;
     199           0 :     switch (mResultType) {
     200             :         case BOOLEAN_TYPE:
     201             :         {
     202           0 :             mBooleanResult = mResult->booleanValue();
     203           0 :             break;
     204             :         }
     205             :         case NUMBER_TYPE:
     206             :         {
     207           0 :             mNumberResult = mResult->numberValue();
     208           0 :             break;
     209             :         }
     210             :         case STRING_TYPE:
     211             :         {
     212           0 :             mResult->stringValue(mStringResult);
     213           0 :             break;
     214             :         }
     215             :         default:
     216             :         {
     217           0 :             MOZ_ASSERT(isNode() || isIterator() || isSnapshot());
     218             :         }
     219             :     }
     220             : 
     221           0 :     if (aExprResult->getResultType() == txAExprResult::NODESET) {
     222           0 :         txNodeSet *nodeSet = static_cast<txNodeSet*>(aExprResult);
     223           0 :         int32_t i, count = nodeSet->size();
     224           0 :         for (i = 0; i < count; ++i) {
     225           0 :             nsINode* node = txXPathNativeNode::getNode(nodeSet->get(i));
     226           0 :             mResultNodes.AppendObject(node);
     227             :         }
     228             : 
     229           0 :         if (count > 0) {
     230           0 :             mResult = nullptr;
     231             :         }
     232             :     }
     233             : 
     234           0 :     if (!isIterator()) {
     235           0 :         return NS_OK;
     236             :     }
     237             : 
     238           0 :     mInvalidIteratorState = false;
     239             : 
     240           0 :     if (mResultNodes.Count() > 0) {
     241             :         // If we support the document() function in DOM-XPath we need to
     242             :         // observe all documents that we have resultnodes in.
     243           0 :         mDocument = mResultNodes[0]->OwnerDoc();
     244           0 :         NS_ASSERTION(mDocument, "We need a document!");
     245           0 :         if (mDocument) {
     246           0 :             mDocument->AddMutationObserver(this);
     247             :         }
     248             :     }
     249             : 
     250           0 :     return NS_OK;
     251             : }
     252             : 
     253             : void
     254           0 : XPathResult::Invalidate(const nsIContent* aChangeRoot)
     255             : {
     256           0 :     nsCOMPtr<nsINode> contextNode = do_QueryReferent(mContextNode);
     257           0 :     if (contextNode && aChangeRoot && aChangeRoot->GetBindingParent()) {
     258             :         // If context node is in anonymous content, changes to
     259             :         // non-anonymous content need to invalidate the XPathResult. If
     260             :         // the changes are happening in a different anonymous trees, no
     261             :         // invalidation should happen.
     262           0 :         nsIContent* ctxBindingParent = nullptr;
     263           0 :         if (contextNode->IsNodeOfType(nsINode::eCONTENT)) {
     264             :             ctxBindingParent =
     265           0 :                 static_cast<nsIContent*>(contextNode.get())
     266           0 :                     ->GetBindingParent();
     267           0 :         } else if (contextNode->IsNodeOfType(nsINode::eATTRIBUTE)) {
     268             :             Element* parent =
     269           0 :               static_cast<Attr*>(contextNode.get())->GetElement();
     270           0 :             if (parent) {
     271           0 :                 ctxBindingParent = parent->GetBindingParent();
     272             :             }
     273             :         }
     274           0 :         if (ctxBindingParent != aChangeRoot->GetBindingParent()) {
     275           0 :           return;
     276             :         }
     277             :     }
     278             : 
     279           0 :     mInvalidIteratorState = true;
     280             :     // Make sure nulling out mDocument is the last thing we do.
     281           0 :     if (mDocument) {
     282           0 :         mDocument->RemoveMutationObserver(this);
     283           0 :         mDocument = nullptr;
     284             :     }
     285             : }
     286             : 
     287             : nsresult
     288           0 : XPathResult::GetExprResult(txAExprResult** aExprResult)
     289             : {
     290           0 :     if (isIterator() && mInvalidIteratorState) {
     291           0 :         return NS_ERROR_DOM_INVALID_STATE_ERR;
     292             :     }
     293             : 
     294           0 :     if (mResult) {
     295           0 :         NS_ADDREF(*aExprResult = mResult);
     296             : 
     297           0 :         return NS_OK;
     298             :     }
     299             : 
     300           0 :     if (mResultNodes.Count() == 0) {
     301           0 :         return NS_ERROR_DOM_INVALID_STATE_ERR;
     302             :     }
     303             : 
     304           0 :     RefPtr<txNodeSet> nodeSet = new txNodeSet(nullptr);
     305           0 :     if (!nodeSet) {
     306           0 :         return NS_ERROR_OUT_OF_MEMORY;
     307             :     }
     308             : 
     309           0 :     uint32_t i, count = mResultNodes.Count();
     310           0 :     for (i = 0; i < count; ++i) {
     311           0 :         nsAutoPtr<txXPathNode> node(txXPathNativeNode::createXPathNode(mResultNodes[i]));
     312           0 :         if (!node) {
     313           0 :             return NS_ERROR_OUT_OF_MEMORY;
     314             :         }
     315             : 
     316           0 :         nodeSet->append(*node);
     317             :     }
     318             : 
     319           0 :     NS_ADDREF(*aExprResult = nodeSet);
     320             : 
     321           0 :     return NS_OK;
     322             : }
     323             : 
     324             : nsresult
     325           0 : XPathResult::Clone(nsIXPathResult **aResult)
     326             : {
     327           0 :     *aResult = nullptr;
     328             : 
     329           0 :     if (isIterator() && mInvalidIteratorState) {
     330           0 :         return NS_ERROR_DOM_INVALID_STATE_ERR;
     331             :     }
     332             : 
     333           0 :     NS_ADDREF(*aResult = new XPathResult(*this));
     334             : 
     335           0 :     return NS_OK;
     336             : }
     337             : 
     338             : } // namespace dom
     339             : } // namespace mozilla

Generated by: LCOV version 1.13