Fix for bug 460512 (Avoid AddRef/Release in scriptable helper methods for NodeList). r/sr=bz.
authorPeter Van der Beken <peterv@propagandism.org>
Wed, 22 Oct 2008 16:31:14 +0200
changeset 20752 9dafdb183b2b7ce2143a570a6a5b28c674dc0c57
parent 20751 ed515d20c255c15848a3c218c615ffe669fee9a2
child 20753 3d9dc59474792451d123c31c2a4517d56ceec65d
push idunknown
push userunknown
push dateunknown
bugs460512
milestone1.9.1b2pre
Fix for bug 460512 (Avoid AddRef/Release in scriptable helper methods for NodeList). r/sr=bz.
content/base/public/nsDOMFile.h
content/base/public/nsINodeList.h
content/base/src/Makefile.in
content/base/src/nsContentList.cpp
content/base/src/nsContentList.h
content/base/src/nsDOMAttribute.h
content/base/src/nsDOMAttributeMap.cpp
content/base/src/nsDOMAttributeMap.h
content/base/src/nsDOMFile.cpp
content/base/src/nsDocument.cpp
content/base/src/nsDocument.h
content/base/src/nsGenericDOMNodeList.cpp
content/base/src/nsGenericDOMNodeList.h
content/base/src/nsGenericElement.cpp
content/base/src/nsGenericElement.h
content/html/content/public/Makefile.in
content/html/content/public/nsIHTMLCollection.h
content/html/content/src/nsClientRect.cpp
content/html/content/src/nsClientRect.h
content/html/content/src/nsHTMLFormElement.cpp
content/html/content/src/nsHTMLSelectElement.cpp
content/html/content/src/nsHTMLSelectElement.h
content/html/content/src/nsHTMLTableElement.cpp
content/html/document/src/nsHTMLDocument.cpp
content/xbl/src/nsBindingManager.cpp
dom/public/idl/base/nsIDOMClientInformation.idl
dom/public/idl/offline/Makefile.in
dom/public/idl/offline/nsIDOMLoadStatusList.idl
dom/public/nsDOMClassInfoID.h
dom/src/base/Makefile.in
dom/src/base/nsDOMClassInfo.cpp
dom/src/base/nsDOMClassInfo.h
dom/src/base/nsGlobalWindow.h
dom/src/base/nsMimeTypeArray.cpp
dom/src/base/nsMimeTypeArray.h
dom/src/base/nsPluginArray.cpp
dom/src/base/nsPluginArray.h
dom/src/offline/nsDOMOfflineLoadStatusList.cpp
layout/style/Makefile.in
layout/style/nsCSSRules.cpp
layout/style/nsCSSRules.h
layout/style/nsCSSStyleRule.cpp
layout/style/nsCSSStyleSheet.cpp
layout/style/nsDOMCSSValueList.cpp
layout/style/nsDOMCSSValueList.h
layout/style/nsICSSRule.h
layout/style/nsICSSRuleList.h
layout/xul/base/src/tree/src/nsTreeColumns.cpp
layout/xul/base/src/tree/src/nsTreeColumns.h
--- a/content/base/public/nsDOMFile.h
+++ b/content/base/public/nsDOMFile.h
@@ -83,13 +83,35 @@ public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIDOMFILELIST
 
   PRBool Append(nsIDOMFile *aFile) { return mFiles.AppendObject(aFile); }
 
   PRBool Remove(PRUint32 aIndex) { return mFiles.RemoveObjectAt(aIndex); }
   void Clear() { return mFiles.Clear(); }
 
+  nsIDOMFile* GetItemAt(PRUint32 aIndex)
+  {
+    return mFiles.SafeObjectAt(aIndex);
+  }
+
+  static nsDOMFileList* FromSupports(nsISupports* aSupports)
+  {
+#ifdef DEBUG
+    {
+      nsCOMPtr<nsIDOMFileList> list_qi = do_QueryInterface(aSupports);
+
+      // If this assertion fires the QI implementation for the object in
+      // question doesn't use the nsIDOMFileList pointer as the nsISupports
+      // pointer. That must be fixed, or we'll crash...
+      NS_ASSERTION(list_qi == static_cast<nsIDOMFileList*>(aSupports),
+                   "Uh, fix QI!");
+    }
+#endif
+
+    return static_cast<nsDOMFileList*>(aSupports);
+  }
+
 private:
   nsCOMArray<nsIDOMFile> mFiles;
 };
 
 #endif
--- a/content/base/public/nsINodeList.h
+++ b/content/base/public/nsINodeList.h
@@ -34,27 +34,28 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef nsINodeList_h___
 #define nsINodeList_h___
 
 class nsINode;
+class nsIDOMNodeList;
 
 // IID for the nsINodeList interface
 #define NS_INODELIST_IID \
-{ 0x06a6639a, 0x2d47, 0x4551, \
- { 0x94, 0xef, 0x93, 0xb8, 0xe1, 0x09, 0x3a, 0xb3 } }
-
+{ 0x943420c4, 0x8774, 0x43ea, \
+ { 0xb3, 0x53, 0x62, 0xa1, 0x26, 0x1c, 0x9b, 0x55 } }
 
 /**
  * An internal interface that allows QI-less getting of nodes from node lists
  */
-class nsINodeList : public nsISupports {
+class nsINodeList : public nsIDOMNodeList
+{
 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 nsINode* GetNodeAt(PRUint32 aIndex) = 0;
 };
--- a/content/base/src/Makefile.in
+++ b/content/base/src/Makefile.in
@@ -130,17 +130,16 @@ CPPSRCS		= \
 		nsDOMParser.cpp \
 		nsDOMSerializer.cpp \
 		nsDocument.cpp \
 		nsDocumentEncoder.cpp \
 		nsDocumentFragment.cpp \
 		nsFrameLoader.cpp \
 		nsGenConImageContent.cpp \
 		nsGenericDOMDataNode.cpp \
-		nsGenericDOMNodeList.cpp \
 		nsGenericElement.cpp \
 		nsGkAtoms.cpp \
 		nsHTMLContentSerializer.cpp \
 		nsImageLoadingContent.cpp \
 		nsLineBreaker.cpp \
 		nsLoadListenerProxy.cpp \
 		nsMappedAttributeElement.cpp \
 		nsMappedAttributes.cpp \
--- a/content/base/src/nsContentList.cpp
+++ b/content/base/src/nsContentList.cpp
@@ -65,37 +65,33 @@ NS_NewPreContentIterator(nsIContentItera
 #define ASSERT_IN_SYNC AssertInSync()
 #else
 #define ASSERT_IN_SYNC PR_BEGIN_MACRO PR_END_MACRO
 #endif
 
 
 static nsContentList *gCachedContentList;
 
-nsBaseContentList::nsBaseContentList()
-{
-}
-
 nsBaseContentList::~nsBaseContentList()
 {
 }
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsBaseContentList)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsBaseContentList)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mElements)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsBaseContentList)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mElements)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 // QueryInterface implementation for nsBaseContentList
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsBaseContentList)
   NS_INTERFACE_MAP_ENTRY(nsINodeList)
   NS_INTERFACE_MAP_ENTRY(nsIDOMNodeList)
-  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMNodeList)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsINodeList)
   NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(NodeList)
 NS_INTERFACE_MAP_END
 
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsBaseContentList)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsBaseContentList)
 
 
--- a/content/base/src/nsContentList.h
+++ b/content/base/src/nsContentList.h
@@ -69,32 +69,30 @@ typedef PRBool (*nsContentListMatchFunc)
                                          void* aData);
 
 typedef void (*nsContentListDestroyFunc)(void* aData);
 
 class nsIDocument;
 class nsIDOMHTMLFormElement;
 
 
-class nsBaseContentList : public nsIDOMNodeList,
-                          public nsINodeList
+class nsBaseContentList : public nsINodeList
 {
 public:
-  nsBaseContentList();
   virtual ~nsBaseContentList();
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
 
   // nsIDOMNodeList
   NS_DECL_NSIDOMNODELIST
 
   // nsINodeList
   virtual nsINode* GetNodeAt(PRUint32 aIndex);
   
-  NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsBaseContentList, nsIDOMNodeList)
+  NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsBaseContentList, nsINodeList)
 
   void AppendElement(nsIContent *aContent);
   void RemoveElement(nsIContent *aContent);
   virtual PRInt32 IndexOf(nsIContent *aContent, PRBool aDoFlush);
   void Reset();
 
   static void Shutdown();
 
@@ -260,16 +258,32 @@ public:
   NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
   NS_DECL_NSIMUTATIONOBSERVER_NODEWILLBEDESTROYED
   
   static void OnDocumentDestroy(nsIDocument *aDocument);
 
+  static nsContentList* 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<nsContentList*>(list);
+  }
+
 protected:
   /**
    * Returns whether the content element matches our criterion
    *
    * @param  aContent the content to attempt to match
    * @return whether we match
    */
   PRBool Match(nsIContent *aContent);
--- a/content/base/src/nsDOMAttribute.h
+++ b/content/base/src/nsDOMAttribute.h
@@ -41,17 +41,16 @@
 
 #ifndef nsDOMAttribute_h___
 #define nsDOMAttribute_h___
 
 #include "nsIAttribute.h"
 #include "nsIDOMAttr.h"
 #include "nsIDOMText.h"
 #include "nsIDOMNodeList.h"
-#include "nsGenericDOMNodeList.h"
 #include "nsString.h"
 #include "nsCOMPtr.h"
 #include "nsINodeInfo.h"
 #include "nsIDOM3Node.h"
 #include "nsIDOM3Attr.h"
 #include "nsDOMAttributeMap.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsContentUtils.h"
--- a/content/base/src/nsDOMAttributeMap.cpp
+++ b/content/base/src/nsDOMAttributeMap.cpp
@@ -158,58 +158,69 @@ nsDOMAttributeMap::DropAttribute(PRInt32
     iAttr->SetMap(nsnull);
 
     // Remove from cache
     mAttributeCache.Remove(attr);
   }
 }
 
 nsresult
-nsDOMAttributeMap::GetAttribute(nsINodeInfo* aNodeInfo,
-                                nsIDOMNode** aReturn,
-                                PRBool aRemove)
+nsDOMAttributeMap::RemoveAttribute(nsINodeInfo* aNodeInfo, nsIDOMNode** aReturn)
 {
-  NS_ASSERTION(aNodeInfo, "GetAttribute() called with aNodeInfo == nsnull!");
-  NS_ASSERTION(aReturn, "GetAttribute() called with aReturn == nsnull");
+  NS_ASSERTION(aNodeInfo, "RemoveAttribute() called with aNodeInfo == nsnull!");
+  NS_ASSERTION(aReturn, "RemoveAttribute() called with aReturn == nsnull");
 
   *aReturn = nsnull;
 
   nsAttrKey attr(aNodeInfo->NamespaceID(), aNodeInfo->NameAtom());
 
   if (!mAttributeCache.Get(attr, aReturn)) {
     nsAutoString value;
-    if (aRemove) {
-      // As we are removing the attribute we need to set the current value in
-      // the attribute node.
-      mContent->GetAttr(aNodeInfo->NamespaceID(), aNodeInfo->NameAtom(), value);
-    }
-    nsCOMPtr<nsIDOMNode> newAttr = new nsDOMAttribute(aRemove ? nsnull : this,
-                                                      aNodeInfo, value);
+    // As we are removing the attribute we need to set the current value in
+    // the attribute node.
+    mContent->GetAttr(aNodeInfo->NamespaceID(), aNodeInfo->NameAtom(), value);
+    nsCOMPtr<nsIDOMNode> newAttr = new nsDOMAttribute(nsnull, aNodeInfo, value);
     if (!newAttr) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
-    if (!aRemove && !mAttributeCache.Put(attr, newAttr)) {
-      return NS_ERROR_OUT_OF_MEMORY;
-    }
     newAttr.swap(*aReturn);
   }
-  else if (aRemove) {
+  else {
     nsCOMPtr<nsIAttribute> iAttr(do_QueryInterface(*aReturn));
     NS_ASSERTION(iAttr, "non-nsIAttribute somehow made it into the hashmap?!");
 
     // Break link to map
     iAttr->SetMap(nsnull);
 
     // Remove from cache
     mAttributeCache.Remove(attr);
   }
 
   return NS_OK;
 }
 
+nsIDOMNode*
+nsDOMAttributeMap::GetAttribute(nsINodeInfo* aNodeInfo)
+{
+  NS_ASSERTION(aNodeInfo, "GetAttribute() called with aNodeInfo == nsnull!");
+
+  nsAttrKey attr(aNodeInfo->NamespaceID(), aNodeInfo->NameAtom());
+
+  nsIDOMNode* node = mAttributeCache.GetWeak(attr);
+  if (!node) {
+    nsCOMPtr<nsIDOMNode> newAttr =
+      new nsDOMAttribute(this, aNodeInfo, EmptyString());
+    if (newAttr && mAttributeCache.Put(attr, newAttr)) {
+      node = newAttr;
+    }
+  }
+
+  return node;
+}
+
 NS_IMETHODIMP
 nsDOMAttributeMap::GetNamedItem(const nsAString& aAttrName,
                                 nsIDOMNode** aAttribute)
 {
   NS_ENSURE_ARG_POINTER(aAttribute);
   *aAttribute = nsnull;
 
   nsresult rv = NS_OK;
@@ -289,27 +300,27 @@ nsDOMAttributeMap::SetNamedItemInternal(
     nsCOMPtr<nsINodeInfo> ni;
 
     // SetNamedItemNS()
     if (aWithNS) {
       // Return existing attribute, if present
       ni = iAttribute->NodeInfo();
 
       if (mContent->HasAttr(ni->NamespaceID(), ni->NameAtom())) {
-        rv = GetAttribute(ni, getter_AddRefs(tmpReturn), PR_TRUE);
+        rv = RemoveAttribute(ni, getter_AddRefs(tmpReturn));
         NS_ENSURE_SUCCESS(rv, rv);
       }
     }
     else { // SetNamedItem()
       attribute->GetName(name);
 
       // get node-info of old attribute
       ni = mContent->GetExistingAttrNameFromQName(name);
       if (ni) {
-        rv = GetAttribute(ni, getter_AddRefs(tmpReturn), PR_TRUE);
+        rv = RemoveAttribute(ni, getter_AddRefs(tmpReturn));
         NS_ENSURE_SUCCESS(rv, rv);
       }
       else {
         rv = mContent->NodeInfo()->NodeInfoManager()->
           GetNodeInfo(name, nsnull, kNameSpaceID_None, getter_AddRefs(ni));
         NS_ENSURE_SUCCESS(rv, rv);
         // value is already empty
       }
@@ -369,36 +380,47 @@ nsDOMAttributeMap::RemoveNamedItem(const
     // This removes the attribute node from the attribute map.
     rv = mContent->UnsetAttr(ni->NamespaceID(), ni->NameAtom(), PR_TRUE);
   }
 
   return rv;
 }
 
 
-NS_IMETHODIMP
-nsDOMAttributeMap::Item(PRUint32 aIndex, nsIDOMNode** aReturn)
+nsIDOMNode*
+nsDOMAttributeMap::GetItemAt(PRUint32 aIndex, nsresult *aResult)
 {
-  NS_ENSURE_ARG_POINTER(aReturn);
+  *aResult = NS_OK;
+
+  nsIDOMNode* node = nsnull;
 
   const nsAttrName* name;
   if (mContent && (name = mContent->GetAttrNameAt(aIndex))) {
     // Don't use the nodeinfo even if one exists since it can
     // have the wrong owner document.
     nsCOMPtr<nsINodeInfo> ni;
     ni = mContent->NodeInfo()->NodeInfoManager()->
       GetNodeInfo(name->LocalName(), name->GetPrefix(), name->NamespaceID());
-    NS_ENSURE_TRUE(ni, NS_ERROR_OUT_OF_MEMORY);
-
-    return GetAttribute(ni, aReturn);
+    if (ni) {
+      node = GetAttribute(ni);
+    }
+    if (!node) {
+      *aResult = NS_ERROR_OUT_OF_MEMORY;
+    }
   }
 
-  *aReturn = nsnull;
+  return node;
+}
 
-  return NS_OK;
+NS_IMETHODIMP
+nsDOMAttributeMap::Item(PRUint32 aIndex, nsIDOMNode** aReturn)
+{
+  nsresult rv;
+  NS_IF_ADDREF(*aReturn = GetItemAt(aIndex, &rv));
+  return rv;
 }
 
 nsresult
 nsDOMAttributeMap::GetLength(PRUint32 *aLength)
 {
   NS_ENSURE_ARG_POINTER(aLength);
 
   if (mContent) {
@@ -452,17 +474,17 @@ nsDOMAttributeMap::GetNamedItemNSInterna
 
     if (nameSpaceID == attrNS &&
         nameAtom->EqualsUTF8(utf8Name)) {
       nsCOMPtr<nsINodeInfo> ni;
       ni = mContent->NodeInfo()->NodeInfoManager()->
         GetNodeInfo(nameAtom, name->GetPrefix(), nameSpaceID);
       NS_ENSURE_TRUE(ni, NS_ERROR_OUT_OF_MEMORY);
 
-      return GetAttribute(ni, aReturn, aRemove);
+      return aRemove ? RemoveAttribute(ni, aReturn) : GetAttribute(ni, aReturn);
     }
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMAttributeMap::RemoveNamedItemNS(const nsAString& aNamespaceURI,
--- a/content/base/src/nsDOMAttributeMap.h
+++ b/content/base/src/nsDOMAttributeMap.h
@@ -43,16 +43,17 @@
 #ifndef nsDOMAttributeMap_h___
 #define nsDOMAttributeMap_h___
 
 #include "nsIDOMNamedNodeMap.h"
 #include "nsString.h"
 #include "nsInterfaceHashtable.h"
 #include "nsCycleCollectionParticipant.h"
 #include "prbit.h"
+#include "nsIDOMNode.h"
 
 class nsIAtom;
 class nsIContent;
 class nsDOMAttribute;
 class nsINodeInfo;
 class nsIDocument;
 
 /**
@@ -164,16 +165,35 @@ public:
   /**
    * Enumerates over the attribute nodess in the map and calls aFunc for each
    * one. If aFunc returns PL_DHASH_STOP we'll stop enumerating at that point.
    *
    * @return The number of attribute nodes that aFunc was called for.
    */
   PRUint32 Enumerate(AttrCache::EnumReadFunction aFunc, void *aUserArg) const;
 
+  nsIDOMNode* GetItemAt(PRUint32 aIndex, nsresult *rv);
+
+  static nsDOMAttributeMap* FromSupports(nsISupports* aSupports)
+  {
+#ifdef DEBUG
+    {
+      nsCOMPtr<nsIDOMNamedNodeMap> map_qi = do_QueryInterface(aSupports);
+
+      // If this assertion fires the QI implementation for the object in
+      // question doesn't use the nsIDOMNamedNodeMap pointer as the nsISupports
+      // pointer. That must be fixed, or we'll crash...
+      NS_ASSERTION(map_qi == static_cast<nsIDOMNamedNodeMap*>(aSupports),
+                   "Uh, fix QI!");
+    }
+#endif
+
+    return static_cast<nsDOMAttributeMap*>(aSupports);
+  }
+
   NS_DECL_CYCLE_COLLECTION_CLASS(nsDOMAttributeMap)
 
 private:
   nsIContent* mContent; // Weak reference
 
   /**
    * Cache of nsDOMAttributes.
    */
@@ -196,14 +216,31 @@ private:
                                   nsIDOMNode** aReturn,
                                   PRBool aRemove = PR_FALSE);
 
   /**
    * Returns an attribute, either by retrieving it from the cache or by
    * creating a new one.
    */
   nsresult GetAttribute(nsINodeInfo*     aNodeInfo,
-                        nsIDOMNode**     aReturn,
-                        PRBool aRemove = PR_FALSE);
+                        nsIDOMNode**     aReturn)
+  {
+    *aReturn = GetAttribute(aNodeInfo);
+    if (!*aReturn) {
+      return NS_ERROR_OUT_OF_MEMORY;
+    }
+
+    NS_ADDREF(*aReturn);
+
+    return NS_OK;
+  }
+
+  nsIDOMNode* GetAttribute(nsINodeInfo*     aNodeInfo);
+
+  /**
+   * Remove an attribute, returns the removed node.
+   */
+  nsresult RemoveAttribute(nsINodeInfo*     aNodeInfo,
+                           nsIDOMNode**     aReturn);
 };
 
 
 #endif /* nsDOMAttributeMap_h___ */
--- a/content/base/src/nsDOMFile.cpp
+++ b/content/base/src/nsDOMFile.cpp
@@ -381,12 +381,12 @@ nsDOMFileList::GetLength(PRUint32* aLeng
   *aLength = mFiles.Count();
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMFileList::Item(PRUint32 aIndex, nsIDOMFile **aFile)
 {
-  NS_IF_ADDREF(*aFile = mFiles.SafeObjectAt(aIndex));
+  NS_IF_ADDREF(*aFile = GetItemAt(aIndex));
 
   return NS_OK;
 }
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -611,30 +611,40 @@ nsDOMStyleSheetList::GetLength(PRUint32*
   }
   else {
     *aLength = 0;
   }
 
   return NS_OK;
 }
 
+nsIStyleSheet*
+nsDOMStyleSheetList::GetItemAt(PRUint32 aIndex)
+{
+  if (!mDocument || aIndex >= (PRUint32)mDocument->GetNumberOfStyleSheets()) {
+    return nsnull;
+  }
+
+  nsIStyleSheet *sheet = mDocument->GetStyleSheetAt(aIndex);
+  NS_ASSERTION(sheet, "Must have a sheet");
+
+  return sheet;
+}
+
 NS_IMETHODIMP
 nsDOMStyleSheetList::Item(PRUint32 aIndex, nsIDOMStyleSheet** aReturn)
 {
-  *aReturn = nsnull;
-  if (mDocument) {
-    PRInt32 count = mDocument->GetNumberOfStyleSheets();
-    if (aIndex < (PRUint32)count) {
-      nsIStyleSheet *sheet = mDocument->GetStyleSheetAt(aIndex);
-      NS_ASSERTION(sheet, "Must have a sheet");
-      return CallQueryInterface(sheet, aReturn);
-    }
-  }
-
-  return NS_OK;
+  nsIStyleSheet *sheet = GetItemAt(aIndex);
+  if (!sheet) {
+      *aReturn = nsnull;
+
+      return NS_OK;
+  }
+
+  return CallQueryInterface(sheet, aReturn);
 }
 
 void
 nsDOMStyleSheetList::NodeWillBeDestroyed(const nsINode *aNode)
 {
   mDocument = nsnull;
 }
 
--- a/content/base/src/nsDocument.h
+++ b/content/base/src/nsDocument.h
@@ -363,16 +363,34 @@ public:
   virtual void NodeWillBeDestroyed(const nsINode *aNode);
   virtual void StyleSheetAdded(nsIDocument *aDocument,
                                nsIStyleSheet* aStyleSheet,
                                PRBool aDocumentSheet);
   virtual void StyleSheetRemoved(nsIDocument *aDocument,
                                  nsIStyleSheet* aStyleSheet,
                                  PRBool aDocumentSheet);
 
+  nsIStyleSheet* GetItemAt(PRUint32 aIndex);
+
+  static nsDOMStyleSheetList* FromSupports(nsISupports* aSupports)
+  {
+    nsIDOMStyleSheetList* list = static_cast<nsIDOMStyleSheetList*>(aSupports);
+#ifdef DEBUG
+    {
+      nsCOMPtr<nsIDOMStyleSheetList> list_qi = do_QueryInterface(aSupports);
+
+      // If this assertion fires the QI implementation for the object in
+      // question doesn't use the nsIDOMStyleSheetList 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<nsDOMStyleSheetList*>(list);
+  }
+
 protected:
   PRInt32       mLength;
   nsIDocument*  mDocument;
 };
 
 class nsOnloadBlocker : public nsIRequest
 {
 public:
deleted file mode 100644
--- a/content/base/src/nsGenericDOMNodeList.cpp
+++ /dev/null
@@ -1,77 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Mozilla Communicator client code.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either of the GNU General Public License Version 2 or later (the "GPL"),
- * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-/*
- * A base class for simple DOM NodeLists which implements nsISupports
- * and expects subclasess to implement GetLength() and Item()
- */
-
-#include "nsGenericDOMNodeList.h"
-#include "nsGenericElement.h"
-
-nsGenericDOMNodeList::nsGenericDOMNodeList() 
-{
-}
-
-nsGenericDOMNodeList::~nsGenericDOMNodeList()
-{
-}
-
-
-NS_IMPL_ADDREF(nsGenericDOMNodeList)
-NS_IMPL_RELEASE(nsGenericDOMNodeList)
-
-
-// QueryInterface implementation for nsGenericDOMNodeList
-NS_INTERFACE_MAP_BEGIN(nsGenericDOMNodeList)
-  NS_INTERFACE_MAP_ENTRY(nsINodeList)
-  NS_INTERFACE_MAP_ENTRY(nsIDOMNodeList)
-  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMNodeList)
-  NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(NodeList)
-NS_INTERFACE_MAP_END
-
-NS_IMETHODIMP
-nsGenericDOMNodeList::Item(PRUint32 aIndex, nsIDOMNode** aReturn)
-{
-  nsINode* node = GetNodeAt(aIndex);
-  if (!node) {
-    *aReturn = nsnull;
-    return NS_OK;
-  }
-
-  return CallQueryInterface(node, aReturn);
-}
deleted file mode 100644
--- a/content/base/src/nsGenericDOMNodeList.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Mozilla Communicator client code.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either of the GNU General Public License Version 2 or later (the "GPL"),
- * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-/*
- * A base class for simple DOM NodeLists which implements nsISupports and Item()
- * and expects subclasess to implement GetLength() and GetNodeAt()
- */
-
-// XXXbz we don't use this for much... should we be using it more, or
-// just nix it?
-
-#ifndef nsGenericDOMNodeList_h__
-#define nsGenericDOMNodeList_h__
-
-#include "nsISupports.h"
-#include "nsIDOMNodeList.h"
-#include "nsINodeList.h"
-
-class nsGenericDOMNodeList : public nsIDOMNodeList,
-                             public nsINodeList
-{
-public:
-  nsGenericDOMNodeList();
-  virtual ~nsGenericDOMNodeList();
-
-  NS_DECL_ISUPPORTS
-
-  NS_IMETHOD    Item(PRUint32 aIndex, nsIDOMNode** aReturn);
-
-  // The following need to be defined in the subclass
-  // nsIDOMNodeList interface
-  NS_IMETHOD    GetLength(PRUint32* aLength)=0;
-
-  // nsINodeList interface
-  virtual nsINode* GetNodeAt(PRUint32 aIndex) = 0;
-};
-
-#endif // nsGenericDOMNodeList_h__
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -451,29 +451,47 @@ nsIContent::FindFirstNonNativeAnonymous(
       return const_cast<nsIContent*>(content);
     }
   }
   return nsnull;
 }
 
 //----------------------------------------------------------------------
 
-nsChildContentList::~nsChildContentList()
-{
-  MOZ_COUNT_DTOR(nsChildContentList);
-}
+NS_IMPL_ADDREF(nsChildContentList)
+NS_IMPL_RELEASE(nsChildContentList)
+
+NS_INTERFACE_MAP_BEGIN(nsChildContentList)
+  NS_INTERFACE_MAP_ENTRY(nsINodeList)
+  NS_INTERFACE_MAP_ENTRY(nsIDOMNodeList)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsINodeList)
+  NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(NodeList)
+NS_INTERFACE_MAP_END
 
 NS_IMETHODIMP
 nsChildContentList::GetLength(PRUint32* aLength)
 {
   *aLength = mNode ? mNode->GetChildCount() : 0;
 
   return NS_OK;
 }
 
