Bug 838686 part 2. Use NodeFilterHolder in treewalker and nodeiterator and start using WebIDL codegen for NodeFilter. r=peterv
☠☠ backed out by 7e07e7ffe99e ☠ ☠
authorBoris Zbarsky <bzbarsky@mit.edu>
Tue, 26 Feb 2013 15:10:15 -0500
changeset 123057 1c851a5bbc9fe9782f0cf347730b1650ca119276
parent 123056 a4763990a983c9e29a3cf49de18abecbbecba75d
child 123058 4d3e8e7ee9779658151127980b4aad5806be2534
push id23639
push userbzbarsky@mozilla.com
push dateTue, 26 Feb 2013 20:12:46 +0000
treeherdermozilla-inbound@1c851a5bbc9f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspeterv
bugs838686
milestone22.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 838686 part 2. Use NodeFilterHolder in treewalker and nodeiterator and start using WebIDL codegen for NodeFilter. r=peterv
content/base/public/nsIDocument.h
content/base/src/nsDocument.cpp
content/base/src/nsNodeIterator.cpp
content/base/src/nsNodeIterator.h
content/base/src/nsTraversal.cpp
content/base/src/nsTraversal.h
content/base/src/nsTreeWalker.cpp
content/base/src/nsTreeWalker.h
dom/bindings/Codegen.py
editor/libeditor/text/nsTextEditRules.cpp
--- a/content/base/public/nsIDocument.h
+++ b/content/base/public/nsIDocument.h
@@ -90,19 +90,23 @@ class CDATASection;
 class Comment;
 class DocumentFragment;
 class DocumentType;
 class DOMImplementation;
 class Element;
 class GlobalObject;
 class HTMLBodyElement;
 class Link;
+class NodeFilter;
 class ProcessingInstruction;
 class UndoManager;
 template<typename> class Sequence;
+
+template<typename, typename> class CallbackObjectHolder;
+typedef CallbackObjectHolder<NodeFilter, nsIDOMNodeFilter> NodeFilterHolder;
 } // namespace dom
 } // namespace mozilla
 
 #define NS_IDOCUMENT_IID \
 { 0x45ce048f, 0x5970, 0x411e, \
   { 0xaa, 0x99, 0x12, 0xed, 0x3a, 0x55, 0xc9, 0xc3 } }
 
 // Flag for AddStyleSheet().
