[Streams API] Implement ReadableStream cancel (abstract part)
authoryouenn.fablet@crf.canon.fr <youenn.fablet@crf.canon.fr@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 22 Jun 2015 13:59:08 +0000 (13:59 +0000)
committeryouenn.fablet@crf.canon.fr <youenn.fablet@crf.canon.fr@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 22 Jun 2015 13:59:08 +0000 (13:59 +0000)
https://bugs.webkit.org/show_bug.cgi?id=146111

Reviewed by Darin Adler.

Source/WebCore:

This patch implements ReadableStream and ReadableStreamReader cancel.
The reader delegates cancellation to its stream.

This patch also ensures that controller.close() will not throw in case cancellation is on-going.

A follow-up patch will implement the calling of 'cancel' JS callback for JS sources.

Covered by rebased tests.

* Modules/streams/ReadableStream.cpp:
(WebCore::ReadableStream::cancel): Checks whether locked or not before cancelling.
(WebCore::ReadableStream::cancelNoCheck): Cancel without lock check.
(WebCore::ReadableStream::notifyCancelSucceeded): Async cancel callback.
(WebCore::ReadableStream::notifyCancelFailed): Ditto.
* Modules/streams/ReadableStream.h:
* Modules/streams/ReadableStream.idl: Cleaned up IDL.
* Modules/streams/ReadableStreamReader.cpp:
(WebCore::ReadableStreamReader::cancel):
* Modules/streams/ReadableStreamReader.h:
* Modules/streams/ReadableStreamReader.idl: Cleaned up IDL
* bindings/js/JSReadableStreamControllerCustom.cpp:
(WebCore::JSReadableStreamController::close):
* bindings/js/JSReadableStreamCustom.cpp:
(WebCore::JSReadableStream::cancel):
* bindings/js/JSReadableStreamReaderCustom.cpp:
(WebCore::JSReadableStreamReader::cancel):
* bindings/js/ReadableJSStream.cpp:
(WebCore::ReadableJSStream::doCancel):
* bindings/js/ReadableJSStream.h:

LayoutTests:

Rebasing expectations.

* streams/reference-implementation/bad-underlying-sources-expected.txt:
* streams/reference-implementation/readable-stream-cancel-expected.txt:
* streams/reference-implementation/readable-stream-expected.txt:
* streams/reference-implementation/readable-stream-reader-expected.txt:
* streams/reference-implementation/readable-stream-templated-expected.txt:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@185826 268f45cc-cd09-0410-ab3c-d52691b4dbfc

18 files changed:
LayoutTests/ChangeLog
LayoutTests/streams/reference-implementation/bad-underlying-sources-expected.txt
LayoutTests/streams/reference-implementation/readable-stream-cancel-expected.txt
LayoutTests/streams/reference-implementation/readable-stream-expected.txt
LayoutTests/streams/reference-implementation/readable-stream-reader-expected.txt
LayoutTests/streams/reference-implementation/readable-stream-templated-expected.txt
Source/WebCore/ChangeLog
Source/WebCore/Modules/streams/ReadableStream.cpp
Source/WebCore/Modules/streams/ReadableStream.h
Source/WebCore/Modules/streams/ReadableStream.idl
Source/WebCore/Modules/streams/ReadableStreamReader.cpp
Source/WebCore/Modules/streams/ReadableStreamReader.h
Source/WebCore/Modules/streams/ReadableStreamReader.idl
Source/WebCore/bindings/js/JSReadableStreamControllerCustom.cpp
Source/WebCore/bindings/js/JSReadableStreamCustom.cpp
Source/WebCore/bindings/js/JSReadableStreamReaderCustom.cpp
Source/WebCore/bindings/js/ReadableJSStream.cpp
Source/WebCore/bindings/js/ReadableJSStream.h

