Bumping manifests a=b2g-bump
[gecko.git] / dom / xslt / xpath / XPathEvaluator.cpp
blob895ae37cb7e13da1ed2a3e3210c4ae619cc59501
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/dom/XPathEvaluator.h"
7 #include "mozilla/Move.h"
8 #include "nsCOMPtr.h"
9 #include "nsIAtom.h"
10 #include "mozilla/dom/XPathExpression.h"
11 #include "nsXPathNSResolver.h"
12 #include "XPathResult.h"
13 #include "nsContentCID.h"
14 #include "txExpr.h"
15 #include "txExprParser.h"
16 #include "nsError.h"
17 #include "txURIUtils.h"
18 #include "nsIDocument.h"
19 #include "nsIDOMDocument.h"
20 #include "nsDOMString.h"
21 #include "nsNameSpaceManager.h"
22 #include "nsContentUtils.h"
23 #include "txIXPathContext.h"
24 #include "mozilla/dom/XPathEvaluatorBinding.h"
25 #include "mozilla/dom/BindingUtils.h"
27 extern nsresult
28 TX_ResolveFunctionCallXPCOM(const nsCString &aContractID, int32_t aNamespaceID,
29 nsIAtom *aName, nsISupports *aState,
30 FunctionCall **aFunction);
32 namespace mozilla {
33 namespace dom {
35 // txIParseContext implementation
36 class XPathEvaluatorParseContext : public txIParseContext
38 public:
39 XPathEvaluatorParseContext(nsIDOMXPathNSResolver* aResolver,
40 bool aIsCaseSensitive)
41 : mResolver(aResolver),
42 mLastError(NS_OK),
43 mIsCaseSensitive(aIsCaseSensitive)
47 nsresult getError()
49 return mLastError;
52 nsresult resolveNamespacePrefix(nsIAtom* aPrefix, int32_t& aID);
53 nsresult resolveFunctionCall(nsIAtom* aName, int32_t aID,
54 FunctionCall** aFunction);
55 bool caseInsensitiveNameTests();
56 void SetErrorOffset(uint32_t aOffset);
58 private:
59 nsIDOMXPathNSResolver* mResolver;
60 nsresult mLastError;
61 bool mIsCaseSensitive;
64 NS_IMPL_ISUPPORTS(XPathEvaluator, nsIDOMXPathEvaluator)
66 XPathEvaluator::XPathEvaluator(nsIDocument* aDocument)
67 : mDocument(do_GetWeakReference(aDocument))
71 XPathEvaluator::~XPathEvaluator()
75 NS_IMETHODIMP
76 XPathEvaluator::CreateNSResolver(nsIDOMNode *aNodeResolver,
77 nsIDOMXPathNSResolver **aResult)
79 NS_ENSURE_ARG(aNodeResolver);
80 if (!nsContentUtils::CanCallerAccess(aNodeResolver))
81 return NS_ERROR_DOM_SECURITY_ERR;
83 *aResult = new nsXPathNSResolver(aNodeResolver);
84 NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY);
86 NS_ADDREF(*aResult);
87 return NS_OK;
90 NS_IMETHODIMP
91 XPathEvaluator::Evaluate(const nsAString & aExpression,
92 nsIDOMNode *aContextNode,
93 nsIDOMXPathNSResolver *aResolver,
94 uint16_t aType,
95 nsISupports *aInResult,
96 nsISupports **aResult)
98 ErrorResult rv;
99 nsAutoPtr<XPathExpression> expression(CreateExpression(aExpression,
100 aResolver, rv));
101 if (rv.Failed()) {
102 return rv.ErrorCode();
105 nsCOMPtr<nsINode> node = do_QueryInterface(aContextNode);
106 if (!node) {
107 return NS_ERROR_FAILURE;
110 nsCOMPtr<nsIXPathResult> inResult = do_QueryInterface(aInResult);
111 nsRefPtr<XPathResult> result =
112 expression->Evaluate(*node, aType,
113 static_cast<XPathResult*>(inResult.get()), rv);
114 if (rv.Failed()) {
115 return rv.ErrorCode();
118 *aResult = ToSupports(result.forget().take());
120 return NS_OK;
124 XPathExpression*
125 XPathEvaluator::CreateExpression(const nsAString & aExpression,
126 nsIDOMXPathNSResolver *aResolver,
127 ErrorResult& aRv)
129 if (!mRecycler) {
130 mRecycler = new txResultRecycler;
133 nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocument);
134 XPathEvaluatorParseContext pContext(aResolver, !(doc && doc->IsHTML()));
136 nsAutoPtr<Expr> expression;
137 aRv = txExprParser::createExpr(PromiseFlatString(aExpression), &pContext,
138 getter_Transfers(expression));
139 if (aRv.Failed()) {
140 if (aRv.ErrorCode() != NS_ERROR_DOM_NAMESPACE_ERR) {
141 aRv.Throw(NS_ERROR_DOM_INVALID_EXPRESSION_ERR);
144 return nullptr;
147 return new XPathExpression(Move(expression), mRecycler, doc);
150 JSObject*
151 XPathEvaluator::WrapObject(JSContext* aCx)
153 return dom::XPathEvaluatorBinding::Wrap(aCx, this);
156 /* static */
157 already_AddRefed<XPathEvaluator>
158 XPathEvaluator::Constructor(const GlobalObject& aGlobal,
159 ErrorResult& rv)
161 nsRefPtr<XPathEvaluator> newObj = new XPathEvaluator(nullptr);
162 return newObj.forget();
165 already_AddRefed<nsIDOMXPathNSResolver>
166 XPathEvaluator::CreateNSResolver(nsINode* aNodeResolver,
167 ErrorResult& rv)
169 nsCOMPtr<nsIDOMNode> nodeResolver = do_QueryInterface(aNodeResolver);
170 nsCOMPtr<nsIDOMXPathNSResolver> res;
171 rv = CreateNSResolver(nodeResolver, getter_AddRefs(res));
172 return res.forget();
175 already_AddRefed<XPathResult>
176 XPathEvaluator::Evaluate(JSContext* aCx, const nsAString& aExpression,
177 nsINode* aContextNode,
178 nsIDOMXPathNSResolver* aResolver, uint16_t aType,
179 JS::Handle<JSObject*> aResult, ErrorResult& rv)
181 nsCOMPtr<nsIDOMNode> contextNode = do_QueryInterface(aContextNode);
182 nsCOMPtr<nsISupports> res;
183 rv = Evaluate(aExpression, contextNode, aResolver, aType,
184 aResult ? UnwrapDOMObjectToISupports(aResult) : nullptr,
185 getter_AddRefs(res));
186 return res.forget().downcast<nsIXPathResult>().downcast<XPathResult>();
191 * Implementation of txIParseContext private to XPathEvaluator, based on a
192 * nsIDOMXPathNSResolver
195 nsresult XPathEvaluatorParseContext::resolveNamespacePrefix
196 (nsIAtom* aPrefix, int32_t& aID)
198 aID = kNameSpaceID_Unknown;
200 if (!mResolver) {
201 return NS_ERROR_DOM_NAMESPACE_ERR;
204 nsAutoString prefix;
205 if (aPrefix) {
206 aPrefix->ToString(prefix);
209 nsVoidableString ns;
210 nsresult rv = mResolver->LookupNamespaceURI(prefix, ns);
211 NS_ENSURE_SUCCESS(rv, rv);
213 if (DOMStringIsNull(ns)) {
214 return NS_ERROR_DOM_NAMESPACE_ERR;
217 if (ns.IsEmpty()) {
218 aID = kNameSpaceID_None;
220 return NS_OK;
223 // get the namespaceID for the URI
224 return nsContentUtils::NameSpaceManager()->RegisterNameSpace(ns, aID);
227 nsresult
228 XPathEvaluatorParseContext::resolveFunctionCall(nsIAtom* aName,
229 int32_t aID,
230 FunctionCall** aFn)
232 return NS_ERROR_XPATH_UNKNOWN_FUNCTION;
235 bool XPathEvaluatorParseContext::caseInsensitiveNameTests()
237 return !mIsCaseSensitive;
240 void
241 XPathEvaluatorParseContext::SetErrorOffset(uint32_t aOffset)
245 } // namespace dom
246 } // namespace mozilla