Fix for bug 649057 (Make all nsINodeLists inherit from nsWrapperCache). r=bz.
authorPeter Van der Beken <peterv@propagandism.org>
Tue, 16 Jun 2009 08:32:10 +0200
changeset 68795 623563df5bd13aee671593129b4a67e0c6a5b6df
parent 68794 3600ea5785275fce6930fc0e839319effe3a1113
child 68796 ac941611adf53e89a22d2590ee5d749b4d22d2c6
child 69316 79876e2cbc82e53327a221e7fed30d7b29038e2c
push id99
push usereakhgari@mozilla.com
push dateTue, 24 May 2011 18:03:59 +0000
treeherdermozilla-aurora@26d6981b3d6a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs649057
milestone6.0a1
Fix for bug 649057 (Make all nsINodeLists inherit from nsWrapperCache). r=bz.
content/base/public/nsContentUtils.h
content/base/public/nsINodeList.h
content/base/src/nsContentList.cpp
content/base/src/nsContentList.h
content/base/src/nsContentUtils.cpp
content/base/src/nsDocument.cpp
content/base/src/nsDocument.h
content/base/src/nsGenericElement.cpp
content/base/src/nsGenericElement.h
content/html/content/src/nsHTMLFormElement.cpp
content/html/document/src/nsHTMLDocument.cpp
content/html/document/src/nsHTMLDocument.h
content/html/document/src/nsIHTMLDocument.h
content/xbl/src/nsBindingManager.cpp
dom/base/nsDOMClassInfo.cpp
--- a/content/base/public/nsContentUtils.h
+++ b/content/base/public/nsContentUtils.h
@@ -560,17 +560,17 @@ public:
   /**
    * Determine whether aContent is in some way associated with aForm.  If the
    * form is a container the only elements that are considered to be associated
    * with a form are the elements that are contained within the form. If the
    * form is a leaf element then all elements will be accepted into this list,
    * since this can happen due to content fixup when a form spans table rows or
    * table cells.
    */
-  static PRBool BelongsInForm(nsIDOMHTMLFormElement *aForm,
+  static PRBool BelongsInForm(nsIContent *aForm,
                               nsIContent *aContent);
 
   static nsresult CheckQName(const nsAString& aQualifiedName,
                              PRBool aNamespaceAware = PR_TRUE);
 
   static nsresult SplitQName(const nsIContent* aNamespaceResolver,
                              const nsAFlatString& aQName,
                              PRInt32 *aNamespace, nsIAtom **aLocalName);
--- a/content/base/public/nsINodeList.h
+++ b/content/base/public/nsINodeList.h
@@ -34,43 +34,51 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef nsINodeList_h___
 #define nsINodeList_h___
 
 #include "nsIDOMNodeList.h"
+#include "nsWrapperCache.h"
 
+class nsINode;
 class nsIContent;
 
 // IID for the nsINodeList interface
 #define NS_INODELIST_IID \
-{ 0x57ac9ea2, 0xe95f, 0x4856, \
- { 0xbb, 0xac, 0x82, 0x2d, 0x65, 0xb1, 0x92, 0x57 } }
+{ 0xa842c1b5, 0x9a6f, 0x4afa, \
+ { 0x9c, 0x1c, 0xf5, 0xf7, 0xdc, 0x70, 0x82, 0xd9 } }
 
 /**
  * An internal interface that allows QI-less getting of nodes from
  * node lists and reasonably fast indexOf.
  */
-class nsINodeList : public nsIDOMNodeList
+class nsINodeList : public nsIDOMNodeList,
+                    public nsWrapperCache
 {
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_INODELIST_IID)
 
   /**
    * Get the node at the index.  Returns null if the index is out of bounds
    */
   virtual nsIContent* GetNodeAt(PRUint32 aIndex) = 0;
 
   /**
    * Get the index of the given node in the list.  Will return -1 if the node
    * is not in the list.
    */
   virtual PRInt32 IndexOf(nsIContent* aContent) = 0;
+
+  /**
+   * Get the root node for this nodelist.
+   */
+  virtual nsINode* GetParentObject() = 0;
 };
 
 #define NS_NODELIST_OFFSET_AND_INTERFACE_TABLE_BEGIN(_class)                  \
   NS_OFFSET_AND_INTERFACE_TABLE_BEGIN_AMBIGUOUS(_class, nsINodeList)
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsINodeList, NS_INODELIST_IID)
 
 #endif /* nsINodeList_h___ */
