Bug 648801 (new DOM list bindings) - Hook up remaining NodeList/HTMLCollection implementations to new proxy-based DOM bindings. r=bz/jst/mrbkap.
authorPeter Van der Beken <peterv@propagandism.org>
Tue, 31 May 2011 23:47:17 +0200
changeset 78429 1169117ea7f1b124aae3b2b66607aeed0af087e8
parent 78428 d64ee71954761887cceb784b141b529c49a315b4
child 78430 2db768787e7bff858cca2dbcd8ce48264a21dde8
push id21294
push userpvanderbeken@mozilla.com
push dateMon, 10 Oct 2011 08:58:09 +0000
treeherdermozilla-central@432f3a96bc2b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz, jst, mrbkap
bugs648801
milestone10.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 648801 (new DOM list bindings) - Hook up remaining NodeList/HTMLCollection implementations to new proxy-based DOM bindings. r=bz/jst/mrbkap.
content/base/src/nsContentList.cpp
content/base/src/nsContentList.h
content/html/content/src/Makefile.in
content/html/content/src/nsHTMLFormElement.cpp
content/html/content/src/nsHTMLTableElement.cpp
content/xbl/src/Makefile.in
content/xbl/src/nsBindingManager.cpp
--- a/content/base/src/nsContentList.cpp
+++ b/content/base/src/nsContentList.cpp
@@ -180,16 +180,22 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsSimpleContentList)
 NS_INTERFACE_MAP_END_INHERITING(nsBaseContentList)
 
 
 NS_IMPL_ADDREF_INHERITED(nsSimpleContentList, nsBaseContentList)
 NS_IMPL_RELEASE_INHERITED(nsSimpleContentList, nsBaseContentList)
 
