diff -r 000000000000 -r 6474c204b198 dom/xslt/xpath/nsXPathExpression.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dom/xslt/xpath/nsXPathExpression.cpp Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,199 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsXPathExpression.h" +#include "txExpr.h" +#include "txExprResult.h" +#include "nsError.h" +#include "nsIDOMCharacterData.h" +#include "nsDOMClassInfoID.h" +#include "nsIDOMDocument.h" +#include "nsXPathResult.h" +#include "txURIUtils.h" +#include "txXPathTreeWalker.h" + +NS_IMPL_CYCLE_COLLECTION(nsXPathExpression, mDocument) + +NS_IMPL_CYCLE_COLLECTING_ADDREF(nsXPathExpression) +NS_IMPL_CYCLE_COLLECTING_RELEASE(nsXPathExpression) + +DOMCI_DATA(XPathExpression, nsXPathExpression) + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXPathExpression) + NS_INTERFACE_MAP_ENTRY(nsIDOMXPathExpression) + NS_INTERFACE_MAP_ENTRY(nsIDOMNSXPathExpression) + NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMXPathExpression) + NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(XPathExpression) +NS_INTERFACE_MAP_END + +nsXPathExpression::nsXPathExpression(nsAutoPtr& aExpression, + txResultRecycler* aRecycler, + nsIDOMDocument *aDocument) + : mExpression(aExpression), + mRecycler(aRecycler), + mDocument(aDocument) +{ +} + +NS_IMETHODIMP +nsXPathExpression::Evaluate(nsIDOMNode *aContextNode, + uint16_t aType, + nsISupports *aInResult, + nsISupports **aResult) +{ + return EvaluateWithContext(aContextNode, 1, 1, aType, aInResult, aResult); +} + +NS_IMETHODIMP +nsXPathExpression::EvaluateWithContext(nsIDOMNode *aContextNode, + uint32_t aContextPosition, + uint32_t aContextSize, + uint16_t aType, + nsISupports *aInResult, + nsISupports **aResult) +{ + nsCOMPtr context = do_QueryInterface(aContextNode); + NS_ENSURE_ARG(context); + + if (aContextPosition > aContextSize) + return NS_ERROR_FAILURE; + + if (!nsContentUtils::CanCallerAccess(aContextNode)) + return NS_ERROR_DOM_SECURITY_ERR; + + if (mDocument && mDocument != aContextNode) { + nsCOMPtr contextDocument; + aContextNode->GetOwnerDocument(getter_AddRefs(contextDocument)); + + if (mDocument != contextDocument) { + return NS_ERROR_DOM_WRONG_DOCUMENT_ERR; + } + } + + uint16_t nodeType = context->NodeType(); + + if (nodeType == nsIDOMNode::TEXT_NODE || + nodeType == nsIDOMNode::CDATA_SECTION_NODE) { + nsCOMPtr textNode = do_QueryInterface(aContextNode); + NS_ENSURE_TRUE(textNode, NS_ERROR_FAILURE); + + if (textNode) { + uint32_t textLength; + textNode->GetLength(&textLength); + if (textLength == 0) + return NS_ERROR_DOM_NOT_SUPPORTED_ERR; + } + + // XXX Need to get logical XPath text node for CDATASection + // and Text nodes. + } + else if (nodeType != nsIDOMNode::DOCUMENT_NODE && + nodeType != nsIDOMNode::ELEMENT_NODE && + nodeType != nsIDOMNode::ATTRIBUTE_NODE && + nodeType != nsIDOMNode::COMMENT_NODE && + nodeType != nsIDOMNode::PROCESSING_INSTRUCTION_NODE) { + return NS_ERROR_DOM_NOT_SUPPORTED_ERR; + } + + NS_ENSURE_ARG(aResult); + *aResult = nullptr; + + nsAutoPtr contextNode(txXPathNativeNode::createXPathNode(aContextNode)); + if (!contextNode) { + return NS_ERROR_OUT_OF_MEMORY; + } + + EvalContextImpl eContext(*contextNode, aContextPosition, aContextSize, + mRecycler); + nsRefPtr exprResult; + nsresult rv = mExpression->evaluate(&eContext, getter_AddRefs(exprResult)); + NS_ENSURE_SUCCESS(rv, rv); + + uint16_t resultType = aType; + if (aType == nsIDOMXPathResult::ANY_TYPE) { + short exprResultType = exprResult->getResultType(); + switch (exprResultType) { + case txAExprResult::NUMBER: + resultType = nsIDOMXPathResult::NUMBER_TYPE; + break; + case txAExprResult::STRING: + resultType = nsIDOMXPathResult::STRING_TYPE; + break; + case txAExprResult::BOOLEAN: + resultType = nsIDOMXPathResult::BOOLEAN_TYPE; + break; + case txAExprResult::NODESET: + resultType = nsIDOMXPathResult::UNORDERED_NODE_ITERATOR_TYPE; + break; + case txAExprResult::RESULT_TREE_FRAGMENT: + NS_ERROR("Can't return a tree fragment!"); + return NS_ERROR_FAILURE; + } + } + + // We need a result object and it must be our implementation. + nsCOMPtr xpathResult = do_QueryInterface(aInResult); + if (!xpathResult) { + // Either no aInResult or not one of ours. + xpathResult = new nsXPathResult(); + NS_ENSURE_TRUE(xpathResult, NS_ERROR_OUT_OF_MEMORY); + } + rv = xpathResult->SetExprResult(exprResult, resultType, context); + NS_ENSURE_SUCCESS(rv, rv); + + return CallQueryInterface(xpathResult, aResult); +} + +/* + * Implementation of the txIEvalContext private to nsXPathExpression + * EvalContextImpl bases on only one context node and no variables + */ + +nsresult +nsXPathExpression::EvalContextImpl::getVariable(int32_t aNamespace, + nsIAtom* aLName, + txAExprResult*& aResult) +{ + aResult = 0; + return NS_ERROR_INVALID_ARG; +} + +bool nsXPathExpression::EvalContextImpl::isStripSpaceAllowed(const txXPathNode& aNode) +{ + return false; +} + +void* nsXPathExpression::EvalContextImpl::getPrivateContext() +{ + // we don't have a private context here. + return nullptr; +} + +txResultRecycler* nsXPathExpression::EvalContextImpl::recycler() +{ + return mRecycler; +} + +void nsXPathExpression::EvalContextImpl::receiveError(const nsAString& aMsg, + nsresult aRes) +{ + mLastError = aRes; + // forward aMsg to console service? +} + +const txXPathNode& nsXPathExpression::EvalContextImpl::getContextNode() +{ + return mContextNode; +} + +uint32_t nsXPathExpression::EvalContextImpl::size() +{ + return mContextSize; +} + +uint32_t nsXPathExpression::EvalContextImpl::position() +{ + return mContextPosition; +}