--- a/content/base/src/nsContentList.cpp
+++ b/content/base/src/nsContentList.cpp
@@ -85,16 +85,17 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 #define NS_CONTENT_LIST_INTERFACES(_class)                                    \
     NS_INTERFACE_TABLE_ENTRY(_class, nsINodeList)                             \
     NS_INTERFACE_TABLE_ENTRY(_class, nsIDOMNodeList)
 
 DOMCI_DATA(NodeList, nsBaseContentList)
 
 // QueryInterface implementation for nsBaseContentList
 NS_INTERFACE_TABLE_HEAD(nsBaseContentList)
+  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_NODELIST_OFFSET_AND_INTERFACE_TABLE_BEGIN(nsBaseContentList)
     NS_CONTENT_LIST_INTERFACES(nsBaseContentList)
   NS_OFFSET_AND_INTERFACE_TABLE_END
   NS_OFFSET_AND_INTERFACE_TABLE_TO_MAP_SEGUE
   NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(nsBaseContentList)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(NodeList)
 NS_INTERFACE_MAP_END
 
@@ -155,27 +156,44 @@ void nsBaseContentList::RemoveElement(ns
 }
 
 void nsBaseContentList::InsertElementAt(nsIContent* aContent, PRInt32 aIndex)
 {
   NS_ASSERTION(aContent, "Element to insert must not be null");
   mElements.InsertObjectAt(aContent, aIndex);
 }
 
+
+NS_IMPL_CYCLE_COLLECTION_CLASS(nsSimpleContentList)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsSimpleContentList,
+                                                  nsBaseContentList)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mRoot)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsSimpleContentList,
+                                                nsBaseContentList)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mRoot)
+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)
+
 // nsFormContentList
 
-nsFormContentList::nsFormContentList(nsIDOMHTMLFormElement *aForm,
+nsFormContentList::nsFormContentList(nsIContent *aForm,
                                      nsBaseContentList& aContentList)
-  : nsBaseContentList()
+  : nsSimpleContentList(aForm)
 {
 
   // move elements that belong to mForm into this content list
 
   PRUint32 i, length = 0;
-
   aContentList.GetLength(&length);
 
   for (i = 0; i < length; i++) {
     nsIContent *c = aContentList.GetNodeAt(i);
     if (c && nsContentUtils::BelongsInForm(aForm, c)) {
       AppendElement(c);
     }
   }
@@ -470,17 +488,16 @@ nsContentList::~nsContentList()
     (*mDestroyFunc)(mData);
   }
 }
 
 DOMCI_DATA(ContentList, nsContentList)
 
 // QueryInterface implementation for nsContentList
 NS_INTERFACE_TABLE_HEAD(nsContentList)
-  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_NODELIST_OFFSET_AND_INTERFACE_TABLE_BEGIN(nsContentList)
     NS_CONTENT_LIST_INTERFACES(nsContentList)
     NS_INTERFACE_TABLE_ENTRY(nsContentList, nsIHTMLCollection)
     NS_INTERFACE_TABLE_ENTRY(nsContentList, nsIDOMHTMLCollection)
     NS_INTERFACE_TABLE_ENTRY(nsContentList, nsIMutationObserver)
   NS_OFFSET_AND_INTERFACE_TABLE_END
   NS_OFFSET_AND_INTERFACE_TABLE_TO_MAP_SEGUE
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(ContentList)
--- a/content/base/src/nsContentList.h
+++ b/content/base/src/nsContentList.h
@@ -69,17 +69,16 @@
 typedef PRBool (*nsContentListMatchFunc)(nsIContent* aContent,
                                          PRInt32 aNamespaceID,
                                          nsIAtom* aAtom,
                                          void* aData);
 
 typedef void (*nsContentListDestroyFunc)(void* aData);
 
 class nsIDocument;
