Title: [221437] trunk
Revision
221437
Author
commit-qu...@webkit.org
Date
2017-08-31 13:03:42 -0700 (Thu, 31 Aug 2017)

Log Message

Add support for Request body stream cloning
https://bugs.webkit.org/show_bug.cgi?id=176148

Patch by Youenn Fablet <you...@apple.com> on 2017-08-31
Reviewed by Alex Christensen.

Source/WebCore:

Tests: http/wpt/fetch/request-clone.html
       http/wpt/fetch/request-consume-stream.html
       http/wpt/fetch/request-stream-disturbed-1.html
       http/wpt/fetch/request-stream-disturbed-2.html
       http/wpt/fetch/request-stream-disturbed-3.html

Adding support for ReadableStream teeing for cloning fetch bodies.
Adding support for pushing request body data to its ReadableStream.
Renamed FetchResponseSource to FetchBodySource for that purpose.

Tests extracting body from a ReadableStream through JS API pass.
Tests extracting data stored in a ReadableStream to resolve fetch body promises are failing.
There is no support yet, this will be added as a follow-up.

* CMakeLists.txt:
* Modules/fetch/FetchBody.cpp:
(WebCore::FetchBody::consume):
(WebCore::FetchBody::consumeAsStream):
(WebCore::FetchBody::clone):
* Modules/fetch/FetchBody.h:
* Modules/fetch/FetchBodyConsumer.h:
* Modules/fetch/FetchBodyOwner.cpp:
(WebCore::FetchBodyOwner::cloneBody):
(WebCore::FetchBodyOwner::loadBlob):
(WebCore::FetchBodyOwner::readableStream):
(WebCore::FetchBodyOwner::consumeBodyAsStream):
* Modules/fetch/FetchBodyOwner.h:
(WebCore::FetchBodyOwner::feedStream):
(WebCore::FetchBodyOwner::cancel):
* Modules/fetch/FetchBodySource.cpp: Renamed from Source/WebCore/Modules/fetch/FetchResponseSource.cpp.
* Modules/fetch/FetchBodySource.h: Renamed from Source/WebCore/Modules/fetch/FetchResponseSource.h.
* Modules/fetch/FetchResponse.cpp:
(WebCore::FetchResponse::consumeBodyAsStream):
(WebCore::FetchResponse::createReadableStream):
* Modules/fetch/FetchResponse.h:
* Modules/fetch/FetchResponse.idl:
* Modules/fetch/FetchResponse.js:
(getter.body):
(clone):
* WebCore.xcodeproj/project.pbxproj:
* bindings/js/ReadableStream.cpp:
(WebCore::ReadableStream::tee):
* bindings/js/ReadableStream.h:
* bindings/js/WebCoreBuiltinNames.h:

LayoutTests:

* http/wpt/fetch/request-clone-expected.txt: Added.
* http/wpt/fetch/request-clone.html: Added.
* http/wpt/fetch/request-consume-stream-expected.txt: Added.
* http/wpt/fetch/request-consume-stream.html: Added.
* http/wpt/fetch/request-stream-disturbed-1-expected.txt: Added.
* http/wpt/fetch/request-stream-disturbed-1.html: Added.
* http/wpt/fetch/request-stream-disturbed-2-expected.txt: Added.
* http/wpt/fetch/request-stream-disturbed-2.html: Added.
* http/wpt/fetch/request-stream-disturbed-3-expected.txt: Added.
* http/wpt/fetch/request-stream-disturbed-3.html: Added.

Modified Paths

Added Paths

Removed Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (221436 => 221437)


--- trunk/LayoutTests/ChangeLog	2017-08-31 19:51:08 UTC (rev 221436)
+++ trunk/LayoutTests/ChangeLog	2017-08-31 20:03:42 UTC (rev 221437)
@@ -1,3 +1,21 @@
+2017-08-31  Youenn Fablet  <you...@apple.com>
+
+        Add support for Request body stream cloning
+        https://bugs.webkit.org/show_bug.cgi?id=176148
+
+        Reviewed by Alex Christensen.
+
+        * http/wpt/fetch/request-clone-expected.txt: Added.
+        * http/wpt/fetch/request-clone.html: Added.
+        * http/wpt/fetch/request-consume-stream-expected.txt: Added.
+        * http/wpt/fetch/request-consume-stream.html: Added.
+        * http/wpt/fetch/request-stream-disturbed-1-expected.txt: Added.
+        * http/wpt/fetch/request-stream-disturbed-1.html: Added.
+        * http/wpt/fetch/request-stream-disturbed-2-expected.txt: Added.
+        * http/wpt/fetch/request-stream-disturbed-2.html: Added.
+        * http/wpt/fetch/request-stream-disturbed-3-expected.txt: Added.
+        * http/wpt/fetch/request-stream-disturbed-3.html: Added.
+
 2017-08-31  Carlos Alberto Lopez Perez  <clo...@igalia.com>
 
         [GTK][WPE] Mark test media/event-queue-crash as flaky

Added: trunk/LayoutTests/http/wpt/fetch/request-clone-expected.txt (0 => 221437)


--- trunk/LayoutTests/http/wpt/fetch/request-clone-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/wpt/fetch/request-clone-expected.txt	2017-08-31 20:03:42 UTC (rev 221437)
@@ -0,0 +1,15 @@
+
+PASS Check orginal request's body after cloning 
+PASS Check cloned request's body 
+PASS Check request clone use structureClone for teed ReadableStreams (Int8Arraychunk) 
+PASS Check request clone use structureClone for teed ReadableStreams (Int16Arraychunk) 
+PASS Check request clone use structureClone for teed ReadableStreams (Int32Arraychunk) 
+PASS Check request clone use structureClone for teed ReadableStreams (ArrayBufferchunk) 
+PASS Check request clone use structureClone for teed ReadableStreams (Uint8Arraychunk) 
+PASS Check request clone use structureClone for teed ReadableStreams (Uint8ClampedArraychunk) 
+PASS Check request clone use structureClone for teed ReadableStreams (Uint16Arraychunk) 
+PASS Check request clone use structureClone for teed ReadableStreams (Uint32Arraychunk) 
+PASS Check request clone use structureClone for teed ReadableStreams (Float32Arraychunk) 
+PASS Check request clone use structureClone for teed ReadableStreams (Float64Arraychunk) 
+PASS Check request clone use structureClone for teed ReadableStreams (DataViewchunk) 
+

Added: trunk/LayoutTests/http/wpt/fetch/request-clone.html (0 => 221437)


