Title: [186740] trunk/Source/WebCore
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;
 };
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to