index e807cf1..37e07ab 100644 (file)
@@ -1,3 +1,18 @@
+2015-06-22  Xabier Rodriguez Calvar  <calvaris@igalia.com> and Youenn Fablet  <youenn.fablet@crf.canon.fr>
+
+        [Streams API] Implement ReadableStream cancel (abstract part)
+        https://bugs.webkit.org/show_bug.cgi?id=146111
+
+        Reviewed by Darin Adler.
+
+        Rebasing expectations.
+
+        * streams/reference-implementation/bad-underlying-sources-expected.txt:
+        * streams/reference-implementation/readable-stream-cancel-expected.txt:
+        * streams/reference-implementation/readable-stream-expected.txt:
+        * streams/reference-implementation/readable-stream-reader-expected.txt:
+        * streams/reference-implementation/readable-stream-templated-expected.txt:
+
 2015-06-22  Xabier Rodriguez Calvar  <calvaris@igalia.com> and Youenn Fablet <youenn.fablet@crf.canon.fr>
 
         [Streams API] Correct releaseLock test in readable-stream-templated.html
index 56cf92d..1bcfa79 100644 (file)
@@ -5,16 +5,16 @@ PASS Underlying source: throwing pull getter (initial pull)
 PASS Underlying source: throwing pull method (initial pull) 
 PASS Underlying source: throwing pull getter (second pull) 
 PASS Underlying source: throwing pull method (second pull) 
-FAIL Underlying source: throwing cancel getter cancel is not implemented
-FAIL Underlying source: throwing cancel method cancel is not implemented
-FAIL Underlying source: calling enqueue on an empty canceled stream should not throw cancel is not implemented
-FAIL Underlying source: calling enqueue on a non-empty canceled stream should not throw cancel is not implemented
+FAIL Underlying source: throwing cancel getter assert_unreached: cancel should not fulfill Reached unreachable code
+FAIL Underlying source: throwing cancel method assert_unreached: cancel should not fulfill Reached unreachable code
+PASS Underlying source: calling enqueue on an empty canceled stream should not throw 
+PASS Underlying source: calling enqueue on a non-empty canceled stream should not throw 
 PASS Underlying source: calling enqueue on a closed stream should throw 
 PASS Underlying source: calling enqueue on an errored stream should throw 
 PASS Underlying source: calling close twice on an empty stream should throw the second time 
 PASS Underlying source: calling close twice on a non-empty stream should throw the second time 
-FAIL Underlying source: calling close on an empty canceled stream should not throw cancel is not implemented
-FAIL Underlying source: calling close on a non-empty canceled stream should not throw cancel is not implemented
+PASS Underlying source: calling close on an empty canceled stream should not throw 
+PASS Underlying source: calling close on a non-empty canceled stream should not throw 
 PASS Underlying source: calling close after error should throw 
 PASS Underlying source: calling error twice should throw the second time 
 PASS Underlying source: calling error after close should throw 
index 750a9de..5a33722 100644 (file)
@@ -1,12 +1,12 @@
 