--- trunk/LayoutTests/http/wpt/fetch/request-clone.html	                        (rev 0)
+++ trunk/LayoutTests/http/wpt/fetch/request-clone.html	2017-08-31 20:03:42 UTC (rev 221437)
@@ -0,0 +1,70 @@
+<!doctype html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title>Request clone</title>
+    <meta name="help" href=""
+    <script src=""
+    <script src=""
+  </head>
+  <body>
+    <script src=""
+    <script>
+var body = "This is request body";
+var headersInit = { "name" : "value" };
+var requestInit  = { "body" : body,
+                     "method" : "POST",
+                     "headers" : headersInit
+};
+var request = new Request("", requestInit);
+var clonedRequest = request.clone();
+
+promise_test(function(test) {
+    return validateStreamFromString(request.body.getReader(), body);
+}, "Check orginal request's body after cloning");
+
+promise_test(function(test) {
+    return validateStreamFromString(clonedRequest.body.getReader(), body);
+}, "Check cloned request's body");
+
+function testReadableStreamClone(initialBuffer, bufferType)
+{
+    promise_test(function(test) {
+        var request = new Request("", {"method" : "POST", "body" : new ReadableStream({start : function(controller) {
+            controller.enqueue(initialBuffer);
+            controller.close();
+        }})});
+
+        var clone = request.clone();
+        var stream1 = request.body;
+        var stream2 = clone.body;
+
+        var buffer;
+        return stream1.getReader().read().then(function(data) {
+            assert_false(data.done);
+            assert_true(data.value === initialBuffer, "Buffer of being-cloned response stream is the same as the original buffer");
+            return stream2.getReader().read();
+        }).then(function(data) {
+            assert_false(data.done);
+            assert_array_equals(data.value, initialBuffer, "Cloned buffer chunks have the same content");
+            assert_equals(Object.getPrototypeOf(data.value), Object.getPrototypeOf(initialBuffer), "Cloned buffers have the same type");
+            assert_true(data.value !== initialBuffer, "Buffer of cloned response stream is a clone of the original buffer");
+        });
+    }, "Check request clone use structureClone for teed ReadableStreams (" + bufferType  + "chunk)");
+}
+
+var arrayBuffer = new ArrayBuffer(16);
+testReadableStreamClone(new Int8Array(arrayBuffer, 1), "Int8Array");
+testReadableStreamClone(new Int16Array(arrayBuffer, 2, 2), "Int16Array");
+testReadableStreamClone(new Int32Array(arrayBuffer), "Int32Array");
+testReadableStreamClone(arrayBuffer, "ArrayBuffer");
+testReadableStreamClone(new Uint8Array(arrayBuffer), "Uint8Array");
+testReadableStreamClone(new Uint8ClampedArray(arrayBuffer), "Uint8ClampedArray");
+testReadableStreamClone(new Uint16Array(arrayBuffer, 2), "Uint16Array");
+testReadableStreamClone(new Uint32Array(arrayBuffer), "Uint32Array");
+testReadableStreamClone(new Float32Array(arrayBuffer), "Float32Array");
+testReadableStreamClone(new Float64Array(arrayBuffer), "Float64Array");
+testReadableStreamClone(new DataView(arrayBuffer, 2, 8), "DataView");
+    </script>
+  </body>
+</html>

Added: trunk/LayoutTests/http/wpt/fetch/request-consume-stream-expected.txt (0 => 221437)


--- trunk/LayoutTests/http/wpt/fetch/request-consume-stream-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/wpt/fetch/request-consume-stream-expected.txt	2017-08-31 20:03:42 UTC (rev 221437)
@@ -0,0 +1,9 @@
+
+FAIL Read empty text request's body as readableStream assert_array_equals: Retrieve and verify stream lengths differ, expected 0 got 16
+FAIL Read empty blob request's body as readableStream assert_array_equals: Retrieve and verify stream lengths differ, expected 0 got 16
+FAIL Read blob request's body as readableStream assert_array_equals: Retrieve and verify stream lengths differ, expected 24 got 16
+FAIL Read text request's body as readableStream assert_array_equals: Retrieve and verify stream lengths differ, expected 24 got 16
+FAIL Read URLSearchParams request's body as readableStream assert_array_equals: Retrieve and verify stream lengths differ, expected 10 got 16
+FAIL Read array buffer request's body as readableStream assert_array_equals: Retrieve and verify stream lengths differ, expected 24 got 16
+FAIL Read form data request's body as readableStream assert_array_equals: Retrieve and verify stream lengths differ, expected 10 got 16
+

Added: trunk/LayoutTests/http/wpt/fetch/request-consume-stream.html (0 => 221437)


--- trunk/LayoutTests/http/wpt/fetch/request-consume-stream.html	                        (rev 0)
+++ trunk/LayoutTests/http/wpt/fetch/request-consume-stream.html	2017-08-31 20:03:42 UTC (rev 221437)
@@ -0,0 +1,67 @@
+<!doctype html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title>Request consume</title>
+    <meta name="help" href=""
+    <meta name="help" href=""
+    <script src=""
+    <script src=""
+    <script src=""
+  </head>
+  <body>
+    <script>
+function createRequestWithBody(body)
+{
+    return new Request("", {body: "{\"key\": \"value\"}", method: "POST"});
+}
+
+promise_test(function(test) {
+    var body = "";
+    var request = createRequestWithBody("");
+    return validateStreamFromString(request.body.getReader(), "");
+}, "Read empty text request's body as readableStream");
+
+promise_test(function(test) {
+    var request = createRequestWithBody(new Blob([], { "type" : "text/plain" }));
+    return validateStreamFromString(request.body.getReader(), "");
+}, "Read empty blob request's body as readableStream");
+
+var formData = new FormData();
+formData.append("name", "value");
+var textData = JSON.stringify("This is request's body");
+var blob = new Blob([textData], { "type" : "text/plain" });
+var urlSearchParamsData = "name=value";
+var urlSearchParams = new URLSearchParams(urlSearchParamsData);
+
+promise_test(function(test) {
+    var request = createRequestWithBody(blob);
+    return validateStreamFromString(request.body.getReader(), textData);
+}, "Read blob request's body as readableStream");
+
+promise_test(function(test) {
+    var request = createRequestWithBody(textData);
+    return validateStreamFromString(request.body.getReader(), textData);
+}, "Read text request's body as readableStream");
+
+promise_test(function(test) {
+    var request = createRequestWithBody(urlSearchParams);
+    return validateStreamFromString(request.body.getReader(), urlSearchParamsData);
+}, "Read URLSearchParams request's body as readableStream");
+
+promise_test(function(test) {
+    var arrayBuffer = new ArrayBuffer(textData.length);
+    var int8Array = new Int8Array(arrayBuffer);
+    for (var cptr = 0; cptr < textData.length; cptr++)
+        int8Array[cptr] = textData.charCodeAt(cptr);
+
+    return validateStreamFromString(createRequestWithBody(arrayBuffer).body.getReader(), textData);
+}, "Read array buffer request's body as readableStream");
+
+promise_test(function(test) {
+    var request = createRequestWithBody(formData);
+    return validateStreamFromString(request.body.getReader(), "name=value");
+}, "Read form data request's body as readableStream");
+    </script>
+  </body>
+</html>

Added: trunk/LayoutTests/http/wpt/fetch/request-stream-disturbed-1-expected.txt (0 => 221437)


