зеркало из https://github.com/mozilla/pjs.git
Fix leak regression from bug 368773 (Add a bunch of DOM objects to cycle collection). r/sr=bz.
This commit is contained in:
Родитель
1d27f5bb84
Коммит
8763e8133a
|
@ -53,7 +53,7 @@
|
|||
#include "nsIDOMWindowInternal.h"
|
||||
#include "nsIFocusController.h"
|
||||
|
||||
#include "nsSupportsArray.h"
|
||||
#include "nsCOMArray.h"
|
||||
|
||||
#include "nsCommandManager.h"
|
||||
|
||||
|
@ -70,30 +70,27 @@ nsCommandManager::~nsCommandManager()
|
|||
}
|
||||
|
||||
|
||||
PR_STATIC_CALLBACK(PRBool)
|
||||
TraverseCommandObservers(nsHashKey *aKey, void *aData, void* aClosure)
|
||||
PR_STATIC_CALLBACK(PLDHashOperator)
|
||||
TraverseCommandObservers(const char* aKey, nsCOMArray<nsIObserver>* aObservers,
|
||||
void* aClosure)
|
||||
{
|
||||
nsISupportsArray *observers = NS_STATIC_CAST(nsISupportsArray*, aData);
|
||||
nsCycleCollectionTraversalCallback *cb =
|
||||
NS_STATIC_CAST(nsCycleCollectionTraversalCallback*, aClosure);
|
||||
|
||||
PRUint32 i, numItems;
|
||||
nsresult rv = observers->Count(&numItems);
|
||||
NS_ENSURE_SUCCESS(rv, kHashEnumerateStop);
|
||||
|
||||
PRInt32 i, numItems = aObservers->Count();
|
||||
for (i = 0; i < numItems; ++i) {
|
||||
cb->NoteXPCOMChild(observers->ElementAt(i));
|
||||
cb->NoteXPCOMChild(aObservers->ObjectAt(i));
|
||||
}
|
||||
|
||||
return kHashEnumerateNext;
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(nsCommandManager)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsCommandManager)
|
||||
tmp->mCommandObserversTable.Reset();
|
||||
tmp->mObserversTable.Clear();
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsCommandManager)
|
||||
tmp->mCommandObserversTable.Enumerate(TraverseCommandObservers, &cb);
|
||||
tmp->mObserversTable.EnumerateRead(TraverseCommandObservers, &cb);
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsCommandManager, nsICommandManager)
|
||||
|
@ -126,31 +123,22 @@ nsCommandManager::Init(nsIDOMWindow *aWindow)
|
|||
NS_IMETHODIMP
|
||||
nsCommandManager::CommandStatusChanged(const char * aCommandName)
|
||||
{
|
||||
nsCStringKey hashKey(aCommandName);
|
||||
nsCOMArray<nsIObserver>* commandObservers;
|
||||
mObserversTable.Get(aCommandName, &commandObservers);
|
||||
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
nsCOMPtr<nsISupports> commandSupports = getter_AddRefs(mCommandObserversTable.Get(&hashKey));
|
||||
nsCOMPtr<nsISupportsArray> commandObservers = do_QueryInterface(commandSupports);
|
||||
if (commandObservers)
|
||||
{
|
||||
PRUint32 numItems;
|
||||
rv = commandObservers->Count(&numItems);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
for (PRUint32 i = 0; i < numItems; i ++)
|
||||
{
|
||||
nsCOMPtr<nsISupports> itemSupports;
|
||||
rv = commandObservers->GetElementAt(i, getter_AddRefs(itemSupports));
|
||||
if (NS_FAILED(rv)) break;
|
||||
nsCOMPtr<nsIObserver> itemObserver = do_QueryInterface(itemSupports);
|
||||
if (itemObserver)
|
||||
{
|
||||
// should we get the command state to pass here? This might be expensive.
|
||||
itemObserver->Observe((nsICommandManager *)this, aCommandName,NS_LITERAL_STRING("command_status_changed").get());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (commandObservers)
|
||||
{
|
||||
// XXX Should we worry about observers removing themselves from Observe()?
|
||||
PRInt32 i, numItems = commandObservers->Count();
|
||||
for (i = 0; i < numItems; ++i)
|
||||
{
|
||||
nsCOMPtr<nsIObserver> observer = commandObservers->ObjectAt(i);
|
||||
// should we get the command state to pass here? This might be expensive.
|
||||
observer->Observe(NS_ISUPPORTS_CAST(nsICommandManager*, this),
|
||||
aCommandName,
|
||||
NS_LITERAL_STRING("command_status_changed").get());
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -163,32 +151,27 @@ nsCommandManager::CommandStatusChanged(const char * aCommandName)
|
|||
NS_IMETHODIMP
|
||||
nsCommandManager::AddCommandObserver(nsIObserver *aCommandObserver, const char *aCommandToObserve)
|
||||
{
|
||||
NS_ENSURE_ARG(aCommandObserver);
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
NS_ENSURE_ARG(aCommandObserver);
|
||||
|
||||
// XXX todo: handle special cases of aCommandToObserve being null, or empty
|
||||
|
||||
// for each command in the table, we make a list of observers for that command
|
||||
nsCStringKey hashKey(aCommandToObserve);
|
||||
|
||||
nsCOMPtr<nsISupports> commandSupports = getter_AddRefs(mCommandObserversTable.Get(&hashKey));
|
||||
nsCOMPtr<nsISupportsArray> commandObservers = do_QueryInterface(commandSupports);
|
||||
if (!commandObservers)
|
||||
{
|
||||
rv = NS_NewISupportsArray(getter_AddRefs(commandObservers));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
commandSupports = do_QueryInterface(commandObservers);
|
||||
rv = mCommandObserversTable.Put(&hashKey, commandSupports);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
// need to check that this command observer hasn't already been registered
|
||||
nsCOMPtr<nsISupports> observerAsSupports = do_QueryInterface(aCommandObserver);
|
||||
PRInt32 existingIndex = commandObservers->IndexOf(observerAsSupports);
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
// XXX todo: handle special cases of aCommandToObserve being null, or empty
|
||||
|
||||
// for each command in the table, we make a list of observers for that command
|
||||
nsCOMArray<nsIObserver>* commandObservers;
|
||||
if (!mObserversTable.Get(aCommandToObserve, &commandObservers))
|
||||
{
|
||||
nsAutoPtr<nsCOMArray<nsIObserver> > array(new nsCOMArray<nsIObserver>);
|
||||
if (!array || !mObserversTable.Put(aCommandToObserve, array))
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
commandObservers = array.forget();
|
||||
}
|
||||
|
||||
// need to check that this command observer hasn't already been registered
|
||||
PRInt32 existingIndex = commandObservers->IndexOf(aCommandObserver);
|
||||
if (existingIndex == -1)
|
||||
rv = commandObservers->AppendElement(observerAsSupports);
|
||||
rv = commandObservers->AppendObject(aCommandObserver);
|
||||
else
|
||||
NS_WARNING("Registering command observer twice on the same command");
|
||||
|
||||
|
@ -199,19 +182,16 @@ nsCommandManager::AddCommandObserver(nsIObserver *aCommandObserver, const char *
|
|||
NS_IMETHODIMP
|
||||
nsCommandManager::RemoveCommandObserver(nsIObserver *aCommandObserver, const char *aCommandObserved)
|
||||
{
|
||||
NS_ENSURE_ARG(aCommandObserver);
|
||||
NS_ENSURE_ARG(aCommandObserver);
|
||||
|
||||
// XXX todo: handle special cases of aCommandToObserve being null, or empty
|
||||
nsCStringKey hashKey(aCommandObserved);
|
||||
// XXX todo: handle special cases of aCommandToObserve being null, or empty
|
||||
|
||||
nsCOMPtr<nsISupports> commandSupports = getter_AddRefs(mCommandObserversTable.Get(&hashKey));
|
||||
nsCOMPtr<nsISupportsArray> commandObservers = do_QueryInterface(commandSupports);
|
||||
if (!commandObservers)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
nsCOMPtr<nsISupports> observerAsSupports = do_QueryInterface(aCommandObserver);
|
||||
nsresult removed = commandObservers->RemoveElement(observerAsSupports);
|
||||
return (removed) ? NS_OK : NS_ERROR_FAILURE;
|
||||
nsCOMArray<nsIObserver>* commandObservers;
|
||||
if (!mObserversTable.Get(aCommandObserved, &commandObservers))
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
return commandObservers->RemoveObject(aCommandObserver) ? NS_OK :
|
||||
NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
/* boolean isCommandSupported(in string aCommandName,
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
|
||||
|
||||
#include "nsString.h"
|
||||
#include "nsHashtable.h"
|
||||
#include "nsClassHashtable.h"
|
||||
#include "nsWeakReference.h"
|
||||
|
||||
#include "nsICommandManager.h"
|
||||
|
@ -49,7 +49,7 @@
|
|||
#include "nsCycleCollectionParticipant.h"
|
||||
|
||||
class nsIController;
|
||||
|
||||
template<class E> class nsCOMArray;
|
||||
|
||||
|
||||
class nsCommandManager : public nsICommandManager,
|
||||
|
@ -84,7 +84,7 @@ protected:
|
|||
|
||||
protected:
|
||||
|
||||
nsSupportsHashtable mCommandObserversTable; // hash table of nsIObservers, keyed by command name
|
||||
nsClassHashtable<nsCharPtrHashKey, nsCOMArray<nsIObserver> > mObserversTable;
|
||||
|
||||
nsIDOMWindow* mWindow; // weak ptr. The window should always outlive us
|
||||
};
|
||||
|
|
Загрузка…
Ссылка в новой задаче