Bug 1029104 - Convert XPathExpression to WebIDL bindings, add WebIDL API and switch to the WebIDL binding. r=bz.
authorPeter Van der Beken <peterv@propagandism.org>
Fri, 27 Jun 2014 21:39:50 +0200
changeset 191347 e8a9bdc06b16c017e104ec319a2eaf5c346ce287
parent 191346 b7cf23c2be3e02e302e5c7938f7ddc3a46c6fe19
child 191348 6abd5ef709cc76f0fd9077fabc6eeb2a3cc19441
push id27041
push userphilringnalda@gmail.com
push dateSun, 29 Jun 2014 00:39:21 +0000
treeherdermozilla-central@afa67a2f7905 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs1029104
milestone33.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1029104 - Convert XPathExpression to WebIDL bindings, add WebIDL API and switch to the WebIDL binding. r=bz.
content/base/public/nsIDocument.h
content/base/src/nsDocument.cpp
content/xul/templates/src/nsXMLBinding.cpp
content/xul/templates/src/nsXMLBinding.h
content/xul/templates/src/nsXULTemplateQueryProcessorXML.cpp
content/xul/templates/src/nsXULTemplateQueryProcessorXML.h
dom/base/nsDOMClassInfo.cpp
dom/base/nsDOMClassInfoClasses.h
dom/bindings/Bindings.conf
dom/interfaces/xpath/moz.build
dom/interfaces/xpath/nsIDOMNSXPathExpression.idl
dom/interfaces/xpath/nsIDOMXPathEvaluator.idl
dom/interfaces/xpath/nsIDOMXPathExpression.idl
dom/webidl/XPathEvaluator.webidl
dom/webidl/XPathExpression.webidl
dom/webidl/moz.build
dom/xslt/xpath/XPathEvaluator.cpp
dom/xslt/xpath/XPathEvaluator.h
dom/xslt/xpath/XPathExpression.cpp
dom/xslt/xpath/XPathExpression.h
js/xpconnect/src/dom_quickstubs.qsconf
--- a/content/base/public/nsIDocument.h
+++ b/content/base/public/nsIDocument.h
@@ -46,17 +46,16 @@ class nsIDocShell;
 class nsIDocumentEncoder;
 class nsIDocumentObserver;
 class nsIDOMDocument;
 class nsIDOMDocumentFragment;
 class nsIDOMDocumentType;
 class nsIDOMElement;
 class nsIDOMNodeFilter;
 class nsIDOMNodeList;
-class nsIDOMXPathExpression;
 class nsIDOMXPathNSResolver;
 class nsIHTMLCollection;
 class nsILayoutHistoryState;
 class nsILoadContext;
 class nsIObjectLoadingContent;
 class nsIObserver;
 class nsIPresShell;
 class nsIPrincipal;
@@ -117,16 +116,17 @@ class NodeIterator;
 class ProcessingInstruction;
 class StyleSheetList;
 class SVGDocument;
 class Touch;
 class TouchList;
 class TreeWalker;
 class UndoManager;
 class XPathEvaluator;
+class XPathExpression;
 class XPathResult;
 template<typename> class OwningNonNull;
 template<typename> class Sequence;
 
 template<typename, typename> class CallbackObjectHolder;
 typedef CallbackObjectHolder<NodeFilter, nsIDOMNodeFilter> NodeFilterHolder;
 } // namespace dom
 } // namespace mozilla
@@ -2264,17 +2264,17 @@ public:
 
   // QuerySelector and QuerySelectorAll already defined on nsINode
   nsINodeList* GetAnonymousNodes(Element& aElement);
   Element* GetAnonymousElementByAttribute(Element& aElement,
                                           const nsAString& aAttrName,
                                           const nsAString& aAttrValue);
   Element* GetBindingParent(nsINode& aNode);
   void LoadBindingDocument(const nsAString& aURI, mozilla::ErrorResult& rv);
-  already_AddRefed<nsIDOMXPathExpression>
+  mozilla::dom::XPathExpression*
     CreateExpression(const nsAString& aExpression,
                      nsIDOMXPathNSResolver* aResolver,
                      mozilla::ErrorResult& rv);
   already_AddRefed<nsIDOMXPathNSResolver>
     CreateNSResolver(nsINode* aNodeResolver, mozilla::ErrorResult& rv);
   already_AddRefed<mozilla::dom::XPathResult>
     Evaluate(JSContext* aCx, const nsAString& aExpression, nsINode* aContextNode,
              nsIDOMXPathNSResolver* aResolver, uint16_t aType,
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -97,17 +97,16 @@
 // for radio group stuff
 #include "nsIDOMHTMLInputElement.h"
 #include "nsIRadioVisitor.h"
 #include "nsIFormControl.h"
 
 #include "nsBidiUtils.h"
 
 #include "nsIDOMUserDataHandler.h"
-#include "nsIDOMXPathExpression.h"
 #include "nsIDOMXPathNSResolver.h"
 #include "nsIParserService.h"
 #include "nsContentCreatorFunctions.h"
 
 #include "nsIScriptContext.h"
 #include "nsBindingManager.h"
 #include "nsIDOMHTMLDocument.h"
 #include "nsHTMLDocument.h"
@@ -12036,17 +12035,17 @@ nsIDocument::Constructor(const GlobalObj
   }
 
   nsCOMPtr<nsIDocument> doc = do_QueryInterface(document);
   doc->SetReadyStateInternal(nsIDocument::READYSTATE_COMPLETE);
 
   return doc.forget();
 }
 
-already_AddRefed<nsIDOMXPathExpression>
+XPathExpression*
 nsIDocument::CreateExpression(const nsAString& aExpression,
                               nsIDOMXPathNSResolver* aResolver,
                               ErrorResult& rv)
 {
   return XPathEvaluator()->CreateExpression(aExpression, aResolver, rv);
 }
 
 already_AddRefed<nsIDOMXPathNSResolver>
@@ -12062,24 +12061,16 @@ nsIDocument::Evaluate(JSContext* aCx, co
                       uint16_t aType, JS::Handle<JSObject*> aResult,
                       ErrorResult& rv)
 {
   return XPathEvaluator()->Evaluate(aCx, aExpression, aContextNode, aResolver,
                                     aType, aResult, rv);
 }
 
 NS_IMETHODIMP
