Index: Source/core/xml/XMLHttpRequest.cpp |
diff --git a/Source/core/xml/XMLHttpRequest.cpp b/Source/core/xml/XMLHttpRequest.cpp |
index 14aca485a6b095e3806c9dd30f08ff5cea6e7cbf..7315dd9326803e09632506d68e222b40475c8194 100644 |
--- a/Source/core/xml/XMLHttpRequest.cpp |
+++ b/Source/core/xml/XMLHttpRequest.cpp |
@@ -144,6 +144,7 @@ PassRefPtrWillBeRawPtr<XMLHttpRequest> XMLHttpRequest::create(ExecutionContext* |
XMLHttpRequest::XMLHttpRequest(ExecutionContext* context, PassRefPtr<SecurityOrigin> securityOrigin) |
: ActiveDOMObject(context) |
, m_timeoutMilliseconds(0) |
+ , m_loaderIdentifier(0) |
, m_state(UNSENT) |
, m_downloadedBlobLength(0) |
, m_receivedLength(0) |
@@ -912,6 +913,7 @@ void XMLHttpRequest::clearVariablesForLoading() |
m_decoder.clear(); |
if (m_responseDocumentParser) { |
+ m_responseDocumentParser->removeClient(this); |
#if !ENABLE(OILPAN) |
m_responseDocumentParser->detach(); |
#endif |
@@ -1280,19 +1282,20 @@ void XMLHttpRequest::didFinishLoading(unsigned long identifier, double) |
if (m_state < HEADERS_RECEIVED) |
changeState(HEADERS_RECEIVED); |
+ m_loaderIdentifier = identifier; |
+ |
if (m_responseDocumentParser) { |
+ // |DocumentParser::finish()| tells the parser that we have reached end of the data. |
+ // When using |HTMLDocumentParser|, which works asynchronously, we do not have the |
+ // complete document just after the |DocumentParser::finish()| call. |
+ // Wait for the parser to call us back in |notifyParserStopped| to progress state. |
m_responseDocumentParser->finish(); |
- m_responseDocumentParser = nullptr; |
- |
- m_responseDocument->implicitClose(); |
- |
- if (!m_responseDocument->wellFormed()) |
- m_responseDocument = nullptr; |
+ ASSERT(m_responseDocument); |
+ return; |
+ } |
- m_parsedResponse = true; |
- } else if (m_decoder) { |
+ if (m_decoder) |
m_responseText = m_responseText.concatenateWith(m_decoder->flush()); |
- } |
if (m_responseLegacyStream) |
m_responseLegacyStream->finalize(); |
@@ -1301,11 +1304,40 @@ void XMLHttpRequest::didFinishLoading(unsigned long identifier, double) |
m_responseStream->close(); |
clearVariablesForLoading(); |
+ endLoading(); |
+} |
+ |
+void XMLHttpRequest::notifyParserStopped() |
+{ |
+ // This should only be called when response document is parsed asynchronously. |
+ ASSERT(m_responseDocumentParser); |
+ ASSERT(!m_responseDocumentParser->isParsing()); |
+ ASSERT(!m_responseLegacyStream); |
+ ASSERT(!m_responseStream); |
+ |
+ // Do nothing if we are called from |internalAbort()|. |
+ if (m_error) |
+ return; |
+ |
+ clearVariablesForLoading(); |
+ |
+ m_responseDocument->implicitClose(); |
- InspectorInstrumentation::didFinishXHRLoading(executionContext(), this, this, identifier, m_responseText, m_method, m_url, m_lastSendURL, m_lastSendLineNumber); |
+ if (!m_responseDocument->wellFormed()) |
+ m_responseDocument = nullptr; |
+ |
+ m_parsedResponse = true; |
+ |
+ endLoading(); |
+} |
+ |
+void XMLHttpRequest::endLoading() |
+{ |
+ InspectorInstrumentation::didFinishXHRLoading(executionContext(), this, this, m_loaderIdentifier, m_responseText, m_method, m_url, m_lastSendURL, m_lastSendLineNumber); |
if (m_loader) |
m_loader = nullptr; |
+ m_loaderIdentifier = 0; |
changeState(DONE); |
} |
@@ -1350,6 +1382,7 @@ void XMLHttpRequest::parseDocumentChunk(const char* data, int len) |
return; |
m_responseDocumentParser = m_responseDocument->implicitOpen(); |
+ m_responseDocumentParser->addClient(this); |
} |
ASSERT(m_responseDocumentParser); |