| Index: Source/core/xml/XMLHttpRequest.cpp
|
| diff --git a/Source/core/xml/XMLHttpRequest.cpp b/Source/core/xml/XMLHttpRequest.cpp
|
| index ee407bcf459a6183fcf587a29e27176344d0836e..961278ebe0183e6070ffd6d277f8345f239c7e98 100644
|
| --- a/Source/core/xml/XMLHttpRequest.cpp
|
| +++ b/Source/core/xml/XMLHttpRequest.cpp
|
| @@ -178,7 +178,6 @@ XMLHttpRequest::XMLHttpRequest(ExecutionContext* context, PassRefPtr<SecurityOri
|
| , m_exceptionCode(0)
|
| , m_progressEventThrottle(this)
|
| , m_responseTypeCode(ResponseTypeDefault)
|
| - , m_dropProtectionRunner(this, &XMLHttpRequest::dropProtection)
|
| , m_securityOrigin(securityOrigin)
|
| {
|
| initializeXMLHttpRequestStaticData();
|
| @@ -849,12 +848,6 @@ void XMLHttpRequest::createRequest(ExceptionState& exceptionState)
|
| // FIXME: Maybe create() can return null for other reasons too?
|
| ASSERT(!m_loader);
|
| m_loader = ThreadableLoader::create(executionContext(), this, request, options);
|
| - if (m_loader) {
|
| - // Neither this object nor the JavaScript wrapper should be deleted while
|
| - // a request is in progress because we need to keep the listeners alive,
|
| - // and they are referenced by the JavaScript wrapper.
|
| - setPendingActivity(this);
|
| - }
|
| } else {
|
| ThreadableLoader::loadResourceSynchronously(executionContext(), request, *this, options);
|
| }
|
| @@ -869,15 +862,19 @@ void XMLHttpRequest::abort()
|
| {
|
| WTF_LOG(Network, "XMLHttpRequest %p abort()", this);
|
|
|
| - // internalAbort() calls dropProtection(), which may release the last reference.
|
| - RefPtr<XMLHttpRequest> protect(this);
|
| -
|
| bool sendFlag = m_loader;
|
|
|
| // Response is cleared next, save needed progress event data.
|
| long long expectedLength = m_response.expectedContentLength();
|
| long long receivedLength = m_receivedLength;
|
|
|
| + // internalAbort() clears m_loader. hasPendingActivity() returns false when
|
| + // m_loader is 0. So, if window.onload is dispatched (see comments in
|
| + // internalAbort()), it's possible that the wrapper gets GC-ed during
|
| + // execution of the event. So, we need to keep this object alive to
|
| + // continue the rest of this method.
|
| + RefPtr<XMLHttpRequest> protect(this);
|
| +
|
| if (!internalAbort())
|
| return;
|
|
|
| @@ -900,7 +897,7 @@ void XMLHttpRequest::clearVariablesForLoading()
|
| m_responseEncoding = String();
|
| }
|
|
|
| -bool XMLHttpRequest::internalAbort(DropProtection async)
|
| +bool XMLHttpRequest::internalAbort()
|
| {
|
| m_error = true;
|
|
|
| @@ -917,32 +914,23 @@ bool XMLHttpRequest::internalAbort(DropProtection async)
|
| // 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.
|
| + // is left to be non 0, internalAbort() for the inner open() repeats the
|
| + // the same work. To avoid that, clears m_loader before calling cancel().
|
| RefPtr<ThreadableLoader> loader = m_loader.release();
|
| loader->cancel();
|
|
|
| - // Save to a local variable since we're going to drop protection.
|
| - bool newLoadStarted = m_loader;
|
| + // 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.
|
| + if (m_loader)
|
| + return false;
|
|
|
| // If abort() called internalAbort() and a nested open() ended up
|
| // clearing the error flag, but didn't send(), make sure the error
|
| // flag is still set.
|
| - if (!newLoadStarted)
|
| - m_error = true;
|
| -
|
| - if (async == DropProtectionAsync)
|
| - dropProtectionSoon();
|
| - else
|
| - dropProtection();
|
| + m_error = true;
|
|
|
| - return !newLoadStarted;
|
| + return true;
|
| }
|
|
|
| void XMLHttpRequest::clearResponse()
|
| @@ -1061,16 +1049,6 @@ void XMLHttpRequest::handleRequestError(ExceptionCode exceptionCode, const Atomi
|
| dispatchEventAndLoadEnd(type, receivedLength, expectedLength);
|
| }
|
|
|
| -void XMLHttpRequest::dropProtectionSoon()
|
| -{
|
| - m_dropProtectionRunner.runAsync();
|
| -}
|
| -
|
| -void XMLHttpRequest::dropProtection()
|
| -{
|
| - unsetPendingActivity(this);
|
| -}
|
| -
|
| void XMLHttpRequest::overrideMimeType(const AtomicString& override)
|
| {
|
| m_mimeTypeOverride = override;
|
| @@ -1263,13 +1241,13 @@ void XMLHttpRequest::didFinishLoading(unsigned long identifier, double)
|
|
|
| InspectorInstrumentation::didFinishXHRLoading(executionContext(), this, this, identifier, m_responseText, m_method, m_url, m_lastSendURL, m_lastSendLineNumber);
|
|
|
| - // Prevent dropProtection releasing the last reference, and retain |this| until the end of this method.
|
| + // hasPendingActivity() returns false when m_loader is 0. So, it's possible
|
| + // that the wrapper gets GC-ed during execution of the event. So, we need
|
| + // to keep this object alive to continue the rest of this method.
|
| RefPtr<XMLHttpRequest> protect(this);
|
|
|
| - if (m_loader) {
|
| + if (m_loader)
|
| m_loader = 0;
|
| - dropProtection();
|
| - }
|
|
|
| changeState(DONE);
|
| }
|
| @@ -1382,9 +1360,6 @@ void XMLHttpRequest::handleDidTimeout()
|
| {
|
| WTF_LOG(Network, "XMLHttpRequest %p handleDidTimeout()", this);
|
|
|
| - // internalAbort() calls dropProtection(), which may release the last reference.
|
| - RefPtr<XMLHttpRequest> protect(this);
|
| -
|
| // Response is cleared next, save needed progress event data.
|
| long long expectedLength = m_response.expectedContentLength();
|
| long long receivedLength = m_receivedLength;
|
| @@ -1408,7 +1383,12 @@ void XMLHttpRequest::resume()
|
|
|
| void XMLHttpRequest::stop()
|
| {
|
| - internalAbort(DropProtectionAsync);
|
| + internalAbort();
|
| +}
|
| +
|
| +bool XMLHttpRequest::hasPendingActivity() const
|
| +{
|
| + return m_loader;
|
| }
|
|
|
| void XMLHttpRequest::contextDestroyed()
|
|
|