[Streams API] Add close method to writable stream
authorcalvaris@igalia.com <calvaris@igalia.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 27 Oct 2015 11:36:56 +0000 (11:36 +0000)
committercalvaris@igalia.com <calvaris@igalia.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 27 Oct 2015 11:36:56 +0000 (11:36 +0000)
https://bugs.webkit.org/show_bug.cgi?id=150560

Reviewed by Darin Adler.

Source/WebCore:

Added the close method which requires three additional writable stream internal functions plus a queuing
function to retrieve a value from the queue according to the spec.

Current test set suffices. Expectations were updated accordingly.

* Modules/streams/StreamInternals.js:
(peekQueueValue):
* Modules/streams/WritableStream.js:
(close):
* Modules/streams/WritableStreamInternals.js:
(callOrScheduleWritableStreamAdvanceQueue):
(writableStreamAdvanceQueue):
(closeWritableStream): Added as per spec.

LayoutTests:

New expectations after adding close method to writable stream.

Two tests were also flagged because of bug 147933 that prevents them from running properly in certain
conditions. So far this only happened in Mac, hence they were flagged only for it.

* platform/mac/TestExpectations:
* streams/reference-implementation/bad-underlying-sinks-expected.txt:
* streams/reference-implementation/brand-checks-expected.txt:
* streams/reference-implementation/pipe-to-expected.txt:
* streams/reference-implementation/writable-stream-abort-expected.txt:
* streams/reference-implementation/writable-stream-expected.txt:

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

LayoutTests/ChangeLog
LayoutTests/platform/mac/TestExpectations
LayoutTests/streams/reference-implementation/bad-underlying-sinks-expected.txt
LayoutTests/streams/reference-implementation/brand-checks-expected.txt
LayoutTests/streams/reference-implementation/pipe-to-expected.txt
LayoutTests/streams/reference-implementation/writable-stream-abort-expected.txt
LayoutTests/streams/reference-implementation/writable-stream-expected.txt
Source/WebCore/ChangeLog
Source/WebCore/Modules/streams/StreamInternals.js
Source/WebCore/Modules/streams/WritableStream.js
Source/WebCore/Modules/streams/WritableStreamInternals.js

index 2a4feb59a2242239a7bf3c8e3f8f436a9c46eaac..6049cf3503fad2bb67856ce25ac7f90d59b21fd7 100644 (file)
@@ -1,3 +1,22 @@
+2015-10-27  Xabier Rodriguez Calvar  <calvaris@igalia.com>
+
+        [Streams API] Add close method to writable stream
+        https://bugs.webkit.org/show_bug.cgi?id=150560
+
+        Reviewed by Darin Adler.
+
+        New expectations after adding close method to writable stream.
+
+        Two tests were also flagged because of bug 147933 that prevents them from running properly in certain
+        conditions. So far this only happened in Mac, hence they were flagged only for it.
+
+        * platform/mac/TestExpectations:
+        * streams/reference-implementation/bad-underlying-sinks-expected.txt:
+        * streams/reference-implementation/brand-checks-expected.txt:
+        * streams/reference-implementation/pipe-to-expected.txt:
+        * streams/reference-implementation/writable-stream-abort-expected.txt:
+        * streams/reference-implementation/writable-stream-expected.txt:
+
 2015-10-26  Ryan Haddad  <ryanhaddad@apple.com>
 
         Removing duplicated test expectations and removing debug flag from flaky fast/canvas/webgl tests
