back out changes.
authordwitte@stanford.edu
Wed, 19 Dec 2007 03:07:41 -0800
changeset 9465 53b19cd504ea9fdb72656da64cd896bfc11fe61c
parent 9464 3286bd5dafa71337f3d54f8b5fa1baa233aad7e3
child 9466 18c4a756ca254dd138b8083ed514e86dd072f344
push id1
push userbsmedberg@mozilla.com
push dateThu, 20 Mar 2008 16:49:24 +0000
treeherdermozilla-central@61007906a1f8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone1.9b3pre
back out changes.
content/base/public/nsIDocument.h
content/base/public/nsINode.h
content/base/public/nsPresShellIterator.h
content/base/src/nsDocument.cpp
content/base/src/nsDocument.h
content/base/src/nsGenericElement.cpp
content/events/src/nsEventListenerManager.cpp
content/events/src/nsEventListenerManager.h
layout/style/nsCSSLoader.cpp
layout/style/nsCSSLoader.h
modules/libpr0n/src/imgRequest.cpp
modules/libpr0n/src/imgRequest.h
xpcom/build/dlldeps.cpp
xpcom/glue/nsTArray.cpp
xpcom/glue/nsTArray.h
xpcom/glue/nsTObserverArray.cpp
xpcom/glue/nsTObserverArray.h
--- a/content/base/public/nsIDocument.h
+++ b/content/base/public/nsIDocument.h
@@ -991,17 +991,17 @@ protected:
   // if this document is part of a multipart document,
   // the ID can be used to distinguish it from the other parts.
   PRUint32 mPartID;
   
   // Cycle collector generation in which we're certain that this document
   // won't be collected
   PRUint32 mMarkedCCGeneration;
 
-  nsTObserverArray<nsIPresShell*> mPresShells;
+  nsTObserverArray<nsIPresShell> mPresShells;
 
   nsCOMArray<nsINode> mSubtreeModifiedTargets;
   PRUint32            mSubtreeModifiedDepth;
 
 private:
   // JSObject cache. Only to be used for performance
   // optimizations. This will be set once this document is touched
   // from JS, and it will be unset once the JSObject is finalized.
--- a/content/base/public/nsINode.h
+++ b/content/base/public/nsINode.h
@@ -559,17 +559,17 @@ public:
      * mFlagsOrSlots member, but these are used when the slots class
      * is allocated.
      */
     PtrBits mFlags;
 
     /**
      * A list of mutation observers
      */
-    nsTObserverArray<nsIMutationObserver*> mMutationObservers;
+    nsTObserverArray<nsIMutationObserver> mMutationObservers;
 
     /**
      * An object implementing nsIDOMNodeList for this content (childNodes)
      * @see nsIDOMNodeList
      * @see nsGenericHTMLElement::GetChildNodes
      *
      * MSVC 7 doesn't like this as an nsRefPtr
      */
--- a/content/base/public/nsPresShellIterator.h
+++ b/content/base/public/nsPresShellIterator.h
@@ -37,27 +37,27 @@
 
 #ifndef nsPresShellIterato_h___
 #define nsPresShellIterato_h___
 
 #include "nsIPresShell.h"
 #include "nsIDocument.h"
 
 class nsPresShellIterator :
