- Revision
- 186740
- Author
- [email protected]
- Date
- 2015-07-12 09:28:11 -0700 (Sun, 12 Jul 2015)
Log Message
[Streams API] Templating ReadableJSStream
https://bugs.webkit.org/show_bug.cgi?id=146802
Reviewed by Darin Adler.
Introducing ReadableStream::clearValues to clear queued values when cancelling and going into error state.
Introducing ReadableEnqueuingStream to handle the stream queue, as a class template.
Specialized ReadableEnqueuingStream for the purpose of ReadableJSStream (storage of JSValue with variable size).
Updated some static functions to accept a ReadableStream in lieu of the more specialized ReadableJSStream.
Covered by existing tests.
* Modules/streams/ReadableStream.cpp:
(WebCore::ReadableStream::changeStateToErrored):
(WebCore::ReadableStream::cancelNoCheck):
* Modules/streams/ReadableStream.h:
(WebCore::ReadableEnqueuingStream::ReadableEnqueuingStream):
(WebCore::ReadableEnqueuingStream::enqueueChunk):
(WebCore::ReadableEnqueuingStream<ChunkType>::read):
* bindings/js/ReadableJSStream.cpp:
(WebCore::ReadableEnqueuingStream<ReadableJSStreamValue>::read):
(WebCore::ReadableEnqueuingStream<ReadableJSStreamValue>::enqueueChunk):
(WebCore::createPullResultFulfilledFunction):
(WebCore::createCancelResultFulfilledFunction):
(WebCore::ReadableJSStream::ReadableJSStream):
(WebCore::ReadableJSStream::enqueue):
* bindings/js/ReadableJSStream.h:
(WebCore::ReadableJSStreamValue::create):
(WebCore::ReadableEnqueuingStream<ReadableJSStreamValue>::desiredSize):
(WebCore::ReadableEnqueuingStream<ReadableJSStreamValue>::ReadableEnqueuingStream):
Modified Paths
Diff
Modified: trunk/Source/WebCore/ChangeLog (186739 => 186740)
--- trunk/Source/WebCore/ChangeLog 2015-07-12 14:46:42 UTC (rev 186739)
+++ trunk/Source/WebCore/ChangeLog 2015-07-12 16:28:11 UTC (rev 186740)
@@ -1,3 +1,38 @@
+2015-07-12 Youenn Fablet <[email protected]>
+
+ [Streams API] Templating ReadableJSStream
+ https://bugs.webkit.org/show_bug.cgi?id=146802
+
+ Reviewed by Darin Adler.
+
+ Introducing ReadableStream::clearValues to clear queued values when cancelling and going into error state.
+
+ Introducing ReadableEnqueuingStream to handle the stream queue, as a class template.
+ Specialized ReadableEnqueuingStream for the purpose of ReadableJSStream (storage of JSValue with variable size).
+
+ Updated some static functions to accept a ReadableStream in lieu of the more specialized ReadableJSStream.
+
+ Covered by existing tests.
+
+ * Modules/streams/ReadableStream.cpp:
+ (WebCore::ReadableStream::changeStateToErrored):
+ (WebCore::ReadableStream::cancelNoCheck):
+ * Modules/streams/ReadableStream.h:
+ (WebCore::ReadableEnqueuingStream::ReadableEnqueuingStream):
+ (WebCore::ReadableEnqueuingStream::enqueueChunk):
+ (WebCore::ReadableEnqueuingStream<ChunkType>::read):
+ * bindings/js/ReadableJSStream.cpp:
+ (WebCore::ReadableEnqueuingStream<ReadableJSStreamValue>::read):
+ (WebCore::ReadableEnqueuingStream<ReadableJSStreamValue>::enqueueChunk):
+ (WebCore::createPullResultFulfilledFunction):
+ (WebCore::createCancelResultFulfilledFunction):
+ (WebCore::ReadableJSStream::ReadableJSStream):
+ (WebCore::ReadableJSStream::enqueue):
+ * bindings/js/ReadableJSStream.h:
+ (WebCore::ReadableJSStreamValue::create):
+ (WebCore::ReadableEnqueuingStream<ReadableJSStreamValue>::desiredSize):
+ (WebCore::ReadableEnqueuingStream<ReadableJSStreamValue>::ReadableEnqueuingStream):
+
2015-07-11 Babak Shafiei <[email protected]>
Unreviewed build fix.
Modified: trunk/Source/WebCore/Modules/streams/ReadableStream.cpp (186739 => 186740)
--- trunk/Source/WebCore/Modules/streams/ReadableStream.cpp 2015-07-12 14:46:42 UTC (rev 186739)
+++ trunk/Source/WebCore/Modules/streams/ReadableStream.cpp 2015-07-12 16:28:11 UTC (rev 186740)
@@ -105,6 +105,8 @@
{
if (m_state != State::Readable)
return;
+
+ clearValues();
m_state = State::Errored;
JSC::JSValue error = this->error();
@@ -197,6 +199,8 @@
}
ASSERT(m_state == State::Readable);
+ clearValues();
+
m_cancelPromise = WTF::move(promise);
close();
Modified: trunk/Source/WebCore/Modules/streams/ReadableStream.h (186739 => 186740)
--- trunk/Source/WebCore/Modules/streams/ReadableStream.h 2015-07-12 14:46:42 UTC (rev 186739)
+++ trunk/Source/WebCore/Modules/streams/ReadableStream.h 2015-07-12 16:28:11 UTC (rev 186740)
@@ -33,7 +33,9 @@
#if ENABLE(STREAMS_API)
#include "ActiveDOMObject.h"
+#include "DOMRequestState.h"
#include "JSDOMPromise.h"
+#include "ScriptState.h"
#include "ScriptWrappable.h"
#include <functional>
#include <wtf/Deque.h>
@@ -113,6 +115,7 @@
void clearCallbacks();
void close();
+ virtual void clearValues() = 0;
virtual bool hasEnoughValues() const = 0;
virtual bool hasValue() const = 0;
virtual JSC::JSValue read() = 0;
@@ -134,8 +137,33 @@
State m_state { State::Readable };
};
+// This class manages the queue and knows whether there is sufficient data in it.
+// Subclasses should implement error storage, pulling and cancelling.
+template<typename ChunkType>
+class ReadableEnqueuingStream final : public ReadableStream {
+protected:
+ explicit ReadableEnqueuingStream(ScriptExecutionContext& context) : ReadableStream(context) { }
+
+ void enqueueChunk(ChunkType&& chunk) { m_queue.append(std::forward(chunk)); }
+
+private:
+ virtual void clearValues() override { m_queue.clear(); }
+ virtual bool hasEnoughValues() const override { return m_queue.size(); }
+ virtual bool hasValue() const override { return m_queue.size(); }
+ virtual JSC::JSValue read() override;
+
+ Deque<ChunkType> m_queue;
+};
+
+template<typename ChunkType>
+inline JSC::JSValue ReadableEnqueuingStream<ChunkType>::read()
+{
+ DOMRequestState state(scriptExecutionContext());
+ return toJS(state.exec(), toJSDOMGlobalObject(scriptExecutionContext(), state.exec()), m_queue.read());
}
+}
+
#endif
#endif // ReadableStream_h
Modified: trunk/Source/WebCore/bindings/js/ReadableJSStream.cpp (186739 => 186740)
--- trunk/Source/WebCore/bindings/js/ReadableJSStream.cpp 2015-07-12 14:46:42 UTC (rev 186739)
+++ trunk/Source/WebCore/bindings/js/ReadableJSStream.cpp 2015-07-12 16:28:11 UTC (rev 186740)
@@ -119,6 +119,19 @@
});
}
+JSC::JSValue ReadableEnqueuingStream<ReadableJSStreamValue>::read()
+{
+ ReadableJSStreamValue chunk = m_queue.takeFirst();
+ m_totalQueueSize -= chunk.size;
+ return chunk.value.get();
+}
+
+void ReadableEnqueuingStream<ReadableJSStreamValue>::enqueueChunk(ReadableJSStreamValue&& chunk)
+{
+ m_totalQueueSize += chunk.size;
+ m_queue.append(WTF::move(chunk));
+}
+
void ReadableJSStream::doStart(ExecState& exec)
{
JSLockHolder lock(&exec);
@@ -136,9 +149,9 @@
thenPromise(exec, promise, createStartResultFulfilledFunction(exec, *this), m_errorFunction.get());
}
-static inline JSFunction* createPullResultFulfilledFunction(ExecState& exec, ReadableJSStream& stream)
+static inline JSFunction* createPullResultFulfilledFunction(ExecState& exec, ReadableStream& stream)
{
- RefPtr<ReadableJSStream> protectedStream = &stream;
+ RefPtr<ReadableStream> protectedStream = &stream;
return JSFunction::create(exec.vm(), exec.callee()->globalObject(), 0, String(), [protectedStream](ExecState*) {
protectedStream->finishPulling();
return JSValue::encode(jsUndefined());
@@ -164,9 +177,9 @@
return !promise;
}
-static JSFunction* createCancelResultFulfilledFunction(ExecState& exec, ReadableJSStream& stream)
+static JSFunction* createCancelResultFulfilledFunction(ExecState& exec, ReadableStream& stream)
{
- RefPtr<ReadableJSStream> protectedStream = &stream;
+ RefPtr<ReadableStream> protectedStream = &stream;
return JSFunction::create(exec.vm(), exec.callee()->globalObject(), 1, String(), [protectedStream](ExecState*) {
protectedStream->notifyCancelSucceeded();
return JSValue::encode(jsUndefined());
@@ -247,8 +260,7 @@
}
ReadableJSStream::ReadableJSStream(ExecState& state, JSObject* source, double highWaterMark, JSFunction* sizeFunction)
- : ReadableStream(*scriptExecutionContextFromExecState(&state))
- , m_highWaterMark(highWaterMark)
+ : ReadableEnqueuingStream<ReadableJSStreamValue>(*scriptExecutionContextFromExecState(&state), highWaterMark)
{
m_source.set(state.vm(), source);
// We do not take a Ref to the stream as this would cause a Ref cycle.
@@ -302,21 +314,6 @@
changeStateToErrored();
}
-bool ReadableJSStream::hasValue() const
-{
- return m_chunkQueue.size();
-}
-
-JSValue ReadableJSStream::read()
-{
- ASSERT(hasValue());
-
- Chunk chunk = m_chunkQueue.takeFirst();
- m_totalQueueSize -= chunk.size;
-
- return chunk.value.get();
-}
-
void ReadableJSStream::enqueue(JSC::ExecState& state, JSC::JSValue chunk)
{
if (isErrored()) {
@@ -339,8 +336,7 @@
if (state.hadException())
return;
- m_chunkQueue.append({ JSC::Strong<JSC::Unknown>(state.vm(), chunk), size });
- m_totalQueueSize += size;
+ enqueueChunk({ JSC::Strong<JSC::Unknown>(state.vm(), chunk), size });
pull();
}
Modified: trunk/Source/WebCore/bindings/js/ReadableJSStream.h (186739 => 186740)
--- trunk/Source/WebCore/bindings/js/ReadableJSStream.h 2015-07-12 14:46:42 UTC (rev 186739)
+++ trunk/Source/WebCore/bindings/js/ReadableJSStream.h 2015-07-12 16:28:11 UTC (rev 186740)
@@ -52,8 +52,35 @@
typedef int ExceptionCode;
-class ReadableJSStream: public ReadableStream {
+struct ReadableJSStreamValue {
+ JSC::Strong<JSC::Unknown> value;
+ double size;
+};
+
+template<> class ReadableEnqueuingStream<ReadableJSStreamValue> : public ReadableStream {
public:
+ double desiredSize() const { return m_highWaterMark - m_totalQueueSize; }
+
+protected:
+ ReadableEnqueuingStream(ScriptExecutionContext& context, double highWaterMark)
+ : ReadableStream(context)
+ , m_highWaterMark(highWaterMark) { }
+
+ void enqueueChunk(ReadableJSStreamValue&&);
+
+private:
+ virtual void clearValues() override { m_queue.clear(); }
+ virtual bool hasEnoughValues() const override { return desiredSize() <= 0; }
+ virtual bool hasValue() const override { return m_queue.size(); }
+ virtual JSC::JSValue read() override;
+
+ Deque<ReadableJSStreamValue> m_queue;
+ double m_totalQueueSize { 0 };
+ double m_highWaterMark;
+};
+
+class ReadableJSStream final : public ReadableEnqueuingStream<ReadableJSStreamValue> {
+public:
static RefPtr<ReadableJSStream> create(JSC::ExecState&, JSC::JSValue, const Dictionary&);
JSC::JSValue jsController(JSC::ExecState&, JSDOMGlobalObject*);
@@ -65,8 +92,6 @@
void enqueue(JSC::ExecState&, JSC::JSValue);
void error(JSC::ExecState&, JSC::JSValue, ExceptionCode&);
- double desiredSize() const { return m_highWaterMark - m_totalQueueSize; }
-
private:
ReadableJSStream(JSC::ExecState&, JSC::JSObject*, double, JSC::JSFunction*);
@@ -75,9 +100,6 @@
JSC::JSPromise* invoke(JSC::ExecState&, const char*, JSC::JSValue parameter);
void storeException(JSC::ExecState&);
- virtual bool hasEnoughValues() const override { return desiredSize() <= 0; }
- virtual bool hasValue() const override;
- virtual JSC::JSValue read() override;
virtual bool doPull() override;
virtual bool doCancel(JSC::JSValue) override;
@@ -89,16 +111,8 @@
// FIXME: we should consider not using JSC::Strong, see https://bugs.webkit.org/show_bug.cgi?id=146278
JSC::Strong<JSC::Unknown> m_error;
JSC::Strong<JSC::JSFunction> m_errorFunction;
+
JSC::Strong<JSC::JSObject> m_source;
-
- struct Chunk {
- JSC::Strong<JSC::Unknown> value;
- double size;
- };
- Deque<Chunk> m_chunkQueue;
-
- double m_totalQueueSize { 0 };
- double m_highWaterMark;
JSC::Strong<JSC::JSFunction> m_sizeFunction;
};