-FAIL ReadableStream cancellation: integration test on an infinite stream derived from a random push source cancel is not implemented
-FAIL ReadableStream cancellation: cancel(reason) should pass through the given reason to the underlying source cancel is not implemented
-FAIL ReadableStream cancellation: cancel() on a locked stream should fail and not call the underlying source cancel cancel is not implemented
-FAIL ReadableStream cancellation: should fulfill promise when cancel callback went fine cancel is not implemented
-FAIL ReadableStream cancellation: returning a value from the underlying source's cancel should not affect the fulfillment value of the promise returned by the stream's cancel cancel is not implemented
-FAIL ReadableStream cancellation: should reject promise when cancel callback raises an exception cancel is not implemented
-FAIL ReadableStream cancellation: if the underlying source's cancel method returns a promise, the promise returned by the stream's cancel should fulfill when that one does (1) cancel is not implemented
-FAIL ReadableStream cancellation: if the underlying source's cancel method returns a promise, the promise returned by the stream's cancel should fulfill when that one does (2) cancel is not implemented
-FAIL ReadableStream cancellation: if the underlying source's cancel method returns a promise, the promise returned by the stream's cancel should reject when that one does cancel is not implemented
-FAIL ReadableStream cancellation: cancelling before start finishes should prevent pull() from being called cancel is not implemented
+FAIL ReadableStream cancellation: integration test on an infinite stream derived from a random push source assert_equals: it returns a promise that is fulfilled when the cancellation finishes expected true but got false
+FAIL ReadableStream cancellation: cancel(reason) should pass through the given reason to the underlying source assert_equals: the error passed to the underlying source's cancel method should equal the one passed to the stream's cancel expected (object) object "Error: Sorry, it just wasn't meant to be." but got (undefined) undefined
+PASS ReadableStream cancellation: cancel() on a locked stream should fail and not call the underlying source cancel 
+FAIL ReadableStream cancellation: should fulfill promise when cancel callback went fine assert_true: expected true got false
+PASS ReadableStream cancellation: returning a value from the underlying source's cancel should not affect the fulfillment value of the promise returned by the stream's cancel 
+FAIL ReadableStream cancellation: should reject promise when cancel callback raises an exception assert_unreached: cancel should reject Reached unreachable code
+PASS ReadableStream cancellation: if the underlying source's cancel method returns a promise, the promise returned by the stream's cancel should fulfill when that one does (1) 
+FAIL ReadableStream cancellation: if the underlying source's cancel method returns a promise, the promise returned by the stream's cancel should fulfill when that one does (2) assert_true: cancel() return value should be fulfilled only after the promise returned by the underlying source's cancel expected true got false
+FAIL ReadableStream cancellation: if the underlying source's cancel method returns a promise, the promise returned by the stream's cancel should reject when that one does assert_unreached: cancel() return value should not be rejected Reached unreachable code
+PASS ReadableStream cancellation: cancelling before start finishes should prevent pull() from being called 
 
index 98d91f2..7d9f59c 100644 (file)
@@ -25,7 +25,7 @@ PASS ReadableStream pull should be able to close a stream.
 PASS ReadableStream: enqueue should throw when the stream is readable but draining 
 PASS ReadableStream: enqueue should throw when the stream is closed 
 PASS ReadableStream: enqueue should throw the stored error when the stream is errored 
-FAIL ReadableStream: should call underlying source methods as methods cancel is not implemented
+FAIL ReadableStream: should call underlying source methods as methods assert_equals: expected 1 but got 0
 FAIL ReadableStream strategies: the default strategy should give desiredSize of 1 to start, decreasing by 1 per enqueue assert_equals: expected (number) 1 but got (undefined) undefined
 FAIL ReadableStream strategies: the default strategy should continue giving desiredSize of 1 if the chunks are read immediately assert_equals: desiredSize should start at 1 expected (number) 1 but got (undefined) undefined
 PASS ReadableStream integration test: adapting a random push source 
index ee7eb82..1650996 100644 (file)
@@ -10,12 +10,12 @@ PASS Getting a ReadableStreamReader via getReader should fail if the stream is a
 PASS Constructing a ReadableStreamReader directly should be OK if the stream is closed 
 PASS Constructing a ReadableStreamReader directly should be OK if the stream is errored 
 PASS Reading from a reader for an empty stream will wait until a chunk is available 
-FAIL cancel() on a reader releases the reader before calling through cancel is not implemented
+FAIL cancel() on a reader releases the reader before calling through assert_true: expected true got false
 PASS closed should be fulfilled after stream is closed (.closed access before acquiring) 
 PASS closed should be fulfilled after reader releases its lock (multiple stream locks) 
 PASS Multiple readers can access the stream in sequence 
 PASS Cannot use an already-released reader to unlock a stream again 
-FAIL cancel() on a released reader is a no-op and does not pass through cancel is not implemented
+PASS cancel() on a released reader is a no-op and does not pass through 
 PASS Getting a second reader after erroring the stream should succeed 
 PASS Garbage-collecting a ReadableStreamReader should not unlock its stream 
 