index 1315484423eea05ad5310d145e38038f58461f93..180b6133e1ea8da4114561f27b89d9772be31b70 100644 (file)
@@ -1348,3 +1348,7 @@ webkit.org/b/149930 fast/canvas/webgl/oes-texture-float-linear.html [ Pass Failu
 
 # Imported Blink tests which have not been investigated.
 imported/blink/compositing/video/video-controls-layer-creation-squashing.html [ Pass ImageOnlyFailure ]
+
+# Promises callbacks issues create problems in the writable stream tests
+webkit.org/b/147933 streams/reference-implementation/count-queuing-strategy.html [ Pass Failure ]
+webkit.org/b/147933 streams/reference-implementation/writable-stream-abort.html [ Pass Failure ]
index 41f976deb23727fb88b3e7a5b26fcce8643de999..9646ebc904648f378f83a1faf5c22aadbdc97553 100644 (file)
@@ -5,6 +5,6 @@ FAIL Underlying sink: throwing write getter write not implemented
 FAIL Underlying sink: throwing write method write not implemented
 PASS Underlying sink: throwing abort getter 
 PASS Underlying sink: throwing abort method 
-FAIL Underlying sink: throwing close getter close not implemented
-FAIL Underlying sink: throwing close method close not implemented
+PASS Underlying sink: throwing close getter 
+PASS Underlying sink: throwing close method 
 
index 0d9da076ee607100e03b7eeff7a6e6706e49662e..5ec77b12745c902a29aed2c43a6c06afc8ec3543 100644 (file)
@@ -22,7 +22,7 @@ PASS WritableStream.prototype.ready enforces a brand check
 PASS WritableStream.prototype.state enforces a brand check 
 PASS WritableStream.prototype.abort enforces a brand check 
 FAIL WritableStream.prototype.write enforces a brand check write not implemented
-FAIL WritableStream.prototype.close enforces a brand check close not implemented
+PASS WritableStream.prototype.close enforces a brand check 
 PASS ByteLengthQueuingStrategy.prototype.size should work generically on its this and its arguments 
 PASS CountQueuingStrategy.prototype.size should work generically on its this and its arguments 
 
index 84294c7de44861691de503d3218461de165d9a7f..855dfeea87fb436b22a52f6495856e6a9cb4ec94 100644 (file)
@@ -1,6 +1,6 @@
 
 FAIL Piping from a ReadableStream from which lots of data are readable synchronously pipeTo is not implemented
-FAIL Piping from a ReadableStream in readable state to a WritableStream in closing state close not implemented
+FAIL Piping from a ReadableStream in readable state to a WritableStream in closing state pipeTo is not implemented
 FAIL Piping from a ReadableStream in readable state to a WritableStream in errored state write not implemented
 FAIL Piping from a ReadableStream in the readable state which becomes closed after pipeTo call to a WritableStream in the writable state pipeTo is not implemented
 FAIL Piping from a ReadableStream in the readable state which becomes errored after pipeTo call to a WritableStream in the writable state pipeTo is not implemented
@@ -17,7 +17,7 @@ FAIL Piping from an empty ReadableStream which becomes errored after a pipeTo ca
 FAIL Piping to a duck-typed asynchronous "writable stream" works pipeTo is not implemented
 FAIL Piping to a stream that has been aborted passes through the error as the cancellation reason pipeTo is not implemented
 FAIL Piping to a stream and then aborting it passes through the error as the cancellation reason pipeTo is not implemented
-FAIL Piping to a stream that has been closed propagates a TypeError cancellation reason backward close not implemented
+FAIL Piping to a stream that has been closed propagates a TypeError cancellation reason backward pipeTo is not implemented
 FAIL Piping to a stream and then closing it propagates a TypeError cancellation reason backward pipeTo is not implemented
 FAIL Piping to a stream that errors on write should pass through the error as the cancellation reason pipeTo is not implemented
 FAIL Piping to a stream that errors on write should not pass through the error if the stream is already closed pipeTo is not implemented
index b08f784363ea4cff4dfeae115103fec3e8135926..9d24281a906451cd190d8bb9adbfab543e8ddcdf 100644 (file)
@@ -7,8 +7,8 @@ PASS Aborting a WritableStream passes through the given reason
 FAIL Aborting a WritableStream puts it in an errored state, with stored error equal to the abort reason write not implemented
 FAIL Aborting a WritableStream causes any outstanding ready promises to be fulfilled immediately write not implemented
 FAIL Aborting a WritableStream causes any outstanding write() promises to be rejected with the abort reason write not implemented
-FAIL Closing but then immediately aborting a WritableStream causes the stream to error close not implemented
-FAIL Closing a WritableStream and aborting it while it closes causes the stream to error close not implemented
-FAIL Aborting a WritableStream after it is closed is a no-op close not implemented
+PASS Closing but then immediately aborting a WritableStream causes the stream to error 
+PASS Closing a WritableStream and aborting it while it closes causes the stream to error 
+PASS Aborting a WritableStream after it is closed is a no-op 
 PASS WritableStream should call underlying sink's close if no abort is supplied 
 
index ce249136e514460cb8f0e2ed98fba19c46c91412..8ece7f15cbe28c3500e1bce723b2ce69d32c0061 100644 (file)
@@ -1,8 +1,8 @@
 
 PASS error argument is given to start method 
 FAIL Underlying sink's write won't be called until start finishes write not implemented
-FAIL Underlying sink's close won't be called until start finishes close not implemented
-FAIL Fulfillment value of ws.close() call must be undefined even if the underlying sink returns a non-undefined value close not implemented
+PASS Underlying sink's close won't be called until start finishes 
+PASS Fulfillment value of ws.close() call must be undefined even if the underlying sink returns a non-undefined value 
 PASS Underlying sink's write or close are never invoked if start throws 
 PASS Underlying sink's write or close are never invoked if the promise returned by start is rejected 
 PASS WritableStream can be constructed with no arguments 
index 7d9bd9b1363d9431c7ef8b1f6a5d3f94d3d7080e..cf0e0736053c6aeb295228f697d66339d58be382 100644 (file)
@@ -1,3 +1,24 @@
+2015-10-27  Xabier Rodriguez Calvar  <calvaris@igalia.com>
+
+        [Streams API] Add close method to writable stream
+        https://bugs.webkit.org/show_bug.cgi?id=150560
+
+        Reviewed by Darin Adler.
+
+        Added the close method which requires three additional writable stream internal functions plus a queuing
+        function to retrieve a value from the queue according to the spec.
+
+        Current test set suffices. Expectations were updated accordingly.
+
+        * Modules/streams/StreamInternals.js:
+        (peekQueueValue):
+        * Modules/streams/WritableStream.js:
+        (close):
+        * Modules/streams/WritableStreamInternals.js:
+        (callOrScheduleWritableStreamAdvanceQueue):
+        (writableStreamAdvanceQueue):
+        (closeWritableStream): Added as per spec.
+
 2015-10-26  Brady Eidson  <beidson@apple.com>
 
         Make IDBKeyData from a struct to a class.
index 63537f7daab7e742e0197ec37f63c583416b6b41..6301ffd40c69eb185cbf23e18c916360e3ce4bdf 100644 (file)
@@ -151,3 +151,11 @@ function enqueueValueWithSize(queue, value, size)
 
     return undefined;
 }