+JSObject*
+nsSimpleContentList::WrapObject(JSContext *cx, XPCWrappedNativeScope *scope)
+{
+  return xpc::dom::NodeListBase::create(cx, scope, this);
+}
+
 // nsFormContentList
 
 nsFormContentList::nsFormContentList(nsIContent *aForm,
                                      nsBaseContentList& aContentList)
   : nsSimpleContentList(aForm)
 {
 
   // move elements that belong to mForm into this content list
@@ -442,19 +448,16 @@ nsContentList::nsContentList(nsINode* aR
 
   // We only need to flush if we're in an non-HTML document, since the
   // HTML5 parser doesn't need flushing.  Further, if we're not in a
   // document at all right now (in the GetCurrentDoc() sense), we're
   // not parser-created and don't need to be flushing stuff under us
   // to get our kids right.
   nsIDocument* doc = mRootNode->GetCurrentDoc();
   mFlushesNeeded = doc && !doc->IsHTML();
-
-  // Mark ourselves as a proxy
-  SetIsProxy();
 }
 
 nsContentList::nsContentList(nsINode* aRootNode,
                              nsContentListMatchFunc aFunc,
                              nsContentListDestroyFunc aDestroyFunc,
                              void* aData,
                              bool aDeep,
                              nsIAtom* aMatchAtom,
@@ -478,19 +481,16 @@ nsContentList::nsContentList(nsINode* aR
 
   // We only need to flush if we're in an non-HTML document, since the
   // HTML5 parser doesn't need flushing.  Further, if we're not in a
   // document at all right now (in the GetCurrentDoc() sense), we're
   // not parser-created and don't need to be flushing stuff under us
   // to get our kids right.
   nsIDocument* doc = mRootNode->GetCurrentDoc();
   mFlushesNeeded = doc && !doc->IsHTML();
-
-  // Mark ourselves as a proxy
-  SetIsProxy();
 }
 
 nsContentList::~nsContentList()
 {
   RemoveFromHashtable();
   if (mRootNode) {
     mRootNode->RemoveMutationObserver(this);
   }
--- a/content/base/src/nsContentList.h
+++ b/content/base/src/nsContentList.h
@@ -79,16 +79,21 @@ namespace dom {
 class Element;
 }
 }
 
 
 class nsBaseContentList : public nsINodeList
 {
 public:
+  nsBaseContentList()
+  {
+    // Mark ourselves as a proxy
+    SetIsProxy();
+  }
   virtual ~nsBaseContentList();
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
 
   // nsIDOMNodeList
   NS_DECL_NSIDOMNODELIST
 
   // nsINodeList
@@ -117,18 +122,19 @@ public:
   void InsertElementAt(nsIContent* aContent, PRInt32 aIndex);
 
   void RemoveElement(nsIContent *aContent); 
 
   void Reset() {
     mElements.Clear();
   }
 
+  virtual PRInt32 IndexOf(nsIContent *aContent, bool aDoFlush);
 
-  virtual PRInt32 IndexOf(nsIContent *aContent, bool aDoFlush);
+  virtual JSObject* WrapObject(JSContext *cx, XPCWrappedNativeScope *scope) = 0;
 
 protected:
   nsCOMArray<nsIContent> mElements;
 };
 
 
 class nsSimpleContentList : public nsBaseContentList
 {
@@ -141,16 +147,17 @@ public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsSimpleContentList,
                                            nsBaseContentList)
 
   virtual nsINode* GetParentObject()
   {
     return mRoot;
   }
+  virtual JSObject* WrapObject(JSContext *cx, XPCWrappedNativeScope *scope);
 
 private:
   // This has to be a strong reference, the root might go away before the list.
   nsCOMPtr<nsINode> mRoot;
 };
 
 // This class is used only by form element code and this is a static
 // list of elements. NOTE! This list holds strong references to
--- a/content/html/content/src/Makefile.in
+++ b/content/html/content/src/Makefile.in
@@ -143,11 +143,12 @@ INCLUDES	+= \
 		-I$(srcdir)/../../../../layout/tables \
 		-I$(srcdir)/../../../../layout/xul/base/src \
 		-I$(srcdir)/../../../../layout/generic \
 		-I$(srcdir)/../../../../dom/base \
 		-I$(srcdir)/../../../../editor/libeditor/base \
 		-I$(srcdir)/../../../../editor/libeditor/text \
 		-I$(srcdir) \
 		-I$(topsrcdir)/xpcom/ds \
+		-I$(srcdir)/../../../../js/src/xpconnect/src \
 		$(NULL)
 
 DEFINES += -D_IMPL_NS_LAYOUT
--- a/content/html/content/src/nsHTMLFormElement.cpp
+++ b/content/html/content/src/nsHTMLFormElement.cpp
@@ -78,16 +78,17 @@
 #include "nsEventDispatcher.h"
 
 #include "mozAutoDocUpdate.h"
 #include "nsIHTMLCollection.h"
 
 #include "nsIConstraintValidation.h"
 
 #include "nsIDOMHTMLButtonElement.h"
+#include "dombindings.h"
 
 using namespace mozilla::dom;
 
 static const int NS_FORM_CONTROL_LIST_HASHTABLE_SIZE = 16;
 
 static const PRUint8 NS_FORM_AUTOCOMPLETE_ON  = 1;
 static const PRUint8 NS_FORM_AUTOCOMPLETE_OFF = 0;
 
@@ -101,17 +102,18 @@ static const nsAttrValue::EnumTable* kFo
 
 // nsHTMLFormElement
 
 bool nsHTMLFormElement::gFirstFormSubmitted = false;
 bool nsHTMLFormElement::gPasswordManagerInitialized = false;
 
 
 // nsFormControlList
-class nsFormControlList : public nsIHTMLCollection
+class nsFormControlList : public nsIHTMLCollection,
+                          public nsWrapperCache
 {
 public:
   nsFormControlList(nsHTMLFormElement* aForm);
   virtual ~nsFormControlList();
 
   nsresult Init();
 
   void DropFormReference();
@@ -150,28 +152,34 @@ public:
    * mNotInElements list. This function does not add references to the
    * elements.
    *
    * @param aControls The list of sorted controls[out].
    * @return NS_OK or NS_ERROR_OUT_OF_MEMORY.
    */
   nsresult GetSortedControls(nsTArray<nsGenericHTMLFormElement*>& aControls) const;
 
+  // nsWrapperCache
+  virtual JSObject* WrapObject(JSContext *cx, XPCWrappedNativeScope *scope)
+  {
+    return xpc::dom::NodeListBase::create(cx, scope, this, this);
+  }
+
   nsHTMLFormElement* mForm;  // WEAK - the form owns me
 
   nsTArray<nsGenericHTMLFormElement*> mElements;  // Holds WEAK references - bug 36639
 
   // This array holds on to all form controls that are not contained
   // in mElements (form.elements in JS, see ShouldBeInFormControl()).
   // This is needed to properly clean up the bi-directional references
   // (both weak and strong) between the form and its form controls.
 
   nsTArray<nsGenericHTMLFormElement*> mNotInElements; // Holds WEAK references
 
-  NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsFormControlList, nsIHTMLCollection)
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsFormControlList)
 
 protected:
   // Drop all our references to the form elements
   void Clear();
 
   // Flush out the content model so it's up to date.
   void FlushPendingNotifications();
   
