Index: third_party/WebKit/Source/modules/fetch/Body.cpp |
diff --git a/third_party/WebKit/Source/modules/fetch/Body.cpp b/third_party/WebKit/Source/modules/fetch/Body.cpp |
index 1e64fe123a83319bc00f9ea7a453c3a6c61a3caa..0d9a78e27dd3c334ee01fa77469dc8323f91685f 100644 |
--- a/third_party/WebKit/Source/modules/fetch/Body.cpp |
+++ b/third_party/WebKit/Source/modules/fetch/Body.cpp |
@@ -14,6 +14,9 @@ |
#include "core/dom/ExceptionCode.h" |
#include "core/fileapi/Blob.h" |
#include "core/frame/UseCounter.h" |
+#include "core/streams/ReadableStreamController.h" |
+#include "core/streams/ReadableStreamOperations.h" |
+#include "core/streams/UnderlyingSourceBase.h" |
#include "modules/fetch/BodyStreamBuffer.h" |
#include "modules/fetch/FetchDataLoader.h" |
#include "wtf/PassRefPtr.h" |
@@ -99,6 +102,60 @@ public: |
} |
}; |
+class UnderlyingSourceFromDataConsumerHandle final : public UnderlyingSourceBase, public WebDataConsumerHandle::Client { |
+ EAGERLY_FINALIZE(); |
+ DECLARE_EAGER_FINALIZATION_OPERATOR_NEW(); |
tyoshino (SeeGerritForStatus)
2016/04/04 09:21:30
Could you please point me to some doc by which I c
yhirano
2016/04/04 09:28:20
I don't know much about it either. I got an assert
|
+public: |
+ UnderlyingSourceFromDataConsumerHandle(ScriptState* scriptState, PassOwnPtr<WebDataConsumerHandle> handle) |
+ : UnderlyingSourceBase(scriptState) |
+ , m_scriptState(scriptState) |
+ , m_reader(handle->obtainReader(this)) |
+ { |
+ } |
+ |
+ ScriptPromise pull(ScriptState* scriptState) override |
+ { |
+ didGetReadable(); |
+ return ScriptPromise::castUndefined(scriptState); |
+ } |
+ |
+ ScriptPromise cancel(ScriptState* scriptState, ScriptValue reason) override |
+ { |
+ m_reader = nullptr; |
+ return ScriptPromise::castUndefined(scriptState); |
+ } |
+ |
+ void didGetReadable() override |
+ { |
+ while (controller()->desiredSize() > 0) { |
+ const auto kNone = WebDataConsumerHandle::FlagNone; |
tyoshino (SeeGerritForStatus)
2016/04/04 09:21:30
kNone is used just once. how about just putting th
yhirano
2016/04/04 09:28:20
Done.
|
+ size_t available; |
+ const void* buffer = nullptr; |
+ WebDataConsumerHandle::Result result = m_reader->beginRead(&buffer, kNone, &available); |
+ if (result == WebDataConsumerHandle::Ok) { |
+ RefPtr<ArrayBuffer> arrayBuffer = ArrayBuffer::create(available, 1); |
+ memcpy(arrayBuffer->data(), buffer, available); |
+ m_reader->endRead(available); |
+ controller()->enqueue(DOMUint8Array::create(arrayBuffer.release(), 0, available)); |
+ } else if (result == WebDataConsumerHandle::ShouldWait) { |
+ break; |
+ } else if (result == WebDataConsumerHandle::Done) { |
+ m_reader = nullptr; |
+ controller()->close(); |
+ break; |
+ } else { |
+ m_reader = nullptr; |
+ controller()->error(V8ThrowException::createTypeError(m_scriptState->isolate(), "Network error")); |
+ break; |
+ } |
+ } |
+ } |
+ |
+private: |
+ RefPtr<ScriptState> m_scriptState; |
+ OwnPtr<WebDataConsumerHandle::Reader> m_reader; |
+}; |
+ |
} // namespace |
ScriptPromise Body::arrayBuffer(ScriptState* scriptState) |
@@ -200,6 +257,16 @@ ReadableByteStream* Body::bodyWithUseCounter() |
return body(); |
} |
+ScriptValue Body::v8ExtraStreamBody(ScriptState* scriptState) |
+{ |
+ if (bodyUsed() || isBodyLocked() || !bodyBuffer()) |
+ return ScriptValue(scriptState, v8::Undefined(scriptState->isolate())); |
+ OwnPtr<FetchDataConsumerHandle> handle = bodyBuffer()->releaseHandle(scriptState->getExecutionContext()); |
+ return ReadableStreamOperations::createReadableStream(scriptState, |
+ new UnderlyingSourceFromDataConsumerHandle(scriptState, handle.release()), |
+ ScriptValue(scriptState, v8::Undefined(scriptState->isolate()))); |
+} |
+ |
bool Body::bodyUsed() |
{ |
return body() && body()->isDisturbed(); |