mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-10 11:55:49 +00:00
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:
parent
853c7fc3d9
commit
0aa1e7650e
@ -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;
|
||||
}
|
||||
|
||||
|
@ -132,7 +132,7 @@ public:
|
||||
* manager.
|
||||
*/
|
||||
|
||||
virtual nsresult RemoveAllListeners() = 0;
|
||||
virtual nsresult RemoveAllListeners(PRBool aScriptOnly) = 0;
|
||||
};
|
||||
|
||||
extern NS_HTML nsresult NS_NewEventListenerManager(nsIEventListenerManager** aInstancePtrResult);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -294,7 +294,7 @@ GlobalWindowImpl::SetNewDocument(nsIDOMDocument *aDocument)
|
||||
ClearAllTimeouts();
|
||||
|
||||
if (mListenerManager) {
|
||||
mListenerManager->RemoveAllListeners();
|
||||
mListenerManager->RemoveAllListeners(PR_FALSE);
|
||||
}
|
||||
|
||||
if ((nsnull != mScriptObject) &&
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -132,7 +132,7 @@ public:
|
||||
* manager.
|
||||
*/
|
||||
|
||||
virtual nsresult RemoveAllListeners() = 0;
|
||||
virtual nsresult RemoveAllListeners(PRBool aScriptOnly) = 0;
|
||||
};
|
||||
|
||||
extern NS_HTML nsresult NS_NewEventListenerManager(nsIEventListenerManager** aInstancePtrResult);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user