Bug 1874684 - Part 4: Prefer const references instead of copying Instant values....
[gecko.git] / dom / xslt / xpath / XPathEvaluator.cpp
blob14889462fb13f7ce69c75b7b82dd617b09b318cb
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
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"
8 #include <utility>
10 #include "XPathResult.h"
11 #include "mozilla/UniquePtrExtensions.h"
12 #include "mozilla/dom/BindingUtils.h"
13 #include "mozilla/dom/Document.h"
14 #include "mozilla/dom/XPathEvaluatorBinding.h"
15 #include "mozilla/dom/XPathExpression.h"
16 #include "mozilla/dom/XPathNSResolverBinding.h"
17 #include "nsAtom.h"
18 #include "nsCOMPtr.h"
19 #include "nsContentUtils.h"
20 #include "nsDOMString.h"
21 #include "nsError.h"
22 #include "nsNameSpaceManager.h"
23 #include "txExpr.h"
24 #include "txExprParser.h"
25 #include "txIXPathContext.h"
26 #include "txURIUtils.h"
28 namespace mozilla::dom {
30 // txIParseContext implementation
31 class XPathEvaluatorParseContext : public txIParseContext {
32 public:
33 XPathEvaluatorParseContext(XPathNSResolver* aResolver, bool aIsCaseSensitive)
34 : mResolver(aResolver),
35 mResolverNode(nullptr),
36 mLastError(NS_OK),
37 mIsCaseSensitive(aIsCaseSensitive) {}
38 XPathEvaluatorParseContext(nsINode* aResolver, bool aIsCaseSensitive)
39 : mResolver(nullptr),
40 mResolverNode(aResolver),
41 mLastError(NS_OK),
42 mIsCaseSensitive(aIsCaseSensitive) {}
44 nsresult getError() { return mLastError; }
46 nsresult resolveNamespacePrefix(nsAtom* aPrefix, int32_t& aID) override;
47 nsresult resolveFunctionCall(nsAtom* aName, int32_t aID,
48 FunctionCall** aFunction) override;
49 bool caseInsensitiveNameTests() override;
50 void SetErrorOffset(uint32_t aOffset) override;
52 private:
53 XPathNSResolver* mResolver;
54 nsINode* mResolverNode;
55 nsresult mLastError;
56 bool mIsCaseSensitive;
59 XPathEvaluator::XPathEvaluator(Document* aDocument) : mDocument(aDocument) {}
61 XPathEvaluator::~XPathEvaluator() = default;
63 UniquePtr<XPathExpression> XPathEvaluator::CreateExpression(
64 const nsAString& aExpression, XPathNSResolver* aResolver,
65 ErrorResult& aRv) {
66 nsCOMPtr<Document> doc(mDocument);
67 XPathEvaluatorParseContext pContext(aResolver,
68 !(doc && doc->IsHTMLDocument()));
69 return CreateExpression(aExpression, &pContext, doc, aRv);
72 UniquePtr<XPathExpression> XPathEvaluator::CreateExpression(
73 const nsAString& aExpression, nsINode* aResolver, ErrorResult& aRv) {
74 nsCOMPtr<Document> doc(mDocument);
75 XPathEvaluatorParseContext pContext(aResolver,
76 !(doc && doc->IsHTMLDocument()));
77 return CreateExpression(aExpression, &pContext, doc, aRv);
80 UniquePtr<XPathExpression> XPathEvaluator::CreateExpression(
81 const nsAString& aExpression, txIParseContext* aContext,
82 Document* aDocument, ErrorResult& aRv) {
83 if (!mRecycler) {
84 mRecycler = new txResultRecycler;
87 UniquePtr<Expr> expression;
88 aRv = txExprParser::createExpr(PromiseFlatString(aExpression), aContext,
89 getter_Transfers(expression));
90 if (aRv.Failed()) {
91 if (!aRv.ErrorCodeIs(NS_ERROR_DOM_NAMESPACE_ERR)) {
92 aRv.SuppressException();
93 aRv.ThrowSyntaxError("The expression is not a legal expression");
96 return nullptr;
99 return MakeUnique<XPathExpression>(std::move(expression), mRecycler,
100 aDocument);
103 bool XPathEvaluator::WrapObject(JSContext* aCx,
104 JS::Handle<JSObject*> aGivenProto,
105 JS::MutableHandle<JSObject*> aReflector) {
106 return dom::XPathEvaluator_Binding::Wrap(aCx, this, aGivenProto, aReflector);
109 /* static */
110 UniquePtr<XPathEvaluator> XPathEvaluator::Constructor(
111 const GlobalObject& aGlobal) {
112 return MakeUnique<XPathEvaluator>(nullptr);
115 already_AddRefed<XPathResult> XPathEvaluator::Evaluate(
116 JSContext* aCx, const nsAString& aExpression, nsINode& aContextNode,
117 XPathNSResolver* aResolver, uint16_t aType, JS::Handle<JSObject*> aResult,
118 ErrorResult& rv) {
119 UniquePtr<XPathExpression> expression(
120 CreateExpression(aExpression, aResolver, rv));
121 if (rv.Failed()) {
122 return nullptr;
124 return expression->Evaluate(aCx, aContextNode, aType, aResult, rv);
128 * Implementation of txIParseContext private to XPathEvaluator, based on a
129 * XPathNSResolver
132 nsresult XPathEvaluatorParseContext::resolveNamespacePrefix(nsAtom* aPrefix,
133 int32_t& aID) {
134 aID = kNameSpaceID_Unknown;
136 if (!mResolver && !mResolverNode) {
137 return NS_ERROR_DOM_NAMESPACE_ERR;
140 nsAutoString prefix;
141 if (aPrefix) {
142 aPrefix->ToString(prefix);
145 nsAutoString ns;
146 if (mResolver) {
147 ErrorResult rv;
148 mResolver->LookupNamespaceURI(prefix, ns, rv);
149 if (rv.Failed()) {
150 return rv.StealNSResult();
152 } else {
153 if (aPrefix == nsGkAtoms::xml) {
154 ns.AssignLiteral("http://www.w3.org/XML/1998/namespace");
155 } else {
156 mResolverNode->LookupNamespaceURI(prefix, ns);
160 if (DOMStringIsNull(ns)) {
161 return NS_ERROR_DOM_NAMESPACE_ERR;
164 if (ns.IsEmpty()) {
165 aID = kNameSpaceID_None;
167 return NS_OK;
170 // get the namespaceID for the URI
171 return nsNameSpaceManager::GetInstance()->RegisterNameSpace(ns, aID);
174 nsresult XPathEvaluatorParseContext::resolveFunctionCall(nsAtom* aName,
175 int32_t aID,
176 FunctionCall** aFn) {
177 return NS_ERROR_XPATH_UNKNOWN_FUNCTION;
180 bool XPathEvaluatorParseContext::caseInsensitiveNameTests() {
181 return !mIsCaseSensitive;
184 void XPathEvaluatorParseContext::SetErrorOffset(uint32_t aOffset) {}
186 } // namespace mozilla::dom