Fix for bug 17835. Free JS event listeners when the JS object they're registered on goes away. a:chofmann r:vidur

This commit is contained in:
joki%netscape.com 1999-11-05 23:37:40 +00:00
parent 853c7fc3d9
commit 0aa1e7650e
9 changed files with 111 additions and 67 deletions

View File

@ -983,6 +983,13 @@ nsGenericElement::SetScriptObject(void *aScriptObject)
nsDOMSlots *slots = GetDOMSlots();
slots->mScriptObject = aScriptObject;
if (!aScriptObject) {
if (mListenerManager) {
mListenerManager->RemoveAllListeners(PR_TRUE);
}
}
return NS_OK;
}

View File

@ -132,7 +132,7 @@ public:
* manager.
*/
virtual nsresult RemoveAllListeners() = 0;
virtual nsresult RemoveAllListeners(PRBool aScriptOnly) = 0;
};
extern NS_HTML nsresult NS_NewEventListenerManager(nsIEventListenerManager** aInstancePtrResult);

View File

@ -68,18 +68,18 @@ nsEventListenerManager::nsEventListenerManager()
nsEventListenerManager::~nsEventListenerManager()
{
ReleaseListeners(&mEventListeners);
ReleaseListeners(&mMouseListeners);
ReleaseListeners(&mMouseMotionListeners);
ReleaseListeners(&mKeyListeners);
ReleaseListeners(&mLoadListeners);
ReleaseListeners(&mFocusListeners);
ReleaseListeners(&mFormListeners);
ReleaseListeners(&mDragListeners);
ReleaseListeners(&mPaintListeners);
ReleaseListeners(&mTextListeners);
ReleaseListeners(&mCompositionListeners);
ReleaseListeners(&mMenuListeners);
ReleaseListeners(&mEventListeners, PR_FALSE);
ReleaseListeners(&mMouseListeners, PR_FALSE);
ReleaseListeners(&mMouseMotionListeners, PR_FALSE);
ReleaseListeners(&mKeyListeners, PR_FALSE);
ReleaseListeners(&mLoadListeners, PR_FALSE);
ReleaseListeners(&mFocusListeners, PR_FALSE);
ReleaseListeners(&mFormListeners, PR_FALSE);
ReleaseListeners(&mDragListeners, PR_FALSE);
ReleaseListeners(&mPaintListeners, PR_FALSE);
ReleaseListeners(&mTextListeners, PR_FALSE);
ReleaseListeners(&mCompositionListeners, PR_FALSE);
ReleaseListeners(&mMenuListeners, PR_FALSE);
}
NS_IMPL_ADDREF(nsEventListenerManager)
@ -138,7 +138,7 @@ nsVoidArray** nsEventListenerManager::GetListenersByIID(const nsIID& aIID)
return nsnull;
}
void nsEventListenerManager::ReleaseListeners(nsVoidArray** aListeners)
void nsEventListenerManager::ReleaseListeners(nsVoidArray** aListeners, PRBool aScriptOnly)
{
if (nsnull != *aListeners) {
PRInt32 i, count = (*aListeners)->Count();
@ -146,13 +146,26 @@ void nsEventListenerManager::ReleaseListeners(nsVoidArray** aListeners)
for (i = 0; i < count; i++) {
ls = (nsListenerStruct*)(*aListeners)->ElementAt(i);
if (ls != nsnull) {
NS_IF_RELEASE(ls->mListener);
PR_DELETE(ls);
if (aScriptOnly) {
if (ls->mFlags & NS_PRIV_EVENT_FLAG_SCRIPT) {
NS_RELEASE(ls->mListener);
(*aListeners)->RemoveElement((void*)ls);
PR_DELETE(ls);
}
}
else {
NS_IF_RELEASE(ls->mListener);
PR_DELETE(ls);
}
}
}
delete *aListeners;
//Only delete if we were removing all listeners or if the script
//listener removal brought the count to 0.
if (!aScriptOnly || (*aListeners)->Count() == 0) {
delete *aListeners;
*aListeners = nsnull;
}
}
*aListeners = nsnull;
}
nsresult nsEventListenerManager::GetEventListeners(nsVoidArray **aListeners, const nsIID& aIID)
@ -206,10 +219,13 @@ nsresult nsEventListenerManager::AddEventListener(nsIDOMEventListener *aListener
break;
}
}
NS_RELEASE(regSel);
}
}
}
NS_IF_RELEASE(sel);
if (!found) {
ls = PR_NEW(nsListenerStruct);
if (ls) {
@ -1228,19 +1244,19 @@ nsresult nsEventListenerManager::ReleaseEvent(nsIDOMEventListener *aListener)
return NS_OK;
}
nsresult nsEventListenerManager::RemoveAllListeners()
nsresult nsEventListenerManager::RemoveAllListeners(PRBool aScriptOnly)
{
ReleaseListeners(&mEventListeners);
ReleaseListeners(&mMouseListeners);
ReleaseListeners(&mMouseMotionListeners);
ReleaseListeners(&mKeyListeners);
ReleaseListeners(&mLoadListeners);
ReleaseListeners(&mFocusListeners);
ReleaseListeners(&mFormListeners);
ReleaseListeners(&mDragListeners);
ReleaseListeners(&mPaintListeners);
ReleaseListeners(&mTextListeners);
ReleaseListeners(&mCompositionListeners);
ReleaseListeners(&mEventListeners, aScriptOnly);
ReleaseListeners(&mMouseListeners, aScriptOnly);
ReleaseListeners(&mMouseMotionListeners, aScriptOnly);
ReleaseListeners(&mKeyListeners, aScriptOnly);
ReleaseListeners(&mLoadListeners, aScriptOnly);
ReleaseListeners(&mFocusListeners, aScriptOnly);
ReleaseListeners(&mFormListeners, aScriptOnly);
ReleaseListeners(&mDragListeners, aScriptOnly);
ReleaseListeners(&mPaintListeners, aScriptOnly);
ReleaseListeners(&mTextListeners, aScriptOnly);
ReleaseListeners(&mCompositionListeners, aScriptOnly);
return NS_OK;
}

View File

@ -47,8 +47,6 @@ public:
nsVoidArray** GetListenersByIID(const nsIID& aIID);
void ReleaseListeners(nsVoidArray** aListeners);
/**
* Retrieves events listeners of all types.
* @param
@ -89,13 +87,14 @@ public:
nsEvent* aEvent,
nsIDOMEvent** aDOMEvent);
virtual nsresult RemoveAllListeners();
virtual nsresult RemoveAllListeners(PRBool aScriptOnly);
protected:
nsresult SetJSEventListener(nsIScriptContext *aContext, JSObject *aObject, REFNSIID aIID);
nsresult GetIdentifiersForType(const nsString& aType, nsIID& aIID, PRInt32* aSubType);
nsresult AddEventListener(nsIDOMEventListener *aListener, const nsIID& aIID, PRInt32 aFlags, PRInt32 aSubType);
nsresult RemoveEventListener(nsIDOMEventListener *aListener, const nsIID& aIID, PRInt32 aFlags, PRInt32 aSubType);
void ReleaseListeners(nsVoidArray** aListeners, PRBool aScriptOnly);
nsVoidArray* mEventListeners;
nsVoidArray* mMouseListeners;

View File

@ -294,7 +294,7 @@ GlobalWindowImpl::SetNewDocument(nsIDOMDocument *aDocument)
ClearAllTimeouts();
if (mListenerManager) {
mListenerManager->RemoveAllListeners();
mListenerManager->RemoveAllListeners(PR_FALSE);
}
if ((nsnull != mScriptObject) &&

View File

@ -983,6 +983,13 @@ nsGenericElement::SetScriptObject(void *aScriptObject)
nsDOMSlots *slots = GetDOMSlots();
slots->mScriptObject = aScriptObject;
if (!aScriptObject) {
if (mListenerManager) {
mListenerManager->RemoveAllListeners(PR_TRUE);
}
}
return NS_OK;
}

View File

@ -132,7 +132,7 @@ public:
* manager.
*/
virtual nsresult RemoveAllListeners() = 0;
virtual nsresult RemoveAllListeners(PRBool aScriptOnly) = 0;
};
extern NS_HTML nsresult NS_NewEventListenerManager(nsIEventListenerManager** aInstancePtrResult);