@@ -1914,20 +1918,29 @@ public:
   already_AddRefed<nsINode>
     ImportNode(nsINode& aNode, bool aDeep, mozilla::ErrorResult& rv) const;
   nsINode* AdoptNode(nsINode& aNode, mozilla::ErrorResult& rv);
   already_AddRefed<nsIDOMEvent> CreateEvent(const nsAString& aEventType,
                                             mozilla::ErrorResult& rv) const;
   already_AddRefed<nsRange> CreateRange(mozilla::ErrorResult& rv);
   already_AddRefed<nsIDOMNodeIterator>
     CreateNodeIterator(nsINode& aRoot, uint32_t aWhatToShow,
-                       nsIDOMNodeFilter* aFilter, mozilla::ErrorResult& rv) const;
+                       mozilla::dom::NodeFilter* aFilter,
+                       mozilla::ErrorResult& rv) const;
+  already_AddRefed<nsIDOMNodeIterator>
+    CreateNodeIterator(nsINode& aRoot, uint32_t aWhatToShow,
+                       const mozilla::dom::NodeFilterHolder& aFilter,
+                       mozilla::ErrorResult& rv) const;
   already_AddRefed<nsIDOMTreeWalker>
     CreateTreeWalker(nsINode& aRoot, uint32_t aWhatToShow,
-                     nsIDOMNodeFilter* aFilter, mozilla::ErrorResult& rv) const;
+                     mozilla::dom::NodeFilter* aFilter, mozilla::ErrorResult& rv) const;
+  already_AddRefed<nsIDOMTreeWalker>
+    CreateTreeWalker(nsINode& aRoot, uint32_t aWhatToShow,
+                     const mozilla::dom::NodeFilterHolder& aFilter,
+                     mozilla::ErrorResult& rv) const;
 
   // Deprecated WebIDL bits
   already_AddRefed<mozilla::dom::CDATASection>
     CreateCDATASection(const nsAString& aData, mozilla::ErrorResult& rv);
   already_AddRefed<nsIDOMAttr>
     CreateAttribute(const nsAString& aName, mozilla::ErrorResult& rv);
   already_AddRefed<nsIDOMAttr>
     CreateAttributeNS(const nsAString& aNamespaceURI,
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -179,16 +179,17 @@
 #include "imgILoader.h"
 #include "imgRequestProxy.h"
 #include "nsWrapperCacheInlines.h"
 #include "nsSandboxFlags.h"
 #include "nsIAppsService.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/DocumentFragment.h"
 #include "mozilla/dom/HTMLBodyElement.h"
+#include "mozilla/dom/NodeFilterBinding.h"
 #include "mozilla/dom/UndoManager.h"
 #include "nsFrame.h"
 #include "nsDOMCaretPosition.h"
 #include "nsIDOMHTMLTextAreaElement.h"
 #include "nsViewportInfo.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
@@ -5349,24 +5350,38 @@ nsDocument::CreateNodeIterator(nsIDOMNod
   if (!aRoot) {
     return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
   }
 
   nsCOMPtr<nsINode> root = do_QueryInterface(aRoot);
   NS_ENSURE_TRUE(root, NS_ERROR_UNEXPECTED);
 
   ErrorResult rv;
-  *_retval = nsIDocument::CreateNodeIterator(*root, aWhatToShow, aFilter,
+  NodeFilterHolder holder(aFilter);
+  *_retval = nsIDocument::CreateNodeIterator(*root, aWhatToShow, holder,
                                              rv).get();
   return rv.ErrorCode();
 }
 
 already_AddRefed<nsIDOMNodeIterator>
 nsIDocument::CreateNodeIterator(nsINode& aRoot, uint32_t aWhatToShow,
-                                nsIDOMNodeFilter* aFilter,
+                                NodeFilter* aFilter,
+                                mozilla::ErrorResult& rv) const
+{
+  NodeFilterHolder holder(aFilter);
+  // We don't really know how to handle WebIDL callbacks yet, in
+  // nsTraversal, so just go ahead and convert to an XPCOM callback.
+  nsCOMPtr<nsIDOMNodeFilter> filter = holder.ToXPCOMCallback();
+  NodeFilterHolder holder2(filter);
+  return CreateNodeIterator(aRoot, aWhatToShow, holder2, rv);
+}
+
+already_AddRefed<nsIDOMNodeIterator>
+nsIDocument::CreateNodeIterator(nsINode& aRoot, uint32_t aWhatToShow,
+                                const NodeFilterHolder& aFilter,
                                 mozilla::ErrorResult& rv) const
 {
   nsINode* root = &aRoot;
   nsresult res = nsContentUtils::CheckSameOrigin(this, root);
   if (NS_FAILED(res)) {
     rv.Throw(res);
     return nullptr;
   }
@@ -5388,24 +5403,38 @@ nsDocument::CreateTreeWalker(nsIDOMNode 
   if (!aOptionalArgc) {
     aWhatToShow = nsIDOMNodeFilter::SHOW_ALL;
   }
 
   nsCOMPtr<nsINode> root = do_QueryInterface(aRoot);
   NS_ENSURE_TRUE(root, NS_ERROR_DOM_NOT_SUPPORTED_ERR);
 
   ErrorResult rv;
-  *_retval = nsIDocument::CreateTreeWalker(*root, aWhatToShow, aFilter,
+  NodeFilterHolder holder(aFilter);
+  *_retval = nsIDocument::CreateTreeWalker(*root, aWhatToShow, holder,
                                            rv).get();
   return rv.ErrorCode();
 }
 
 already_AddRefed<nsIDOMTreeWalker>
 nsIDocument::CreateTreeWalker(nsINode& aRoot, uint32_t aWhatToShow,
-                              nsIDOMNodeFilter* aFilter,
+                              NodeFilter* aFilter,
+                              mozilla::ErrorResult& rv) const
+{
+  NodeFilterHolder holder(aFilter);
+  // We don't really know how to handle WebIDL callbacks yet, in
+  // nsTraversal, so just go ahead and convert to an XPCOM callback.
+  nsCOMPtr<nsIDOMNodeFilter> filter = holder.ToXPCOMCallback();
+  NodeFilterHolder holder2(filter);
+  return CreateTreeWalker(aRoot, aWhatToShow, holder2, rv);
+}
+
+already_AddRefed<nsIDOMTreeWalker>
+nsIDocument::CreateTreeWalker(nsINode& aRoot, uint32_t aWhatToShow,
+                              const NodeFilterHolder& aFilter,
                               mozilla::ErrorResult& rv) const
 {
   nsINode* root = &aRoot;
   nsresult res = nsContentUtils::CheckSameOrigin(this, root);
   if (NS_FAILED(res)) {
     rv.Throw(res);
     return nullptr;
   }
--- a/content/base/src/nsNodeIterator.cpp
+++ b/content/base/src/nsNodeIterator.cpp
@@ -14,16 +14,19 @@
 #include "nsIDOMNodeFilter.h"
 #include "nsError.h"
 
 #include "nsIContent.h"
 #include "nsIDocument.h"
 #include "nsDOMClassInfoID.h"
 #include "nsContentUtils.h"
 #include "nsCOMPtr.h"
+#include "mozilla/dom/NodeFilterBinding.h"
+
+using namespace mozilla::dom;
 
 /*
  * NodePointer implementation
  */
 nsNodeIterator::NodePointer::NodePointer(nsINode *aNode,
                                          bool aBeforeNode) :
     mNode(aNode),
     mBeforeNode(aBeforeNode)
@@ -132,17 +135,17 @@ void nsNodeIterator::NodePointer::MoveBa
 }
 
 /*
  * Factories, constructors and destructors
  */
 
 nsNodeIterator::nsNodeIterator(nsINode *aRoot,
                                uint32_t aWhatToShow,
-                               nsIDOMNodeFilter *aFilter) :
+                               const NodeFilterHolder &aFilter) :
     nsTraversal(aRoot, aWhatToShow, aFilter),
     mDetached(false),
     mPointer(mRoot, true)
 {
     aRoot->AddMutationObserver(this);
 }
 
 nsNodeIterator::~nsNodeIterator()
@@ -198,17 +201,17 @@ NS_IMETHODIMP nsNodeIterator::GetWhatToS
     return NS_OK;
 }
 
 /* readonly attribute nsIDOMNodeFilter filter; */
 NS_IMETHODIMP nsNodeIterator::GetFilter(nsIDOMNodeFilter **aFilter)
 {
     NS_ENSURE_ARG_POINTER(aFilter);
 
-    NS_IF_ADDREF(*aFilter = mFilter);
+    *aFilter = mFilter.ToXPCOMCallback().get();
 
     return NS_OK;
 }
 
 /* nsIDOMNode nextNode ()  raises (DOMException); */
 NS_IMETHODIMP nsNodeIterator::NextNode(nsIDOMNode **_retval)
 {
     return NextOrPrevNode(&NodePointer::MoveToNext, _retval);
--- a/content/base/src/nsNodeIterator.h
+++ b/content/base/src/nsNodeIterator.h
@@ -25,17 +25,17 @@ class nsNodeIterator : public nsIDOMNode
                        public nsStubMutationObserver
 {
 public:
     NS_DECL_CYCLE_COLLECTING_ISUPPORTS
     NS_DECL_NSIDOMNODEITERATOR
 
     nsNodeIterator(nsINode *aRoot,
                    uint32_t aWhatToShow,
-                   nsIDOMNodeFilter *aFilter);
+                   const mozilla::dom::NodeFilterHolder &aFilter);
     virtual ~nsNodeIterator();
 
     NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
 
     NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsNodeIterator, nsIDOMNodeIterator)
 
 private:
     struct NodePointer {
--- a/content/base/src/nsTraversal.cpp
+++ b/content/base/src/nsTraversal.cpp
@@ -5,22 +5,27 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsTraversal.h"
 
 #include "nsIDOMNode.h"
 #include "nsIDOMNodeFilter.h"
 #include "nsError.h"
 #include "nsINode.h"
+#include "mozilla/dom/NodeFilterBinding.h"
+#include "mozilla/AutoRestore.h"
 
 #include "nsGkAtoms.h"
 
+using namespace mozilla;
+using namespace mozilla::dom;
+
 nsTraversal::nsTraversal(nsINode *aRoot,
                          uint32_t aWhatToShow,
-                         nsIDOMNodeFilter *aFilter) :
+                         const NodeFilterHolder &aFilter) :
     mRoot(aRoot),
     mWhatToShow(aWhatToShow),
     mFilter(aFilter),
     mInAcceptNode(false)
 {
     NS_ASSERTION(aRoot, "invalid root in call to nsTraversal constructor");
 }
 
@@ -35,29 +40,35 @@ nsTraversal::~nsTraversal()
  * @param aNode     Node to test
  * @param _filtered Returned filtervalue. See nsIDOMNodeFilter.idl
  * @returns         Errorcode
  */
 nsresult nsTraversal::TestNode(nsINode* aNode, int16_t* _filtered)
 {
     NS_ENSURE_TRUE(!mInAcceptNode, NS_ERROR_DOM_INVALID_STATE_ERR);
 
-    nsresult rv;
-
     *_filtered = nsIDOMNodeFilter::FILTER_SKIP;
 
     uint16_t nodeType = aNode->NodeType();
 
     if (nodeType <= 12 && !((1 << (nodeType-1)) & mWhatToShow)) {
         return NS_OK;
     }
 
-    if (mFilter) {
-        nsCOMPtr<nsIDOMNode> domNode = do_QueryInterface(aNode);
-        mInAcceptNode = true;
-        rv = mFilter->AcceptNode(domNode, _filtered);
-        mInAcceptNode = false;
-        return rv;
+    if (!mFilter.GetISupports()) {
+        // No filter, just accept
+        *_filtered = nsIDOMNodeFilter::FILTER_ACCEPT;
+        return NS_OK;
     }
 
-    *_filtered = nsIDOMNodeFilter::FILTER_ACCEPT;
-    return NS_OK;
+    if (mFilter.HasWebIDLCallback()) {
+        AutoRestore<bool> inAcceptNode(mInAcceptNode);
+        mInAcceptNode = true;
+        ErrorResult res;
+        *_filtered = mFilter.GetWebIDLCallback()->AcceptNode(*aNode, res);
+        return res.ErrorCode();
+    }
+
+    nsCOMPtr<nsIDOMNode> domNode = do_QueryInterface(aNode);
+    AutoRestore<bool> inAcceptNode(mInAcceptNode);
+    mInAcceptNode = true;
+    return mFilter.GetXPCOMCallback()->AcceptNode(domNode, _filtered);
 }
--- a/content/base/src/nsTraversal.h
+++ b/content/base/src/nsTraversal.h
@@ -7,32 +7,34 @@
 /*
  * Implementation of DOM Traversal's nsIDOMTreeWalker
  */
 
 #ifndef nsTraversal_h___
 #define nsTraversal_h___
 
 #include "nsCOMPtr.h"
+#include "nsIDocument.h"
+#include "mozilla/dom/CallbackObject.h"
 
 class nsINode;
 class nsIDOMNodeFilter;
 
 class nsTraversal
 {
 public:
     nsTraversal(nsINode *aRoot,
                 uint32_t aWhatToShow,
-                nsIDOMNodeFilter *aFilter);
+                const mozilla::dom::NodeFilterHolder &aFilter);
     virtual ~nsTraversal();
 
 protected:
     nsCOMPtr<nsINode> mRoot;
     uint32_t mWhatToShow;
-    nsCOMPtr<nsIDOMNodeFilter> mFilter;
+    mozilla::dom::NodeFilterHolder mFilter;
     bool mInAcceptNode;
 
     /*
      * Tests if and how a node should be filtered. Uses mWhatToShow and
      * mFilter to test the node.
      * @param aNode     Node to test
      * @param _filtered Returned filtervalue. See nsIDOMNodeFilter.idl
      * @returns         Errorcode
--- a/content/base/src/nsTreeWalker.cpp
+++ b/content/base/src/nsTreeWalker.cpp
@@ -11,24 +11,27 @@
 #include "nsTreeWalker.h"
 
 #include "nsIDOMNode.h"
 #include "nsIDOMNodeFilter.h"
 #include "nsError.h"
 #include "nsINode.h"
 #include "nsDOMClassInfoID.h"
 #include "nsContentUtils.h"
+#include "mozilla/dom/NodeFilterBinding.h"
+
+using namespace mozilla::dom;
 
 /*
  * Factories, constructors and destructors
  */
 
 nsTreeWalker::nsTreeWalker(nsINode *aRoot,
                            uint32_t aWhatToShow,
-                           nsIDOMNodeFilter *aFilter) :
+                           const NodeFilterHolder &aFilter) :
     nsTraversal(aRoot, aWhatToShow, aFilter),
     mCurrentNode(aRoot)
 {
 }
 
 nsTreeWalker::~nsTreeWalker()
 {
     /* destructor code */
@@ -77,17 +80,17 @@ NS_IMETHODIMP nsTreeWalker::GetWhatToSho
     return NS_OK;
 }
 
 /* readonly attribute nsIDOMNodeFilter filter; */
 NS_IMETHODIMP nsTreeWalker::GetFilter(nsIDOMNodeFilter * *aFilter)
 {
     NS_ENSURE_ARG_POINTER(aFilter);
 
-    NS_IF_ADDREF(*aFilter = mFilter);
+    *aFilter = mFilter.ToXPCOMCallback().get();
 
     return NS_OK;
 }
 
 /* attribute nsIDOMNode currentNode; */
 NS_IMETHODIMP nsTreeWalker::GetCurrentNode(nsIDOMNode * *aCurrentNode)
 {
     if (mCurrentNode) {
--- a/content/base/src/nsTreeWalker.h
+++ b/content/base/src/nsTreeWalker.h
@@ -24,17 +24,17 @@ class nsIDOMNodeFilter;
 class nsTreeWalker : public nsIDOMTreeWalker, public nsTraversal
 {
 public:
     NS_DECL_CYCLE_COLLECTING_ISUPPORTS
     NS_DECL_NSIDOMTREEWALKER
 
     nsTreeWalker(nsINode *aRoot,
                  uint32_t aWhatToShow,
-                 nsIDOMNodeFilter *aFilter);
+                 const mozilla::dom::NodeFilterHolder &aFilter);
     virtual ~nsTreeWalker();
 
     NS_DECL_CYCLE_COLLECTION_CLASS(nsTreeWalker)
 
 private:
     nsCOMPtr<nsINode> mCurrentNode;
 
     /*
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -2619,17 +2619,16 @@ for (uint32_t i = 0; i < length; ++i) {
 
     if type.isGeckoInterface():
         assert not isEnforceRange and not isClamp
 
         descriptor = descriptorProvider.getDescriptor(
             type.unroll().inner.identifier.name)
 
         if (descriptor.interface.isCallback() and
-            descriptor.interface.identifier.name != "NodeFilter" and
             descriptor.interface.identifier.name != "EventListener"):
             if descriptor.workers:
                 if type.nullable():
                     declType = CGGeneric("JSObject*")
                 else:
                     declType = CGGeneric("NonNull<JSObject>")
                 conversion = "  ${declName} = &${val}.toObject();\n"
             else:
@@ -3465,18 +3464,17 @@ if (!returnArray) {
   }
 }\n""" % (result, exceptionCodeIndented.define(),
           innerTemplate,
           CGIndenter(exceptionCodeIndented, 4).define())) +
                 setValue("JS::ObjectValue(*returnArray)"), False)
 
     if (type.isGeckoInterface() and
         (not type.isCallbackInterface() or
-         type.unroll().inner.identifier.name == "EventListener" or
-         type.unroll().inner.identifier.name == "NodeFilter")):
+         type.unroll().inner.identifier.name == "EventListener")):
         descriptor = descriptorProvider.getDescriptor(type.unroll().inner.identifier.name)
         if type.nullable():
             wrappingCode = ("if (!%s) {\n" % (result) +
                             CGIndenter(CGGeneric(setValue("JSVAL_NULL"))).define() + "\n" +
                             "}\n")
         else:
             wrappingCode = ""
 
@@ -7459,17 +7457,16 @@ class CGNativeMember(ClassMethod):
 
         if type.isUnion():
             if type.nullable():
                 type = type.inner
             return str(type), True, True
 
         if (type.isGeckoInterface() and
             (not type.isCallbackInterface() or
-             type.unroll().inner.identifier.name == "NodeFilter" or
              type.unroll().inner.identifier.name == "EventListener")):
             iface = type.unroll().inner
             argIsPointer = type.nullable() or iface.isExternal()
             forceOwningType = iface.isCallback() or isMember
             if argIsPointer:
                 if (optional or isMember) and forceOwningType:
                     typeDecl = "nsRefPtr<%s>"
                 else:
--- a/editor/libeditor/text/nsTextEditRules.cpp
+++ b/editor/libeditor/text/nsTextEditRules.cpp
@@ -444,17 +444,18 @@ GetTextNode(nsISelection *selection, nsE
   nsresult res = editor->GetStartNodeAndOffset(selection, getter_AddRefs(selNode), &selOffset);
   NS_ENSURE_SUCCESS(res, nullptr);
   if (!editor->IsTextNode(selNode)) {
     // Get an nsINode from the nsIDOMNode
     nsCOMPtr<nsINode> node = do_QueryInterface(selNode);
     // if node is null, return it to indicate there's no text
     NS_ENSURE_TRUE(node, nullptr);
     // This should be the root node, walk the tree looking for text nodes
-    nsNodeIterator iter(node, nsIDOMNodeFilter::SHOW_TEXT, nullptr);
+    mozilla::dom::NodeFilterHolder filter;
+    nsNodeIterator iter(node, nsIDOMNodeFilter::SHOW_TEXT, filter);
     while (!editor->IsTextNode(selNode)) {
       if (NS_FAILED(res = iter.NextNode(getter_AddRefs(selNode))) || !selNode) {
         return nullptr;
       }
     }
   }
   return selNode.forget();
 }