-class nsIDOMHTMLFormElement;
 
 
 class nsBaseContentList : public nsINodeList
 {
 public:
   virtual ~nsBaseContentList();
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
@@ -121,23 +120,45 @@ public:
 
   virtual PRInt32 IndexOf(nsIContent *aContent, PRBool aDoFlush);
 
 protected:
   nsCOMArray<nsIContent> mElements;
 };
 
 
+class nsSimpleContentList : public nsBaseContentList
+{
+public:
+  nsSimpleContentList(nsINode *aRoot) : nsBaseContentList(),
+                                        mRoot(aRoot)
+  {
+  }
+
+  NS_DECL_ISUPPORTS_INHERITED
+  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsSimpleContentList,
+                                           nsBaseContentList)
+
+  virtual nsINode* GetParentObject()
+  {
+    return mRoot;
+  }
+
+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
 // the elements in the list.
-class nsFormContentList : public nsBaseContentList
+class nsFormContentList : public nsSimpleContentList
 {
 public:
-  nsFormContentList(nsIDOMHTMLFormElement *aForm,
+  nsFormContentList(nsIContent *aForm,
                     nsBaseContentList& aContentList);
 };
 
 /**
  * Class that's used as the key to hash nsContentList implementations
  * for fast retrieval
  */
 struct nsContentListKey
@@ -192,18 +213,17 @@ struct nsContentListKey
 #define LIST_LAZY 2
 
 /**
  * Class that implements a live NodeList that matches Elements in the
  * tree based on some criterion.
  */
 class nsContentList : public nsBaseContentList,
                       public nsIHTMLCollection,
-                      public nsStubMutationObserver,
-                      public nsWrapperCache
+                      public nsStubMutationObserver
 {
 public:
   NS_DECL_ISUPPORTS_INHERITED
 
   /**
    * @param aRootNode The node under which to limit our search.
    * @param aMatchAtom An atom whose meaning depends on aMatchNameSpaceId.
    *                   The special value "*" always matches whatever aMatchAtom
@@ -253,24 +273,27 @@ public:
 
   // nsIDOMHTMLCollection
   NS_DECL_NSIDOMHTMLCOLLECTION
 
   // nsBaseContentList overrides
   virtual PRInt32 IndexOf(nsIContent *aContent, PRBool aDoFlush);
   virtual nsIContent* GetNodeAt(PRUint32 aIndex);
   virtual PRInt32 IndexOf(nsIContent* aContent);
+  virtual nsINode* GetParentObject()
+  {
+    return mRootNode;
+  }
 
   // nsIHTMLCollection
   // GetNodeAt already declared as part of nsINodeList
   virtual nsISupports* GetNamedItem(const nsAString& aName,
                                     nsWrapperCache** aCache);
 
   // nsContentList public methods
-  NS_HIDDEN_(nsINode*) GetParentObject() { return mRootNode; }
   NS_HIDDEN_(PRUint32) Length(PRBool aDoFlush);
   NS_HIDDEN_(nsIContent*) Item(PRUint32 aIndex, PRBool aDoFlush);
   NS_HIDDEN_(nsIContent*) NamedItem(const nsAString& aName, PRBool aDoFlush);
 
   // nsIMutationObserver
   NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -2208,68 +2208,60 @@ nsContentUtils::NewURIWithDocumentCharse
 {
   return NS_NewURI(aResult, aSpec,
                    aDocument ? aDocument->GetDocumentCharacterSet().get() : nsnull,
                    aBaseURI, sIOService);
 }
 
 // static
 PRBool
-nsContentUtils::BelongsInForm(nsIDOMHTMLFormElement *aForm,
+nsContentUtils::BelongsInForm(nsIContent *aForm,
                               nsIContent *aContent)
 {
   NS_PRECONDITION(aForm, "Must have a form");
   NS_PRECONDITION(aContent, "Must have a content node");
 
-  nsCOMPtr<nsIContent> form(do_QueryInterface(aForm));
-
-  if (!form) {
-    NS_ERROR("This should not happen, form is not an nsIContent!");
-
-    return PR_TRUE;
-  }
-
-  if (form == aContent) {
+  if (aForm == aContent) {
     // A form does not belong inside itself, so we return false here
 
     return PR_FALSE;
   }
 
   nsIContent* content = aContent->GetParent();
 
   while (content) {
-    if (content == form) {
+    if (content == aForm) {
       // aContent is contained within the form so we return true.
 
       return PR_TRUE;
     }
 
     if (content->Tag() == nsGkAtoms::form &&
         content->IsHTML()) {
       // The child is contained within a form, but not the right form
       // so we ignore it.
 
       return PR_FALSE;
     }
 
     content = content->GetParent();
   }
 
-  if (form->GetChildCount() > 0) {
+  if (aForm->GetChildCount() > 0) {
     // The form is a container but aContent wasn't inside the form,
     // return false
 
     return PR_FALSE;
   }
 
   // The form is a leaf and aContent wasn't inside any other form so
   // we check whether the content comes after the form.  If it does,
   // return true.  If it does not, then it couldn't have been inside
   // the form in the HTML.
-  if (PositionIsBefore(form, aContent)) {
+  if (PositionIsBefore(aForm, aContent)) {
     // We could be in this form!
     // In the future, we may want to get document.forms, look at the
     // form after aForm, and if aContent is after that form after
     // aForm return false here....
     return PR_TRUE;
   }
 
   return PR_FALSE;
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -210,17 +210,17 @@ using namespace mozilla::dom;
 typedef nsTArray<Link*> LinkArray;
 
 
 #ifdef PR_LOGGING
 static PRLogModuleInfo* gDocumentLeakPRLog;
 static PRLogModuleInfo* gCspPRLog;
 #endif
 
-#define NAME_NOT_VALID ((nsBaseContentList*)1)
+#define NAME_NOT_VALID ((nsSimpleContentList*)1)
 
 nsIdentifierMapEntry::~nsIdentifierMapEntry()
 {
 }
 
 void
 nsIdentifierMapEntry::Traverse(nsCycleCollectionTraversalCallback* aCallback)
 {
@@ -418,20 +418,20 @@ nsIdentifierMapEntry::SetImageElement(El
   mImageElement = aElement;
   Element* newElement = GetImageIdElement();
   if (oldElement != newElement) {
     FireChangeCallbacks(oldElement, newElement, PR_TRUE);
   }
 }
 
 void
-nsIdentifierMapEntry::AddNameElement(Element* aElement)
+nsIdentifierMapEntry::AddNameElement(nsIDocument* aDocument, Element* aElement)
 {
   if (!mNameContentList) {
-    mNameContentList = new nsBaseContentList();
+    mNameContentList = new nsSimpleContentList(aDocument);
   }
 
   mNameContentList->AppendElement(aElement);
 }
 
 void
 nsIdentifierMapEntry::RemoveNameElement(Element* aElement)
 {
@@ -2554,17 +2554,17 @@ nsDocument::GetLastModified(nsAString& a
 void
 nsDocument::AddToNameTable(Element *aElement, nsIAtom* aName)
 {
   nsIdentifierMapEntry *entry =
     mIdentifierMap.PutEntry(nsDependentAtomString(aName));
 
   // Null for out-of-memory
   if (entry) {
-    entry->AddNameElement(aElement);
+    entry->AddNameElement(this, aElement);
   }
 }
 
 void
 nsDocument::RemoveFromNameTable(Element *aElement, nsIAtom* aName)
 {
   // Speed up document teardown
   if (mIdentifierMap.Count() == 0)
@@ -2841,17 +2841,17 @@ nsDocument::NodesFromRectHelper(float aX
                                 float aTopSize, float aRightSize,
                                 float aBottomSize, float aLeftSize,
                                 PRBool aIgnoreRootScrollFrame,
                                 PRBool aFlushLayout,
                                 nsIDOMNodeList** aReturn)
 {
   NS_ENSURE_ARG_POINTER(aReturn);
   
-  nsBaseContentList* elements = new nsBaseContentList();
+  nsSimpleContentList* elements = new nsSimpleContentList(this);
   NS_ADDREF(elements);
   *aReturn = elements;
 
   // Following the same behavior of elementFromPoint,
   // we don't return anything if either coord is negative
   if (!aIgnoreRootScrollFrame && (aX < 0 || aY < 0))
     return NS_OK;
 
--- a/content/base/src/nsDocument.h
+++ b/content/base/src/nsDocument.h
@@ -162,17 +162,17 @@ public:
     nsStringHashKey(&aOther.GetKey())
   {
     NS_ERROR("Should never be called");
   }
   ~nsIdentifierMapEntry();
 
   void SetInvalidName();
   PRBool IsInvalidName();
-  void AddNameElement(Element* aElement);
+  void AddNameElement(nsIDocument* aDocument, Element* aElement);
   void RemoveNameElement(Element* aElement);
   PRBool IsEmpty();
   nsBaseContentList* GetNameContentList() {
     return mNameContentList;
   }
 
   /**
    * Returns the element if we know the element associated with this
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -3074,17 +3074,17 @@ nsGenericElement::UnbindFromTree(PRBool 
   }
 
   nsNodeUtils::ParentChainChanged(this);
 }
 
 already_AddRefed<nsINodeList>
 nsGenericElement::GetChildren(PRUint32 aFilter)
 {
-  nsRefPtr<nsBaseContentList> list = new nsBaseContentList();
+  nsRefPtr<nsSimpleContentList> list = new nsSimpleContentList(this);
   if (!list) {
     return nsnull;
   }
 
   nsIFrame *frame = GetPrimaryFrame();
 
   // Append :before generated content.
   if (frame) {
@@ -5523,17 +5523,17 @@ nsGenericElement::doQuerySelector(nsINod
 /* static */
 nsresult
 nsGenericElement::doQuerySelectorAll(nsINode* aRoot,
                                      const nsAString& aSelector,
                                      nsIDOMNodeList **aReturn)
 {
   NS_PRECONDITION(aReturn, "Null out param?");
 
-  nsBaseContentList* contentList = new nsBaseContentList();
+  nsSimpleContentList* contentList = new nsSimpleContentList(aRoot);
   NS_ENSURE_TRUE(contentList, NS_ERROR_OUT_OF_MEMORY);
   NS_ADDREF(*aReturn = contentList);
   
   nsAutoPtr<nsCSSSelectorList> selectorList;
   nsresult rv = ParseSelectorList(aRoot, aSelector,
                                   getter_Transfers(selectorList));
   NS_ENSURE_SUCCESS(rv, rv);
 
--- a/content/base/src/nsGenericElement.h
+++ b/content/base/src/nsGenericElement.h
@@ -90,18 +90,17 @@ struct nsRect;
 typedef PRUptrdiff PtrBits;
 
 /**
  * Class that implements the nsIDOMNodeList interface (a list of children of
  * the content), by holding a reference to the content and delegating GetLength
  * and Item to its existing child list.
  * @see nsIDOMNodeList
  */
-class nsChildContentList : public nsINodeList,
-                           public nsWrapperCache
+class nsChildContentList : public nsINodeList
 {
 public:
   nsChildContentList(nsINode* aNode)
     : mNode(aNode)
   {
   }
 
   NS_DECL_ISUPPORTS
@@ -113,37 +112,21 @@ public:
   virtual nsIContent* GetNodeAt(PRUint32 aIndex);
   virtual PRInt32 IndexOf(nsIContent* aContent);
 
   void DropReference()
   {
     mNode = nsnull;
   }
 
-  nsINode* GetParentObject()
+  virtual nsINode* GetParentObject()
   {
     return mNode;
   }
 
-  static nsChildContentList* FromSupports(nsISupports* aSupports)
-  {
-    nsINodeList* list = static_cast<nsINodeList*>(aSupports);
-#ifdef DEBUG
-    {
-      nsCOMPtr<nsINodeList> list_qi = do_QueryInterface(aSupports);
-
-      // If this assertion fires the QI implementation for the object in
-      // question doesn't use the nsINodeList pointer as the nsISupports
-      // pointer. That must be fixed, or we'll crash...
-      NS_ASSERTION(list_qi == list, "Uh, fix QI!");
-    }
-#endif
-    return static_cast<nsChildContentList*>(list);
-  }
-
 private:
   // The node whose children make up the list (weak reference)
   nsINode* mNode;
 };
 
 /**
  * A tearoff class for nsGenericElement to implement additional interfaces
  */
--- a/content/html/content/src/nsHTMLFormElement.cpp
+++ b/content/html/content/src/nsHTMLFormElement.cpp
@@ -2382,17 +2382,17 @@ nsFormControlList::AddElementToTable(nsG
       // happen if a form control has both a name and an id with the same
       // value
       if (content == aChild) {
         return NS_OK;
       }
 
       // Found an element, create a list, add the element to the list and put
       // the list in the hash
-      nsBaseContentList *list = new nsBaseContentList();
+      nsSimpleContentList *list = new nsSimpleContentList(mForm);
       NS_ENSURE_TRUE(list, NS_ERROR_OUT_OF_MEMORY);
 
       NS_ASSERTION(content->GetParent(), "Item in list without parent");
 
       // Determine the ordering between the new and old element.
       PRBool newFirst = nsContentUtils::PositionIsBefore(aChild, content);
 
       list->AppendElement(newFirst ? aChild : content);
@@ -2406,17 +2406,17 @@ nsFormControlList::AddElementToTable(nsG
       NS_ENSURE_TRUE(mNameLookupTable.Put(aName, listSupports),
                      NS_ERROR_FAILURE);
     } else {
       // There's already a list in the hash, add the child to the list
       nsCOMPtr<nsIDOMNodeList> nodeList(do_QueryInterface(supports));
       NS_ENSURE_TRUE(nodeList, NS_ERROR_FAILURE);
 
       // Upcast, uggly, but it works!
-      nsBaseContentList *list = static_cast<nsBaseContentList *>
+      nsSimpleContentList *list = static_cast<nsSimpleContentList *>
                                            ((nsIDOMNodeList *)nodeList.get());
 
       NS_ASSERTION(list->Length() > 1,
                    "List should have been converted back to a single element");
 
       // Fast-path appends; this check is ok even if the child is
       // already in the list, since if it tests true the child would
       // have come at the end of the list, and the PositionIsBefore
--- a/content/html/document/src/nsHTMLDocument.cpp
+++ b/content/html/document/src/nsHTMLDocument.cpp
@@ -2517,17 +2517,17 @@ nsHTMLDocument::GetPlugins(nsIDOMHTMLCol
 {
   *aPlugins = nsnull;
 
   return GetEmbeds(aPlugins);
 }
 
 nsresult
 nsHTMLDocument::ResolveName(const nsAString& aName,
-                            nsIDOMHTMLFormElement *aForm,
+                            nsIContent *aForm,
                             nsISupports **aResult,
                             nsWrapperCache **aCache)
 {
   *aResult = nsnull;
   *aCache = nsnull;
 
   nsIdentifierMapEntry *entry = mIdentifierMap.GetEntry(aName);
   if (!entry) {
--- a/content/html/document/src/nsHTMLDocument.h
+++ b/content/html/document/src/nsHTMLDocument.h
@@ -163,17 +163,17 @@ public:
     return NS_GetFuncStringContentList(this, MatchNameAttribute, nsnull,
                                        UseExistingNameString, aName);
   }
 
   // nsIDOMNSHTMLDocument interface
   NS_DECL_NSIDOMNSHTMLDOCUMENT
 
   virtual nsresult ResolveName(const nsAString& aName,
-                               nsIDOMHTMLFormElement *aForm,
+                               nsIContent *aForm,
                                nsISupports **aResult,
                                nsWrapperCache **aCache);
 
   virtual void ScriptLoading(nsIScriptElement *aScript);
   virtual void ScriptExecuted(nsIScriptElement *aScript);
 
   virtual void AddedForm();
   virtual void RemovedForm();
--- a/content/html/document/src/nsIHTMLDocument.h
+++ b/content/html/document/src/nsIHTMLDocument.h
@@ -50,18 +50,18 @@ class nsWrapperCache;
 
 namespace mozilla {
 namespace dom {
 class Element;
 } // namespace dom
 } // namespace mozilla
 
 #define NS_IHTMLDOCUMENT_IID \
-{ 0xe43a4bfd, 0xff5a, 0x40b0, \
-  { 0x8c, 0x31, 0x24, 0xac, 0xe8, 0x15, 0xda, 0xf2 } }
+{ 0x8cc90664, 0xb0fe, 0x4cdb, \
+ { 0xa2, 0xdd, 0x25, 0xcd, 0x8c, 0x2b, 0xfd, 0x08 } }
 
 
 /**
  * HTML document extensions to nsIDocument.
  */
 class nsIHTMLDocument : public nsISupports
 {
 public:
@@ -70,17 +70,17 @@ public:
   virtual mozilla::dom::Element* GetImageMap(const nsAString& aMapName) = 0;
 
   /**
    * Set compatibility mode for this document
    */
   virtual void SetCompatibilityMode(nsCompatibility aMode) = 0;
 
   virtual nsresult ResolveName(const nsAString& aName,
-                               nsIDOMHTMLFormElement *aForm,
+                               nsIContent *aForm,
                                nsISupports **aResult,
                                nsWrapperCache **aCache) = 0;
 
   /**
    * Called from the script loader to notify this document that a new
    * script is being loaded.
    */
   virtual void ScriptLoading(nsIScriptElement *aScript) = 0;
--- a/content/xbl/src/nsBindingManager.cpp
+++ b/content/xbl/src/nsBindingManager.cpp
@@ -88,42 +88,49 @@
 
 #define NS_ANONYMOUS_CONTENT_LIST_IID \
   { 0xa29df1f8, 0xaeca, 0x4356, \
     { 0xa8, 0xc2, 0xa7, 0x24, 0xa2, 0x11, 0x73, 0xac } }
 
 class nsAnonymousContentList : public nsINodeList
 {
 public:
-  nsAnonymousContentList(nsInsertionPointList* aElements);
+  nsAnonymousContentList(nsIContent *aContent, nsInsertionPointList* aElements);
   virtual ~nsAnonymousContentList();
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsAnonymousContentList, nsINodeList)
   // 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); }
   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)
 
-nsAnonymousContentList::nsAnonymousContentList(nsInsertionPointList* aElements)
-  : mElements(aElements)
+nsAnonymousContentList::nsAnonymousContentList(nsIContent *aContent,
+                                               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.
 }
 
 nsAnonymousContentList::~nsAnonymousContentList()
@@ -144,20 +151,22 @@ NS_INTERFACE_TABLE_HEAD(nsAnonymousConte
     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_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_END
@@ -705,17 +714,17 @@ nsBindingManager::SetContentListFor(nsIC
                                     nsInsertionPointList* aList)
 {
   if (mDestroyed) {
     return NS_OK;
   }
 
   nsAnonymousContentList* contentList = nsnull;
   if (aList) {
-    contentList = new nsAnonymousContentList(aList);
+    contentList = new nsAnonymousContentList(aContent, aList);
     if (!contentList) {
       delete aList;
       return NS_ERROR_OUT_OF_MEMORY;
     }
   }
 
   return SetOrRemoveObject(mContentListTable, aContent, contentList);
 }
@@ -769,17 +778,17 @@ nsBindingManager::SetAnonymousNodesFor(n
                                        nsInsertionPointList* aList)
 {
   if (mDestroyed) {
     return NS_OK;
   }
 
   nsAnonymousContentList* contentList = nsnull;
   if (aList) {
-    contentList = new nsAnonymousContentList(aList);
+    contentList = new nsAnonymousContentList(aContent, aList);
     if (!contentList) {
       delete aList;
       return NS_ERROR_OUT_OF_MEMORY;
     }
   }
 
   return SetOrRemoveObject(mAnonymousNodesTable, aContent, contentList);
 }
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -8217,29 +8217,29 @@ nsArraySH::GetProperty(nsIXPConnectWrapp
 
 
 // NodeList scriptable helper
 
 nsresult
 nsNodeListSH::PreCreate(nsISupports *nativeObj, JSContext *cx,
                         JSObject *globalObj, JSObject **parentObj)
 {
-  nsWrapperCache* cache = nsnull;
-  CallQueryInterface(nativeObj, &cache);
-  if (!cache) {
-    return nsDOMClassInfo::PreCreate(nativeObj, cx, globalObj, parentObj);
-  }
-
-  // nsChildContentList is the only class that uses nsNodeListSH and has a
-  // cached wrapper.
-  nsChildContentList *list = nsChildContentList::FromSupports(nativeObj);
-  nsINode *native_parent = list->GetParentObject();
-  if (!native_parent) {
-    return NS_ERROR_FAILURE;
-  }
+  nsINodeList* list = static_cast<nsINodeList*>(nativeObj);
+#ifdef DEBUG
+  {
+    nsCOMPtr<nsINodeList> list_qi = do_QueryInterface(nativeObj);
+
+    // If this assertion fires the QI implementation for the object in
+    // question doesn't use the nsINodeList pointer as the nsISupports
+    // pointer. That must be fixed, or we'll crash...
+    NS_ASSERTION(list_qi == list, "Uh, fix QI!");
+  }
+#endif
+
+  nsINode* native_parent = list->GetParentObject();
 
   nsresult rv =
     WrapNativeParent(cx, globalObj, native_parent, native_parent, parentObj);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_SUCCESS_ALLOW_SLIM_WRAPPERS;
 }
 
@@ -9421,23 +9421,22 @@ nsHTMLFormElementSH::FindNamedItem(nsIFo
   nsDependentJSString name(id);
 
   *aResult = aForm->ResolveName(name).get();
   // FIXME Get the wrapper cache from nsIForm::ResolveName
   *aCache = nsnull;
 
   if (!*aResult) {
     nsCOMPtr<nsIContent> content(do_QueryInterface(aForm));
-    nsCOMPtr<nsIDOMHTMLFormElement> form_element(do_QueryInterface(aForm));
 
     nsCOMPtr<nsIHTMLDocument> html_doc =
       do_QueryInterface(content->GetDocument());
 
-    if (html_doc && form_element) {
-      html_doc->ResolveName(name, form_element, aResult, aCache);
+    if (html_doc && content) {
+      html_doc->ResolveName(name, content, aResult, aCache);
     }
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsHTMLFormElementSH::NewResolve(nsIXPConnectWrappedNative *wrapper,