+NS_IMETHODIMP
+nsChildContentList::Item(PRUint32 aIndex, nsIDOMNode** aReturn)
+{
+  nsINode* node = GetNodeAt(aIndex);
+  if (!node) {
+    *aReturn = nsnull;
+
+    return NS_OK;
+  }
+
+  return CallQueryInterface(node, aReturn);
+}
+
 nsINode*
 nsChildContentList::GetNodeAt(PRUint32 aIndex)
 {
   if (mNode) {
     return mNode->GetChildAt(aIndex);
   }
 
   return nsnull;
--- a/content/base/src/nsGenericElement.h
+++ b/content/base/src/nsGenericElement.h
@@ -50,17 +50,16 @@
 #include "nsIDOMElement.h"
 #include "nsIDOMDocumentFragment.h"
 #include "nsIDOMEventTarget.h"
 #include "nsIDOM3EventTarget.h"
 #include "nsIDOM3Node.h"
 #include "nsIDOMNSEventTarget.h"
 #include "nsIDOMNSElement.h"
 #include "nsILinkHandler.h"
-#include "nsGenericDOMNodeList.h"
 #include "nsContentUtils.h"
 #include "nsNodeUtils.h"
 #include "nsAttrAndChildArray.h"
 #include "mozFlushType.h"
 #include "nsDOMAttributeMap.h"
 #include "nsIWeakReference.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsIDocument.h"
@@ -85,28 +84,28 @@ struct nsRect;
 typedef unsigned long 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 nsGenericDOMNodeList 
+class nsChildContentList : public nsINodeList
 {
 public:
   nsChildContentList(nsINode* aNode)
     : mNode(aNode)
   {
-    MOZ_COUNT_CTOR(nsChildContentList);
   }
-  virtual ~nsChildContentList();
+
+  NS_DECL_ISUPPORTS
 
   // nsIDOMNodeList interface
-  NS_IMETHOD GetLength(PRUint32* aLength);
+  NS_DECL_NSIDOMNODELIST
 
   // nsINodeList interface
   virtual nsINode* GetNodeAt(PRUint32 aIndex);  
   
   void DropReference()
   {
     mNode = nsnull;
   }
--- a/content/html/content/public/Makefile.in
+++ b/content/html/content/public/Makefile.in
@@ -62,12 +62,13 @@ EXPORTS		= \
 		nsIRadioGroupContainer.h \
 		nsITextControlElement.h \
 		nsIFileControlElement.h \
 		nsIFormSubmission.h \
 		nsIFrameSetElement.h \
 		nsHTMLAudioElement.h \
 		nsHTMLMediaElement.h \
 		nsHTMLVideoElement.h \
+		nsIHTMLCollection.h \
                 $(NULL)
 
 include $(topsrcdir)/config/rules.mk
 
new file mode 100644
--- /dev/null
+++ b/content/html/content/public/nsIHTMLCollection.h
@@ -0,0 +1,65 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla DOM code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *         Peter Van der Beken <peterv@propagandism.org> (Original Author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsIHTMLCollection_h___
+#define nsIHTMLCollection_h___
+
+#include "nsIDOMHTMLCollection.h";
+
+// IID for the nsIHTMLCollection interface
+#define NS_IHTMLCOLLECTION_IID \
+{ 0xb90f2c8c, 0xc564, 0x4464, \
+ { 0x97, 0x01, 0x05, 0x14, 0xe4, 0xeb, 0x69, 0x65 } }
+
+/**
+ * An internal interface that allows QI-less getting of nodes from HTML
+ * collections
+ */
+class nsIHTMLCollection : public nsIDOMHTMLCollection
+{
+public:
+  NS_DECLARE_STATIC_IID_ACCESSOR(NS_IHTMLCOLLECTION_IID)
+
+  /**
+   * Get the node at the index.  Returns null if the index is out of bounds
+   */
+  virtual nsISupports* GetNodeAt(PRUint32 aIndex, nsresult* aResult) = 0;
+};
+
+NS_DEFINE_STATIC_IID_ACCESSOR(nsIHTMLCollection, NS_IHTMLCOLLECTION_IID)
+
+#endif /* nsIHTMLCollection_h___ */
--- a/content/html/content/src/nsClientRect.cpp
+++ b/content/html/content/src/nsClientRect.cpp
@@ -113,22 +113,17 @@ nsClientRectList::GetLength(PRUint32* aL
 {
   *aLength = mArray.Count();
   return NS_OK;
 }
 
 NS_IMETHODIMP    
 nsClientRectList::Item(PRUint32 aIndex, nsIDOMClientRect** aReturn)
 {
-  if (aIndex >= PRUint32(mArray.Count())) {
-    *aReturn = nsnull;
-    return NS_OK;
-  } 
-  
-  NS_IF_ADDREF(*aReturn = mArray.ObjectAt(aIndex));
+  NS_IF_ADDREF(*aReturn = GetItemAt(aIndex));
   return NS_OK;
 }
 
 static double
 RoundFloat(double aValue)
 {
   return floor(aValue + 0.5);
 }
--- a/content/html/content/src/nsClientRect.h
+++ b/content/html/content/src/nsClientRect.h
@@ -38,16 +38,17 @@
 
 #ifndef NSCLIENTRECT_H_
 #define NSCLIENTRECT_H_
 
 #include "nsIDOMClientRect.h"
 #include "nsIDOMClientRectList.h"
 #include "nsCOMArray.h"
 #include "nsRect.h"
+#include "nsCOMPtr.h"
 
 class nsPresContext;
 
 class nsClientRect : public nsIDOMClientRect
 {
 public:
   NS_DECL_ISUPPORTS
 
@@ -71,15 +72,37 @@ public:
   nsClientRectList() {}
 
   NS_DECL_ISUPPORTS
 
   NS_DECL_NSIDOMCLIENTRECTLIST
   
   void Append(nsIDOMClientRect* aElement) { mArray.AppendObject(aElement); }
 
+  nsIDOMClientRect* GetItemAt(PRUint32 aIndex)
+  {
+    return mArray.SafeObjectAt(aIndex);
+  }
+
+  static nsClientRectList* FromSupports(nsISupports* aSupports)
+  {
+#ifdef DEBUG
+    {
+      nsCOMPtr<nsIDOMClientRectList> list_qi = do_QueryInterface(aSupports);
+
+      // If this assertion fires the QI implementation for the object in
+      // question doesn't use the nsIDOMClientRectList pointer as the nsISupports
+      // pointer. That must be fixed, or we'll crash...
+      NS_ASSERTION(list_qi == static_cast<nsIDOMClientRectList*>(aSupports),
+                   "Uh, fix QI!");
+    }
+#endif
+
+    return static_cast<nsClientRectList*>(aSupports);
+  }
+
 protected:
   virtual ~nsClientRectList() {}
 
   nsCOMArray<nsIDOMClientRect> mArray;
 };
 
 #endif /*NSCLIENTRECT_H_*/
--- a/content/html/content/src/nsHTMLFormElement.cpp
+++ b/content/html/content/src/nsHTMLFormElement.cpp
@@ -83,16 +83,17 @@
 #include "nsIRadioGroupContainer.h"
 
 #include "nsLayoutUtils.h"
 
 #include "nsUnicharUtils.h"
 #include "nsEventDispatcher.h"
 
 #include "mozAutoDocUpdate.h"
+#include "nsIHTMLCollection.h"
 
 static const int NS_FORM_CONTROL_LIST_HASHTABLE_SIZE = 16;
 
 class nsFormControlList;
 
 /**
  * hashkey wrapper using nsAString KeyType
  *
@@ -343,17 +344,17 @@ protected:
 };
 
 PRBool nsHTMLFormElement::gFirstFormSubmitted = PR_FALSE;
 PRBool nsHTMLFormElement::gPasswordManagerInitialized = PR_FALSE;
 
 
 // nsFormControlList
 class nsFormControlList : public nsIDOMNSHTMLFormControlList,
-                          public nsIDOMHTMLCollection
+                          public nsIHTMLCollection
 {
 public:
   nsFormControlList(nsHTMLFormElement* aForm);
   virtual ~nsFormControlList();
 
   nsresult Init();
 
   void DropFormReference();
@@ -361,16 +362,25 @@ public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
 
   // nsIDOMHTMLCollection interface
   NS_DECL_NSIDOMHTMLCOLLECTION
 
   // nsIDOMNSHTMLFormControlList interface
   NS_DECL_NSIDOMNSHTMLFORMCONTROLLIST
 
+  virtual nsISupports* GetNodeAt(PRUint32 aIndex, nsresult* aResult)
+  {
+    FlushPendingNotifications();
+
+    *aResult = NS_OK;
+
+    return mElements.SafeElementAt(aIndex, nsnull);
+  }
+
   nsresult AddElementToTable(nsIFormControl* aChild,
                              const nsAString& aName);
   nsresult RemoveElementFromTable(nsIFormControl* aChild,
                                   const nsAString& aName);
   nsresult IndexOfControl(nsIFormControl* aControl,
                           PRInt32* aIndex);
 
   void NamedItemInternal(const nsAString& aName, PRBool aFlushContent,
@@ -393,18 +403,17 @@ public:
 
   // 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<nsIFormControl*> mNotInElements; // Holds WEAK references
 
-  NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsFormControlList,
-                                           nsIDOMHTMLCollection)
+  NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsFormControlList, nsIHTMLCollection)
 
 protected:
   // Drop all our references to the form elements
   void Clear();
 
   // Flush out the content model so it's up to date.
   void FlushPendingNotifications();
   
@@ -2107,51 +2116,51 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ns
   tmp->Clear();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsFormControlList)
   tmp->mNameLookupTable.EnumerateRead(ControlTraverser, &cb);
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 // XPConnect interface list for nsFormControlList
 NS_INTERFACE_TABLE_HEAD(nsFormControlList)
-  NS_INTERFACE_TABLE2(nsFormControlList,
+  NS_INTERFACE_TABLE3(nsFormControlList,
+                      nsIHTMLCollection,
                       nsIDOMHTMLCollection,
                       nsIDOMNSHTMLFormControlList)
   NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(nsFormControlList)
   NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(HTMLFormControlCollection)
 NS_INTERFACE_MAP_END
 
 
-NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsFormControlList,
-                                          nsIDOMHTMLCollection)
-NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS(nsFormControlList,
-                                           nsIDOMHTMLCollection)
+NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsFormControlList, nsIHTMLCollection)
+NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS(nsFormControlList, nsIHTMLCollection)
 
 
 // nsIDOMHTMLCollection interface
 
 NS_IMETHODIMP    
 nsFormControlList::GetLength(PRUint32* aLength)
 {
   FlushPendingNotifications();
   *aLength = mElements.Length();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsFormControlList::Item(PRUint32 aIndex, nsIDOMNode** aReturn)
 {
-  FlushPendingNotifications();
+  nsresult rv;
+  nsISupports* item = GetNodeAt(aIndex, &rv);
+  if (!item) {
+    *aReturn = nsnull;
 
-  if (aIndex < mElements.Length()) {
-    return CallQueryInterface(mElements[aIndex], aReturn);
+    return rv;
   }
 
-  *aReturn = nsnull;
-  return NS_OK;
+  return CallQueryInterface(item, aReturn);
 }
 
 NS_IMETHODIMP 
 nsFormControlList::NamedItem(const nsAString& aName,
                              nsIDOMNode** aReturn)
 {
   FlushPendingNotifications();
 
--- a/content/html/content/src/nsHTMLSelectElement.cpp
+++ b/content/html/content/src/nsHTMLSelectElement.cpp
@@ -1840,29 +1840,30 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsHTMLOptionCollection)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mElements)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 // nsISupports
 
 // QueryInterface implementation for nsHTMLOptionCollection
 NS_INTERFACE_TABLE_HEAD(nsHTMLOptionCollection)
-  NS_INTERFACE_TABLE3(nsHTMLOptionCollection,
+  NS_INTERFACE_TABLE4(nsHTMLOptionCollection,
+                      nsIHTMLCollection,
                       nsIDOMNSHTMLOptionCollection,
                       nsIDOMHTMLOptionsCollection,
                       nsIDOMHTMLCollection)
   NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(nsHTMLOptionCollection)
   NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(HTMLOptionsCollection)
 NS_INTERFACE_MAP_END
 
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsHTMLOptionCollection,
-                                          nsIDOMNSHTMLOptionCollection)
+                                          nsIHTMLCollection)
 NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS(nsHTMLOptionCollection,
-                                           nsIDOMNSHTMLOptionCollection)
+                                           nsIHTMLCollection)
 
 
 // nsIDOMNSHTMLOptionCollection interface
 
 NS_IMETHODIMP
 nsHTMLOptionCollection::GetLength(PRUint32* aLength)
 {
   *aLength = mElements.Count();
@@ -1942,21 +1943,25 @@ nsHTMLOptionCollection::SetSelectedIndex
   NS_ENSURE_TRUE(mSelect, NS_ERROR_UNEXPECTED);
 
   return mSelect->SetSelectedIndex(aSelectedIndex);
 }
 
 NS_IMETHODIMP
 nsHTMLOptionCollection::Item(PRUint32 aIndex, nsIDOMNode** aReturn)
 {
-  nsIDOMHTMLOptionElement *option = mElements.SafeObjectAt(aIndex);
+  nsresult rv;
+  nsISupports* item = GetNodeAt(aIndex, &rv);
+  if (!item) {
+    *aReturn = nsnull;
 
-  NS_IF_ADDREF(*aReturn = option);
+    return rv;
+  }
 
-  return NS_OK;
+  return CallQueryInterface(item, aReturn);
 }
 
 NS_IMETHODIMP
 nsHTMLOptionCollection::NamedItem(const nsAString& aName,
                                   nsIDOMNode** aReturn)
 {
   PRInt32 count = mElements.Count();
   nsresult rv = NS_OK;
--- a/content/html/content/src/nsHTMLSelectElement.h
+++ b/content/html/content/src/nsHTMLSelectElement.h
@@ -44,21 +44,21 @@
 #include "nsCOMArray.h"
 #include "nsGenericHTMLElement.h"
 #include "nsISelectElement.h"
 #include "nsIDOMHTMLSelectElement.h"
 #include "nsIDOMNSHTMLSelectElement.h"
 #include "nsIDOMNSXBLFormControl.h"
 #include "nsIDOMHTMLFormElement.h"
 #include "nsIDOMHTMLOptionElement.h"
-#include "nsIDOMHTMLCollection.h"
 #include "nsIDOMHTMLOptionsCollection.h"
 #include "nsIDOMNSHTMLOptionCollectn.h"
 #include "nsISelectControlFrame.h"
 #include "nsContentUtils.h"
+#include "nsIHTMLCollection.h"
 
 // PresState
 #include "nsXPCOM.h"
 #include "nsPresState.h"
 #include "nsIComponentManager.h"
 #include "nsCheapSets.h"
 #include "nsLayoutErrors.h"
 
@@ -66,35 +66,42 @@
 class nsHTMLSelectElement;
 
 /**
  * The collection of options in the select (what you get back when you do
  * select.options in DOM)
  */
 class nsHTMLOptionCollection: public nsIDOMHTMLOptionsCollection,
                               public nsIDOMNSHTMLOptionCollection,
-                              public nsIDOMHTMLCollection
+                              public nsIHTMLCollection
 {
 public:
   nsHTMLOptionCollection(nsHTMLSelectElement* aSelect);
   virtual ~nsHTMLOptionCollection();
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
 
   // nsIDOMHTMLOptionsCollection interface
   NS_DECL_NSIDOMHTMLOPTIONSCOLLECTION
 
   // nsIDOMNSHTMLOptionCollection interface
   NS_DECL_NSIDOMNSHTMLOPTIONCOLLECTION
 
   // nsIDOMHTMLCollection interface, all its methods are defined in
   // nsIDOMHTMLOptionsCollection
 
+  virtual nsISupports* GetNodeAt(PRUint32 aIndex, nsresult* aResult)
+  {
+    *aResult = NS_OK;
+
+    return mElements.SafeObjectAt(aIndex);
+  }
+
   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsHTMLOptionCollection,
-                                           nsIDOMNSHTMLOptionCollection)
+                                           nsIHTMLCollection)
 
   // Helpers for nsHTMLSelectElement
   /**
    * Insert an option
    * @param aOption the option to insert
    * @param aIndex the index to insert at
    */
   PRBool InsertOptionAt(nsIDOMHTMLOptionElement* aOption, PRInt32 aIndex)
--- a/content/html/content/src/nsHTMLTableElement.cpp
+++ b/content/html/content/src/nsHTMLTableElement.cpp
@@ -49,16 +49,17 @@
 #include "nsHTMLParts.h"
 #include "nsRuleData.h"
 #include "nsStyleContext.h"
 #include "nsIDocument.h"
 
 /* for collections */
 #include "nsIDOMElement.h"
 #include "nsGenericHTMLElement.h"
+#include "nsIHTMLCollection.h"
 /* end for collections */
 
 class TableRowsCollection;
 
 class nsHTMLTableElement :  public nsGenericHTMLElement,
                             public nsIDOMHTMLTableElement
 {
 public:
@@ -100,27 +101,29 @@ protected:
 };
 
 
 /* ------------------------------ 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 nsIDOMHTMLCollection 
+class TableRowsCollection : public nsIHTMLCollection 
 {
 public:
   TableRowsCollection(nsHTMLTableElement *aParent);
   virtual ~TableRowsCollection();
 
   nsresult Init();
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_NSIDOMHTMLCOLLECTION
 
+  virtual nsISupports* GetNodeAt(PRUint32 aIndex, nsresult* aResult);
+
   NS_IMETHOD    ParentDestroyed();
 
   NS_DECL_CYCLE_COLLECTION_CLASS(TableRowsCollection)
 
 protected:
   // Those rows that are not in table sections
   nsRefPtr<nsContentList> mOrphanRows;  
   nsHTMLTableElement * mParent;
@@ -167,67 +170,80 @@ TableRowsCollection::Init()
 }
 
 // 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
 // rowgroup's rows will be in the nsIDOMHTMLCollection* named "rows".  Note
 // that this may be null at any time.  This macro assumes an nsresult named
 // |rv| is in scope.
 #define DO_FOR_EACH_ROWGROUP(_code)                                  \
-  PR_BEGIN_MACRO                                                     \
+  do {                                                               \
     if (mParent) {                                                   \
       /* THead */                                                    \
       nsCOMPtr<nsIDOMHTMLTableSectionElement> rowGroup;              \
       rv = mParent->GetTHead(getter_AddRefs(rowGroup));              \
-      NS_ENSURE_SUCCESS(rv, rv);                                     \
+      if (NS_FAILED(rv)) {                                           \
+        break;                                                       \
+      }                                                              \
       nsCOMPtr<nsIDOMHTMLCollection> rows;                           \
       if (rowGroup) {                                                \
         rowGroup->GetRows(getter_AddRefs(rows));                     \
         do { /* gives scoping */                                     \
           _code                                                      \
         } while (0);                                                 \
       }                                                              \
       nsCOMPtr<nsIDOMHTMLCollection> _tbodies;                       \
       /* TBodies */                                                  \
       rv = mParent->GetTBodies(getter_AddRefs(_tbodies));            \
-      NS_ENSURE_SUCCESS(rv, rv);                                     \
+      if (NS_FAILED(rv)) {                                           \
+        break;                                                       \
+      }                                                              \
       if (_tbodies) {                                                \
         nsCOMPtr<nsIDOMNode> _node;                                  \
         PRUint32 _tbodyIndex = 0;                                    \
         rv = _tbodies->Item(_tbodyIndex, getter_AddRefs(_node));     \
-        NS_ENSURE_SUCCESS(rv, rv);                                   \
+        if (NS_FAILED(rv)) {                                         \
+          break;                                                     \
+        }                                                            \
         while (_node) {                                              \
           rowGroup = do_QueryInterface(_node);                       \
           if (rowGroup) {                                            \
             rowGroup->GetRows(getter_AddRefs(rows));                 \
             do { /* gives scoping */                                 \
               _code                                                  \
             } while (0);                                             \
           }                                                          \
           rv = _tbodies->Item(++_tbodyIndex, getter_AddRefs(_node)); \
-          NS_ENSURE_SUCCESS(rv, rv);                                 \
+          if (NS_FAILED(rv)) {                                       \
+            break;                                                   \
+          }                                                          \
+        }                                                            \
+        if (NS_FAILED(rv)) {                                         \
+          break;                                                     \
         }                                                            \
       }                                                              \
       /* orphan rows */                                              \
       rows = mOrphanRows;                                            \
       do { /* gives scoping */                                       \
         _code                                                        \
       } while (0);                                                   \
       /* TFoot */                                                    \
       rv = mParent->GetTFoot(getter_AddRefs(rowGroup));              \
-      NS_ENSURE_SUCCESS(rv, rv);                                     \
+      if (NS_FAILED(rv)) {                                           \
+        break;                                                       \
+      }                                                              \
       rows = nsnull;                                                 \
       if (rowGroup) {                                                \
         rowGroup->GetRows(getter_AddRefs(rows));                     \
         do { /* gives scoping */                                     \
           _code                                                      \
         } while (0);                                                 \
       }                                                              \
     }                                                                \
-  PR_END_MACRO
+  } while (0);
 
 static PRUint32
 CountRowsInRowGroup(nsIDOMHTMLCollection* rows)
 {
   PRUint32 length = 0;
   
   if (rows) {
     rows->GetLength(&length);
@@ -247,55 +263,69 @@ TableRowsCollection::GetLength(PRUint32*
 
   DO_FOR_EACH_ROWGROUP(
     *aLength += CountRowsInRowGroup(rows);
   );
 
   return rv;
 }
 
-// Returns the number of items in the row group, only if *aItem ends
-// up null.  Otherwise, returns 0.
-static PRUint32
+// Returns the item at index aIndex if available. If null is returned,
+// then aCount will be set to the number of rows in this row collection.
+// Otherwise, the value of aCount is undefined.
+static nsINode*
 GetItemOrCountInRowGroup(nsIDOMHTMLCollection* rows,
-                         PRUint32 aIndex, nsIDOMNode** aItem)
+                         PRUint32 aIndex, PRUint32* aCount)
 {
-  NS_PRECONDITION(aItem, "Null out param");
+  *aCount = 0;
 
-  *aItem = nsnull;
-  PRUint32 length = 0;
-  
   if (rows) {
-    rows->Item(aIndex, aItem);
-    if (!*aItem) {
-      rows->GetLength(&length);
+    rows->GetLength(aCount);
+    if (aIndex < *aCount) {
+      nsCOMPtr<nsINodeList> list = do_QueryInterface(rows);
+      return list->GetNodeAt(aIndex);
     }
   }
   
-  return length;
+  return nsnull;
 }
 
-// increments aReturn refcnt by 1
-NS_IMETHODIMP 
-TableRowsCollection::Item(PRUint32 aIndex, nsIDOMNode** aReturn)
+nsISupports* 
+TableRowsCollection::GetNodeAt(PRUint32 aIndex, nsresult *aResult)
 {
-  *aReturn = nsnull;
-  nsresult rv = NS_OK;
-
+  nsresult rv;
   DO_FOR_EACH_ROWGROUP(
-    PRUint32 count = GetItemOrCountInRowGroup(rows, aIndex, aReturn);
-    if (*aReturn) {
-      return NS_OK; 
+    PRUint32 count;
+    nsINode* node = GetItemOrCountInRowGroup(rows, aIndex, &count);
+    if (node) {
+      return node; 
     }
 
     NS_ASSERTION(count <= aIndex, "GetItemOrCountInRowGroup screwed up");
     aIndex -= count;
   );
 
-  return rv;
+  *aResult = rv;
+
+  return nsnull;
+}
+
+NS_IMETHODIMP 
+TableRowsCollection::Item(PRUint32 aIndex, nsIDOMNode** aReturn)
+{
+  nsresult rv;
+
+  nsISupports* node = GetNodeAt(aIndex, &rv);
+  if (!node) {
+    *aReturn = nsnull;
+
+    return rv;
+  }
+
+  return CallQueryInterface(node, aReturn);
 }
 
 static nsresult
 GetNamedItemInRowGroup(nsIDOMHTMLCollection* aRows,
                        const nsAString& aName, nsIDOMNode** aNamedItem)
 {
   if (aRows) {
     return aRows->NamedItem(aName, aNamedItem);
--- a/content/html/document/src/nsHTMLDocument.cpp
+++ b/content/html/document/src/nsHTMLDocument.cpp
@@ -93,17 +93,16 @@
 #include "nsIConsoleService.h"
 #include "nsIComponentManager.h"
 #include "nsParserCIID.h"
 #include "nsIDOMHTMLElement.h"
 #include "nsIDOMHTMLMapElement.h"
 #include "nsIDOMHTMLBodyElement.h"
 #include "nsINameSpaceManager.h"
 #include "nsGenericHTMLElement.h"
-#include "nsGenericDOMNodeList.h"
 #include "nsICSSLoader.h"
 #include "nsIHttpChannel.h"
 #include "nsIFile.h"
 #include "nsIEventListenerManager.h"
 #include "nsISelectElement.h"
 #include "nsFrameSelection.h"
 #include "nsISelectionPrivate.h"//for toStringwithformat code
 
@@ -2855,17 +2854,17 @@ nsHTMLDocument::ResolveName(const nsAStr
       return NS_OK;
     }
 
     // The list contains more than one element, return the whole
     // list, unless...
 
     if (aForm) {
       // ... we're called from a form, in that case we create a
-      // nsFormNameContentList which will filter out the elements in the
+      // nsFormContentList which will filter out the elements in the
       // list that don't belong to aForm
 
       nsFormContentList *fc_list = new nsFormContentList(aForm, *list);
       NS_ENSURE_TRUE(fc_list, NS_ERROR_OUT_OF_MEMORY);
 
       PRUint32 len;
       fc_list->GetLength(&len);
 
--- a/content/xbl/src/nsBindingManager.cpp
+++ b/content/xbl/src/nsBindingManager.cpp
@@ -53,17 +53,16 @@
 #include "nsIDOMElement.h"
 #include "nsIDocument.h"
 #include "nsContentUtils.h"
 #include "nsIPresShell.h"
 #include "nsIXMLContentSink.h"
 #include "nsContentCID.h"
 #include "nsXMLDocument.h"
 #include "nsIStreamListener.h"
-#include "nsGenericDOMNodeList.h"
 
 #include "nsXBLBinding.h"
 #include "nsXBLPrototypeBinding.h"
 #include "nsIXBLDocumentInfo.h"
 #include "nsXBLInsertionPoint.h"
 
 #include "nsIStyleSheet.h"
 #include "nsHTMLStyleSheet.h"
@@ -87,25 +86,24 @@
 // ==================================================================
 // = nsAnonymousContentList 
 // ==================================================================
 
 #define NS_ANONYMOUS_CONTENT_LIST_IID \
   { 0xa29df1f8, 0xaeca, 0x4356, \
     { 0xa8, 0xc2, 0xa7, 0x24, 0xa2, 0x11, 0x73, 0xac } }
 
-class nsAnonymousContentList : public nsIDOMNodeList,
-                               public nsINodeList
+class nsAnonymousContentList : public nsINodeList
 {
 public:
   nsAnonymousContentList(nsInsertionPointList* aElements);
   virtual ~nsAnonymousContentList();
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-  NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsAnonymousContentList, nsIDOMNodeList)
+  NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsAnonymousContentList, nsINodeList)
   // nsIDOMNodeList interface
   NS_DECL_NSIDOMNODELIST
 
   // nsINodeList interface
   virtual nsINode* GetNodeAt(PRUint32 aIndex);
 
   PRInt32 GetInsertionPointCount() { return mElements->Length(); }
 
@@ -137,20 +135,18 @@ nsAnonymousContentList::~nsAnonymousCont
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsAnonymousContentList)
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsAnonymousContentList)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsAnonymousContentList)
 
 NS_INTERFACE_MAP_BEGIN(nsAnonymousContentList)
   NS_INTERFACE_MAP_ENTRY(nsINodeList)
   NS_INTERFACE_MAP_ENTRY(nsIDOMNodeList)
-  if (aIID.Equals(NS_GET_IID(nsAnonymousContentList)))
-    foundInterface = static_cast<nsIDOMNodeList*>(this);
-  else
-  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMNodeList)
+  NS_INTERFACE_MAP_ENTRY(nsAnonymousContentList)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsINodeList)
   NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(NodeList)
   NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(nsAnonymousContentList)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_0(nsAnonymousContentList)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsAnonymousContentList)
   {
     PRInt32 i, count = tmp->mElements->Length();
--- a/dom/public/idl/base/nsIDOMClientInformation.idl
+++ b/dom/public/idl/base/nsIDOMClientInformation.idl
@@ -33,17 +33,16 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "domstubs.idl"
 
 interface nsIDOMOfflineResourceList;
-interface nsIDOMLoadStatusList;
 
 [scriptable, uuid(f8bbf8c3-c47b-465a-a221-22824449f689)]
 interface nsIDOMClientInformation : nsISupports
 {
   /**
    * Web Applications 1.0 Browser State: registerContentHandler
    * Allows web services to register themselves as handlers for certain content
    * types.
--- a/dom/public/idl/offline/Makefile.in
+++ b/dom/public/idl/offline/Makefile.in
@@ -43,14 +43,13 @@ VPATH          = @srcdir@
 include $(DEPTH)/config/autoconf.mk
 
 MODULE         = dom
 XPIDL_MODULE   = dom_offline
 GRE_MODULE     = 1
 
 XPIDLSRCS =                           \
         nsIDOMOfflineResourceList.idl \
-        nsIDOMLoadStatusList.idl      \
         nsIDOMLoadStatus.idl          \
         nsIDOMLoadStatusEvent.idl     \
         $(NULL)
 
 include $(topsrcdir)/config/rules.mk
deleted file mode 100644
--- a/dom/public/idl/offline/nsIDOMLoadStatusList.idl
+++ /dev/null
@@ -1,48 +0,0 @@
-/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is mozilla.org code.
- *
- * The Initial Developer of the Original Code is
- * Mozilla Corporation
- * Portions created by the Initial Developer are Copyright (C) 2007
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Dave Camp <dcamp@mozilla.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#include "domstubs.idl"
-
-interface nsIDOMLoadStatus;
-
-[scriptable, uuid(d58bc0cf-e35c-4d22-9e21-9ada8fc4203a)]
-interface nsIDOMLoadStatusList : nsISupports
-{
-  readonly attribute unsigned long length;
-  nsIDOMLoadStatus item(in unsigned long index);
-};
--- a/dom/public/nsDOMClassInfoID.h
+++ b/dom/public/nsDOMClassInfoID.h
@@ -403,17 +403,16 @@ enum nsDOMClassInfoID {
 
 #ifdef MOZ_SVG
   eDOMClassInfo_SVGForeignObjectElement_id,
 #endif
 
   eDOMClassInfo_XULCommandEvent_id,
   eDOMClassInfo_CommandEvent_id,
   eDOMClassInfo_OfflineResourceList_id,
-  eDOMClassInfo_LoadStatusList_id,
   eDOMClassInfo_LoadStatus_id,
   eDOMClassInfo_LoadStatusEvent_id,
 
   eDOMClassInfo_FileList_id,
   eDOMClassInfo_File_id,
   eDOMClassInfo_FileException_id,
 
   // DOM modal content window class, almost identical to Window
--- a/dom/src/base/Makefile.in
+++ b/dom/src/base/Makefile.in
@@ -127,16 +127,17 @@ LOCAL_INCLUDES = \
 		-I$(srcdir)/../geolocation \
 		-I$(srcdir)/../threads \
 		-I$(topsrcdir)/content/xbl/src \
 		-I$(topsrcdir)/content/xul/document/src \
 		-I$(topsrcdir)/content/events/src \
 		-I$(topsrcdir)/content/base/src \
 		-I$(topsrcdir)/content/html/document/src \
 		-I$(topsrcdir)/layout/style \
+		-I$(topsrcdir)/layout/xul/base/src/tree/src \
 		$(NULL)
 
 DEFINES += -D_IMPL_NS_LAYOUT
 
 ifdef MOZ_JSDEBUGGER
 DEFINES += -DMOZ_JSDEBUGGER
 endif
 
--- a/dom/src/base/nsDOMClassInfo.cpp
+++ b/dom/src/base/nsDOMClassInfo.cpp
@@ -108,18 +108,17 @@
 #include "nsIDOMWindowInternal.h"
 #include "nsPIDOMWindow.h"
 #include "nsIDOMJSWindow.h"
 #include "nsIDOMWindowCollection.h"
 #include "nsIDOMHistory.h"
 #include "nsIDOMMediaList.h"
 #include "nsIDOMChromeWindow.h"
 #include "nsIDOMConstructor.h"
-#include "nsIDOMClientRect.h"
-#include "nsIDOMClientRectList.h"
+#include "nsClientRect.h"
 
 // DOM core includes
 #include "nsDOMError.h"
 #include "nsIDOMDOMException.h"
 #include "nsIDOMNode.h"
 #include "nsIDOM3Node.h"
 #include "nsIDOM3Attr.h"
 #include "nsIDOMNodeList.h"
@@ -129,16 +128,17 @@
 #include "nsIDOMNSElement.h"
 
 // HTMLFormElement helper includes
 #include "nsIForm.h"
 #include "nsIFormControl.h"
 #include "nsIDOMHTMLFormElement.h"
 #include "nsIDOMNSHTMLFormControlList.h"
 #include "nsIDOMHTMLCollection.h"
+#include "nsIHTMLCollection.h"
 #include "nsHTMLDocument.h"
 
 // HTMLSelectElement helper includes
 #include "nsIDOMHTMLSelectElement.h"
 #include "nsIDOMNSXBLFormControl.h"
 
 // HTMLEmbed/ObjectElement helper includes
 #include "nsIPluginInstance.h"
@@ -177,17 +177,18 @@
 #include "nsIDOMEventTarget.h"
 #include "nsIDOMNSEventTarget.h"
 
 // CSS related includes
 #include "nsIDOMStyleSheet.h"
 #include "nsIDOMStyleSheetList.h"
 #include "nsIDOMCSSStyleDeclaration.h"
 #include "nsIDOMCSSRule.h"
-#include "nsIDOMCSSRuleList.h"
+#include "nsICSSRule.h"
+#include "nsICSSRuleList.h"
 #include "nsIDOMRect.h"
 #include "nsIDOMRGBColor.h"
 #include "nsIDOMNSRGBAColor.h"
 
 // XBL related includes.
 #include "nsIXBLService.h"
 #include "nsXBLBinding.h"
 #include "nsBindingManager.h"
@@ -326,17 +327,17 @@
 #include "nsIDOMCSSCharsetRule.h"
 #include "nsIDOMCSSImportRule.h"
 #include "nsIDOMCSSMediaRule.h"
 #include "nsIDOMCSSFontFaceRule.h"
 #include "nsIDOMCSSMozDocumentRule.h"
 #include "nsIDOMCSSPrimitiveValue.h"
 #include "nsIDOMCSSStyleRule.h"
 #include "nsIDOMCSSStyleSheet.h"
-#include "nsIDOMCSSValueList.h"
+#include "nsDOMCSSValueList.h"
 #include "nsIDOMRange.h"
 #include "nsIDOMNSRange.h"
 #include "nsIDOMRangeException.h"
 #include "nsIDOMNodeIterator.h"
 #include "nsIDOMTreeWalker.h"
 #include "nsIDOMXULDocument.h"
 #include "nsIDOMXULElement.h"
 #include "nsIDOMXULCommandDispatcher.h"
@@ -346,17 +347,17 @@
 #include "nsIControllers.h"
 #include "nsISelection.h"
 #include "nsIBoxObject.h"
 #ifdef MOZ_XUL
 #include "nsITreeSelection.h"
 #include "nsITreeContentView.h"
 #include "nsITreeView.h"
 #include "nsIXULTemplateBuilder.h"
-#include "nsITreeColumns.h"
+#include "nsTreeColumns.h"
 #endif
 #include "nsIDOMXPathException.h"
 #include "nsIDOMXPathExpression.h"
 #include "nsIDOMNSXPathExpression.h"
 #include "nsIDOMXPathNSResolver.h"
 #include "nsIDOMXPathResult.h"
 
 #ifdef MOZ_SVG
@@ -448,27 +449,25 @@
 #include "nsIDOMStorageItem.h"
 #include "nsIDOMStorageEvent.h"
 #include "nsIDOMToString.h"
 
 // Drag and drop
 #include "nsIDOMDataTransfer.h"
 
 // Offline includes
-#include "nsIDOMLoadStatusList.h"
 #include "nsIDOMLoadStatus.h"
 #include "nsIDOMLoadStatusEvent.h"
 
 // Geolocation
 #include "nsIDOMGeoGeolocation.h"
 #include "nsIDOMGeoPosition.h"
 #include "nsIDOMGeoPositionError.h"
 
-#include "nsIDOMFileList.h"
-#include "nsIDOMFile.h"
+#include "nsDOMFile.h"
 #include "nsIDOMFileException.h"
 
 static NS_DEFINE_CID(kCPluginManagerCID, NS_PLUGINMANAGER_CID);
 static NS_DEFINE_CID(kDOMSOF_CID, NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
 
 static const char kDOMStringBundleURL[] =
   "chrome://global/locale/dom/dom.properties";
 
@@ -629,17 +628,17 @@ static nsDOMClassInfoData sClassInfoData
   NS_DEFINE_CLASSINFO_DATA(Text, nsNodeSH,
                            NODE_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(Comment, nsNodeSH,
                            NODE_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(CDATASection, nsNodeSH, NODE_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(ProcessingInstruction, nsNodeSH,
                            NODE_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(Notation, nsNodeSH, NODE_SCRIPTABLE_FLAGS)
-  NS_DEFINE_CLASSINFO_DATA(NodeList, nsArraySH, ARRAY_SCRIPTABLE_FLAGS)
+  NS_DEFINE_CLASSINFO_DATA(NodeList, nsNodeListSH, ARRAY_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(NamedNodeMap, nsNamedNodeMapSH,
                            ARRAY_SCRIPTABLE_FLAGS)
 
   // Misc Core related classes
 
   // StyleSheet classes
   NS_DEFINE_CLASSINFO_DATA_WITH_NAME(DocumentStyleSheetList, StyleSheetList,
                                      nsStyleSheetListSH,
@@ -1224,18 +1223,16 @@ static nsDOMClassInfoData sClassInfoData
   NS_DEFINE_CLASSINFO_DATA(XULCommandEvent, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(CommandEvent, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(OfflineResourceList, nsOfflineResourceListSH,
                            ARRAY_SCRIPTABLE_FLAGS)
 
-  NS_DEFINE_CLASSINFO_DATA(LoadStatusList, nsLoadStatusListSH,
-                           ARRAY_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(LoadStatus, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(LoadStatusEvent, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(FileList, nsFileListSH,
                            ARRAY_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(File, nsDOMGenericSH,
@@ -3414,21 +3411,16 @@ nsDOMClassInfo::Init()
     DOM_CLASSINFO_EVENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(OfflineResourceList, nsIDOMOfflineResourceList)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMOfflineResourceList)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
   DOM_CLASSINFO_MAP_END
 
-  DOM_CLASSINFO_MAP_BEGIN(LoadStatusList, nsIDOMLoadStatusList)
-    DOM_CLASSINFO_MAP_ENTRY(nsIDOMLoadStatusList)
-    DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
-  DOM_CLASSINFO_MAP_END
-
   DOM_CLASSINFO_MAP_BEGIN(LoadStatus, nsIDOMLoadStatus)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMLoadStatus)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(LoadStatusEvent, nsIDOMLoadStatusEvent)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMLoadStatusEvent)
     DOM_CLASSINFO_EVENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
@@ -7533,56 +7525,56 @@ nsGenericArraySH::NewResolve(nsIXPConnec
 
   if (is_number && n >= 0) {
     // XXX The following is a cheap optimization to avoid hitting xpconnect to
     // get the length. We may want to consider asking our concrete
     // implementation for the length, and falling back onto the GetProperty if
     // it doesn't provide one.
 
     PRUint32 length;
-
-    nsCOMPtr<nsIDOMNodeList> map = do_QueryWrappedNative(wrapper);
-    if (map) {
-      // Fast path: Get the length from our map.
-
-      map->GetLength(&length);
-    } else {
-      // Slow path: We don't know how to get the length in a fast way, ask our
-      // implementation.
-
-      jsval lenval;
-      if (!JS_GetProperty(cx, obj, "length", &lenval)) {
-        return NS_ERROR_UNEXPECTED;
-      }
-
-      if (!JSVAL_IS_INT(lenval)) {
-        // This can apparently happen with some sparse array impls falling back
-        // onto this code.
-
-        return NS_OK;
-      }
-
-      PRInt32 slen = JSVAL_TO_INT(lenval);
-      if (slen < 0) {
-        return NS_OK;
-      }
-
-      length = (PRUint32)slen;
-    }
+    nsresult rv = GetLength(wrapper, cx, obj, &length);
+    NS_ENSURE_SUCCESS(rv, rv);
 
     if ((PRUint32)n < length) {
       *_retval = ::JS_DefineElement(cx, obj, n, JSVAL_VOID, nsnull, nsnull,
                                     JSPROP_ENUMERATE | JSPROP_SHARED);
       *objp = obj;
     }
   }
 
   return NS_OK;
 }
 
+nsresult
+nsGenericArraySH::GetLength(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
+                             JSObject *obj, PRUint32 *length)
+{
+  *length = 0;
+
+  jsval lenval;
+  if (!JS_GetProperty(cx, obj, "length", &lenval)) {
+    return NS_ERROR_UNEXPECTED;
+  }
+
+  if (!JSVAL_IS_INT(lenval)) {
+    // This can apparently happen with some sparse array impls falling back
+    // onto this code.
+    return NS_OK;
+  }
+
+  PRInt32 slen = JSVAL_TO_INT(lenval);
+  if (slen < 0) {
+    return NS_OK;
+  }
+
+  *length = (PRUint32)slen;
+
+  return NS_OK;
+}
+
 NS_IMETHODIMP
 nsGenericArraySH::Enumerate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
                             JSObject *obj, PRBool *_retval)
 {
   // Recursion protection in case someone tries to be smart and call
   // the enumerate hook from a user defined .length getter, or
   // somesuch.
 
@@ -7608,65 +7600,93 @@ nsGenericArraySH::Enumerate(nsIXPConnect
     }
   }
 
   sCurrentlyEnumerating = PR_FALSE;
 
   return ok ? NS_OK : NS_ERROR_UNEXPECTED;
 }
 
-// NodeList scriptable helper
-
-nsresult
-nsArraySH::GetItemAt(nsISupports *aNative, PRUint32 aIndex,
-                     nsISupports **aResult)
-{
-  nsCOMPtr<nsINodeList> list(do_QueryInterface(aNative));
-  if (!list) {
-    return NS_ERROR_UNEXPECTED;
-  }
-
-  NS_IF_ADDREF(*aResult = list->GetNodeAt(aIndex));
-
-  return NS_OK;
-}
+// Array scriptable helper
 
 NS_IMETHODIMP
 nsArraySH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
                        JSObject *obj, jsval id, jsval *vp, PRBool *_retval)
 {
   PRBool is_number = PR_FALSE;
   PRInt32 n = GetArrayIndexFromId(cx, id, &is_number);
 
   nsresult rv = NS_OK;
 
   if (is_number) {
     if (n < 0) {
       return NS_ERROR_DOM_INDEX_SIZE_ERR;
     }
 
-    nsCOMPtr<nsISupports> array_item;
-
-    rv = GetItemAt(wrapper->Native(), n, getter_AddRefs(array_item));
+    // Make sure rv == NS_OK here, so GetItemAt implementations that never fail
+    // don't have to set rv.
+    rv = NS_OK;
+    nsISupports* array_item = GetItemAt(wrapper->Native(), n, &rv);
     NS_ENSURE_SUCCESS(rv, rv);
 
     if (array_item) {
       nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
       rv = WrapNative(cx, obj, array_item, NS_GET_IID(nsISupports), vp,
                       getter_AddRefs(holder));
       NS_ENSURE_SUCCESS(rv, rv);
 
       rv = NS_SUCCESS_I_DID_SOMETHING;
     }
   }
 
   return rv;
 }
 
 
+// NodeList scriptable helper
+
+nsresult
+nsNodeListSH::GetLength(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
+                        JSObject *obj, PRUint32 *length)
+{
+  nsINodeList* list = static_cast<nsINodeList*>(wrapper->Native());
+#ifdef DEBUG
+  {
+    nsCOMPtr<nsINodeList> list_qi = do_QueryWrappedNative(wrapper);
+
+    // 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 list->GetLength(length);
+}
+
+nsISupports*
+nsNodeListSH::GetItemAt(nsISupports *aNative, PRUint32 aIndex,
+                        nsresult *aResult)
+{
+  nsINodeList* list = static_cast<nsINodeList*>(aNative);
+#ifdef DEBUG
+  {
+    nsCOMPtr<nsINodeList> list_qi = do_QueryInterface(aNative);
+
+    // 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 list->GetNodeAt(aIndex);
+}
+
+
 // StringList scriptable helper
 
 nsresult
 nsStringListSH::GetStringAt(nsISupports *aNative, PRInt32 aIndex,
                             nsAString& aResult)
 {
   nsCOMPtr<nsIDOMDOMStringList> list(do_QueryInterface(aNative));
   NS_ENSURE_TRUE(list, NS_ERROR_UNEXPECTED);
@@ -7702,29 +7722,23 @@ nsNamedArraySH::GetProperty(nsIXPConnect
   }
 
   return nsArraySH::GetProperty(wrapper, cx, obj, id, vp, _retval);
 }
 
 
 // NamedNodeMap helper
 
-nsresult
+nsISupports*
 nsNamedNodeMapSH::GetItemAt(nsISupports *aNative, PRUint32 aIndex,
-                            nsISupports **aResult)
-{
-  nsCOMPtr<nsIDOMNamedNodeMap> map(do_QueryInterface(aNative));
-  NS_ENSURE_TRUE(map, NS_ERROR_UNEXPECTED);
-
-  nsIDOMNode *node = nsnull; // Weak, transfer the ownership over to aResult
-  nsresult rv = map->Item(aIndex, &node);
-
-  *aResult = node;
-
-  return rv;
+                            nsresult *aResult)
+{
+  nsDOMAttributeMap* map = nsDOMAttributeMap::FromSupports(aNative);
+
+  return map->GetItemAt(aIndex, aResult);
 }
 
 nsresult
 nsNamedNodeMapSH::GetNamedItem(nsISupports *aNative, const nsAString& aName,
                                nsISupports **aResult)
 {
   nsCOMPtr<nsIDOMNamedNodeMap> map(do_QueryInterface(aNative));
   NS_ENSURE_TRUE(map, NS_ERROR_UNEXPECTED);
@@ -7735,35 +7749,33 @@ nsNamedNodeMapSH::GetNamedItem(nsISuppor
   *aResult = node;
 
   return rv;
 }
 
 
 // HTMLCollection helper
 
-nsresult
+nsISupports*
 nsHTMLCollectionSH::GetItemAt(nsISupports *aNative, PRUint32 aIndex,
-                              nsISupports **aResult)
-{
-  // Common case is that we're also an nsINodeList
-  nsresult rv = nsArraySH::GetItemAt(aNative, aIndex, aResult);
-  if (NS_SUCCEEDED(rv)) {
-    return rv;
-  }
-  
-  nsCOMPtr<nsIDOMHTMLCollection> collection(do_QueryInterface(aNative));
-  NS_ENSURE_TRUE(collection, NS_ERROR_UNEXPECTED);
-
-  nsIDOMNode *node = nsnull; // Weak, transfer the ownership over to aResult
-  rv = collection->Item(aIndex, &node);
-
-  *aResult = node;
-
-  return rv;
+                              nsresult *aResult)
+{
+  nsIHTMLCollection* collection = static_cast<nsIHTMLCollection*>(aNative);
+#ifdef DEBUG
+  {
+    nsCOMPtr<nsIHTMLCollection> collection_qi = do_QueryInterface(aNative);
+
+    // If this assertion fires the QI implementation for the object in
+    // question doesn't use the nsIHTMLCollection pointer as the nsISupports
+    // pointer. That must be fixed, or we'll crash...
+    NS_ASSERTION(collection_qi == collection, "Uh, fix QI!");
+  }
+#endif
+
+  return collection->GetNodeAt(aIndex, aResult);
 }
 
 nsresult
 nsHTMLCollectionSH::GetNamedItem(nsISupports *aNative,
                                  const nsAString& aName,
                                  nsISupports **aResult)
 {
   nsCOMPtr<nsIDOMHTMLCollection> collection(do_QueryInterface(aNative));
@@ -7778,24 +7790,17 @@ nsHTMLCollectionSH::GetNamedItem(nsISupp
 }
 
 
 // ContentList helper
 nsresult
 nsContentListSH::PreCreate(nsISupports *nativeObj, JSContext *cx,
                            JSObject *globalObj, JSObject **parentObj)
 {
-  nsCOMPtr<nsIDOMNodeList> nodeList(do_QueryInterface(nativeObj));
-  nsContentList *contentList =
-    static_cast<nsContentList*>(static_cast<nsIDOMNodeList*>(nodeList));
-
-  if (!contentList) {
-    return NS_OK;
-  }
-
+  nsContentList *contentList = nsContentList::FromSupports(nativeObj);
   nsISupports *native_parent = contentList->GetParentObject();
 
   if (!native_parent) {
     *parentObj = globalObj;
     return NS_OK;
   }
 
   jsval v;
@@ -7804,16 +7809,39 @@ nsContentListSH::PreCreate(nsISupports *
                            NS_GET_IID(nsISupports), &v,
                            getter_AddRefs(holder));
 
   *parentObj = JSVAL_TO_OBJECT(v);
 
   return rv;
 }
 
+NS_IMETHODIMP
+nsContentListSH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
+                             JSObject *obj, jsval id, jsval *vp,
+                             PRBool *_retval)
+{
+  if (JSVAL_IS_STRING(id) && !ObjectIsNativeWrapper(cx, obj)) {
+    nsContentList *list = nsContentList::FromSupports(wrapper->Native());
+    nsINode* node = list->NamedItem(nsDependentJSString(id), PR_TRUE);
+    if (!node) {
+      return NS_OK;
+    }
+
+    nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
+    nsresult rv = WrapNative(cx, obj, node, NS_GET_IID(nsISupports), vp,
+                             getter_AddRefs(holder));
+
+    return NS_FAILED(rv) ? rv : NS_SUCCESS_I_DID_SOMETHING;
+  }
+
+  return nsNodeListSH::GetProperty(wrapper, cx, obj, id, vp, _retval);
+}
+
+
 // FormControlList helper
 
 nsresult
 nsFormControlListSH::GetNamedItem(nsISupports *aNative,
                                   const nsAString& aName,
                                   nsISupports **aResult)
 {
   nsCOMPtr<nsIDOMNSHTMLFormControlList> list(do_QueryInterface(aNative));
@@ -9841,29 +9869,23 @@ nsHTMLOptionsCollectionSH::Add(JSContext
   }
 
   return NS_SUCCEEDED(rv);
 }
 
 
 // Plugin helper
 
-nsresult
+nsISupports*
 nsPluginSH::GetItemAt(nsISupports *aNative, PRUint32 aIndex,
-                      nsISupports **aResult)
-{
-  nsCOMPtr<nsIDOMPlugin> plugin(do_QueryInterface(aNative));
-  NS_ENSURE_TRUE(plugin, NS_ERROR_UNEXPECTED);
-
-  nsIDOMMimeType *mime_type = nsnull;
-  nsresult rv = plugin->Item(aIndex, &mime_type);
-
-  *aResult = mime_type;
-
-  return rv;
+                      nsresult *aResult)
+{
+  nsPluginElement* plugin = nsPluginElement::FromSupports(aNative);
+
+  return plugin->GetItemAt(aIndex, aResult);
 }
 
 nsresult
 nsPluginSH::GetNamedItem(nsISupports *aNative, const nsAString& aName,
                          nsISupports **aResult)
 {
   nsCOMPtr<nsIDOMPlugin> plugin(do_QueryInterface(aNative));
   NS_ENSURE_TRUE(plugin, NS_ERROR_UNEXPECTED);
@@ -9875,29 +9897,23 @@ nsPluginSH::GetNamedItem(nsISupports *aN
   *aResult = mime_type;
 
   return rv;
 }
 
 
 // PluginArray helper
 
-nsresult
+nsISupports*
 nsPluginArraySH::GetItemAt(nsISupports *aNative, PRUint32 aIndex,
-                           nsISupports **aResult)
-{
-  nsCOMPtr<nsIDOMPluginArray> array(do_QueryInterface(aNative));
-  NS_ENSURE_TRUE(array, NS_ERROR_UNEXPECTED);
-
-  nsIDOMPlugin *plugin = nsnull;
-  nsresult rv = array->Item(aIndex, &plugin);
-
-  *aResult = plugin;
-
-  return rv;
+                           nsresult *aResult)
+{
+  nsPluginArray* array = nsPluginArray::FromSupports(aNative);
+
+  return array->GetItemAt(aIndex, aResult);
 }
 
 nsresult
 nsPluginArraySH::GetNamedItem(nsISupports *aNative, const nsAString& aName,
                               nsISupports **aResult)
 {
   nsCOMPtr<nsIDOMPluginArray> array(do_QueryInterface(aNative));
   NS_ENSURE_TRUE(array, NS_ERROR_UNEXPECTED);
@@ -9909,29 +9925,23 @@ nsPluginArraySH::GetNamedItem(nsISupport
   *aResult = plugin;
 
   return rv;
 }
 
 
 // MimeTypeArray helper
 
-nsresult
+nsISupports*
 nsMimeTypeArraySH::GetItemAt(nsISupports *aNative, PRUint32 aIndex,
-                             nsISupports **aResult)
-{
-  nsCOMPtr<nsIDOMMimeTypeArray> array(do_QueryInterface(aNative));
-  NS_ENSURE_TRUE(array, NS_ERROR_UNEXPECTED);
-
-  nsIDOMMimeType *mime_type = nsnull;
-  nsresult rv = array->Item(aIndex, &mime_type);
-
-  *aResult = mime_type;
-
-  return rv;
+                             nsresult *aResult)
+{
+  nsMimeTypeArray* array = nsMimeTypeArray::FromSupports(aNative);
+
+  return array->GetItemAt(aIndex, aResult);
 }
 
 nsresult
 nsMimeTypeArraySH::GetNamedItem(nsISupports *aNative, const nsAString& aName,
                                 nsISupports **aResult)
 {
   nsCOMPtr<nsIDOMMimeTypeArray> array(do_QueryInterface(aNative));
   NS_ENSURE_TRUE(array, NS_ERROR_UNEXPECTED);
@@ -10036,47 +10046,35 @@ nsMediaListSH::GetStringAt(nsISupports *
   nsCOMPtr<nsIDOMMediaList> media_list(do_QueryInterface(aNative));
 
   return media_list->Item(PRUint32(aIndex), aResult);
 }
 
 
 // StyleSheetList helper
 
-nsresult
+nsISupports*
 nsStyleSheetListSH::GetItemAt(nsISupports *aNative, PRUint32 aIndex,
-                              nsISupports **aResult)
-{
-  nsCOMPtr<nsIDOMStyleSheetList> stylesheets(do_QueryInterface(aNative));
-  NS_ENSURE_TRUE(stylesheets, NS_ERROR_UNEXPECTED);
-
-  nsIDOMStyleSheet *sheet = nsnull;
-  nsresult rv = stylesheets->Item(aIndex, &sheet);
-
-  *aResult = sheet;
-
-  return rv;
+                              nsresult *rv)
+{
+  nsDOMStyleSheetList* list = nsDOMStyleSheetList::FromSupports(aNative);
+
+  return list->GetItemAt(aIndex);
 }
 
 
 // CSSValueList helper
 
-nsresult
+nsISupports*
 nsCSSValueListSH::GetItemAt(nsISupports *aNative, PRUint32 aIndex,
-                            nsISupports **aResult)
-{
-  nsCOMPtr<nsIDOMCSSValueList> cssValueList(do_QueryInterface(aNative));
-  NS_ENSURE_TRUE(cssValueList, NS_ERROR_UNEXPECTED);
-
-  nsIDOMCSSValue *cssValue = nsnull; // Weak, transfer the ownership over to aResult
-  nsresult rv = cssValueList->Item(aIndex, &cssValue);
-
-  *aResult = cssValue;
-
-  return rv;
+                            nsresult *aResult)
+{
+  nsDOMCSSValueList* list = nsDOMCSSValueList::FromSupports(aNative);
+
+  return list->GetItemAt(aIndex);
 }
 
 
 // CSSStyleDeclaration helper
 
 nsresult
 nsCSSStyleDeclSH::GetStringAt(nsISupports *aNative, PRInt32 aIndex,
                               nsAString& aResult)
@@ -10088,64 +10086,56 @@ nsCSSStyleDeclSH::GetStringAt(nsISupport
   nsCOMPtr<nsIDOMCSSStyleDeclaration> style_decl(do_QueryInterface(aNative));
 
   return style_decl->Item(PRUint32(aIndex), aResult);
 }
 
 
 // CSSRuleList scriptable helper
 
-nsresult
+nsISupports*
 nsCSSRuleListSH::GetItemAt(nsISupports *aNative, PRUint32 aIndex,
-                           nsISupports **aResult)
-{
-  nsCOMPtr<nsIDOMCSSRuleList> list(do_QueryInterface(aNative));
-  NS_ENSURE_TRUE(list, NS_ERROR_UNEXPECTED);
-
-  nsIDOMCSSRule *rule = nsnull; // Weak, transfer the ownership over to aResult
-  nsresult rv = list->Item(aIndex, &rule);
-
-  *aResult = rule;
-
-  return rv;
+                           nsresult *aResult)
+{
+  nsICSSRuleList* list = static_cast<nsICSSRuleList*>(aNative);
+#ifdef DEBUG
+  {
+    nsCOMPtr<nsICSSRuleList> list_qi = do_QueryInterface(aNative);
+
+    // If this assertion fires the QI implementation for the object in
+    // question doesn't use the nsICSSRuleList pointer as the nsISupports
+    // pointer. That must be fixed, or we'll crash...
+    NS_ASSERTION(list_qi == list, "Uh, fix QI!");
+  }
+#endif
+
+  return list->GetItemAt(aIndex, aResult);
 }
 
 // ClientRectList scriptable helper
 
-nsresult
+nsISupports*
 nsClientRectListSH::GetItemAt(nsISupports *aNative, PRUint32 aIndex,
-                              nsISupports **aResult)
-{
-  nsCOMPtr<nsIDOMClientRectList> list(do_QueryInterface(aNative));
-  NS_ENSURE_TRUE(list, NS_ERROR_UNEXPECTED);
-
-  nsIDOMClientRect *rule = nsnull; // Weak, transfer the ownership over to aResult
-  nsresult rv = list->Item(aIndex, &rule);
-
-  *aResult = rule;
-
-  return rv;
+                              nsresult *aResult)
+{
+  nsClientRectList* list = nsClientRectList::FromSupports(aNative);
+
+  return list->GetItemAt(aIndex);
 }
 
 #ifdef MOZ_XUL
 // TreeColumns helper
 
-nsresult
+nsISupports*
 nsTreeColumnsSH::GetItemAt(nsISupports *aNative, PRUint32 aIndex,
-                           nsISupports **aResult)
-{
-  nsCOMPtr<nsITreeColumns> columns(do_QueryInterface(aNative));
-  NS_ENSURE_TRUE(columns, NS_ERROR_UNEXPECTED);
-
-  nsITreeColumn* column = nsnull; // Weak, transfer the ownership over to aResult
-  nsresult rv = columns->GetColumnAt(aIndex, &column);
-
-  *aResult = column;
-
-  return rv;
+                           nsresult *aResult)
+{
+  nsTreeColumns* columns = nsTreeColumns::FromSupports(aNative);
+
+  return columns->GetColumnAt(aIndex);
 }
 
 nsresult
 nsTreeColumnsSH::GetNamedItem(nsISupports *aNative,
                               const nsAString& aName,
                               nsISupports **aResult)
 {
   nsCOMPtr<nsITreeColumns> columns(do_QueryInterface(aNative));
@@ -10474,39 +10464,17 @@ nsOfflineResourceListSH::GetStringAt(nsI
                                      nsAString& aResult)
 {
   nsCOMPtr<nsIDOMOfflineResourceList> list(do_QueryInterface(aNative));
   NS_ENSURE_TRUE(list, NS_ERROR_UNEXPECTED);
 
   return list->Item(aIndex, aResult);
 }
 
-// nsLoadStatusListSH
-nsresult
-nsLoadStatusListSH::GetItemAt(nsISupports *aNative, PRUint32 aIndex,
-                              nsISupports **aResult)
-{
-  nsCOMPtr<nsIDOMLoadStatusList> list(do_QueryInterface(aNative));
-  NS_ENSURE_TRUE(list, NS_ERROR_UNEXPECTED);
-
-  nsIDOMLoadStatus *status = nsnull; // Weak, transfer the ownership over to aResult
-  nsresult rv = list->Item(aIndex, &status);
-
-  *aResult = status;
-
-  return rv;
-}
-
 // nsFileListSH
-nsresult
+nsISupports*
 nsFileListSH::GetItemAt(nsISupports *aNative, PRUint32 aIndex,
-                        nsISupports **aResult)
-{
-  nsCOMPtr<nsIDOMFileList> list(do_QueryInterface(aNative));
-  NS_ENSURE_TRUE(list, NS_ERROR_UNEXPECTED);
-
-  nsIDOMFile *file = nsnull; // weak, transfer ownership over to aResult
-  nsresult rv = list->Item(aIndex, &file);
-
-  *aResult = file;
-
-  return rv;
-}
+                        nsresult *aResult)
+{
+  nsDOMFileList* list = nsDOMFileList::FromSupports(aNative);
+
+  return list->GetItemAt(aIndex);
+}
--- a/dom/src/base/nsDOMClassInfo.h
+++ b/dom/src/base/nsDOMClassInfo.h
@@ -615,46 +615,72 @@ protected:
   
 public:
   NS_IMETHOD NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
                         JSObject *obj, jsval id, PRUint32 flags,
                         JSObject **objp, PRBool *_retval);
   NS_IMETHOD Enumerate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
                        JSObject *obj, PRBool *_retval);
   
+  virtual nsresult GetLength(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
+                             JSObject *obj, PRUint32 *length);
+
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
     return new nsGenericArraySH(aData);
   }
 };
 
 
-// NodeList scriptable helper
+// Array scriptable helper
 
 class nsArraySH : public nsGenericArraySH
 {
 protected:
   nsArraySH(nsDOMClassInfoData* aData) : nsGenericArraySH(aData)
   {
   }
 
   virtual ~nsArraySH()
   {
   }
 
-  virtual nsresult GetItemAt(nsISupports *aNative, PRUint32 aIndex,
-                             nsISupports **aResult);
+  // Subclasses need to override this, if the implementation can't fail it's
+  // allowed to not set *aResult.
+  virtual nsISupports* GetItemAt(nsISupports *aNative, PRUint32 aIndex,
+                                 nsresult *aResult) = 0;
 
 public:
   NS_IMETHOD GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
                          JSObject *obj, jsval id, jsval *vp, PRBool *_retval);
 
+private:
+  // Not implemented, nothing should create an instance of this class.
+  static nsIClassInfo *doCreate(nsDOMClassInfoData* aData);
+};
+
+
+// NodeList scriptable helper
+ 
+class nsNodeListSH : public nsArraySH
+{
+protected:
+  nsNodeListSH(nsDOMClassInfoData* aData) : nsArraySH(aData)
+  {
+  }
+
+public:
+  virtual nsresult GetLength(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
+                             JSObject *obj, PRUint32 *length);
+  virtual nsISupports* GetItemAt(nsISupports *aNative, PRUint32 aIndex,
+                                 nsresult *aResult);
+ 
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
-    return new nsArraySH(aData);
+    return new nsNodeListSH(aData);
   }
 };
 
 
 // NamedArray helper
 
 class nsNamedArraySH : public nsArraySH
 {
@@ -668,36 +694,38 @@ protected:
   }
 
   virtual nsresult GetNamedItem(nsISupports *aNative, const nsAString& aName,
                                 nsISupports **aResult) = 0;
 
 public:
   NS_IMETHOD GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
                          JSObject *obj, jsval id, jsval *vp, PRBool *_retval);
+
+private:
+  // Not implemented, nothing should create an instance of this class.
+  static nsIClassInfo *doCreate(nsDOMClassInfoData* aData);
 };
 
 
 // NamedNodeMap helper
 
 class nsNamedNodeMapSH : public nsNamedArraySH
 {
 protected:
   nsNamedNodeMapSH(nsDOMClassInfoData* aData) : nsNamedArraySH(aData)
   {
   }
 
   virtual ~nsNamedNodeMapSH()
   {
   }
 
-  // Override nsArraySH::GetItemAt() since our list isn't a
-  // nsIDOMNodeList
-  virtual nsresult GetItemAt(nsISupports *aNative, PRUint32 aIndex,
-                             nsISupports **aResult);
+  virtual nsISupports* GetItemAt(nsISupports *aNative, PRUint32 aIndex,
+                                 nsresult *aResult);
 
   // Override nsNamedArraySH::GetNamedItem()
   virtual nsresult GetNamedItem(nsISupports *aNative, const nsAString& aName,
                                 nsISupports **aResult);
 
 public:
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
@@ -714,49 +742,45 @@ protected:
   nsHTMLCollectionSH(nsDOMClassInfoData* aData) : nsNamedArraySH(aData)
   {
   }
 
   virtual ~nsHTMLCollectionSH()
   {
   }
 
-  // Override nsArraySH::GetItemAt() since our list isn't a
-  // nsIDOMNodeList
-  virtual nsresult GetItemAt(nsISupports *aNative, PRUint32 aIndex,
-                             nsISupports **aResult);
+  virtual nsISupports* GetItemAt(nsISupports *aNative, PRUint32 aIndex,
+                                 nsresult *aResult);
 
   // Override nsNamedArraySH::GetNamedItem()
   virtual nsresult GetNamedItem(nsISupports *aNative, const nsAString& aName,
                                 nsISupports **aResult);
 
 public:
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
     return new nsHTMLCollectionSH(aData);
   }
 };
 
 
 // ContentList helper
 
-class nsContentListSH : public nsHTMLCollectionSH
+class nsContentListSH : public nsNodeListSH
 {
 protected:
-  nsContentListSH(nsDOMClassInfoData* aData) : nsHTMLCollectionSH(aData)
-  {
-  }
-
-  virtual ~nsContentListSH()
+  nsContentListSH(nsDOMClassInfoData* aData) : nsNodeListSH(aData)
   {
   }
 
 public:
   NS_IMETHOD PreCreate(nsISupports *nativeObj, JSContext *cx,
                        JSObject *globalObj, JSObject **parentObj);
+  NS_IMETHOD GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
+                         JSObject *obj, jsval id, jsval *vp, PRBool *_retval);
 
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
     return new nsContentListSH(aData);
   }
 };
 
 
@@ -1062,20 +1086,18 @@ protected:
   nsPluginSH(nsDOMClassInfoData* aData) : nsNamedArraySH(aData)
   {
   }
 
   virtual ~nsPluginSH()
   {
   }
 
-  // Override nsArraySH::GetItemAt() since our list isn't a
-  // nsIDOMNodeList
-  virtual nsresult GetItemAt(nsISupports *aNative, PRUint32 aIndex,
-                             nsISupports **aResult);
+  virtual nsISupports* GetItemAt(nsISupports *aNative, PRUint32 aIndex,
+                                 nsresult *aResult);
 
   // Override nsNamedArraySH::GetNamedItem()
   virtual nsresult GetNamedItem(nsISupports *aNative, const nsAString& aName,
                                 nsISupports **aResult);
 
 public:
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
@@ -1092,20 +1114,18 @@ protected:
   nsPluginArraySH(nsDOMClassInfoData* aData) : nsNamedArraySH(aData)
   {
   }
 
   virtual ~nsPluginArraySH()
   {
   }
 
-  // Override nsArraySH::GetItemAt() since our list isn't a
-  // nsIDOMNodeList
-  virtual nsresult GetItemAt(nsISupports *aNative, PRUint32 aIndex,
-                             nsISupports **aResult);
+  virtual nsISupports* GetItemAt(nsISupports *aNative, PRUint32 aIndex,
+                                 nsresult *aResult);
 
   // Override nsNamedArraySH::GetNamedItem()
   virtual nsresult GetNamedItem(nsISupports *aNative, const nsAString& aName,
                                 nsISupports **aResult);
 
 public:
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
@@ -1122,20 +1142,18 @@ protected:
   nsMimeTypeArraySH(nsDOMClassInfoData* aData) : nsNamedArraySH(aData)
   {
   }
 
   virtual ~nsMimeTypeArraySH()
   {
   }
 
-  // Override nsArraySH::GetItemAt() since our list isn't a
-  // nsIDOMNodeList
-  virtual nsresult GetItemAt(nsISupports *aNative, PRUint32 aIndex,
-                             nsISupports **aResult);
+  virtual nsISupports* GetItemAt(nsISupports *aNative, PRUint32 aIndex,
+                                 nsresult *aResult);
 
   // Override nsNamedArraySH::GetNamedItem()
   virtual nsresult GetNamedItem(nsISupports *aNative, const nsAString& aName,
                                 nsISupports **aResult);
 
 public:
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
@@ -1250,20 +1268,18 @@ protected:
   nsStyleSheetListSH(nsDOMClassInfoData* aData) : nsArraySH(aData)
   {
   }
 
   virtual ~nsStyleSheetListSH()
   {
   }
 
-  // Override nsArraySH::GetItemAt() since our list isn't a
-  // nsIDOMNodeList
-  virtual nsresult GetItemAt(nsISupports *aNative, PRUint32 aIndex,
-                             nsISupports **aResult);
+  virtual nsISupports* GetItemAt(nsISupports *aNative, PRUint32 aIndex,
+                                 nsresult *aResult);
 
 public:
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
     return new nsStyleSheetListSH(aData);
   }
 };
 
@@ -1276,20 +1292,18 @@ protected:
   nsCSSValueListSH(nsDOMClassInfoData* aData) : nsArraySH(aData)
   {
   }
 
   virtual ~nsCSSValueListSH()
   {
   }
 
-  // Override nsArraySH::GetItemAt() since our list isn't a
-  // nsIDOMNodeList
-  virtual nsresult GetItemAt(nsISupports *aNative, PRUint32 aIndex,
-                             nsISupports **aResult);
+  virtual nsISupports* GetItemAt(nsISupports *aNative, PRUint32 aIndex,
+                                 nsresult *aResult);
 
 public:
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
     return new nsCSSValueListSH(aData);
   }
 };
 
@@ -1326,20 +1340,18 @@ protected:
   nsCSSRuleListSH(nsDOMClassInfoData* aData) : nsArraySH(aData)
   {
   }
 
   virtual ~nsCSSRuleListSH()
   {
   }
 
-  // Override nsArraySH::GetItemAt() since our list isn't a
-  // nsIDOMNodeList
-  virtual nsresult GetItemAt(nsISupports *aNative, PRUint32 aIndex,
-                             nsISupports **aResult);
+  virtual nsISupports* GetItemAt(nsISupports *aNative, PRUint32 aIndex,
+                                 nsresult *aResult);
 
 public:
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
     return new nsCSSRuleListSH(aData);
   }
 };
 
@@ -1351,20 +1363,18 @@ protected:
   nsClientRectListSH(nsDOMClassInfoData* aData) : nsArraySH(aData)
   {
   }
 
   virtual ~nsClientRectListSH()
   {
   }
 
-  // Override nsArraySH::GetItemAt() since our list isn't a
-  // nsIDOMNodeList
-  virtual nsresult GetItemAt(nsISupports *aNative, PRUint32 aIndex,
-                             nsISupports **aResult);
+  virtual nsISupports* GetItemAt(nsISupports *aNative, PRUint32 aIndex,
+                                 nsresult *aResult);
 
 public:
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
     return new nsClientRectListSH(aData);
   }
 };
 
@@ -1378,20 +1388,18 @@ protected:
   nsTreeColumnsSH(nsDOMClassInfoData* aData) : nsNamedArraySH(aData)
   {
   }
 
   virtual ~nsTreeColumnsSH()
   {
   }
 
-  // Override nsArraySH::GetItemAt() since our list isn't a
-  // nsIDOMNodeList
-  virtual nsresult GetItemAt(nsISupports *aNative, PRUint32 aIndex,
-                             nsISupports **aResult);
+  virtual nsISupports* GetItemAt(nsISupports *aNative, PRUint32 aIndex,
+                                 nsresult *aResult);
 
   // Override nsNamedArraySH::GetNamedItem()
   virtual nsresult GetNamedItem(nsISupports *aNative, const nsAString& aName,
                                 nsISupports **aResult);
 
 public:
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
@@ -1419,16 +1427,21 @@ protected:
   NS_IMETHOD SetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
                          JSObject *obj, jsval id, jsval *vp, PRBool *_retval);
   NS_IMETHOD DelProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
                          JSObject *obj, jsval id, jsval *vp, PRBool *_retval);
   NS_IMETHOD NewEnumerate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
                           JSObject *obj, PRUint32 enum_op, jsval *statep,
                           jsid *idp, PRBool *_retval);
 
+  virtual nsISupports* GetItemAt(nsISupports *aNative, PRUint32 aIndex,
+                                 nsresult *aResult)
+  {
+    return nsnull;
+  }
   // Override nsNamedArraySH::GetNamedItem()
   virtual nsresult GetNamedItem(nsISupports *aNative, const nsAString& aName,
                                 nsISupports **aResult);
 
 public:
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
     return new nsStorageSH(aData);
@@ -1441,16 +1454,21 @@ protected:
   nsStorageListSH(nsDOMClassInfoData* aData) : nsNamedArraySH(aData)
   {
   }
 
   virtual ~nsStorageListSH()
   {
   }
 
+  virtual nsISupports* GetItemAt(nsISupports *aNative, PRUint32 aIndex,
+                                 nsresult *aResult)
+  {
+    return nsnull;
+  }
   // Override nsNamedArraySH::GetNamedItem()
   virtual nsresult GetNamedItem(nsISupports *aNative, const nsAString& aName,
                                 nsISupports **aResult);
 
 public:
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
     return new nsStorageListSH(aData);
@@ -1566,50 +1584,29 @@ protected:
 
 public:
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
     return new nsOfflineResourceListSH(aData);
   }
 };
 
-class nsLoadStatusListSH : public nsArraySH
-{
-protected:
-  nsLoadStatusListSH(nsDOMClassInfoData *aData) : nsArraySH(aData)
-  {
-  }
-
-  virtual ~nsLoadStatusListSH()
-  {
-  }
-
-  virtual nsresult GetItemAt(nsISupports *aNative, PRUint32 aIndex,
-                             nsISupports **aResult);
-
-public:
-  static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
-  {
-    return new nsLoadStatusListSH(aData);
-  }
-};
-
 class nsFileListSH : public nsArraySH
 {
 protected:
   nsFileListSH(nsDOMClassInfoData *aData) : nsArraySH(aData)
   {
   }
 
   virtual ~nsFileListSH()
   {
   }
 
-  virtual nsresult GetItemAt(nsISupports *aNative, PRUint32 aIndex,
-                             nsISupports **aResult);
+  virtual nsISupports* GetItemAt(nsISupports *aNative, PRUint32 aIndex,
+                                 nsresult *aResult);
 
 public:
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
     return new nsFileListSH(aData);
   }
 };
 
--- a/dom/src/base/nsGlobalWindow.h
+++ b/dom/src/base/nsGlobalWindow.h
@@ -119,17 +119,16 @@ class nsHistory;
 class nsIDocShellLoadInfo;
 class WindowStateHolder;
 class nsGlobalWindowObserver;
 class nsGlobalWindow;
 class nsDummyJavaPluginOwner;
 class PostMessageEvent;
 
 class nsDOMOfflineResourceList;
-class nsDOMOfflineLoadStatusList;
 class nsGeolocation;
 
 // permissible values for CheckOpenAllow
 enum OpenAllowValue {
   allowNot = 0,     // the window opening is denied
   allowNoAbuse,     // allowed: not a popup
   allowWhitelisted  // allowed: it's whitelisted or popup blocking is disabled
 };
--- a/dom/src/base/nsMimeTypeArray.cpp
+++ b/dom/src/base/nsMimeTypeArray.cpp
@@ -80,30 +80,44 @@ nsMimeTypeArray::GetLength(PRUint32* aLe
     nsresult rv = GetMimeTypes();
     if (rv != NS_OK)
       return rv;
   }
   *aLength = mMimeTypeCount;
   return NS_OK;
 }
 
+nsIDOMMimeType*
+nsMimeTypeArray::GetItemAt(PRUint32 aIndex, nsresult *aResult)
+{
+  if (mMimeTypeArray == nsnull) {
+    *aResult = GetMimeTypes();
+    if (*aResult != NS_OK)
+      return nsnull;
+  }
+
+  if (aIndex >= mMimeTypeCount) {
+    *aResult = NS_ERROR_FAILURE;
+
+    return nsnull;
+  }
+
+  *aResult = NS_OK;
+
+  return mMimeTypeArray[aIndex];
+}
+
 NS_IMETHODIMP
 nsMimeTypeArray::Item(PRUint32 aIndex, nsIDOMMimeType** aReturn)
 {
-  if (mMimeTypeArray == nsnull) {
-    nsresult rv = GetMimeTypes();
-    if (rv != NS_OK)
-      return rv;
-  }
-  if (aIndex < mMimeTypeCount) {
-    *aReturn = mMimeTypeArray[aIndex];
-    NS_IF_ADDREF(*aReturn);
-    return NS_OK;
-  }
-  return NS_ERROR_FAILURE;
+  nsresult rv;
+
+  NS_IF_ADDREF(*aReturn = GetItemAt(aIndex, &rv));
+
+  return rv;
 }
 
 NS_IMETHODIMP
 nsMimeTypeArray::NamedItem(const nsAString& aName, nsIDOMMimeType** aReturn)
 {
   NS_ENSURE_ARG_POINTER(aReturn);
   *aReturn = nsnull;
 
--- a/dom/src/base/nsMimeTypeArray.h
+++ b/dom/src/base/nsMimeTypeArray.h
@@ -51,16 +51,35 @@ public:
   nsMimeTypeArray(nsIDOMNavigator* navigator);
   virtual ~nsMimeTypeArray();
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSIDOMMIMETYPEARRAY
 
   nsresult Refresh();
 
+  nsIDOMMimeType* GetItemAt(PRUint32 aIndex, nsresult* aResult);
+
+  static nsMimeTypeArray* FromSupports(nsISupports* aSupports)
+  {
+#ifdef DEBUG
+    {
+      nsCOMPtr<nsIDOMMimeTypeArray> array_qi = do_QueryInterface(aSupports);
+
+      // If this assertion fires the QI implementation for the object in
+      // question doesn't use the nsIDOMMimeTypeArray pointer as the nsISupports
+      // pointer. That must be fixed, or we'll crash...
+      NS_ASSERTION(array_qi == static_cast<nsIDOMMimeTypeArray*>(aSupports),
+                   "Uh, fix QI!");
+    }
+#endif
+
+    return static_cast<nsMimeTypeArray*>(aSupports);
+  }
+
 private:
   nsresult GetMimeTypes();
   void     Clear();
 
 protected:
   nsIDOMNavigator* mNavigator;
   PRUint32 mMimeTypeCount;
   nsIDOMMimeType** mMimeTypeArray;
--- a/dom/src/base/nsPluginArray.cpp
+++ b/dom/src/base/nsPluginArray.cpp
@@ -100,37 +100,41 @@ nsPluginArray::AllowPlugins()
   PRBool allowPlugins = PR_FALSE;
   if (mDocShell)
     if (NS_FAILED(mDocShell->GetAllowPlugins(&allowPlugins)))
       allowPlugins = PR_FALSE;
 
   return allowPlugins;
 }
 
+nsIDOMPlugin*
+nsPluginArray::GetItemAt(PRUint32 aIndex, nsresult* aResult)
+{
+  *aResult = NS_OK;
+
+  if (!AllowPlugins())
+    return nsnull;
+
+  if (mPluginArray == nsnull) {
+    *aResult = GetPlugins();
+    if (*aResult != NS_OK)
+      return nsnull;
+  }
+
+  return aIndex < mPluginCount ? mPluginArray[aIndex] : nsnull;
+}
+
 NS_IMETHODIMP
 nsPluginArray::Item(PRUint32 aIndex, nsIDOMPlugin** aReturn)
 {
-  NS_PRECONDITION(nsnull != aReturn, "null arg");
-  *aReturn = nsnull;
-
-  if (!AllowPlugins())
-    return NS_OK;
+  nsresult rv;
 
-  if (mPluginArray == nsnull) {
-    nsresult rv = GetPlugins();
-    if (rv != NS_OK)
-      return rv;
-  }
+  NS_IF_ADDREF(*aReturn = GetItemAt(aIndex, &rv));
 
-  if (aIndex < mPluginCount) {
-    *aReturn = mPluginArray[aIndex];
-    NS_IF_ADDREF(*aReturn);
-  }
-
-  return NS_OK;
+  return rv;
 }
 
 NS_IMETHODIMP
 nsPluginArray::NamedItem(const nsAString& aName, nsIDOMPlugin** aReturn)
 {
   NS_PRECONDITION(nsnull != aReturn, "null arg");
   *aReturn = nsnull;
 
@@ -325,31 +329,44 @@ nsPluginElement::GetName(nsAString& aNam
 }
 
 NS_IMETHODIMP
 nsPluginElement::GetLength(PRUint32* aLength)
 {
   return mPlugin->GetLength(aLength);
 }
 
+nsIDOMMimeType*
+nsPluginElement::GetItemAt(PRUint32 aIndex, nsresult *aResult)
+{
+  if (mMimeTypeArray == nsnull) {
+    *aResult = GetMimeTypes();
+    if (*aResult != NS_OK)
+      return nsnull;
+  }
+
+  if (aIndex >= mMimeTypeCount) {
+    *aResult = NS_ERROR_FAILURE;
+
+    return nsnull;
+  }
+
+  *aResult = NS_OK;
+
+  return mMimeTypeArray[aIndex];
+}
+
 NS_IMETHODIMP
 nsPluginElement::Item(PRUint32 aIndex, nsIDOMMimeType** aReturn)
 {
-  if (mMimeTypeArray == nsnull) {
-    nsresult rv = GetMimeTypes();
-    if (rv != NS_OK)
-      return rv;
-  }
-  if (aIndex < mMimeTypeCount) {
-    nsIDOMMimeType* mimeType = mMimeTypeArray[aIndex];
-    NS_IF_ADDREF(mimeType);
-    *aReturn = mimeType;
-    return NS_OK;
-  }
-  return NS_ERROR_FAILURE;
+  nsresult rv;
+
+  NS_IF_ADDREF(*aReturn = GetItemAt(aIndex, &rv));
+
+  return rv;
 }
 
 NS_IMETHODIMP
 nsPluginElement::NamedItem(const nsAString& aName, nsIDOMMimeType** aReturn)
 {
   if (mMimeTypeArray == nsnull) {
     nsresult rv = GetMimeTypes();
     if (rv != NS_OK)
--- a/dom/src/base/nsPluginArray.h
+++ b/dom/src/base/nsPluginArray.h
@@ -55,16 +55,35 @@ public:
 
   NS_DECL_ISUPPORTS
 
   // nsIDOMPluginArray
   NS_DECL_NSIDOMPLUGINARRAY
 
   nsresult GetPluginHost(nsIPluginHost** aPluginHost);
 
+  nsIDOMPlugin* GetItemAt(PRUint32 aIndex, nsresult* aResult);
+
+  static nsPluginArray* FromSupports(nsISupports* aSupports)
+  {
+#ifdef DEBUG
+    {
+      nsCOMPtr<nsIDOMPluginArray> array_qi = do_QueryInterface(aSupports);
+
+      // If this assertion fires the QI implementation for the object in
+      // question doesn't use the nsIDOMPluginArray pointer as the nsISupports
+      // pointer. That must be fixed, or we'll crash...
+      NS_ASSERTION(array_qi == static_cast<nsIDOMPluginArray*>(aSupports),
+                   "Uh, fix QI!");
+    }
+#endif
+
+    return static_cast<nsPluginArray*>(aSupports);
+  }
+
 private:
   nsresult GetPlugins();
   PRBool AllowPlugins();
 
 public:
   void SetDocShell(nsIDocShell* aDocShell);
 
 protected:
@@ -79,16 +98,35 @@ class nsPluginElement : public nsIDOMPlu
 {
 public:
   nsPluginElement(nsIDOMPlugin* plugin);
   virtual ~nsPluginElement();
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSIDOMPLUGIN
 
+  nsIDOMMimeType* GetItemAt(PRUint32 aIndex, nsresult* aResult);
+
+  static nsPluginElement* FromSupports(nsISupports* aSupports)
+  {
+#ifdef DEBUG
+    {
+      nsCOMPtr<nsIDOMPlugin> plugin_qi = do_QueryInterface(aSupports);
+
+      // If this assertion fires the QI implementation for the object in
+      // question doesn't use the nsIDOMPlugin pointer as the nsISupports
+      // pointer. That must be fixed, or we'll crash...
+      NS_ASSERTION(plugin_qi == static_cast<nsIDOMPlugin*>(aSupports),
+                   "Uh, fix QI!");
+    }
+#endif
+
+    return static_cast<nsPluginElement*>(aSupports);
+  }
+
 private:
   nsresult GetMimeTypes();
 
 protected:
   nsIDOMPlugin* mPlugin;
   PRUint32 mMimeTypeCount;
   nsIDOMMimeType** mMimeTypeArray;
 };
deleted file mode 100644
--- a/dom/src/offline/nsDOMOfflineLoadStatusList.cpp
+++ /dev/null
@@ -1,577 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is mozilla.org code.
- *
- * The Initial Developer of the Original Code is
- * Mozilla Corporation
- * Portions created by the Initial Developer are Copyright (C) 2007
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Dave Camp <dcamp@mozilla.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#include "nsDOMOfflineLoadStatusList.h"
-#include "nsDOMClassInfo.h"
-#include "nsIMutableArray.h"
-#include "nsCPrefetchService.h"
-#include "nsIObserverService.h"
-#include "nsIJSContextStack.h"
-#include "nsIScriptSecurityManager.h"
-#include "nsIContent.h"
-#include "nsNetCID.h"
-#include "nsICacheService.h"
-#include "nsICacheSession.h"
-#include "nsIOfflineCacheUpdate.h"
-#include "nsContentUtils.h"
-#include "nsDOMError.h"
-#include "nsNetUtil.h"
-#include "nsAutoPtr.h"
-
-#define LOADREQUESTED_STR "loadrequested"
-#define LOADCOMPLETED_STR "loadcompleted"
-
-//
-// nsDOMOfflineLoadStatus
-//
-
-// XXX
-//
-// nsDOMOfflineLoadStatusList has an array wrapper in its classinfo struct
-// (LoadStatusList) that exposes nsDOMOfflineLoadStatusList::Item() as
-// array items.
-//
-// For scripts to recognize these as nsIDOMLoadStatus objects, I needed
-// to add a LoadStatus classinfo.
-//
-// Because the prefetch service is outside the dom module, it can't
-// actually use the LoadStatus classinfo.
-//
-// nsDOMOfflineLoadStatus is just a simple wrapper around the
-// nsIDOMLoadStatus objects returned by the prefetch service that adds the
-// LoadStatus classinfo implementation.
-//
-// Is there a better way around this?
-
-class nsDOMOfflineLoadStatus : public nsIDOMLoadStatus
-{
-public:
-  NS_DECL_ISUPPORTS
-  NS_DECL_NSIDOMLOADSTATUS
-
-  nsDOMOfflineLoadStatus(nsIDOMLoadStatus *status);
-  virtual ~nsDOMOfflineLoadStatus();
-
-  const nsIDOMLoadStatus *Implementation() { return mStatus; }
-private:
-  nsCOMPtr<nsIDOMLoadStatus> mStatus;
-};
-
-NS_INTERFACE_MAP_BEGIN(nsDOMOfflineLoadStatus)
-  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMLoadStatus)
-  NS_INTERFACE_MAP_ENTRY(nsIDOMLoadStatus)
-  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(LoadStatus)
-NS_INTERFACE_MAP_END
-
-NS_IMPL_ADDREF(nsDOMOfflineLoadStatus)
-NS_IMPL_RELEASE(nsDOMOfflineLoadStatus)
-
-nsDOMOfflineLoadStatus::nsDOMOfflineLoadStatus(nsIDOMLoadStatus *aStatus)
-  : mStatus(aStatus)
-{
-}
-
-nsDOMOfflineLoadStatus::~nsDOMOfflineLoadStatus()
-{
-}
-
-NS_IMETHODIMP
-nsDOMOfflineLoadStatus::GetSource(nsIDOMNode **aSource)
-{
-  return mStatus->GetSource(aSource);
-}
-
-NS_IMETHODIMP
-nsDOMOfflineLoadStatus::GetUri(nsAString &aURI)
-{
-  return mStatus->GetUri(aURI);
-}
-
-NS_IMETHODIMP
-nsDOMOfflineLoadStatus::GetTotalSize(PRInt32 *aTotalSize)
-{
-  return mStatus->GetTotalSize(aTotalSize);
-}
-
-NS_IMETHODIMP
-nsDOMOfflineLoadStatus::GetLoadedSize(PRInt32 *aLoadedSize)
-{
-  return mStatus->GetLoadedSize(aLoadedSize);
-}
-
-NS_IMETHODIMP
-nsDOMOfflineLoadStatus::GetReadyState(PRUint16 *aReadyState)
-{
-  return mStatus->GetReadyState(aReadyState);
-}
-
-NS_IMETHODIMP
-nsDOMOfflineLoadStatus::GetStatus(PRUint16 *aStatus)
-{
-  return mStatus->GetStatus(aStatus);
-}
-
-//
-// nsDOMOfflineLoadStatusList
-//
-
-NS_INTERFACE_MAP_BEGIN(nsDOMOfflineLoadStatusList)
-  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMLoadStatusList)
-  NS_INTERFACE_MAP_ENTRY(nsIDOMLoadStatusList)
-  NS_INTERFACE_MAP_ENTRY(nsIDOMEventTarget)
-  NS_INTERFACE_MAP_ENTRY(nsIObserver)
-  NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
-  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(LoadStatusList)
-NS_INTERFACE_MAP_END
-
-NS_IMPL_ADDREF(nsDOMOfflineLoadStatusList)
-NS_IMPL_RELEASE(nsDOMOfflineLoadStatusList)
-
-nsDOMOfflineLoadStatusList::nsDOMOfflineLoadStatusList(nsIURI *aURI)
-  : mInitialized(PR_FALSE)
-  , mURI(aURI)
-{
-}
-
-nsDOMOfflineLoadStatusList::~nsDOMOfflineLoadStatusList()
-{
-  mLoadRequestedEventListeners.Clear();
-  mLoadCompletedEventListeners.Clear();
-}
-
-nsresult
-nsDOMOfflineLoadStatusList::Init()
-{
-  if (mInitialized) {
-    return NS_OK;
-  }
-
-  mInitialized = PR_TRUE;
-
-  nsresult rv = mURI->GetHostPort(mHostPort);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  nsCOMPtr<nsIOfflineCacheUpdateService> cacheUpdateService =
-    do_GetService(NS_OFFLINECACHEUPDATESERVICE_CONTRACTID, &rv);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  PRUint32 numUpdates;
-  rv = cacheUpdateService->GetNumUpdates(&numUpdates);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  for (PRUint32 i = 0; i < numUpdates; i++) {
-    nsCOMPtr<nsIOfflineCacheUpdate> cacheUpdate;
-    rv = cacheUpdateService->GetUpdate(i, getter_AddRefs(cacheUpdate));
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    UpdateAdded(cacheUpdate);
-    NS_ENSURE_SUCCESS(rv, rv);
-  }
-
-  // watch for new offline cache updates
-  nsCOMPtr<nsIObserverService> observerServ =
-    do_GetService("@mozilla.org/observer-service;1", &rv);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  rv = observerServ->AddObserver(this, "offline-cache-update-added", PR_TRUE);
-  NS_ENSURE_SUCCESS(rv, rv);
-  rv = observerServ->AddObserver(this, "offline-cache-update-completed", PR_TRUE);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  return NS_OK;
-}
-
-nsIDOMLoadStatus *
-nsDOMOfflineLoadStatusList::FindWrapper(nsIDOMLoadStatus *aStatus,
-                                        PRUint32 *index)
-{
-  for (int i = 0; i < mItems.Count(); i++) {
-    nsDOMOfflineLoadStatus *item = static_cast<nsDOMOfflineLoadStatus*>
-                                              (mItems[i]);
-    if (item->Implementation() == aStatus) {
-      *index = i;
-      return mItems[i];
-    }
-  }
-
-  return nsnull;
-}
-
-nsresult
-nsDOMOfflineLoadStatusList::UpdateAdded(nsIOfflineCacheUpdate *aUpdate)
-{
-  nsCAutoString owner;
-  nsresult rv = aUpdate->GetUpdateDomain(owner);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  if (owner != mHostPort) {
-    // This update doesn't belong to us
-    return NS_OK;
-  }
-
-  PRUint32 numItems;
-  rv = aUpdate->GetCount(&numItems);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  for (PRUint32 i = 0; i < numItems; i++) {
-    nsCOMPtr<nsIDOMLoadStatus> status;
-    rv = aUpdate->Item(i, getter_AddRefs(status));
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    nsDOMOfflineLoadStatus *wrapper = new nsDOMOfflineLoadStatus(status);
-    if (!wrapper) return NS_ERROR_OUT_OF_MEMORY;
-
-    mItems.AppendObject(wrapper);
-
-    SendLoadEvent(NS_LITERAL_STRING(LOADREQUESTED_STR),
-                  mLoadRequestedEventListeners,
-                  wrapper);
-  }
-
-  return NS_OK;
-}
-
-nsresult
-nsDOMOfflineLoadStatusList::UpdateCompleted(nsIOfflineCacheUpdate *aUpdate)
-{
-  nsCAutoString owner;
-  nsresult rv = aUpdate->GetUpdateDomain(owner);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  if (owner != mHostPort) {
-    // This update doesn't belong to us
-    return NS_OK;
-  }
-
-  PRUint32 numItems;
-  rv = aUpdate->GetCount(&numItems);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  for (PRUint32 i = 0; i < numItems; i++) {
-    nsCOMPtr<nsIDOMLoadStatus> status;
-    rv = aUpdate->Item(i, getter_AddRefs(status));
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    PRUint32 index;
-    nsCOMPtr<nsIDOMLoadStatus> wrapper = FindWrapper(status, &index);
-    if (wrapper) {
-      mItems.RemoveObjectAt(index);
-      nsresult rv = SendLoadEvent(NS_LITERAL_STRING(LOADCOMPLETED_STR),
-                                  mLoadCompletedEventListeners,
-                                  wrapper);
-      NS_ENSURE_SUCCESS(rv, rv);
-    }
-  }
-
-  return NS_OK;
-}
-
-
-//
-// nsDOMOfflineLoadStatusList::nsIDOMLoadStatusList
-//
-
-NS_IMETHODIMP
-nsDOMOfflineLoadStatusList::GetLength(PRUint32 *aLength)
-{
-  nsresult rv = Init();
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  *aLength = mItems.Count();
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsDOMOfflineLoadStatusList::Item(PRUint32 aItem, nsIDOMLoadStatus **aStatus)
-{
-  nsresult rv = Init();
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  if ((PRInt32)aItem >= mItems.Count()) return NS_ERROR_DOM_INDEX_SIZE_ERR;
-
-  NS_ADDREF(*aStatus = mItems[aItem]);
-
-  return NS_OK;
-}
-
-//
-// nsDOMOfflineLoadStatusList::nsIDOMEventTarget
-//
-
-static nsIScriptContext *
-GetCurrentContext()
-{
-  // Get JSContext from stack.
-  nsCOMPtr<nsIJSContextStack> stack =
-    do_GetService("@mozilla.org/js/xpc/ContextStack;1");
-
-  if (!stack) {
-    return nsnull;
-  }
-
-  JSContext *cx;
-
-  if (NS_FAILED(stack->Peek(&cx)) || !cx) {
-    return nsnull;
-  }
-
-  return GetScriptContextFromJSContext(cx);
-}
-
-NS_IMETHODIMP
-nsDOMOfflineLoadStatusList::AddEventListener(const nsAString& aType,
-                                             nsIDOMEventListener *aListener,
-                                             PRBool aUseCapture)
-{
-  nsresult rv = Init();
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  NS_ENSURE_ARG(aListener);
-
-  nsCOMArray<nsIDOMEventListener> *array;
-
-#define IMPL_ADD_LISTENER(_type, _member)    \
-  if (aType.EqualsLiteral(_type)) {           \
-    array = &(_member);                      \
-  } else
-
-  IMPL_ADD_LISTENER(LOADREQUESTED_STR, mLoadRequestedEventListeners)
-  IMPL_ADD_LISTENER(LOADCOMPLETED_STR, mLoadCompletedEventListeners)
-  {
-    return NS_ERROR_INVALID_ARG;
-  }
-
-  array->AppendObject(aListener);
-  mScriptContext = GetCurrentContext();
-#undef IMPL_ADD_LISTENER
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsDOMOfflineLoadStatusList::RemoveEventListener(const nsAString &aType,
-                                                nsIDOMEventListener *aListener,
-                                                PRBool aUseCapture)
-{
-  nsresult rv = Init();
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  NS_ENSURE_ARG(aListener);
-
-  nsCOMArray<nsIDOMEventListener> *array;
-
-#define IMPL_REMOVE_LISTENER(_type, _member)  \
-  if (aType.EqualsLiteral(_type)) {            \
-    array = &(_member);                       \
-  } else
-
-  IMPL_REMOVE_LISTENER(LOADREQUESTED_STR, mLoadRequestedEventListeners)
-  IMPL_REMOVE_LISTENER(LOADCOMPLETED_STR, mLoadCompletedEventListeners)
-  {
-    return NS_ERROR_INVALID_ARG;
-  }
-
-  // Allow a caller to remove O(N^2) behavior by removing end-to-start.
-  for (PRUint32 i = array->Count() - 1; i != PRUint32(-1); --i) {
-    if (array->ObjectAt(i) == aListener) {
-      array->RemoveObjectAt(i);
-      break;
-    }
-  }
-
-#undef IMPL_ADD_LISTENER
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsDOMOfflineLoadStatusList::DispatchEvent(nsIDOMEvent *evt, PRBool *_retval)
-{
-  // Ignored
-
-  return NS_OK;
-}
-
-void
-nsDOMOfflineLoadStatusList::NotifyEventListeners(const nsCOMArray<nsIDOMEventListener>& aListeners,
-                                                 nsIDOMEvent* aEvent)
-{
-  // XXXbz wouldn't it be easier to just have an actual nsEventListenerManager
-  // to work with or something?  I feel like we're duplicating code here...
-  //
-  // (and this was duplicated from XMLHttpRequest)
-  if (!aEvent)
-    return;
-
-  nsCOMPtr<nsIJSContextStack> stack;
-  JSContext *cx = nsnull;
-
-  if (mScriptContext) {
-    stack = do_GetService("@mozilla.org/js/xpc/ContextStack;1");
-
-    if (stack) {
-      cx = (JSContext *)mScriptContext->GetNativeContext();
-
-      if (cx) {
-        stack->Push(cx);
-      }
-    }
-  }
-
-  PRInt32 count = aListeners.Count();
-  for (PRInt32 index = 0; index < count; ++index) {
-    nsIDOMEventListener* listener = aListeners[index];
-
-    if (listener) {
-      listener->HandleEvent(aEvent);
-    }
-  }
-
-  if (cx) {
-    stack->Pop(&cx);
-  }
-}
-
-nsresult
-nsDOMOfflineLoadStatusList::SendLoadEvent(const nsAString &aEventName,
-                                          const nsCOMArray<nsIDOMEventListener> &aListeners,
-                                          nsIDOMLoadStatus *aStatus)
-{
-  NS_ENSURE_ARG(aStatus);
-
-  if (aListeners.Count() == 0) return NS_OK;
-
-  nsRefPtr<nsDOMLoadStatusEvent> event = new nsDOMLoadStatusEvent(aEventName,
-                                                                  aStatus);
-  if (!event) return NS_ERROR_OUT_OF_MEMORY;
-
-  nsresult rv = event->Init();
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  NotifyEventListeners(aListeners,
-                       static_cast<nsIDOMLoadStatusEvent*>(event));
-
-  return NS_OK;
-}
-
-//
-// nsDOMLoadStatusList::nsIObserver
-//
-NS_IMETHODIMP
-nsDOMOfflineLoadStatusList::Observe(nsISupports *aSubject,
-                                    const char *aTopic,
-                                    const PRUnichar *aData)
-{
-  if (!strcmp(aTopic, "offline-cache-update-added")) {
-    nsCOMPtr<nsIOfflineCacheUpdate> update = do_QueryInterface(aSubject);
-    if (update) {
-      UpdateAdded(update);
-    }
-  } else if (!strcmp(aTopic, "offline-cache-update-completed")) {
-    nsCOMPtr<nsIOfflineCacheUpdate> update = do_QueryInterface(aSubject);
-    if (update) {
-      UpdateCompleted(update);
-    }
-  }
-
-  return NS_OK;
-}
-
-//
-// nsDOMLoadStatusEvent
-//
-
-NS_INTERFACE_MAP_BEGIN(nsDOMLoadStatusEvent)
-  NS_INTERFACE_MAP_ENTRY(nsIDOMLoadStatusEvent)
-  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(LoadStatusEvent)
-NS_INTERFACE_MAP_END_INHERITING(nsDOMEvent)
-
-NS_IMPL_ADDREF_INHERITED(nsDOMLoadStatusEvent, nsDOMEvent)
-NS_IMPL_RELEASE_INHERITED(nsDOMLoadStatusEvent, nsDOMEvent)
-
-nsresult
-nsDOMLoadStatusEvent::Init()
-{
-  nsresult rv = InitEvent(mEventName, PR_TRUE, PR_FALSE);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  // This init method is only called by native code, so set the
-  // trusted flag there.
-  SetTrusted(PR_TRUE);
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsDOMLoadStatusEvent::InitLoadStatusEvent(const nsAString& aTypeArg,
-                                          PRBool aCanBubbleArg,
-                                          PRBool aCancelableArg,
-                                          nsIDOMLoadStatus* aStatusArg)
-{
-  nsresult rv = InitEvent(aTypeArg, aCanBubbleArg, aCancelableArg);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  mStatus = aStatusArg;
-
-  return NS_OK;
-}
-
-
-NS_IMETHODIMP
-nsDOMLoadStatusEvent::InitLoadStatusEventNS(const nsAString& aNamespaceURIArg,
-                                            const nsAString& aTypeArg,
-                                            PRBool aCanBubbleArg,
-                                            PRBool aCancelableArg,
-                                            nsIDOMLoadStatus* aStatusArg)
-{
-  // XXX: Figure out what to do with aNamespaceURIArg here!
-  nsresult rv = InitEvent(aTypeArg, aCanBubbleArg, aCancelableArg);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  mStatus = aStatusArg;
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsDOMLoadStatusEvent::GetStatus(nsIDOMLoadStatus **aStatus)
-{
-  NS_ADDREF(*aStatus = mStatus);
-
-  return NS_OK;
-}
--- a/layout/style/Makefile.in
+++ b/layout/style/Makefile.in
@@ -97,16 +97,17 @@ EXPORTS		= \
 		nsICSSImportRule.h \
 		nsICSSLoader.h \
 		nsICSSLoaderObserver.h \
 		nsICSSNameSpaceRule.h \
 		nsICSSOMFactory.h \
 		nsICSSParser.h \
 		nsICSSPseudoComparator.h \
 		nsICSSRule.h \
+		nsICSSRuleList.h \
 		nsICSSStyleRule.h \
 		nsICSSStyleRuleDOMWrapper.h \
 		nsICSSStyleSheet.h \
 		nsIComputedDOMStyle.h \
 		nsIHTMLCSSStyleSheet.h \
 		nsIInspectorCSSUtils.h \
 		nsIStyleRule.h \
 		nsIStyleRuleProcessor.h \
--- a/layout/style/nsCSSRules.cpp
+++ b/layout/style/nsCSSRules.cpp
@@ -56,52 +56,53 @@
 #include "nsIDOMCSSRule.h"
 #include "nsIDOMCSSImportRule.h"
 #include "nsIDOMCSSMediaRule.h"
 #include "nsIDOMCSSMozDocumentRule.h"
 #include "nsIDOMCSSCharsetRule.h"
 #include "nsIDOMCSSStyleDeclaration.h"
 #include "nsIMediaList.h"
 #include "nsIDOMMediaList.h"
-#include "nsIDOMCSSRuleList.h"
+#include "nsICSSRuleList.h"
 #include "nsIDOMStyleSheet.h"
 #include "nsIDocument.h"
 #include "nsPresContext.h"
 
 #include "nsContentUtils.h"
 #include "nsStyleConsts.h"
 #include "nsDOMError.h"
 #include "nsStyleUtil.h"
 #include "nsCSSDeclaration.h"
 
 #define IMPL_STYLE_RULE_INHERIT(_class, super) \
 NS_IMETHODIMP _class::GetStyleSheet(nsIStyleSheet*& aSheet) const { return super::GetStyleSheet(aSheet); }  \
 NS_IMETHODIMP _class::SetStyleSheet(nsICSSStyleSheet* aSheet) { return super::SetStyleSheet(aSheet); }  \
 NS_IMETHODIMP _class::SetParentRule(nsICSSGroupRule* aRule) { return super::SetParentRule(aRule); }  \
-NS_IMETHODIMP _class::GetDOMRule(nsIDOMCSSRule** aDOMRule) { return CallQueryInterface(this, aDOMRule); }  \
+nsIDOMCSSRule* _class::GetDOMRuleWeak(nsresult *aResult) { *aResult = NS_OK; return this; }  \
 NS_IMETHODIMP _class::MapRuleInfoInto(nsRuleData* aRuleData) { return NS_OK; } 
 
 #define IMPL_STYLE_RULE_INHERIT2(_class, super) \
 NS_IMETHODIMP _class::GetStyleSheet(nsIStyleSheet*& aSheet) const { return super::GetStyleSheet(aSheet); }  \
 NS_IMETHODIMP _class::SetParentRule(nsICSSGroupRule* aRule) { return super::SetParentRule(aRule); }  \
-NS_IMETHODIMP _class::GetDOMRule(nsIDOMCSSRule** aDOMRule) { return CallQueryInterface(this, aDOMRule); }  \
 NS_IMETHODIMP _class::MapRuleInfoInto(nsRuleData* aRuleData) { return NS_OK; } 
 
 // -------------------------------
 // Style Rule List for group rules
 //
-class CSSGroupRuleRuleListImpl : public nsIDOMCSSRuleList
+class CSSGroupRuleRuleListImpl : public nsICSSRuleList
 {
 public:
   CSSGroupRuleRuleListImpl(nsICSSGroupRule *aGroupRule);
 
   NS_DECL_ISUPPORTS
 
   NS_DECL_NSIDOMCSSRULELIST
 
+  virtual nsIDOMCSSRule* GetItemAt(PRUint32 aIndex, nsresult* aResult);
+
   void DropReference() { mGroupRule = nsnull; }
 
 protected:
   virtual ~CSSGroupRuleRuleListImpl(void);
 
 private:
   nsICSSGroupRule* mGroupRule;
 };
@@ -114,16 +115,17 @@ CSSGroupRuleRuleListImpl::CSSGroupRuleRu
 }
 
 CSSGroupRuleRuleListImpl::~CSSGroupRuleRuleListImpl()
 {
 }
 
 // QueryInterface implementation for CSSGroupRuleRuleList
 NS_INTERFACE_MAP_BEGIN(CSSGroupRuleRuleListImpl)
+  NS_INTERFACE_MAP_ENTRY(nsICSSRuleList)
   NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRuleList)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(CSSGroupRuleRuleList)
 NS_INTERFACE_MAP_END
 
 
 NS_IMPL_ADDREF(CSSGroupRuleRuleListImpl)
 NS_IMPL_RELEASE(CSSGroupRuleRuleListImpl)
@@ -137,34 +139,49 @@ CSSGroupRuleRuleListImpl::GetLength(PRUi
     *aLength = (PRUint32)count;
   } else {
     *aLength = 0;
   }
 
   return NS_OK;
 }
 
-NS_IMETHODIMP    
-CSSGroupRuleRuleListImpl::Item(PRUint32 aIndex, nsIDOMCSSRule** aReturn)
+nsIDOMCSSRule*    
+CSSGroupRuleRuleListImpl::GetItemAt(PRUint32 aIndex, nsresult* aResult)
 {
   nsresult result = NS_OK;
 
-  *aReturn = nsnull;
   if (mGroupRule) {
     nsCOMPtr<nsICSSRule> rule;
 
     result = mGroupRule->GetStyleRuleAt(aIndex, *getter_AddRefs(rule));
     if (rule) {
-      result = rule->GetDOMRule(aReturn);
-    } else if (result == NS_ERROR_ILLEGAL_VALUE) {
+      return rule->GetDOMRuleWeak(aResult);
+    }
+    if (result == NS_ERROR_ILLEGAL_VALUE) {
       result = NS_OK; // per spec: "Return Value ... null if ... not a valid index."
     }
   }
-  
-  return result;
+
+  *aResult = result;
+
+  return nsnull;
+}
+
+NS_IMETHODIMP    
+CSSGroupRuleRuleListImpl::Item(PRUint32 aIndex, nsIDOMCSSRule** aReturn)
+{
+  nsresult rv;
+  nsIDOMCSSRule* rule = GetItemAt(aIndex, &rv);
+  if (!rule) {
+    *aReturn = nsnull;
+    return rv;
+  }
+
+  return CallQueryInterface(rule, aReturn);
 }
 
 // -------------------------------------------
 // CharsetRule
 //
 class CSSCharsetRuleImpl : public nsCSSRule,
                            public nsICSSRule,
                            public nsIDOMCSSCharsetRule
--- a/layout/style/nsCSSRules.h
+++ b/layout/style/nsCSSRules.h
@@ -51,34 +51,37 @@
 #include "nsIDOMCSSStyleDeclaration.h"
 #include "nsAutoPtr.h"
 #include "nsCSSProperty.h"
 #include "nsCSSValue.h"
 
 class CSSGroupRuleRuleListImpl;
 class nsMediaList;
 
-#define DECL_STYLE_RULE_INHERIT  \
+#define DECL_STYLE_RULE_INHERIT_NO_DOMRULE  \
 NS_IMETHOD GetStyleSheet(nsIStyleSheet*& aSheet) const; \
 NS_IMETHOD SetStyleSheet(nsICSSStyleSheet* aSheet); \
 NS_IMETHOD SetParentRule(nsICSSGroupRule* aRule); \
-NS_IMETHOD GetDOMRule(nsIDOMCSSRule** aDOMRule); \
 NS_IMETHOD MapRuleInfoInto(nsRuleData* aRuleData);
 
+#define DECL_STYLE_RULE_INHERIT  \
+DECL_STYLE_RULE_INHERIT_NO_DOMRULE \
+nsIDOMCSSRule* GetDOMRuleWeak(nsresult* aResult);
+
 // inherits from nsCSSRule and also implements methods on nsICSSGroupRule
 // so they can be shared between nsCSSMediaRule and nsCSSDocumentRule
 class nsCSSGroupRule : public nsCSSRule, public nsICSSGroupRule
 {
 protected:
   nsCSSGroupRule();
   nsCSSGroupRule(const nsCSSGroupRule& aCopy);
   ~nsCSSGroupRule();
 
   // implement part of nsIStyleRule and nsICSSRule
-  DECL_STYLE_RULE_INHERIT
+  DECL_STYLE_RULE_INHERIT_NO_DOMRULE
 
   // to help implement nsIStyleRule
 #ifdef DEBUG
   NS_IMETHOD List(FILE* out = stdout, PRInt32 aIndent = 0) const;
 #endif
 
 public:
   // implement nsICSSGroupRule
@@ -123,16 +126,21 @@ public:
 #ifdef DEBUG
   NS_IMETHOD List(FILE* out = stdout, PRInt32 aIndent = 0) const;
 #endif
 
   // nsICSSRule methods
   NS_IMETHOD SetStyleSheet(nsICSSStyleSheet* aSheet); //override nsCSSGroupRule
   NS_IMETHOD GetType(PRInt32& aType) const;
   NS_IMETHOD Clone(nsICSSRule*& aClone) const;
+  nsIDOMCSSRule* GetDOMRuleWeak(nsresult *aResult)
+  {
+    *aResult = NS_OK;
+    return this;
+  }
 
   // nsIDOMCSSRule interface
   NS_DECL_NSIDOMCSSRULE
 
   // nsIDOMCSSMediaRule interface
   NS_DECL_NSIDOMCSSMEDIARULE
 
   // rest of nsICSSGroupRule interface
@@ -159,16 +167,21 @@ public:
   // nsIStyleRule methods
 #ifdef DEBUG
   NS_IMETHOD List(FILE* out = stdout, PRInt32 aIndent = 0) const;
 #endif
 
   // nsICSSRule methods
   NS_IMETHOD GetType(PRInt32& aType) const;
   NS_IMETHOD Clone(nsICSSRule*& aClone) const;
+  nsIDOMCSSRule* GetDOMRuleWeak(nsresult *aResult)
+  {
+    *aResult = NS_OK;
+    return this;
+  }
 
   // nsIDOMCSSRule interface
   NS_DECL_NSIDOMCSSRULE
 
   // nsIDOMCSSMozDocumentRule interface
   NS_DECL_NSIDOMCSSMOZDOCUMENTRULE
 
   // rest of nsICSSGroupRule interface
--- a/layout/style/nsCSSStyleRule.cpp
+++ b/layout/style/nsCSSStyleRule.cpp
@@ -1182,17 +1182,17 @@ public:
   virtual nsresult GetParentStyleSheet(nsICSSStyleSheet** aSheet);
   virtual nsresult GetParentRule(nsICSSGroupRule** aParentRule);
   virtual nsresult GetSelectorText(nsAString& aSelectorText);
   virtual nsresult SetSelectorText(const nsAString& aSelectorText);
 
   NS_IMETHOD GetType(PRInt32& aType) const;
   NS_IMETHOD Clone(nsICSSRule*& aClone) const;
 
-  NS_IMETHOD GetDOMRule(nsIDOMCSSRule** aDOMRule);
+  nsIDOMCSSRule* GetDOMRuleWeak(nsresult* aResult);
 
   virtual already_AddRefed<nsICSSStyleRule>
     DeclarationChanged(PRBool aHandleContainer);
 
   // The new mapping function.
   NS_IMETHOD MapRuleInfoInto(nsRuleData* aRuleData);
 
 #ifdef DEBUG
@@ -1371,36 +1371,34 @@ CSSStyleRuleImpl::Clone(nsICSSRule*& aCl
   if (!clone || !clone->mDeclaration || (!clone->mSelector != !mSelector)) {
     delete clone;
     aClone = nsnull;
     return NS_ERROR_OUT_OF_MEMORY;
   }
   return CallQueryInterface(clone, &aClone);
 }
 
-NS_IMETHODIMP
-CSSStyleRuleImpl::GetDOMRule(nsIDOMCSSRule** aDOMRule)
+nsIDOMCSSRule*
+CSSStyleRuleImpl::GetDOMRuleWeak(nsresult *aResult)
 {
+  *aResult = NS_OK;
   if (!mSheet) {
     // inline style rules aren't supposed to have a DOM rule object, only
     // a declaration.
-    *aDOMRule = nsnull;
-    return NS_OK;
+    return nsnull;
   }
   if (!mDOMRule) {
     mDOMRule = new DOMCSSStyleRuleImpl(this);
     if (!mDOMRule) {
-      *aDOMRule = nsnull;
-      return NS_ERROR_OUT_OF_MEMORY;
+      *aResult = NS_ERROR_OUT_OF_MEMORY;
+      return nsnull;
     }
     NS_ADDREF(mDOMRule);
   }
-  *aDOMRule = mDOMRule;
-  NS_ADDREF(*aDOMRule);
-  return NS_OK;
+  return mDOMRule;
 }
 
 /* virtual */ already_AddRefed<nsICSSStyleRule>
 CSSStyleRuleImpl::DeclarationChanged(PRBool aHandleContainer)
 {
   CSSStyleRuleImpl* clone = new CSSStyleRuleImpl(*this, mDeclaration);
   if (!clone) {
     return nsnull;
--- a/layout/style/nsCSSStyleSheet.cpp
+++ b/layout/style/nsCSSStyleSheet.cpp
@@ -56,17 +56,17 @@
 #include "nsPresContext.h"
 #include "nsGkAtoms.h"
 #include "nsString.h"
 #include "nsVoidArray.h"
 #include "nsIDOMStyleSheetList.h"
 #include "nsIDOMCSSStyleSheet.h"
 #include "nsIDOMCSSRule.h"
 #include "nsIDOMCSSImportRule.h"
-#include "nsIDOMCSSRuleList.h"
+#include "nsICSSRuleList.h"
 #include "nsIDOMMediaList.h"
 #include "nsIDOMNode.h"
 #include "nsDOMError.h"
 #include "nsICSSParser.h"
 #include "nsICSSLoader.h"
 #include "nsICSSLoaderObserver.h"
 #include "nsINameSpaceManager.h"
 #include "nsXMLNameSpaceMap.h"
@@ -76,27 +76,29 @@
 #include "nsIScriptSecurityManager.h"
 #include "mozAutoDocUpdate.h"
 #include "nsCSSDeclaration.h"
 #include "nsRuleNode.h"
 
 // -------------------------------
 // Style Rule List for the DOM
 //
-class CSSRuleListImpl : public nsIDOMCSSRuleList
+class CSSRuleListImpl : public nsICSSRuleList
 {
 public:
   CSSRuleListImpl(nsCSSStyleSheet *aStyleSheet);
 
   NS_DECL_ISUPPORTS
 
   // nsIDOMCSSRuleList interface
   NS_IMETHOD    GetLength(PRUint32* aLength); 
   NS_IMETHOD    Item(PRUint32 aIndex, nsIDOMCSSRule** aReturn); 
 
+  virtual nsIDOMCSSRule* GetItemAt(PRUint32 aIndex, nsresult* aResult);
+
   void DropReference() { mStyleSheet = nsnull; }
 
 protected:
   virtual ~CSSRuleListImpl();
 
   nsCSSStyleSheet*  mStyleSheet;
 public:
   PRBool              mRulesAccessed;
@@ -111,16 +113,17 @@ CSSRuleListImpl::CSSRuleListImpl(nsCSSSt
 }
 
 CSSRuleListImpl::~CSSRuleListImpl()
 {
 }
 
 // QueryInterface implementation for CSSRuleList
 NS_INTERFACE_MAP_BEGIN(CSSRuleListImpl)
+  NS_INTERFACE_MAP_ENTRY(nsICSSRuleList)
   NS_INTERFACE_MAP_ENTRY(nsIDOMCSSRuleList)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(CSSRuleList)
 NS_INTERFACE_MAP_END
 
 
 NS_IMPL_ADDREF(CSSRuleListImpl)
 NS_IMPL_RELEASE(CSSRuleListImpl)
@@ -136,38 +139,53 @@ CSSRuleListImpl::GetLength(PRUint32* aLe
   }
   else {
     *aLength = 0;
   }
 
   return NS_OK;
 }
 
-NS_IMETHODIMP    
-CSSRuleListImpl::Item(PRUint32 aIndex, nsIDOMCSSRule** aReturn)
+nsIDOMCSSRule*    
+CSSRuleListImpl::GetItemAt(PRUint32 aIndex, nsresult* aResult)
 {
   nsresult result = NS_OK;
 
-  *aReturn = nsnull;
   if (mStyleSheet) {
     result = mStyleSheet->EnsureUniqueInner(); // needed to ensure rules have correct parent
     if (NS_SUCCEEDED(result)) {
       nsCOMPtr<nsICSSRule> rule;
 
       result = mStyleSheet->GetStyleRuleAt(aIndex, *getter_AddRefs(rule));
       if (rule) {
-        result = rule->GetDOMRule(aReturn);
         mRulesAccessed = PR_TRUE; // signal to never share rules again
-      } else if (result == NS_ERROR_ILLEGAL_VALUE) {
+        return rule->GetDOMRuleWeak(aResult);
+      }
+      if (result == NS_ERROR_ILLEGAL_VALUE) {
         result = NS_OK; // per spec: "Return Value ... null if ... not a valid index."
       }
     }
   }
-  
-  return result;
+
+  *aResult = result;
+  return nsnull;
+}
+
+NS_IMETHODIMP    
+CSSRuleListImpl::Item(PRUint32 aIndex, nsIDOMCSSRule** aReturn)
+{
+  nsresult rv;
+  nsIDOMCSSRule* rule = GetItemAt(aIndex, &rv);
+  if (!rule) {
+    *aReturn = nsnull;
+
+    return rv;
+  }
+
+  return CallQueryInterface(rule, aReturn);
 }
 
 template <class Numeric>
 PRInt32 DoCompare(Numeric a, Numeric b)
 {
   if (a == b)
     return 0;
   if (a < b)
--- a/layout/style/nsDOMCSSValueList.cpp
+++ b/layout/style/nsDOMCSSValueList.cpp
@@ -79,18 +79,17 @@ nsDOMCSSValueList::GetLength(PRUint32* a
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMCSSValueList::Item(PRUint32 aIndex, nsIDOMCSSValue **aReturn)
 {
   NS_ENSURE_ARG_POINTER(aReturn);
 
-  *aReturn = mCSSValues[aIndex];
-  NS_IF_ADDREF(*aReturn);
+  NS_IF_ADDREF(*aReturn = GetItemAt(aIndex));
 
   return NS_OK;
 }
 
 // nsIDOMCSSValue
 
 NS_IMETHODIMP
 nsDOMCSSValueList::GetCssText(nsAString& aCssText)
--- a/layout/style/nsDOMCSSValueList.h
+++ b/layout/style/nsDOMCSSValueList.h
@@ -63,16 +63,38 @@ public:
 
   /**
    * Adds a value to this list.
    * @retval PR_TRUE Adding the value succeeded
    * @retval PR_FALSE The value could not be added (Out of memory)
    */
   PRBool AppendCSSValue(nsIDOMCSSValue* aValue);
 
+  nsIDOMCSSValue* GetItemAt(PRUint32 aIndex)
+  {
+    return mCSSValues.SafeObjectAt(aIndex);
+  }
+
+  static nsDOMCSSValueList* FromSupports(nsISupports* aSupports)
+  {
+#ifdef DEBUG
+    {
+      nsCOMPtr<nsIDOMCSSValueList> list_qi = do_QueryInterface(aSupports);
+
+      // If this assertion fires the QI implementation for the object in
+      // question doesn't use the nsIDOMCSSValueList pointer as the nsISupports
+      // pointer. That must be fixed, or we'll crash...
+      NS_ASSERTION(list_qi == static_cast<nsIDOMCSSValueList*>(aSupports),
+                   "Uh, fix QI!");
+    }
+#endif
+
+    return static_cast<nsDOMCSSValueList*>(aSupports);
+  }
+
 private:
   PRPackedBool                mCommaDelimited;  // some value lists use a comma
                                                 // as the delimiter, some just use
                                                 // spaces.
 
   PRPackedBool                mReadonly;    // Are we read-only?
 
   nsCOMArray<nsIDOMCSSValue>  mCSSValues;
--- a/layout/style/nsICSSRule.h
+++ b/layout/style/nsICSSRule.h
@@ -36,25 +36,25 @@
  * ***** END LICENSE BLOCK ***** */
 
 /* internal interface for all rule types in a CSS style sheet */
 
 #ifndef nsICSSRule_h___
 #define nsICSSRule_h___
 
 #include "nsIStyleRule.h"
+#include "nsIDOMCSSRule.h"
 
 class nsICSSStyleSheet;
 class nsICSSGroupRule;
-class nsIDOMCSSRule;
 class nsAString;
 
-// IID for the nsICSSRule interface {b9791e20-1a04-11d3-805a-006008159b5a}
+// IID for the nsICSSRule interface {e775eac0-b022-462c-b1f9-221c01aa2988}
 #define NS_ICSS_RULE_IID     \
-{0xb9791e20, 0x1a04, 0x11d3, {0x80, 0x5a, 0x00, 0x60, 0x08, 0x15, 0x9b, 0x5a}}
+{0xe775eac0, 0xb022, 0x462c, {0xb1, 0xf9, 0x22, 0x1c, 0x01, 0xaa, 0x29, 0x88}}
 
 // inheriting from nsIStyleRule is only for style rules, not other rule types
 class nsICSSRule : public nsIStyleRule {
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_ICSS_RULE_IID)
   enum {
     UNKNOWN_RULE = 0,
     STYLE_RULE = 1,
@@ -72,17 +72,23 @@ public:
   NS_IMETHOD GetStyleSheet(nsIStyleSheet*& aSheet) const = 0;
   NS_IMETHOD SetStyleSheet(nsICSSStyleSheet* aSheet) = 0;
   NS_IMETHOD SetParentRule(nsICSSGroupRule* aRule) = 0;
 
   NS_IMETHOD Clone(nsICSSRule*& aClone) const = 0;
 
   // Note that this returns null for inline style rules since they aren't
   // supposed to have a DOM rule representation (and our code wouldn't work).
-  NS_IMETHOD GetDOMRule(nsIDOMCSSRule** aDOMRule) = 0;
+  nsresult GetDOMRule(nsIDOMCSSRule** aDOMRule)
+  {
+    nsresult rv;
+    NS_IF_ADDREF(*aDOMRule = GetDOMRuleWeak(&rv));
+    return rv;
+  }
+  virtual nsIDOMCSSRule* GetDOMRuleWeak(nsresult* aResult) = 0;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsICSSRule, NS_ICSS_RULE_IID)
 
 /* Define global NS_New* functions for rules that don't need their own
    interfaces here */
 nsresult
 NS_NewCSSCharsetRule(nsICSSRule** aInstancePtrResult,
new file mode 100644
--- /dev/null
+++ b/layout/style/nsICSSRuleList.h
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla layout code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *         Peter Van der Beken <peterv@propagandism.org> (Original Author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsICSSRuleList_h___
+#define nsICSSRuleList_h___
+
+#include "nsIDOMCSSRuleList.h"
+
+// IID for the nsICSSRuleList interface
+#define NS_ICSSRULELIST_IID \
+{ 0x7ae746fd, 0x259a, 0x4a69, \
+ { 0x97, 0x2d, 0x2c, 0x10, 0xf7, 0xb0, 0x04, 0xa1 } }
+
+class nsICSSRuleList : public nsIDOMCSSRuleList
+{
+public:
+  NS_DECLARE_STATIC_IID_ACCESSOR(NS_ICSSRULELIST_IID)
+
+  virtual nsIDOMCSSRule* GetItemAt(PRUint32 aIndex, nsresult* aResult) = 0;
+};
+
+NS_DEFINE_STATIC_IID_ACCESSOR(nsICSSRuleList, NS_ICSSRULELIST_IID)
+
+#endif /* nsICSSRuleList_h___ */
--- a/layout/xul/base/src/tree/src/nsTreeColumns.cpp
+++ b/layout/xul/base/src/tree/src/nsTreeColumns.cpp
@@ -530,27 +530,33 @@ nsTreeColumns::GetNamedColumn(const nsAS
     if (currCol->GetId().Equals(aId)) {
       NS_ADDREF(*_retval = currCol);
       break;
     }
   }
   return NS_OK;
 }
 
+nsITreeColumn*
+nsTreeColumns::GetColumnAt(PRInt32 aIndex)
+{
+  EnsureColumns();
+  for (nsTreeColumn* currCol = mFirstColumn; currCol; currCol = currCol->GetNext()) {
+    if (currCol->GetIndex() == aIndex) {
+      return currCol;
+    }
+  }
+  return nsnull;
+}
+
 NS_IMETHODIMP
 nsTreeColumns::GetColumnAt(PRInt32 aIndex, nsITreeColumn** _retval)
 {
   EnsureColumns();
-  *_retval = nsnull;
-  for (nsTreeColumn* currCol = mFirstColumn; currCol; currCol = currCol->GetNext()) {
-    if (currCol->GetIndex() == aIndex) {
-      NS_ADDREF(*_retval = currCol);
-      break;
-    }
-  }
+  NS_IF_ADDREF(*_retval = GetColumnAt(aIndex));
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsTreeColumns::InvalidateColumns()
 {
   NS_IF_RELEASE(mFirstColumn);
   return NS_OK;
--- a/layout/xul/base/src/tree/src/nsTreeColumns.h
+++ b/layout/xul/base/src/tree/src/nsTreeColumns.h
@@ -139,16 +139,35 @@ private:
 class nsTreeColumns : public nsITreeColumns {
 public:
   nsTreeColumns(nsITreeBoxObject* aTree);
   ~nsTreeColumns();
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSITREECOLUMNS
 
+  nsITreeColumn* GetColumnAt(PRInt32 aIndex);
+
+  static nsTreeColumns* FromSupports(nsISupports* aSupports)
+  {
+#ifdef DEBUG
+    {
+      nsCOMPtr<nsITreeColumns> columns_qi = do_QueryInterface(aSupports);
+
+      // If this assertion fires the QI implementation for the object in
+      // question doesn't use the nsITreeColumns pointer as the nsISupports
+      // pointer. That must be fixed, or we'll crash...
+      NS_ASSERTION(columns_qi == static_cast<nsITreeColumns*>(aSupports),
+                   "Uh, fix QI!");
+    }
+#endif
+
+    return static_cast<nsTreeColumns*>(aSupports);
+  }
+
   friend class nsTreeBodyFrame;
 protected:
   void SetTree(nsITreeBoxObject* aTree) { mTree = aTree; }
 
   // Builds our cache of column info.
   void EnsureColumns();
 
   nsTreeColumn* GetFirstColumn() { EnsureColumns(); return mFirstColumn; }