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"
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"
19 #include "nsContentUtils.h"
20 #include "nsDOMString.h"
22 #include "nsNameSpaceManager.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
{
33 XPathEvaluatorParseContext(XPathNSResolver
* aResolver
, bool aIsCaseSensitive
)
34 : mResolver(aResolver
),
35 mResolverNode(nullptr),
37 mIsCaseSensitive(aIsCaseSensitive
) {}
38 XPathEvaluatorParseContext(nsINode
* aResolver
, bool aIsCaseSensitive
)
40 mResolverNode(aResolver
),
42 mIsCaseSensitive(aIsCaseSensitive
) {}
44 nsresult
getError() { return mLastError
; }
46 int32_t resolveNamespacePrefix(nsAtom
* aPrefix
) override
;
47 nsresult
resolveFunctionCall(nsAtom
* aName
, int32_t aID
,
48 FunctionCall
** aFunction
) override
;
49 bool caseInsensitiveNameTests() override
;
50 void SetErrorOffset(uint32_t aOffset
) override
;
53 XPathNSResolver
* mResolver
;
54 nsINode
* mResolverNode
;
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
,
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
) {
84 mRecycler
= new txResultRecycler
;
87 UniquePtr
<Expr
> expression
;
88 aRv
= txExprParser::createExpr(PromiseFlatString(aExpression
), aContext
,
89 getter_Transfers(expression
));
91 if (!aRv
.ErrorCodeIs(NS_ERROR_DOM_NAMESPACE_ERR
)) {
92 aRv
.SuppressException();
93 aRv
.ThrowSyntaxError("The expression is not a legal expression");
99 return MakeUnique
<XPathExpression
>(std::move(expression
), mRecycler
,
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
);
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
,
119 UniquePtr
<XPathExpression
> expression(
120 CreateExpression(aExpression
, aResolver
, rv
));
124 return expression
->Evaluate(aCx
, aContextNode
, aType
, aResult
, rv
);
128 * Implementation of txIParseContext private to XPathEvaluator, based on a
132 int32_t XPathEvaluatorParseContext::resolveNamespacePrefix(nsAtom
* aPrefix
) {
133 if (!mResolver
&& !mResolverNode
) {
134 return kNameSpaceID_Unknown
;
139 aPrefix
->ToString(prefix
);
145 mResolver
->LookupNamespaceURI(prefix
, ns
, rv
);
147 rv
.SuppressException();
148 return kNameSpaceID_Unknown
;
151 if (aPrefix
== nsGkAtoms::xml
) {
152 ns
.AssignLiteral("http://www.w3.org/XML/1998/namespace");
154 mResolverNode
->LookupNamespaceURI(prefix
, ns
);
158 if (DOMStringIsNull(ns
)) {
159 return kNameSpaceID_Unknown
;
163 return kNameSpaceID_None
;
166 // get the namespaceID for the URI
169 nsNameSpaceManager::GetInstance()->RegisterNameSpace(ns
, id
))
171 : kNameSpaceID_Unknown
;
174 nsresult
XPathEvaluatorParseContext::resolveFunctionCall(nsAtom
* aName
,
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