index 7ea0f4d..0e38551 100644 (file)
@@ -12,32 +12,32 @@ PASS releasing the lock with pending read requests should throw but the read req
 PASS releasing the lock should cause further read() calls to resolve as if the stream is closed 
 PASS releasing the lock should cause closed to fulfill 
 PASS releasing the lock should cause locked to become false 
-FAIL canceling via the reader should cause the reader to act closed cancel is not implemented
-FAIL canceling via the stream should fail cancel is not implemented
+PASS canceling via the reader should cause the reader to act closed 
+PASS canceling via the stream should fail 
 PASS Running templatedRSClosed with ReadableStream (closed via call in start) 
-FAIL cancel() should return a distinct fulfilled promise each time cancel is not implemented
+PASS cancel() should return a distinct fulfilled promise each time 
 PASS locked should be false 
 PASS getReader() should be OK 
 PASS should be able to acquire multiple readers, since they are all auto-released 
 PASS Running templatedRSClosedReader with ReadableStream (closed via call in start) reader 
 PASS read() should fulfill with { value: undefined, done: true } 
 PASS closed should fulfill with undefined 
-FAIL cancel() should return a distinct fulfilled promise each time cancel is not implemented
+PASS cancel() should return a distinct fulfilled promise each time 
 PASS Running templatedRSClosed with ReadableStream (closed via cancel) 
-FAIL cancel() should return a distinct fulfilled promise each time cancel is not implemented
-FAIL locked should be false cancel is not implemented
-FAIL getReader() should be OK cancel is not implemented
-FAIL should be able to acquire multiple readers, since they are all auto-released cancel is not implemented
+PASS cancel() should return a distinct fulfilled promise each time 
+PASS locked should be false 
+PASS getReader() should be OK 
+PASS should be able to acquire multiple readers, since they are all auto-released 
 PASS Running templatedRSClosedReader with ReadableStream (closed via cancel) reader 
-FAIL read() should fulfill with { value: undefined, done: true } cancel is not implemented
-FAIL closed should fulfill with undefined cancel is not implemented
-FAIL cancel() should return a distinct fulfilled promise each time cancel is not implemented
+PASS read() should fulfill with { value: undefined, done: true } 
+PASS closed should fulfill with undefined 
+PASS cancel() should return a distinct fulfilled promise each time 
 PASS Running templatedRSErrored with ReadableStream (errored via call in start) 
 PASS getReader() should return a reader that acts errored 
 PASS locked should be false 
 PASS Running templatedRSErroredSyncOnly with ReadableStream (errored via call in start) 
-FAIL cancel() should return a distinct rejected promise each time cancel is not implemented
-FAIL reader cancel() should return a distinct rejected promise each time cancel is not implemented
+PASS cancel() should return a distinct rejected promise each time 
+PASS reader cancel() should return a distinct rejected promise each time 
 PASS should be able to acquire multiple readers, since they are all auto-released 
 PASS Running templatedRSErrored with ReadableStream (errored via returning a rejected promise in start) 
 PASS getReader() should return a reader that acts errored 