--- trunk/LayoutTests/http/wpt/fetch/request-stream-disturbed-1-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/wpt/fetch/request-stream-disturbed-1-expected.txt	2017-08-31 20:03:42 UTC (rev 221437)
@@ -0,0 +1,6 @@
+
+PASS Getting blob after getting the Request body - not disturbed, not locked 
+FAIL Getting text after getting the Request body - not disturbed, not locked assert_true: expected true got false
+FAIL Getting json after getting the Request body - not disturbed, not locked promise_test: Unhandled rejection with value: object "SyntaxError: The string did not match the expected pattern."
+FAIL Getting arrayBuffer after getting the Request body - not disturbed, not locked assert_true: expected true got false
+

Added: trunk/LayoutTests/http/wpt/fetch/request-stream-disturbed-1.html (0 => 221437)


--- trunk/LayoutTests/http/wpt/fetch/request-stream-disturbed-1.html	                        (rev 0)
+++ trunk/LayoutTests/http/wpt/fetch/request-stream-disturbed-1.html	2017-08-31 20:03:42 UTC (rev 221437)
@@ -0,0 +1,53 @@
+<!doctype html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title>Consuming Request body after getting a ReadableStream</title>
+    <meta name="help" href=""
+    <script src=""
+    <script src=""
+  </head>
+  <body>
+    <script>
+function createRequestWithReadableStream(callback) {
+    var request = new Request("", {body: "{\"key\": \"value\"}", method: "POST"});
+    var reader = request.body.getReader();
+    reader.releaseLock();
+    return callback(request);
+}
+
+promise_test(function() {
+    return createRequestWithReadableStream(function(request) {
+        return request.blob().then(function(blob) {
+            assert_true(blob instanceof Blob);
+        });
+    });
+}, "Getting blob after getting the Request body - not disturbed, not locked");
+
+promise_test(function() {
+    return createRequestWithReadableStream(function(request) {
+        return request.text().then(function(text) {
+            assert_true(text.length > 0);
+        });
+    });
+}, "Getting text after getting the Request body - not disturbed, not locked");
+
+promise_test(function() {
+    return createRequestWithReadableStream(function(request) {
+        return request.json().then(function(json) {
+            assert_true(typeof json === "object");
+        });
+    });
+}, "Getting json after getting the Request body - not disturbed, not locked");
+
+promise_test(function() {
+    return createRequestWithReadableStream(function(request) {
+        return request.arrayBuffer().then(function(arrayBuffer) {
+            assert_true(arrayBuffer.byteLength > 0);
+        });
+    });
+}, "Getting arrayBuffer after getting the Request body - not disturbed, not locked");
+
+    </script>
+  </body>
+</html>

Added: trunk/LayoutTests/http/wpt/fetch/request-stream-disturbed-2-expected.txt (0 => 221437)


--- trunk/LayoutTests/http/wpt/fetch/request-stream-disturbed-2-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/wpt/fetch/request-stream-disturbed-2-expected.txt	2017-08-31 20:03:42 UTC (rev 221437)
@@ -0,0 +1,6 @@
+
+FAIL Getting blob after getting a locked Request body assert_unreached: Should have rejected: undefined Reached unreachable code
+FAIL Getting text after getting a locked Request body assert_unreached: Should have rejected: undefined Reached unreachable code
+FAIL Getting json after getting a locked Request body assert_throws: function "function () { throw e }" threw object "SyntaxError: The string did not match the expected pattern." ("SyntaxError") expected object "TypeError" ("TypeError")
+FAIL Getting arrayBuffer after getting a locked Request body assert_unreached: Should have rejected: undefined Reached unreachable code
+

Added: trunk/LayoutTests/http/wpt/fetch/request-stream-disturbed-2.html (0 => 221437)


--- trunk/LayoutTests/http/wpt/fetch/request-stream-disturbed-2.html	                        (rev 0)
+++ trunk/LayoutTests/http/wpt/fetch/request-stream-disturbed-2.html	2017-08-31 20:03:42 UTC (rev 221437)
@@ -0,0 +1,43 @@
+<!doctype html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title>Consuming Request body after getting a ReadableStream</title>
+    <script src=""
+    <script src=""
+  </head>
+  <body>
+    <script>
+function createRequestWithLockedReadableStream(callback) {
+    var request = new Request("", {body: "{\"key\": \"value\"}", method: "POST"});
+    var reader = request.body.getReader();
+    return callback(request);
+}
+
+promise_test(function(test) {
+    return createRequestWithLockedReadableStream(function(request) {
+        return promise_rejects(test, new TypeError(), request.blob());
+    });
+}, "Getting blob after getting a locked Request body");
+
+promise_test(function(test) {
+    return createRequestWithLockedReadableStream(function(request) {
+        return promise_rejects(test, new TypeError(), request.text());
+    });
+}, "Getting text after getting a locked Request body");
+
+promise_test(function(test) {
+    return createRequestWithLockedReadableStream(function(request) {
+        return promise_rejects(test, new TypeError(), request.json());
+    });
+}, "Getting json after getting a locked Request body");
+
+promise_test(function(test) {
+    return createRequestWithLockedReadableStream(function(request) {
+        return promise_rejects(test, new TypeError(), request.arrayBuffer());
+    });
+}, "Getting arrayBuffer after getting a locked Request body");
+
+    </script>
+  </body>
+</html>

Added: trunk/LayoutTests/http/wpt/fetch/request-stream-disturbed-3-expected.txt (0 => 221437)


--- trunk/LayoutTests/http/wpt/fetch/request-stream-disturbed-3-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/wpt/fetch/request-stream-disturbed-3-expected.txt	2017-08-31 20:03:42 UTC (rev 221437)
@@ -0,0 +1,6 @@
+
+FAIL Getting blob after reading the Request body assert_unreached: Should have rejected: undefined Reached unreachable code
+FAIL Getting text after reading the Request body assert_unreached: Should have rejected: undefined Reached unreachable code
+FAIL Getting json after reading the Request body assert_throws: function "function () { throw e }" threw object "SyntaxError: The string did not match the expected pattern." ("SyntaxError") expected object "TypeError" ("TypeError")
+FAIL Getting arrayBuffer after reading the Request body assert_unreached: Should have rejected: undefined Reached unreachable code
+

Added: trunk/LayoutTests/http/wpt/fetch/request-stream-disturbed-3.html (0 => 221437)


--- trunk/LayoutTests/http/wpt/fetch/request-stream-disturbed-3.html	                        (rev 0)
+++ trunk/LayoutTests/http/wpt/fetch/request-stream-disturbed-3.html	2017-08-31 20:03:42 UTC (rev 221437)
@@ -0,0 +1,45 @@
+<!doctype html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title>Consuming Request body after getting a ReadableStream</title>
+    <script src=""
+    <script src=""
+  </head>
+  <body>
+    <script>
+
+function createRequestWithDisturbedReadableStream(callback) {
+    var request = new Request("", {body: "{\"key\": \"value\"}", method: "POST"});
+    var reader = request.body.getReader();
+    reader.read();
+    return callback(request);
+}
+
+promise_test(function(test) {
+    return createRequestWithDisturbedReadableStream(function(request) {
+        return promise_rejects(test, new TypeError(), request.blob());
+    });
+}, "Getting blob after reading the Request body");
+
+promise_test(function(test) {
+    return createRequestWithDisturbedReadableStream(function(request) {
+        return promise_rejects(test, new TypeError(), request.text());
+    });
+}, "Getting text after reading the Request body");
+
+promise_test(function(test) {
+    return createRequestWithDisturbedReadableStream(function(request) {
+        return promise_rejects(test, new TypeError(), request.json());
+    });
+}, "Getting json after reading the Request body");
+
+promise_test(function(test) {
+    return createRequestWithDisturbedReadableStream(function(request) {
+        return promise_rejects(test, new TypeError(), request.arrayBuffer());
+    });
+}, "Getting arrayBuffer after reading the Request body");
+
+    </script>
+  </body>
+</html>

