- Revision
- 210027
- Author
- [email protected]
- Date
- 2016-12-20 11:43:48 -0800 (Tue, 20 Dec 2016)
Log Message
[Readable Streams API] Implement readableByteStreamControllerCallPullIfNeeded()
https://bugs.webkit.org/show_bug.cgi?id=166022
Patch by Romain Bellessort <[email protected]> on 2016-12-20
Reviewed by Youenn Fablet.
Source/WebCore:
Implemented readableByteStreamControllerCallPullIfNeeded(). This function is
in particular called when a new ReadableByteStreamController is created; hence,
ReadableByteStreamController constructor has been updated.
Added 3 tests to check behaviour in case of success/failure of the start and pull functions
associated to the underlyingByteSource.
* Modules/streams/ReadableByteStreamInternals.js:
(privateInitializeReadableByteStreamController): Updated handling of underlyingByteSource
start function (especially with call to readableByteStreamControllerCallPullIfNeeded).
(isReadableStreamBYOBReader): Added.
(readableStreamHasBYOBReader): Added.
(readableStreamHasDefaultReader): Added.
(readableByteStreamControllerCallPullIfNeeded): Added.
* Modules/streams/ReadableStreamInternals.js:
(privateInitializeReadableStreamDefaultController): Added missing asserts.
* bindings/js/WebCoreBuiltinNames.h: Added readIntoRequests.
LayoutTests:
Added 3 tests to check behaviour in case of success/failure of the start and pull functions
associated to the underlyingByteSource.
* streams/readable-byte-stream-controller-expected.txt: Added expectations for new tests.
* streams/readable-byte-stream-controller.js: Added 3 new tests.
Modified Paths
Diff
Modified: trunk/LayoutTests/ChangeLog (210026 => 210027)
--- trunk/LayoutTests/ChangeLog 2016-12-20 18:54:33 UTC (rev 210026)
+++ trunk/LayoutTests/ChangeLog 2016-12-20 19:43:48 UTC (rev 210027)
@@ -1,3 +1,17 @@
+2016-12-20 Romain Bellessort <[email protected]>
+
+
+ [Readable Streams API] Implement readableByteStreamControllerCallPullIfNeeded()
+ https://bugs.webkit.org/show_bug.cgi?id=166022
+
+ Reviewed by Youenn Fablet.
+
+ Added 3 tests to check behaviour in case of success/failure of the start and pull functions
+ associated to the underlyingByteSource.
+
+ * streams/readable-byte-stream-controller-expected.txt: Added expectations for new tests.
+ * streams/readable-byte-stream-controller.js: Added 3 new tests.
+
2016-12-20 Sam Weinig <[email protected]>
[DataCue] Un-prefix DataCue and remove custom bindings
Modified: trunk/LayoutTests/streams/readable-byte-stream-controller-expected.txt (210026 => 210027)
--- trunk/LayoutTests/streams/readable-byte-stream-controller-expected.txt 2016-12-20 18:54:33 UTC (rev 210026)
+++ trunk/LayoutTests/streams/readable-byte-stream-controller-expected.txt 2016-12-20 19:43:48 UTC (rev 210027)
@@ -12,6 +12,9 @@
FAIL Calling read() after a chunk has been enqueued should result in obtaining said chunk ReadableByteStreamController enqueue() is not implemented
PASS By default initial value of desiredSize should be 1
PASS Calling cancel() on a readable ReadableStream that is not locked to a reader should return a promise whose fulfillment handler returns undefined
+PASS Test that pull is called once when a new ReadableStream is created with a ReadableByteStreamController
+PASS Calling cancel after pull has thrown an error should result in a promise rejected with the same error
+PASS Calling cancel after creating a ReadableStream with an underlyingByteStream's start function returning a rejected promise should result in a promise rejected with the same error
PASS Creating a ReadableStream with an underlyingSource with type property set to 'bytes' should succeed
PASS ReadableByteStreamController instances should have the correct list of properties
PASS Calling error() with a this object different from ReadableByteStreamController should throw a TypeError
@@ -25,4 +28,7 @@
FAIL Calling read() after a chunk has been enqueued should result in obtaining said chunk ReadableByteStreamController enqueue() is not implemented
PASS By default initial value of desiredSize should be 1
PASS Calling cancel() on a readable ReadableStream that is not locked to a reader should return a promise whose fulfillment handler returns undefined
+PASS Test that pull is called once when a new ReadableStream is created with a ReadableByteStreamController
+PASS Calling cancel after pull has thrown an error should result in a promise rejected with the same error
+PASS Calling cancel after creating a ReadableStream with an underlyingByteStream's start function returning a rejected promise should result in a promise rejected with the same error
Modified: trunk/LayoutTests/streams/readable-byte-stream-controller.js (210026 => 210027)
--- trunk/LayoutTests/streams/readable-byte-stream-controller.js 2016-12-20 18:54:33 UTC (rev 210026)
+++ trunk/LayoutTests/streams/readable-byte-stream-controller.js 2016-12-20 19:43:48 UTC (rev 210027)
@@ -223,4 +223,68 @@
);
}, "Calling cancel() on a readable ReadableStream that is not locked to a reader should return a promise whose fulfillment handler returns undefined");
+promise_test(function() {
+ let pullCalls = 0;
+ const rs = new ReadableStream({
+ pull: function () {
+ pullCalls++;
+ },
+ type: "bytes"
+ });
+ return new Promise(function(resolve, reject) {
+ setTimeout(function() {
+ if (pullCalls === 1)
+ resolve("ok");
+ else
+ reject("1 call should have been made to pull function");
+ }, 200);
+ });
+}, "Test that pull is called once when a new ReadableStream is created with a ReadableByteStreamController");
+
+promise_test(function() {
+ const myError = new Error("Pull failed");
+ const rs = new ReadableStream({
+ pull: function () {
+ throw myError;
+ },
+ type: "bytes"
+ });
+
+ return new Promise(function(resolve, reject) {
+ setTimeout(function() {
+ rs.cancel().then(
+ function (res) { reject("Cancel should return a promise resolved with rejection"); },
+ function (err) {
+ if (err === myError)
+ resolve();
+ else
+ reject("Reason for rejection should be the error that was thrown in pull");
+ }
+ )
+ }, 200)});
+}, "Calling cancel after pull has thrown an error should result in a promise rejected with the same error");
+
+promise_test(function() {
+ const myError = new Error("Start failed");
+ const rs = new ReadableStream({
+ start: function () {
+ return new Promise(function(resolve, reject) { reject(myError); });
+ },
+ type: "bytes"
+ });
+
+ return new Promise(function(resolve, reject) {
+ setTimeout(function() {
+ rs.cancel().then(
+ function (res) { reject("An error should have been thrown"); },
+ function (err) {
+ if (err === myError)
+ resolve();
+ else
+ reject("Reason for rejection should be the error that led the promise returned by start to fail");
+ }
+ )
+ }, 200)});
+}, "Calling cancel after creating a ReadableStream with an underlyingByteStream's start function returning a rejected promise should result in a promise rejected with the same error");
+
done();
Modified: trunk/Source/WebCore/ChangeLog (210026 => 210027)
--- trunk/Source/WebCore/ChangeLog 2016-12-20 18:54:33 UTC (rev 210026)
+++ trunk/Source/WebCore/ChangeLog 2016-12-20 19:43:48 UTC (rev 210027)
@@ -1,3 +1,28 @@
+2016-12-20 Romain Bellessort <[email protected]>
+
+ [Readable Streams API] Implement readableByteStreamControllerCallPullIfNeeded()
+ https://bugs.webkit.org/show_bug.cgi?id=166022
+
+ Reviewed by Youenn Fablet.
+
+ Implemented readableByteStreamControllerCallPullIfNeeded(). This function is
+ in particular called when a new ReadableByteStreamController is created; hence,
+ ReadableByteStreamController constructor has been updated.
+
+ Added 3 tests to check behaviour in case of success/failure of the start and pull functions
+ associated to the underlyingByteSource.
+
+ * Modules/streams/ReadableByteStreamInternals.js:
+ (privateInitializeReadableByteStreamController): Updated handling of underlyingByteSource
+ start function (especially with call to readableByteStreamControllerCallPullIfNeeded).
+ (isReadableStreamBYOBReader): Added.
+ (readableStreamHasBYOBReader): Added.
+ (readableStreamHasDefaultReader): Added.
+ (readableByteStreamControllerCallPullIfNeeded): Added.
+ * Modules/streams/ReadableStreamInternals.js:
+ (privateInitializeReadableStreamDefaultController): Added missing asserts.
+ * bindings/js/WebCoreBuiltinNames.h: Added readIntoRequests.
+
2016-12-20 Sam Weinig <[email protected]>
[DataCue] Un-prefix DataCue and remove custom bindings
Modified: trunk/Source/WebCore/Modules/streams/ReadableByteStreamInternals.js (210026 => 210027)
--- trunk/Source/WebCore/Modules/streams/ReadableByteStreamInternals.js 2016-12-20 18:54:33 UTC (rev 210026)
+++ trunk/Source/WebCore/Modules/streams/ReadableByteStreamInternals.js 2016-12-20 19:43:48 UTC (rev 210027)
@@ -66,9 +66,10 @@
controller.@started = true;
@assert(!controller.@pulling);
@assert(!controller.@pullAgain);
- // FIXME: Implement readableByteStreamControllerCallPullIfNeed.
+ @readableByteStreamControllerCallPullIfNeeded(controller);
}, (error) => {
- // FIXME: Implement readableByteStreamControllerError.
+ if (stream.@state === @streamReadable)
+ @readableByteStreamControllerError(controller, error);
});
this.@cancel = @readableByteStreamControllerCancel;
@@ -86,6 +87,16 @@
return @isObject(controller) && !!controller.@underlyingByteSource;
}
+function isReadableStreamBYOBReader(reader)
+{
+ "use strict";
+
+ // FIXME: Since BYOBReader is not yet implemented, always return false.
+ // To be implemented at the same time as BYOBReader (see isReadableStreamDefaultReader
+ // to apply same model).
+ return false;
+}
+
function readableByteStreamControllerCancel(controller, reason)
{
"use strict";
@@ -143,3 +154,49 @@
return controller.@strategyHWM - controller.@totalQueuedBytes;
}
+
+function readableStreamHasBYOBReader(stream)
+{
+ "use strict";
+
+ return stream.@reader !== @undefined && @isReadableStreamBYOBReader(stream.@reader);
+}
+
+function readableStreamHasDefaultReader(stream)
+{
+ "use strict";
+
+ return stream.@reader !== @undefined && @isReadableStreamDefaultReader(stream.@reader);
+}
+
+function readableByteStreamControllerCallPullIfNeeded(controller)
+{
+ "use strict";
+
+ const stream = controller.@controlledReadableStream;
+
+ if (stream.@state !== @streamReadable)
+ return;
+ if (controller.@closeRequested)
+ return;
+ if (!@readableStreamHasDefaultReader(stream) || stream.@reader.@readRequests <= 0)
+ if (!@readableStreamHasBYOBReader(stream) || stream.@reader.@readIntoRequests <= 0)
+ if (@readableByteStreamControllerGetDesiredSize(controller) <= 0)
+ return;
+ if (controller.@pulling) {
+ controller.@pullAgain = true;
+ return;
+ }
+ @assert(!controller.@pullAgain);
+ controller.@pulling = true;
+ @promiseInvokeOrNoop(controller.@underlyingByteSource, "pull", [controller]).@then(() => {
+ controller.@pulling = false;
+ if (controller.@pullAgain) {
+ controller.@pullAgain = false;
+ @readableByteStreamControllerCallPullIfNeeded(controller);
+ }
+ }, (error) => {
+ if (controller.@controlledReadableStream.@state === @streamReadable)
+ @readableByteStreamControllerError(controller, error);
+ });
+}
Modified: trunk/Source/WebCore/Modules/streams/ReadableStreamInternals.js (210026 => 210027)
--- trunk/Source/WebCore/Modules/streams/ReadableStreamInternals.js 2016-12-20 18:54:33 UTC (rev 210026)
+++ trunk/Source/WebCore/Modules/streams/ReadableStreamInternals.js 2016-12-20 19:43:48 UTC (rev 210027)
@@ -79,8 +79,10 @@
this.@strategy = @validateAndNormalizeQueuingStrategy(size, highWaterMark);
const controller = this;
- const startResult = @promiseInvokeOrNoopNoCatch(underlyingSource, "start", [this]).@then(() => {
+ @promiseInvokeOrNoopNoCatch(underlyingSource, "start", [this]).@then(() => {
controller.@started = true;
+ @assert(!controller.@pulling);
+ @assert(!controller.@pullAgain);
@readableStreamDefaultControllerCallPullIfNeeded(controller);
}, (error) => {
if (stream.@state === @streamReadable)
Modified: trunk/Source/WebCore/bindings/js/WebCoreBuiltinNames.h (210026 => 210027)
--- trunk/Source/WebCore/bindings/js/WebCoreBuiltinNames.h 2016-12-20 18:54:33 UTC (rev 210026)
+++ trunk/Source/WebCore/bindings/js/WebCoreBuiltinNames.h 2016-12-20 19:43:48 UTC (rev 210027)
@@ -73,6 +73,7 @@
macro(queuedSetLocalDescription) \
macro(queuedSetRemoteDescription) \
macro(reader) \
+ macro(readIntoRequests) \
macro(readRequests) \
macro(readableStreamController) \
macro(readyPromiseCapability) \