@@ -49,7 +49,7 @@ PASS Running templatedRSTwoChunksOpenReader with ReadableStream (two chunks enqu
 PASS calling read() twice without waiting will eventually give both chunks 
 PASS calling read() twice with waiting will eventually give both chunks 
 PASS read() should return distinct promises each time 
-FAIL cancel() after a read() should still give that single read result cancel is not implemented
+PASS cancel() after a read() should still give that single read result 
 PASS Running templatedRSTwoChunksClosedReader with ReadableStream (two chunks enqueued, then closed) reader 
 PASS third read(), without waiting, should give { value: undefined, done: true } 
 PASS third read, with waiting, should give { value: undefined, done: true } 
index 89e2115..ad34293 100644 (file)
@@ -1,3 +1,40 @@
+2015-06-22  Xabier Rodriguez Calvar  <calvaris@igalia.com> and Youenn Fablet  <youenn.fablet@crf.canon.fr>
+
+        [Streams API] Implement ReadableStream cancel (abstract part)
+        https://bugs.webkit.org/show_bug.cgi?id=146111
+
+        Reviewed by Darin Adler.
+
+        This patch implements ReadableStream and ReadableStreamReader cancel.
+        The reader delegates cancellation to its stream.
+
+        This patch also ensures that controller.close() will not throw in case cancellation is on-going.
+
+        A follow-up patch will implement the calling of 'cancel' JS callback for JS sources.
+
+        Covered by rebased tests.
+
+        * Modules/streams/ReadableStream.cpp:
+        (WebCore::ReadableStream::cancel): Checks whether locked or not before cancelling.
+        (WebCore::ReadableStream::cancelNoCheck): Cancel without lock check.
+        (WebCore::ReadableStream::notifyCancelSucceeded): Async cancel callback.
+        (WebCore::ReadableStream::notifyCancelFailed): Ditto.
+        * Modules/streams/ReadableStream.h:
+        * Modules/streams/ReadableStream.idl: Cleaned up IDL.
+        * Modules/streams/ReadableStreamReader.cpp:
+        (WebCore::ReadableStreamReader::cancel):
+        * Modules/streams/ReadableStreamReader.h:
+        * Modules/streams/ReadableStreamReader.idl: Cleaned up IDL
+        * bindings/js/JSReadableStreamControllerCustom.cpp:
+        (WebCore::JSReadableStreamController::close):
+        * bindings/js/JSReadableStreamCustom.cpp:
+        (WebCore::JSReadableStream::cancel):
+        * bindings/js/JSReadableStreamReaderCustom.cpp:
+        (WebCore::JSReadableStreamReader::cancel):
+        * bindings/js/ReadableJSStream.cpp:
+        (WebCore::ReadableJSStream::doCancel):
+        * bindings/js/ReadableJSStream.h:
+
 2015-06-22  Adam Bergkvist  <adam.bergkvist@ericsson.com>
 
         WebRTC: Navigator.webkitGetUserMedia() requires three arguments
index 8b4f894..42795ef 100644 (file)
@@ -32,6 +32,7 @@
 
 #if ENABLE(STREAMS_API)
 
+#include "ExceptionCode.h"
 #include "ReadableStreamReader.h"
 #include <runtime/JSCJSValueInlines.h>
 #include <wtf/RefCountedLeakCounter.h>
@@ -162,6 +163,53 @@ ReadableStreamReader& ReadableStream::getReader()
     return reader;
 }
 