Modified: trunk/Source/WebCore/CMakeLists.txt (221436 => 221437)


--- trunk/Source/WebCore/CMakeLists.txt	2017-08-31 19:51:08 UTC (rev 221436)
+++ trunk/Source/WebCore/CMakeLists.txt	2017-08-31 20:03:42 UTC (rev 221437)
@@ -936,11 +936,11 @@
     Modules/fetch/FetchBody.cpp
     Modules/fetch/FetchBodyConsumer.cpp
     Modules/fetch/FetchBodyOwner.cpp
+    Modules/fetch/FetchBodySource.cpp
     Modules/fetch/FetchHeaders.cpp
     Modules/fetch/FetchLoader.cpp
     Modules/fetch/FetchRequest.cpp
     Modules/fetch/FetchResponse.cpp
-    Modules/fetch/FetchResponseSource.cpp
     Modules/fetch/WorkerGlobalScopeFetch.cpp
 
     Modules/geolocation/Coordinates.cpp

Modified: trunk/Source/WebCore/ChangeLog (221436 => 221437)


--- trunk/Source/WebCore/ChangeLog	2017-08-31 19:51:08 UTC (rev 221436)
+++ trunk/Source/WebCore/ChangeLog	2017-08-31 20:03:42 UTC (rev 221437)
@@ -1,3 +1,55 @@
+2017-08-31  Youenn Fablet  <you...@apple.com>
+
+        Add support for Request body stream cloning
+        https://bugs.webkit.org/show_bug.cgi?id=176148
+
+        Reviewed by Alex Christensen.
+
+        Tests: http/wpt/fetch/request-clone.html
+               http/wpt/fetch/request-consume-stream.html
+               http/wpt/fetch/request-stream-disturbed-1.html
+               http/wpt/fetch/request-stream-disturbed-2.html
+               http/wpt/fetch/request-stream-disturbed-3.html
+
+        Adding support for ReadableStream teeing for cloning fetch bodies.
+        Adding support for pushing request body data to its ReadableStream.
+        Renamed FetchResponseSource to FetchBodySource for that purpose.
+
+        Tests extracting body from a ReadableStream through JS API pass.
+        Tests extracting data stored in a ReadableStream to resolve fetch body promises are failing.
+        There is no support yet, this will be added as a follow-up.
+
+        * CMakeLists.txt:
+        * Modules/fetch/FetchBody.cpp:
+        (WebCore::FetchBody::consume):
+        (WebCore::FetchBody::consumeAsStream):
+        (WebCore::FetchBody::clone):
+        * Modules/fetch/FetchBody.h:
+        * Modules/fetch/FetchBodyConsumer.h:
+        * Modules/fetch/FetchBodyOwner.cpp:
+        (WebCore::FetchBodyOwner::cloneBody):
+        (WebCore::FetchBodyOwner::loadBlob):
+        (WebCore::FetchBodyOwner::readableStream):
+        (WebCore::FetchBodyOwner::consumeBodyAsStream):
+        * Modules/fetch/FetchBodyOwner.h:
+        (WebCore::FetchBodyOwner::feedStream):
+        (WebCore::FetchBodyOwner::cancel):
+        * Modules/fetch/FetchBodySource.cpp: Renamed from Source/WebCore/Modules/fetch/FetchResponseSource.cpp.
+        * Modules/fetch/FetchBodySource.h: Renamed from Source/WebCore/Modules/fetch/FetchResponseSource.h.
+        * Modules/fetch/FetchResponse.cpp:
+        (WebCore::FetchResponse::consumeBodyAsStream):
+        (WebCore::FetchResponse::createReadableStream):
+        * Modules/fetch/FetchResponse.h:
+        * Modules/fetch/FetchResponse.idl:
+        * Modules/fetch/FetchResponse.js:
+        (getter.body):
+        (clone):
+        * WebCore.xcodeproj/project.pbxproj:
+        * bindings/js/ReadableStream.cpp:
+        (WebCore::ReadableStream::tee):
+        * bindings/js/ReadableStream.h:
+        * bindings/js/WebCoreBuiltinNames.h:
+
 2017-08-31  Chris Dumez  <cdu...@apple.com>
 
         Use WTF::crossThreadCopy() in more places

Modified: trunk/Source/WebCore/Modules/fetch/FetchBody.cpp (221436 => 221437)


--- trunk/Source/WebCore/Modules/fetch/FetchBody.cpp	2017-08-31 19:51:08 UTC (rev 221436)
+++ trunk/Source/WebCore/Modules/fetch/FetchBody.cpp	2017-08-31 20:03:42 UTC (rev 221437)
@@ -31,8 +31,8 @@
 
 #include "Document.h"
 #include "FetchBodyOwner.h"
+#include "FetchBodySource.h"
 #include "FetchHeaders.h"
-#include "FetchResponseSource.h"
 #include "HTTPHeaderValues.h"
 #include "HTTPParsers.h"
 #include "ReadableStreamSource.h"
@@ -137,11 +137,12 @@
         promise->reject();
         return;
     }
+
     m_consumer.resolve(WTFMove(promise));
 }
 
 #if ENABLE(STREAMS_API)