@@ -2144,16 +2152,18 @@ nsHTMLFormElement::SetValueMissingState(
 // a lightweight collection implementation somewhere
 
 nsFormControlList::nsFormControlList(nsHTMLFormElement* aForm) :
   mForm(aForm),
   // Initialize the elements list to have an initial capacity
   // of 8 to reduce allocations on small forms.
   mElements(8)
 {
+  // Mark ourselves as a proxy
+  SetIsProxy();
 }
 
 nsFormControlList::~nsFormControlList()
 {
   mForm = nsnull;
   Clear();
 }
 
@@ -2210,25 +2220,31 @@ ControlTraverser(const nsAString& key, n
  
   cb->NoteXPCOMChild(control);
   return PL_DHASH_NEXT;
 }
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsFormControlList)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsFormControlList)
   tmp->Clear();
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsFormControlList)
   tmp->mNameLookupTable.EnumerateRead(ControlTraverser, &cb);
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsFormControlList)
+  NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
+NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 DOMCI_DATA(HTMLCollection, nsFormControlList)
 
 // XPConnect interface list for nsFormControlList
 NS_INTERFACE_TABLE_HEAD(nsFormControlList)
+  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_TABLE2(nsFormControlList,
                       nsIHTMLCollection,
                       nsIDOMHTMLCollection)
   NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(nsFormControlList)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(HTMLCollection)
 NS_INTERFACE_MAP_END
 
 
--- a/content/html/content/src/nsHTMLTableElement.cpp
+++ b/content/html/content/src/nsHTMLTableElement.cpp
@@ -45,81 +45,96 @@
 #include "nsGkAtoms.h"
 #include "nsStyleConsts.h"
 #include "nsPresContext.h"
 #include "nsHTMLParts.h"
 #include "nsRuleData.h"
 #include "nsStyleContext.h"
 #include "nsIDocument.h"
 #include "nsContentUtils.h"
-/* for collections */
 #include "nsIDOMElement.h"
 #include "nsGenericHTMLElement.h"
 #include "nsIHTMLCollection.h"
-/* end for collections */
 #include "nsHTMLStyleSheet.h"
+#include "dombindings.h"
 
 /* ------------------------------ TableRowsCollection -------------------------------- */
 /**
  * This class provides a late-bound collection of rows in a table.
  * mParent is NOT ref-counted to avoid circular references
  */
-class TableRowsCollection : public nsIHTMLCollection 
+class TableRowsCollection : public nsIHTMLCollection,
+                            public nsWrapperCache
 {
 public:
   TableRowsCollection(nsHTMLTableElement *aParent);
   virtual ~TableRowsCollection();
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_NSIDOMHTMLCOLLECTION
 
   virtual nsIContent* GetNodeAt(PRUint32 aIndex);
   virtual nsISupports* GetNamedItem(const nsAString& aName,
                                     nsWrapperCache **aCache);
 
   NS_IMETHOD    ParentDestroyed();
 
-  NS_DECL_CYCLE_COLLECTION_CLASS(TableRowsCollection)
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(TableRowsCollection)
+
+  // nsWrapperCache
+  virtual JSObject* WrapObject(JSContext *cx, XPCWrappedNativeScope *scope)
+  {
+    return xpc::dom::NodeListBase::create(cx, scope, this, this);
+  }
 
 protected:
   // Those rows that are not in table sections
   nsHTMLTableElement* mParent;
   nsRefPtr<nsContentList> mOrphanRows;  
 };
 
 
 TableRowsCollection::TableRowsCollection(nsHTMLTableElement *aParent)
   : mParent(aParent)
   , mOrphanRows(new nsContentList(mParent,
                                   mParent->NodeInfo()->NamespaceID(),
                                   nsGkAtoms::tr,
                                   nsGkAtoms::tr,
                                   PR_FALSE))
 {
+  // Mark ourselves as a proxy
+  SetIsProxy();
 }
 
 TableRowsCollection::~TableRowsCollection()
 {
   // we do NOT have a ref-counted reference to mParent, so do NOT
   // release it!  this is to avoid circular references.  The
   // instantiator who provided mParent is responsible for managing our
   // reference for us.
 }
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(TableRowsCollection)
-NS_IMPL_CYCLE_COLLECTION_UNLINK_0(TableRowsCollection)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(TableRowsCollection)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(TableRowsCollection)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mOrphanRows,
                                                        nsIDOMNodeList)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(TableRowsCollection)
+  NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
+NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(TableRowsCollection)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(TableRowsCollection)
 
 NS_INTERFACE_TABLE_HEAD(TableRowsCollection)
+  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_TABLE2(TableRowsCollection, nsIHTMLCollection,
                       nsIDOMHTMLCollection)
   NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(TableRowsCollection)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(HTMLCollection)
 NS_INTERFACE_MAP_END
 
 // Macro that can be used to avoid copy/pasting code to iterate over the
 // rowgroups.  _code should be the code to execute for each rowgroup.  The
--- a/content/xbl/src/Makefile.in
+++ b/content/xbl/src/Makefile.in
@@ -84,11 +84,12 @@ LOCAL_INCLUDES	= \
 		-I$(srcdir)/../../html/document/src \
 		-I$(srcdir)/../../xml/document/src \
 		-I$(srcdir)/../../xul/content/src \
 		-I$(srcdir)/../../xul/document/src \
 		-I$(srcdir)/../../events/src \
 		-I$(srcdir)/../../../layout/style \
 		-I$(srcdir)/../../../dom/base \
 		-I$(topsrcdir)/xpcom/ds \
