Bumping manifests a=b2g-bump
[gecko.git] / dom / xslt / xpath / XPathExpression.cpp
blobc52d5ad58e4bf285ccfdd1b36cb6927bb1ad7359
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/. */
6 #include "mozilla/Move.h"
7 #include "XPathExpression.h"
8 #include "txExpr.h"
9 #include "txExprResult.h"
10 #include "txIXPathContext.h"
11 #include "nsError.h"
12 #include "nsIDOMCharacterData.h"
13 #include "nsDOMClassInfoID.h"
14 #include "nsIDOMDocument.h"
15 #include "XPathResult.h"
16 #include "txURIUtils.h"
17 #include "txXPathTreeWalker.h"
18 #include "mozilla/dom/BindingUtils.h"
19 #include "mozilla/dom/XPathResultBinding.h"
21 using mozilla::Move;
23 namespace mozilla {
24 namespace dom {
26 class EvalContextImpl : public txIEvalContext
28 public:
29 EvalContextImpl(const txXPathNode& aContextNode,
30 uint32_t aContextPosition, uint32_t aContextSize,
31 txResultRecycler* aRecycler)
32 : mContextNode(aContextNode),
33 mContextPosition(aContextPosition),
34 mContextSize(aContextSize),
35 mLastError(NS_OK),
36 mRecycler(aRecycler)
40 nsresult getError()
42 return mLastError;
45 TX_DECL_EVAL_CONTEXT;
47 private:
48 const txXPathNode& mContextNode;
49 uint32_t mContextPosition;
50 uint32_t mContextSize;
51 nsresult mLastError;
52 nsRefPtr<txResultRecycler> mRecycler;
55 XPathExpression::XPathExpression(nsAutoPtr<Expr>&& aExpression,
56 txResultRecycler* aRecycler,
57 nsIDocument *aDocument)
58 : mExpression(Move(aExpression)),
59 mRecycler(aRecycler),
60 mDocument(do_GetWeakReference(aDocument)),
61 mCheckDocument(aDocument != nullptr)
65 XPathExpression::~XPathExpression()
69 already_AddRefed<XPathResult>
70 XPathExpression::EvaluateWithContext(JSContext* aCx,
71 nsINode& aContextNode,
72 uint32_t aContextPosition,
73 uint32_t aContextSize,
74 uint16_t aType,
75 JS::Handle<JSObject*> aInResult,
76 ErrorResult& aRv)
78 XPathResult* inResult = nullptr;
79 if (aInResult) {
80 nsresult rv = UNWRAP_OBJECT(XPathResult, aInResult, inResult);
81 if (NS_FAILED(rv) && rv != NS_ERROR_XPC_BAD_CONVERT_JS) {
82 aRv.Throw(rv);
83 return nullptr;
87 return EvaluateWithContext(aContextNode, aContextPosition, aContextSize,
88 aType, inResult, aRv);
91 already_AddRefed<XPathResult>
92 XPathExpression::EvaluateWithContext(nsINode& aContextNode,
93 uint32_t aContextPosition,
94 uint32_t aContextSize,
95 uint16_t aType,
96 XPathResult* aInResult,
97 ErrorResult& aRv)
99 if (aContextPosition > aContextSize) {
100 aRv.Throw(NS_ERROR_FAILURE);
101 return nullptr;
104 if (!nsContentUtils::CanCallerAccess(&aContextNode)) {
105 aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
106 return nullptr;
109 if (mCheckDocument) {
110 nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocument);
111 if (doc != aContextNode.OwnerDoc()) {
112 aRv.Throw(NS_ERROR_DOM_WRONG_DOCUMENT_ERR);
113 return nullptr;
117 uint16_t nodeType = aContextNode.NodeType();
119 if (nodeType == nsIDOMNode::TEXT_NODE ||
120 nodeType == nsIDOMNode::CDATA_SECTION_NODE) {
121 nsCOMPtr<nsIDOMCharacterData> textNode =
122 do_QueryInterface(&aContextNode);
123 if (!textNode) {
124 aRv.Throw(NS_ERROR_FAILURE);
125 return nullptr;
128 uint32_t textLength;
129 textNode->GetLength(&textLength);
130 if (textLength == 0) {
131 aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
132 return nullptr;
135 // XXX Need to get logical XPath text node for CDATASection
136 // and Text nodes.
138 else if (nodeType != nsIDOMNode::DOCUMENT_NODE &&
139 nodeType != nsIDOMNode::ELEMENT_NODE &&
140 nodeType != nsIDOMNode::ATTRIBUTE_NODE &&
141 nodeType != nsIDOMNode::COMMENT_NODE &&
142 nodeType != nsIDOMNode::PROCESSING_INSTRUCTION_NODE) {
143 aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
144 return nullptr;
147 nsAutoPtr<txXPathNode> contextNode(txXPathNativeNode::createXPathNode(&aContextNode));
148 EvalContextImpl eContext(*contextNode, aContextPosition, aContextSize,
149 mRecycler);
150 nsRefPtr<txAExprResult> exprResult;
151 aRv = mExpression->evaluate(&eContext, getter_AddRefs(exprResult));
152 if (aRv.Failed()) {
153 return nullptr;
156 uint16_t resultType = aType;
157 if (aType == XPathResult::ANY_TYPE) {
158 short exprResultType = exprResult->getResultType();
159 switch (exprResultType) {
160 case txAExprResult::NUMBER:
161 resultType = XPathResult::NUMBER_TYPE;
162 break;
163 case txAExprResult::STRING:
164 resultType = XPathResult::STRING_TYPE;
165 break;
166 case txAExprResult::BOOLEAN:
167 resultType = XPathResult::BOOLEAN_TYPE;
168 break;
169 case txAExprResult::NODESET:
170 resultType = XPathResult::UNORDERED_NODE_ITERATOR_TYPE;
171 break;
172 case txAExprResult::RESULT_TREE_FRAGMENT:
173 aRv.Throw(NS_ERROR_FAILURE);
174 return nullptr;
178 nsRefPtr<XPathResult> xpathResult = aInResult;
179 if (!xpathResult) {
180 xpathResult = new XPathResult(&aContextNode);
183 aRv = xpathResult->SetExprResult(exprResult, resultType, &aContextNode);
185 return xpathResult.forget();
189 * Implementation of the txIEvalContext private to XPathExpression
190 * EvalContextImpl bases on only one context node and no variables
193 nsresult
194 EvalContextImpl::getVariable(int32_t aNamespace,
195 nsIAtom* aLName,
196 txAExprResult*& aResult)
198 aResult = 0;
199 return NS_ERROR_INVALID_ARG;
202 bool
203 EvalContextImpl::isStripSpaceAllowed(const txXPathNode& aNode)
205 return false;
208 void*
209 EvalContextImpl::getPrivateContext()
211 // we don't have a private context here.
212 return nullptr;
215 txResultRecycler*
216 EvalContextImpl::recycler()
218 return mRecycler;
221 void
222 EvalContextImpl::receiveError(const nsAString& aMsg, nsresult aRes)
224 mLastError = aRes;
225 // forward aMsg to console service?
228 const txXPathNode&
229 EvalContextImpl::getContextNode()
231 return mContextNode;
234 uint32_t
235 EvalContextImpl::size()
237 return mContextSize;
240 uint32_t
241 EvalContextImpl::position()
243 return mContextPosition;
246 } // namespace dom
247 } // namespace mozilla