From 2ecabbedcdbeaec074fc85fee6770913314c64a4 Mon Sep 17 00:00:00 2001 From: "bzbarsky%mit.edu" Date: Thu, 30 Sep 2004 22:47:50 +0000 Subject: [PATCH] Make it possible to re-call an XMLHttpRequest object from its onreadystate handler by clearing listeners before calling onreadystate, not after. Bug 258768, r=doron, sr=jst git-svn-id: svn://10.0.0.236/trunk@163048 18797224-902f-48f8-a5cc-f745e15eee43 --- .../xmlextras/base/src/nsXMLHttpRequest.cpp | 39 +++++++++++++------ .../xmlextras/base/src/nsXMLHttpRequest.h | 11 ++++-- 2 files changed, 35 insertions(+), 15 deletions(-) diff --git a/mozilla/extensions/xmlextras/base/src/nsXMLHttpRequest.cpp b/mozilla/extensions/xmlextras/base/src/nsXMLHttpRequest.cpp index c759f84106d..ef1df6acd40 100644 --- a/mozilla/extensions/xmlextras/base/src/nsXMLHttpRequest.cpp +++ b/mozilla/extensions/xmlextras/base/src/nsXMLHttpRequest.cpp @@ -652,9 +652,7 @@ nsXMLHttpRequest::Abort() mDocument = nsnull; mState |= XML_HTTP_REQUEST_ABORTED; - ChangeState(XML_HTTP_REQUEST_COMPLETED); - - ClearEventListeners(); + ChangeState(XML_HTTP_REQUEST_COMPLETED, PR_TRUE, PR_TRUE); ChangeState(XML_HTTP_REQUEST_UNINITIALIZED, PR_FALSE); // IE seems to do it @@ -1348,16 +1346,19 @@ nsXMLHttpRequest::RequestCompleted() } } - ChangeState(XML_HTTP_REQUEST_COMPLETED); + // Grab hold of the event listener lists we will need + nsCOMPtr onLoadListener = mOnLoadListener; + nsCOMPtr loadEventListeners = mLoadEventListeners; - NotifyEventListeners(mOnLoadListener, mLoadEventListeners, domevent); + // Clear listeners here unless we're multipart + ChangeState(XML_HTTP_REQUEST_COMPLETED, PR_TRUE, + !(mState & XML_HTTP_REQUEST_MULTIPART)); + + NotifyEventListeners(onLoadListener, loadEventListeners, domevent); if (mState & XML_HTTP_REQUEST_MULTIPART) { // We're a multipart request, so we're not done. Reset to opened. ChangeState(XML_HTTP_REQUEST_OPENED); - } else { - // We're done. Clear event listeners. - ClearEventListeners(); } return rv; @@ -1710,14 +1711,19 @@ nsXMLHttpRequest::Error(nsIDOMEvent* aEvent) mState &= ~XML_HTTP_REQUEST_SYNCLOOPING; - NotifyEventListeners(mOnErrorListener, mErrorEventListeners, event); + nsCOMPtr onErrorListener = mOnErrorListener; + nsCOMPtr errorEventListeners = mErrorEventListeners; + ClearEventListeners(); + + NotifyEventListeners(onErrorListener, errorEventListeners, event); return NS_OK; } nsresult -nsXMLHttpRequest::ChangeState(PRUint32 aState, PRBool aBroadcast) +nsXMLHttpRequest::ChangeState(PRUint32 aState, PRBool aBroadcast, + PRBool aClearEventListeners) { // If we are setting one of the mutually exclusing states, // unset those state bits first. @@ -1726,10 +1732,19 @@ nsXMLHttpRequest::ChangeState(PRUint32 aState, PRBool aBroadcast) } mState |= aState; nsresult rv = NS_OK; + + // Take ref to the one listener we need + nsCOMPtr onReadyStateChangeListener = + mOnReadystatechangeListener; + + if (aClearEventListeners) { + ClearEventListeners(); + } + if ((mState & XML_HTTP_REQUEST_ASYNC) && (aState & XML_HTTP_REQUEST_LOADSTATES) && // Broadcast load states only aBroadcast && - mOnReadystatechangeListener) { + onReadyStateChangeListener) { nsCOMPtr stack; JSContext *cx = nsnull; @@ -1745,7 +1760,7 @@ nsXMLHttpRequest::ChangeState(PRUint32 aState, PRBool aBroadcast) } } - rv = mOnReadystatechangeListener->HandleEvent(); + rv = onReadyStateChangeListener->HandleEvent(); if (cx) { stack->Pop(&cx); diff --git a/mozilla/extensions/xmlextras/base/src/nsXMLHttpRequest.h b/mozilla/extensions/xmlextras/base/src/nsXMLHttpRequest.h index c3d328a619b..45a005aec04 100644 --- a/mozilla/extensions/xmlextras/base/src/nsXMLHttpRequest.h +++ b/mozilla/extensions/xmlextras/base/src/nsXMLHttpRequest.h @@ -124,9 +124,14 @@ protected: PRUint32 toOffset, PRUint32 count, PRUint32 *writeCount); - // Change the state of the object with this. The broadcast member determines - // if the onreadystatechange listener should be called. - nsresult ChangeState(PRUint32 aState, PRBool aBroadcast = PR_TRUE); + // Change the state of the object with this. The broadcast argument + // determines if the onreadystatechange listener should be called. + // If aClearEventListeners is true, ChangeState will take refs to + // any event listeners it needs and call ClearEventListeners before + // making any HandleEvent() calls that could change the listener + // values. + nsresult ChangeState(PRUint32 aState, PRBool aBroadcast = PR_TRUE, + PRBool aClearEventListeners = PR_FALSE); nsresult RequestCompleted(); nsresult GetLoadGroup(nsILoadGroup **aLoadGroup); nsIURI *GetBaseURI();