-  private nsTObserverArray<nsIPresShell*>::ForwardIterator
+  private nsTObserverArray<nsIPresShell>::ForwardIterator
 {
 public:
   nsPresShellIterator(nsIDocument* aDoc)
-  : nsTObserverArray<nsIPresShell*>::ForwardIterator(aDoc->mPresShells),
+  : nsTObserverArray<nsIPresShell>::ForwardIterator(aDoc->mPresShells),
     mDoc(aDoc) {}
 
   already_AddRefed<nsIPresShell> GetNextShell()
   {
     nsIPresShell* shell = nsnull;
-    if (!mDoc->ShellsAreHidden() && HasMore()) {
+    if (!mDoc->ShellsAreHidden()) {
       shell = GetNext();
       NS_IF_ADDREF(shell);
     }
     return shell;
   }
 private:
   static void* operator new(size_t) CPP_THROW_NEW { return 0; }
   static void operator delete(void*, size_t) {}
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -1121,17 +1121,17 @@ nsDocument::Init()
 
   nsINode::nsSlots* slots = GetSlots();
   NS_ENSURE_TRUE(slots,NS_ERROR_OUT_OF_MEMORY);
 
   // Prepend self as mutation-observer whether we need it or not (some
   // subclasses currently do, other don't). This is because the code in
   // nsNodeUtils always notifies the first observer first, expecting the
   // first observer to be the document.
-  NS_ENSURE_TRUE(slots->mMutationObservers.PrependElementUnlessExists(this),
+  NS_ENSURE_TRUE(slots->mMutationObservers.PrependObserver(this),
                  NS_ERROR_OUT_OF_MEMORY);
 
 
   mOnloadBlocker = new nsOnloadBlocker();
   NS_ENSURE_TRUE(mOnloadBlocker, NS_ERROR_OUT_OF_MEMORY);
   
   NS_NewCSSLoader(this, &mCSSLoader);
   NS_ENSURE_TRUE(mCSSLoader, NS_ERROR_OUT_OF_MEMORY);
@@ -2040,34 +2040,34 @@ nsDocument::doCreateShell(nsPresContext*
   if (NS_FAILED(rv)) {
     return rv;
   }
 
   rv = shell->Init(this, aContext, aViewManager, aStyleSet, aCompatMode);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Note: we don't hold a ref to the shell (it holds a ref to us)
-  NS_ENSURE_TRUE(mPresShells.AppendElementUnlessExists(shell),
+  NS_ENSURE_TRUE(mPresShells.AppendObserverUnlessExists(shell),
                  NS_ERROR_OUT_OF_MEMORY);
   shell.swap(*aInstancePtrResult);
 
   return NS_OK;
 }
 
 PRBool
 nsDocument::DeleteShell(nsIPresShell* aShell)
 {
-  return mPresShells.RemoveElement(aShell);
+  return mPresShells.RemoveObserver(aShell);
 }
 
 
 nsIPresShell *
 nsDocument::GetPrimaryShell() const
 {
-  return mShellsAreHidden ? nsnull : mPresShells.SafeElementAt(0, nsnull);
+  return mShellsAreHidden ? nsnull : mPresShells.SafeObserverAt(0);
 }
 
 PR_STATIC_CALLBACK(void)
 SubDocClearEntry(PLDHashTable *table, PLDHashEntryHdr *entry)
 {
   SubDocMapEntry *e = static_cast<SubDocMapEntry *>(entry);
 
   NS_RELEASE(e->mKey);
@@ -2649,30 +2649,30 @@ nsDocument::ScriptLoader()
 }
 
 // Note: We don't hold a reference to the document observer; we assume
 // that it has a live reference to the document.
 void
 nsDocument::AddObserver(nsIDocumentObserver* aObserver)
 {
   // The array makes sure the observer isn't already in the list
-  mObservers.AppendElementUnlessExists(aObserver);
+  mObservers.AppendObserverUnlessExists(aObserver);
   AddMutationObserver(aObserver);
 }
 
 PRBool
 nsDocument::RemoveObserver(nsIDocumentObserver* aObserver)
 {
   // If we're in the process of destroying the document (and we're
   // informing the observers of the destruction), don't remove the
   // observers from the list. This is not a big deal, since we
   // don't hold a live reference to the observers.
   if (!mInDestructor) {
     RemoveMutationObserver(aObserver);
-    return mObservers.RemoveElement(aObserver);
+    return mObservers.RemoveObserver(aObserver);
   }
 
   return mObservers.Contains(aObserver);
 }
 
 void
 nsDocument::BeginUpdate(nsUpdateType aUpdateType)
 {
--- a/content/base/src/nsDocument.h
+++ b/content/base/src/nsDocument.h
@@ -736,17 +736,17 @@ protected:
   // will allow us to flush out any pending stuff from the sink even if
   // EndLoad() has already happened.
   nsWeakPtr mWeakSink;
 
   nsCOMArray<nsIStyleSheet> mStyleSheets;
   nsCOMArray<nsIStyleSheet> mCatalogSheets;
 
   // Array of observers
-  nsTObserverArray<nsIDocumentObserver*> mObservers;
+  nsTObserverArray<nsIDocumentObserver> mObservers;
 
   // The document's script global object, the object from which the
   // document can get its script context and scope. This is the
   // *inner* window object.
   nsCOMPtr<nsIScriptGlobalObject> mScriptGlobalObject;
 
   // If document is created for example using
   // document.implementation.createDocument(...), mScriptObject points to
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -315,26 +315,26 @@ nsINode::CreateSlots()
   return new (GetAllocator()) nsSlots(mFlagsOrSlots);
 }
 
 void
 nsINode::AddMutationObserver(nsIMutationObserver* aMutationObserver)
 {
   nsSlots* slots = GetSlots();
   if (slots) {
-    slots->mMutationObservers.AppendElementUnlessExists(aMutationObserver);
+    slots->mMutationObservers.AppendObserverUnlessExists(aMutationObserver);
   }
 }
 
 void
 nsINode::RemoveMutationObserver(nsIMutationObserver* aMutationObserver)
 {
   nsSlots* slots = GetExistingSlots();
   if (slots) {
-    slots->mMutationObservers.RemoveElement(aMutationObserver);
+    slots->mMutationObservers.RemoveObserver(aMutationObserver);
   }
 }
 
 PRBool
 nsINode::IsEditableInternal() const
 {
   if (HasFlag(NODE_IS_EDITABLE)) {
     // The node is in an editable contentEditable subtree.
--- a/content/events/src/nsEventListenerManager.cpp
+++ b/content/events/src/nsEventListenerManager.cpp
@@ -364,19 +364,19 @@ nsEventListenerManager::~nsEventListener
     delete gEventIdTable;
     gEventIdTable = nsnull;
   }
 }
 
 nsresult
 nsEventListenerManager::RemoveAllListeners()
 {
-  PRInt32 count = mListeners.Length();
+  PRInt32 count = mListeners.Count();
   for (PRInt32 i = 0; i < count; i++) {
-    delete mListeners.ElementAt(i);
+    delete mListeners.FastObserverAt(i);
   }
   mListeners.Clear();
   return NS_OK;
 }
 
 void
 nsEventListenerManager::Shutdown()
 {
@@ -392,19 +392,19 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(
    NS_INTERFACE_MAP_ENTRY(nsIDOMEventTarget)
    NS_INTERFACE_MAP_ENTRY(nsIDOM3EventTarget)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsEventListenerManager, nsIEventListenerManager)
 NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS(nsEventListenerManager, nsIEventListenerManager)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsEventListenerManager)
-  PRInt32 i, count = tmp->mListeners.Length();
+  PRInt32 i, count = tmp->mListeners.Count();
   for (i = 0; i < count; i++) {
-    cb.NoteXPCOMChild(tmp->mListeners.ElementAt(i)->mListener.get());
+    cb.NoteXPCOMChild(tmp->mListeners.FastObserverAt(i)->mListener.get());
   }  
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsEventListenerManager)
   tmp->Disconnect();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 
@@ -472,19 +472,19 @@ nsEventListenerManager::AddEventListener
       if (ifaceListener) {
         aTypeData = td;
         NS_RELEASE(ifaceListener);
       }
     }
   }
 
   nsListenerStruct* ls = nsnull;
-  PRInt32 count = mListeners.Length();
+  PRInt32 count = mListeners.Count();
   for (PRInt32 i = 0; i < count; i++) {
-    ls = mListeners.ElementAt(i);
+    ls = mListeners.FastObserverAt(i);
     if (ls->mListener == aListener && ls->mFlags == aFlags &&
         ls->mGroupFlags == group &&
         (EVENT_TYPE_EQUALS(ls, aType, aTypeAtom) ||
          EVENT_TYPE_DATA_EQUALS(aTypeData, ls->mTypeData))) {
       return NS_OK;
     }
   }
 
@@ -496,17 +496,17 @@ nsEventListenerManager::AddEventListener
 
   ls->mListener = aListener;
   ls->mEventType = aType;
   ls->mTypeAtom = aTypeAtom;
   ls->mFlags = aFlags;
   ls->mGroupFlags = group;
   ls->mHandlerIsString = PR_FALSE;
   ls->mTypeData = aTypeData;
-  mListeners.AppendElement(ls);
+  mListeners.AppendObserver(ls);
 
   // For mutation listeners, we need to update the global bit on the DOM window.
   // Otherwise we won't actually fire the mutation event.
   if (aType >= NS_MUTATION_START && aType <= NS_MUTATION_END) {
     mMayHaveMutationListeners = PR_TRUE;
     // Go from our target to the nearest enclosing DOM window.
     nsCOMPtr<nsPIDOMWindow> window;
     nsCOMPtr<nsIDocument> document;
@@ -558,26 +558,26 @@ nsEventListenerManager::RemoveEventListe
     if (isSame) {
       group = NS_EVENT_FLAG_SYSTEM_EVENT;
     }
   }
 
   nsListenerStruct* ls = nsnull;
   aFlags &= ~NS_PRIV_EVENT_UNTRUSTED_PERMITTED;
 
-  PRInt32 count = mListeners.Length();
+  PRInt32 count = mListeners.Count();
   for (PRInt32 i = 0; i < count; ++i) {
-    ls = mListeners.ElementAt(i);
+    ls = mListeners.FastObserverAt(i);
     if (ls->mListener == aListener &&
         ls->mGroupFlags == group &&
         ((ls->mFlags & ~NS_PRIV_EVENT_UNTRUSTED_PERMITTED) == aFlags) &&
         (EVENT_TYPE_EQUALS(ls, aType, aUserType) ||
          (!(ls->mEventType) &&
           EVENT_TYPE_DATA_EQUALS(ls->mTypeData, aTypeData)))) {
-      mListeners.RemoveElementAt(i);
+      mListeners.RemoveObserverAt(i);
       delete ls;
       mNoListenerForEvent = NS_EVENT_TYPE_NULL;
       mNoListenerForEventAtom = nsnull;
       break;
     }
   }
 
   return NS_OK;
@@ -640,19 +640,19 @@ nsEventListenerManager::RemoveEventListe
 
 nsListenerStruct*
 nsEventListenerManager::FindJSEventListener(PRUint32 aEventType,
                                             nsIAtom* aTypeAtom)
 {
   // Run through the listeners for this type and see if a script
   // listener is registered
   nsListenerStruct *ls;
-  PRInt32 count = mListeners.Length();
+  PRInt32 count = mListeners.Count();
   for (PRInt32 i = 0; i < count; ++i) {
-    ls = mListeners.ElementAt(i);
+    ls = mListeners.FastObserverAt(i);
     if (EVENT_TYPE_EQUALS(ls, aEventType, aTypeAtom) &&
         ls->mFlags & NS_PRIV_EVENT_FLAG_SCRIPT) {
       return ls;
     }
   }
   return nsnull;
 }
 
@@ -838,17 +838,17 @@ nsEventListenerManager::AddScriptEventLi
 
 nsresult
 nsEventListenerManager::RemoveScriptEventListener(nsIAtom* aName)
 {
   PRUint32 eventType = nsContentUtils::GetEventId(aName);
   nsListenerStruct* ls = FindJSEventListener(eventType, aName);
 
   if (ls) {
-    mListeners.RemoveElement(ls);
+    mListeners.RemoveObserver(ls);
     delete ls;
     mNoListenerForEvent = NS_EVENT_TYPE_NULL;
     mNoListenerForEventAtom = nsnull;
   }
 
   return NS_OK;
 }
 
@@ -1101,17 +1101,17 @@ static const EventDispatchData* sLatestE
 
 nsresult
 nsEventListenerManager::HandleEvent(nsPresContext* aPresContext,
                                     nsEvent* aEvent, nsIDOMEvent** aDOMEvent,
                                     nsISupports* aCurrentTarget,
                                     PRUint32 aFlags,
                                     nsEventStatus* aEventStatus)
 {
-  if (mListeners.IsEmpty() || aEvent->flags & NS_EVENT_FLAG_STOP_DISPATCH) {
+  if (mListeners.Count() == 0 || aEvent->flags & NS_EVENT_FLAG_STOP_DISPATCH) {
     return NS_OK;
   }
 
   // Check if we already know that there is no event listener for the event.
   if (mNoListenerForEvent == aEvent->message &&
       (mNoListenerForEvent != NS_USER_DEFINED_EVENT ||
        mNoListenerForEventAtom == aEvent->userType)) {
     return NS_OK;
@@ -1152,21 +1152,21 @@ nsEventListenerManager::HandleEvent(nsPr
      }
      typeData = nsnull;
      dispData = nsnull;
     }
   }
 
 found:
 
-  nsTObserverArray<nsListenerStruct*>::EndLimitedIterator iter(mListeners);
+  nsTObserverArray<nsListenerStruct>::EndLimitedIterator iter(mListeners);
   nsAutoPopupStatePusher popupStatePusher(nsDOMEvent::GetEventPopupControlState(aEvent));
   PRBool hasListener = PR_FALSE;
-  while (iter.HasMore()) {
-    nsListenerStruct* ls = iter.GetNext();
+  nsListenerStruct* ls;
+  while ((ls = iter.GetNext())) {
     PRBool useTypeInterface =
       EVENT_TYPE_DATA_EQUALS(ls->mTypeData, typeData);
     PRBool useGenericInterface =
       (!useTypeInterface && ListenerCanHandle(ls, aEvent));
     // Don't fire the listener if it's been removed.
     // Check that the phase is same in event and event listener.
     // Handle only trusted events, except when listener permits untrusted events.
     if (useTypeInterface || useGenericInterface) {
@@ -1677,38 +1677,38 @@ nsEventListenerManager::GetCoordinatesFo
   }
 }
 
 NS_IMETHODIMP
 nsEventListenerManager::HasMutationListeners(PRBool* aListener)
 {
   *aListener = PR_FALSE;
   if (mMayHaveMutationListeners) {
-    PRInt32 count = mListeners.Length();
+    PRInt32 count = mListeners.Count();
     for (PRInt32 i = 0; i < count; ++i) {
-      nsListenerStruct* ls = mListeners.ElementAt(i);
+      nsListenerStruct* ls = mListeners.FastObserverAt(i);
       if (ls->mEventType >= NS_MUTATION_START &&
           ls->mEventType <= NS_MUTATION_END) {
         *aListener = PR_TRUE;
         break;
       }
     }
   }
 
   return NS_OK;
 }
 
 PRUint32
 nsEventListenerManager::MutationListenerBits()
 {
   PRUint32 bits = 0;
   if (mMayHaveMutationListeners) {
-    PRInt32 i, count = mListeners.Length();
+    PRInt32 i, count = mListeners.Count();
     for (i = 0; i < count; ++i) {
-      nsListenerStruct* ls = mListeners.ElementAt(i);
+      nsListenerStruct* ls = mListeners.FastObserverAt(i);
       if (ls->mEventType >= NS_MUTATION_START &&
           ls->mEventType <= NS_MUTATION_END) {
         if (ls->mEventType == NS_MUTATION_SUBTREEMODIFIED) {
           return kAllMutationBits;
         }
         bits |= MutationBitForEventType(ls->mEventType);
       }
     }
@@ -1734,33 +1734,33 @@ nsEventListenerManager::HasListenersFor(
        }
      }
      typeData = nsnull;
      dispData = nsnull;
     }
   }
 found:
 
-  PRInt32 i, count = mListeners.Length();
+  PRInt32 i, count = mListeners.Count();
   for (i = 0; i < count; ++i) {
-    nsListenerStruct* ls = mListeners.ElementAt(i);
+    nsListenerStruct* ls = mListeners.FastObserverAt(i);
     if (ls->mTypeAtom == atom ||
         EVENT_TYPE_DATA_EQUALS(ls->mTypeData, typeData)) {
       return PR_TRUE;
     }
   }
   return PR_FALSE;
 }
 
 PRBool
 nsEventListenerManager::HasUnloadListeners()
 {
-  PRInt32 count = mListeners.Length();
+  PRInt32 count = mListeners.Count();
   for (PRInt32 i = 0; i < count; ++i) {
-    nsListenerStruct* ls = mListeners.ElementAt(i);
+    nsListenerStruct* ls = mListeners.FastObserverAt(i);
     if (ls->mEventType == NS_PAGE_UNLOAD ||
         ls->mEventType == NS_BEFORE_PAGE_UNLOAD ||
         (ls->mTypeData && ls->mTypeData->iid &&
          ls->mTypeData->iid->Equals(NS_GET_IID(nsIDOMLoadListener)))) {
       return PR_TRUE;
     }
   }
   return PR_FALSE;
--- a/content/events/src/nsEventListenerManager.h
+++ b/content/events/src/nsEventListenerManager.h
@@ -44,16 +44,17 @@
 #include "nsAutoPtr.h"
 #include "nsIDOMEventTarget.h"
 #include "nsIDOM3EventTarget.h"
 #include "nsHashtable.h"
 #include "nsIScriptContext.h"
 #include "nsCycleCollectionParticipant.h"
 
 class nsIDOMEvent;
+class nsVoidArray;
 class nsIAtom;
 struct EventTypeData;
 
 typedef struct {
   nsRefPtr<nsIDOMEventListener> mListener;
   PRUint32                      mEventType;
   nsCOMPtr<nsIAtom>             mTypeAtom;
   PRUint16                      mFlags;
@@ -183,22 +184,22 @@ protected:
   PRBool PrepareToUseCaretPosition(nsIWidget* aEventWidget,
                                    nsIPresShell* aShell,
                                    nsPoint& aTargetPt);
   void GetCoordinatesFor(nsIDOMElement *aCurrentEl, nsPresContext *aPresContext,
                          nsIPresShell *aPresShell, nsPoint& aTargetPt);
   nsresult GetDOM2EventGroup(nsIDOMEventGroup** aGroup);
   PRBool ListenerCanHandle(nsListenerStruct* aLs, nsEvent* aEvent);
 
-  nsTObserverArray<nsListenerStruct*> mListeners;
-  nsISupports*                        mTarget;  //WEAK
-  PRUint32                            mMayHaveMutationListeners : 1;
+  nsTObserverArray<nsListenerStruct> mListeners;
+  nsISupports*                       mTarget;  //WEAK
+  PRUint32                           mMayHaveMutationListeners : 1;
   // These two member variables are used to cache the information
   // about the last event which was handled but for which event listener manager
   // didn't have event listeners.
-  PRUint32                            mNoListenerForEvent : 31;
-  nsCOMPtr<nsIAtom>                   mNoListenerForEventAtom;
+  PRUint32                           mNoListenerForEvent : 31;
+  nsCOMPtr<nsIAtom>                  mNoListenerForEventAtom;
 
-  static PRUint32                     mInstanceCount;
-  static jsval                        sAddListenerID;
+  static PRUint32                    mInstanceCount;
+  static jsval                       sAddListenerID;
 };
 
 #endif // nsEventListenerManager_h__
--- a/layout/style/nsCSSLoader.cpp
+++ b/layout/style/nsCSSLoader.cpp
@@ -1570,20 +1570,19 @@ CSSLoaderImpl::SheetComplete(SheetLoadDa
     NS_ASSERTION(data && data->mMustNotify, "How did this data get here?");
     if (data->mObserver) {
       LOG(("  Notifying observer 0x%x for data 0x%s.  wasAlternate: %d",
            data->mObserver.get(), data, data->mWasAlternate));
       data->mObserver->StyleSheetLoaded(data->mSheet, data->mWasAlternate,
                                         aStatus);
     }
 
-    nsTObserverArray<nsICSSLoaderObserver*>::ForwardIterator iter(mObservers);
+    nsTObserverArray<nsICSSLoaderObserver>::ForwardIterator iter(mObservers);
     nsCOMPtr<nsICSSLoaderObserver> obs;
-    while (iter.HasMore()) {
-      obs = iter.GetNext();
+    while ((obs = iter.GetNext())) {
       LOG(("  Notifying global observer 0x%x for data 0x%s.  wasAlternate: %d",
            obs.get(), data, data->mWasAlternate));
       obs->StyleSheetLoaded(data->mSheet, data->mWasAlternate, aStatus);
     }
   }
 
   if (mLoadingDatas.Count() == 0 && mPendingDatas.Count() > 0) {
     LOG(("  No more loading sheets; starting alternates"));
@@ -2321,28 +2320,28 @@ CSSLoaderImpl::HasPendingLoads()
     mPostedEvents.Length() != 0 ||
     mDatasToNotifyOn != 0;
 }
 
 NS_IMETHODIMP
 CSSLoaderImpl::AddObserver(nsICSSLoaderObserver* aObserver)
 {
   NS_PRECONDITION(aObserver, "Must have observer");
-  if (mObservers.AppendElementUnlessExists(aObserver)) {
+  if (mObservers.AppendObserverUnlessExists(aObserver)) {
     NS_ADDREF(aObserver);
     return NS_OK;
   }
 
   return NS_ERROR_OUT_OF_MEMORY;
 }
 
 NS_IMETHODIMP_(void)
 CSSLoaderImpl::RemoveObserver(nsICSSLoaderObserver* aObserver)
 {
-  if (mObservers.RemoveElement(aObserver)) {
+  if (mObservers.RemoveObserver(aObserver)) {
     NS_RELEASE(aObserver);
   }
 }
 
 PR_STATIC_CALLBACK(PLDHashOperator)
 CollectLoadDatas(nsURIAndPrincipalHashKey *aKey,
                  SheetLoadData* &aData,
                  void* aClosure)
--- a/layout/style/nsCSSLoader.h
+++ b/layout/style/nsCSSLoader.h
@@ -500,12 +500,12 @@ private:
 
   // Number of datas still waiting to be notified on if we're notifying on a
   // whole bunch at once (e.g. in one of the stop methods).  This is used to
   // make sure that HasPendingLoads() won't return false until we're notifying
   // on the last data we're working with.
   PRUint32 mDatasToNotifyOn;
 
   // Our array of "global" observers
-  nsTObserverArray<nsICSSLoaderObserver*> mObservers;
+  nsTObserverArray<nsICSSLoaderObserver> mObservers;
 };
 
 #endif // nsCSSLoader_h__
--- a/modules/libpr0n/src/imgRequest.cpp
+++ b/modules/libpr0n/src/imgRequest.cpp
@@ -125,25 +125,25 @@ nsresult imgRequest::Init(nsIURI *aURI,
   return NS_OK;
 }
 
 nsresult imgRequest::AddProxy(imgRequestProxy *proxy)
 {
   NS_PRECONDITION(proxy, "null imgRequestProxy passed in");
   LOG_SCOPE_WITH_PARAM(gImgLog, "imgRequest::AddProxy", "proxy", proxy);
 
-  return mObservers.AppendElementUnlessExists(proxy) ?
+  return mObservers.AppendObserverUnlessExists(proxy) ?
     NS_OK : NS_ERROR_OUT_OF_MEMORY;
 }
 
 nsresult imgRequest::RemoveProxy(imgRequestProxy *proxy, nsresult aStatus, PRBool aNotify)
 {
   LOG_SCOPE_WITH_PARAM(gImgLog, "imgRequest::RemoveProxy", "proxy", proxy);
 
-  mObservers.RemoveElement(proxy);
+  mObservers.RemoveObserver(proxy);
 
   /* Check mState below before we potentially call Cancel() below. Since
      Cancel() may result in OnStopRequest being called back before Cancel()
      returns, leaving mState in a different state then the one it was in at
      this point.
    */
 
   if (aNotify) {
@@ -328,20 +328,19 @@ void imgRequest::RemoveFromCache()
   if (mCacheEntry) {
     mCacheEntry->Doom();
     mCacheEntry = nsnull;
   }
 }
 
 PRBool imgRequest::HaveProxyWithObserver(imgRequestProxy* aProxyToIgnore) const
 {
-  nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mObservers);
+  nsTObserverArray<imgRequestProxy>::ForwardIterator iter(mObservers);
   imgRequestProxy* proxy;
-  while (iter.HasMore()) {
-    proxy = iter.GetNext();
+  while ((proxy = iter.GetNext())) {
     if (proxy == aProxyToIgnore) {
       continue;
     }
     
     if (proxy->HasObserver()) {
       return PR_TRUE;
     }
   }
@@ -362,17 +361,17 @@ void imgRequest::AdjustPriority(imgReque
 {
   // only the first proxy is allowed to modify the priority of this image load.
   //
   // XXX(darin): this is probably not the most optimal algorithm as we may want
   // to increase the priority of requests that have a lot of proxies.  the key
   // concern though is that image loads remain lower priority than other pieces
   // of content such as link clicks, CSS, and JS.
   //
-  if (mObservers.SafeElementAt(0, nsnull) != proxy)
+  if (mObservers.SafeObserverAt(0) != proxy)
     return;
 
   nsCOMPtr<nsISupportsPriority> p = do_QueryInterface(mRequest);
   if (p)
     p->AdjustPriority(delta);
 }
 
 /** imgILoad methods **/
@@ -408,36 +407,38 @@ NS_IMETHODIMP imgRequest::GetIsMultiPart
 
 /* [noscript] void frameChanged (in imgIContainer container, in gfxIImageFrame newframe, in nsIntRect dirtyRect); */
 NS_IMETHODIMP imgRequest::FrameChanged(imgIContainer *container,
                                        gfxIImageFrame *newframe,
                                        nsIntRect * dirtyRect)
 {
   LOG_SCOPE(gImgLog, "imgRequest::FrameChanged");
 
-  nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mObservers);
-  while (iter.HasMore()) {
-    iter.GetNext()->FrameChanged(container, newframe, dirtyRect);
+  nsTObserverArray<imgRequestProxy>::ForwardIterator iter(mObservers);
+  imgRequestProxy* proxy;
+  while ((proxy = iter.GetNext())) {
+    proxy->FrameChanged(container, newframe, dirtyRect);
   }
 
   return NS_OK;
 }
 
 /** imgIDecoderObserver methods **/
 
 /* void onStartDecode (in imgIRequest request); */
 NS_IMETHODIMP imgRequest::OnStartDecode(imgIRequest *request)
 {
   LOG_SCOPE(gImgLog, "imgRequest::OnStartDecode");
 
   mState |= onStartDecode;
 
-  nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mObservers);
-  while (iter.HasMore()) {
-    iter.GetNext()->OnStartDecode();
+  nsTObserverArray<imgRequestProxy>::ForwardIterator iter(mObservers);
+  imgRequestProxy* proxy;
+  while ((proxy = iter.GetNext())) {
+    proxy->OnStartDecode();
   }
 
   /* In the case of streaming jpegs, it is possible to get multiple OnStartDecodes which
      indicates the beginning of a new decode.
      The cache entry's size therefore needs to be reset to 0 here.  If we do not do this,
      the code in imgRequest::OnStopFrame will continue to increase the data size cumulatively.
    */
   if (mCacheEntry)
@@ -459,48 +460,51 @@ NS_IMETHODIMP imgRequest::OnStartContain
 
   NS_ASSERTION(image, "imgRequest::OnStartContainer called with a null image!");
   if (!image) return NS_ERROR_UNEXPECTED;
 
   mState |= onStartContainer;
 
   mImageStatus |= imgIRequest::STATUS_SIZE_AVAILABLE;
 
-  nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mObservers);
-  while (iter.HasMore()) {
-    iter.GetNext()->OnStartContainer(image);
+  nsTObserverArray<imgRequestProxy>::ForwardIterator iter(mObservers);
+  imgRequestProxy* proxy;
+  while ((proxy = iter.GetNext())) {
+    proxy->OnStartContainer(image);
   }
 
   return NS_OK;
 }
 
 /* void onStartFrame (in imgIRequest request, in gfxIImageFrame frame); */
 NS_IMETHODIMP imgRequest::OnStartFrame(imgIRequest *request,
                                        gfxIImageFrame *frame)
 {
   LOG_SCOPE(gImgLog, "imgRequest::OnStartFrame");
 
-  nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mObservers);
-  while (iter.HasMore()) {
-    iter.GetNext()->OnStartFrame(frame);
+  nsTObserverArray<imgRequestProxy>::ForwardIterator iter(mObservers);
+  imgRequestProxy* proxy;
+  while ((proxy = iter.GetNext())) {
+    proxy->OnStartFrame(frame);
   }
 
   return NS_OK;
 }
 
 /* [noscript] void onDataAvailable (in imgIRequest request, in gfxIImageFrame frame, [const] in nsIntRect rect); */
 NS_IMETHODIMP imgRequest::OnDataAvailable(imgIRequest *request,
                                           gfxIImageFrame *frame,
                                           const nsIntRect * rect)
 {
   LOG_SCOPE(gImgLog, "imgRequest::OnDataAvailable");
 
-  nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mObservers);
-  while (iter.HasMore()) {
-    iter.GetNext()->OnDataAvailable(frame, rect);
+  nsTObserverArray<imgRequestProxy>::ForwardIterator iter(mObservers);
+  imgRequestProxy* proxy;
+  while ((proxy = iter.GetNext())) {
+    proxy->OnDataAvailable(frame, rect);
   }
 
   return NS_OK;
 }
 
 /* void onStopFrame (in imgIRequest request, in gfxIImageFrame frame); */
 NS_IMETHODIMP imgRequest::OnStopFrame(imgIRequest *request,
                                       gfxIImageFrame *frame)
@@ -517,35 +521,37 @@ NS_IMETHODIMP imgRequest::OnStopFrame(im
     mCacheEntry->GetDataSize(&cacheSize);
 
     PRUint32 imageSize = 0;
     frame->GetImageDataLength(&imageSize);
 
     mCacheEntry->SetDataSize(cacheSize + imageSize);
   }
 
-  nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mObservers);
-  while (iter.HasMore()) {
-    iter.GetNext()->OnStopFrame(frame);
+  nsTObserverArray<imgRequestProxy>::ForwardIterator iter(mObservers);
+  imgRequestProxy* proxy;
+  while ((proxy = iter.GetNext())) {
+    proxy->OnStopFrame(frame);
   }
 
   return NS_OK;
 }
 
 /* void onStopContainer (in imgIRequest request, in imgIContainer image); */
 NS_IMETHODIMP imgRequest::OnStopContainer(imgIRequest *request,
                                           imgIContainer *image)
 {
   LOG_SCOPE(gImgLog, "imgRequest::OnStopContainer");
 
   mState |= onStopContainer;
 
-  nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mObservers);
-  while (iter.HasMore()) {
-    iter.GetNext()->OnStopContainer(image);
+  nsTObserverArray<imgRequestProxy>::ForwardIterator iter(mObservers);
+  imgRequestProxy* proxy;
+  while ((proxy = iter.GetNext())) {
+    proxy->OnStopContainer(image);
   }
 
   return NS_OK;
 }
 
 /* void onStopDecode (in imgIRequest request, in nsresult status, in wstring statusArg); */
 NS_IMETHODIMP imgRequest::OnStopDecode(imgIRequest *aRequest,
                                        nsresult aStatus,
@@ -556,19 +562,20 @@ NS_IMETHODIMP imgRequest::OnStopDecode(i
   NS_ASSERTION(!(mState & onStopDecode), "OnStopDecode called multiple times.");
 
   mState |= onStopDecode;
 
   if (NS_FAILED(aStatus) && !(mImageStatus & imgIRequest::STATUS_LOAD_PARTIAL)) {
     mImageStatus |= imgIRequest::STATUS_ERROR;
   }
 
-  nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mObservers);
-  while (iter.HasMore()) {
-    iter.GetNext()->OnStopDecode(GetResultFromImageStatus(mImageStatus), aStatusArg);
+  nsTObserverArray<imgRequestProxy>::ForwardIterator iter(mObservers);
+  imgRequestProxy* proxy;
+  while ((proxy = iter.GetNext())) {
+    proxy->OnStopDecode(GetResultFromImageStatus(mImageStatus), aStatusArg);
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP imgRequest::OnStopRequest(imgIRequest *aRequest,
                                         PRBool aLastPart)
 {
@@ -595,19 +602,20 @@ NS_IMETHODIMP imgRequest::OnStartRequest
      to onStartRequest. */
   mImageStatus = imgIRequest::STATUS_NONE;
   mState = onStartRequest;
 
   /* set our loading flag to true */
   mLoading = PR_TRUE;
 
   /* notify our kids */
-  nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mObservers);
-  while (iter.HasMore()) {
-    iter.GetNext()->OnStartRequest(aRequest, ctxt);
+  nsTObserverArray<imgRequestProxy>::ForwardIterator iter(mObservers);
+  imgRequestProxy* proxy;
+  while ((proxy = iter.GetNext())) {
+    proxy->OnStartRequest(aRequest, ctxt);
   }
 
   /* Get our principal */
   nsCOMPtr<nsIChannel> chan(do_QueryInterface(aRequest));
   if (chan) {
     nsCOMPtr<nsIScriptSecurityManager> secMan =
       do_GetService("@mozilla.org/scriptsecuritymanager;1");
     if (secMan) {
@@ -726,19 +734,23 @@ NS_IMETHODIMP imgRequest::OnStopRequest(
 
   // if there was an error loading the image, (mState & onStopDecode) won't be true.
   // Send an onStopDecode message
   if (!(mState & onStopDecode)) {
     this->OnStopDecode(nsnull, status, nsnull);
   }
 
   /* notify the kids */
-  nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mObservers);
-  while (iter.HasMore()) {
-    iter.GetNext()->OnStopRequest(aRequest, ctxt, status, mHadLastPart);
+  nsTObserverArray<imgRequestProxy>::ForwardIterator iter(mObservers);
+  imgRequestProxy* proxy;
+  while ((proxy = iter.GetNext())) {
+    /* calling OnStopRequest may result in the death of |proxy| so don't use the
+       pointer after this call.
+     */
+    proxy->OnStopRequest(aRequest, ctxt, status, mHadLastPart);
   }
 
   return NS_OK;
 }
 
 
 
 
--- a/modules/libpr0n/src/imgRequest.h
+++ b/modules/libpr0n/src/imgRequest.h
@@ -153,17 +153,17 @@ public:
 private:
   nsCOMPtr<nsIRequest> mRequest;
   nsCOMPtr<nsIURI> mURI;
   nsCOMPtr<nsIPrincipal> mPrincipal;
   nsCOMPtr<imgIContainer> mImage;
   nsCOMPtr<imgIDecoder> mDecoder;
   nsCOMPtr<nsIProperties> mProperties;
 
-  nsTObserverArray<imgRequestProxy*> mObservers;
+  nsTObserverArray<imgRequestProxy> mObservers;
 
   PRPackedBool mLoading;
   PRPackedBool mProcessing;
   PRPackedBool mHadLastPart;
   PRUint32 mNetworkStatus;
   PRUint32 mImageStatus;
   PRUint32 mState;
   nsCString mContentType;
--- a/xpcom/build/dlldeps.cpp
+++ b/xpcom/build/dlldeps.cpp
@@ -122,18 +122,18 @@ void XXXNeverCalled()
       array1.AppendElement(a);
       array2.InsertElementAt(b, 0);
       array2.InsertElementAt(c, 0);
       array1.AppendElements(array2);
     }
     {
       nsTObserverArray<PRBool> dummyObserverArray;
       PRBool a = PR_FALSE;
-      dummyObserverArray.AppendElement(a);
-      dummyObserverArray.RemoveElement(a);
+      dummyObserverArray.AppendObserver(&a);
+      dummyObserverArray.RemoveObserver(&a);
       dummyObserverArray.Clear();
     }
     nsStringHashSet();
     nsCStringHashSet();
     nsInt32HashSet();
     nsVoidHashSet();
     nsCheapStringSet();
     nsCheapInt32Set();
--- a/xpcom/glue/nsTArray.cpp
+++ b/xpcom/glue/nsTArray.cpp
@@ -31,17 +31,16 @@
  * 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 <stdlib.h>
 #include <string.h>
 #include "nsTArray.h"
 #include "nsXPCOM.h"
 #include "nsDebug.h"
 
 nsTArray_base::Header nsTArray_base::sEmptyHdr = { 0, 0, 0 };
 
 nsTArray_base::nsTArray_base()
@@ -66,52 +65,47 @@ nsTArray_base::EnsureCapacity(size_type 
   if (capacity * elemSize > size_type(-1)/2) {
     NS_ERROR("Attempting to allocate excessively large array");
     return PR_FALSE;
   }
 
   if (mHdr == &sEmptyHdr) {
     // NS_Alloc new data
     Header *header = static_cast<Header*>
-                                (malloc(sizeof(Header) + capacity * elemSize));
+                                (NS_Alloc(sizeof(Header) + capacity * elemSize));
     if (!header)
       return PR_FALSE;
     header->mLength = 0;
     header->mCapacity = capacity;
     header->mIsAutoArray = 0;
     mHdr = header;
     
     return PR_TRUE;
   }
 
   // Use doubling algorithm when forced to increase available capacity.
   NS_ASSERTION(mHdr->mCapacity > 0, "should not have buffer of zero size");
-  if (capacity < 8) {
-    // grow to 8 elements
-    capacity = 8;
-  } else {
-    size_type temp = mHdr->mCapacity;
-    while (temp < capacity)
-      temp <<= 1;
-    capacity = temp;
-  }
+  size_type temp = mHdr->mCapacity;
+  while (temp < capacity)
+    temp <<= 1;
+  capacity = temp;
 
   Header *header;
   if (UsesAutoArrayBuffer()) {
     // NS_Alloc and copy
     header = static_cast<Header*>
-                        (malloc(sizeof(Header) + capacity * elemSize));
+                        (NS_Alloc(sizeof(Header) + capacity * elemSize));
     if (!header)
       return PR_FALSE;
 
     memcpy(header, mHdr, sizeof(Header) + Length() * elemSize);
   } else {
     // NS_Realloc existing data
     size_type size = sizeof(Header) + capacity * elemSize;
-    header = static_cast<Header*>(realloc(mHdr, size));
+    header = static_cast<Header*>(NS_Realloc(mHdr, size));
     if (!header)
       return PR_FALSE;
   }
 
   header->mCapacity = capacity;
   mHdr = header;
 
   return PR_TRUE;
@@ -129,30 +123,30 @@ nsTArray_base::ShrinkCapacity(size_type 
 
   if (IsAutoArray() && GetAutoArrayBuffer()->mCapacity >= length) {
     Header* header = GetAutoArrayBuffer();
 
     // copy data, but don't copy the header to avoid overwritng mCapacity
     header->mLength = length;
     memcpy(header + 1, mHdr + 1, length * elemSize);
 
-    free(mHdr);
+    NS_Free(mHdr);
     mHdr = header;
     return;
   }
 
   if (length == 0) {
     NS_ASSERTION(!IsAutoArray(), "autoarray should have fit 0 elements");
-    free(mHdr);
+    NS_Free(mHdr);
     mHdr = &sEmptyHdr;
     return;
   }
 
   size_type size = sizeof(Header) + length * elemSize;
-  void *ptr = realloc(mHdr, size);
+  void *ptr = NS_Realloc(mHdr, size);
   if (!ptr)
     return;
   mHdr = static_cast<Header*>(ptr);
   mHdr->mCapacity = length;
 }
 
 void
 nsTArray_base::ShiftData(index_type start, size_type oldLen, size_type newLen,
@@ -266,17 +260,17 @@ nsTArray_base::SwapArrayElements(nsTArra
 }
 
 PRBool
 nsTArray_base::EnsureNotUsingAutoArrayBuffer(size_type elemSize)
 {
   if (UsesAutoArrayBuffer()) {
     size_type size = sizeof(Header) + Length() * elemSize;
 
-    Header* header = static_cast<Header*>(malloc(size));
+    Header* header = static_cast<Header*>(NS_Alloc(size));
     if (!header)
       return PR_FALSE;
 
     memcpy(header, mHdr, size);
     header->mCapacity = Length();
     mHdr = header;
   }
   
--- a/xpcom/glue/nsTArray.h
+++ b/xpcom/glue/nsTArray.h
@@ -354,36 +354,16 @@ class nsTArray : public nsTArray_base {
     const elem_type& operator[](index_type i) const {
       return ElementAt(i);
     }
 
     //
     // Search methods
     //
 
-    // This method searches for the first element in this array that is equal
-    // to the given element.
-    // @param item   The item to search for.
-    // @param comp   The Comparator used to determine element equality.
-    // @return       PR_TRUE if the element was found.
-    template<class Item, class Comparator>
-    PRBool Contains(const Item& item, const Comparator& comp) const {
-      return IndexOf(item, 0, comp) != NoIndex;
-    }
-
-    // This method searches for the first element in this array that is equal
-    // to the given element.  This method assumes that 'operator==' is defined
-    // for elem_type.
-    // @param item   The item to search for.
-    // @return       PR_TRUE if the element was found.
-    template<class Item>
-    PRBool Contains(const Item& item) const {
-      return IndexOf(item) != NoIndex;
-    }
-
     // This method searches for the offset of the first element in this
     // array that is equal to the given element.
     // @param item   The item to search for.
     // @param start  The index to start from.
     // @param comp   The Comparator used to determine element equality.
     // @return       The index of the found element or NoIndex if not found.
     template<class Item, class Comparator>
     index_type IndexOf(const Item& item, index_type start,
@@ -750,17 +730,9 @@ class nsAutoTArray : public nsTArray<E> 
                    reinterpret_cast<Header*>(&mAutoBuf),
                    "GetAutoArrayBuffer needs to be fixed");
     }
 
   protected:
     char mAutoBuf[sizeof(Header) + N * sizeof(elem_type)];
 };
 
-// specialization for N = 0. this makes the inheritance model easier for
-// templated users of nsAutoTArray.
-template<class E>
-class nsAutoTArray<E, 0> : public nsTArray<E> {
-  public:
-    nsAutoTArray() {}
-};
-
 #endif  // nsTArray_h__
--- a/xpcom/glue/nsTObserverArray.cpp
+++ b/xpcom/glue/nsTObserverArray.cpp
@@ -15,17 +15,16 @@
  * 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) 2006
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Jonas Sicking <jonas@sicking.cc> (Original Author)
- *   Daniel Witte <dwitte@stanford.edu>
  *
  * 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
@@ -34,31 +33,37 @@
  * 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 "nsTObserverArray.h"
 
 void
-nsTObserverArray_base::AdjustIterators(index_type aModPos,
-                                       diff_type  aAdjustment)
+nsTObserverArray_base::AdjustIterators(PRInt32 aModPos,
+                                       PRInt32 aAdjustment)
 {
   NS_PRECONDITION(aAdjustment == -1 || aAdjustment == 1,
                   "invalid adjustment");
   Iterator_base* iter = mIterators;
   while (iter) {
+    NS_ASSERTION(&(iter->mArray) == this, "wrong array");
+
     if (iter->mPosition > aModPos) {
       iter->mPosition += aAdjustment;
     }
     iter = iter->mNext;
   }
 }
 
 void
-nsTObserverArray_base::ClearIterators()
+nsTObserverArray_base::Clear()
 {
+  mObservers.Clear();
+
   Iterator_base* iter = mIterators;
   while (iter) {
+    NS_ASSERTION(&(iter->mArray) == this, "wrong array");
+
     iter->mPosition = 0;
     iter = iter->mNext;
   }
 }
--- a/xpcom/glue/nsTObserverArray.h
+++ b/xpcom/glue/nsTObserverArray.h
@@ -15,17 +15,16 @@
  * 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) 2006
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Jonas Sicking <jonas@sicking.cc> (Original Author)
- *   Daniel Witte <dwitte@stanford.edu>
  *
  * 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
@@ -34,344 +33,247 @@
  * 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 nsTObserverArray_h___
 #define nsTObserverArray_h___
 
-#include "nsTArray.h"
+#include "nsVoidArray.h"
 
 class NS_COM_GLUE nsTObserverArray_base {
-  protected:
-    typedef PRUint32 index_type;
-    typedef PRUint32 size_type;
-    typedef PRInt32  diff_type;
+  public:
+    class Iterator_base;
+    friend class Iterator_base;
 
     class Iterator_base {
       protected:
         friend class nsTObserverArray_base;
 
-        Iterator_base(index_type aPosition, Iterator_base* aNext)
+        Iterator_base(PRInt32 aPosition, const nsTObserverArray_base& aArray)
           : mPosition(aPosition),
-            mNext(aNext) {
+            mNext(aArray.mIterators),
+            mArray(aArray) {
+          aArray.mIterators = this;
+        }
+
+        ~Iterator_base() {
+          NS_ASSERTION(mArray.mIterators == this,
+                       "Iterators must currently be destroyed in opposite order "
+                       "from the construction order. It is suggested that you "
+                       "simply put them on the stack");
+          mArray.mIterators = mNext;
         }
 
-        // The current position of the iterator. Its exact meaning differs
-        // depending on iterator. See nsTObserverArray<T>::ForwardIterator.
-        index_type mPosition;
+        // These functions exists solely to avoid having to make the
+        // subclasses into friends of nsTObserverArray_base
+        void* GetSafeElementAt(PRInt32 aIndex) {
+          return mArray.mObservers.SafeElementAt(aIndex);
+        }
+        void* FastElementAt(PRInt32 aIndex) {
+          return mArray.mObservers.FastElementAt(aIndex);
+        }
+
+        // The current position of the iterator. It's exact meaning differs
+        // depending on if the array is iterated forwards or backwards. See
+        // nsTObserverArray<T>::ForwardIterator and
+        // nsTObserverArray<T>::ReverseIterator
+        PRInt32 mPosition;
 
         // The next iterator currently iterating the same array
         Iterator_base* mNext;
+
+        // The array we're iterating
+        const nsTObserverArray_base& mArray;
     };
 
+    /**
+     * Removes all observers and collapses all iterators to the beginning of
+     * the array. The result is that forward iterators will see all elements
+     * in the array, and backward iterators will not see any more elements.
+     */
+    void Clear();
+
+  protected:
     nsTObserverArray_base()
       : mIterators(nsnull) {
     }
 
     /**
      * Adjusts iterators after an element has been inserted or removed
      * from the array.
      * @param modPos     Position where elements were added or removed.
      * @param adjustment -1 if an element was removed, 1 if an element was
      *                   added.
      */
-    void AdjustIterators(index_type aModPos, diff_type aAdjustment);
-
-    /**
-     * Clears iterators when the array is destroyed.
-     */
-    void ClearIterators();
+    void AdjustIterators(PRInt32 aModPos, PRInt32 aAdjustment);
 
     mutable Iterator_base* mIterators;
+    nsVoidArray mObservers;
 };
 
 /**
  * An array of observers. Like a normal array, but supports iterators that are
  * stable even if the array is modified during iteration.
- * The template parameter T is the observer type the array will hold;
- * N is the number of built-in storage slots that come with the array.
- * NOTE: You probably want to use nsTObserverArray, unless you specifically
- * want built-in storage. See below.
- * @see nsTObserverArray, nsTArray
+ * The template parameter is the type of observer the array will hold pointers
+ * to.
  */
 
-template<class T, PRUint32 N>
-class nsAutoTObserverArray : protected nsTObserverArray_base {
+template<class T>
+class nsTObserverArray : public nsTObserverArray_base {
   public:
-    typedef T           elem_type;
-    typedef nsTArray<T> array_type;
 
-    nsAutoTObserverArray() {
-    }
-
-    //
-    // Accessor methods
-    //
-
-    // @return The number of elements in the array.
-    size_type Length() const {
-      return mArray.Length();
+    PRUint32 Count() const {
+      return mObservers.Count();
     }
 
-    // @return True if the array is empty or false otherwise.
-    PRBool IsEmpty() const {
-      return mArray.IsEmpty();
-    }
-
-    // This method provides direct access to the i'th element of the array.
-    // The given index must be within the array bounds.
-    // @param i  The index of an element in the array.
-    // @return   A reference to the i'th element of the array.
-    elem_type& ElementAt(index_type i) {
-      return mArray.ElementAt(i);
-    }
+    /**
+     * Adds an observer to the beginning of the array
+     * @param aObserver Observer to add
+     */
+    PRBool PrependObserver(T* aObserver) {
+      NS_PRECONDITION(!Contains(aObserver),
+                      "Don't prepend if the observer is already in the list");
 
-    // Same as above, but readonly.
-    const elem_type& ElementAt(index_type i) const {
-      return mArray.ElementAt(i);
-    }
-
-    // This method provides direct access to the i'th element of the array in
-    // a bounds safe manner. If the requested index is out of bounds the
-    // provided default value is returned.
-    // @param i  The index of an element in the array.
-    // @param def The value to return if the index is out of bounds.
-    elem_type& SafeElementAt(index_type i, elem_type& def) {
-      return mArray.SafeElementAt(i, def);
-    }
-
-    // Same as above, but readonly.
-    const elem_type& SafeElementAt(index_type i, const elem_type& def) const {
-      return mArray.SafeElementAt(i, def);
+      PRBool res = mObservers.InsertElementAt(aObserver, 0);
+      if (res) {
+        AdjustIterators(0, 1);
+      }
+      return res;
     }
 
-    //
-    // Search methods
-    //
-
-    // This method searches, starting from the beginning of the array,
-    // for the first element in this array that is equal to the given element.
-    // 'operator==' must be defined for elem_type.
-    // @param item   The item to search for.
-    // @return       PR_TRUE if the element was found.
-    template<class Item>
-    PRBool Contains(const Item& item) const {
-      return IndexOf(item) != array_type::NoIndex;
-    }
-
-    // This method searches for the offset of the first element in this
-    // array that is equal to the given element.
-    // 'operator==' must be defined for elem_type.
-    // @param item   The item to search for.
-    // @param start  The index to start from.
-    // @return       The index of the found element or NoIndex if not found.
-    template<class Item>
-    index_type IndexOf(const Item& item, index_type start = 0) const {
-      return mArray.IndexOf(item, start);
-    }
-
-    //
-    // Mutation methods
-    //
-
-    // Prepend an element to the array unless it already exists in the array.
-    // 'operator==' must be defined for elem_type.
-    // @param item   The item to prepend.
-    // @return       PR_TRUE if the element was found, or inserted successfully.
-    template<class Item>
-    PRBool PrependElementUnlessExists(const Item& item) {
-      return Contains(item) || mArray.InsertElementAt(0, item) != nsnull;
+    /**
+     * Adds an observer to the end of the array unless it already exists in
+     * the array.
+     * @param aObserver Observer to add
+     * @return True on success, false otherwise
+     */
+    PRBool AppendObserverUnlessExists(T* aObserver) {
+      return Contains(aObserver) || mObservers.AppendElement(aObserver);
     }
 
-    // Append an element to the array.
-    // @param item   The item to append.
-    // @return A pointer to the newly appended element, or null on OOM.
-    template<class Item>
-    elem_type* AppendElement(const Item& item) {
-      return mArray.AppendElement(item);
-    }
-
-    // Same as above, but without copy-constructing. This is useful to avoid
-    // temporaries.
-    elem_type* AppendElement() {
-      return mArray.AppendElement();
+    /**
+     * Adds an observer to the end of the array.
+     * @param aObserver Observer to add
+     * @return True on success, false otherwise
+     */
+    PRBool AppendObserver(T* aObserver) {
+      return mObservers.AppendElement(aObserver);
     }
 
-    // Append an element to the array unless it already exists in the array.
-    // 'operator==' must be defined for elem_type.
-    // @param item   The item to append.
-    // @return       PR_TRUE if the element was found, or inserted successfully.
-    template<class Item>
-    PRBool AppendElementUnlessExists(const Item& item) {
-      return Contains(item) || AppendElement(item) != nsnull;
-    }
+    /**
+     * Removes an observer from the array
+     * @param aObserver Observer to remove
+     * @return True if observer was found and removed, false otherwise
+     */
+    PRBool RemoveObserver(T* aObserver) {
+      PRInt32 index = mObservers.IndexOf(aObserver);
+      if (index < 0) {
+        return PR_FALSE;
+      }
 
-    // Remove an element from the array.
-    // @param index  The index of the item to remove.
-    void RemoveElementAt(index_type index) {
-      NS_ASSERTION(index < mArray.Length(), "invalid index");
-      mArray.RemoveElementAt(index);
+      mObservers.RemoveElementAt(index);
       AdjustIterators(index, -1);
-    }
 
-    // This helper function combines IndexOf with RemoveElementAt to "search
-    // and destroy" the first element that is equal to the given element.
-    // 'operator==' must be defined for elem_type.
-    // @param item  The item to search for.
-    // @return PR_TRUE if the element was found and removed.
-    template<class Item>
-    PRBool RemoveElement(const Item& item) {
-      index_type index = mArray.IndexOf(item, 0);
-      if (index == array_type::NoIndex)
-        return PR_FALSE;
-
-      mArray.RemoveElementAt(index);
-      AdjustIterators(index, -1);
       return PR_TRUE;
     }
 
-    // Removes all observers and collapses all iterators to the beginning of
-    // the array. The result is that forward iterators will see all elements
-    // in the array.
-    void Clear() {
-      mArray.Clear();
-      ClearIterators();
+    /**
+     * Removes an observer from the array
+     * @param aIndex Index of observer to remove
+     */
+    void RemoveObserverAt(PRUint32 aIndex) {
+      if (aIndex < (PRUint32)mObservers.Count()) {
+        mObservers.RemoveElementAt(aIndex);
+        AdjustIterators(aIndex, -1);
+      }
+    }
+
+    PRBool Contains(T* aObserver) const {
+      return mObservers.IndexOf(aObserver) >= 0;
+    }
+
+    PRBool IsEmpty() const {
+      return mObservers.Count() == 0;
     }
 
-    //
-    // Iterators
-    //
+    T* SafeObserverAt(PRInt32 aIndex) const {
+      return static_cast<T*>(mObservers.SafeElementAt(aIndex));
+    }
 
-    // Base class for iterators. Do not use this directly.
-    class Iterator : public Iterator_base {
-      protected:
-        friend class nsAutoTObserverArray;
-        typedef nsAutoTObserverArray<T, N> array_type;
+    T* FastObserverAt(PRInt32 aIndex) const {
+      return static_cast<T*>(mObservers.FastElementAt(aIndex));
+    }
 
-        Iterator(index_type aPosition, const array_type& aArray)
-          : Iterator_base(aPosition, aArray.mIterators),
-            mArray(const_cast<array_type&>(aArray)) {
-          aArray.mIterators = this;
-        }
+    /**
+     * Iterators
+     */
 
-        ~Iterator() {
-          NS_ASSERTION(mArray.mIterators == this,
-                       "Iterators must currently be destroyed in opposite order "
-                       "from the construction order. It is suggested that you "
-                       "simply put them on the stack");
-          mArray.mIterators = mNext;
+    // Iterates the array forward from beginning to end.
+    // mPosition points to the element that will be returned on next call
+    // to GetNext
+    class ForwardIterator : public nsTObserverArray_base::Iterator_base {
+      public:
+        ForwardIterator(const nsTObserverArray<T>& aArray)
+          : Iterator_base(0, aArray) {
+        }
+        ForwardIterator(const nsTObserverArray<T>& aArray, PRInt32 aPos)
+          : Iterator_base(aPos, aArray) {
         }
 
-        // The array we're iterating
-        array_type& mArray;
-    };
-
-    // Iterates the array forward from beginning to end. mPosition points
-    // to the element that will be returned on next call to GetNext.
-    // Elements:
-    // - prepended to the array during iteration *will not* be traversed
-    // - appended during iteration *will* be traversed
-    // - removed during iteration *will not* be traversed.
-    // @see EndLimitedIterator
-    class ForwardIterator : protected Iterator {
-      public:
-        typedef nsAutoTObserverArray<T, N> array_type;
-        typedef Iterator                   base_type;
-
-        ForwardIterator(const array_type& aArray)
-          : Iterator(0, aArray) {
+        PRBool operator <(const ForwardIterator& aOther) {
+          NS_ASSERTION(&mArray == &aOther.mArray,
+                       "not iterating the same array");
+          return mPosition < aOther.mPosition;
         }
 
-        ForwardIterator(const array_type& aArray, index_type aPos)
-          : Iterator(aPos, aArray) {
-        }
-
-        PRBool operator <(const ForwardIterator& aOther) const {
-          NS_ASSERTION(&this->mArray == &aOther.mArray,
-                       "not iterating the same array");
-          return base_type::mPosition < aOther.mPosition;
-        }
-
-        // Returns PR_TRUE if there are more elements to iterate.
-        // This must precede a call to GetNext(). If PR_FALSE is
-        // returned, GetNext() must not be called.
-        PRBool HasMore() const {
-          return base_type::mPosition < base_type::mArray.Length();
-        }
-
-        // Returns the next element and steps one step. This must
-        // be preceded by a call to HasMore().
-        // @return The next observer.
-        elem_type& GetNext() {
-          NS_ASSERTION(HasMore(), "iterating beyond end of array");
-          return base_type::mArray.ElementAt(base_type::mPosition++);
+        /**
+         * Returns the next element and steps one step.
+         * Returns null if there are no more observers. Once null is returned
+         * the iterator becomes invalid and GetNext must not be called any more.
+         * @return The next observer.
+         */
+        T* GetNext() {
+          return static_cast<T*>(GetSafeElementAt(mPosition++));
         }
     };
 
     // EndLimitedIterator works like ForwardIterator, but will not iterate new
-    // observers appended to the array after the iterator was created.
-    class EndLimitedIterator : protected ForwardIterator {
+    // observers added to the array after the iterator was created.
+    class EndLimitedIterator : private ForwardIterator {
       public:
-        typedef nsAutoTObserverArray<T, N> array_type;
-        typedef Iterator                   base_type;
+        typedef typename nsTObserverArray<T>::ForwardIterator base_type;
 
-        EndLimitedIterator(const array_type& aArray)
+        EndLimitedIterator(const nsTObserverArray<T>& aArray)
           : ForwardIterator(aArray),
-            mEnd(aArray, aArray.Length()) {
+            mEnd(aArray, aArray.Count()) {
         }
 
-        // Returns PR_TRUE if there are more elements to iterate.
-        // This must precede a call to GetNext(). If PR_FALSE is
-        // returned, GetNext() must not be called.
-        PRBool HasMore() const {
-          return *this < mEnd;
-        }
-
-        // Returns the next element and steps one step. This must
-        // be preceded by a call to HasMore().
-        // @return The next observer.
-        elem_type& GetNext() {
-          NS_ASSERTION(HasMore(), "iterating beyond end of array");
-          return base_type::mArray.ElementAt(base_type::mPosition++);
+        /**
+         * Returns the next element and steps one step.
+         * Returns null if there are no more observers. Once null is returned
+         * the iterator becomes invalid and GetNext must not be called any more.
+         * @return The next observer.
+         */
+        T* GetNext() {
+          return (*this < mEnd) ?
+                 static_cast<T*>(FastElementAt(base_type::mPosition++)) :
+                 nsnull;
         }
 
       private:
         ForwardIterator mEnd;
     };
-
-  protected:
-    nsAutoTArray<T, N> mArray;
-};
-
-template<class T>
-class nsTObserverArray : public nsAutoTObserverArray<T, 0> {
-  public:
-    typedef nsAutoTObserverArray<T, 0>       base_type;
-    typedef nsTObserverArray_base::size_type size_type;
-
-    //
-    // Initialization methods
-    //
-
-    nsTObserverArray() {}
-
-    // Initialize this array and pre-allocate some number of elements.
-    explicit nsTObserverArray(size_type capacity) {
-      base_type::mArray.SetCapacity(capacity);
-    }
 };
 
 // XXXbz I wish I didn't have to pass in the observer type, but I
 // don't see a way to get it out of array_.
-// Note that this macro only works if the array holds pointers to XPCOM objects.
 #define NS_OBSERVER_ARRAY_NOTIFY_OBSERVERS(array_, obstype_, func_, params_) \
   PR_BEGIN_MACRO                                                             \
-    nsTObserverArray<obstype_ *>::ForwardIterator iter_(array_);             \
+    nsTObserverArray<obstype_>::ForwardIterator iter_(array_);               \
     nsCOMPtr<obstype_> obs_;                                                 \
-    while (iter_.HasMore()) {                                                 \
-      obs_ = iter_.GetNext();                                                \
+    while ((obs_ = iter_.GetNext())) {                                       \
       obs_ -> func_ params_ ;                                                \
     }                                                                        \
   PR_END_MACRO
 
 #endif // nsTObserverArray_h___