-nsDocument::CreateExpression(const nsAString& aExpression,
-                             nsIDOMXPathNSResolver* aResolver,
-                             nsIDOMXPathExpression** aResult)
-{
-  return XPathEvaluator()->CreateExpression(aExpression, aResolver, aResult);
-}
-
-NS_IMETHODIMP
 nsDocument::CreateNSResolver(nsIDOMNode* aNodeResolver,
                              nsIDOMXPathNSResolver** aResult)
 {
   return XPathEvaluator()->CreateNSResolver(aNodeResolver, aResult);
 }
 
 NS_IMETHODIMP
 nsDocument::Evaluate(const nsAString& aExpression, nsIDOMNode* aContextNode,
--- a/content/xul/templates/src/nsXMLBinding.cpp
+++ b/content/xul/templates/src/nsXMLBinding.cpp
@@ -11,19 +11,19 @@
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 nsXMLBindingSet::~nsXMLBindingSet()
 {}
 
 void
-nsXMLBindingSet::AddBinding(nsIAtom* aVar, nsIDOMXPathExpression* aExpr)
+nsXMLBindingSet::AddBinding(nsIAtom* aVar, nsAutoPtr<XPathExpression>&& aExpr)
 {
-  nsAutoPtr<nsXMLBinding> newbinding(new nsXMLBinding(aVar, aExpr));
+  nsAutoPtr<nsXMLBinding> newbinding(new nsXMLBinding(aVar, Move(aExpr)));
 
   if (mFirst) {
     nsXMLBinding* binding = mFirst;
 
     while (binding) {
       // if the target variable is already used in a binding, ignore it
       // since it won't be useful for anything
       if (binding->mVar == aVar)
@@ -69,28 +69,26 @@ nsXMLBindingValues::GetAssignmentFor(nsX
                                      int32_t aIndex,
                                      uint16_t aType)
 {
   XPathResult* value = mValues.SafeElementAt(aIndex);
   if (value) {
     return value;
   }
 
-  nsCOMPtr<nsIDOMNode> contextNode = do_QueryInterface(aResult->Node());
+  nsINode* contextNode = aResult->Node();
   if (!contextNode) {
     return nullptr;
   }
 
   mValues.EnsureLengthAtLeast(aIndex + 1);
 
-  nsCOMPtr<nsISupports> resultsupports;
-  aBinding->mExpr->Evaluate(contextNode, aType,
-                            nullptr, getter_AddRefs(resultsupports));
-
-  mValues.ReplaceElementAt(aIndex, XPathResult::FromSupports(resultsupports));
+  ErrorResult ignored;
+  mValues[aIndex] = aBinding->mExpr->Evaluate(*contextNode, aType, nullptr,
+                                              ignored);
 
   return mValues[aIndex];
 }
 
 nsINode*
 nsXMLBindingValues::GetNodeAssignmentFor(nsXULTemplateResultXML* aResult,
                                          nsXMLBinding* aBinding,
                                          int32_t aIndex)
--- a/content/xul/templates/src/nsXMLBinding.h
+++ b/content/xul/templates/src/nsXMLBinding.h
@@ -4,16 +4,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsXMLBinding_h__
 #define nsXMLBinding_h__
 
 #include "nsAutoPtr.h"
 #include "nsIAtom.h"
 #include "mozilla/Attributes.h"
+#include "mozilla/dom/XPathExpression.h"
 
 class nsINode;
 class nsXULTemplateResultXML;
 class nsXMLBindingValues;
 namespace mozilla {
 namespace dom {
 class XPathResult;
 }
@@ -23,21 +24,21 @@ class XPathResult;
  * Classes related to storing bindings for XML handling.
  */
 
 /**
  * a <binding> description
  */
 struct nsXMLBinding {
   nsCOMPtr<nsIAtom> mVar;
-  nsCOMPtr<nsIDOMXPathExpression> mExpr;
+  nsAutoPtr<mozilla::dom::XPathExpression> mExpr;
 
   nsAutoPtr<nsXMLBinding> mNext;
 
-  nsXMLBinding(nsIAtom* aVar, nsIDOMXPathExpression* aExpr)
+  nsXMLBinding(nsIAtom* aVar, nsAutoPtr<mozilla::dom::XPathExpression>&& aExpr)
     : mVar(aVar), mExpr(aExpr), mNext(nullptr)
   {
     MOZ_COUNT_CTOR(nsXMLBinding);
   }
 
   ~nsXMLBinding()
   {
     MOZ_COUNT_DTOR(nsXMLBinding);
@@ -57,17 +58,17 @@ public:
   nsAutoPtr<nsXMLBinding> mFirst;
 
   NS_INLINE_DECL_REFCOUNTING(nsXMLBindingSet);
 
   /**
    * Add a binding to the set
    */
   void
-  AddBinding(nsIAtom* aVar, nsIDOMXPathExpression* aExpr);
+  AddBinding(nsIAtom* aVar, nsAutoPtr<mozilla::dom::XPathExpression>&& aExpr);
 
   /**
    * The nsXMLBindingValues class stores an array of values, one for each
    * target symbol that could be set by the bindings in the set.
    * LookupTargetIndex determines the index into the array for a given
    * target symbol.
    */
   int32_t
--- a/content/xul/templates/src/nsXULTemplateQueryProcessorXML.cpp
+++ b/content/xul/templates/src/nsXULTemplateQueryProcessorXML.cpp
@@ -202,19 +202,19 @@ NS_IMETHODIMP
 nsXULTemplateQueryProcessorXML::InitializeForBuilding(nsISupports* aDatasource,
                                                       nsIXULTemplateBuilder* aBuilder,
                                                       nsIDOMNode* aRootNode)
 {
     if (mGenerationStarted)
         return NS_ERROR_UNEXPECTED;
 
     // the datasource is either a document or a DOM element
-    nsCOMPtr<nsIDOMDocument> doc = do_QueryInterface(aDatasource);
+    nsCOMPtr<nsIDocument> doc = do_QueryInterface(aDatasource);
     if (doc)
-        doc->GetDocumentElement(getter_AddRefs(mRoot));
+        mRoot = doc->GetDocumentElement();
     else
       mRoot = do_QueryInterface(aDatasource);
     NS_ENSURE_STATE(mRoot);
 
     mEvaluator = new XPathEvaluator();
 
     return NS_OK;
 }
@@ -231,64 +231,62 @@ nsXULTemplateQueryProcessorXML::Done()
 
 NS_IMETHODIMP
 nsXULTemplateQueryProcessorXML::CompileQuery(nsIXULTemplateBuilder* aBuilder,
                                              nsIDOMNode* aQueryNode,
                                              nsIAtom* aRefVariable,
                                              nsIAtom* aMemberVariable,
                                              nsISupports** _retval)
 {
-    nsresult rv = NS_OK;
-
     *_retval = nullptr;
 
     nsCOMPtr<nsIContent> content = do_QueryInterface(aQueryNode);
 
     nsAutoString expr;
     content->GetAttr(kNameSpaceID_None, nsGkAtoms::expr, expr);
 
     // if an expression is not specified, then the default is to
     // just take all of the children
     if (expr.IsEmpty())
         expr.Assign('*');
 
-    nsCOMPtr<nsIDOMXPathExpression> compiledexpr;
-    rv = CreateExpression(expr, content, getter_AddRefs(compiledexpr));
-    if (NS_FAILED(rv)) {
+    ErrorResult rv;
+    nsAutoPtr<XPathExpression> compiledexpr;
+    compiledexpr = CreateExpression(expr, content, rv);
+    if (rv.Failed()) {
         nsXULContentUtils::LogTemplateError(ERROR_TEMPLATE_BAD_XPATH);
-        return rv;
+        return rv.ErrorCode();
     }
 
     nsRefPtr<nsXMLQuery> query =
-        new nsXMLQuery(this, aMemberVariable, compiledexpr);
+        new nsXMLQuery(this, aMemberVariable, Move(compiledexpr));
 
     for (nsIContent* condition = content->GetFirstChild();
          condition;
          condition = condition->GetNextSibling()) {
 
         if (condition->NodeInfo()->Equals(nsGkAtoms::assign,
                                           kNameSpaceID_XUL)) {
             nsAutoString var;
             condition->GetAttr(kNameSpaceID_None, nsGkAtoms::var, var);
 
             nsAutoString expr;
             condition->GetAttr(kNameSpaceID_None, nsGkAtoms::expr, expr);
 
             // ignore assignments without a variable or an expression
             if (!var.IsEmpty() && !expr.IsEmpty()) {
-                rv = CreateExpression(expr, condition,
-                                      getter_AddRefs(compiledexpr));
-                if (NS_FAILED(rv)) {
+                compiledexpr = CreateExpression(expr, condition, rv);
+                if (rv.Failed()) {
                     nsXULContentUtils::LogTemplateError(ERROR_TEMPLATE_BAD_ASSIGN_XPATH);
-                    return rv;
+                    return rv.ErrorCode();
                 }
 
                 nsCOMPtr<nsIAtom> varatom = do_GetAtom(var);
 
-                query->AddBinding(varatom, compiledexpr);
+                query->AddBinding(varatom, Move(compiledexpr));
             }
         }
     }
 
     *_retval = query;
     NS_ADDREF(*_retval);
 
     return NS_OK;
@@ -305,37 +303,38 @@ nsXULTemplateQueryProcessorXML::Generate
 
     mGenerationStarted = true;
 
     nsCOMPtr<nsXMLQuery> xmlquery = do_QueryInterface(aQuery);
     if (!xmlquery)
         return NS_ERROR_INVALID_ARG;
 
     nsCOMPtr<nsISupports> supports;
-    nsCOMPtr<nsIDOMNode> context;
+    nsCOMPtr<nsINode> context;
     if (aRef)
       aRef->GetBindingObjectFor(xmlquery->GetMemberVariable(),
                                 getter_AddRefs(supports));
     context = do_QueryInterface(supports);
     if (!context)
         context = mRoot;
 
-    nsIDOMXPathExpression* expr = xmlquery->GetResultsExpression();
+    XPathExpression* expr = xmlquery->GetResultsExpression();
     if (!expr)
         return NS_ERROR_FAILURE;
 
-    nsCOMPtr<nsISupports> exprsupportsresults;
-    nsresult rv = expr->Evaluate(context,
-                                 XPathResult::ORDERED_NODE_SNAPSHOT_TYPE,
-                                 nullptr, getter_AddRefs(exprsupportsresults));
-    NS_ENSURE_SUCCESS(rv, rv);
+    ErrorResult rv;
+    nsRefPtr<XPathResult> exprresults =
+        expr->Evaluate(*context, XPathResult::ORDERED_NODE_SNAPSHOT_TYPE,
+                       nullptr, rv);
+    if (rv.Failed()) {
+        return rv.ErrorCode();
+    }
 
-    XPathResult* exprresults = XPathResult::FromSupports(exprsupportsresults);
     nsXULTemplateResultSetXML* results =
-        new nsXULTemplateResultSetXML(xmlquery, exprresults,
+        new nsXULTemplateResultSetXML(xmlquery, exprresults.forget(),
                                       xmlquery->GetBindingSet());
 
     *aResults = results;
     NS_ADDREF(*aResults);
 
     return NS_OK;
 }
 
@@ -350,26 +349,27 @@ nsXULTemplateQueryProcessorXML::AddBindi
 
     nsRefPtr<nsXMLBindingSet> bindings = mRuleToBindingsMap.GetWeak(aRuleNode);
     if (!bindings) {
         bindings = new nsXMLBindingSet();
         mRuleToBindingsMap.Put(aRuleNode, bindings);
     }
 
     nsCOMPtr<nsINode> ruleNode = do_QueryInterface(aRuleNode);
-    nsCOMPtr<nsIDOMXPathExpression> compiledexpr;
-    nsresult rv =
-        CreateExpression(aExpr, ruleNode, getter_AddRefs(compiledexpr));
-    if (NS_FAILED(rv)) {
+
+    ErrorResult rv;
+    nsAutoPtr<XPathExpression> compiledexpr;
+    compiledexpr = CreateExpression(aExpr, ruleNode, rv);
+    if (rv.Failed()) {
         nsXULContentUtils::LogTemplateError(ERROR_TEMPLATE_BAD_BINDING_XPATH);
         return NS_OK;
     }
 
     // aRef isn't currently used for XML query processors
-    bindings->AddBinding(aVar, compiledexpr);
+    bindings->AddBinding(aVar, Move(compiledexpr));
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXULTemplateQueryProcessorXML::TranslateRef(nsISupports* aDatasource,
                                              const nsAString& aRefString,
                                              nsIXULTemplateResult** aRef)
 {
@@ -382,20 +382,17 @@ nsXULTemplateQueryProcessorXML::Translat
         rootElement = doc->GetRootElement();
     else
         rootElement = do_QueryInterface(aDatasource);
 
     // if no root element, just return. The document may not have loaded yet
     if (!rootElement)
         return NS_OK;
     
-    nsXULTemplateResultXML* result =
-        new nsXULTemplateResultXML(nullptr, rootElement, nullptr);
-
-    *aRef = result;
+    *aRef = new nsXULTemplateResultXML(nullptr, rootElement, nullptr);
     NS_ADDREF(*aRef);
 
     return NS_OK;
 }
 
 
 NS_IMETHODIMP
 nsXULTemplateQueryProcessorXML::CompareResults(nsIXULTemplateResult* aLeft,
@@ -421,29 +418,28 @@ nsXULTemplateQueryProcessorXML::CompareR
 }
 
 nsXMLBindingSet*
 nsXULTemplateQueryProcessorXML::GetOptionalBindingsForRule(nsIDOMNode* aRuleNode)
 {
     return mRuleToBindingsMap.GetWeak(aRuleNode);
 }
 
-nsresult
+XPathExpression*
 nsXULTemplateQueryProcessorXML::CreateExpression(const nsAString& aExpr,
                                                  nsINode* aNode,
-                                                 nsIDOMXPathExpression** aCompiledExpr)
+                                                 ErrorResult& aRv)
 {
-    ErrorResult rv;
     nsCOMPtr<nsIDOMXPathNSResolver> nsResolver =
-        aNode->OwnerDoc()->CreateNSResolver(aNode, rv);
-    if (rv.Failed()) {
-        return rv.ErrorCode();
+        aNode->OwnerDoc()->CreateNSResolver(aNode, aRv);
+    if (aRv.Failed()) {
+        return nullptr;
     }
 
-    return mEvaluator->CreateExpression(aExpr, nsResolver, aCompiledExpr);
+    return mEvaluator->CreateExpression(aExpr, nsResolver, aRv);
 }
 
 NS_IMETHODIMP
 nsXULTemplateQueryProcessorXML::HandleEvent(nsIDOMEvent* aEvent)
 {
     NS_PRECONDITION(aEvent, "aEvent null");
     nsAutoString eventType;
     aEvent->GetType(eventType);
--- a/content/xul/templates/src/nsXULTemplateQueryProcessorXML.h
+++ b/content/xul/templates/src/nsXULTemplateQueryProcessorXML.h
@@ -8,24 +8,24 @@
 
 #include "nsIXULTemplateBuilder.h"
 #include "nsIXULTemplateQueryProcessor.h"
 
 #include "nsISimpleEnumerator.h"
 #include "nsString.h"
 #include "nsCOMArray.h"
 #include "nsRefPtrHashtable.h"
-#include "nsIDOMElement.h"
 #include "nsIDOMEventListener.h"
-#include "nsIDOMXPathExpression.h"
 #include "nsIDOMXPathEvaluator.h"
 #include "nsXMLBinding.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsIXMLHttpRequest.h"
 #include "mozilla/Attributes.h"
+#include "mozilla/dom/Element.h"
+#include "mozilla/dom/XPathEvaluator.h"
 #include "mozilla/dom/XPathResult.h"
 
 class nsXULTemplateQueryProcessorXML;
 
 #define NS_IXMLQUERY_IID \
   {0x0358d692, 0xccce, 0x4a97, \
     { 0xb2, 0x51, 0xba, 0x8f, 0x17, 0x0f, 0x3b, 0x6f }}
  
@@ -38,48 +38,49 @@ class nsXMLQuery MOZ_FINAL : public nsIS
 
     // return a weak reference to the processor the query was created from
     nsXULTemplateQueryProcessorXML* Processor() { return mProcessor; }
 
     // return a weak reference t the member variable for the query
     nsIAtom* GetMemberVariable() { return mMemberVariable; }
 
     // return a weak reference to the expression used to generate results
-    nsIDOMXPathExpression* GetResultsExpression() { return mResultsExpr; }
+    mozilla::dom::XPathExpression* GetResultsExpression()
+      { return mResultsExpr; }
 
     // return a weak reference to the additional required bindings
     nsXMLBindingSet* GetBindingSet() { return mRequiredBindings; }
 
     // add a required binding for the query
     void
-    AddBinding(nsIAtom* aVar, nsIDOMXPathExpression* aExpr)
+    AddBinding(nsIAtom* aVar, nsAutoPtr<mozilla::dom::XPathExpression>&& aExpr)
     {
         if (!mRequiredBindings) {
             mRequiredBindings = new nsXMLBindingSet();
         }
 
-        mRequiredBindings->AddBinding(aVar, aExpr);
+        mRequiredBindings->AddBinding(aVar, mozilla::Move(aExpr));
     }
 
     nsXMLQuery(nsXULTemplateQueryProcessorXML* aProcessor,
-                        nsIAtom* aMemberVariable,
-                        nsIDOMXPathExpression* aResultsExpr)
+               nsIAtom* aMemberVariable,
+               nsAutoPtr<mozilla::dom::XPathExpression>&& aResultsExpr)
         : mProcessor(aProcessor),
           mMemberVariable(aMemberVariable),
           mResultsExpr(aResultsExpr)
     { }
 
   protected:
     ~nsXMLQuery() {}
 
     nsXULTemplateQueryProcessorXML* mProcessor;
 
     nsCOMPtr<nsIAtom> mMemberVariable;
 
-    nsCOMPtr<nsIDOMXPathExpression> mResultsExpr;
+    nsAutoPtr<mozilla::dom::XPathExpression> mResultsExpr;
 
     nsRefPtr<nsXMLBindingSet> mRequiredBindings;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsXMLQuery, NS_IXMLQUERY_IID)
 
 class nsXULTemplateResultSetXML MOZ_FINAL : public nsISimpleEnumerator
 {
@@ -103,17 +104,17 @@ public:
 
     // nsISupports interface
     NS_DECL_ISUPPORTS
 
     // nsISimpleEnumerator interface
     NS_DECL_NSISIMPLEENUMERATOR
 
     nsXULTemplateResultSetXML(nsXMLQuery* aQuery,
-                              mozilla::dom::XPathResult* aResults,
+                              already_AddRefed<mozilla::dom::XPathResult> aResults,
                               nsXMLBindingSet* aBindingSet)
         : mQuery(aQuery),
           mBindingSet(aBindingSet),
           mResults(aResults),
           mPosition(0)
     {}
 };
 
@@ -137,32 +138,32 @@ public:
     // nsIDOMEventListener interface
     NS_DECL_NSIDOMEVENTLISTENER
 
     nsXMLBindingSet*
     GetOptionalBindingsForRule(nsIDOMNode* aRuleNode);
 
     // create an XPath expression from aExpr, using aNode for
     // resolving namespaces
-    nsresult
+    mozilla::dom::XPathExpression*
     CreateExpression(const nsAString& aExpr,
                      nsINode* aNode,
-                     nsIDOMXPathExpression** aCompiledExpr);
+                     mozilla::ErrorResult& aRv);
 
 private:
 
     ~nsXULTemplateQueryProcessorXML() {}
 
     bool mGenerationStarted;
 
     nsRefPtrHashtable<nsISupportsHashKey, nsXMLBindingSet> mRuleToBindingsMap;
 
-    nsCOMPtr<nsIDOMElement> mRoot;
+    nsCOMPtr<mozilla::dom::Element> mRoot;
 
-    nsCOMPtr<nsIDOMXPathEvaluator> mEvaluator;
+    nsRefPtr<mozilla::dom::XPathEvaluator> mEvaluator;
 
     nsCOMPtr<nsIXULTemplateBuilder> mTemplateBuilder;
 
     nsCOMPtr<nsIXMLHttpRequest> mRequest;
 };
 
 
 #endif // nsXULTemplateQueryProcessorXML_h__
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -106,18 +106,16 @@
 #include "nsIBoxObject.h"
 #ifdef MOZ_XUL
 #include "nsITreeSelection.h"
 #include "nsITreeContentView.h"
 #include "nsITreeView.h"
 #include "nsIXULTemplateBuilder.h"
 #include "nsITreeColumns.h"
 #endif
-#include "nsIDOMXPathExpression.h"
-#include "nsIDOMNSXPathExpression.h"
 #include "nsIDOMXPathNSResolver.h"
 
 // Storage includes
 #include "nsIDOMStorage.h"
 #include "nsPIDOMStorage.h"
 
 // Drag and drop
 #include "nsIDOMFile.h"
@@ -339,18 +337,16 @@ static nsDOMClassInfoData sClassInfoData
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(CSSSupportsRule, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(XSLTProcessor, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
-  NS_DEFINE_CLASSINFO_DATA(XPathExpression, nsDOMGenericSH,
-                           DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(XPathNSResolver, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   // WhatWG Storage
 
   // mrbkap says we don't need WANT_ADDPROPERTY on Storage objects
   // since a call to addProperty() is always followed by a call to
   // setProperty(), except in the case when a getter or setter is set
@@ -937,21 +933,16 @@ nsDOMClassInfo::Init()
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSSupportsRule)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(XSLTProcessor, nsIXSLTProcessor)
     DOM_CLASSINFO_MAP_ENTRY(nsIXSLTProcessor)
     DOM_CLASSINFO_MAP_ENTRY(nsIXSLTProcessorPrivate)
   DOM_CLASSINFO_MAP_END
 
-  DOM_CLASSINFO_MAP_BEGIN(XPathExpression, nsIDOMXPathExpression)
-    DOM_CLASSINFO_MAP_ENTRY(nsIDOMXPathExpression)
-    DOM_CLASSINFO_MAP_ENTRY(nsIDOMNSXPathExpression)
-  DOM_CLASSINFO_MAP_END
-
   DOM_CLASSINFO_MAP_BEGIN(XPathNSResolver, nsIDOMXPathNSResolver)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMXPathNSResolver)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(Storage, nsIDOMStorage)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMStorage)
   DOM_CLASSINFO_MAP_END
 
--- a/dom/base/nsDOMClassInfoClasses.h
+++ b/dom/base/nsDOMClassInfoClasses.h
@@ -41,17 +41,16 @@ DOMCI_CLASS(TreeColumn)
 
 DOMCI_CLASS(CSSMozDocumentRule)
 DOMCI_CLASS(CSSSupportsRule)
 
 // XSLTProcessor
 DOMCI_CLASS(XSLTProcessor)
 
 // DOM Level 3 XPath objects
-DOMCI_CLASS(XPathExpression)
 DOMCI_CLASS(XPathNSResolver)
 
 // WhatWG WebApps Objects
 DOMCI_CLASS(Storage)
 
 DOMCI_CLASS(Blob)
 DOMCI_CLASS(File)
 
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -1667,16 +1667,21 @@ DOMInterfaces = {
 'XPathEvaluator': {
     'wrapperCache': False
 },
 
 'XPathResult': {
     'resultNotAddRefed': ['singleNodeValue', 'iterateNext', 'snapshotItem']
 },
 
+'XPathExpression': {
+    'wrapperCache': False,
+    'nativeOwnership': 'owned',
+},
+
 'XULDocument': {
     'headerFile': 'XULDocument.h'
 },
 
 'XULElement': {
     'nativeType': 'nsXULElement',
     'resultNotAddRefed': [ 'controllers', 'style' ]
 },
@@ -2006,11 +2011,10 @@ addExternalIface('OutputStream', nativeT
                  notflattened=True)
 addExternalIface('Principal', nativeType='nsIPrincipal',
                  headerFile='nsIPrincipal.h', notflattened=True)
 addExternalIface('StackFrame', nativeType='nsIStackFrame',
                  headerFile='nsIException.h', notflattened=True)
 addExternalIface('URI', nativeType='nsIURI', headerFile='nsIURI.h',
                  notflattened=True)
 addExternalIface('UserDataHandler')
-addExternalIface('XPathExpression')
 addExternalIface('XPathNSResolver')
 addExternalIface('XULCommandDispatcher')
--- a/dom/interfaces/xpath/moz.build
+++ b/dom/interfaces/xpath/moz.build
@@ -1,16 +1,14 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
 XPIDL_SOURCES += [
-    'nsIDOMNSXPathExpression.idl',
     'nsIDOMXPathEvaluator.idl',
-    'nsIDOMXPathExpression.idl',
     'nsIDOMXPathNSResolver.idl',
     'nsIDOMXPathResult.idl',
 ]
 
 XPIDL_MODULE = 'dom_xpath'
 
deleted file mode 100644
--- a/dom/interfaces/xpath/nsIDOMNSXPathExpression.idl
+++ /dev/null
@@ -1,34 +0,0 @@
-/* -*- Mode: IDL; tab-width: 2; 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 "domstubs.idl"
-
-interface XPathException;
-
-/**
- * Interface for Mozilla specific XPathExpression functions.
- */
-[scriptable, uuid(ce600ca8-e98a-4419-ad61-2f6d0cb0ecc8)]
-interface nsIDOMNSXPathExpression : nsISupports
-{
-  /**
-   * Evaluate the expression with the given context. Similar to
-   * nsIDOMXPathExpression::evaluate(), except that this takes the context
-   * position and size too.
-   *
-   * @param contextNode       The context node
-   * @param contextPosition   The context position
-   * @param contextSize       The context size
-   * @param type              The needed result type
-   * @param result            The result
-   */
-  nsISupports evaluateWithContext(in nsIDOMNode contextNode,
-                                  in unsigned long contextPosition,
-                                  in unsigned long contextSize,
-                                  in unsigned short type,
-                                  in nsISupports result)
-                                    raises(XPathException,
-                                           DOMException);
-};
--- a/dom/interfaces/xpath/nsIDOMXPathEvaluator.idl
+++ b/dom/interfaces/xpath/nsIDOMXPathEvaluator.idl
@@ -5,26 +5,21 @@
 
 /**
  * Corresponds to http://www.w3.org/TR/2002/WD-DOM-Level-3-XPath-20020208
  */
 
 #include "domstubs.idl"
 
 interface nsIDOMXPathNSResolver;
-interface nsIDOMXPathExpression;
 interface XPathException;
 
-[uuid(75506f8a-b504-11d5-a7f2-ca108ab8b6fc)]
+[uuid(89a0fe71-c1d9-46bd-b76b-47f51fd935ff)]
 interface nsIDOMXPathEvaluator : nsISupports
 {
-  nsIDOMXPathExpression    createExpression(in DOMString expression, 
-                                            in nsIDOMXPathNSResolver resolver)
-                                      raises(XPathException,
-                                             DOMException);
   nsIDOMXPathNSResolver    createNSResolver(in nsIDOMNode nodeResolver);
   nsISupports              evaluate(in DOMString expression, 
                                     in nsIDOMNode contextNode, 
                                     in nsIDOMXPathNSResolver resolver, 
                                     in unsigned short type, 
                                     in nsISupports result)
                                       raises(XPathException,
                                              DOMException);
deleted file mode 100644
--- a/dom/interfaces/xpath/nsIDOMXPathExpression.idl
+++ /dev/null
@@ -1,22 +0,0 @@
-/* -*- Mode: IDL; tab-width: 2; 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/. */
-
-/**
- * Corresponds to http://www.w3.org/TR/2002/WD-DOM-Level-3-XPath-20020208
- */
-
-#include "domstubs.idl"
-
-interface XPathException;
-
-[scriptable, uuid(75506f82-b504-11d5-a7f2-ca108ab8b6fc)]
-interface nsIDOMXPathExpression : nsISupports
-{
-  nsISupports              evaluate(in nsIDOMNode contextNode, 
-                                    in unsigned short type, 
-                                    in nsISupports result)
-                                      raises(XPathException,
-                                             DOMException);
-};
--- a/dom/webidl/XPathEvaluator.webidl
+++ b/dom/webidl/XPathEvaluator.webidl
@@ -1,15 +1,14 @@
 /* -*- Mode: IDL; tab-width: 2; 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/.
  */
 
-interface XPathExpression;
 interface XPathNSResolver;
 
 [Constructor]
 interface XPathEvaluator {
   // Based on nsIDOMXPathEvaluator
   [NewObject, Throws]
   XPathExpression createExpression(DOMString expression,
                                    XPathNSResolver? resolver);
new file mode 100644
--- /dev/null
+++ b/dom/webidl/XPathExpression.webidl
@@ -0,0 +1,22 @@
+/* -*- Mode: IDL; tab-width: 2; 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/.
+ */
+
+interface XPathExpression {
+  // The result specifies a specific result object which may be reused and
+  // returned by this method. If this is specified as null or it's not an
+  // XPathResult object, a new result object will be constructed and returned.
+  [Throws]
+  XPathResult evaluate(Node contextNode, unsigned short type, object? result);
+
+  // The result specifies a specific result object which may be reused and
+  // returned by this method. If this is specified as null or it's not an
+  // XPathResult object, a new result object will be constructed and returned.
+  [Throws, ChromeOnly]
+  XPathResult evaluateWithContext(Node contextNode,
+                                  unsigned long contextPosition,
+                                  unsigned long contextSize,
+                                  unsigned short type, object? result);
+};
--- a/dom/webidl/moz.build
+++ b/dom/webidl/moz.build
@@ -476,16 +476,17 @@ WEBIDL_FILES = [
     'WorkerNavigator.webidl',
     'XMLDocument.webidl',
     'XMLHttpRequest.webidl',
     'XMLHttpRequestEventTarget.webidl',
     'XMLHttpRequestUpload.webidl',
     'XMLSerializer.webidl',
     'XMLStylesheetProcessingInstruction.webidl',
     'XPathEvaluator.webidl',
+    'XPathExpression.webidl',
     'XPathResult.webidl',
     'XULCommandEvent.webidl',
     'XULDocument.webidl',
     'XULElement.webidl',
 ]
 
 if CONFIG['MOZ_AUDIO_CHANNEL_MANAGER']:
     WEBIDL_FILES += [
--- a/dom/xslt/xpath/XPathEvaluator.cpp
+++ b/dom/xslt/xpath/XPathEvaluator.cpp
@@ -90,58 +90,66 @@ XPathEvaluator::CreateNSResolver(nsIDOMN
 NS_IMETHODIMP
 XPathEvaluator::Evaluate(const nsAString & aExpression,
                          nsIDOMNode *aContextNode,
                          nsIDOMXPathNSResolver *aResolver,
                          uint16_t aType,
                          nsISupports *aInResult,
                          nsISupports **aResult)
 {
-    nsCOMPtr<nsIDOMXPathExpression> expression;
-    nsresult rv = CreateExpression(aExpression, aResolver,
-                                   getter_AddRefs(expression));
-    NS_ENSURE_SUCCESS(rv, rv);
+    ErrorResult rv;
+    nsAutoPtr<XPathExpression> expression(CreateExpression(aExpression,
+                                                           aResolver, rv));
+    if (rv.Failed()) {
+        return rv.ErrorCode();
+    }
+
+    nsCOMPtr<nsINode> node = do_QueryInterface(aContextNode);
+    if (!node) {
+        return NS_ERROR_FAILURE;
+    }
 
-    return expression->Evaluate(aContextNode, aType, aInResult, aResult);
+    nsCOMPtr<nsIXPathResult> inResult = do_QueryInterface(aInResult);
+    nsRefPtr<XPathResult> result =
+        expression->Evaluate(*node, aType,
+                             static_cast<XPathResult*>(inResult.get()), rv);
+    if (rv.Failed()) {
+        return rv.ErrorCode();
+    }
+
+    *aResult = ToSupports(result.forget().take());
+
+    return NS_OK;
 }
 
 
-NS_IMETHODIMP
+XPathExpression*
 XPathEvaluator::CreateExpression(const nsAString & aExpression,
                                  nsIDOMXPathNSResolver *aResolver,
-                                 nsIDOMXPathExpression **aResult)
+                                 ErrorResult& aRv)
 {
-    nsresult rv;
     if (!mRecycler) {
         mRecycler = new txResultRecycler;
     }
 
     nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocument);
     XPathEvaluatorParseContext pContext(aResolver, !(doc && doc->IsHTML()));
 
     nsAutoPtr<Expr> expression;
-    rv = txExprParser::createExpr(PromiseFlatString(aExpression), &pContext,
-                                  getter_Transfers(expression));
-    if (NS_FAILED(rv)) {
-        if (rv == NS_ERROR_DOM_NAMESPACE_ERR) {
-            return NS_ERROR_DOM_NAMESPACE_ERR;
+    aRv = txExprParser::createExpr(PromiseFlatString(aExpression), &pContext,
+                                   getter_Transfers(expression));
+    if (aRv.Failed()) {
+        if (aRv.ErrorCode() != NS_ERROR_DOM_NAMESPACE_ERR) {
+            aRv.Throw(NS_ERROR_DOM_INVALID_EXPRESSION_ERR);
         }
 
-        return NS_ERROR_DOM_INVALID_EXPRESSION_ERR;
+        return nullptr;
     }
 
-    nsCOMPtr<nsIDOMDocument> document = do_QueryReferent(mDocument);
-
-    *aResult = new XPathExpression(Move(expression), mRecycler, document);
-    if (!*aResult) {
-        return NS_ERROR_OUT_OF_MEMORY;
-    }
-
-    NS_ADDREF(*aResult);
-    return NS_OK;
+    return new XPathExpression(Move(expression), mRecycler, doc);
 }
 
 JSObject*
 XPathEvaluator::WrapObject(JSContext* aCx)
 {
     return dom::XPathEvaluatorBinding::Wrap(aCx, this);
 }
 
@@ -149,26 +157,16 @@ XPathEvaluator::WrapObject(JSContext* aC
 already_AddRefed<XPathEvaluator>
 XPathEvaluator::Constructor(const GlobalObject& aGlobal,
                             ErrorResult& rv)
 {
     nsRefPtr<XPathEvaluator> newObj = new XPathEvaluator(nullptr);
     return newObj.forget();
 }
 
-already_AddRefed<nsIDOMXPathExpression>
-XPathEvaluator::CreateExpression(const nsAString& aExpression,
-                                 nsIDOMXPathNSResolver* aResolver,
-                                 ErrorResult& rv)
-{
-  nsCOMPtr<nsIDOMXPathExpression> expr;
-  rv = CreateExpression(aExpression, aResolver, getter_AddRefs(expr));
-  return expr.forget();
-}
-
 already_AddRefed<nsIDOMXPathNSResolver>
 XPathEvaluator::CreateNSResolver(nsINode* aNodeResolver,
                                  ErrorResult& rv)
 {
   nsCOMPtr<nsIDOMNode> nodeResolver = do_QueryInterface(aNodeResolver);
   nsCOMPtr<nsIDOMXPathNSResolver> res;
   rv = CreateNSResolver(nodeResolver, getter_AddRefs(res));
   return res.forget();
--- a/dom/xslt/xpath/XPathEvaluator.h
+++ b/dom/xslt/xpath/XPathEvaluator.h
@@ -16,16 +16,17 @@
 
 class nsINode;
 class txResultRecycler;
 
 namespace mozilla {
 namespace dom {
 
 class GlobalObject;
+class XPathExpression;
 class XPathResult;
 
 /**
  * A class for evaluating an XPath expression string
  */
 class XPathEvaluator MOZ_FINAL : public nsIDOMXPathEvaluator
 {
     ~XPathEvaluator();
@@ -42,17 +43,17 @@ public:
     JSObject* WrapObject(JSContext* aCx);
     nsIDocument* GetParentObject()
     {
         nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocument);
         return doc;
     }
     static already_AddRefed<XPathEvaluator>
         Constructor(const GlobalObject& aGlobal, ErrorResult& rv);
-    already_AddRefed<nsIDOMXPathExpression>
+    XPathExpression*
         CreateExpression(const nsAString& aExpression,
                          nsIDOMXPathNSResolver* aResolver,
                          ErrorResult& rv);
     already_AddRefed<nsIDOMXPathNSResolver>
         CreateNSResolver(nsINode* aNodeResolver, ErrorResult& rv);
     already_AddRefed<XPathResult>
         Evaluate(JSContext* aCx, const nsAString& aExpression,
                  nsINode* aContextNode, nsIDOMXPathNSResolver* aResolver,
--- a/dom/xslt/xpath/XPathExpression.cpp
+++ b/dom/xslt/xpath/XPathExpression.cpp
@@ -10,21 +10,21 @@
 #include "txIXPathContext.h"
 #include "nsError.h"
 #include "nsIDOMCharacterData.h"
 #include "nsDOMClassInfoID.h"
 #include "nsIDOMDocument.h"
 #include "XPathResult.h"
 #include "txURIUtils.h"
 #include "txXPathTreeWalker.h"
+#include "mozilla/dom/BindingUtils.h"
+#include "mozilla/dom/XPathResultBinding.h"
 
 using mozilla::Move;
 
-DOMCI_DATA(XPathExpression, mozilla::dom::XPathExpression)
- 
 namespace mozilla {
 namespace dom {
 
 class EvalContextImpl : public txIEvalContext
 {
 public:
     EvalContextImpl(const txXPathNode& aContextNode,
                     uint32_t aContextPosition, uint32_t aContextSize,
@@ -47,112 +47,116 @@ public:
 private:
     const txXPathNode& mContextNode;
     uint32_t mContextPosition;
     uint32_t mContextSize;
     nsresult mLastError;
     nsRefPtr<txResultRecycler> mRecycler;
 };
 
-NS_IMPL_ADDREF(XPathExpression)
-NS_IMPL_RELEASE(XPathExpression)
-
-NS_INTERFACE_MAP_BEGIN(XPathExpression)
-  NS_INTERFACE_MAP_ENTRY(nsIDOMXPathExpression)
-  NS_INTERFACE_MAP_ENTRY(nsIDOMNSXPathExpression)
-  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMXPathExpression)
-  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(XPathExpression)
-NS_INTERFACE_MAP_END
-
 XPathExpression::XPathExpression(nsAutoPtr<Expr>&& aExpression,
                                  txResultRecycler* aRecycler,
-                                 nsIDOMDocument *aDocument)
+                                 nsIDocument *aDocument)
     : mExpression(Move(aExpression)),
       mRecycler(aRecycler),
       mDocument(do_GetWeakReference(aDocument)),
       mCheckDocument(aDocument != nullptr)
 {
 }
 
-NS_IMETHODIMP
-XPathExpression::Evaluate(nsIDOMNode *aContextNode,
-                          uint16_t aType,
-                          nsISupports *aInResult,
-                          nsISupports **aResult)
+XPathExpression::~XPathExpression()
 {
-    return EvaluateWithContext(aContextNode, 1, 1, aType, aInResult, aResult);
 }
 
-NS_IMETHODIMP
-XPathExpression::EvaluateWithContext(nsIDOMNode *aContextNode,
+already_AddRefed<XPathResult>
+XPathExpression::EvaluateWithContext(JSContext* aCx,
+                                     nsINode& aContextNode,
+                                     uint32_t aContextPosition,
+                                     uint32_t aContextSize,
+                                     uint16_t aType,
+                                     JS::Handle<JSObject*> aInResult,
+                                     ErrorResult& aRv)
+{
+    XPathResult* inResult = nullptr;
+    if (aInResult) {
+        nsresult rv = UNWRAP_OBJECT(XPathResult, aInResult, inResult);
+        if (NS_FAILED(rv) && rv != NS_ERROR_XPC_BAD_CONVERT_JS) {
+            aRv.Throw(rv);
+            return nullptr;
+        }
+    }
+
+    return EvaluateWithContext(aContextNode, aContextPosition, aContextSize,
+                               aType, inResult, aRv);
+}
+
+already_AddRefed<XPathResult>
+XPathExpression::EvaluateWithContext(nsINode& aContextNode,
                                      uint32_t aContextPosition,
                                      uint32_t aContextSize,
                                      uint16_t aType,
-                                     nsISupports *aInResult,
-                                     nsISupports **aResult)
+                                     XPathResult* aInResult,
+                                     ErrorResult& aRv)
 {
-    nsCOMPtr<nsINode> context = do_QueryInterface(aContextNode);
-    NS_ENSURE_ARG(context);
+    if (aContextPosition > aContextSize) {
+        aRv.Throw(NS_ERROR_FAILURE);
+        return nullptr;
+    }
 
-    if (aContextPosition > aContextSize)
-        return NS_ERROR_FAILURE;
-
-    if (!nsContentUtils::CanCallerAccess(aContextNode))
-        return NS_ERROR_DOM_SECURITY_ERR;
+    if (!nsContentUtils::CanCallerAccess(&aContextNode)) {
+        aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
+        return nullptr;
+    }
 
     if (mCheckDocument) {
-        nsCOMPtr<nsIDOMDocument> doc = do_QueryReferent(mDocument);
-        if (!doc || doc != aContextNode) {
-            nsCOMPtr<nsIDOMDocument> contextDocument;
-            aContextNode->GetOwnerDocument(getter_AddRefs(contextDocument));
-
-            if (doc != contextDocument) {
-                return NS_ERROR_DOM_WRONG_DOCUMENT_ERR;
-            }
+        nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocument);
+        if (doc != aContextNode.OwnerDoc()) {
+            aRv.Throw(NS_ERROR_DOM_WRONG_DOCUMENT_ERR);
+            return nullptr;
         }
     }
 
-    uint16_t nodeType = context->NodeType();
+    uint16_t nodeType = aContextNode.NodeType();
 
     if (nodeType == nsIDOMNode::TEXT_NODE ||
         nodeType == nsIDOMNode::CDATA_SECTION_NODE) {
-        nsCOMPtr<nsIDOMCharacterData> textNode = do_QueryInterface(aContextNode);
-        NS_ENSURE_TRUE(textNode, NS_ERROR_FAILURE);
+        nsCOMPtr<nsIDOMCharacterData> textNode =
+            do_QueryInterface(&aContextNode);
+        if (!textNode) {
+            aRv.Throw(NS_ERROR_FAILURE);
+            return nullptr;
+        }
 
-        if (textNode) {
-            uint32_t textLength;
-            textNode->GetLength(&textLength);
-            if (textLength == 0)
-                return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
+        uint32_t textLength;
+        textNode->GetLength(&textLength);
+        if (textLength == 0) {
+            aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
+            return nullptr;
         }
 
         // XXX Need to get logical XPath text node for CDATASection
         //     and Text nodes.
     }
     else if (nodeType != nsIDOMNode::DOCUMENT_NODE &&
              nodeType != nsIDOMNode::ELEMENT_NODE &&
              nodeType != nsIDOMNode::ATTRIBUTE_NODE &&
              nodeType != nsIDOMNode::COMMENT_NODE &&
              nodeType != nsIDOMNode::PROCESSING_INSTRUCTION_NODE) {
-        return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
+        aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
+        return nullptr;
     }
 
-    NS_ENSURE_ARG(aResult);
-    *aResult = nullptr;
-
-    nsAutoPtr<txXPathNode> contextNode(txXPathNativeNode::createXPathNode(aContextNode));
-    if (!contextNode) {
-        return NS_ERROR_OUT_OF_MEMORY;
-    }
-
+    nsAutoPtr<txXPathNode> contextNode(txXPathNativeNode::createXPathNode(&aContextNode));
     EvalContextImpl eContext(*contextNode, aContextPosition, aContextSize,
                              mRecycler);
     nsRefPtr<txAExprResult> exprResult;
-    nsresult rv = mExpression->evaluate(&eContext, getter_AddRefs(exprResult));
-    NS_ENSURE_SUCCESS(rv, rv);
+    aRv = mExpression->evaluate(&eContext, getter_AddRefs(exprResult));
+    if (aRv.Failed()) {
+        return nullptr;
+    }
 
     uint16_t resultType = aType;
     if (aType == XPathResult::ANY_TYPE) {
         short exprResultType = exprResult->getResultType();
         switch (exprResultType) {
             case txAExprResult::NUMBER:
                 resultType = XPathResult::NUMBER_TYPE;
                 break;
@@ -161,31 +165,29 @@ XPathExpression::EvaluateWithContext(nsI
                 break;
             case txAExprResult::BOOLEAN:
                 resultType = XPathResult::BOOLEAN_TYPE;
                 break;
             case txAExprResult::NODESET:
                 resultType = XPathResult::UNORDERED_NODE_ITERATOR_TYPE;
                 break;
             case txAExprResult::RESULT_TREE_FRAGMENT:
-                NS_ERROR("Can't return a tree fragment!");
-                return NS_ERROR_FAILURE;
+                aRv.Throw(NS_ERROR_FAILURE);
+                return nullptr;
         }
     }
 
-    // We need a result object and it must be our implementation.
-    nsCOMPtr<nsIXPathResult> xpathResult = do_QueryInterface(aInResult);
+    nsRefPtr<XPathResult> xpathResult = aInResult;
     if (!xpathResult) {
-        // Either no aInResult or not one of ours.
-        xpathResult = new XPathResult(context);
+        xpathResult = new XPathResult(&aContextNode);
     }
-    rv = xpathResult->SetExprResult(exprResult, resultType, context);
-    NS_ENSURE_SUCCESS(rv, rv);
 
-    return CallQueryInterface(xpathResult, aResult);
+    aRv = xpathResult->SetExprResult(exprResult, resultType, &aContextNode);
+
+    return xpathResult.forget();
 }
 
 /*
  * Implementation of the txIEvalContext private to XPathExpression
  * EvalContextImpl bases on only one context node and no variables
  */
 
 nsresult
--- a/dom/xslt/xpath/XPathExpression.h
+++ b/dom/xslt/xpath/XPathExpression.h
@@ -1,52 +1,73 @@
 /* -*- 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/. */
 
 #ifndef mozilla_dom_XPathExpression_h
 #define mozilla_dom_XPathExpression_h
 
-#include "nsIDOMXPathExpression.h"
-#include "nsIDOMNSXPathExpression.h"
-#include "txResultRecycler.h"
 #include "nsAutoPtr.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsIWeakReferenceUtils.h"
 #include "mozilla/Attributes.h"
+#include "mozilla/dom/NonRefcountedDOMObject.h"
+#include "mozilla/dom/XPathExpressionBinding.h"
 
 class Expr;
+class nsIDocument;
+class nsINode;
+class txResultRecycler;
 class txXPathNode;
 
 namespace mozilla {
 namespace dom {
 
+class XPathResult;
+
 /**
  * A class for evaluating an XPath expression string
  */
-class XPathExpression MOZ_FINAL : public nsIDOMXPathExpression,
-                                  public nsIDOMNSXPathExpression
+class XPathExpression MOZ_FINAL : public NonRefcountedDOMObject
 {
 public:
     XPathExpression(nsAutoPtr<Expr>&& aExpression, txResultRecycler* aRecycler,
-                    nsIDOMDocument *aDocument);
+                    nsIDocument *aDocument);
+    ~XPathExpression();
 
-    // nsISupports interface
-    NS_DECL_ISUPPORTS
+    JSObject* WrapObject(JSContext* aCx, bool* aTookOwnership)
+    {
+        return XPathExpressionBinding::Wrap(aCx, this, aTookOwnership);
+    }
 
-    // nsIDOMXPathExpression interface
-    NS_DECL_NSIDOMXPATHEXPRESSION
-
-    // nsIDOMNSXPathExpression interface
-    NS_DECL_NSIDOMNSXPATHEXPRESSION
+    already_AddRefed<XPathResult>
+        Evaluate(JSContext* aCx, nsINode& aContextNode, uint16_t aType,
+                 JS::Handle<JSObject*> aInResult, ErrorResult& aRv)
+    {
+        return EvaluateWithContext(aCx, aContextNode, 1, 1, aType, aInResult,
+                                   aRv);
+    }
+    already_AddRefed<XPathResult>
+        EvaluateWithContext(JSContext* aCx, nsINode& aContextNode,
+                            uint32_t aContextPosition, uint32_t aContextSize,
+                            uint16_t aType, JS::Handle<JSObject*> aInResult,
+                            ErrorResult& aRv);
+    already_AddRefed<XPathResult>
+        Evaluate(nsINode& aContextNode, uint16_t aType, XPathResult* aInResult,
+                 ErrorResult& aRv)
+    {
+        return EvaluateWithContext(aContextNode, 1, 1, aType, aInResult, aRv);
+    }
+    already_AddRefed<XPathResult>
+        EvaluateWithContext(nsINode& aContextNode, uint32_t aContextPosition,
+                            uint32_t aContextSize, uint16_t aType,
+                            XPathResult* aInResult, ErrorResult& aRv);
 
 private:
-    ~nsXPathExpression() {}
-
     nsAutoPtr<Expr> mExpression;
     nsRefPtr<txResultRecycler> mRecycler;
     nsWeakPtr mDocument;
     bool mCheckDocument;
 };
 
 } // namespace dom
 } // namespace mozilla
--- a/js/xpconnect/src/dom_quickstubs.qsconf
+++ b/js/xpconnect/src/dom_quickstubs.qsconf
@@ -36,19 +36,17 @@ members = [
     'nsIDOMStorage.setItem',
     'nsIDOMStorage.length',
     'nsIDOMStorage.getItem',
     'nsIDOMStorage.key',
     'nsIDOMStorage.removeItem',
     'nsIDOMStorage.clear',
 
     # dom/interfaces/xpath
-    'nsIDOMXPathExpression.evaluate',
     'nsIDOMXPathNSResolver.lookupNamespaceURI',
-    'nsIDOMNSXPathExpression.evaluateWithContext',
 
     # layout/xul/base/public
     'nsIBoxObject.x',
     'nsIBoxObject.y',
     'nsIBoxObject.screenX',
     'nsIBoxObject.screenY',
     'nsIBoxObject.width',
     'nsIBoxObject.height',