Fix for bug 461560 (Make nsNamedArraySH::NamedItem not AddRef/Release). r/sr=bz.
authorPeter Van der Beken <peterv@propagandism.org>
Fri, 31 Oct 2008 14:40:35 -0700
changeset 21159 20165908edd94a97ee7a6cabaa0624aa1f8c5c2c
parent 21158 47dd67ed93a4e22dea0acfbdf74e4350b9180799
child 21160 7e750c55fd897ae7e2f65e5590cd067d4b8c7693
push idunknown
push userunknown
push dateunknown
bugs461560
milestone1.9.1b2pre
Fix for bug 461560 (Make nsNamedArraySH::NamedItem not AddRef/Release). r/sr=bz.
content/base/src/nsContentList.cpp
content/base/src/nsContentList.h
content/base/src/nsDOMAttributeMap.cpp
content/base/src/nsDOMAttributeMap.h
content/html/content/public/nsIHTMLCollection.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
dom/src/base/nsDOMClassInfo.cpp
dom/src/base/nsDOMClassInfo.h
dom/src/base/nsMimeTypeArray.cpp
dom/src/base/nsMimeTypeArray.h
dom/src/base/nsPluginArray.cpp
dom/src/base/nsPluginArray.h
dom/src/storage/nsDOMStorage.cpp
dom/src/storage/nsDOMStorage.h
layout/xul/base/src/tree/src/nsTreeColumns.cpp
layout/xul/base/src/tree/src/nsTreeColumns.h
--- a/content/base/src/nsContentList.cpp
+++ b/content/base/src/nsContentList.cpp
@@ -346,16 +346,17 @@ nsContentList::~nsContentList()
     // Clean up mData
     (*mDestroyFunc)(mData);
   }
 }
 
 
 // QueryInterface implementation for nsContentList
 NS_INTERFACE_MAP_BEGIN(nsContentList)
+  NS_INTERFACE_MAP_ENTRY(nsIHTMLCollection)
   NS_INTERFACE_MAP_ENTRY(nsIDOMHTMLCollection)
   NS_INTERFACE_MAP_ENTRY(nsIMutationObserver)
   NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(ContentList)
 NS_INTERFACE_MAP_END_INHERITING(nsBaseContentList)
 
 
 NS_IMPL_ADDREF_INHERITED(nsContentList, nsBaseContentList)
 NS_IMPL_RELEASE_INHERITED(nsContentList, nsBaseContentList)
@@ -496,16 +497,30 @@ nsContentList::NamedItem(const nsAString
 }
 
 nsINode*
 nsContentList::GetNodeAt(PRUint32 aIndex)
 {
   return Item(aIndex, PR_TRUE);
 }
 