+
+function peekQueueValue(queue)
+{
+    // FIXME
+    // assert(queue.content.length > 0);
+
+    return queue.content[0].value;
+}
index d5c1d312bf14f3d20c60140ffde332ade5a30a8b..feee3fcac807fca89c0e6279549fa0d8a6ed82fb 100644 (file)
@@ -88,7 +88,23 @@ function close()
 {
     "use strict";
 
-    throw new EvalError("close not implemented");
+    if (!@isWritableStream(this))
+        return Promise.reject(new @TypeError("The WritableStream.close method can only be used on instances of WritableStream"));
+
+    if (this.@state === "closed" || this.@state === "closing")
+        return Promise.reject(new @TypeError("Cannot close a WritableString that is closed or closing"));
+
+    if (this.@state === "errored")
+        return Promise.reject(this.@storedError);
+
+    if (this.@state === "waiting")
+        @resolveStreamsPromise(this.@readyPromise, undefined);
+
+    this.@state = "closing";
+    @enqueueValueWithSize(this.@queue, "close", 0);
+    @callOrScheduleWritableStreamAdvanceQueue(this);
+
+    return this.@closedPromise;
 }
 
 function write(chunk)
index 9151fedff0eb827c80d256c61a76e226815e8fa1..a9aee34460f0d96b7483145618c108cd06d94d71 100644 (file)
@@ -73,3 +73,69 @@ function errorWritableStream(e)
     this.@state = "errored";
     return undefined;
 }
+
+function callOrScheduleWritableStreamAdvanceQueue(stream)
+{
+    if (!stream.@started)
+        stream.@startedPromise.then(function() { @writableStreamAdvanceQueue(stream); });
+    else
+        @writableStreamAdvanceQueue(stream);
+
+    return undefined;
+}
+
+function writableStreamAdvanceQueue(stream)
+{
+    if (stream.@queue.content.length === 0 || stream.@writing)
+        return undefined;
+
+    const writeRecord = @peekQueueValue(stream.@queue);
+    if (writeRecord === "close") {
+        // FIXME
+        // assert(stream.@state === "closing");
+        @dequeueValue(stream.@queue);
+        // FIXME
+        // assert(stream.@queue.content.length === 0);
+        @closeWritableStream(stream);
+        return undefined;
+    }
+
+    stream.@writing = true;
+    @promiseInvokeOrNoop(stream.@underlyingSink, "write", [writeRecord.chunk]).then(
+        function() {
+            if (stream.@state === "errored")
+                return;
+            stream.@writing = false;
+            @resolveStreamsPromise(writeRecord.promise, undefined);
+            @dequeueValue(stream.@queue);
+            @syncWritableStreamStateWithQueue(stream);
+            @writableStreamAdvanceQueue(stream);
+        },
+        function(r) {
+            @errorWritableStream.@apply(stream, [r]);
+        }
+    );
+
+    return undefined;
+}
+
+function closeWritableStream(stream)
+{
+    // FIXME
+    // assert(stream.@state === "closing");
+    @promiseInvokeOrNoop(stream.@underlyingSink, "close").then(
+        function() {
+            if (stream.@state === "errored")
+                return;
+            // FIXME
+            // assert(stream.@state === "closing");
+            @resolveStreamsPromise(stream.@closedPromise, undefined);
+            stream.@state = "closed";
+        },
+        function(r) {
+            @errorWritableStream.@apply(stream, [r]);
+        }
+    );
+
+    return undefined;
+}