Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(28)

Unified Diff: Source/modules/fetch/Body.cpp

Issue 1192913007: Change BodyStreamBuffer to be FetchDataConsumerHandle-based and enable backpressure in Fetch API (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: (temp) alternative to calling didGetReadable in sync. Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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();
}

Powered by Google App Engine
This is Rietveld 408576698