+nsISupports*
+nsContentList::GetNodeAt(PRUint32 aIndex, nsresult* aResult)
+{
+  *aResult = NS_OK;
+  return Item(aIndex, PR_TRUE);
+}
+
+nsISupports*
+nsContentList::GetNamedItem(const nsAString& aName, nsresult* aResult)
+{
+  *aResult = NS_OK;
+  return NamedItem(aName, PR_TRUE);
+}
+
 void
 nsContentList::AttributeChanged(nsIDocument *aDocument, nsIContent* aContent,
                                 PRInt32 aNameSpaceID, nsIAtom* aAttribute,
                                 PRInt32 aModType, PRUint32 aStateMask)
 {
   NS_PRECONDITION(aContent, "Must have a content node to work with");
   NS_PRECONDITION(aContent->IsNodeOfType(nsINode::eELEMENT),
                   "Should be an element");
--- a/content/base/src/nsContentList.h
+++ b/content/base/src/nsContentList.h
@@ -42,17 +42,17 @@
  */
 
 #ifndef nsContentList_h___
 #define nsContentList_h___
 
 #include "nsISupports.h"
 #include "nsCOMArray.h"
 #include "nsString.h"
-#include "nsIDOMHTMLCollection.h"
+#include "nsIHTMLCollection.h"
 #include "nsIDOMNodeList.h"
 #include "nsINodeList.h"
 #include "nsStubMutationObserver.h"
 #include "nsIAtom.h"
 #include "nsINameSpaceManager.h"
 #include "nsCycleCollectionParticipant.h"
 
 // Magic namespace id that means "match all namespaces".  This is
@@ -176,17 +176,17 @@ protected:
 #define LIST_LAZY 2
 
 /**
  * Class that implements a live NodeList that matches Elements in the
  * tree based on some criterion.
  */
 class nsContentList : public nsBaseContentList,
                       protected nsContentListKey,
-                      public nsIDOMHTMLCollection,
+                      public nsIHTMLCollection,
                       public nsStubMutationObserver
 {
 public:
   NS_DECL_ISUPPORTS_INHERITED
 
   /**
    * @param aRootNode The node under which to limit our search.
    * @param aMatchAtom An atom whose meaning depends on aMatchNameSpaceId.
@@ -236,17 +236,20 @@ public:
   virtual ~nsContentList();
 
   // nsIDOMHTMLCollection
   NS_DECL_NSIDOMHTMLCOLLECTION
 
   // nsBaseContentList overrides
   virtual PRInt32 IndexOf(nsIContent *aContent, PRBool aDoFlush);
   virtual nsINode* GetNodeAt(PRUint32 aIndex);
-  
+
+  // nsIHTMLCollection
+  virtual nsISupports* GetNodeAt(PRUint32 aIndex, nsresult* aResult);
+  virtual nsISupports* GetNamedItem(const nsAString& aName, nsresult* aResult);
 
   // nsContentList public methods
   NS_HIDDEN_(nsISupports*) GetParentObject();
   NS_HIDDEN_(PRUint32) Length(PRBool aDoFlush);
   NS_HIDDEN_(nsIContent*) Item(PRUint32 aIndex, PRBool aDoFlush);
   NS_HIDDEN_(nsIContent*) NamedItem(const nsAString& aName, PRBool aDoFlush);
 
   nsContentListKey* GetKey() {
--- a/content/base/src/nsDOMAttributeMap.cpp
+++ b/content/base/src/nsDOMAttributeMap.cpp
@@ -211,31 +211,45 @@ nsDOMAttributeMap::GetAttribute(nsINodeI
     if (newAttr && mAttributeCache.Put(attr, newAttr)) {
       node = newAttr;
     }
   }
 
   return node;
 }
 
+nsIDOMNode*
+nsDOMAttributeMap::GetNamedItem(const nsAString& aAttrName, nsresult *aResult)
+{
+  *aResult = NS_OK;
+
+  if (mContent) {
+    nsCOMPtr<nsINodeInfo> ni =
+      mContent->GetExistingAttrNameFromQName(aAttrName);
+    if (ni) {
+      nsIDOMNode* node = GetAttribute(ni);
+      if (node) {
+        return node;
+      }
+
+      *aResult = NS_ERROR_OUT_OF_MEMORY;
+    }
+  }
+
+  return nsnull;
+}
+
 NS_IMETHODIMP
 nsDOMAttributeMap::GetNamedItem(const nsAString& aAttrName,
                                 nsIDOMNode** aAttribute)
 {
   NS_ENSURE_ARG_POINTER(aAttribute);
-  *aAttribute = nsnull;
 
-  nsresult rv = NS_OK;
-  if (mContent) {
-    nsCOMPtr<nsINodeInfo> ni =
-      mContent->GetExistingAttrNameFromQName(aAttrName);
-    if (ni) {
-      rv = GetAttribute(ni, aAttribute);
-    }
-  }
+  nsresult rv;
+  NS_IF_ADDREF(*aAttribute = GetNamedItem(aAttrName, &rv));
 
   return rv;
 }
 
 NS_IMETHODIMP
 nsDOMAttributeMap::SetNamedItem(nsIDOMNode *aNode, nsIDOMNode **aReturn)
 {
   return SetNamedItemInternal(aNode, aReturn, PR_FALSE);
--- a/content/base/src/nsDOMAttributeMap.h
+++ b/content/base/src/nsDOMAttributeMap.h
@@ -166,16 +166,17 @@ 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);
+  nsIDOMNode* GetNamedItem(const nsAString& aAttrName, 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
--- a/content/html/content/public/nsIHTMLCollection.h
+++ b/content/html/content/public/nsIHTMLCollection.h
@@ -37,29 +37,35 @@
 
 #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 } }
+{ 0x5709485b, 0xc057, 0x4ba7, \
+ { 0x95, 0xbd, 0x98, 0xb7, 0x94, 0x4f, 0x13, 0xe7 } }
 
 /**
  * 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
+   * Get the node at the index.  Returns null if the index is out of bounds.
    */
   virtual nsISupports* GetNodeAt(PRUint32 aIndex, nsresult* aResult) = 0;
+
+  /**
+   * Get the node for the name.  Returns null if no node exists for the name.
+   */
+  virtual nsISupports* GetNamedItem(const nsAString& aName,
+                                    nsresult* aResult) = 0;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIHTMLCollection, NS_IHTMLCOLLECTION_IID)
 
 #endif /* nsIHTMLCollection_h___ */
--- a/content/html/content/src/nsHTMLFormElement.cpp
+++ b/content/html/content/src/nsHTMLFormElement.cpp
@@ -370,26 +370,31 @@ public:
   virtual nsISupports* GetNodeAt(PRUint32 aIndex, nsresult* aResult)
   {
     FlushPendingNotifications();
 
     *aResult = NS_OK;
 
     return mElements.SafeElementAt(aIndex, nsnull);
   }
+  virtual nsISupports* GetNamedItem(const nsAString& aName, nsresult* aResult)
+  {
+    *aResult = NS_OK;
+
+    return NamedItemInternal(aName, PR_TRUE);
+  }
 
   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,
-                         nsISupports **aResult);
+  nsISupports* NamedItemInternal(const nsAString& aName, PRBool aFlushContent);
   
   /**
    * Create a sorted list of form control elements. This list is sorted
    * in document order and contains the controls in the mElements and
    * mNotInElements list. This function does not add references to the
    * elements.
    *
    * @param aControls The list of sorted controls[out].
@@ -1542,18 +1547,18 @@ nsHTMLFormElement::ResolveName(const nsA
 {
   return DoResolveName(aName, PR_TRUE);
 }
 
 already_AddRefed<nsISupports>
 nsHTMLFormElement::DoResolveName(const nsAString& aName,
                                  PRBool aFlushContent)
 {
-  nsISupports *result = nsnull;
-  mControls->NamedItemInternal(aName, aFlushContent, &result);
+  nsISupports *result;
+  NS_IF_ADDREF(result = mControls->NamedItemInternal(aName, aFlushContent));
   return result;
 }
 
 NS_IMETHODIMP
 nsHTMLFormElement::OnSubmitClickBegin()
 {
   mDeferSubmission = PR_TRUE;
 
@@ -2192,30 +2197,29 @@ nsFormControlList::NamedItem(const nsASt
 
   return rv;
 }
 
 NS_IMETHODIMP
 nsFormControlList::NamedItem(const nsAString& aName,
                              nsISupports** aReturn)
 {
-  NamedItemInternal(aName, PR_TRUE, aReturn);
+  NS_IF_ADDREF(*aReturn = NamedItemInternal(aName, PR_TRUE));
   return NS_OK;
 }
 
-void
+nsISupports*
 nsFormControlList::NamedItemInternal(const nsAString& aName,
-                                     PRBool aFlushContent,
-                                     nsISupports** aReturn)
+                                     PRBool aFlushContent)
 {
   if (aFlushContent) {
     FlushPendingNotifications();
   }
 
-  mNameLookupTable.Get(aName, aReturn);
+  return mNameLookupTable.GetWeak(aName);
 }
 
 nsresult
 nsFormControlList::AddElementToTable(nsIFormControl* aChild,
                                      const nsAString& aName)
 {
   if (!ShouldBeInElements(aChild)) {
     return NS_OK;
--- a/content/html/content/src/nsHTMLSelectElement.cpp
+++ b/content/html/content/src/nsHTMLSelectElement.cpp
@@ -1954,41 +1954,49 @@ nsHTMLOptionCollection::Item(PRUint32 aI
     *aReturn = nsnull;
 
     return rv;
   }
 
   return CallQueryInterface(item, aReturn);
 }
 
+nsISupports*
+nsHTMLOptionCollection::GetNamedItem(const nsAString& aName, nsresult* aResult)
+{
+  *aResult = NS_OK;
+
+  PRInt32 count = mElements.Count();
+  for (PRInt32 i = 0; i < count; i++) {
+    nsCOMPtr<nsIContent> content = do_QueryInterface(mElements.ObjectAt(i));
+    if (content &&
+        (content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::name, aName,
+                              eCaseMatters) ||
+         content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::id, aName,
+                              eCaseMatters))) {
+      return content;
+    }
+  }
+
+  return nsnull;
+}
+
 NS_IMETHODIMP
 nsHTMLOptionCollection::NamedItem(const nsAString& aName,
                                   nsIDOMNode** aReturn)
 {
-  PRInt32 count = mElements.Count();
-  nsresult rv = NS_OK;
-
-  *aReturn = nsnull;
-
-  for (PRInt32 i = 0; i < count; i++) {
-    nsCOMPtr<nsIContent> content = do_QueryInterface(mElements.ObjectAt(i));
+  nsresult rv;
+  nsISupports* item = GetNamedItem(aName, &rv);
+  if (!item) {
+    *aReturn = nsnull;
 
-    if (content) {
-      if (content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::name, aName,
-                               eCaseMatters) ||
-          content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::id, aName,
-                               eCaseMatters)) {
-        rv = CallQueryInterface(content, aReturn);
-
-        break;
-      }
-    }
+    return rv;
   }
 
-  return rv;
+  return CallQueryInterface(item, aReturn);
 }
 
 NS_IMETHODIMP
 nsHTMLOptionCollection::GetSelect(nsIDOMHTMLSelectElement **aReturn)
 {
   NS_IF_ADDREF(*aReturn = mSelect);
   return NS_OK;
 }
--- a/content/html/content/src/nsHTMLSelectElement.h
+++ b/content/html/content/src/nsHTMLSelectElement.h
@@ -89,16 +89,17 @@ public:
   // nsIDOMHTMLOptionsCollection
 
   virtual nsISupports* GetNodeAt(PRUint32 aIndex, nsresult* aResult)
   {
     *aResult = NS_OK;
 
     return mElements.SafeObjectAt(aIndex);
   }
+  virtual nsISupports* GetNamedItem(const nsAString& aName, nsresult* aResult);
 
   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsHTMLOptionCollection,
                                            nsIHTMLCollection)
 
   // Helpers for nsHTMLSelectElement
   /**
    * Insert an option
    * @param aOption the option to insert
--- a/content/html/content/src/nsHTMLTableElement.cpp
+++ b/content/html/content/src/nsHTMLTableElement.cpp
@@ -113,16 +113,17 @@ public:
   virtual ~TableRowsCollection();
 
   nsresult Init();
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_NSIDOMHTMLCOLLECTION
 
   virtual nsISupports* GetNodeAt(PRUint32 aIndex, nsresult* aResult);
+  virtual nsISupports* GetNamedItem(const nsAString& aName, nsresult* aResult);
 
   NS_IMETHOD    ParentDestroyed();
 
   NS_DECL_CYCLE_COLLECTION_CLASS(TableRowsCollection)
 
 protected:
   // Those rows that are not in table sections
   nsRefPtr<nsContentList> mOrphanRows;  
@@ -319,42 +320,56 @@ TableRowsCollection::Item(PRUint32 aInde
     *aReturn = nsnull;
 
     return rv;
   }
 
   return CallQueryInterface(node, aReturn);
 }
 
-static nsresult
+static nsISupports*
 GetNamedItemInRowGroup(nsIDOMHTMLCollection* aRows,
-                       const nsAString& aName, nsIDOMNode** aNamedItem)
+                       const nsAString& aName, nsresult* aResult)
 {
-  if (aRows) {
-    return aRows->NamedItem(aName, aNamedItem);
+  nsCOMPtr<nsIHTMLCollection> rows = do_QueryInterface(aRows);
+  if (rows) {
+    return rows->GetNamedItem(aName, aResult);
   }
 
-  *aNamedItem = nsnull;
-  return NS_OK;
+  *aResult = NS_OK;
+  return nsnull;
+}
+
+nsISupports* 
+TableRowsCollection::GetNamedItem(const nsAString& aName, nsresult* aResult)
+{
+  nsresult rv = NS_OK;
+  DO_FOR_EACH_ROWGROUP(
+    nsISupports* item = GetNamedItemInRowGroup(rows, aName, aResult);
+    if (NS_FAILED(*aResult) || item) {
+      return item;
+    }
+  );
+  *aResult = rv;
+  return nsnull;
 }
 
 NS_IMETHODIMP 
 TableRowsCollection::NamedItem(const nsAString& aName,
                                nsIDOMNode** aReturn)
 {
-  *aReturn = nsnull;
-  nsresult rv = NS_OK;
-  DO_FOR_EACH_ROWGROUP(
-    rv = GetNamedItemInRowGroup(rows, aName, aReturn);
-    NS_ENSURE_SUCCESS(rv, rv);
-    if (*aReturn) {
-      return rv;
-    }
-  );
-  return rv;
+  nsresult rv;
+  nsISupports* item = GetNamedItem(aName, &rv);
+  if (!item) {
+    *aReturn = nsnull;
+
+    return rv;
+  }
+
+  return CallQueryInterface(item, aReturn);
 }
 
 NS_IMETHODIMP
 TableRowsCollection::ParentDestroyed()
 {
   // see comment in destructor, do NOT release mParent!
   mParent = nsnull;
 
--- a/dom/src/base/nsDOMClassInfo.cpp
+++ b/dom/src/base/nsDOMClassInfo.cpp
@@ -438,22 +438,17 @@
 
 #ifdef MOZ_ENABLE_CANVAS
 #include "nsIDOMCanvasRenderingContext2D.h"
 #endif
 
 #include "nsIImageDocument.h"
 
 // Storage includes
-#include "nsIDOMStorage.h"
-#include "nsPIDOMStorage.h"
-#include "nsIDOMStorageList.h"
-#include "nsIDOMStorageItem.h"
-#include "nsIDOMStorageEvent.h"
-#include "nsIDOMToString.h"
+#include "nsDOMStorage.h"
 
 // Drag and drop
 #include "nsIDOMDataTransfer.h"
 
 // Offline includes
 #include "nsIDOMLoadStatus.h"
 #include "nsIDOMLoadStatusEvent.h"
 
@@ -669,17 +664,17 @@ static nsDOMClassInfoData sClassInfoData
   // Misc HTML classes
   NS_DEFINE_CLASSINFO_DATA(HTMLDocument, nsHTMLDocumentSH,
                            DOCUMENT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(HTMLOptionsCollection,
                            nsHTMLOptionsCollectionSH,
                            ARRAY_SCRIPTABLE_FLAGS |
                            nsIXPCScriptable::WANT_SETPROPERTY)
   NS_DEFINE_CLASSINFO_DATA_WITH_NAME(HTMLFormControlCollection, HTMLCollection,
-                                     nsFormControlListSH,
+                                     nsHTMLCollectionSH,
                                      ARRAY_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA_WITH_NAME(HTMLGenericCollection, HTMLCollection,
                                      nsHTMLCollectionSH,
                                      ARRAY_SCRIPTABLE_FLAGS)
 
   // HTML element classes
   NS_DEFINE_CLASSINFO_DATA(HTMLAnchorElement, nsHTMLElementSH,
                            ELEMENT_SCRIPTABLE_FLAGS)
@@ -7710,19 +7705,19 @@ nsStringListSH::GetStringAt(nsISupports 
 // Named Array helper
 
 NS_IMETHODIMP
 nsNamedArraySH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
                             JSObject *obj, jsval id, jsval *vp,
                             PRBool *_retval)
 {
   if (JSVAL_IS_STRING(id) && !ObjectIsNativeWrapper(cx, obj)) {
-    nsCOMPtr<nsISupports> item;
-    nsresult rv = GetNamedItem(wrapper->Native(), nsDependentJSString(id),
-                               getter_AddRefs(item));
+    nsresult rv = NS_OK;
+    nsISupports* item = GetNamedItem(wrapper->Native(), nsDependentJSString(id),
+                                     &rv);
     NS_ENSURE_SUCCESS(rv, rv);
 
     if (item) {
       nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
       rv = WrapNative(cx, obj, item, NS_GET_IID(nsISupports), vp,
                       getter_AddRefs(holder));
       NS_ENSURE_SUCCESS(rv, rv);
 
@@ -7743,34 +7738,49 @@ nsISupports*
 nsNamedNodeMapSH::GetItemAt(nsISupports *aNative, PRUint32 aIndex,
                             nsresult *aResult)
 {
   nsDOMAttributeMap* map = nsDOMAttributeMap::FromSupports(aNative);
 
   return map->GetItemAt(aIndex, aResult);
 }
 
-nsresult
+nsISupports*
 nsNamedNodeMapSH::GetNamedItem(nsISupports *aNative, const nsAString& aName,
-                               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->GetNamedItem(aName, &node);
-
-  *aResult = node;
-
-  return rv;
+                               nsresult *aResult)
+{
+  nsDOMAttributeMap* map = nsDOMAttributeMap::FromSupports(aNative);
+
+  return map->GetNamedItem(aName, aResult);
 }
 
 
 // HTMLCollection helper
 
+nsresult
+nsHTMLCollectionSH::GetLength(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
+                              JSObject *obj, PRUint32 *length)
+{
+  nsIHTMLCollection* collection =
+    static_cast<nsIHTMLCollection*>(wrapper->Native());
+#ifdef DEBUG
+  {
+    nsCOMPtr<nsIHTMLCollection> collection_qi =
+      do_QueryInterface(wrapper->Native());
+
+    // 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->GetLength(length);
+}
+
 nsISupports*
 nsHTMLCollectionSH::GetItemAt(nsISupports *aNative, PRUint32 aIndex,
                               nsresult *aResult)
 {
   nsIHTMLCollection* collection = static_cast<nsIHTMLCollection*>(aNative);
 #ifdef DEBUG
   {
     nsCOMPtr<nsIHTMLCollection> collection_qi = do_QueryInterface(aNative);
@@ -7780,30 +7790,34 @@ nsHTMLCollectionSH::GetItemAt(nsISupport
     // pointer. That must be fixed, or we'll crash...
     NS_ASSERTION(collection_qi == collection, "Uh, fix QI!");
   }
 #endif
 
   return collection->GetNodeAt(aIndex, aResult);
 }
 
-nsresult
+nsISupports*
 nsHTMLCollectionSH::GetNamedItem(nsISupports *aNative,
                                  const nsAString& aName,
-                                 nsISupports **aResult)
-{
-  nsCOMPtr<nsIDOMHTMLCollection> collection(do_QueryInterface(aNative));
-  NS_ENSURE_TRUE(collection, NS_ERROR_UNEXPECTED);
-
-  nsIDOMNode *node = nsnull; // Weak, transfer the ownership over to aResult
-  nsresult rv = collection->NamedItem(aName, &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->GetNamedItem(aName, aResult);
 }
 
 
 // ContentList helper
 nsresult
 nsContentListSH::PreCreate(nsISupports *nativeObj, JSContext *cx,
                            JSObject *globalObj, JSObject **parentObj)
 {
@@ -7821,51 +7835,43 @@ 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));
-  NS_ENSURE_TRUE(list, NS_ERROR_UNEXPECTED);
-
-  return list->NamedItem(aName, aResult);
-}
+nsContentListSH::GetLength(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
+                           JSObject *obj, PRUint32 *length)
+{
+  nsContentList *list = nsContentList::FromSupports(wrapper->Native());
+
+  return list->GetLength(length);
+}
+
+nsISupports*
+nsContentListSH::GetItemAt(nsISupports *aNative, PRUint32 aIndex,
+                           nsresult *aResult)
+{
+  nsContentList *list = nsContentList::FromSupports(aNative);
+
+  return list->GetNodeAt(aIndex, aResult);
+}
+
+nsISupports*
+nsContentListSH::GetNamedItem(nsISupports *aNative, const nsAString& aName,
+                              nsresult *aResult)
+{
+  nsContentList *list = nsContentList::FromSupports(aNative);
+
+  return list->GetNamedItem(aName, aResult);
+}
+
 
 // Document helper for document.location and document.on*
 
 NS_IMETHODIMP
 nsDocumentSH::AddProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
                           JSObject *obj, jsval id, jsval *vp,
                           PRBool *_retval)
 {
@@ -9890,86 +9896,65 @@ nsISupports*
 nsPluginSH::GetItemAt(nsISupports *aNative, PRUint32 aIndex,
                       nsresult *aResult)
 {
   nsPluginElement* plugin = nsPluginElement::FromSupports(aNative);
 
   return plugin->GetItemAt(aIndex, aResult);
 }
 
-nsresult
+nsISupports*
 nsPluginSH::GetNamedItem(nsISupports *aNative, const nsAString& aName,
-                         nsISupports **aResult)
-{
-  nsCOMPtr<nsIDOMPlugin> plugin(do_QueryInterface(aNative));
-  NS_ENSURE_TRUE(plugin, NS_ERROR_UNEXPECTED);
-
-  nsIDOMMimeType *mime_type = nsnull;
-
-  nsresult rv = plugin->NamedItem(aName, &mime_type);
-
-  *aResult = mime_type;
-
-  return rv;
+                         nsresult *aResult)
+{
+  nsPluginElement* plugin = nsPluginElement::FromSupports(aNative);
+
+  return plugin->GetNamedItem(aName, aResult);
 }
 
 
 // PluginArray helper
 
 nsISupports*
 nsPluginArraySH::GetItemAt(nsISupports *aNative, PRUint32 aIndex,
                            nsresult *aResult)
 {
   nsPluginArray* array = nsPluginArray::FromSupports(aNative);
 
   return array->GetItemAt(aIndex, aResult);
 }
 
-nsresult
+nsISupports*
 nsPluginArraySH::GetNamedItem(nsISupports *aNative, const nsAString& aName,
-                              nsISupports **aResult)
-{
-  nsCOMPtr<nsIDOMPluginArray> array(do_QueryInterface(aNative));
-  NS_ENSURE_TRUE(array, NS_ERROR_UNEXPECTED);
-
-  nsIDOMPlugin *plugin = nsnull;
-
-  nsresult rv = array->NamedItem(aName, &plugin);
-
-  *aResult = plugin;
-
-  return rv;
+                              nsresult *aResult)
+{
+  nsPluginArray* array = nsPluginArray::FromSupports(aNative);
+
+  return array->GetNamedItem(aName, aResult);
 }
 
 
 // MimeTypeArray helper
 
 nsISupports*
 nsMimeTypeArraySH::GetItemAt(nsISupports *aNative, PRUint32 aIndex,
                              nsresult *aResult)
 {
   nsMimeTypeArray* array = nsMimeTypeArray::FromSupports(aNative);
 
   return array->GetItemAt(aIndex, aResult);
 }
 
-nsresult
+nsISupports*
 nsMimeTypeArraySH::GetNamedItem(nsISupports *aNative, const nsAString& aName,
-                                nsISupports **aResult)
-{
-  nsCOMPtr<nsIDOMMimeTypeArray> array(do_QueryInterface(aNative));
-  NS_ENSURE_TRUE(array, NS_ERROR_UNEXPECTED);
-
-  nsIDOMMimeType *mime_type = nsnull;
-
-  nsresult rv = array->NamedItem(aName, &mime_type);
-
-  *aResult = mime_type;
-
-  return rv;
+                                nsresult *aResult)
+{
+  nsMimeTypeArray* array = nsMimeTypeArray::FromSupports(aNative);
+
+  return array->GetNamedItem(aName, aResult);
 }
 
 
 // StringArray helper
 
 NS_IMETHODIMP
 nsStringArraySH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
                              JSObject *obj, jsval id, jsval *vp,
@@ -10140,30 +10125,24 @@ nsISupports*
 nsTreeColumnsSH::GetItemAt(nsISupports *aNative, PRUint32 aIndex,
                            nsresult *aResult)
 {
   nsTreeColumns* columns = nsTreeColumns::FromSupports(aNative);
 
   return columns->GetColumnAt(aIndex);
 }
 
-nsresult
+nsISupports*
 nsTreeColumnsSH::GetNamedItem(nsISupports *aNative,
                               const nsAString& aName,
-                              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->GetNamedColumn(aName, &column);
-
-  *aResult = column;
-
-  return rv;
+                              nsresult *aResult)
+{
+  nsTreeColumns* columns = nsTreeColumns::FromSupports(aNative);
+
+  return columns->GetNamedColumn(aName);
 }
 #endif
 
 
 // Storage scriptable helper
 
 // One reason we need a newResolve hook is that in order for
 // enumeration of storage object keys to work the keys we're
@@ -10219,30 +10198,23 @@ nsStorageSH::NewResolve(nsIXPConnectWrap
     }
 
     *objp = realObj;
   }
 
   return NS_OK;
 }
 
-nsresult
+nsISupports*
 nsStorageSH::GetNamedItem(nsISupports *aNative, const nsAString& aName,
-                          nsISupports **aResult)
-{
-  nsCOMPtr<nsIDOMStorage> storage(do_QueryInterface(aNative));
-  NS_ENSURE_TRUE(storage, NS_ERROR_UNEXPECTED);
-
-  // Weak, transfer the ownership over to aResult
-  nsIDOMStorageItem* item = nsnull;
-  nsresult rv = storage->GetItem(aName, &item);
-
-  *aResult = item;
-
-  return rv;
+                          nsresult *aResult)
+{
+  nsDOMStorage* storage = nsDOMStorage::FromSupports(aNative);
+
+  return storage->GetNamedItem(aName, aResult);
 }
 
 NS_IMETHODIMP
 nsStorageSH::SetProperty(nsIXPConnectWrappedNative *wrapper,
                          JSContext *cx, JSObject *obj, jsval id,
                          jsval *vp, PRBool *_retval)
 {
   nsCOMPtr<nsIDOMStorage> storage(do_QueryWrappedNative(wrapper));
@@ -10337,30 +10309,23 @@ nsStorageSH::NewEnumerate(nsIXPConnectWr
   }
 
   return NS_OK;
 }
 
 
 // StorageList scriptable helper
 
-nsresult
+nsISupports*
 nsStorageListSH::GetNamedItem(nsISupports *aNative, const nsAString& aName,
-                              nsISupports **aResult)
-{
-  nsCOMPtr<nsIDOMStorageList> storagelist(do_QueryInterface(aNative));
-  NS_ENSURE_TRUE(storagelist, NS_ERROR_UNEXPECTED);
-
-  // Weak, transfer the ownership over to aResult
-  nsIDOMStorage* storage = nsnull;
-  nsresult rv = storagelist->NamedItem(aName, &storage);
-
-  *aResult = storage;
-
-  return rv;
+                              nsresult *aResult)
+{
+  nsDOMStorageList* storagelist = static_cast<nsDOMStorageList*>(aNative);
+
+  return storagelist->GetNamedItem(aName, aResult);
 }
 
 
 // nsIDOMEventListener::HandleEvent() 'this' converter helper
 
 NS_INTERFACE_MAP_BEGIN(nsEventListenerThisTranslator)
   NS_INTERFACE_MAP_ENTRY(nsIXPCFunctionThisTranslator)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
--- a/dom/src/base/nsDOMClassInfo.h
+++ b/dom/src/base/nsDOMClassInfo.h
@@ -688,18 +688,19 @@ protected:
   nsNamedArraySH(nsDOMClassInfoData* aData) : nsArraySH(aData)
   {
   }
 
   virtual ~nsNamedArraySH()
   {
   }
 
-  virtual nsresult GetNamedItem(nsISupports *aNative, const nsAString& aName,
-                                nsISupports **aResult) = 0;
+  virtual nsISupports* GetNamedItem(nsISupports *aNative,
+                                    const nsAString& aName,
+                                    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);
@@ -718,18 +719,19 @@ protected:
   virtual ~nsNamedNodeMapSH()
   {
   }
 
   virtual nsISupports* GetItemAt(nsISupports *aNative, PRUint32 aIndex,
                                  nsresult *aResult);
 
   // Override nsNamedArraySH::GetNamedItem()
-  virtual nsresult GetNamedItem(nsISupports *aNative, const nsAString& aName,
-                                nsISupports **aResult);
+  virtual nsISupports* GetNamedItem(nsISupports *aNative,
+                                    const nsAString& aName,
+                                    nsresult *aResult);
 
 public:
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
     return new nsNamedNodeMapSH(aData);
   }
 };
 
@@ -742,80 +744,63 @@ protected:
   nsHTMLCollectionSH(nsDOMClassInfoData* aData) : nsNamedArraySH(aData)
   {
   }
 
   virtual ~nsHTMLCollectionSH()
   {
   }
 
+  virtual nsresult GetLength(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
+                             JSObject *obj, PRUint32 *length);
   virtual nsISupports* GetItemAt(nsISupports *aNative, PRUint32 aIndex,
                                  nsresult *aResult);
 
   // Override nsNamedArraySH::GetNamedItem()
-  virtual nsresult GetNamedItem(nsISupports *aNative, const nsAString& aName,
-                                nsISupports **aResult);
+  virtual nsISupports* GetNamedItem(nsISupports *aNative,
+                                    const nsAString& aName,
+                                    nsresult *aResult);
 
 public:
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
     return new nsHTMLCollectionSH(aData);
   }
 };
 
 
 // ContentList helper
 
-class nsContentListSH : public nsNodeListSH
+class nsContentListSH : public nsNamedArraySH
 {
 protected:
-  nsContentListSH(nsDOMClassInfoData* aData) : nsNodeListSH(aData)
+  nsContentListSH(nsDOMClassInfoData* aData) : nsNamedArraySH(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);
+
+  virtual nsresult GetLength(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
+                             JSObject *obj, PRUint32 *length);
+  virtual nsISupports* GetItemAt(nsISupports *aNative, PRUint32 aIndex,
+                                 nsresult *aResult);
+  virtual nsISupports* GetNamedItem(nsISupports *aNative,
+                                    const nsAString& aName,
+                                    nsresult *aResult);
 
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
     return new nsContentListSH(aData);
   }
 };
 
 
 
-// FomrControlList helper
-
-class nsFormControlListSH : public nsHTMLCollectionSH
-{
-protected:
-  nsFormControlListSH(nsDOMClassInfoData* aData) : nsHTMLCollectionSH(aData)
-  {
-  }
-
-  virtual ~nsFormControlListSH()
-  {
-  }
-
-  // Override nsNamedArraySH::GetNamedItem() since our NamedItem() can
-  // return either a nsIDOMNode or a nsIHTMLCollection
-  virtual nsresult GetNamedItem(nsISupports *aNative, const nsAString& aName,
-                                nsISupports **aResult);
-
-public:
-  static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
-  {
-    return new nsFormControlListSH(aData);
-  }
-};
-
-
 // Document helper, for document.location and document.on*
 
 class nsDocumentSH : public nsNodeSH
 {
 public:
   nsDocumentSH(nsDOMClassInfoData* aData) : nsNodeSH(aData)
   {
   }
@@ -1090,18 +1075,19 @@ protected:
   virtual ~nsPluginSH()
   {
   }
 
   virtual nsISupports* GetItemAt(nsISupports *aNative, PRUint32 aIndex,
                                  nsresult *aResult);
 
   // Override nsNamedArraySH::GetNamedItem()
-  virtual nsresult GetNamedItem(nsISupports *aNative, const nsAString& aName,
-                                nsISupports **aResult);
+  virtual nsISupports* GetNamedItem(nsISupports *aNative,
+                                    const nsAString& aName,
+                                    nsresult *aResult);
 
 public:
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
     return new nsPluginSH(aData);
   }
 };
 
@@ -1118,18 +1104,19 @@ protected:
   virtual ~nsPluginArraySH()
   {
   }
 
   virtual nsISupports* GetItemAt(nsISupports *aNative, PRUint32 aIndex,
                                  nsresult *aResult);
 
   // Override nsNamedArraySH::GetNamedItem()
-  virtual nsresult GetNamedItem(nsISupports *aNative, const nsAString& aName,
-                                nsISupports **aResult);
+  virtual nsISupports* GetNamedItem(nsISupports *aNative,
+                                    const nsAString& aName,
+                                    nsresult *aResult);
 
 public:
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
     return new nsPluginArraySH(aData);
   }
 };
 
@@ -1146,18 +1133,19 @@ protected:
   virtual ~nsMimeTypeArraySH()
   {
   }
 
   virtual nsISupports* GetItemAt(nsISupports *aNative, PRUint32 aIndex,
                                  nsresult *aResult);
 
   // Override nsNamedArraySH::GetNamedItem()
-  virtual nsresult GetNamedItem(nsISupports *aNative, const nsAString& aName,
-                                nsISupports **aResult);
+  virtual nsISupports* GetNamedItem(nsISupports *aNative,
+                                    const nsAString& aName,
+                                    nsresult *aResult);
 
 public:
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
     return new nsMimeTypeArraySH(aData);
   }
 };
 
@@ -1392,18 +1380,19 @@ protected:
   virtual ~nsTreeColumnsSH()
   {
   }
 
   virtual nsISupports* GetItemAt(nsISupports *aNative, PRUint32 aIndex,
                                  nsresult *aResult);
 
   // Override nsNamedArraySH::GetNamedItem()
-  virtual nsresult GetNamedItem(nsISupports *aNative, const nsAString& aName,
-                                nsISupports **aResult);
+  virtual nsISupports* GetNamedItem(nsISupports *aNative,
+                                    const nsAString& aName,
+                                    nsresult *aResult);
 
 public:
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
     return new nsTreeColumnsSH(aData);
   }
 };
 #endif
@@ -1433,18 +1422,19 @@ protected:
                           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);
+  virtual nsISupports* GetNamedItem(nsISupports *aNative,
+                                    const nsAString& aName,
+                                    nsresult *aResult);
 
 public:
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
     return new nsStorageSH(aData);
   }
 };
 
@@ -1460,18 +1450,19 @@ protected:
   }
 
   virtual nsISupports* GetItemAt(nsISupports *aNative, PRUint32 aIndex,
                                  nsresult *aResult)
   {
     return nsnull;
   }
   // Override nsNamedArraySH::GetNamedItem()
-  virtual nsresult GetNamedItem(nsISupports *aNative, const nsAString& aName,
-                                nsISupports **aResult);
+  virtual nsISupports* GetNamedItem(nsISupports *aNative,
+                                    const nsAString& aName,
+                                    nsresult *aResult);
 
 public:
   static nsIClassInfo *doCreate(nsDOMClassInfoData* aData)
   {
     return new nsStorageListSH(aData);
   }
 };
 
--- a/dom/src/base/nsMimeTypeArray.cpp
+++ b/dom/src/base/nsMimeTypeArray.cpp
@@ -44,20 +44,20 @@
 #include "nsIDOMPlugin.h"
 #include "nsDOMClassInfo.h"
 #include "nsIMIMEService.h"
 #include "nsIMIMEInfo.h"
 #include "nsIFile.h"
 
 
 nsMimeTypeArray::nsMimeTypeArray(nsIDOMNavigator* navigator)
+  : mNavigator(navigator),
+    mPluginMimeTypeCount(0),
+    mInited(PR_FALSE)
 {
-  mNavigator = navigator;
-  mMimeTypeCount = 0;
-  mMimeTypeArray = nsnull;
 }
 
 nsMimeTypeArray::~nsMimeTypeArray()
 {
   Clear();
 }
 
 
@@ -71,35 +71,44 @@ NS_INTERFACE_MAP_END
 
 NS_IMPL_ADDREF(nsMimeTypeArray)
 NS_IMPL_RELEASE(nsMimeTypeArray)
 
 
 NS_IMETHODIMP
 nsMimeTypeArray::GetLength(PRUint32* aLength)
 {
-  if (mMimeTypeArray == nsnull) {
+  if (!mInited) {
     nsresult rv = GetMimeTypes();
     if (rv != NS_OK)
       return rv;
   }
-  *aLength = mMimeTypeCount;
+
+  NS_ASSERTION(mPluginMimeTypeCount <= mMimeTypeArray.Count(),
+               "The number of total mimetypes should be equal to or higher "
+               "than the number of plugin mimetypes.");
+ 
+  *aLength = mPluginMimeTypeCount;
   return NS_OK;
 }
 
 nsIDOMMimeType*
 nsMimeTypeArray::GetItemAt(PRUint32 aIndex, nsresult *aResult)
 {
-  if (mMimeTypeArray == nsnull) {
+  if (!mInited) {
     *aResult = GetMimeTypes();
     if (*aResult != NS_OK)
       return nsnull;
   }
 
-  if (aIndex >= mMimeTypeCount) {
+  NS_ASSERTION(mPluginMimeTypeCount <= mMimeTypeArray.Count(),
+               "The number of total mimetypes should be equal to or higher "
+               "than the number of plugin mimetypes.");
+
+  if (aIndex >= mPluginMimeTypeCount) {
     *aResult = NS_ERROR_FAILURE;
 
     return nsnull;
   }
 
   *aResult = NS_OK;
 
   return mMimeTypeArray[aIndex];
@@ -110,41 +119,40 @@ nsMimeTypeArray::Item(PRUint32 aIndex, n
 {
   nsresult rv;
 
   NS_IF_ADDREF(*aReturn = GetItemAt(aIndex, &rv));
 
   return rv;
 }
 
-NS_IMETHODIMP
-nsMimeTypeArray::NamedItem(const nsAString& aName, nsIDOMMimeType** aReturn)
+nsIDOMMimeType*
+nsMimeTypeArray::GetNamedItem(const nsAString& aName, nsresult* aResult)
 {
-  NS_ENSURE_ARG_POINTER(aReturn);
-  *aReturn = nsnull;
+  if (!mInited) {
+    *aResult = GetMimeTypes();
+    if (*aResult != NS_OK)
+      return nsnull;
+  }
 
-  if (mMimeTypeArray == nsnull) {
-    nsresult rv = GetMimeTypes();
-    if (rv != NS_OK)
-      return rv;
-  }
+  NS_ASSERTION(mPluginMimeTypeCount <= mMimeTypeArray.Count(),
+               "The number of total mimetypes should be equal to or higher "
+               "than the number of plugin mimetypes.");
+
+  *aResult = NS_OK;
 
   nsAutoString type;
 
-  for (PRUint32 i = 0; i < mMimeTypeCount; i++) {
+  for (PRInt32 i = 0; i < mMimeTypeArray.Count(); i++) {
     nsIDOMMimeType *mtype = mMimeTypeArray[i];
 
     mtype->GetType(type);
 
     if (type.Equals(aName)) {
-      *aReturn = mtype;
-
-      NS_ADDREF(*aReturn);
-
-      return NS_OK;
+      return mtype;
     }
   }
 
   // Now let's check with the MIME service.
   nsCOMPtr<nsIMIMEService> mimeSrv = do_GetService("@mozilla.org/mime;1");
   if (mimeSrv) {
     nsCOMPtr<nsIMIMEInfo> mimeInfo;
     mimeSrv->GetFromTypeAndExtension(NS_ConvertUTF16toUTF8(aName), EmptyCString(),
@@ -161,94 +169,99 @@ nsMimeTypeArray::NamedItem(const nsAStri
           mimeInfo->GetPreferredApplicationHandler(getter_AddRefs(helper));
           if (!helper) {
             // mime info from the OS may not have a PreferredApplicationHandler
             // so just check for an empty default description
             nsAutoString defaultDescription;
             mimeInfo->GetDefaultDescription(defaultDescription);
             if (defaultDescription.IsEmpty()) {
               // no support; just leave
-              return NS_OK;
+              return nsnull;
             }
           }
         }
       }
 
       // If we got here, we support this type!  Say so.
-      nsCOMPtr<nsIDOMMimeType> helper = new nsHelperMimeType(aName);
-      if (!helper) {
-        return NS_ERROR_OUT_OF_MEMORY;
-      }
-      nsCOMPtr<nsIDOMMimeType> entry = new nsMimeType(nsnull, helper);
-      if (!entry) {
-        return NS_ERROR_OUT_OF_MEMORY;
+      nsCOMPtr<nsIDOMMimeType> helper, entry;
+      if (!(helper = new nsHelperMimeType(aName)) ||
+          !(entry = new nsMimeType(nsnull, helper)) ||
+          !mMimeTypeArray.AppendObject(entry)) {
+        *aResult = NS_ERROR_OUT_OF_MEMORY;
+
+        return nsnull;
       }
 
-      entry.swap(*aReturn);
+      return entry;
     }
   }
 
-  return NS_OK;
+  return nsnull;
+}
+
+NS_IMETHODIMP
+nsMimeTypeArray::NamedItem(const nsAString& aName, nsIDOMMimeType** aReturn)
+{
+  nsresult rv;
+
+  NS_IF_ADDREF(*aReturn = GetNamedItem(aName, &rv));
+
+  return rv;
 }
 
 void  nsMimeTypeArray::Clear()
 {
-  if (mMimeTypeArray != nsnull) {
-    for (PRUint32 i = 0; i < mMimeTypeCount; i++) {
-      NS_IF_RELEASE(mMimeTypeArray[i]);
-    }
-    delete[] mMimeTypeArray;
-    mMimeTypeArray = nsnull;
-  }
-  mMimeTypeCount = 0;
+  mMimeTypeArray.Clear();
+  mPluginMimeTypeCount = 0;
 }
 
 nsresult nsMimeTypeArray::Refresh()
 {
   Clear();
   return GetMimeTypes();
 }
 
 nsresult nsMimeTypeArray::GetMimeTypes()
 {
-  NS_PRECONDITION(!mMimeTypeArray && mMimeTypeCount==0,
+  NS_PRECONDITION(!mInited && mPluginMimeTypeCount==0,
                       "already initialized");
 
   nsIDOMPluginArray* pluginArray = nsnull;
   nsresult rv = mNavigator->GetPlugins(&pluginArray);
   if (rv == NS_OK) {
     // count up all possible MimeTypes, and collect them here. Later,
     // we'll remove duplicates.
-    mMimeTypeCount = 0;
+    mPluginMimeTypeCount = 0;
     PRUint32 pluginCount = 0;
     rv = pluginArray->GetLength(&pluginCount);
     if (rv == NS_OK) {
       PRUint32 i;
       for (i = 0; i < pluginCount; i++) {
         nsCOMPtr<nsIDOMPlugin> plugin;
         if (NS_SUCCEEDED(pluginArray->Item(i, getter_AddRefs(plugin))) &&
             plugin) {
           PRUint32 mimeTypeCount = 0;
           if (plugin->GetLength(&mimeTypeCount) == NS_OK)
-            mMimeTypeCount += mimeTypeCount;
+            mPluginMimeTypeCount += mimeTypeCount;
         }
       }
       // now we know how many there are, start gathering them.
-      mMimeTypeArray = new nsIDOMMimeType*[mMimeTypeCount];
-      if (mMimeTypeArray == nsnull)
+      if (!mMimeTypeArray.SetCapacity(mPluginMimeTypeCount))
         return NS_ERROR_OUT_OF_MEMORY;
-      PRUint32 mimeTypeIndex = 0;
       PRUint32 k;
       for (k = 0; k < pluginCount; k++) {
         nsIDOMPlugin* plugin = nsnull;
         if (pluginArray->Item(k, &plugin) == NS_OK) {
           PRUint32 mimeTypeCount = 0;
           if (plugin->GetLength(&mimeTypeCount) == NS_OK) {
-            for (PRUint32 j = 0; j < mimeTypeCount; j++)
-              plugin->Item(j, &mMimeTypeArray[mimeTypeIndex++]);
+            nsCOMPtr<nsIDOMMimeType> item;
+            for (PRUint32 j = 0; j < mimeTypeCount; j++) {
+              plugin->Item(j, getter_AddRefs(item));
+              mMimeTypeArray.AppendObject(item);
+            }
           }
           NS_RELEASE(plugin);
         }
       }
     }
     NS_RELEASE(pluginArray);
   }
   return rv;
--- a/dom/src/base/nsMimeTypeArray.h
+++ b/dom/src/base/nsMimeTypeArray.h
@@ -37,31 +37,33 @@
 
 #ifndef nsMimeTypeArray_h___
 #define nsMimeTypeArray_h___
 
 #include "nsIDOMMimeTypeArray.h"
 #include "nsIDOMMimeType.h"
 #include "nsString.h"
 #include "nsCOMPtr.h"
+#include "nsCOMArray.h"
 
 class nsIDOMNavigator;
 
 class nsMimeTypeArray : public nsIDOMMimeTypeArray
 {
 public:
   nsMimeTypeArray(nsIDOMNavigator* navigator);
   virtual ~nsMimeTypeArray();
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSIDOMMIMETYPEARRAY
 
   nsresult Refresh();
 
   nsIDOMMimeType* GetItemAt(PRUint32 aIndex, nsresult* aResult);
+  nsIDOMMimeType* GetNamedItem(const nsAString& aName, 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
@@ -76,18 +78,24 @@ public:
   }
 
 private:
   nsresult GetMimeTypes();
   void     Clear();
 
 protected:
   nsIDOMNavigator* mNavigator;
-  PRUint32 mMimeTypeCount;
-  nsIDOMMimeType** mMimeTypeArray;
+  // Number of mimetypes handled by plugins.
+  PRUint32 mPluginMimeTypeCount;
+  // mMimeTypeArray contains all mimetypes handled by plugins
+  // (mPluginMimeTypeCount) and any mimetypes that we handle internally and
+  // have been looked up before. The number of items in mMimeTypeArray should
+  // thus always be equal to or higher than mPluginMimeTypeCount.
+  nsCOMArray<nsIDOMMimeType> mMimeTypeArray;
+  PRBool mInited;
 };
 
 class nsMimeType : public nsIDOMMimeType
 {
 public:
   nsMimeType(nsIDOMPlugin* aPlugin, nsIDOMMimeType* aMimeType);
   virtual ~nsMimeType();
 
--- a/dom/src/base/nsPluginArray.cpp
+++ b/dom/src/base/nsPluginArray.cpp
@@ -127,44 +127,51 @@ nsPluginArray::Item(PRUint32 aIndex, nsI
 {
   nsresult rv;
 
   NS_IF_ADDREF(*aReturn = GetItemAt(aIndex, &rv));
 
   return rv;
 }
 
-NS_IMETHODIMP
-nsPluginArray::NamedItem(const nsAString& aName, nsIDOMPlugin** aReturn)
+nsIDOMPlugin*
+nsPluginArray::GetNamedItem(const nsAString& aName, nsresult* aResult)
 {
-  NS_PRECONDITION(nsnull != aReturn, "null arg");
-  *aReturn = nsnull;
+  *aResult = NS_OK;
 
   if (!AllowPlugins())
-    return NS_OK;
+    return nsnull;
 
   if (mPluginArray == nsnull) {
-    nsresult rv = GetPlugins();
-    if (rv != NS_OK)
-      return rv;
+    *aResult = GetPlugins();
+    if (*aResult != NS_OK)
+      return nsnull;
   }
 
   for (PRUint32 i = 0; i < mPluginCount; i++) {
     nsAutoString pluginName;
     nsIDOMPlugin* plugin = mPluginArray[i];
-    if (plugin->GetName(pluginName) == NS_OK) {
-      if (pluginName.Equals(aName)) {
-        *aReturn = plugin;
-        NS_IF_ADDREF(plugin);
-        break;
-      }
+    if (plugin->GetName(pluginName) == NS_OK && pluginName.Equals(aName)) {
+      return plugin;
     }
   }
 
-  return NS_OK;
+  return nsnull;
+}
+
+NS_IMETHODIMP
+nsPluginArray::NamedItem(const nsAString& aName, nsIDOMPlugin** aReturn)
+{
+  NS_PRECONDITION(nsnull != aReturn, "null arg");
+
+  nsresult rv;
+
+  NS_IF_ADDREF(*aReturn = GetNamedItem(aName, &rv));
+
+  return rv;
 }
 
 nsresult
 nsPluginArray::GetPluginHost(nsIPluginHost** aPluginHost)
 {
   NS_ENSURE_ARG_POINTER(aPluginHost);
 
   nsresult rv = NS_OK;
@@ -359,39 +366,45 @@ nsPluginElement::Item(PRUint32 aIndex, n
 {
   nsresult rv;
 
   NS_IF_ADDREF(*aReturn = GetItemAt(aIndex, &rv));
 
   return rv;
 }
 
+nsIDOMMimeType*
+nsPluginElement::GetNamedItem(const nsAString& aName, nsresult *aResult)
+{
+  if (mMimeTypeArray == nsnull) {
+    *aResult = GetMimeTypes();
+    if (*aResult != NS_OK)
+      return nsnull;
+  }
+
+  *aResult = NS_OK;
+  for (PRUint32 i = 0; i < mMimeTypeCount; i++) {
+    nsAutoString type;
+    nsIDOMMimeType* mimeType = mMimeTypeArray[i];
+    if (mimeType->GetType(type) == NS_OK && type.Equals(aName)) {
+      return mimeType;
+    }
+  }
+
+  return nsnull;
+}
+
 NS_IMETHODIMP
 nsPluginElement::NamedItem(const nsAString& aName, nsIDOMMimeType** aReturn)
 {
-  if (mMimeTypeArray == nsnull) {
-    nsresult rv = GetMimeTypes();
-    if (rv != NS_OK)
-      return rv;
-  }
+  nsresult rv;
 
-  *aReturn = nsnull;
-  for (PRUint32 i = 0; i < mMimeTypeCount; i++) {
-    nsAutoString type;
-    nsIDOMMimeType* mimeType = mMimeTypeArray[i];
-    if (mimeType->GetType(type) == NS_OK) {
-      if (type.Equals(aName)) {
-        *aReturn = mimeType;
-        NS_ADDREF(mimeType);
-        break;
-      }
-    }
-  }
+  NS_IF_ADDREF(*aReturn = GetNamedItem(aName, &rv));
 
-  return NS_OK;
+  return rv;
 }
 
 nsresult
 nsPluginElement::GetMimeTypes()
 {
   nsresult rv = mPlugin->GetLength(&mMimeTypeCount);
   if (rv == NS_OK) {
     mMimeTypeArray = new nsIDOMMimeType*[mMimeTypeCount];
--- a/dom/src/base/nsPluginArray.h
+++ b/dom/src/base/nsPluginArray.h
@@ -56,16 +56,17 @@ public:
   NS_DECL_ISUPPORTS
 
   // nsIDOMPluginArray
   NS_DECL_NSIDOMPLUGINARRAY
 
   nsresult GetPluginHost(nsIPluginHost** aPluginHost);
 
   nsIDOMPlugin* GetItemAt(PRUint32 aIndex, nsresult* aResult);
+  nsIDOMPlugin* GetNamedItem(const nsAString& aName, 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
@@ -99,16 +100,17 @@ class nsPluginElement : public nsIDOMPlu
 public:
   nsPluginElement(nsIDOMPlugin* plugin);
   virtual ~nsPluginElement();
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSIDOMPLUGIN
 
   nsIDOMMimeType* GetItemAt(PRUint32 aIndex, nsresult* aResult);
+  nsIDOMMimeType* GetNamedItem(const nsAString& aName, 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
--- a/dom/src/storage/nsDOMStorage.cpp
+++ b/dom/src/storage/nsDOMStorage.cpp
@@ -601,58 +601,69 @@ nsDOMStorage::Key(PRUint32 aIndex, nsASt
     return NS_ERROR_DOM_INDEX_SIZE_ERR;
   }
 
   aKey = data.mItem->GetKey();
 
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsDOMStorage::GetItem(const nsAString& aKey, nsIDOMStorageItem **aItem)
+nsIDOMStorageItem*
+nsDOMStorage::GetNamedItem(const nsAString& aKey, nsresult* aResult)
 {
-  *aItem = nsnull;
+  if (!CacheStoragePermissions()) {
+    *aResult = NS_ERROR_DOM_SECURITY_ERR;
+    return nsnull;
+  }
 
-  if (!CacheStoragePermissions())
-    return NS_ERROR_DOM_SECURITY_ERR;
-
+  *aResult = NS_OK;
   if (aKey.IsEmpty())
-    return NS_OK;
+    return nsnull;
 
   nsSessionStorageEntry *entry = mItems.GetEntry(aKey);
- 
+  nsIDOMStorageItem* item = nsnull;
   if (entry) {
-    if (!IsCallerSecure() && entry->mItem->IsSecure()) {
-      return NS_OK;
+    if (IsCallerSecure() || !entry->mItem->IsSecure()) {
+      item = entry->mItem;
     }
-    NS_ADDREF(*aItem = entry->mItem);
   }
   else if (UseDB()) {
     PRBool secure;
     nsAutoString value;
     nsAutoString unused;
     nsresult rv = GetDBValue(aKey, value, &secure, unused);
     // return null if access isn't allowed or the key wasn't found
     if (rv == NS_ERROR_DOM_SECURITY_ERR || rv == NS_ERROR_DOM_NOT_FOUND_ERR)
-      return NS_OK;
-    NS_ENSURE_SUCCESS(rv, rv);
+      return nsnull;
+
+    *aResult = rv;
+    NS_ENSURE_SUCCESS(rv, nsnull);
 
     nsRefPtr<nsDOMStorageItem> newitem =
       new nsDOMStorageItem(this, aKey, value, secure);
-    if (!newitem)
-      return NS_ERROR_OUT_OF_MEMORY;
-
-    entry = mItems.PutEntry(aKey);
-    NS_ENSURE_TRUE(entry, NS_ERROR_OUT_OF_MEMORY);
-
-    entry->mItem = newitem;
-    NS_ADDREF(*aItem = newitem);
+    if (newitem && (entry = mItems.PutEntry(aKey))) {
+      item = entry->mItem = newitem;
+    }
+    else {
+      *aResult = NS_ERROR_OUT_OF_MEMORY;
+    }
   }
 
-  return NS_OK;
+  return item;
+}
+
+
+NS_IMETHODIMP
+nsDOMStorage::GetItem(const nsAString& aKey, nsIDOMStorageItem **aItem)
+{
+  nsresult rv;
+
+  NS_IF_ADDREF(*aItem = GetNamedItem(aKey, &rv));
+
+  return rv;
 }
 
 NS_IMETHODIMP
 nsDOMStorage::SetItem(const nsAString& aKey, const nsAString& aData)
 {
   if (!CacheStoragePermissions())
     return NS_ERROR_DOM_SECURITY_ERR;
 
@@ -1036,138 +1047,152 @@ NS_INTERFACE_MAP_BEGIN(nsDOMStorageList)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_INTERFACE_MAP_ENTRY(nsIDOMStorageList)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(StorageList)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_ADDREF(nsDOMStorageList)
 NS_IMPL_RELEASE(nsDOMStorageList)
 
-nsresult
-nsDOMStorageList::NamedItem(const nsAString& aDomain,
-                            nsIDOMStorage** aStorage)
+nsIDOMStorage*
+nsDOMStorageList::GetNamedItem(const nsAString& aDomain, nsresult* aResult)
 {
-  *aStorage = nsnull;
-
   nsCAutoString requestedDomain;
 
-  nsresult rv;
   // Normalize the requested domain
   nsCOMPtr<nsIIDNService> idn = do_GetService(NS_IDNSERVICE_CONTRACTID);
   if (idn) {
-    rv = idn->ConvertUTF8toACE(NS_ConvertUTF16toUTF8(aDomain),
-                               requestedDomain);
-    NS_ENSURE_SUCCESS(rv, rv);
+    *aResult = idn->ConvertUTF8toACE(NS_ConvertUTF16toUTF8(aDomain),
+                                     requestedDomain);
+    NS_ENSURE_SUCCESS(*aResult, nsnull);
   } else {
     // Don't have the IDN service, best we can do is URL escape.
     NS_EscapeURL(NS_ConvertUTF16toUTF8(aDomain),
                  esc_OnlyNonASCII | esc_AlwaysCopy,
                  requestedDomain);
   }
   ToLowerCase(requestedDomain);
 
   nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
-  if (!ssm)
-    return NS_ERROR_FAILURE;
+  if (!ssm) {
+    *aResult = NS_ERROR_FAILURE;
+    return nsnull;
+  }
 
   nsCOMPtr<nsIPrincipal> subjectPrincipal;
-  rv = ssm->GetSubjectPrincipal(getter_AddRefs(subjectPrincipal));
-  NS_ENSURE_SUCCESS(rv, rv);
+  *aResult = ssm->GetSubjectPrincipal(getter_AddRefs(subjectPrincipal));
+  NS_ENSURE_SUCCESS(*aResult, nsnull);
 
   nsCOMPtr<nsIURI> uri;
   nsCAutoString currentDomain;
   if (subjectPrincipal) {
-    rv = subjectPrincipal->GetDomain(getter_AddRefs(uri));
-    NS_ENSURE_SUCCESS(rv, rv);
+    *aResult = subjectPrincipal->GetDomain(getter_AddRefs(uri));
+    NS_ENSURE_SUCCESS(*aResult, nsnull);
 
     if (!uri) {
-      rv = subjectPrincipal->GetURI(getter_AddRefs(uri));
-      NS_ENSURE_SUCCESS(rv, rv);
+      *aResult = subjectPrincipal->GetURI(getter_AddRefs(uri));
+      NS_ENSURE_SUCCESS(*aResult, nsnull);
     }
 
     if (uri) {
       PRPackedBool sessionOnly;
-      if (!nsDOMStorage::CanUseStorage(uri, &sessionOnly))
-        return NS_ERROR_DOM_SECURITY_ERR;
+      if (!nsDOMStorage::CanUseStorage(uri, &sessionOnly)) {
+        *aResult = NS_ERROR_DOM_SECURITY_ERR;
+        return nsnull;
+      }
 
       nsCOMPtr<nsIURI> innerUri = NS_GetInnermostURI(uri);
-      if (!innerUri)
-        return NS_ERROR_UNEXPECTED;
+      if (!innerUri) {
+        *aResult = NS_ERROR_UNEXPECTED;
+        return nsnull;
+      }
 
       uri = innerUri;
-      rv = uri->GetAsciiHost(currentDomain);
-      NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_SECURITY_ERR);
+      nsresult rv = uri->GetAsciiHost(currentDomain);
+      if (NS_FAILED(rv)) {
+        *aResult = NS_ERROR_DOM_SECURITY_ERR;
+        return nsnull;
+      }
     }
   }
 
   PRBool isSystem;
-  rv = ssm->SubjectPrincipalIsSystem(&isSystem);
-  NS_ENSURE_SUCCESS(rv, rv);
+  *aResult = ssm->SubjectPrincipalIsSystem(&isSystem);
+  NS_ENSURE_SUCCESS(*aResult, nsnull);
 
   // allow code that has read privileges to get the storage for any domain
   if (!isSystem && nsContentUtils::IsCallerTrustedForRead())
     isSystem = PR_TRUE;
 
   if (isSystem || !currentDomain.IsEmpty()) {
     return GetStorageForDomain(uri, NS_ConvertUTF8toUTF16(requestedDomain),
                                NS_ConvertUTF8toUTF16(currentDomain),
-                               isSystem, aStorage);
+                               isSystem, aResult);
   }
 
-  return NS_ERROR_DOM_SECURITY_ERR;
+  *aResult = NS_ERROR_DOM_SECURITY_ERR;
+  return nsnull;
+}
+
+NS_IMETHODIMP
+nsDOMStorageList::NamedItem(const nsAString& aDomain,
+                            nsIDOMStorage** aStorage)
+{
+  nsresult rv;
+  NS_IF_ADDREF(*aStorage = GetNamedItem(aDomain, &rv));
+  return rv;
 }
 
 // static
 PRBool
 nsDOMStorageList::CanAccessDomain(const nsAString& aRequestedDomain,
                                   const nsAString& aCurrentDomain)
 {
   return aRequestedDomain.Equals(aCurrentDomain);
 }
 
-nsresult
+nsIDOMStorage*
 nsDOMStorageList::GetStorageForDomain(nsIURI* aURI,
                                       const nsAString& aRequestedDomain,
                                       const nsAString& aCurrentDomain,
                                       PRBool aNoCurrentDomainCheck,
-                                      nsIDOMStorage** aStorage)
+                                      nsresult* aResult)
 {
-  if (!aNoCurrentDomainCheck && !CanAccessDomain(aRequestedDomain,
-                                                 aCurrentDomain)) {
-    return NS_ERROR_DOM_SECURITY_ERR;
+  nsStringArray requestedDomainArray;
+  if ((!aNoCurrentDomainCheck &&
+       !CanAccessDomain(aRequestedDomain, aCurrentDomain)) ||
+      !ConvertDomainToArray(aRequestedDomain, &requestedDomainArray)) {
+    *aResult = NS_ERROR_DOM_SECURITY_ERR;
+
+    return nsnull;
   }
 
-  nsStringArray requestedDomainArray;
-  PRBool ok = ConvertDomainToArray(aRequestedDomain, &requestedDomainArray);
-  if (!ok)
-    return NS_ERROR_DOM_SECURITY_ERR;
-  
   // now rebuild a string for the domain.
   nsAutoString usedDomain;
   PRInt32 requestedPos = 0;
   for (requestedPos = 0; requestedPos < requestedDomainArray.Count();
        requestedPos++) {
     if (!usedDomain.IsEmpty())
       usedDomain.AppendLiteral(".");
     usedDomain.Append(*requestedDomainArray[requestedPos]);
   }
 
+  *aResult = NS_OK;
+
   // now have a valid domain, so look it up in the storage table
-  if (!mStorages.Get(usedDomain, aStorage)) {
+  nsIDOMStorage* storage = mStorages.GetWeak(usedDomain);
+  if (!storage) {
     nsCOMPtr<nsIDOMStorage> newstorage = new nsDOMStorage(aURI, usedDomain, PR_TRUE);
-    if (!newstorage)
-      return NS_ERROR_OUT_OF_MEMORY;
-
-    if (!mStorages.Put(usedDomain, newstorage))
-      return NS_ERROR_OUT_OF_MEMORY;
-
-    newstorage.swap(*aStorage);
+    if (newstorage && mStorages.Put(usedDomain, newstorage))
+      storage = newstorage;
+    else
+      *aResult = NS_ERROR_OUT_OF_MEMORY;
   }
 
-  return NS_OK;
+  return storage;
 }
 
 // static
 PRBool
 nsDOMStorageList::ConvertDomainToArray(const nsAString& aDomain,
                                        nsStringArray* aArray)
 {
   PRInt32 length = aDomain.Length();
--- a/dom/src/storage/nsDOMStorage.h
+++ b/dom/src/storage/nsDOMStorage.h
@@ -162,16 +162,23 @@ public:
 
   // set the value corresponding to a key as secure.
   nsresult
   SetSecure(const nsAString& aKey, PRBool aSecure);
 
   // clear all values from the store
   void ClearAll();
 
+  nsIDOMStorageItem* GetNamedItem(const nsAString& aKey, nsresult* aResult);
+
+  static nsDOMStorage* FromSupports(nsISupports* aSupports)
+  {
+    return static_cast<nsDOMStorage*>(static_cast<nsIDOMStorage*>(aSupports));
+  }
+
 protected:
 
   friend class nsDOMStorageManager;
 
   static nsresult InitDB();
 
   // cache the keys from the database for faster lookup
   nsresult CacheKeysFromDB();
@@ -212,16 +219,18 @@ public:
   virtual ~nsDOMStorageList() {}
 
   // nsISupports
   NS_DECL_ISUPPORTS
 
   // nsIDOMStorageList
   NS_DECL_NSIDOMSTORAGELIST
 
+  nsIDOMStorage* GetNamedItem(const nsAString& aDomain, nsresult* aResult);
+
   /**
    * Check whether aCurrentDomain has access to aRequestedDomain
    */
   static PRBool
   CanAccessDomain(const nsAString& aRequestedDomain,
                   const nsAString& aCurrentDomain);
 
 protected:
@@ -231,22 +240,22 @@ protected:
    * aNoCurrentDomainCheck may be true to skip the domain comparison;
    * this is used for chrome code so that it may retrieve data from
    * any domain.
    *
    * @param aRequestedDomain domain to return
    * @param aCurrentDomain domain of current caller
    * @param aNoCurrentDomainCheck true to skip domain comparison
    */
-  nsresult
+  nsIDOMStorage*
   GetStorageForDomain(nsIURI* aURI,
                       const nsAString& aRequestedDomain,
                       const nsAString& aCurrentDomain,
                       PRBool aNoCurrentDomainCheck,
-                      nsIDOMStorage** aStorage);
+                      nsresult* aResult);
 
   /**
    * Convert the domain into an array of its component parts.
    */
   static PRBool
   ConvertDomainToArray(const nsAString& aDomain,
                        nsStringArray* aArray);
 
--- a/layout/xul/base/src/tree/src/nsTreeColumns.cpp
+++ b/layout/xul/base/src/tree/src/nsTreeColumns.cpp
@@ -519,27 +519,32 @@ nsTreeColumns::GetColumnFor(nsIDOMElemen
       NS_ADDREF(*_retval = currCol);
       break;
     }
   }
 
   return NS_OK;
 }
 
+nsITreeColumn*
+nsTreeColumns::GetNamedColumn(const nsAString& aId)
+{
+  EnsureColumns();
+  for (nsTreeColumn* currCol = mFirstColumn; currCol; currCol = currCol->GetNext()) {
+    if (currCol->GetId().Equals(aId)) {
+      return currCol;
+    }
+  }
+  return nsnull;
+}
+
 NS_IMETHODIMP
 nsTreeColumns::GetNamedColumn(const nsAString& aId, nsITreeColumn** _retval)
 {
-  EnsureColumns();
-  *_retval = nsnull;
-  for (nsTreeColumn* currCol = mFirstColumn; currCol; currCol = currCol->GetNext()) {
-    if (currCol->GetId().Equals(aId)) {
-      NS_ADDREF(*_retval = currCol);
-      break;
-    }
-  }
+  NS_IF_ADDREF(*_retval = GetNamedColumn(aId));
   return NS_OK;
 }
 
 nsITreeColumn*
 nsTreeColumns::GetColumnAt(PRInt32 aIndex)
 {
   EnsureColumns();
   for (nsTreeColumn* currCol = mFirstColumn; currCol; currCol = currCol->GetNext()) {
@@ -548,17 +553,16 @@ nsTreeColumns::GetColumnAt(PRInt32 aInde
     }
   }
   return nsnull;
 }
 
 NS_IMETHODIMP
 nsTreeColumns::GetColumnAt(PRInt32 aIndex, nsITreeColumn** _retval)
 {
-  EnsureColumns();
   NS_IF_ADDREF(*_retval = GetColumnAt(aIndex));
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsTreeColumns::InvalidateColumns()
 {
   NS_IF_RELEASE(mFirstColumn);
--- a/layout/xul/base/src/tree/src/nsTreeColumns.h
+++ b/layout/xul/base/src/tree/src/nsTreeColumns.h
@@ -144,16 +144,17 @@ class nsTreeColumns : public nsITreeColu
 public:
   nsTreeColumns(nsITreeBoxObject* aTree);
   ~nsTreeColumns();
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSITREECOLUMNS
 
   nsITreeColumn* GetColumnAt(PRInt32 aIndex);
+  nsITreeColumn* GetNamedColumn(const nsAString& aId);
 
   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