summaryrefslogtreecommitdiffstats
path: root/dom/xslt/xpath/XPathEvaluator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dom/xslt/xpath/XPathEvaluator.cpp')
-rw-r--r--dom/xslt/xpath/XPathEvaluator.cpp187
1 files changed, 187 insertions, 0 deletions
diff --git a/dom/xslt/xpath/XPathEvaluator.cpp b/dom/xslt/xpath/XPathEvaluator.cpp
new file mode 100644
index 0000000000..269ea98ff6
--- /dev/null
+++ b/dom/xslt/xpath/XPathEvaluator.cpp
@@ -0,0 +1,187 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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 "mozilla/dom/XPathEvaluator.h"
+
+#include <utility>
+
+#include "XPathResult.h"
+#include "mozilla/UniquePtrExtensions.h"
+#include "mozilla/dom/BindingUtils.h"
+#include "mozilla/dom/Document.h"
+#include "mozilla/dom/XPathEvaluatorBinding.h"
+#include "mozilla/dom/XPathExpression.h"
+#include "mozilla/dom/XPathNSResolverBinding.h"
+#include "nsAtom.h"
+#include "nsCOMPtr.h"
+#include "nsContentCID.h"
+#include "nsContentUtils.h"
+#include "nsDOMString.h"
+#include "nsError.h"
+#include "nsNameSpaceManager.h"
+#include "txExpr.h"
+#include "txExprParser.h"
+#include "txIXPathContext.h"
+#include "txURIUtils.h"
+
+namespace mozilla::dom {
+
+// txIParseContext implementation
+class XPathEvaluatorParseContext : public txIParseContext {
+ public:
+ XPathEvaluatorParseContext(XPathNSResolver* aResolver, bool aIsCaseSensitive)
+ : mResolver(aResolver),
+ mResolverNode(nullptr),
+ mLastError(NS_OK),
+ mIsCaseSensitive(aIsCaseSensitive) {}
+ XPathEvaluatorParseContext(nsINode* aResolver, bool aIsCaseSensitive)
+ : mResolver(nullptr),
+ mResolverNode(aResolver),
+ mLastError(NS_OK),
+ mIsCaseSensitive(aIsCaseSensitive) {}
+
+ nsresult getError() { return mLastError; }
+
+ nsresult resolveNamespacePrefix(nsAtom* aPrefix, int32_t& aID) override;
+ nsresult resolveFunctionCall(nsAtom* aName, int32_t aID,
+ FunctionCall** aFunction) override;
+ bool caseInsensitiveNameTests() override;
+ void SetErrorOffset(uint32_t aOffset) override;
+
+ private:
+ XPathNSResolver* mResolver;
+ nsINode* mResolverNode;
+ nsresult mLastError;
+ bool mIsCaseSensitive;
+};
+
+XPathEvaluator::XPathEvaluator(Document* aDocument) : mDocument(aDocument) {}
+
+XPathEvaluator::~XPathEvaluator() = default;
+
+UniquePtr<XPathExpression> XPathEvaluator::CreateExpression(
+ const nsAString& aExpression, XPathNSResolver* aResolver,
+ ErrorResult& aRv) {
+ nsCOMPtr<Document> doc(mDocument);
+ XPathEvaluatorParseContext pContext(aResolver,
+ !(doc && doc->IsHTMLDocument()));
+ return CreateExpression(aExpression, &pContext, doc, aRv);
+}
+
+UniquePtr<XPathExpression> XPathEvaluator::CreateExpression(
+ const nsAString& aExpression, nsINode* aResolver, ErrorResult& aRv) {
+ nsCOMPtr<Document> doc(mDocument);
+ XPathEvaluatorParseContext pContext(aResolver,
+ !(doc && doc->IsHTMLDocument()));
+ return CreateExpression(aExpression, &pContext, doc, aRv);
+}
+
+UniquePtr<XPathExpression> XPathEvaluator::CreateExpression(
+ const nsAString& aExpression, txIParseContext* aContext,
+ Document* aDocument, ErrorResult& aRv) {
+ if (!mRecycler) {
+ mRecycler = new txResultRecycler;
+ }
+
+ UniquePtr<Expr> expression;
+ aRv = txExprParser::createExpr(PromiseFlatString(aExpression), aContext,
+ getter_Transfers(expression));
+ if (aRv.Failed()) {
+ if (!aRv.ErrorCodeIs(NS_ERROR_DOM_NAMESPACE_ERR)) {
+ aRv.SuppressException();
+ aRv.ThrowSyntaxError("The expression is not a legal expression");
+ }
+
+ return nullptr;
+ }
+
+ return MakeUnique<XPathExpression>(std::move(expression), mRecycler,
+ aDocument);
+}
+
+bool XPathEvaluator::WrapObject(JSContext* aCx,
+ JS::Handle<JSObject*> aGivenProto,
+ JS::MutableHandle<JSObject*> aReflector) {
+ return dom::XPathEvaluator_Binding::Wrap(aCx, this, aGivenProto, aReflector);
+}
+
+/* static */
+UniquePtr<XPathEvaluator> XPathEvaluator::Constructor(
+ const GlobalObject& aGlobal) {
+ return MakeUnique<XPathEvaluator>(nullptr);
+}
+
+already_AddRefed<XPathResult> XPathEvaluator::Evaluate(
+ JSContext* aCx, const nsAString& aExpression, nsINode& aContextNode,
+ XPathNSResolver* aResolver, uint16_t aType, JS::Handle<JSObject*> aResult,
+ ErrorResult& rv) {
+ UniquePtr<XPathExpression> expression(
+ CreateExpression(aExpression, aResolver, rv));
+ if (rv.Failed()) {
+ return nullptr;
+ }
+ return expression->Evaluate(aCx, aContextNode, aType, aResult, rv);
+}
+
+/*
+ * Implementation of txIParseContext private to XPathEvaluator, based on a
+ * XPathNSResolver
+ */
+
+nsresult XPathEvaluatorParseContext::resolveNamespacePrefix(nsAtom* aPrefix,
+ int32_t& aID) {
+ aID = kNameSpaceID_Unknown;
+
+ if (!mResolver && !mResolverNode) {
+ return NS_ERROR_DOM_NAMESPACE_ERR;
+ }
+
+ nsAutoString prefix;
+ if (aPrefix) {
+ aPrefix->ToString(prefix);
+ }
+
+ nsAutoString ns;
+ if (mResolver) {
+ ErrorResult rv;
+ mResolver->LookupNamespaceURI(prefix, ns, rv);
+ if (rv.Failed()) {
+ return rv.StealNSResult();
+ }
+ } else {
+ if (aPrefix == nsGkAtoms::xml) {
+ ns.AssignLiteral("http://www.w3.org/XML/1998/namespace");
+ } else {
+ mResolverNode->LookupNamespaceURI(prefix, ns);
+ }
+ }
+
+ if (DOMStringIsNull(ns)) {
+ return NS_ERROR_DOM_NAMESPACE_ERR;
+ }
+
+ if (ns.IsEmpty()) {
+ aID = kNameSpaceID_None;
+
+ return NS_OK;
+ }
+
+ // get the namespaceID for the URI
+ return nsNameSpaceManager::GetInstance()->RegisterNameSpace(ns, aID);
+}
+
+nsresult XPathEvaluatorParseContext::resolveFunctionCall(nsAtom* aName,
+ int32_t aID,
+ FunctionCall** aFn) {
+ return NS_ERROR_XPATH_UNKNOWN_FUNCTION;
+}
+
+bool XPathEvaluatorParseContext::caseInsensitiveNameTests() {
+ return !mIsCaseSensitive;
+}
+
+void XPathEvaluatorParseContext::SetErrorOffset(uint32_t aOffset) {}
+
+} // namespace mozilla::dom