+		-I$(srcdir)/../../../js/src/xpconnect/src \
 		$(NULL)
 
 DEFINES += -D_IMPL_NS_LAYOUT
--- a/content/xbl/src/nsBindingManager.cpp
+++ b/content/xbl/src/nsBindingManager.cpp
@@ -76,48 +76,55 @@
 #include "nsIDOMScriptObjectFactory.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsTHashtable.h"
 
 #include "nsIScriptContext.h"
 #include "nsBindingManager.h"
 
 #include "nsThreadUtils.h"
+#include "dombindings.h"
 
 // ==================================================================
 // = nsAnonymousContentList 
 // ==================================================================
 
 #define NS_ANONYMOUS_CONTENT_LIST_IID \
   { 0xbfb5d8e7, 0xf718, 0x4a46, \
     { 0xb2, 0x2b, 0x22, 0x4a, 0x44, 0x4c, 0xb9, 0x77 } }
 
 class nsAnonymousContentList : public nsINodeList
 {
 public:
   nsAnonymousContentList(nsIContent *aContent, nsInsertionPointList* aElements);
   virtual ~nsAnonymousContentList();
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-  NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsAnonymousContentList, nsINodeList)
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsAnonymousContentList)
   // nsIDOMNodeList interface
   NS_DECL_NSIDOMNODELIST
 
   // nsINodeList interface
   virtual nsIContent* GetNodeAt(PRUint32 aIndex);
   virtual PRInt32 IndexOf(nsIContent* aContent);
   virtual nsINode *GetParentObject()
   {
     return mContent;
   }
 
   PRInt32 GetInsertionPointCount() { return mElements->Length(); }
 
   nsXBLInsertionPoint* GetInsertionPointAt(PRInt32 i) { return static_cast<nsXBLInsertionPoint*>(mElements->ElementAt(i)); }
   void RemoveInsertionPointAt(PRInt32 i) { mElements->RemoveElementAt(i); }
+
+  virtual JSObject* WrapObject(JSContext *cx, XPCWrappedNativeScope *scope)
+  {
+    return xpc::dom::NodeListBase::create(cx, scope, this);
+  }
+
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_ANONYMOUS_CONTENT_LIST_IID)
 private:
   nsCOMPtr<nsIContent> mContent;
   nsInsertionPointList* mElements;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsAnonymousContentList,
                               NS_ANONYMOUS_CONTENT_LIST_IID)
@@ -126,55 +133,62 @@ nsAnonymousContentList::nsAnonymousConte
                                                nsInsertionPointList* aElements)
   : mContent(aContent),
     mElements(aElements)
 {
   MOZ_COUNT_CTOR(nsAnonymousContentList);
 
   // We don't reference count our Anonymous reference (to avoid circular
   // references). We'll be told when the Anonymous goes away.
+  SetIsProxy();
 }
 
 nsAnonymousContentList::~nsAnonymousContentList()
 {
   MOZ_COUNT_DTOR(nsAnonymousContentList);
   delete mElements;
 }
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsAnonymousContentList)
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsAnonymousContentList)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsAnonymousContentList)
 
 NS_INTERFACE_TABLE_HEAD(nsAnonymousContentList)
+  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_NODELIST_OFFSET_AND_INTERFACE_TABLE_BEGIN(nsAnonymousContentList)
     NS_INTERFACE_TABLE_ENTRY(nsAnonymousContentList, nsINodeList)
     NS_INTERFACE_TABLE_ENTRY(nsAnonymousContentList, nsIDOMNodeList)
     NS_INTERFACE_TABLE_ENTRY(nsAnonymousContentList, nsAnonymousContentList)
   NS_OFFSET_AND_INTERFACE_TABLE_END
   NS_OFFSET_AND_INTERFACE_TABLE_TO_MAP_SEGUE
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(NodeList)
   NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(nsAnonymousContentList)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsAnonymousContentList)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mContent)
   tmp->mElements->Clear();
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsAnonymousContentList)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mContent)
   {
     PRInt32 i, count = tmp->mElements->Length();
     for (i = 0; i < count; ++i) {
       NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_MEMBER(mElements->ElementAt(i),
                                                       nsXBLInsertionPoint);
     }
   }
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsAnonymousContentList)
+  NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
+NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 NS_IMETHODIMP
 nsAnonymousContentList::GetLength(PRUint32* aLength)
 {
   NS_ASSERTION(aLength != nsnull, "null ptr");
   if (! aLength)
       return NS_ERROR_NULL_POINTER;