+void ReadableStream::cancel(JSC::JSValue reason, CancelPromise&& promise, ExceptionCode& ec)
+{
+    if (locked()) {
+        ec = TypeError;
+        return;
+    }
+    cancelNoCheck(reason, WTF::move(promise));
+}
+
+void ReadableStream::cancelNoCheck(JSC::JSValue reason, CancelPromise&& promise)
+{
+    if (m_state == State::Closed) {
+        promise.resolve(nullptr);
+        return;
+    }
+    if (m_state == State::Errored) {
+        promise.reject(error());
+        return;
+    }
+    ASSERT(m_state == State::Readable);
+
+    m_cancelPromise = WTF::move(promise);
+
+    close();
+
+    if (doCancel(reason))
+        error() ? notifyCancelFailed() : notifyCancelSucceeded();
+}
+
+void ReadableStream::notifyCancelSucceeded()
+{
+    ASSERT(m_state == State::Closed);
+    ASSERT(m_cancelPromise);
+
+    m_cancelPromise.value().resolve(nullptr);
+    m_cancelPromise = Nullopt;
+}
+
+void ReadableStream::notifyCancelFailed()
+{
+    ASSERT(m_state == State::Closed);
+    ASSERT(m_cancelPromise);
+
+    m_cancelPromise.value().reject(error());
+    m_cancelPromise = Nullopt;
+}
+
 void ReadableStream::closed(ClosedSuccessCallback&& successCallback, FailureCallback&& failureCallback)
 {
     if (m_state == State::Closed) {
index e52995b..80bc650 100644 (file)
 #if ENABLE(STREAMS_API)
 
 #include "ActiveDOMObject.h"
+#include "JSDOMPromise.h"
 #include "ScriptWrappable.h"
 #include <functional>
 #include <wtf/Deque.h>
+#include <wtf/Optional.h>
 #include <wtf/Ref.h>
 #include <wtf/RefCounted.h>
 
@@ -48,6 +50,8 @@ namespace WebCore {
 class ReadableStreamReader;
 class ScriptExecutionContext;
 
+typedef int ExceptionCode;
+
 // ReadableStream implements the core of the streams API ReadableStream functionality.
 // It handles in particular the backpressure according the queue size.
 // ReadableStream is using a ReadableStreamSource to get data in its queue.
@@ -80,9 +84,15 @@ public:
     void changeStateToClosed();
     void changeStateToErrored();
     void finishPulling();
+    void notifyCancelSucceeded();
+    void notifyCancelFailed();
 
     typedef std::function<void(JSC::JSValue)> FailureCallback;
 
+    typedef DOMPromise<std::nullptr_t, JSC::JSValue> CancelPromise;
+    void cancel(JSC::JSValue, CancelPromise&&, ExceptionCode&);
+    void cancelNoCheck(JSC::JSValue, CancelPromise&&);
+
     typedef std::function<void()> ClosedSuccessCallback;
     void closed(ClosedSuccessCallback&&, FailureCallback&&);
 
@@ -107,10 +117,13 @@ private:
     virtual bool hasValue() const = 0;
     virtual JSC::JSValue read() = 0;
     virtual bool doPull() = 0;
+    virtual bool doCancel(JSC::JSValue) = 0;
 
     std::unique_ptr<ReadableStreamReader> m_reader;
     Vector<std::unique_ptr<ReadableStreamReader>> m_releasedReaders;
 
+    Optional<CancelPromise> m_cancelPromise;
+
     ClosedSuccessCallback m_closedSuccessCallback;
     FailureCallback m_closedFailureCallback;
 
index 3080f6f..afcdcc3 100644 (file)
     Conditional=STREAMS_API,
     SkipVTableValidation
 ] interface ReadableStream {
-    // FIXME: Remove RaisesException once methods are actually implemented.
-    [Custom, RaisesException] Promise cancel(DOMString reason);
-    [Custom, RaisesException] ReadableStreamReader getReader();
-    [Custom, RaisesException] Promise pipeTo(any streams, any options);
-    [Custom, RaisesException] Object pipeThrough(any dest, any options);
+    [Custom] Promise cancel(any reason);
+    [Custom] ReadableStreamReader getReader();
+    [Custom] Promise pipeTo(any streams, any options);
+    [Custom] Object pipeThrough(any dest, any options);
 
     readonly attribute boolean locked;
 };
index 2b27096..d34e91c 100644 (file)
 
 namespace WebCore {
 
+void ReadableStreamReader::cancel(JSC::JSValue reason, ReadableStream::CancelPromise&& promise)
+{
+    if (m_stream.isReadable() && m_stream.reader() != this) {
+        promise.resolve(nullptr);
+        return;
+    }
+    m_stream.cancelNoCheck(reason, WTF::move(promise));
+}
+
 void ReadableStreamReader::closed(ReadableStream::ClosedSuccessCallback&& successCallback, ReadableStream::FailureCallback&& failureCallback)
 {
     if (m_stream.isReadable() && m_stream.reader() != this) {
index 0710c8f..0076632 100644 (file)
@@ -53,6 +53,7 @@ public:
     ReadableStreamReader(ReadableStream& stream)
         : m_stream(stream) { }
 
+    void cancel(JSC::JSValue, ReadableStream::CancelPromise&&);
     void closed(ReadableStream::ClosedSuccessCallback&&, ReadableStream::FailureCallback&&);
     void read(ReadableStream::ReadSuccessCallback&&, ReadableStream::ReadEndCallback&&, ReadableStream::FailureCallback&&);
     void releaseLock(ExceptionCode&);
index 7c90390..4a0f45e 100644 (file)
@@ -33,9 +33,8 @@
     NoInterfaceObject,
     SkipVTableValidation
 ] interface ReadableStreamReader {
-    // FIXME: Remove RaisesException once methods are implemented.
-    [Custom, RaisesException] Object read();
-    [Custom, RaisesException] Promise cancel(DOMString reason);
+    [Custom] Object read();
+    [Custom] Promise cancel(any reason);
     [RaisesException] void releaseLock();
 
     [CustomGetter] readonly attribute Promise closed;
index 12d49cb..1337bce 100644 (file)
@@ -43,9 +43,10 @@ namespace WebCore {
 JSValue JSReadableStreamController::close(ExecState* exec)
 {
     ReadableJSStream& stream = impl().stream();
-    // FIXME: Handle the case of draining.
-    if (!stream.isReadable())
-        return exec->vm().throwException(exec, createTypeError(exec, ASCIILiteral("Calling close on a stream which is not readable")));
+    if (stream.isCloseRequested())
+        return exec->vm().throwException(exec, createTypeError(exec, ASCIILiteral("Calling enqueue on a stream which is closing")));
+    if (stream.isErrored())
+        return exec->vm().throwException(exec, createTypeError(exec, ASCIILiteral("Calling close on a stream which is errored")));
     stream.changeStateToClosed();
     return jsUndefined();
 }
index 403b679..227b9e1 100644 (file)
@@ -49,8 +49,15 @@ namespace WebCore {
 
 JSValue JSReadableStream::cancel(ExecState* exec)
 {
-    JSValue error = createError(exec, ASCIILiteral("cancel is not implemented"));
-    return exec->vm().throwException(exec, error);
+    // FIXME: We should be able to remove this custom binding, once we can pass a JSValue or a ScriptValue.
+    ExceptionCode ec = 0;
+    JSPromiseDeferred& promiseDeferred = *JSPromiseDeferred::create(exec, globalObject());
+    impl().cancel(exec->argument(0), DeferredWrapper(exec, globalObject(), &promiseDeferred), ec);
+
+    if (ec)
+        DeferredWrapper(exec, globalObject(), &promiseDeferred).reject(ec);
+
+    return promiseDeferred.promise();
 }
 
 JSValue JSReadableStream::getReader(ExecState* exec)
index 4fed7e8..16ac39c 100644 (file)
@@ -88,8 +88,10 @@ JSValue JSReadableStreamReader::closed(ExecState* exec) const
 
 JSValue JSReadableStreamReader::cancel(ExecState* exec)
 {
-    JSValue error = createError(exec, ASCIILiteral("cancel is not implemented"));
-    return exec->vm().throwException(exec, error);
+    // FIXME: We should be able to remove this custom binding, once we can pass a JSValue or a ScriptValue.
+    JSPromiseDeferred& promiseDeferred = *JSPromiseDeferred::create(exec, globalObject());
+    impl().cancel(exec->argument(0), DeferredWrapper(exec, globalObject(), &promiseDeferred));
+    return promiseDeferred.promise();
 }
 
 EncodedJSValue JSC_HOST_CALL constructJSReadableStreamReader(ExecState* exec)
index 83b8ab5..fd3c427 100644 (file)
@@ -182,6 +182,12 @@ RefPtr<ReadableJSStream> ReadableJSStream::create(ExecState& exec, ScriptExecuti
     return readableStream;
 }
 
+bool ReadableJSStream::doCancel(JSValue)
+{
+    // FIXME: Implement it.
+    return true;
+}
+
 ReadableJSStream::ReadableJSStream(ScriptExecutionContext& scriptExecutionContext, ExecState& state, JSObject* source)
     : ReadableStream(scriptExecutionContext)
 {
index caa76f2..d3f7358 100644 (file)
@@ -72,6 +72,7 @@ private:
     virtual bool hasValue() const override;
     virtual JSC::JSValue read() override;
     virtual bool doPull() override;
+    virtual bool doCancel(JSC::JSValue) override;
 
     JSDOMGlobalObject* globalObject();