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

Unified Diff: Source/core/streams/ExclusiveStreamReader.cpp

Issue 837673002: Introduce ExclusiveStreamReader. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Created 5 years, 10 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
« no previous file with comments | « Source/core/streams/ExclusiveStreamReader.h ('k') | Source/core/streams/ExclusiveStreamReader.idl » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/core/streams/ExclusiveStreamReader.cpp
diff --git a/Source/core/streams/ExclusiveStreamReader.cpp b/Source/core/streams/ExclusiveStreamReader.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..9615cefa95d93f7447ffc970bc89626a9a5654e4
--- /dev/null
+++ b/Source/core/streams/ExclusiveStreamReader.cpp
@@ -0,0 +1,198 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "config.h"
+#include "core/streams/ExclusiveStreamReader.h"
+
+#include "bindings/core/v8/ExceptionState.h"
+#include "bindings/core/v8/ScriptFunction.h"
+#include "bindings/core/v8/ScriptPromiseResolver.h"
+#include "core/dom/DOMException.h"
+#include "core/streams/ReadableStream.h"
+
+namespace blink {
+
+namespace {
+
+class PromiseRaceFulfillHandler : public ScriptFunction {
+public:
+ static v8::Handle<v8::Function> create(PassRefPtrWillBeRawPtr<ScriptPromiseResolver> resolver)
+ {
+ return (new PromiseRaceFulfillHandler(resolver))->bindToV8Function();
+ }
+
+ void trace(Visitor* visitor)
+ {
+ visitor->trace(m_resolver);
+ ScriptFunction::trace(visitor);
+ }
+
+private:
+ explicit PromiseRaceFulfillHandler(PassRefPtrWillBeRawPtr<ScriptPromiseResolver> resolver)
+ : ScriptFunction(resolver->scriptState())
+ , m_resolver(resolver) { }
+ ScriptValue call(ScriptValue value) override
+ {
+ m_resolver->resolve(value);
+ return ScriptValue(scriptState(), v8::Undefined(scriptState()->isolate()));
+ }
+
+ RefPtrWillBeMember<ScriptPromiseResolver> m_resolver;
+};
+
+class PromiseRaceRejectHandler : public ScriptFunction {
+public:
+ static v8::Handle<v8::Function> create(PassRefPtrWillBeRawPtr<ScriptPromiseResolver> resolver)
+ {
+ return (new PromiseRaceRejectHandler(resolver))->bindToV8Function();
+ }
+
+ void trace(Visitor* visitor)
+ {
+ visitor->trace(m_resolver);
+ ScriptFunction::trace(visitor);
+ }
+
+private:
+ explicit PromiseRaceRejectHandler(PassRefPtrWillBeRawPtr<ScriptPromiseResolver> resolver)
+ : ScriptFunction(resolver->scriptState())
+ , m_resolver(resolver) { }
+ ScriptValue call(ScriptValue value) override
+ {
+ m_resolver->reject(value);
+ return ScriptValue(scriptState(), v8::Undefined(scriptState()->isolate()));
+ }
+
+ RefPtrWillBeMember<ScriptPromiseResolver> m_resolver;
+};
+
+ScriptPromise race(ScriptState* scriptState, const Vector<ScriptPromise>& promises)
+{
+ RefPtrWillBeRawPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(scriptState);
+ for (ScriptPromise promise : promises) {
+ promise.then(PromiseRaceFulfillHandler::create(resolver), PromiseRaceRejectHandler::create(resolver));
+ }
+ return resolver->promise();
+}
+
+} // namespace
+
+ExclusiveStreamReader::ExclusiveStreamReader(ReadableStream* stream)
+ : ActiveDOMObject(stream->executionContext())
+ , m_stream(stream)
+ , m_released(new ReleasedPromise(stream->executionContext(), this, ReleasedPromise::Released))
+ , m_stateAfterRelease(ReadableStream::Closed)
+{
+ suspendIfNeeded();
+ ASSERT(m_stream->isLockedTo(nullptr));
+ m_stream->setReader(this);
+}
+
+ScriptPromise ExclusiveStreamReader::closed(ScriptState* scriptState)
+{
+ if (isActive()) {
+ Vector<ScriptPromise> promises;
+ promises.append(m_stream->closed(scriptState));
+ promises.append(m_released->promise(scriptState->world()));
+ return race(scriptState, promises);
+ }
+ ASSERT(m_released);
+ return m_closedAfterRelease->promise(scriptState->world());
+}
+
+bool ExclusiveStreamReader::isActive() const
+{
+ return m_stream->isLockedTo(this);
+}
+
+ScriptPromise ExclusiveStreamReader::ready(ScriptState* scriptState)
+{
+ if (isActive()) {
+ Vector<ScriptPromise> promises;
+ promises.append(m_stream->readyInternal(scriptState));
+ promises.append(m_released->promise(scriptState->world()));
+ return race(scriptState, promises);
+ }
+ ASSERT(m_readyAfterRelease);
+ return m_readyAfterRelease->promise(scriptState->world());
+}
+
+String ExclusiveStreamReader::state() const
+{
+ if (isActive())
+ return ReadableStream::stateToString(m_stream->stateInternal());
+ return ReadableStream::stateToString(m_stateAfterRelease);
+}
+
+ScriptPromise ExclusiveStreamReader::cancel(ScriptState* scriptState, ScriptValue reason)
+{
+ if (isActive()) {
+ releaseLock();
+ return m_stream->cancel(scriptState, reason);
+ }
+ return m_closedAfterRelease->promise(scriptState->world());
+}
+
+ScriptValue ExclusiveStreamReader::read(ScriptState* scriptState, ExceptionState& es)
+{
+ if (!isActive()) {
+ es.throwTypeError("The stream is not locked to this reader");
+ return ScriptValue();
+ }
+ return m_stream->readInternal(scriptState, es);
+}
+
+void ExclusiveStreamReader::releaseLock()
+{
+ if (!isActive())
+ return;
+
+ m_stream->setReader(nullptr);
+
+ m_readyAfterRelease = new ReadyPromise(executionContext(), this, ReadyPromise::Ready);
+ m_readyAfterRelease->resolve(ToV8UndefinedGenerator());
+ m_closedAfterRelease = new ClosedPromise(executionContext(), this, ReadyPromise::Closed);
+
+ if (m_stream->stateInternal() == ReadableStream::Closed) {
+ m_stateAfterRelease = ReadableStream::Closed;
+ m_closedAfterRelease->resolve(ToV8UndefinedGenerator());
+ } else if (m_stream->stateInternal() == ReadableStream::Errored) {
+ m_stateAfterRelease = ReadableStream::Errored;
+ m_closedAfterRelease->reject(m_stream->storedException());
+ } else {
+ m_stateAfterRelease = ReadableStream::Closed;
+ m_closedAfterRelease->resolve(ToV8UndefinedGenerator());
+ }
+ m_released->resolve(ToV8UndefinedGenerator());
+ ASSERT(!isActive());
+}
+
+ScriptPromise ExclusiveStreamReader::released(ScriptState* scriptState)
+{
+ return m_released->promise(scriptState->world());
+}
+
+bool ExclusiveStreamReader::hasPendingActivity() const
+{
+ // We need to extend ExclusiveStreamReader's wrapper's life while it is
+ // active in order to call resolve / reject on ScriptPromiseProperties.
+ return isActive();
+}
+
+void ExclusiveStreamReader::stop()
+{
+ releaseLock();
+ ActiveDOMObject::stop();
+}
+
+void ExclusiveStreamReader::trace(Visitor* visitor)
+{
+ visitor->trace(m_stream);
+ visitor->trace(m_released);
+ visitor->trace(m_closedAfterRelease);
+ visitor->trace(m_readyAfterRelease);
+ ActiveDOMObject::trace(visitor);
+}
+
+} // namespace blink
« no previous file with comments | « Source/core/streams/ExclusiveStreamReader.h ('k') | Source/core/streams/ExclusiveStreamReader.idl » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698