Index: Source/modules/fetch/Body.cpp |
diff --git a/Source/modules/fetch/Body.cpp b/Source/modules/fetch/Body.cpp |
index 0be313e412339d2df44a9ff3303435e9b7786011..f95b4406b7d0ec8cacc5e6e4a6839b1ee21442f3 100644 |
--- a/Source/modules/fetch/Body.cpp |
+++ b/Source/modules/fetch/Body.cpp |
@@ -12,77 +12,41 @@ |
#include "bindings/core/v8/V8ThrowException.h" |
#include "core/dom/DOMArrayBuffer.h" |
#include "core/dom/DOMTypedArray.h" |
+#include "core/dom/ExceptionCode.h" |
#include "core/fileapi/Blob.h" |
-#include "core/fileapi/FileReaderLoader.h" |
-#include "core/fileapi/FileReaderLoaderClient.h" |
#include "core/frame/UseCounter.h" |
#include "core/streams/ReadableByteStream.h" |
#include "core/streams/ReadableByteStreamReader.h" |
#include "core/streams/UnderlyingSource.h" |
#include "modules/fetch/BodyStreamBuffer.h" |
+#include "modules/fetch/DataConsumerHandleUtil.h" |
+#include "modules/fetch/FetchBlobDataConsumerHandle.h" |
namespace blink { |
-class Body::BlobHandleReceiver final : public BodyStreamBuffer::BlobHandleCreatorClient { |
-public: |
- explicit BlobHandleReceiver(Body* body) |
- : m_body(body) |
- { |
- } |
- void didCreateBlobHandle(PassRefPtr<BlobDataHandle> handle) override |
- { |
- ASSERT(m_body); |
- m_body->readAsyncFromBlob(handle); |
- m_body = nullptr; |
- } |
- void didFail(DOMException* exception) override |
- { |
- ASSERT(m_body); |
- m_body->didBlobHandleReceiveError(exception); |
- m_body = nullptr; |
- } |
- DEFINE_INLINE_VIRTUAL_TRACE() |
- { |
- BodyStreamBuffer::BlobHandleCreatorClient::trace(visitor); |
- visitor->trace(m_body); |
- } |
-private: |
- Member<Body> m_body; |
-}; |
- |
// This class is an ActiveDOMObject subclass only for holding the |
yhirano
2015/07/03 04:42:28
We do no longer need ExecutionContext, right?
hiroshige
2015/07/05 07:30:24
Done.
|
// ExecutionContext used in |pullSource|. |
-class Body::ReadableStreamSource : public BodyStreamBuffer::Observer, public UnderlyingSource, public FileReaderLoaderClient, public ActiveDOMObject { |
+class Body::ReadableStreamSource : public GarbageCollectedFinalized<Body::ReadableStreamSource>, public UnderlyingSource, public WebDataConsumerHandle::Client, public BodyStreamBuffer::DrainingStreamNotificationClient, public ActiveDOMObject { |
USING_GARBAGE_COLLECTED_MIXIN(ReadableStreamSource); |
public: |
enum State { |
yhirano
2015/07/03 04:42:28
Now we can remove this enum and rely on the stream
hiroshige
2015/07/05 07:30:24
Done.
|
- Initial, |
Streaming, |
Closed, |
Errored, |
}; |
- ReadableStreamSource(ExecutionContext* executionContext, PassRefPtr<BlobDataHandle> handle) |
- : ActiveDOMObject(executionContext) |
- , m_blobDataHandle(handle ? handle : BlobDataHandle::create(BlobData::create(), 0)) |
- , m_state(Initial) |
- { |
- suspendIfNeeded(); |
- } |
ReadableStreamSource(ExecutionContext* executionContext, BodyStreamBuffer* buffer) |
: ActiveDOMObject(executionContext) |
, m_bodyStreamBuffer(buffer) |
- , m_state(Initial) |
- { |
- suspendIfNeeded(); |
- } |
- |
- explicit ReadableStreamSource(ExecutionContext* executionContext) |
- : ActiveDOMObject(executionContext) |
- , m_blobDataHandle(BlobDataHandle::create(BlobData::create(), 0)) |
- , m_state(Initial) |
+ , m_state(Streaming) |
+ , m_streamNeedsMore(false) |
+#if ENABLE(ASSERT) |
+ , m_drained(false) |
+#endif |
{ |
suspendIfNeeded(); |
+ if (m_bodyStreamBuffer) |
+ obtainReader(); |
} |
~ReadableStreamSource() override { } |
@@ -95,42 +59,31 @@ public: |
stream->didSourceStart(); |
} |
// Creates a new BodyStreamBuffer to drain the data. |
- BodyStreamBuffer* createDrainingStream() |
+ PassOwnPtr<DrainingBodyStreamBuffer> createDrainingStream() |
{ |
- ASSERT(m_state != Initial); |
+ if (!m_bodyStreamBuffer) |
+ return nullptr; |
- auto drainingStreamBuffer = new BodyStreamBuffer(new Canceller(this)); |
- if (m_stream->stateInternal() == ReadableByteStream::Closed) { |
- drainingStreamBuffer->close(); |
- return drainingStreamBuffer; |
- } |
- if (m_stream->stateInternal() == ReadableByteStream::Errored) { |
- drainingStreamBuffer->error(exception()); |
- return drainingStreamBuffer; |
- } |
+ ASSERT(!m_drained); |
+#if ENABLE(ASSERT) |
+ m_drained = true; |
+#endif |
- ASSERT(!m_drainingStreamBuffer); |
- // Take back the data in |m_stream|. |
- Deque<std::pair<RefPtr<DOMArrayBufferView>, size_t>> tmp_queue; |
- ASSERT(m_stream->stateInternal() == ReadableStream::Readable); |
- m_stream->readInternal(tmp_queue); |
- while (!tmp_queue.isEmpty()) { |
- std::pair<RefPtr<DOMArrayBufferView>, size_t> data = tmp_queue.takeFirst(); |
- drainingStreamBuffer->write(data.first->buffer()); |
- } |
- if (m_state == Closed) |
- drainingStreamBuffer->close(); |
+ if (m_stream->stateInternal() == ReadableByteStream::Closed) |
+ m_bodyStreamBuffer = BodyStreamBuffer::createEmpty(); |
+ if (m_stream->stateInternal() == ReadableByteStream::Errored) |
+ m_bodyStreamBuffer = BodyStreamBuffer::create(createFetchDataConsumerHandleFromWebHandle(createUnexpectedErrorDataConsumerHandle())); |
- m_drainingStreamBuffer = drainingStreamBuffer; |
- return m_drainingStreamBuffer; |
+ m_reader.clear(); |
+ return DrainingBodyStreamBuffer::create(m_bodyStreamBuffer, this); |
} |
+ |
DEFINE_INLINE_VIRTUAL_TRACE() |
{ |
visitor->trace(m_bodyStreamBuffer); |
- visitor->trace(m_drainingStreamBuffer); |
visitor->trace(m_stream); |
- BodyStreamBuffer::Observer::trace(visitor); |
UnderlyingSource::trace(visitor); |
+ DrainingStreamNotificationClient::trace(visitor); |
ActiveDOMObject::trace(visitor); |
} |
@@ -143,145 +96,118 @@ public: |
return; |
} |
m_state = Closed; |
- if (m_drainingStreamBuffer) |
- m_drainingStreamBuffer->close(); |
+ m_reader.clear(); |
m_stream->close(); |
} |
void error() |
{ |
m_state = Errored; |
- if (m_drainingStreamBuffer) |
- m_drainingStreamBuffer->error(exception()); |
- m_stream->error(exception()); |
+ m_reader.clear(); |
+ m_stream->error(DOMException::create(NetworkError, "network error")); |
} |
-private: |
- class Canceller : public BodyStreamBuffer::Canceller { |
- public: |
- Canceller(ReadableStreamSource* source) : m_source(source) { } |
- void cancel() override |
- { |
- m_source->cancel(); |
- } |
- |
- DEFINE_INLINE_VIRTUAL_TRACE() |
- { |
- visitor->trace(m_source); |
- BodyStreamBuffer::Canceller::trace(visitor); |
- } |
- |
- private: |
- Member<ReadableStreamSource> m_source; |
- }; |
- |
- // UnderlyingSource functions. |
- void pullSource() override |
+ void obtainReader() |
{ |
- // Note that one |pull| is called only when |read| is called on the |
- // associated ReadableByteStreamReader because we create a stream with |
- // StrictStrategy. |
- if (m_state == Initial) { |
- m_state = Streaming; |
- if (m_bodyStreamBuffer) { |
- m_bodyStreamBuffer->registerObserver(this); |
- onWrite(); |
- if (m_bodyStreamBuffer->hasError()) |
- return onError(); |
- if (m_bodyStreamBuffer->isClosed()) |
- return onClose(); |
- } else { |
- FileReaderLoader::ReadType readType = FileReaderLoader::ReadAsArrayBuffer; |
- m_loader = adoptPtr(new FileReaderLoader(readType, this)); |
- m_loader->start(executionContext(), m_blobDataHandle); |
- } |
- } |
+ m_reader = m_bodyStreamBuffer->handle()->obtainReader(this); |
} |
- ScriptPromise cancelSource(ScriptState* scriptState, ScriptValue reason) override |
+private: |
+ void didFetchDataLoadFinishedFromDrainingStream() |
{ |
- cancel(); |
- return ScriptPromise::cast(scriptState, v8::Undefined(scriptState->isolate())); |
+ ASSERT(m_bodyStreamBuffer); |
yhirano
2015/07/03 04:42:28
ASSERT(m_drained)?
hiroshige
2015/07/05 07:30:24
Done.
|
+ |
+#if ENABLE(ASSERT) |
+ m_drained = false; |
+#endif |
+ obtainReader(); |
+ // We have to call didGetReadable() now to call close()/error() if |
+ // necessary. |
+ // didGetReadable() would be called asynchronously, but it is too late. |
+ didGetReadable(); |
} |
- // BodyStreamBuffer::Observer functions. |
- void onWrite() override |
+ void didGetReadable() override |
{ |
- ASSERT(m_state == Streaming); |
- while (RefPtr<DOMArrayBuffer> buf = m_bodyStreamBuffer->read()) { |
- write(buf); |
+ if (!m_streamNeedsMore) { |
+ // Perform zero-length read to call close()/error() early. |
+ size_t readSize; |
+ WebDataConsumerHandle::Result result = m_reader->read(nullptr, 0, WebDataConsumerHandle::FlagNone, &readSize); |
+ switch (result) { |
+ case WebDataConsumerHandle::Ok: |
+ case WebDataConsumerHandle::ShouldWait: |
+ return; |
+ case WebDataConsumerHandle::Done: |
+ close(); |
+ return; |
+ case WebDataConsumerHandle::Busy: |
+ case WebDataConsumerHandle::ResourceExhausted: |
+ case WebDataConsumerHandle::UnexpectedError: |
+ error(); |
+ return; |
+ } |
} |
- } |
- void onClose() override |
- { |
- ASSERT(m_state == Streaming); |
- close(); |
- m_bodyStreamBuffer->unregisterObserver(); |
- } |
- void onError() override |
- { |
- ASSERT(m_state == Streaming); |
- error(); |
- m_bodyStreamBuffer->unregisterObserver(); |
- } |
- // FileReaderLoaderClient functions. |
- void didStartLoading() override { } |
- void didReceiveData() override { } |
- void didFinishLoading() override |
- { |
- ASSERT(m_state == Streaming); |
- write(m_loader->arrayBufferResult()); |
- close(); |
- } |
- void didFail(FileError::ErrorCode) override |
- { |
- ASSERT(m_state == Streaming); |
- error(); |
+ processData(); |
} |
- void write(PassRefPtr<DOMArrayBuffer> buf) |
+ // UnderlyingSource functions. |
+ void pullSource() override |
{ |
- if (m_drainingStreamBuffer) { |
- m_drainingStreamBuffer->write(buf); |
- } else { |
- auto size = buf->byteLength(); |
- m_stream->enqueue(DOMUint8Array::create(buf, 0, size)); |
- } |
+ ASSERT(!m_streamNeedsMore); |
+ m_streamNeedsMore = true; |
+ |
+ ASSERT(!m_drained); |
+ |
+ processData(); |
} |
- void cancel() |
+ |
+ ScriptPromise cancelSource(ScriptState* scriptState, ScriptValue reason) override |
{ |
- if (m_bodyStreamBuffer) { |
- m_bodyStreamBuffer->cancel(); |
- // We should not close the stream here, because it is canceller's |
- // responsibility. |
- } else { |
- if (m_loader) |
- m_loader->cancel(); |
- close(); |
- } |
+ close(); |
+ return ScriptPromise::cast(scriptState, v8::Undefined(scriptState->isolate())); |
} |
- DOMException* exception() |
+ // Reads data and writes the data to |m_stream|, as long as data are |
+ // available and the stream has pending reads. |
+ void processData() |
{ |
- if (m_state != Errored) |
- return nullptr; |
- if (m_bodyStreamBuffer) { |
- ASSERT(m_bodyStreamBuffer->exception()); |
- return m_bodyStreamBuffer->exception(); |
+ ASSERT(m_reader); |
+ while (m_streamNeedsMore) { |
+ const void* buffer; |
+ size_t available; |
+ WebDataConsumerHandle::Result result = m_reader->beginRead(&buffer, WebDataConsumerHandle::FlagNone, &available); |
+ switch (result) { |
+ case WebDataConsumerHandle::Ok: |
+ m_streamNeedsMore = m_stream->enqueue(DOMUint8Array::create(static_cast<const unsigned char*>(buffer), available)); |
+ m_reader->endRead(available); |
+ break; |
+ |
+ case WebDataConsumerHandle::Done: |
+ close(); |
+ return; |
+ |
+ case WebDataConsumerHandle::ShouldWait: |
+ return; |
+ |
+ case WebDataConsumerHandle::Busy: |
+ case WebDataConsumerHandle::ResourceExhausted: |
+ case WebDataConsumerHandle::UnexpectedError: |
+ error(); |
+ return; |
+ } |
} |
- return DOMException::create(NetworkError, "network error"); |
} |
- // Set when the data container of the Body is a BodyStreamBuffer. |
+ // Source of data. |
Member<BodyStreamBuffer> m_bodyStreamBuffer; |
- // Set when the data container of the Body is a BlobDataHandle. |
- RefPtr<BlobDataHandle> m_blobDataHandle; |
- // Used to read the data from BlobDataHandle. |
- OwnPtr<FileReaderLoader> m_loader; |
- // Created when createDrainingStream is called to drain the data. |
- Member<BodyStreamBuffer> m_drainingStreamBuffer; |
+ OwnPtr<FetchDataConsumerHandle::Reader> m_reader; |
+ |
Member<ReadableByteStream> m_stream; |
State m_state; |
+ bool m_streamNeedsMore; |
+#if ENABLE(ASSERT) |
+ bool m_drained; |
+#endif |
}; |
ScriptPromise Body::readAsync(ScriptState* scriptState, ResponseType type) |
@@ -307,94 +233,84 @@ ScriptPromise Body::readAsync(ScriptState* scriptState, ResponseType type) |
ScriptPromise promise = m_resolver->promise(); |
if (m_stream->stateInternal() == ReadableStream::Closed) { |
- // We resolve the resolver manually in order not to use member |
- // variables. |
- switch (m_responseType) { |
- case ResponseAsArrayBuffer: |
- m_resolver->resolve(DOMArrayBuffer::create(nullptr, 0)); |
- break; |
- case ResponseAsBlob: { |
- OwnPtr<BlobData> blobData = BlobData::create(); |
- blobData->setContentType(mimeType()); |
- m_resolver->resolve(Blob::create(BlobDataHandle::create(blobData.release(), 0))); |
- break; |
- } |
- case ResponseAsText: |
- m_resolver->resolve(String()); |
- break; |
- case ResponseAsFormData: |
- // TODO(yhirano): Implement this. |
- ASSERT_NOT_REACHED(); |
- break; |
- case ResponseAsJSON: { |
- ScriptState::Scope scope(m_resolver->scriptState()); |
- m_resolver->reject(V8ThrowException::createSyntaxError(m_resolver->scriptState()->isolate(), "Unexpected end of input")); |
- break; |
- } |
- case ResponseUnknown: |
- ASSERT_NOT_REACHED(); |
- break; |
- } |
- m_resolver.clear(); |
+ resolveWithEmptyDataSynchronously(); |
} else if (m_stream->stateInternal() == ReadableStream::Errored) { |
m_resolver->reject(m_stream->storedException()); |
m_resolver.clear(); |
- } else if (isBodyConsumed()) { |
- m_streamSource->createDrainingStream()->readAllAndCreateBlobHandle(mimeType(), new BlobHandleReceiver(this)); |
- } else if (buffer()) { |
- buffer()->readAllAndCreateBlobHandle(mimeType(), new BlobHandleReceiver(this)); |
} else { |
- readAsyncFromBlob(blobDataHandle()); |
+ readAsyncFromDrainingBodyStreamBuffer(createDrainingStream(), mimeType()); |
} |
return promise; |
} |
-void Body::readAsyncFromBlob(PassRefPtr<BlobDataHandle> handle) |
+void Body::resolveWithEmptyDataSynchronously() |
{ |
- FileReaderLoader::ReadType readType = FileReaderLoader::ReadAsText; |
- RefPtr<BlobDataHandle> blobHandle = handle; |
- if (!blobHandle) |
- blobHandle = BlobDataHandle::create(BlobData::create(), 0); |
+ // We resolve the resolver manually in order not to use member |
+ // variables. |
switch (m_responseType) { |
case ResponseAsArrayBuffer: |
- readType = FileReaderLoader::ReadAsArrayBuffer; |
+ m_resolver->resolve(DOMArrayBuffer::create(nullptr, 0)); |
break; |
- case ResponseAsBlob: |
- if (blobHandle->size() != kuint64max) { |
- // If the size of |blobHandle| is set correctly, creates Blob from |
- // it. |
- if (blobHandle->type() != mimeType()) { |
- // A new BlobDataHandle is created to override the Blob's type. |
- m_resolver->resolve(Blob::create(BlobDataHandle::create(blobHandle->uuid(), mimeType(), blobHandle->size()))); |
- } else { |
- m_resolver->resolve(Blob::create(blobHandle)); |
- } |
- m_stream->close(); |
- m_resolver.clear(); |
- return; |
- } |
- // If the size is not set, read as ArrayBuffer and create a new blob to |
- // get the size. |
- // FIXME: This workaround is not good for performance. |
- // When we will stop using Blob as a base system of Body to support |
- // stream, this problem should be solved. |
- readType = FileReaderLoader::ReadAsArrayBuffer; |
+ case ResponseAsBlob: { |
+ OwnPtr<BlobData> blobData = BlobData::create(); |
+ blobData->setContentType(mimeType()); |
+ m_resolver->resolve(Blob::create(BlobDataHandle::create(blobData.release(), 0))); |
+ break; |
+ } |
+ case ResponseAsText: |
+ m_resolver->resolve(String()); |
break; |
case ResponseAsFormData: |
- // FIXME: Implement this. |
+ // TODO(yhirano): Implement this. |
+ ASSERT_NOT_REACHED(); |
+ break; |
+ case ResponseAsJSON: { |
+ ScriptState::Scope scope(m_resolver->scriptState()); |
+ m_resolver->reject(V8ThrowException::createSyntaxError(m_resolver->scriptState()->isolate(), "Unexpected end of input")); |
+ break; |
+ } |
+ case ResponseUnknown: |
ASSERT_NOT_REACHED(); |
break; |
+ } |
+ m_resolver.clear(); |
+} |
+ |
+void Body::readAsyncFromDrainingBodyStreamBuffer(PassOwnPtr<DrainingBodyStreamBuffer> buffer, const String& mimeType) |
+{ |
+ if (!buffer) { |
+ resolveWithEmptyDataSynchronously(); |
+ m_streamSource->close(); |
+ return; |
+ } |
+ |
+ FetchDataLoader* fetchDataLoader = nullptr; |
+ |
+ switch (m_responseType) { |
+ case ResponseAsArrayBuffer: |
+ fetchDataLoader = FetchDataLoader::createLoaderAsArrayBuffer(); |
+ break; |
+ |
case ResponseAsJSON: |
case ResponseAsText: |
+ fetchDataLoader = FetchDataLoader::createLoaderAsString(); |
+ break; |
+ |
+ case ResponseAsBlob: |
+ fetchDataLoader = FetchDataLoader::createLoaderAsBlobHandle(mimeType); |
break; |
+ |
+ case ResponseAsFormData: |
+ // FIXME: Implement this. |
+ ASSERT_NOT_REACHED(); |
+ return; |
+ |
default: |
ASSERT_NOT_REACHED(); |
+ return; |
} |
- m_loader = adoptPtr(new FileReaderLoader(readType, this)); |
- m_loader->start(m_resolver->scriptState()->executionContext(), blobHandle); |
- |
- return; |
+ buffer->startLoading(fetchDataLoader, this); |
} |
ScriptPromise Body::arrayBuffer(ScriptState* scriptState) |
@@ -444,41 +360,20 @@ void Body::lockBody(LockBodyOption option) |
ASSERT(!exceptionState.hadException()); |
} |
-bool Body::isBodyConsumed() const |
+void Body::setBody(BodyStreamBuffer* buffer) |
{ |
- if (m_streamSource->state() != m_streamSource->Initial) { |
- // Some data is pulled from the source. |
- return true; |
- } |
- if (m_stream->stateInternal() == ReadableStream::Closed) { |
- // Return true if the blob handle is originally not empty. |
- RefPtr<BlobDataHandle> handle = blobDataHandle(); |
- return handle && handle->size(); |
- } |
- if (m_stream->stateInternal() == ReadableStream::Errored) { |
- // The stream is errored. That means an effort to read data was made. |
- return true; |
- } |
- return false; |
-} |
- |
-void Body::setBody(ReadableStreamSource* source) |
-{ |
- m_streamSource = source; |
+ m_streamSource = new ReadableStreamSource(executionContext(), buffer); |
m_stream = new ReadableByteStream(m_streamSource, new ReadableByteStream::StrictStrategy); |
m_streamSource->startStream(m_stream); |
} |
-BodyStreamBuffer* Body::createDrainingStream() |
+PassOwnPtr<DrainingBodyStreamBuffer> Body::createDrainingStream() |
{ |
return m_streamSource->createDrainingStream(); |
} |
void Body::stop() |
yhirano
2015/07/03 04:42:28
If you do nothing you can delete this function.
hiroshige
2015/07/05 07:30:24
Done.
|
{ |
- // Canceling the load will call didFail which will remove the resolver. |
- if (m_loader) |
- m_loader->cancel(); |
} |
bool Body::hasPendingActivity() const |
@@ -492,29 +387,20 @@ bool Body::hasPendingActivity() const |
return false; |
} |
-Body::ReadableStreamSource* Body::createBodySource(PassRefPtr<BlobDataHandle> handle) |
-{ |
- return new ReadableStreamSource(executionContext(), handle); |
-} |
- |
-Body::ReadableStreamSource* Body::createBodySource(BodyStreamBuffer* buffer) |
-{ |
- return new ReadableStreamSource(executionContext(), buffer); |
-} |
- |
DEFINE_TRACE(Body) |
{ |
visitor->trace(m_resolver); |
visitor->trace(m_stream); |
visitor->trace(m_streamSource); |
ActiveDOMObject::trace(visitor); |
+ FetchDataLoader::Client::trace(visitor); |
} |
Body::Body(ExecutionContext* context) |
: ActiveDOMObject(context) |
, m_bodyUsed(false) |
, m_responseType(ResponseType::ResponseUnknown) |
- , m_streamSource(new ReadableStreamSource(context)) |
+ , m_streamSource(new ReadableStreamSource(context, nullptr)) |
, m_stream(new ReadableByteStream(m_streamSource, new ReadableByteStream::StrictStrategy)) |
{ |
m_streamSource->startStream(m_stream); |
@@ -534,63 +420,60 @@ void Body::resolveJSON(const String& string) |
m_resolver->reject(trycatch.Exception()); |
} |
-// FileReaderLoaderClient functions. |
-void Body::didStartLoading() { } |
-void Body::didReceiveData() { } |
-void Body::didFinishLoading() |
+// FetchDataLoader::Client functions. |
+void Body::didFetchDataLoadFailed() |
{ |
if (!executionContext() || executionContext()->activeDOMObjectsAreStopped()) |
return; |
- switch (m_responseType) { |
- case ResponseAsArrayBuffer: |
- m_resolver->resolve(m_loader->arrayBufferResult()); |
- break; |
- case ResponseAsBlob: { |
- ASSERT(blobDataHandle()->size() == kuint64max); |
- OwnPtr<BlobData> blobData = BlobData::create(); |
- RefPtr<DOMArrayBuffer> buffer = m_loader->arrayBufferResult(); |
- blobData->appendBytes(buffer->data(), buffer->byteLength()); |
- blobData->setContentType(mimeType()); |
- const size_t length = blobData->length(); |
- m_resolver->resolve(Blob::create(BlobDataHandle::create(blobData.release(), length))); |
- break; |
- } |
- case ResponseAsFormData: |
- ASSERT_NOT_REACHED(); |
- break; |
- case ResponseAsJSON: |
- resolveJSON(m_loader->stringResult()); |
- break; |
- case ResponseAsText: |
- m_resolver->resolve(m_loader->stringResult()); |
- break; |
- default: |
- ASSERT_NOT_REACHED(); |
+ if (m_resolver) { |
+ if (!m_resolver->executionContext() || m_resolver->executionContext()->activeDOMObjectsAreStopped()) { |
+ m_resolver.clear(); |
+ return; |
+ } |
+ ScriptState* state = m_resolver->scriptState(); |
+ ScriptState::Scope scope(state); |
+ m_resolver->reject(V8ThrowException::createTypeError(state->isolate(), "Failed to fetch")); |
+ m_resolver.clear(); |
} |
- m_streamSource->close(); |
+} |
+ |
+void Body::didFetchDataLoadedBlobHandle(PassRefPtr<BlobDataHandle> blobDataHandle) |
+{ |
+ if (!executionContext() || executionContext()->activeDOMObjectsAreStopped()) |
+ return; |
+ |
+ ASSERT(m_responseType == ResponseAsBlob); |
+ m_resolver->resolve(Blob::create(blobDataHandle)); |
m_resolver.clear(); |
} |
-void Body::didFail(FileError::ErrorCode code) |
+void Body::didFetchDataLoadedArrayBuffer(PassRefPtr<DOMArrayBuffer> arrayBuffer) |
{ |
if (!executionContext() || executionContext()->activeDOMObjectsAreStopped()) |
return; |
- m_streamSource->error(); |
- if (m_resolver) { |
- // FIXME: We should reject the promise. |
- m_resolver->resolve(""); |
- m_resolver.clear(); |
- } |
+ ASSERT(m_responseType == ResponseAsArrayBuffer); |
+ m_resolver->resolve(arrayBuffer); |
+ m_resolver.clear(); |
} |
-void Body::didBlobHandleReceiveError(DOMException* exception) |
+void Body::didFetchDataLoadedString(const String& str) |
{ |
- if (!m_resolver) |
+ if (!executionContext() || executionContext()->activeDOMObjectsAreStopped()) |
return; |
- m_streamSource->error(); |
- m_resolver->reject(exception); |
+ |
+ switch (m_responseType) { |
+ case ResponseAsJSON: |
+ resolveJSON(str); |
+ break; |
+ case ResponseAsText: |
+ m_resolver->resolve(str); |
+ break; |
+ default: |
+ ASSERT_NOT_REACHED(); |
+ } |
+ |
m_resolver.clear(); |
} |