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.cpp263
1 files changed, 263 insertions, 0 deletions
diff --git a/dom/xslt/xpath/XPathEvaluator.cpp b/dom/xslt/xpath/XPathEvaluator.cpp
new file mode 100644
index 000000000..e7170373d
--- /dev/null
+++ b/dom/xslt/xpath/XPathEvaluator.cpp
@@ -0,0 +1,263 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* 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 "mozilla/Move.h"
+#include "nsCOMPtr.h"
+#include "nsIAtom.h"
+#include "mozilla/dom/XPathExpression.h"
+#include "XPathResult.h"
+#include "nsContentCID.h"
+#include "txExpr.h"
+#include "txExprParser.h"
+#include "nsError.h"
+#include "txURIUtils.h"
+#include "nsIDocument.h"
+#include "nsIDOMDocument.h"
+#include "nsDOMString.h"
+#include "nsNameSpaceManager.h"
+#include "nsContentUtils.h"
+#include "txIXPathContext.h"
+#include "mozilla/dom/XPathEvaluatorBinding.h"
+#include "mozilla/dom/BindingUtils.h"
+#include "mozilla/dom/XPathNSResolverBinding.h"
+
+extern nsresult
+TX_ResolveFunctionCallXPCOM(const nsCString &aContractID, int32_t aNamespaceID,
+ nsIAtom *aName, nsISupports *aState,
+ FunctionCall **aFunction);
+
+namespace mozilla {
+namespace 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(nsIAtom* aPrefix, int32_t& aID);
+ nsresult resolveFunctionCall(nsIAtom* aName, int32_t aID,
+ FunctionCall** aFunction);
+ bool caseInsensitiveNameTests();
+ void SetErrorOffset(uint32_t aOffset);
+
+private:
+ XPathNSResolver* mResolver;
+ nsINode* mResolverNode;
+ nsresult mLastError;
+ bool mIsCaseSensitive;
+};
+
+NS_IMPL_ISUPPORTS(XPathEvaluator, nsIDOMXPathEvaluator)
+
+XPathEvaluator::XPathEvaluator(nsIDocument* aDocument)
+ : mDocument(do_GetWeakReference(aDocument))
+{
+}
+
+XPathEvaluator::~XPathEvaluator()
+{
+}
+
+NS_IMETHODIMP
+XPathEvaluator::Evaluate(const nsAString & aExpression,
+ nsIDOMNode *aContextNode,
+ nsIDOMNode *aResolver,
+ uint16_t aType,
+ nsISupports *aInResult,
+ nsISupports **aResult)
+{
+ nsCOMPtr<nsINode> resolver = do_QueryInterface(aResolver);
+ ErrorResult rv;
+ nsAutoPtr<XPathExpression> expression(CreateExpression(aExpression,
+ resolver, rv));
+ if (rv.Failed()) {
+ return rv.StealNSResult();
+ }
+
+ nsCOMPtr<nsINode> node = do_QueryInterface(aContextNode);
+ if (!node) {
+ return NS_ERROR_FAILURE;
+ }
+
+ nsCOMPtr<nsIXPathResult> inResult = do_QueryInterface(aInResult);
+ RefPtr<XPathResult> result =
+ expression->Evaluate(*node, aType,
+ static_cast<XPathResult*>(inResult.get()), rv);
+ if (rv.Failed()) {
+ return rv.StealNSResult();
+ }
+
+ *aResult = ToSupports(result.forget().take());
+
+ return NS_OK;
+}
+
+XPathExpression*
+XPathEvaluator::CreateExpression(const nsAString& aExpression,
+ XPathNSResolver* aResolver, ErrorResult& aRv)
+{
+ nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocument);
+ XPathEvaluatorParseContext pContext(aResolver,
+ !(doc && doc->IsHTMLDocument()));
+ return CreateExpression(aExpression, &pContext, doc, aRv);
+}
+
+XPathExpression*
+XPathEvaluator::CreateExpression(const nsAString& aExpression,
+ nsINode* aResolver, ErrorResult& aRv)
+{
+ nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocument);
+ XPathEvaluatorParseContext pContext(aResolver,
+ !(doc && doc->IsHTMLDocument()));
+ return CreateExpression(aExpression, &pContext, doc, aRv);
+}
+
+XPathExpression*
+XPathEvaluator::CreateExpression(const nsAString & aExpression,
+ txIParseContext* aContext,
+ nsIDocument* aDocument,
+ ErrorResult& aRv)
+{
+ if (!mRecycler) {
+ mRecycler = new txResultRecycler;
+ }
+
+ nsAutoPtr<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.Throw(NS_ERROR_DOM_INVALID_EXPRESSION_ERR);
+ }
+
+ return nullptr;
+ }
+
+ return new XPathExpression(Move(expression), mRecycler, aDocument);
+}
+
+bool
+XPathEvaluator::WrapObject(JSContext* aCx,
+ JS::Handle<JSObject*> aGivenProto,
+ JS::MutableHandle<JSObject*> aReflector)
+{
+ return dom::XPathEvaluatorBinding::Wrap(aCx, this, aGivenProto, aReflector);
+}
+
+/* static */
+already_AddRefed<XPathEvaluator>
+XPathEvaluator::Constructor(const GlobalObject& aGlobal,
+ ErrorResult& rv)
+{
+ RefPtr<XPathEvaluator> newObj = new XPathEvaluator(nullptr);
+ return newObj.forget();
+}
+
+already_AddRefed<XPathResult>
+XPathEvaluator::Evaluate(JSContext* aCx, const nsAString& aExpression,
+ nsINode& aContextNode, XPathNSResolver* aResolver,
+ uint16_t aType, JS::Handle<JSObject*> aResult,
+ ErrorResult& rv)
+{
+ nsAutoPtr<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
+ (nsIAtom* aPrefix, int32_t& aID)
+{
+ aID = kNameSpaceID_Unknown;
+
+ if (!mResolver && !mResolverNode) {
+ return NS_ERROR_DOM_NAMESPACE_ERR;
+ }
+
+ nsAutoString prefix;
+ if (aPrefix) {
+ aPrefix->ToString(prefix);
+ }
+
+ nsVoidableString 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 nsContentUtils::NameSpaceManager()->RegisterNameSpace(ns, aID);
+}
+
+nsresult
+XPathEvaluatorParseContext::resolveFunctionCall(nsIAtom* aName,
+ int32_t aID,
+ FunctionCall** aFn)
+{
+ return NS_ERROR_XPATH_UNKNOWN_FUNCTION;
+}
+
+bool XPathEvaluatorParseContext::caseInsensitiveNameTests()
+{
+ return !mIsCaseSensitive;
+}
+
+void
+XPathEvaluatorParseContext::SetErrorOffset(uint32_t aOffset)
+{
+}
+
+} // namespace dom
+} // namespace mozilla