-void FetchBody::consumeAsStream(FetchBodyOwner& owner, FetchResponseSource& source)
+void FetchBody::consumeAsStream(FetchBodyOwner& owner, FetchBodySource& source)
 {
     bool closeStream = false;
     if (isArrayBuffer()) {
@@ -270,7 +271,7 @@
     return nullptr;
 }
 
-FetchBody FetchBody::clone() const
+FetchBody FetchBody::clone()
 {
     FetchBody clone(m_consumer);
 
@@ -286,6 +287,12 @@
         clone.m_data = textBody();
     else if (isURLSearchParams())
         clone.m_data = urlSearchParamsBody();
+
+    if (m_readableStream) {
+        auto clones = m_readableStream->tee();
+        m_readableStream = WTFMove(clones.first);
+        clone.m_readableStream = WTFMove(clones.second);
+    }
     return clone;
 }
 

Modified: trunk/Source/WebCore/Modules/fetch/FetchBody.h (221436 => 221437)


--- trunk/Source/WebCore/Modules/fetch/FetchBody.h	2017-08-31 19:51:08 UTC (rev 221436)
+++ trunk/Source/WebCore/Modules/fetch/FetchBody.h	2017-08-31 20:03:42 UTC (rev 221437)
@@ -39,7 +39,7 @@
 namespace WebCore {
 
 class FetchBodyOwner;
-class FetchResponseSource;
+class FetchBodySource;
 class ScriptExecutionContext;
 
 class FetchBody {
@@ -51,7 +51,7 @@
     void formData(FetchBodyOwner&, Ref<DeferredPromise>&& promise) { promise.get().reject(NotSupportedError); }
 
 #if ENABLE(STREAMS_API)
-    void consumeAsStream(FetchBodyOwner&, FetchResponseSource&);
+    void consumeAsStream(FetchBodyOwner&, FetchBodySource&);
 #endif
 
     bool isBlob() const { return WTF::holds_alternative<Ref<const Blob>>(m_data); }
@@ -80,7 +80,7 @@
     void consumeOnceLoadingFinished(FetchBodyConsumer::Type, Ref<DeferredPromise>&&, const String&);
     void cleanConsumer() { m_consumer.clean(); }
 
-    FetchBody clone() const;
+    FetchBody clone();
     ReadableStream* readableStream() { return m_readableStream.get(); }
     void setReadableStream(Ref<ReadableStream>&& stream)
     {

Modified: trunk/Source/WebCore/Modules/fetch/FetchBodyOwner.cpp (221436 => 221437)


--- trunk/Source/WebCore/Modules/fetch/FetchBodyOwner.cpp	2017-08-31 19:51:08 UTC (rev 221436)
+++ trunk/Source/WebCore/Modules/fetch/FetchBodyOwner.cpp	2017-08-31 20:03:42 UTC (rev 221437)
@@ -100,7 +100,7 @@
     m_body->blob(*this, WTFMove(promise), m_contentType);
 }
 
-void FetchBodyOwner::cloneBody(const FetchBodyOwner& owner)
+void FetchBodyOwner::cloneBody(FetchBodyOwner& owner)
 {
     m_contentType = owner.m_contentType;
     if (owner.isBodyNull())
@@ -200,7 +200,6 @@
 void FetchBodyOwner::loadBlob(const Blob& blob, FetchBodyConsumer* consumer)
 {
     // Can only be called once for a body instance.
-    ASSERT(isDisturbed());
     ASSERT(!m_blobLoader);
     ASSERT(!isBodyNull());
 
@@ -293,10 +292,21 @@
     if (isBodyNull())
         return nullptr;
 
-    if (!m_body->hasReadableStream())
+    if (!m_body->hasReadableStream()) {
+        ASSERT(!m_readableStreamSource);
+        m_readableStreamSource = adoptRef(*new FetchBodySource(*this));
         m_body->setReadableStream(ReadableStream::create(state, m_readableStreamSource));
-
+    }
     return m_body->readableStream();
 }
 
+void FetchBodyOwner::consumeBodyAsStream()
+{
+    ASSERT(m_readableStreamSource);
+
+    body().consumeAsStream(*this, *m_readableStreamSource);
+    if (!m_readableStreamSource->isPulling())
+        m_readableStreamSource = nullptr;
+}
+
 } // namespace WebCore

Modified: trunk/Source/WebCore/Modules/fetch/FetchBodyOwner.h (221436 => 221437)


--- trunk/Source/WebCore/Modules/fetch/FetchBodyOwner.h	2017-08-31 19:51:08 UTC (rev 221436)
+++ trunk/Source/WebCore/Modules/fetch/FetchBodyOwner.h	2017-08-31 20:03:42 UTC (rev 221437)
@@ -30,10 +30,10 @@
 
 #include "ActiveDOMObject.h"
 #include "FetchBody.h"
+#include "FetchBodySource.h"
 #include "FetchHeaders.h"
 #include "FetchLoader.h"
 #include "FetchLoaderClient.h"
-#include "FetchResponseSource.h"
 
 namespace WebCore {
 
@@ -41,8 +41,6 @@
 public:
     FetchBodyOwner(ScriptExecutionContext&, std::optional<FetchBody>&&, Ref<FetchHeaders>&&);
 
-    // Exposed Body API
-    // FIXME: Missing body attribute returning a ReadableStream.
     bool bodyUsed() const { return isDisturbed(); }
     void arrayBuffer(Ref<DeferredPromise>&&);
     void blob(Ref<DeferredPromise>&&);
@@ -60,11 +58,17 @@
     RefPtr<ReadableStream> readableStream(JSC::ExecState&);
     virtual bool hasReadableStreamBody() const { return m_body && m_body->hasReadableStream(); }
 
+#if ENABLE(STREAMS_API)
+    virtual void consumeBodyAsStream();
+    virtual void feedStream() { }
+    virtual void cancel() { }
+#endif
+
 protected:
     const FetchBody& body() const { return *m_body; }
     FetchBody& body() { return *m_body; }
     bool isBodyNull() const { return !m_body; }
-    void cloneBody(const FetchBodyOwner&);
+    void cloneBody(FetchBodyOwner&);
 
     void extractBody(ScriptExecutionContext&, FetchBody::Init&&);
     void updateContentType();
@@ -103,7 +107,7 @@
     String m_contentType;
     bool m_isDisturbed { false };
 #if ENABLE(STREAMS_API)
-    RefPtr<FetchResponseSource> m_readableStreamSource;
+    RefPtr<FetchBodySource> m_readableStreamSource;
 #endif
     Ref<FetchHeaders> m_headers;
 

Copied: trunk/Source/WebCore/Modules/fetch/FetchBodySource.cpp (from rev 221436, trunk/Source/WebCore/Modules/fetch/FetchResponseSource.cpp) (0 => 221437)


--- trunk/Source/WebCore/Modules/fetch/FetchBodySource.cpp	                        (rev 0)
+++ trunk/Source/WebCore/Modules/fetch/FetchBodySource.cpp	2017-08-31 20:03:42 UTC (rev 221437)
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2016 Canon Inc.
+ * Copyright (C) 2017 Apple Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted, provided that the following conditions
+ * are required to be met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY CANON INC. AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL CANON INC. AND ITS CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "FetchBodySource.h"
+
+#if ENABLE(STREAMS_API)
+
+#include "FetchResponse.h"
+
+namespace WebCore {
+
+FetchBodySource::FetchBodySource(FetchBodyOwner& bodyOwner)
+    : m_bodyOwner(bodyOwner)
+{
+}
+
+bool FetchBodySource::isReadableStreamLocked() const
+{
+    return controller().isControlledReadableStreamLocked();
+}
+
+void FetchBodySource::setActive()
+{
+    m_bodyOwner.setPendingActivity(&m_bodyOwner);
+}
+
+void FetchBodySource::setInactive()
+{
+    m_bodyOwner.unsetPendingActivity(&m_bodyOwner);
+}
+
+void FetchBodySource::doStart()
+{
+    m_bodyOwner.consumeBodyAsStream();
+}
+
+void FetchBodySource::doPull()
+{
+    m_bodyOwner.feedStream();
+}
+
+void FetchBodySource::doCancel()
+{
+    m_isCancelling = true;
+    m_bodyOwner.cancel();
+}
+
+void FetchBodySource::close()
+{
+    controller().close();
+    clean();
+}
+void FetchBodySource::error(const String& value)
+{
+    controller().error(value);
+    clean();
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(STREAMS_API)

Copied: trunk/Source/WebCore/Modules/fetch/FetchBodySource.h (from rev 221436, trunk/Source/WebCore/Modules/fetch/FetchResponseSource.h) (0 => 221437)


--- trunk/Source/WebCore/Modules/fetch/FetchBodySource.h	                        (rev 0)
+++ trunk/Source/WebCore/Modules/fetch/FetchBodySource.h	2017-08-31 20:03:42 UTC (rev 221437)
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2016 Canon Inc.
+ * Copyright (C) 2017 Apple Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted, provided that the following conditions
+ * are required to be met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY CANON INC. AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL CANON INC. AND ITS CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(STREAMS_API)
+
+#include "ReadableStreamSource.h"
+
+namespace JSC {
+class ArrayBuffer;
+};
+
+namespace WebCore {
+
+class FetchBodyOwner;
+
+class FetchBodySource final : public ReadableStreamSource {
+public:
+    FetchBodySource(FetchBodyOwner&);
+
+    bool enqueue(RefPtr<JSC::ArrayBuffer>&& chunk) { return controller().enqueue(WTFMove(chunk)); }
+    void close();
+    void error(const String&);
+
+    bool isCancelling() const { return m_isCancelling; }
+    bool isReadableStreamLocked() const;
+
+    void resolvePullPromise() { pullFinished(); }
+
+private:
+    void doStart() final;
+    void doPull() final;
+    void doCancel() final;
+    void setActive() final;
+    void setInactive() final;
+
+    FetchBodyOwner& m_bodyOwner;
+    bool m_isCancelling { false };
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(STREAMS_API)

Modified: trunk/Source/WebCore/Modules/fetch/FetchResponse.cpp (221436 => 221437)


--- trunk/Source/WebCore/Modules/fetch/FetchResponse.cpp	2017-08-31 19:51:08 UTC (rev 221436)
+++ trunk/Source/WebCore/Modules/fetch/FetchResponse.cpp	2017-08-31 20:03:42 UTC (rev 221437)
@@ -324,14 +324,12 @@
 {
     ASSERT(m_shouldExposeBody);
     ASSERT(m_readableStreamSource);
-    m_isDisturbed = true;
     if (!isLoading()) {
-        body().consumeAsStream(*this, *m_readableStreamSource);
-        if (!m_readableStreamSource->isPulling())
-            m_readableStreamSource = nullptr;
+        FetchBodyOwner::consumeBodyAsStream();
         return;
     }
 
+    m_isDisturbed = true;
     ASSERT(m_bodyLoader);
 
     setBodyAsReadableStream();
@@ -373,16 +371,12 @@
     closeStream();
 }
 
-ReadableStreamSource* FetchResponse::createReadableStreamSource()
+RefPtr<ReadableStream> FetchResponse::createReadableStream(JSC::ExecState& state)
 {
-    ASSERT(!m_readableStreamSource);
-    ASSERT(!m_isDisturbed);
-
-    if (isBodyNull() || !m_shouldExposeBody)
+    if (!m_shouldExposeBody)
         return nullptr;
 
-    m_readableStreamSource = adoptRef(*new FetchResponseSource(*this));
-    return m_readableStreamSource.get();
+    return FetchBodyOwner::readableStream(state);
 }
 
 RefPtr<SharedBuffer> FetchResponse::BodyLoader::startStreaming()

Modified: trunk/Source/WebCore/Modules/fetch/FetchResponse.h (221436 => 221437)


--- trunk/Source/WebCore/Modules/fetch/FetchResponse.h	2017-08-31 19:51:08 UTC (rev 221436)
+++ trunk/Source/WebCore/Modules/fetch/FetchResponse.h	2017-08-31 20:03:42 UTC (rev 221437)
@@ -85,10 +85,10 @@
     Ref<FetchResponse> cloneForJS();
 
 #if ENABLE(STREAMS_API)
-    ReadableStreamSource* createReadableStreamSource();
-    void consumeBodyAsStream();
-    void feedStream();
-    void cancel();
+    RefPtr<ReadableStream> createReadableStream(JSC::ExecState&);
+    void consumeBodyAsStream() final;
+    void feedStream() final;
+    void cancel() final;
 #endif
 
     using ResponseData = Variant<std::nullptr_t, Ref<FormData>, Ref<SharedBuffer>>;

Modified: trunk/Source/WebCore/Modules/fetch/FetchResponse.idl (221436 => 221437)


--- trunk/Source/WebCore/Modules/fetch/FetchResponse.idl	2017-08-31 19:51:08 UTC (rev 221436)
+++ trunk/Source/WebCore/Modules/fetch/FetchResponse.idl	2017-08-31 20:03:42 UTC (rev 221437)
@@ -83,7 +83,7 @@
     [PrivateIdentifier] boolean isLoading();
     [MayThrowException, PrivateIdentifier] void setStatus(unsigned short status, DOMString statusText);
     [PrivateIdentifier] void initializeWith(BodyInit body);
-    [NewObject, PrivateIdentifier] ReadableStreamSource createReadableStreamSource();
+    [CallWith=ScriptState, NewObject, PrivateIdentifier] ReadableStream? createReadableStream();
     [PrivateIdentifier] boolean isDisturbed();
     [PrivateIdentifier] void setBodyAsReadableStream();
 };

Modified: trunk/Source/WebCore/Modules/fetch/FetchResponse.js (221436 => 221437)


--- trunk/Source/WebCore/Modules/fetch/FetchResponse.js	2017-08-31 19:51:08 UTC (rev 221436)
+++ trunk/Source/WebCore/Modules/fetch/FetchResponse.js	2017-08-31 20:03:42 UTC (rev 221437)
@@ -77,15 +77,13 @@
     if (!(this instanceof @Response))
         throw @makeGetterTypeError("Response", "body");
 
-    if (!this.@body) {
+    if (this.@body === @undefined) {
         if (@Response.prototype.@isDisturbed.@call(this)) {
             this.@body = new @ReadableStream();
             // Get reader to lock it.
             new @ReadableStreamDefaultReader(this.@body);
-        } else {
-            var source = @Response.prototype.@createReadableStreamSource.@call(this);
-            this.@body = source ? new @ReadableStream(source) : null;
-        }
+        } else
+            this.@body = @Response.prototype.@createReadableStream.@call(this);
     }
     return this.@body;
 }
@@ -101,11 +99,8 @@
     var cloned = @Response.prototype.@cloneForJS.@call(this);
 
     // Let's create @body if response body is loading to provide data to both clones.
-    if (@Response.prototype.@isLoading.@call(this) && !this.@body) {
-        var source = @Response.prototype.@createReadableStreamSource.@call(this);
-        @assert(!!source);
-        this.@body = new @ReadableStream(source);
-    }
+    if (@Response.prototype.@isLoading.@call(this) && this.@body === @undefined)
+        this.@body = @Response.prototype.@createReadableStream.@call(this);
 
     if (this.@body) {
         var teedReadableStreams = @readableStreamTee(this.@body, true);

Deleted: trunk/Source/WebCore/Modules/fetch/FetchResponseSource.cpp (221436 => 221437)


--- trunk/Source/WebCore/Modules/fetch/FetchResponseSource.cpp	2017-08-31 19:51:08 UTC (rev 221436)
+++ trunk/Source/WebCore/Modules/fetch/FetchResponseSource.cpp	2017-08-31 20:03:42 UTC (rev 221437)
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2016 Canon Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted, provided that the following conditions
- * are required to be met:
- *
- * 1.  Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- * 2.  Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- * 3.  Neither the name of Canon Inc. nor the names of
- *     its contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY CANON INC. AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL CANON INC. AND ITS CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "FetchResponseSource.h"
-
-#if ENABLE(STREAMS_API)
-
-#include "FetchResponse.h"
-
-namespace WebCore {
-
-FetchResponseSource::FetchResponseSource(FetchResponse& response)
-    : m_response(response)
-{
-}
-
-bool FetchResponseSource::isReadableStreamLocked() const
-{
-    return controller().isControlledReadableStreamLocked();
-}
-
-void FetchResponseSource::setActive()
-{
-    m_response.setPendingActivity(&m_response);
-}
-
-void FetchResponseSource::setInactive()
-{
-    m_response.unsetPendingActivity(&m_response);
-}
-
-void FetchResponseSource::doStart()
-{
-    m_response.consumeBodyAsStream();
-}
-
-void FetchResponseSource::doPull()
-{
-    m_response.feedStream();
-}
-
-void FetchResponseSource::doCancel()
-{
-    m_isCancelling = true;
-    m_response.cancel();
-}
-
-void FetchResponseSource::close()
-{
-    controller().close();
-    clean();
-}
-void FetchResponseSource::error(const String& value)
-{
-    controller().error(value);
-    clean();
-}
-
-} // namespace WebCore
-
-#endif // ENABLE(STREAMS_API)

Deleted: trunk/Source/WebCore/Modules/fetch/FetchResponseSource.h (221436 => 221437)


--- trunk/Source/WebCore/Modules/fetch/FetchResponseSource.h	2017-08-31 19:51:08 UTC (rev 221436)
+++ trunk/Source/WebCore/Modules/fetch/FetchResponseSource.h	2017-08-31 20:03:42 UTC (rev 221437)
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2016 Canon Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted, provided that the following conditions
- * are required to be met:
- *
- * 1.  Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- * 2.  Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- * 3.  Neither the name of Canon Inc. nor the names of
- *     its contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY CANON INC. AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL CANON INC. AND ITS CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#pragma once
-
-#if ENABLE(STREAMS_API)
-
-#include "ReadableStreamSource.h"
-
-namespace JSC {
-class ArrayBuffer;
-};
-
-namespace WebCore {
-
-class FetchResponse;
-
-class FetchResponseSource final : public ReadableStreamSource {
-public:
-    FetchResponseSource(FetchResponse&);
-
-    bool enqueue(RefPtr<JSC::ArrayBuffer>&& chunk) { return controller().enqueue(WTFMove(chunk)); }
-    void close();
-    void error(const String&);
-
-    bool isCancelling() const { return m_isCancelling; }
-    bool isReadableStreamLocked() const;
-
-    void resolvePullPromise() { pullFinished(); }
-
-private:
-    void doStart() final;
-    void doPull() final;
-    void doCancel() final;
-    void setActive() final;
-    void setInactive() final;
-
-    FetchResponse& m_response;
-    bool m_isCancelling { false };
-};
-
-} // namespace WebCore
-
-#endif // ENABLE(STREAMS_API)

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (221436 => 221437)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2017-08-31 19:51:08 UTC (rev 221436)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2017-08-31 20:03:42 UTC (rev 221437)
@@ -1676,7 +1676,7 @@
 		4129DF851BB5B80700322A16 /* JSReadableStreamPrivateConstructors.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4129DF831BB5B7F700322A16 /* JSReadableStreamPrivateConstructors.cpp */; };
 		4129DF861BB5B80C00322A16 /* JSReadableStreamPrivateConstructors.h in Headers */ = {isa = PBXBuildFile; fileRef = 4129DF841BB5B7F700322A16 /* JSReadableStreamPrivateConstructors.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		413015D91C7B571400091C6E /* FetchResponse.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 413015D51C7B570400091C6E /* FetchResponse.cpp */; };
-		413015D91C7B571400091C6F /* FetchResponseSource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 413015D51C7B570400091C6F /* FetchResponseSource.cpp */; };
+		413015D91C7B571400091C6F /* FetchBodySource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 413015D51C7B570400091C6F /* FetchBodySource.cpp */; };
 		41380C261F3436A600155FDA /* Cache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41380C201F34368A00155FDA /* Cache.cpp */; };
 		41380C271F3436AC00155FDA /* Cache.h in Headers */ = {isa = PBXBuildFile; fileRef = 41380C251F34369A00155FDA /* Cache.h */; };
 		41380C281F3436AC00155FDA /* CacheStorage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41380C211F34368D00155FDA /* CacheStorage.cpp */; };
@@ -9382,9 +9382,9 @@
 		4129DF831BB5B7F700322A16 /* JSReadableStreamPrivateConstructors.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSReadableStreamPrivateConstructors.cpp; sourceTree = "<group>"; };
 		4129DF841BB5B7F700322A16 /* JSReadableStreamPrivateConstructors.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSReadableStreamPrivateConstructors.h; sourceTree = "<group>"; };
 		413015D51C7B570400091C6E /* FetchResponse.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FetchResponse.cpp; sourceTree = "<group>"; };
-		413015D51C7B570400091C6F /* FetchResponseSource.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FetchResponseSource.cpp; sourceTree = "<group>"; };
+		413015D51C7B570400091C6F /* FetchBodySource.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FetchBodySource.cpp; sourceTree = "<group>"; };
 		413015D61C7B570400091C6E /* FetchResponse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FetchResponse.h; sourceTree = "<group>"; };
-		413015D61C7B570400091C6F /* FetchResponseSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FetchResponseSource.h; sourceTree = "<group>"; };
+		413015D61C7B570400091C6F /* FetchBodySource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FetchBodySource.h; sourceTree = "<group>"; };
 		413015D71C7B570400091C6E /* FetchResponse.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = FetchResponse.idl; sourceTree = "<group>"; };
 		413015D81C7B570400091C6E /* FetchResponse.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode._javascript_; path = FetchResponse.js; sourceTree = "<group>"; };
 		41380C201F34368A00155FDA /* Cache.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = Cache.cpp; path = Modules/cache/Cache.cpp; sourceTree = SOURCE_ROOT; };
@@ -18031,6 +18031,8 @@
 				41CF8BE51D46222000707DC9 /* FetchBodyConsumer.h */,
 				4147E2B31C89912600A7E715 /* FetchBodyOwner.cpp */,
 				4147E2B21C88337F00A7E715 /* FetchBodyOwner.h */,
+				413015D51C7B570400091C6F /* FetchBodySource.cpp */,
+				413015D61C7B570400091C6F /* FetchBodySource.h */,
 				41F54F821C50C4F600338488 /* FetchHeaders.cpp */,
 				41F54F831C50C4F600338488 /* FetchHeaders.h */,
 				41F54F841C50C4F600338488 /* FetchHeaders.idl */,
@@ -18057,8 +18059,6 @@
 				413015D61C7B570400091C6E /* FetchResponse.h */,
 				413015D71C7B570400091C6E /* FetchResponse.idl */,
 				413015D81C7B570400091C6E /* FetchResponse.js */,
-				413015D51C7B570400091C6F /* FetchResponseSource.cpp */,
-				413015D61C7B570400091C6F /* FetchResponseSource.h */,
 				418C39571C8DD6960051C8A3 /* WorkerGlobalScopeFetch.cpp */,
 				418C39581C8DD6960051C8A3 /* WorkerGlobalScopeFetch.h */,
 				418C39591C8DD6960051C8A3 /* WorkerGlobalScopeFetch.idl */,
@@ -31590,11 +31590,11 @@
 				41F54F8B1C50C50300338488 /* FetchBody.cpp in Sources */,
 				41CF8BE71D46226700707DC9 /* FetchBodyConsumer.cpp in Sources */,
 				4147E2B81C89912F00A7E715 /* FetchBodyOwner.cpp in Sources */,
+				413015D91C7B571400091C6F /* FetchBodySource.cpp in Sources */,
 				41F54F8D1C50C50800338488 /* FetchHeaders.cpp in Sources */,
 				4147E2B71C89912C00A7E715 /* FetchLoader.cpp in Sources */,
 				41F54F8E1C50C50C00338488 /* FetchRequest.cpp in Sources */,
 				413015D91C7B571400091C6E /* FetchResponse.cpp in Sources */,
-				413015D91C7B571400091C6F /* FetchResponseSource.cpp in Sources */,
 				84730D8A1248F0B300D3A9C9 /* FETile.cpp in Sources */,
 				84730D8C1248F0B300D3A9C9 /* FETurbulence.cpp in Sources */,
 				FD31609412B026F700C1A359 /* FFTConvolver.cpp in Sources */,
@@ -31837,7 +31837,6 @@
 				A871DE250A152AC800B12A68 /* HTMLHeadElement.cpp in Sources */,
 				A8EA7CAE0A192B9C00A8EF5F /* HTMLHeadingElement.cpp in Sources */,
 				A8EA7CB30A192B9C00A8EF5F /* HTMLHRElement.cpp in Sources */,
-				E41FA9B91F5758FF0033858A /* RenderTreeUpdaterMultiColumn.cpp in Sources */,
 				A871DE260A152AC800B12A68 /* HTMLHtmlElement.cpp in Sources */,
 				A871DE240A152AC800B12A68 /* HTMLIFrameElement.cpp in Sources */,
 				A8EA7D310A19385500A8EF5F /* HTMLImageElement.cpp in Sources */,
@@ -33444,6 +33443,7 @@
 				E48284081F44594C00863AC3 /* RenderTreeUpdaterFirstLetter.cpp in Sources */,
 				E48E33311F47437000BAB0EF /* RenderTreeUpdaterGeneratedContent.cpp in Sources */,
 				E48E332D1F47038000BAB0EF /* RenderTreeUpdaterListItem.cpp in Sources */,
+				E41FA9B91F5758FF0033858A /* RenderTreeUpdaterMultiColumn.cpp in Sources */,
 				E44614510CD68A3500FADA75 /* RenderVideo.cpp in Sources */,
 				BCEA4867097D93020094C9E4 /* RenderView.cpp in Sources */,
 				BE20507D18A458BF0080647E /* RenderVTTCue.cpp in Sources */,

Modified: trunk/Source/WebCore/bindings/js/ReadableStream.cpp (221436 => 221437)


--- trunk/Source/WebCore/bindings/js/ReadableStream.cpp	2017-08-31 19:51:08 UTC (rev 221436)
+++ trunk/Source/WebCore/bindings/js/ReadableStream.cpp	2017-08-31 20:03:42 UTC (rev 221437)
@@ -26,6 +26,7 @@
 #include "config.h"
 #include "ReadableStream.h"
 
+#include "JSDOMConvertSequences.h"
 #include "JSReadableStreamSource.h"
 #include "WebCoreJSClientData.h"
 
@@ -53,4 +54,27 @@
     return create(globalObject, *newReadableStream);
 }
 
+std::pair<Ref<ReadableStream>, Ref<ReadableStream>> ReadableStream::tee()
+{
+    auto& state = *m_globalObject->globalExec();
+    JSVMClientData* clientData = static_cast<JSVMClientData*>(state.vm().clientData);
+    const Identifier& privateName = clientData->builtinFunctions().readableStreamInternalsBuiltins().readableStreamTeePrivateName();
+
+    auto readableStreamTee = m_globalObject->get(&state, privateName);
+    ASSERT(readableStreamTee.isFunction());
+
+    CallData callData;
+    CallType callType = getCallData(readableStreamTee, callData);
+    ASSERT(callType != JSC::CallType::None);
+    MarkedArgumentBuffer arguments;
+    arguments.append(readableStream());
+    arguments.append(JSC::jsBoolean(true));
+    JSValue returnedValue = JSC::call(&state, readableStreamTee, callType, callData, JSC::jsUndefined(), arguments);
+
+    auto results = Detail::SequenceConverter<IDLInterface<ReadableStream>>::convert(state, returnedValue);
+
+    ASSERT(results.size() == 2);
+    return std::make_pair(results[0].releaseNonNull(), results[1].releaseNonNull());
 }
+
+}