View File

@ -68,18 +68,18 @@ nsEventListenerManager::nsEventListenerManager()
nsEventListenerManager::~nsEventListenerManager()
{
ReleaseListeners(&mEventListeners);
ReleaseListeners(&mMouseListeners);
ReleaseListeners(&mMouseMotionListeners);
ReleaseListeners(&mKeyListeners);
ReleaseListeners(&mLoadListeners);
ReleaseListeners(&mFocusListeners);
ReleaseListeners(&mFormListeners);
ReleaseListeners(&mDragListeners);
ReleaseListeners(&mPaintListeners);
ReleaseListeners(&mTextListeners);
ReleaseListeners(&mCompositionListeners);
ReleaseListeners(&mMenuListeners);
ReleaseListeners(&mEventListeners, PR_FALSE);
ReleaseListeners(&mMouseListeners, PR_FALSE);
ReleaseListeners(&mMouseMotionListeners, PR_FALSE);
ReleaseListeners(&mKeyListeners, PR_FALSE);
ReleaseListeners(&mLoadListeners, PR_FALSE);
ReleaseListeners(&mFocusListeners, PR_FALSE);
ReleaseListeners(&mFormListeners, PR_FALSE);
ReleaseListeners(&mDragListeners, PR_FALSE);
ReleaseListeners(&mPaintListeners, PR_FALSE);
ReleaseListeners(&mTextListeners, PR_FALSE);
ReleaseListeners(&mCompositionListeners, PR_FALSE);
ReleaseListeners(&mMenuListeners, PR_FALSE);
}
NS_IMPL_ADDREF(nsEventListenerManager)
@ -138,7 +138,7 @@ nsVoidArray** nsEventListenerManager::GetListenersByIID(const nsIID& aIID)
return nsnull;
}
void nsEventListenerManager::ReleaseListeners(nsVoidArray** aListeners)
void nsEventListenerManager::ReleaseListeners(nsVoidArray** aListeners, PRBool aScriptOnly)
{
if (nsnull != *aListeners) {
PRInt32 i, count = (*aListeners)->Count();
@ -146,13 +146,26 @@ void nsEventListenerManager::ReleaseListeners(nsVoidArray** aListeners)
for (i = 0; i < count; i++) {
ls = (nsListenerStruct*)(*aListeners)->ElementAt(i);
if (ls != nsnull) {
NS_IF_RELEASE(ls->mListener);
PR_DELETE(ls);
if (aScriptOnly) {
if (ls->mFlags & NS_PRIV_EVENT_FLAG_SCRIPT) {
NS_RELEASE(ls->mListener);
(*aListeners)->RemoveElement((void*)ls);
PR_DELETE(ls);
}
}
else {
NS_IF_RELEASE(ls->mListener);
PR_DELETE(ls);
}
}
}
delete *aListeners;
//Only delete if we were removing all listeners or if the script
//listener removal brought the count to 0.
if (!aScriptOnly || (*aListeners)->Count() == 0) {
delete *aListeners;
*aListeners = nsnull;
}
}
*aListeners = nsnull;
}
nsresult nsEventListenerManager::GetEventListeners(nsVoidArray **aListeners, const nsIID& aIID)
@ -206,10 +219,13 @@ nsresult nsEventListenerManager::AddEventListener(nsIDOMEventListener *aListener
break;
}
}
NS_RELEASE(regSel);
}
}
}
NS_IF_RELEASE(sel);
if (!found) {
ls = PR_NEW(nsListenerStruct);
if (ls) {
@ -1228,19 +1244,19 @@ nsresult nsEventListenerManager::ReleaseEvent(nsIDOMEventListener *aListener)
return NS_OK;
}
nsresult nsEventListenerManager::RemoveAllListeners()
nsresult nsEventListenerManager::RemoveAllListeners(PRBool aScriptOnly)
{
ReleaseListeners(&mEventListeners);
ReleaseListeners(&mMouseListeners);
ReleaseListeners(&mMouseMotionListeners);
ReleaseListeners(&mKeyListeners);
ReleaseListeners(&mLoadListeners);
ReleaseListeners(&mFocusListeners);
ReleaseListeners(&mFormListeners);
ReleaseListeners(&mDragListeners);
ReleaseListeners(&mPaintListeners);
ReleaseListeners(&mTextListeners);
ReleaseListeners(&mCompositionListeners);
ReleaseListeners(&mEventListeners, aScriptOnly);
ReleaseListeners(&mMouseListeners, aScriptOnly);
ReleaseListeners(&mMouseMotionListeners, aScriptOnly);
ReleaseListeners(&mKeyListeners, aScriptOnly);
ReleaseListeners(&mLoadListeners, aScriptOnly);
ReleaseListeners(&mFocusListeners, aScriptOnly);
ReleaseListeners(&mFormListeners, aScriptOnly);
ReleaseListeners(&mDragListeners, aScriptOnly);
ReleaseListeners(&mPaintListeners, aScriptOnly);
ReleaseListeners(&mTextListeners, aScriptOnly);
ReleaseListeners(&mCompositionListeners, aScriptOnly);
return NS_OK;
}

View File

@ -47,8 +47,6 @@ public:
nsVoidArray** GetListenersByIID(const nsIID& aIID);
void ReleaseListeners(nsVoidArray** aListeners);
/**
* Retrieves events listeners of all types.
* @param
@ -89,13 +87,14 @@ public:
nsEvent* aEvent,
nsIDOMEvent** aDOMEvent);
virtual nsresult RemoveAllListeners();
virtual nsresult RemoveAllListeners(PRBool aScriptOnly);
protected:
nsresult SetJSEventListener(nsIScriptContext *aContext, JSObject *aObject, REFNSIID aIID);
nsresult GetIdentifiersForType(const nsString& aType, nsIID& aIID, PRInt32* aSubType);
nsresult AddEventListener(nsIDOMEventListener *aListener, const nsIID& aIID, PRInt32 aFlags, PRInt32 aSubType);
nsresult RemoveEventListener(nsIDOMEventListener *aListener, const nsIID& aIID, PRInt32 aFlags, PRInt32 aSubType);
void ReleaseListeners(nsVoidArray** aListeners, PRBool aScriptOnly);
nsVoidArray* mEventListeners;
nsVoidArray* mMouseListeners;