1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/dom/xslt/xpath/nsXPathExpression.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,199 @@ 1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "nsXPathExpression.h" 1.10 +#include "txExpr.h" 1.11 +#include "txExprResult.h" 1.12 +#include "nsError.h" 1.13 +#include "nsIDOMCharacterData.h" 1.14 +#include "nsDOMClassInfoID.h" 1.15 +#include "nsIDOMDocument.h" 1.16 +#include "nsXPathResult.h" 1.17 +#include "txURIUtils.h" 1.18 +#include "txXPathTreeWalker.h" 1.19 + 1.20 +NS_IMPL_CYCLE_COLLECTION(nsXPathExpression, mDocument) 1.21 + 1.22 +NS_IMPL_CYCLE_COLLECTING_ADDREF(nsXPathExpression) 1.23 +NS_IMPL_CYCLE_COLLECTING_RELEASE(nsXPathExpression) 1.24 + 1.25 +DOMCI_DATA(XPathExpression, nsXPathExpression) 1.26 + 1.27 +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXPathExpression) 1.28 + NS_INTERFACE_MAP_ENTRY(nsIDOMXPathExpression) 1.29 + NS_INTERFACE_MAP_ENTRY(nsIDOMNSXPathExpression) 1.30 + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMXPathExpression) 1.31 + NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(XPathExpression) 1.32 +NS_INTERFACE_MAP_END 1.33 + 1.34 +nsXPathExpression::nsXPathExpression(nsAutoPtr<Expr>& aExpression, 1.35 + txResultRecycler* aRecycler, 1.36 + nsIDOMDocument *aDocument) 1.37 + : mExpression(aExpression), 1.38 + mRecycler(aRecycler), 1.39 + mDocument(aDocument) 1.40 +{ 1.41 +} 1.42 + 1.43 +NS_IMETHODIMP 1.44 +nsXPathExpression::Evaluate(nsIDOMNode *aContextNode, 1.45 + uint16_t aType, 1.46 + nsISupports *aInResult, 1.47 + nsISupports **aResult) 1.48 +{ 1.49 + return EvaluateWithContext(aContextNode, 1, 1, aType, aInResult, aResult); 1.50 +} 1.51 + 1.52 +NS_IMETHODIMP 1.53 +nsXPathExpression::EvaluateWithContext(nsIDOMNode *aContextNode, 1.54 + uint32_t aContextPosition, 1.55 + uint32_t aContextSize, 1.56 + uint16_t aType, 1.57 + nsISupports *aInResult, 1.58 + nsISupports **aResult) 1.59 +{ 1.60 + nsCOMPtr<nsINode> context = do_QueryInterface(aContextNode); 1.61 + NS_ENSURE_ARG(context); 1.62 + 1.63 + if (aContextPosition > aContextSize) 1.64 + return NS_ERROR_FAILURE; 1.65 + 1.66 + if (!nsContentUtils::CanCallerAccess(aContextNode)) 1.67 + return NS_ERROR_DOM_SECURITY_ERR; 1.68 + 1.69 + if (mDocument && mDocument != aContextNode) { 1.70 + nsCOMPtr<nsIDOMDocument> contextDocument; 1.71 + aContextNode->GetOwnerDocument(getter_AddRefs(contextDocument)); 1.72 + 1.73 + if (mDocument != contextDocument) { 1.74 + return NS_ERROR_DOM_WRONG_DOCUMENT_ERR; 1.75 + } 1.76 + } 1.77 + 1.78 + uint16_t nodeType = context->NodeType(); 1.79 + 1.80 + if (nodeType == nsIDOMNode::TEXT_NODE || 1.81 + nodeType == nsIDOMNode::CDATA_SECTION_NODE) { 1.82 + nsCOMPtr<nsIDOMCharacterData> textNode = do_QueryInterface(aContextNode); 1.83 + NS_ENSURE_TRUE(textNode, NS_ERROR_FAILURE); 1.84 + 1.85 + if (textNode) { 1.86 + uint32_t textLength; 1.87 + textNode->GetLength(&textLength); 1.88 + if (textLength == 0) 1.89 + return NS_ERROR_DOM_NOT_SUPPORTED_ERR; 1.90 + } 1.91 + 1.92 + // XXX Need to get logical XPath text node for CDATASection 1.93 + // and Text nodes. 1.94 + } 1.95 + else if (nodeType != nsIDOMNode::DOCUMENT_NODE && 1.96 + nodeType != nsIDOMNode::ELEMENT_NODE && 1.97 + nodeType != nsIDOMNode::ATTRIBUTE_NODE && 1.98 + nodeType != nsIDOMNode::COMMENT_NODE && 1.99 + nodeType != nsIDOMNode::PROCESSING_INSTRUCTION_NODE) { 1.100 + return NS_ERROR_DOM_NOT_SUPPORTED_ERR; 1.101 + } 1.102 + 1.103 + NS_ENSURE_ARG(aResult); 1.104 + *aResult = nullptr; 1.105 + 1.106 + nsAutoPtr<txXPathNode> contextNode(txXPathNativeNode::createXPathNode(aContextNode)); 1.107 + if (!contextNode) { 1.108 + return NS_ERROR_OUT_OF_MEMORY; 1.109 + } 1.110 + 1.111 + EvalContextImpl eContext(*contextNode, aContextPosition, aContextSize, 1.112 + mRecycler); 1.113 + nsRefPtr<txAExprResult> exprResult; 1.114 + nsresult rv = mExpression->evaluate(&eContext, getter_AddRefs(exprResult)); 1.115 + NS_ENSURE_SUCCESS(rv, rv); 1.116 + 1.117 + uint16_t resultType = aType; 1.118 + if (aType == nsIDOMXPathResult::ANY_TYPE) { 1.119 + short exprResultType = exprResult->getResultType(); 1.120 + switch (exprResultType) { 1.121 + case txAExprResult::NUMBER: 1.122 + resultType = nsIDOMXPathResult::NUMBER_TYPE; 1.123 + break; 1.124 + case txAExprResult::STRING: 1.125 + resultType = nsIDOMXPathResult::STRING_TYPE; 1.126 + break; 1.127 + case txAExprResult::BOOLEAN: 1.128 + resultType = nsIDOMXPathResult::BOOLEAN_TYPE; 1.129 + break; 1.130 + case txAExprResult::NODESET: 1.131 + resultType = nsIDOMXPathResult::UNORDERED_NODE_ITERATOR_TYPE; 1.132 + break; 1.133 + case txAExprResult::RESULT_TREE_FRAGMENT: 1.134 + NS_ERROR("Can't return a tree fragment!"); 1.135 + return NS_ERROR_FAILURE; 1.136 + } 1.137 + } 1.138 + 1.139 + // We need a result object and it must be our implementation. 1.140 + nsCOMPtr<nsIXPathResult> xpathResult = do_QueryInterface(aInResult); 1.141 + if (!xpathResult) { 1.142 + // Either no aInResult or not one of ours. 1.143 + xpathResult = new nsXPathResult(); 1.144 + NS_ENSURE_TRUE(xpathResult, NS_ERROR_OUT_OF_MEMORY); 1.145 + } 1.146 + rv = xpathResult->SetExprResult(exprResult, resultType, context); 1.147 + NS_ENSURE_SUCCESS(rv, rv); 1.148 + 1.149 + return CallQueryInterface(xpathResult, aResult); 1.150 +} 1.151 + 1.152 +/* 1.153 + * Implementation of the txIEvalContext private to nsXPathExpression 1.154 + * EvalContextImpl bases on only one context node and no variables 1.155 + */ 1.156 + 1.157 +nsresult 1.158 +nsXPathExpression::EvalContextImpl::getVariable(int32_t aNamespace, 1.159 + nsIAtom* aLName, 1.160 + txAExprResult*& aResult) 1.161 +{ 1.162 + aResult = 0; 1.163 + return NS_ERROR_INVALID_ARG; 1.164 +} 1.165 + 1.166 +bool nsXPathExpression::EvalContextImpl::isStripSpaceAllowed(const txXPathNode& aNode) 1.167 +{ 1.168 + return false; 1.169 +} 1.170 + 1.171 +void* nsXPathExpression::EvalContextImpl::getPrivateContext() 1.172 +{ 1.173 + // we don't have a private context here. 1.174 + return nullptr; 1.175 +} 1.176 + 1.177 +txResultRecycler* nsXPathExpression::EvalContextImpl::recycler() 1.178 +{ 1.179 + return mRecycler; 1.180 +} 1.181 + 1.182 +void nsXPathExpression::EvalContextImpl::receiveError(const nsAString& aMsg, 1.183 + nsresult aRes) 1.184 +{ 1.185 + mLastError = aRes; 1.186 + // forward aMsg to console service? 1.187 +} 1.188 + 1.189 +const txXPathNode& nsXPathExpression::EvalContextImpl::getContextNode() 1.190 +{ 1.191 + return mContextNode; 1.192 +} 1.193 + 1.194 +uint32_t nsXPathExpression::EvalContextImpl::size() 1.195 +{ 1.196 + return mContextSize; 1.197 +} 1.198 + 1.199 +uint32_t nsXPathExpression::EvalContextImpl::position() 1.200 +{ 1.201 + return mContextPosition; 1.202 +}