Modified: trunk/Source/WebCore/bindings/js/ReadableStream.h (221436 => 221437)


--- trunk/Source/WebCore/bindings/js/ReadableStream.h	2017-08-31 19:51:08 UTC (rev 221436)
+++ trunk/Source/WebCore/bindings/js/ReadableStream.h	2017-08-31 20:03:42 UTC (rev 221437)
@@ -40,6 +40,8 @@
 
     static Ref<ReadableStream> create(JSC::ExecState&, RefPtr<ReadableStreamSource>&&);
 
+    std::pair<Ref<ReadableStream>, Ref<ReadableStream>> tee();
+
     JSReadableStream* readableStream() { return guarded(); }
 
 protected:

Modified: trunk/Source/WebCore/bindings/js/WebCoreBuiltinNames.h (221436 => 221437)


--- trunk/Source/WebCore/bindings/js/WebCoreBuiltinNames.h	2017-08-31 19:51:08 UTC (rev 221436)
+++ trunk/Source/WebCore/bindings/js/WebCoreBuiltinNames.h	2017-08-31 20:03:42 UTC (rev 221437)
@@ -47,7 +47,7 @@
     macro(consumeChunk) \
     macro(controlledReadableStream) \
     macro(controller) \
-    macro(createReadableStreamSource) \
+    macro(createReadableStream) \
     macro(disturbed) \
     macro(failureKind) \
     macro(fetchRequest) \
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to