LCOV - code coverage report
Current view: top level - dom/xslt/xpath - txMozillaXPathTreeWalker.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 323 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 35 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 "txXPathTreeWalker.h"
       7             : #include "nsIAtom.h"
       8             : #include "nsIAttribute.h"
       9             : #include "nsIDOMAttr.h"
      10             : #include "nsIDOMDocument.h"
      11             : #include "nsIDOMNode.h"
      12             : #include "nsIDOMElement.h"
      13             : #include "nsIDOMProcessingInstruction.h"
      14             : #include "nsPrintfCString.h"
      15             : #include "nsReadableUtils.h"
      16             : #include "nsString.h"
      17             : #include "nsTextFragment.h"
      18             : #include "txXMLUtils.h"
      19             : #include "txLog.h"
      20             : #include "nsUnicharUtils.h"
      21             : #include "nsAttrName.h"
      22             : #include "nsTArray.h"
      23             : #include "mozilla/dom/Attr.h"
      24             : #include "mozilla/dom/Element.h"
      25             : #include <stdint.h>
      26             : #include <algorithm>
      27             : 
      28             : using namespace mozilla::dom;
      29             : 
      30           0 : txXPathTreeWalker::txXPathTreeWalker(const txXPathTreeWalker& aOther)
      31           0 :     : mPosition(aOther.mPosition)
      32             : {
      33           0 : }
      34             : 
      35           0 : txXPathTreeWalker::txXPathTreeWalker(const txXPathNode& aNode)
      36           0 :     : mPosition(aNode)
      37             : {
      38           0 : }
      39             : 
      40             : void
      41           0 : txXPathTreeWalker::moveToRoot()
      42             : {
      43           0 :     if (mPosition.isDocument()) {
      44           0 :         return;
      45             :     }
      46             : 
      47           0 :     nsIDocument* root = mPosition.mNode->GetUncomposedDoc();
      48           0 :     if (root) {
      49           0 :         mPosition.mIndex = txXPathNode::eDocument;
      50           0 :         mPosition.mNode = root;
      51             :     }
      52             :     else {
      53           0 :         nsINode *rootNode = mPosition.Root();
      54             : 
      55           0 :         NS_ASSERTION(rootNode->IsNodeOfType(nsINode::eCONTENT),
      56             :                      "root of subtree wasn't an nsIContent");
      57             : 
      58           0 :         mPosition.mIndex = txXPathNode::eContent;
      59           0 :         mPosition.mNode = rootNode;
      60             :     }
      61             : }
      62             : 
      63             : bool
      64           0 : txXPathTreeWalker::moveToElementById(const nsAString& aID)
      65             : {
      66           0 :     if (aID.IsEmpty()) {
      67           0 :         return false;
      68             :     }
      69             : 
      70           0 :     nsIDocument* doc = mPosition.mNode->GetUncomposedDoc();
      71             : 
      72           0 :     nsCOMPtr<nsIContent> content;
      73           0 :     if (doc) {
      74           0 :         content = doc->GetElementById(aID);
      75             :     }
      76             :     else {
      77             :         // We're in a disconnected subtree, search only that subtree.
      78           0 :         nsINode *rootNode = mPosition.Root();
      79             : 
      80           0 :         NS_ASSERTION(rootNode->IsNodeOfType(nsINode::eCONTENT),
      81             :                      "root of subtree wasn't an nsIContent");
      82             : 
      83           0 :         content = nsContentUtils::MatchElementId(
      84           0 :             static_cast<nsIContent*>(rootNode), aID);
      85             :     }
      86             : 
      87           0 :     if (!content) {
      88           0 :         return false;
      89             :     }
      90             : 
      91           0 :     mPosition.mIndex = txXPathNode::eContent;
      92           0 :     mPosition.mNode = content;
      93             : 
      94           0 :     return true;
      95             : }
      96             : 
      97             : bool
      98           0 : txXPathTreeWalker::moveToFirstAttribute()
      99             : {
     100           0 :     if (!mPosition.isContent()) {
     101           0 :         return false;
     102             :     }
     103             : 
     104           0 :     return moveToValidAttribute(0);
     105             : }
     106             : 
     107             : bool
     108           0 : txXPathTreeWalker::moveToNextAttribute()
     109             : {
     110             :     // XXX an assertion should be enough here with the current code
     111           0 :     if (!mPosition.isAttribute()) {
     112           0 :         return false;
     113             :     }
     114             : 
     115           0 :     return moveToValidAttribute(mPosition.mIndex + 1);
     116             : }
     117             : 
     118             : bool
     119           0 : txXPathTreeWalker::moveToValidAttribute(uint32_t aStartIndex)
     120             : {
     121           0 :     NS_ASSERTION(!mPosition.isDocument(), "documents doesn't have attrs");
     122             : 
     123           0 :     uint32_t total = mPosition.Content()->GetAttrCount();
     124           0 :     if (aStartIndex >= total) {
     125           0 :         return false;
     126             :     }
     127             : 
     128             :     uint32_t index;
     129           0 :     for (index = aStartIndex; index < total; ++index) {
     130           0 :         const nsAttrName* name = mPosition.Content()->GetAttrNameAt(index);
     131             : 
     132             :         // We need to ignore XMLNS attributes.
     133           0 :         if (name->NamespaceID() != kNameSpaceID_XMLNS) {
     134           0 :             mPosition.mIndex = index;
     135             : 
     136           0 :             return true;
     137             :         }
     138             :     }
     139           0 :     return false;
     140             : }
     141             : 
     142             : bool
     143           0 : txXPathTreeWalker::moveToNamedAttribute(nsIAtom* aLocalName, int32_t aNSID)
     144             : {
     145           0 :     if (!mPosition.isContent()) {
     146           0 :         return false;
     147             :     }
     148             : 
     149             :     const nsAttrName* name;
     150             :     uint32_t i;
     151           0 :     for (i = 0; (name = mPosition.Content()->GetAttrNameAt(i)); ++i) {
     152           0 :         if (name->Equals(aLocalName, aNSID)) {
     153           0 :             mPosition.mIndex = i;
     154             : 
     155           0 :             return true;
     156             :         }
     157             :     }
     158           0 :     return false;
     159             : }
     160             : 
     161             : bool
     162           0 : txXPathTreeWalker::moveToFirstChild()
     163             : {
     164           0 :     if (mPosition.isAttribute()) {
     165           0 :         return false;
     166             :     }
     167             : 
     168           0 :     nsIContent* child = mPosition.mNode->GetFirstChild();
     169           0 :     if (!child) {
     170           0 :         return false;
     171             :     }
     172           0 :     mPosition.mIndex = txXPathNode::eContent;
     173           0 :     mPosition.mNode = child;
     174             : 
     175           0 :     return true;
     176             : }
     177             : 
     178             : bool
     179           0 : txXPathTreeWalker::moveToLastChild()
     180             : {
     181           0 :     if (mPosition.isAttribute()) {
     182           0 :         return false;
     183             :     }
     184             : 
     185           0 :     nsIContent* child = mPosition.mNode->GetLastChild();
     186           0 :     if (!child) {
     187           0 :         return false;
     188             :     }
     189             : 
     190           0 :     mPosition.mIndex = txXPathNode::eContent;
     191           0 :     mPosition.mNode = child;
     192             : 
     193           0 :     return true;
     194             : }
     195             : 
     196             : bool
     197           0 : txXPathTreeWalker::moveToNextSibling()
     198             : {
     199           0 :     if (!mPosition.isContent()) {
     200           0 :         return false;
     201             :     }
     202             : 
     203           0 :     nsINode* sibling = mPosition.mNode->GetNextSibling();
     204           0 :     if (!sibling) {
     205           0 :       return false;
     206             :     }
     207             : 
     208           0 :     mPosition.mNode = sibling;
     209             : 
     210           0 :     return true;
     211             : }
     212             : 
     213             : bool
     214           0 : txXPathTreeWalker::moveToPreviousSibling()
     215             : {
     216           0 :     if (!mPosition.isContent()) {
     217           0 :         return false;
     218             :     }
     219             : 
     220           0 :     nsINode* sibling = mPosition.mNode->GetPreviousSibling();
     221           0 :     if (!sibling) {
     222           0 :       return false;
     223             :     }
     224             : 
     225           0 :     mPosition.mNode = sibling;
     226             : 
     227           0 :     return true;
     228             : }
     229             : 
     230             : bool
     231           0 : txXPathTreeWalker::moveToParent()
     232             : {
     233           0 :     if (mPosition.isDocument()) {
     234           0 :         return false;
     235             :     }
     236             : 
     237           0 :     if (mPosition.isAttribute()) {
     238           0 :         mPosition.mIndex = txXPathNode::eContent;
     239             : 
     240           0 :         return true;
     241             :     }
     242             : 
     243           0 :     nsINode* parent = mPosition.mNode->GetParentNode();
     244           0 :     if (!parent) {
     245           0 :         return false;
     246             :     }
     247             : 
     248           0 :     mPosition.mIndex = mPosition.mNode->GetParent() ?
     249             :       txXPathNode::eContent : txXPathNode::eDocument;
     250           0 :     mPosition.mNode = parent;
     251             : 
     252           0 :     return true;
     253             : }
     254             : 
     255           0 : txXPathNode::txXPathNode(const txXPathNode& aNode)
     256           0 :   : mNode(aNode.mNode),
     257           0 :     mRefCountRoot(aNode.mRefCountRoot),
     258           0 :     mIndex(aNode.mIndex)
     259             : {
     260           0 :     MOZ_COUNT_CTOR(txXPathNode);
     261           0 :     if (mRefCountRoot) {
     262           0 :         NS_ADDREF(Root());
     263             :     }
     264           0 : }
     265             : 
     266           0 : txXPathNode::~txXPathNode()
     267             : {
     268           0 :     MOZ_COUNT_DTOR(txXPathNode);
     269           0 :     if (mRefCountRoot) {
     270           0 :         nsINode *root = Root();
     271           0 :         NS_RELEASE(root);
     272             :     }
     273           0 : }
     274             : 
     275             : /* static */
     276             : bool
     277           0 : txXPathNodeUtils::getAttr(const txXPathNode& aNode, nsIAtom* aLocalName,
     278             :                           int32_t aNSID, nsAString& aValue)
     279             : {
     280           0 :     if (aNode.isDocument() || aNode.isAttribute()) {
     281           0 :         return false;
     282             :     }
     283             : 
     284           0 :     return aNode.Content()->GetAttr(aNSID, aLocalName, aValue);
     285             : }
     286             : 
     287             : /* static */
     288             : already_AddRefed<nsIAtom>
     289           0 : txXPathNodeUtils::getLocalName(const txXPathNode& aNode)
     290             : {
     291           0 :     if (aNode.isDocument()) {
     292           0 :         return nullptr;
     293             :     }
     294             : 
     295           0 :     if (aNode.isContent()) {
     296           0 :         if (aNode.mNode->IsElement()) {
     297             :             nsCOMPtr<nsIAtom> localName =
     298           0 :                 aNode.Content()->NodeInfo()->NameAtom();
     299           0 :             return localName.forget();
     300             :         }
     301             : 
     302           0 :         if (aNode.mNode->IsNodeOfType(nsINode::ePROCESSING_INSTRUCTION)) {
     303           0 :             nsCOMPtr<nsIDOMNode> node = do_QueryInterface(aNode.mNode);
     304           0 :             nsAutoString target;
     305           0 :             node->GetNodeName(target);
     306             : 
     307           0 :             return NS_Atomize(target);
     308             :         }
     309             : 
     310           0 :         return nullptr;
     311             :     }
     312             : 
     313           0 :     nsCOMPtr<nsIAtom> localName = aNode.Content()->
     314           0 :         GetAttrNameAt(aNode.mIndex)->LocalName();
     315             : 
     316           0 :     return localName.forget();
     317             : }
     318             : 
     319             : nsIAtom*
     320           0 : txXPathNodeUtils::getPrefix(const txXPathNode& aNode)
     321             : {
     322           0 :     if (aNode.isDocument()) {
     323           0 :         return nullptr;
     324             :     }
     325             : 
     326           0 :     if (aNode.isContent()) {
     327             :         // All other nsIContent node types but elements have a null prefix
     328             :         // which is what we want here.
     329           0 :         return aNode.Content()->NodeInfo()->GetPrefixAtom();
     330             :     }
     331             : 
     332           0 :     return aNode.Content()->GetAttrNameAt(aNode.mIndex)->GetPrefix();
     333             : }
     334             : 
     335             : /* static */
     336             : void
     337           0 : txXPathNodeUtils::getLocalName(const txXPathNode& aNode, nsAString& aLocalName)
     338             : {
     339           0 :     if (aNode.isDocument()) {
     340           0 :         aLocalName.Truncate();
     341             : 
     342           0 :         return;
     343             :     }
     344             : 
     345           0 :     if (aNode.isContent()) {
     346           0 :         if (aNode.mNode->IsElement()) {
     347           0 :             mozilla::dom::NodeInfo* nodeInfo = aNode.Content()->NodeInfo();
     348           0 :             nodeInfo->GetName(aLocalName);
     349           0 :             return;
     350             :         }
     351             : 
     352           0 :         if (aNode.mNode->IsNodeOfType(nsINode::ePROCESSING_INSTRUCTION)) {
     353             :             // PIs don't have a nodeinfo but do have a name
     354           0 :             nsCOMPtr<nsIDOMNode> node = do_QueryInterface(aNode.mNode);
     355           0 :             node->GetNodeName(aLocalName);
     356             : 
     357           0 :             return;
     358             :         }
     359             : 
     360           0 :         aLocalName.Truncate();
     361             : 
     362           0 :         return;
     363             :     }
     364             : 
     365           0 :     aNode.Content()->GetAttrNameAt(aNode.mIndex)->LocalName()->
     366           0 :       ToString(aLocalName);
     367             : 
     368             :     // Check for html
     369           0 :     if (aNode.Content()->NodeInfo()->NamespaceEquals(kNameSpaceID_None) &&
     370           0 :         aNode.Content()->IsHTMLElement()) {
     371           0 :         nsContentUtils::ASCIIToUpper(aLocalName);
     372             :     }
     373             : }
     374             : 
     375             : /* static */
     376             : void
     377           0 : txXPathNodeUtils::getNodeName(const txXPathNode& aNode, nsAString& aName)
     378             : {
     379           0 :     if (aNode.isDocument()) {
     380           0 :         aName.Truncate();
     381             : 
     382           0 :         return;
     383             :     }
     384             : 
     385           0 :     if (aNode.isContent()) {
     386             :         // Elements and PIs have a name
     387           0 :         if (aNode.mNode->IsElement() ||
     388           0 :             aNode.mNode->NodeType() ==
     389             :             nsIDOMNode::PROCESSING_INSTRUCTION_NODE) {
     390           0 :             aName = aNode.Content()->NodeName();
     391           0 :             return;
     392             :         }
     393             : 
     394           0 :         aName.Truncate();
     395             : 
     396           0 :         return;
     397             :     }
     398             : 
     399           0 :     aNode.Content()->GetAttrNameAt(aNode.mIndex)->GetQualifiedName(aName);
     400             : }
     401             : 
     402             : /* static */
     403             : int32_t
     404           0 : txXPathNodeUtils::getNamespaceID(const txXPathNode& aNode)
     405             : {
     406           0 :     if (aNode.isDocument()) {
     407           0 :         return kNameSpaceID_None;
     408             :     }
     409             : 
     410           0 :     if (aNode.isContent()) {
     411           0 :         return aNode.Content()->GetNameSpaceID();
     412             :     }
     413             : 
     414           0 :     return aNode.Content()->GetAttrNameAt(aNode.mIndex)->NamespaceID();
     415             : }
     416             : 
     417             : /* static */
     418             : void
     419           0 : txXPathNodeUtils::getNamespaceURI(const txXPathNode& aNode, nsAString& aURI)
     420             : {
     421           0 :     nsContentUtils::NameSpaceManager()->GetNameSpaceURI(getNamespaceID(aNode), aURI);
     422           0 : }
     423             : 
     424             : /* static */
     425             : uint16_t
     426           0 : txXPathNodeUtils::getNodeType(const txXPathNode& aNode)
     427             : {
     428           0 :     if (aNode.isDocument()) {
     429           0 :         return txXPathNodeType::DOCUMENT_NODE;
     430             :     }
     431             : 
     432           0 :     if (aNode.isContent()) {
     433           0 :         return aNode.mNode->NodeType();
     434             :     }
     435             : 
     436           0 :     return txXPathNodeType::ATTRIBUTE_NODE;
     437             : }
     438             : 
     439             : /* static */
     440             : void
     441           0 : txXPathNodeUtils::appendNodeValue(const txXPathNode& aNode, nsAString& aResult)
     442             : {
     443           0 :     if (aNode.isAttribute()) {
     444           0 :         const nsAttrName* name = aNode.Content()->GetAttrNameAt(aNode.mIndex);
     445             : 
     446           0 :         if (aResult.IsEmpty()) {
     447           0 :             aNode.Content()->GetAttr(name->NamespaceID(), name->LocalName(),
     448           0 :                                      aResult);
     449             :         }
     450             :         else {
     451           0 :             nsAutoString result;
     452           0 :             aNode.Content()->GetAttr(name->NamespaceID(), name->LocalName(),
     453           0 :                                      result);
     454           0 :             aResult.Append(result);
     455             :         }
     456             : 
     457           0 :         return;
     458             :     }
     459             : 
     460           0 :     if (aNode.isDocument() ||
     461           0 :         aNode.mNode->IsElement() ||
     462           0 :         aNode.mNode->IsNodeOfType(nsINode::eDOCUMENT_FRAGMENT)) {
     463           0 :         nsContentUtils::AppendNodeTextContent(aNode.mNode, true, aResult,
     464           0 :                                               mozilla::fallible);
     465             : 
     466           0 :         return;
     467             :     }
     468             : 
     469           0 :     aNode.Content()->AppendTextTo(aResult);
     470             : }
     471             : 
     472             : /* static */
     473             : bool
     474           0 : txXPathNodeUtils::isWhitespace(const txXPathNode& aNode)
     475             : {
     476           0 :     NS_ASSERTION(aNode.isContent() && isText(aNode), "Wrong type!");
     477             : 
     478           0 :     return aNode.Content()->TextIsOnlyWhitespace();
     479             : }
     480             : 
     481             : /* static */
     482             : txXPathNode*
     483           0 : txXPathNodeUtils::getOwnerDocument(const txXPathNode& aNode)
     484             : {
     485           0 :     return new txXPathNode(aNode.mNode->OwnerDoc());
     486             : }
     487             : 
     488             : const char gPrintfFmt[] = "id0x%" PRIxPTR;
     489             : const char gPrintfFmtAttr[] = "id0x%" PRIxPTR "-%010i";
     490             : 
     491             : /* static */
     492             : nsresult
     493           0 : txXPathNodeUtils::getXSLTId(const txXPathNode& aNode,
     494             :                             const txXPathNode& aBase,
     495             :                             nsAString& aResult)
     496             : {
     497           0 :     uintptr_t nodeid = ((uintptr_t)aNode.mNode) - ((uintptr_t)aBase.mNode);
     498           0 :     if (!aNode.isAttribute()) {
     499           0 :         CopyASCIItoUTF16(nsPrintfCString(gPrintfFmt, nodeid),
     500           0 :                          aResult);
     501             :     }
     502             :     else {
     503           0 :         CopyASCIItoUTF16(nsPrintfCString(gPrintfFmtAttr,
     504           0 :                                          nodeid, aNode.mIndex), aResult);
     505             :     }
     506             : 
     507           0 :     return NS_OK;
     508             : }
     509             : 
     510             : /* static */
     511             : nsresult
     512           0 : txXPathNodeUtils::getBaseURI(const txXPathNode& aNode, nsAString& aURI)
     513             : {
     514           0 :     return aNode.mNode->GetBaseURI(aURI);
     515             : }
     516             : 
     517             : /* static */
     518             : int
     519           0 : txXPathNodeUtils::comparePosition(const txXPathNode& aNode,
     520             :                                   const txXPathNode& aOtherNode)
     521             : {
     522             :     // First check for equal nodes or attribute-nodes on the same element.
     523           0 :     if (aNode.mNode == aOtherNode.mNode) {
     524           0 :         if (aNode.mIndex == aOtherNode.mIndex) {
     525           0 :             return 0;
     526             :         }
     527             : 
     528           0 :         NS_ASSERTION(!aNode.isDocument() && !aOtherNode.isDocument(),
     529             :                      "documents should always have a set index");
     530             : 
     531           0 :         if (aNode.isContent() || (!aOtherNode.isContent() &&
     532           0 :                                   aNode.mIndex < aOtherNode.mIndex)) {
     533           0 :             return -1;
     534             :         }
     535             : 
     536           0 :         return 1;
     537             :     }
     538             : 
     539             :     // Get document for both nodes.
     540           0 :     nsIDocument* document = aNode.mNode->GetUncomposedDoc();
     541           0 :     nsIDocument* otherDocument = aOtherNode.mNode->GetUncomposedDoc();
     542             : 
     543             :     // If the nodes have different current documents, compare the document
     544             :     // pointers.
     545           0 :     if (document != otherDocument) {
     546           0 :         return document < otherDocument ? -1 : 1;
     547             :     }
     548             : 
     549             :     // Now either both nodes are in orphan trees, or they are both in the
     550             :     // same tree.
     551             : 
     552             :     // Get parents up the tree.
     553           0 :     AutoTArray<nsINode*, 8> parents, otherParents;
     554           0 :     nsINode* node = aNode.mNode;
     555           0 :     nsINode* otherNode = aOtherNode.mNode;
     556             :     nsINode* parent;
     557             :     nsINode* otherParent;
     558           0 :     while (node && otherNode) {
     559           0 :         parent = node->GetParentNode();
     560           0 :         otherParent = otherNode->GetParentNode();
     561             : 
     562             :         // Hopefully this is a common case.
     563           0 :         if (parent == otherParent) {
     564           0 :             if (!parent) {
     565             :                 // Both node and otherNode are root nodes in respective orphan
     566             :                 // tree.
     567           0 :                 return node < otherNode ? -1 : 1;
     568             :             }
     569             : 
     570           0 :             return parent->IndexOf(node) < parent->IndexOf(otherNode) ?
     571           0 :                    -1 : 1;
     572             :         }
     573             : 
     574           0 :         parents.AppendElement(node);
     575           0 :         otherParents.AppendElement(otherNode);
     576           0 :         node = parent;
     577           0 :         otherNode = otherParent;
     578             :     }
     579             : 
     580           0 :     while (node) {
     581           0 :         parents.AppendElement(node);
     582           0 :         node = node->GetParentNode();
     583             :     }
     584           0 :     while (otherNode) {
     585           0 :         otherParents.AppendElement(otherNode);
     586           0 :         otherNode = otherNode->GetParentNode();
     587             :     }
     588             : 
     589             :     // Walk back down along the parent-chains until we find where they split.
     590           0 :     int32_t total = parents.Length() - 1;
     591           0 :     int32_t otherTotal = otherParents.Length() - 1;
     592           0 :     NS_ASSERTION(total != otherTotal, "Can't have same number of parents");
     593             : 
     594           0 :     int32_t lastIndex = std::min(total, otherTotal);
     595             :     int32_t i;
     596           0 :     parent = nullptr;
     597           0 :     for (i = 0; i <= lastIndex; ++i) {
     598           0 :         node = parents.ElementAt(total - i);
     599           0 :         otherNode = otherParents.ElementAt(otherTotal - i);
     600           0 :         if (node != otherNode) {
     601           0 :             if (!parent) {
     602             :                 // The two nodes are in different orphan subtrees.
     603           0 :                 NS_ASSERTION(i == 0, "this shouldn't happen");
     604           0 :                 return node < otherNode ? -1 : 1;
     605             :             }
     606             : 
     607           0 :             int32_t index = parent->IndexOf(node);
     608           0 :             int32_t otherIndex = parent->IndexOf(otherNode);
     609           0 :             NS_ASSERTION(index != otherIndex && index >= 0 && otherIndex >= 0,
     610             :                          "invalid index in compareTreePosition");
     611             : 
     612           0 :             return index < otherIndex ? -1 : 1;
     613             :         }
     614             : 
     615           0 :         parent = node;
     616             :     }
     617             : 
     618             :     // One node is a descendant of the other. The one with the shortest
     619             :     // parent-chain is first in the document.
     620           0 :     return total < otherTotal ? -1 : 1;
     621             : }
     622             : 
     623             : /* static */
     624             : txXPathNode*
     625           0 : txXPathNativeNode::createXPathNode(nsIContent* aContent, bool aKeepRootAlive)
     626             : {
     627           0 :     nsINode* root = aKeepRootAlive ? txXPathNode::RootOf(aContent) : nullptr;
     628             : 
     629           0 :     return new txXPathNode(aContent, txXPathNode::eContent, root);
     630             : }
     631             : 
     632             : /* static */
     633             : txXPathNode*
     634           0 : txXPathNativeNode::createXPathNode(nsINode* aNode, bool aKeepRootAlive)
     635             : {
     636           0 :     uint16_t nodeType = aNode->NodeType();
     637           0 :     if (nodeType == nsIDOMNode::ATTRIBUTE_NODE) {
     638           0 :         nsCOMPtr<nsIAttribute> attr = do_QueryInterface(aNode);
     639           0 :         NS_ASSERTION(attr, "doesn't implement nsIAttribute");
     640             : 
     641           0 :         mozilla::dom::NodeInfo *nodeInfo = attr->NodeInfo();
     642             :         mozilla::dom::Element* parent =
     643           0 :           static_cast<Attr*>(attr.get())->GetElement();
     644           0 :         if (!parent) {
     645           0 :             return nullptr;
     646             :         }
     647             : 
     648           0 :         nsINode* root = aKeepRootAlive ? txXPathNode::RootOf(parent) : nullptr;
     649             : 
     650           0 :         uint32_t i, total = parent->GetAttrCount();
     651           0 :         for (i = 0; i < total; ++i) {
     652           0 :             const nsAttrName* name = parent->GetAttrNameAt(i);
     653           0 :             if (nodeInfo->Equals(name->LocalName(), name->NamespaceID())) {
     654           0 :                 return new txXPathNode(parent, i, root);
     655             :             }
     656             :         }
     657             : 
     658           0 :         NS_ERROR("Couldn't find the attribute in its parent!");
     659             : 
     660           0 :         return nullptr;
     661             :     }
     662             : 
     663             :     uint32_t index;
     664           0 :     nsINode* root = aKeepRootAlive ? aNode : nullptr;
     665             : 
     666           0 :     if (nodeType == nsIDOMNode::DOCUMENT_NODE) {
     667           0 :         index = txXPathNode::eDocument;
     668             :     }
     669             :     else {
     670           0 :         index = txXPathNode::eContent;
     671           0 :         if (root) {
     672           0 :             root = txXPathNode::RootOf(root);
     673             :         }
     674             :     }
     675             : 
     676           0 :     return new txXPathNode(aNode, index, root);
     677             : }
     678             : 
     679             : /* static */
     680             : txXPathNode*
     681           0 : txXPathNativeNode::createXPathNode(nsIDOMDocument* aDocument)
     682             : {
     683           0 :     nsCOMPtr<nsIDocument> document = do_QueryInterface(aDocument);
     684           0 :     return new txXPathNode(document);
     685             : }
     686             : 
     687             : /* static */
     688             : nsINode*
     689           0 : txXPathNativeNode::getNode(const txXPathNode& aNode)
     690             : {
     691           0 :     if (!aNode.isAttribute()) {
     692           0 :         return aNode.mNode;
     693             :     }
     694             : 
     695           0 :     const nsAttrName* name = aNode.Content()->GetAttrNameAt(aNode.mIndex);
     696             : 
     697           0 :     nsAutoString namespaceURI;
     698           0 :     nsContentUtils::NameSpaceManager()->GetNameSpaceURI(name->NamespaceID(), namespaceURI);
     699             : 
     700           0 :     nsCOMPtr<Element> element = do_QueryInterface(aNode.mNode);
     701           0 :     nsDOMAttributeMap* map = element->Attributes();
     702             :     return map->GetNamedItemNS(namespaceURI,
     703           0 :                                nsDependentAtomString(name->LocalName()));
     704             : }
     705             : 
     706             : /* static */
     707             : nsIContent*
     708           0 : txXPathNativeNode::getContent(const txXPathNode& aNode)
     709             : {
     710           0 :     NS_ASSERTION(aNode.isContent(),
     711             :                  "Only call getContent on nsIContent wrappers!");
     712           0 :     return aNode.Content();
     713             : }
     714             : 
     715             : /* static */
     716             : nsIDocument*
     717           0 : txXPathNativeNode::getDocument(const txXPathNode& aNode)
     718             : {
     719           0 :     NS_ASSERTION(aNode.isDocument(),
     720             :                  "Only call getDocument on nsIDocument wrappers!");
     721           0 :     return aNode.Document();
     722             : }

Generated by: LCOV version 1.13