Index: Source/core/xml/XMLHttpRequest.cpp |
=================================================================== |
--- Source/core/xml/XMLHttpRequest.cpp (revision 159103) |
+++ Source/core/xml/XMLHttpRequest.cpp (working copy) |
@@ -450,7 +450,9 @@ |
void XMLHttpRequest::open(const String& method, const KURL& url, bool async, ExceptionState& es) |
{ |
- internalAbort(); |
+ if (!internalAbort()) |
+ return; |
+ |
State previousState = m_state; |
m_state = UNSENT; |
m_error = false; |
@@ -783,7 +785,8 @@ |
bool sendFlag = m_loader; |
- internalAbort(); |
+ if (!internalAbort()) |
+ return; |
clearResponseBuffers(); |
@@ -806,7 +809,7 @@ |
} |
} |
-void XMLHttpRequest::internalAbort() |
+bool XMLHttpRequest::internalAbort() |
{ |
bool hadLoader = m_loader; |
@@ -816,8 +819,19 @@ |
m_receivedLength = 0; |
if (hadLoader) { |
- m_loader->cancel(); |
- m_loader = 0; |
+ // Cancelling the ThreadableLoader m_loader may result in calling |
+ // window.onload synchronously. If such an onload handler contains |
+ // open() call on the same XMLHttpRequest object, reentry happens. If |
+ // m_loader is left to be non 0, internalAbort() call for the inner |
+ // open() makes an extra dropProtection() call (when we're back to the |
+ // outer open(), we'll call dropProtection()). To avoid that, clears |
+ // m_loader before calling cancel. |
+ // |
+ // If, window.onload contains open() and send(), m_loader will be set to |
+ // non 0 value. So, we cannot continue the outer open(). In such case, |
+ // just abort the outer open() by returning false. |
+ RefPtr<ThreadableLoader> loader = m_loader.release(); |
+ loader->cancel(); |
} |
m_decoder = 0; |
@@ -826,6 +840,8 @@ |
if (hadLoader) |
dropProtectionSoon(); |
+ |
+ return !m_loader; |
} |
void XMLHttpRequest::clearResponse() |
@@ -1186,7 +1202,8 @@ |
{ |
// internalAbort() calls dropProtection(), which may release the last reference. |
RefPtr<XMLHttpRequest> protect(this); |
- internalAbort(); |
+ if (!internalAbort()) |
+ return; |
clearResponse(); |
clearRequest(); |