Diff
Modified: trunk/LayoutTests/imported/w3c/ChangeLog (221771 => 221772)
--- trunk/LayoutTests/imported/w3c/ChangeLog 2017-09-07 23:18:04 UTC (rev 221771)
+++ trunk/LayoutTests/imported/w3c/ChangeLog 2017-09-07 23:23:57 UTC (rev 221772)
@@ -1,3 +1,18 @@
+2017-09-07 Youenn Fablet <[email protected]>
+
+ Align FetchResponse and FetchRequest body handling
+ https://bugs.webkit.org/show_bug.cgi?id=176539
+
+ Reviewed by Alex Christensen.
+
+ * web-platform-tests/fetch/api/request/request-consume-empty-expected.txt:
+ * web-platform-tests/fetch/api/request/request-consume-expected.txt:
+ * web-platform-tests/fetch/api/request/request-idl-expected.txt:
+ * web-platform-tests/fetch/api/request/request-structure-expected.txt:
+ * web-platform-tests/fetch/api/response/response-consume-empty-expected.txt:
+ * web-platform-tests/fetch/api/response/response-consume-expected.txt:
+ * web-platform-tests/url/urlencoded-parser-expected.txt:
+
2017-09-06 Youenn Fablet <[email protected]>
Support caching of Response with a ReadableStream body
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/request/request-consume-empty-expected.txt (221771 => 221772)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/request/request-consume-empty-expected.txt 2017-09-07 23:18:04 UTC (rev 221771)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/request/request-consume-empty-expected.txt 2017-09-07 23:23:57 UTC (rev 221772)
@@ -3,9 +3,9 @@
PASS Consume request's body as blob
PASS Consume request's body as arrayBuffer
PASS Consume request's body as json (error case)
-FAIL Consume request's body as formData with correct multipart type (error case) request.formData is not a function. (In 'request.formData()', 'request.formData' is undefined)
-FAIL Consume request's body as formData with correct urlencoded type request.formData is not a function. (In 'request.formData()', 'request.formData' is undefined)
-FAIL Consume request's body as formData without correct type (error case) request.formData is not a function. (In 'request.formData()', 'request.formData' is undefined)
+FAIL Consume request's body as formData with correct multipart type (error case) promise_test: Unhandled rejection with value: object "TypeError: undefined is not an object (evaluating 'e.name')"
+FAIL Consume request's body as formData with correct urlencoded type promise_test: Unhandled rejection with value: undefined
+FAIL Consume request's body as formData without correct type (error case) promise_test: Unhandled rejection with value: object "TypeError: undefined is not an object (evaluating 'e.name')"
PASS Consume empty blob request body as arrayBuffer
PASS Consume empty text request body as arrayBuffer
PASS Consume empty blob request body as text
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/request/request-consume-expected.txt (221771 => 221772)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/request/request-consume-expected.txt 2017-09-07 23:18:04 UTC (rev 221771)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/request/request-consume-expected.txt 2017-09-07 23:23:57 UTC (rev 221772)
@@ -23,7 +23,7 @@
PASS Consume DataView request's body as blob
PASS Consume DataView request's body as arrayBuffer
PASS Consume DataView request's body as JSON
-FAIL Consume FormData request's body as FormData request.formData is not a function. (In 'request.formData()', 'request.formData' is undefined)
+FAIL Consume FormData request's body as FormData promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
PASS Consume blob response's body as blob
PASS Consume blob response's body as text
PASS Consume blob response's body as json
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/request/request-idl-expected.txt (221771 => 221772)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/request/request-idl-expected.txt 2017-09-07 23:18:04 UTC (rev 221771)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/request/request-idl-expected.txt 2017-09-07 23:23:57 UTC (rev 221772)
@@ -22,7 +22,7 @@
PASS Request interface: attribute bodyUsed
PASS Request interface: operation arrayBuffer()
PASS Request interface: operation blob()
-FAIL Request interface: operation formData() assert_own_property: interface prototype object missing non-static operation expected property "formData" missing
+PASS Request interface: operation formData()
PASS Request interface: operation json()
PASS Request interface: operation text()
PASS Request interface: new Request("") must inherit property "method" with the proper type (0)
@@ -43,7 +43,7 @@
PASS Request interface: new Request("") must inherit property "bodyUsed" with the proper type (15)
PASS Request interface: new Request("") must inherit property "arrayBuffer" with the proper type (16)
PASS Request interface: new Request("") must inherit property "blob" with the proper type (17)
-FAIL Request interface: new Request("") must inherit property "formData" with the proper type (18) assert_inherits: property "formData" not found in prototype chain
+PASS Request interface: new Request("") must inherit property "formData" with the proper type (18)
PASS Request interface: new Request("") must inherit property "json" with the proper type (19)
PASS Request interface: new Request("") must inherit property "text" with the proper type (20)
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/request/request-structure-expected.txt (221771 => 221772)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/request/request-structure-expected.txt 2017-09-07 23:18:04 UTC (rev 221771)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/request/request-structure-expected.txt 2017-09-07 23:23:57 UTC (rev 221772)
@@ -2,7 +2,7 @@
PASS Request has clone method
PASS Request has arrayBuffer method
PASS Request has blob method
-FAIL Request has formData method assert_true: request has formData method expected true got false
+PASS Request has formData method
PASS Request has json method
PASS Request has text method
PASS Check method attribute
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/response/response-consume-empty-expected.txt (221771 => 221772)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/response/response-consume-empty-expected.txt 2017-09-07 23:18:04 UTC (rev 221771)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/response/response-consume-empty-expected.txt 2017-09-07 23:23:57 UTC (rev 221772)
@@ -3,9 +3,9 @@
PASS Consume response's body as blob
PASS Consume response's body as arrayBuffer
PASS Consume response's body as json (error case)
-FAIL Consume response's body as formData with correct multipart type (error case) assert_throws: function "function () { throw e }" threw "Not implemented" (undefined) expected object "TypeError" ("TypeError")
-FAIL Consume response's body as formData with correct urlencoded type promise_test: Unhandled rejection with value: "Not implemented"
-FAIL Consume response's body as formData without correct type (error case) assert_throws: function "function () { throw e }" threw "Not implemented" (undefined) expected object "TypeError" ("TypeError")
+FAIL Consume response's body as formData with correct multipart type (error case) promise_test: Unhandled rejection with value: object "TypeError: undefined is not an object (evaluating 'e.name')"
+FAIL Consume response's body as formData with correct urlencoded type promise_test: Unhandled rejection with value: undefined
+FAIL Consume response's body as formData without correct type (error case) promise_test: Unhandled rejection with value: object "TypeError: undefined is not an object (evaluating 'e.name')"
PASS Consume empty blob response body as arrayBuffer
PASS Consume empty text response body as arrayBuffer
PASS Consume empty blob response body as text
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/response/response-consume-expected.txt (221771 => 221772)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/response/response-consume-expected.txt 2017-09-07 23:18:04 UTC (rev 221771)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/response/response-consume-expected.txt 2017-09-07 23:23:57 UTC (rev 221772)
@@ -3,25 +3,25 @@
PASS Consume response's body: from text to blob
PASS Consume response's body: from text to arrayBuffer
PASS Consume response's body: from text to json
-FAIL Consume response's body: from text with correct multipart type to formData promise_test: Unhandled rejection with value: "Not implemented"
-FAIL Consume response's body: from text without correct multipart type to formData (error case) assert_throws: function "function () { throw e }" threw "Not implemented" (undefined) expected object "TypeError" ("TypeError")
-FAIL Consume response's body: from text with correct urlencoded type to formData promise_test: Unhandled rejection with value: "Not implemented"
-FAIL Consume response's body: from text without correct urlencoded type to formData (error case) assert_throws: function "function () { throw e }" threw "Not implemented" (undefined) expected object "TypeError" ("TypeError")
+FAIL Consume response's body: from text with correct multipart type to formData promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
+FAIL Consume response's body: from text without correct multipart type to formData (error case) assert_throws: function "function () { throw e }" threw object "NotSupportedError: The operation is not supported." ("NotSupportedError") expected object "TypeError" ("TypeError")
+FAIL Consume response's body: from text with correct urlencoded type to formData promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
+FAIL Consume response's body: from text without correct urlencoded type to formData (error case) assert_throws: function "function () { throw e }" threw object "NotSupportedError: The operation is not supported." ("NotSupportedError") expected object "TypeError" ("TypeError")
PASS Consume response's body: from blob to blob
PASS Consume response's body: from blob to text
PASS Consume response's body: from blob to arrayBuffer
PASS Consume response's body: from blob to json
-FAIL Consume response's body: from blob with correct multipart type to formData promise_test: Unhandled rejection with value: "Not implemented"
-FAIL Consume response's body: from blob without correct multipart type to formData (error case) assert_throws: function "function () { throw e }" threw "Not implemented" (undefined) expected object "TypeError" ("TypeError")
-FAIL Consume response's body: from blob with correct urlencoded type to formData promise_test: Unhandled rejection with value: "Not implemented"
-FAIL Consume response's body: from blob without correct urlencoded type to formData (error case) assert_throws: function "function () { throw e }" threw "Not implemented" (undefined) expected object "TypeError" ("TypeError")
-FAIL Consume response's body: from FormData to formData promise_test: Unhandled rejection with value: "Not implemented"
-FAIL Consume response's body: from FormData without correct type to formData (error case) assert_throws: function "function () { throw e }" threw "Not implemented" (undefined) expected object "TypeError" ("TypeError")
+FAIL Consume response's body: from blob with correct multipart type to formData promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
+FAIL Consume response's body: from blob without correct multipart type to formData (error case) assert_throws: function "function () { throw e }" threw object "NotSupportedError: The operation is not supported." ("NotSupportedError") expected object "TypeError" ("TypeError")
+FAIL Consume response's body: from blob with correct urlencoded type to formData promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
+FAIL Consume response's body: from blob without correct urlencoded type to formData (error case) assert_throws: function "function () { throw e }" threw object "NotSupportedError: The operation is not supported." ("NotSupportedError") expected object "TypeError" ("TypeError")
+FAIL Consume response's body: from FormData to formData promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
+FAIL Consume response's body: from FormData without correct type to formData (error case) assert_throws: function "function () { throw e }" threw object "NotSupportedError: The operation is not supported." ("NotSupportedError") expected object "TypeError" ("TypeError")
FAIL Consume response's body: from FormData to blob promise_test: Unhandled rejection with value: undefined
FAIL Consume response's body: from FormData to text promise_test: Unhandled rejection with value: undefined
FAIL Consume response's body: from FormData to arrayBuffer promise_test: Unhandled rejection with value: undefined
-FAIL Consume response's body: from URLSearchParams to formData promise_test: Unhandled rejection with value: "Not implemented"
-FAIL Consume response's body: from URLSearchParams without correct type to formData (error case) assert_throws: function "function () { throw e }" threw "Not implemented" (undefined) expected object "TypeError" ("TypeError")
+FAIL Consume response's body: from URLSearchParams to formData promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
+FAIL Consume response's body: from URLSearchParams without correct type to formData (error case) assert_throws: function "function () { throw e }" threw object "NotSupportedError: The operation is not supported." ("NotSupportedError") expected object "TypeError" ("TypeError")
FAIL Consume response's body: from URLSearchParams to blob assert_equals: Blob body type should be computed from the response Content-Type expected "application/x-www-form-urlencoded;charset=utf-8" but got "application/x-www-form-urlencoded"
PASS Consume response's body: from URLSearchParams to text
PASS Consume response's body: from URLSearchParams to arrayBuffer
@@ -29,13 +29,13 @@
PASS Consume response's body: from stream to text
PASS Consume response's body: from stream to arrayBuffer
PASS Consume response's body: from stream to json
-FAIL Consume response's body: from stream with correct multipart type to formData promise_test: Unhandled rejection with value: "Not implemented"
-FAIL Consume response's body: from stream without correct multipart type to formData (error case) assert_throws: function "function () { throw e }" threw "Not implemented" (undefined) expected object "TypeError" ("TypeError")
-FAIL Consume response's body: from stream with correct urlencoded type to formData promise_test: Unhandled rejection with value: "Not implemented"
-FAIL Consume response's body: from stream without correct urlencoded type to formData (error case) assert_throws: function "function () { throw e }" threw "Not implemented" (undefined) expected object "TypeError" ("TypeError")
+FAIL Consume response's body: from stream with correct multipart type to formData promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
+FAIL Consume response's body: from stream without correct multipart type to formData (error case) assert_throws: function "function () { throw e }" threw object "NotSupportedError: The operation is not supported." ("NotSupportedError") expected object "TypeError" ("TypeError")
+FAIL Consume response's body: from stream with correct urlencoded type to formData promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
+FAIL Consume response's body: from stream without correct urlencoded type to formData (error case) assert_throws: function "function () { throw e }" threw object "NotSupportedError: The operation is not supported." ("NotSupportedError") expected object "TypeError" ("TypeError")
PASS Consume response's body: from fetch to blob
PASS Consume response's body: from fetch to text
PASS Consume response's body: from fetch to arrayBuffer
-FAIL Consume response's body: from fetch without correct type to formData (error case) assert_throws: function "function () { throw e }" threw "Not implemented" (undefined) expected object "TypeError" ("TypeError")
-FAIL Consume response's body: from multipart form data blob to formData promise_test: Unhandled rejection with value: "Not implemented"
+FAIL Consume response's body: from fetch without correct type to formData (error case) assert_throws: function "function () { throw e }" threw object "NotSupportedError: The operation is not supported." ("NotSupportedError") expected object "TypeError" ("TypeError")
+FAIL Consume response's body: from multipart form data blob to formData promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/url/urlencoded-parser-expected.txt (221771 => 221772)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/url/urlencoded-parser-expected.txt 2017-09-07 23:18:04 UTC (rev 221771)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/url/urlencoded-parser-expected.txt 2017-09-07 23:23:57 UTC (rev 221772)
@@ -1,92 +1,92 @@
PASS URLSearchParams constructed with: test
-FAIL request.formData() with input: test undefined is not a function (near '...s-1252"} }).formData()...')
-FAIL response.formData() with input: test promise_test: Unhandled rejection with value: "Not implemented"
+FAIL request.formData() with input: test promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
+FAIL response.formData() with input: test promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
PASS URLSearchParams constructed with: test=
-FAIL request.formData() with input: test= undefined is not a function (near '...s-1252"} }).formData()...')
-FAIL response.formData() with input: test= promise_test: Unhandled rejection with value: "Not implemented"
+FAIL request.formData() with input: test= promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
+FAIL response.formData() with input: test= promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
PASS URLSearchParams constructed with: %EF%BB%BFtest=%EF%BB%BF
-FAIL request.formData() with input: %EF%BB%BFtest=%EF%BB%BF undefined is not a function (near '...s-1252"} }).formData()...')
-FAIL response.formData() with input: %EF%BB%BFtest=%EF%BB%BF promise_test: Unhandled rejection with value: "Not implemented"
+FAIL request.formData() with input: %EF%BB%BFtest=%EF%BB%BF promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
+FAIL response.formData() with input: %EF%BB%BFtest=%EF%BB%BF promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
FAIL URLSearchParams constructed with: %FE%FF assert_array_equals: property 0, expected "\ufffd\ufffd" but got ""
-FAIL request.formData() with input: %FE%FF undefined is not a function (near '...s-1252"} }).formData()...')
-FAIL response.formData() with input: %FE%FF promise_test: Unhandled rejection with value: "Not implemented"
+FAIL request.formData() with input: %FE%FF promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
+FAIL response.formData() with input: %FE%FF promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
FAIL URLSearchParams constructed with: %FF%FE assert_array_equals: property 0, expected "\ufffd\ufffd" but got ""
-FAIL request.formData() with input: %FF%FE undefined is not a function (near '...s-1252"} }).formData()...')
-FAIL response.formData() with input: %FF%FE promise_test: Unhandled rejection with value: "Not implemented"
+FAIL request.formData() with input: %FF%FE promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
+FAIL response.formData() with input: %FF%FE promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
PASS URLSearchParams constructed with: †&†=x
-FAIL request.formData() with input: †&†=x undefined is not a function (near '...s-1252"} }).formData()...')
-FAIL response.formData() with input: †&†=x promise_test: Unhandled rejection with value: "Not implemented"
+FAIL request.formData() with input: †&†=x promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
+FAIL response.formData() with input: †&†=x promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
FAIL URLSearchParams constructed with: %C2 assert_array_equals: property 0, expected "\ufffd" but got ""
-FAIL request.formData() with input: %C2 undefined is not a function (near '...s-1252"} }).formData()...')
-FAIL response.formData() with input: %C2 promise_test: Unhandled rejection with value: "Not implemented"
+FAIL request.formData() with input: %C2 promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
+FAIL response.formData() with input: %C2 promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
FAIL URLSearchParams constructed with: %C2x assert_array_equals: property 0, expected "\ufffdx" but got ""
-FAIL request.formData() with input: %C2x undefined is not a function (near '...s-1252"} }).formData()...')
-FAIL response.formData() with input: %C2x promise_test: Unhandled rejection with value: "Not implemented"
+FAIL request.formData() with input: %C2x promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
+FAIL response.formData() with input: %C2x promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
FAIL URLSearchParams constructed with: _charset_=windows-1252&test=%C2x assert_array_equals: property 1, expected "\ufffdx" but got ""
-FAIL request.formData() with input: _charset_=windows-1252&test=%C2x undefined is not a function (near '...s-1252"} }).formData()...')
-FAIL response.formData() with input: _charset_=windows-1252&test=%C2x promise_test: Unhandled rejection with value: "Not implemented"
+FAIL request.formData() with input: _charset_=windows-1252&test=%C2x promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
+FAIL response.formData() with input: _charset_=windows-1252&test=%C2x promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
PASS URLSearchParams constructed with:
-FAIL request.formData() with input: undefined is not a function (near '...s-1252"} }).formData()...')
-FAIL response.formData() with input: promise_test: Unhandled rejection with value: "Not implemented"
+FAIL request.formData() with input: promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
+FAIL response.formData() with input: promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
PASS URLSearchParams constructed with: a
-FAIL request.formData() with input: a undefined is not a function (near '...s-1252"} }).formData()...')
-FAIL response.formData() with input: a promise_test: Unhandled rejection with value: "Not implemented"
+FAIL request.formData() with input: a promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
+FAIL response.formData() with input: a promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
PASS URLSearchParams constructed with: a=b
-FAIL request.formData() with input: a=b undefined is not a function (near '...s-1252"} }).formData()...')
-FAIL response.formData() with input: a=b promise_test: Unhandled rejection with value: "Not implemented"
+FAIL request.formData() with input: a=b promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
+FAIL response.formData() with input: a=b promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
PASS URLSearchParams constructed with: a=
-FAIL request.formData() with input: a= undefined is not a function (near '...s-1252"} }).formData()...')
-FAIL response.formData() with input: a= promise_test: Unhandled rejection with value: "Not implemented"
+FAIL request.formData() with input: a= promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
+FAIL response.formData() with input: a= promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
PASS URLSearchParams constructed with: =b
-FAIL request.formData() with input: =b undefined is not a function (near '...s-1252"} }).formData()...')
-FAIL response.formData() with input: =b promise_test: Unhandled rejection with value: "Not implemented"
+FAIL request.formData() with input: =b promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
+FAIL response.formData() with input: =b promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
PASS URLSearchParams constructed with: &
-FAIL request.formData() with input: & undefined is not a function (near '...s-1252"} }).formData()...')
-FAIL response.formData() with input: & promise_test: Unhandled rejection with value: "Not implemented"
+FAIL request.formData() with input: & promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
+FAIL response.formData() with input: & promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
PASS URLSearchParams constructed with: &a
-FAIL request.formData() with input: &a undefined is not a function (near '...s-1252"} }).formData()...')
-FAIL response.formData() with input: &a promise_test: Unhandled rejection with value: "Not implemented"
+FAIL request.formData() with input: &a promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
+FAIL response.formData() with input: &a promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
PASS URLSearchParams constructed with: a&
-FAIL request.formData() with input: a& undefined is not a function (near '...s-1252"} }).formData()...')
-FAIL response.formData() with input: a& promise_test: Unhandled rejection with value: "Not implemented"
+FAIL request.formData() with input: a& promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
+FAIL response.formData() with input: a& promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
PASS URLSearchParams constructed with: a&a
-FAIL request.formData() with input: a&a undefined is not a function (near '...s-1252"} }).formData()...')
-FAIL response.formData() with input: a&a promise_test: Unhandled rejection with value: "Not implemented"
+FAIL request.formData() with input: a&a promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
+FAIL response.formData() with input: a&a promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
PASS URLSearchParams constructed with: a&b&c
-FAIL request.formData() with input: a&b&c undefined is not a function (near '...s-1252"} }).formData()...')
-FAIL response.formData() with input: a&b&c promise_test: Unhandled rejection with value: "Not implemented"
+FAIL request.formData() with input: a&b&c promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
+FAIL response.formData() with input: a&b&c promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
PASS URLSearchParams constructed with: a=b&c=d
-FAIL request.formData() with input: a=b&c=d undefined is not a function (near '...s-1252"} }).formData()...')
-FAIL response.formData() with input: a=b&c=d promise_test: Unhandled rejection with value: "Not implemented"
+FAIL request.formData() with input: a=b&c=d promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
+FAIL response.formData() with input: a=b&c=d promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
PASS URLSearchParams constructed with: a=b&c=d&
-FAIL request.formData() with input: a=b&c=d& undefined is not a function (near '...s-1252"} }).formData()...')
-FAIL response.formData() with input: a=b&c=d& promise_test: Unhandled rejection with value: "Not implemented"
+FAIL request.formData() with input: a=b&c=d& promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
+FAIL response.formData() with input: a=b&c=d& promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
PASS URLSearchParams constructed with: &&&a=b&&&&c=d&
-FAIL request.formData() with input: &&&a=b&&&&c=d& undefined is not a function (near '...s-1252"} }).formData()...')
-FAIL response.formData() with input: &&&a=b&&&&c=d& promise_test: Unhandled rejection with value: "Not implemented"
+FAIL request.formData() with input: &&&a=b&&&&c=d& promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
+FAIL response.formData() with input: &&&a=b&&&&c=d& promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
PASS URLSearchParams constructed with: a=a&a=b&a=c
-FAIL request.formData() with input: a=a&a=b&a=c undefined is not a function (near '...s-1252"} }).formData()...')
-FAIL response.formData() with input: a=a&a=b&a=c promise_test: Unhandled rejection with value: "Not implemented"
+FAIL request.formData() with input: a=a&a=b&a=c promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
+FAIL response.formData() with input: a=a&a=b&a=c promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
PASS URLSearchParams constructed with: a==a
-FAIL request.formData() with input: a==a undefined is not a function (near '...s-1252"} }).formData()...')
-FAIL response.formData() with input: a==a promise_test: Unhandled rejection with value: "Not implemented"
+FAIL request.formData() with input: a==a promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
+FAIL response.formData() with input: a==a promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
PASS URLSearchParams constructed with: a=a+b+c+d
-FAIL request.formData() with input: a=a+b+c+d undefined is not a function (near '...s-1252"} }).formData()...')
-FAIL response.formData() with input: a=a+b+c+d promise_test: Unhandled rejection with value: "Not implemented"
+FAIL request.formData() with input: a=a+b+c+d promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
+FAIL response.formData() with input: a=a+b+c+d promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
PASS URLSearchParams constructed with: %=a
-FAIL request.formData() with input: %=a undefined is not a function (near '...s-1252"} }).formData()...')
-FAIL response.formData() with input: %=a promise_test: Unhandled rejection with value: "Not implemented"
+FAIL request.formData() with input: %=a promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
+FAIL response.formData() with input: %=a promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
PASS URLSearchParams constructed with: %a=a
-FAIL request.formData() with input: %a=a undefined is not a function (near '...s-1252"} }).formData()...')
-FAIL response.formData() with input: %a=a promise_test: Unhandled rejection with value: "Not implemented"
+FAIL request.formData() with input: %a=a promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
+FAIL response.formData() with input: %a=a promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
PASS URLSearchParams constructed with: %a_=a
-FAIL request.formData() with input: %a_=a undefined is not a function (near '...s-1252"} }).formData()...')
-FAIL response.formData() with input: %a_=a promise_test: Unhandled rejection with value: "Not implemented"
+FAIL request.formData() with input: %a_=a promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
+FAIL response.formData() with input: %a_=a promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
PASS URLSearchParams constructed with: %61=a
-FAIL request.formData() with input: %61=a undefined is not a function (near '...s-1252"} }).formData()...')
-FAIL response.formData() with input: %61=a promise_test: Unhandled rejection with value: "Not implemented"
+FAIL request.formData() with input: %61=a promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
+FAIL response.formData() with input: %61=a promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
PASS URLSearchParams constructed with: %61+%4d%4D=
-FAIL request.formData() with input: %61+%4d%4D= undefined is not a function (near '...s-1252"} }).formData()...')
-FAIL response.formData() with input: %61+%4d%4D= promise_test: Unhandled rejection with value: "Not implemented"
+FAIL request.formData() with input: %61+%4d%4D= promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
+FAIL response.formData() with input: %61+%4d%4D= promise_test: Unhandled rejection with value: object "NotSupportedError: The operation is not supported."
Modified: trunk/Source/WebCore/ChangeLog (221771 => 221772)
--- trunk/Source/WebCore/ChangeLog 2017-09-07 23:18:04 UTC (rev 221771)
+++ trunk/Source/WebCore/ChangeLog 2017-09-07 23:23:57 UTC (rev 221772)
@@ -1,3 +1,69 @@
+2017-09-07 Youenn Fablet <[email protected]>
+
+ Align FetchResponse and FetchRequest body handling
+ https://bugs.webkit.org/show_bug.cgi?id=176539
+
+ Reviewed by Alex Christensen.
+
+ Covered by rebased tests.
+
+ Removing most of FetchResponse JS Builtins now that ReadableStream has full support.
+ Implementing FetchResponse body cloning through ReadableStream.
+ Cloning a loading FetchResponse still requires to create a ReadableStream for the purpose of teeing.
+
+ Moving exposure of the body from FetchResponse to FetchBodyOwner.
+ This is controlled by a boolean flag set according response tainting.
+
+ Moving handling of body ReadableStream consuming from FetchResponse to FetchBodyConsumer.
+ For that purpose, a loading boolean flag is added to FetchBodyConsumer so that it will resolve consume promises
+ when loading is finished.
+
+ Added support for getting a body in case the request/response body is already consumed.
+ In that case, a locked ReadableStream is returned.
+
+ * Modules/cache/DOMCache.cpp:
+ (WebCore::DOMCache::doMatch):
+ (WebCore::DOMCache::matchAll):
+ * Modules/fetch/FetchBody.h:
+ (WebCore::FetchBody::loadingBody):
+ (WebCore::FetchBody::FetchBody):
+ * Modules/fetch/FetchBody.idl:
+ * Modules/fetch/FetchBodyConsumer.cpp:
+ (WebCore::FetchBodyConsumer::resolve):
+ (WebCore::FetchBodyConsumer::loadingFailed):
+ (WebCore::FetchBodyConsumer::loadingSucceeded):
+ * Modules/fetch/FetchBodyConsumer.h:
+ (WebCore::FetchBodyConsumer::setAsLoading):
+ * Modules/fetch/FetchBodyOwner.cpp:
+ (WebCore::FetchBodyOwner::arrayBuffer):
+ (WebCore::FetchBodyOwner::blob):
+ (WebCore::FetchBodyOwner::formData):
+ (WebCore::FetchBodyOwner::json):
+ (WebCore::FetchBodyOwner::text):
+ (WebCore::FetchBodyOwner::readableStream):
+ * Modules/fetch/FetchBodyOwner.h:
+ (WebCore::FetchBodyOwner::isBodyNullOrOpaque const):
+ (WebCore::FetchBodyOwner::setBodyAsOpaque):
+ (WebCore::FetchBodyOwner::isBodyOpaque const):
+ * Modules/fetch/FetchInternals.js:
+ (fillFetchHeaders):
+ * Modules/fetch/FetchResponse.cpp:
+ (WebCore::FetchResponse::clone):
+ (WebCore::FetchResponse::fetch):
+ (WebCore::FetchResponse::BodyLoader::didReceiveResponse):
+ (WebCore::FetchResponse::setBodyData):
+ (WebCore::FetchResponse::consumeChunk):
+ (WebCore::FetchResponse::consumeBodyAsStream):
+ * Modules/fetch/FetchResponse.h:
+ * Modules/fetch/FetchResponse.idl:
+ * Modules/fetch/FetchResponse.js:
+ (initializeFetchResponse):
+ * bindings/js/ReadableStream.cpp:
+ (WebCore::ReadableStream::create):
+ (WebCore::ReadableStream::lock):
+ * bindings/js/ReadableStream.h:
+ * bindings/js/WebCoreBuiltinNames.h:
+
2017-09-07 Michael Saboff <[email protected]>
Add support for RegExp named capture groups
Modified: trunk/Source/WebCore/Modules/cache/DOMCache.cpp (221771 => 221772)
--- trunk/Source/WebCore/Modules/cache/DOMCache.cpp 2017-09-07 23:18:04 UTC (rev 221771)
+++ trunk/Source/WebCore/Modules/cache/DOMCache.cpp 2017-09-07 23:23:57 UTC (rev 221772)
@@ -82,7 +82,7 @@
}
auto request = requestOrException.releaseReturnValue();
- queryCache(request.get(), WTFMove(options), [callback = WTFMove(callback)](ExceptionOr<Vector<CacheStorageRecord>>&& result) mutable {
+ queryCache(request.get(), WTFMove(options), [this, callback = WTFMove(callback)](ExceptionOr<Vector<CacheStorageRecord>>&& result) mutable {
if (result.hasException()) {
callback(result.releaseException());
return;
@@ -91,7 +91,7 @@
callback(nullptr);
return;
}
- callback(result.returnValue()[0].response->cloneForJS().ptr());
+ callback(result.returnValue()[0].response->clone(*scriptExecutionContext()).releaseReturnValue().ptr());
});
}
@@ -119,12 +119,12 @@
Vector<Ref<FetchResponse>> responses;
responses.reserveInitialCapacity(m_records.size());
for (auto& record : m_records)
- responses.uncheckedAppend(record.response->cloneForJS());
- promise.resolve(responses);
+ responses.uncheckedAppend(record.response->clone(*scriptExecutionContext()).releaseReturnValue());
+ promise.resolve(WTFMove(responses));
});
return;
}
- queryCache(request.releaseNonNull(), WTFMove(options), [promise = WTFMove(promise)](ExceptionOr<Vector<CacheStorageRecord>>&& result) mutable {
+ queryCache(request.releaseNonNull(), WTFMove(options), [this, promise = WTFMove(promise)](ExceptionOr<Vector<CacheStorageRecord>>&& result) mutable {
if (result.hasException()) {
promise.reject(result.releaseException());
return;
@@ -133,7 +133,7 @@
Vector<Ref<FetchResponse>> responses;
responses.reserveInitialCapacity(records.size());
for (auto& record : records)
- responses.uncheckedAppend(record.response->cloneForJS());
+ responses.uncheckedAppend(record.response->clone(*scriptExecutionContext()).releaseReturnValue());
promise.resolve(responses);
});
}
Modified: trunk/Source/WebCore/Modules/fetch/FetchBody.h (221771 => 221772)
--- trunk/Source/WebCore/Modules/fetch/FetchBody.h 2017-09-07 23:18:04 UTC (rev 221771)
+++ trunk/Source/WebCore/Modules/fetch/FetchBody.h 2017-09-07 23:23:57 UTC (rev 221772)
@@ -64,7 +64,7 @@
using Init = Variant<RefPtr<Blob>, RefPtr<ArrayBufferView>, RefPtr<ArrayBuffer>, RefPtr<DOMFormData>, RefPtr<URLSearchParams>, RefPtr<ReadableStream>, String>;
static FetchBody extract(ScriptExecutionContext&, Init&&, String&);
- static FetchBody loadingBody() { return { }; }
+ FetchBody() = default;
void loadingFailed();
void loadingSucceeded();
@@ -98,7 +98,6 @@
explicit FetchBody(Ref<const URLSearchParams>&& data) : m_data(WTFMove(data)) { }
explicit FetchBody(const FetchBodyConsumer& consumer) : m_consumer(consumer) { }
explicit FetchBody(Ref<ReadableStream>&& stream) : m_readableStream(WTFMove(stream)) { }
- FetchBody() = default;
void consume(FetchBodyOwner&, Ref<DeferredPromise>&&);
Modified: trunk/Source/WebCore/Modules/fetch/FetchBody.idl (221771 => 221772)
--- trunk/Source/WebCore/Modules/fetch/FetchBody.idl 2017-09-07 23:18:04 UTC (rev 221771)
+++ trunk/Source/WebCore/Modules/fetch/FetchBody.idl 2017-09-07 23:23:57 UTC (rev 221772)
@@ -37,8 +37,7 @@
readonly attribute boolean bodyUsed;
[NewObject] Promise<ArrayBuffer> arrayBuffer();
[NewObject] Promise<Blob> blob();
- // FIXME: Add support for form data consumption (https://bugs.webkit.org/show_bug.cgi?id=161190).
- //[NewObject] Promise<DOMFormData> formData();
+ [NewObject] Promise<DOMFormData> formData();
[NewObject] Promise<any> json();
[NewObject] Promise<USVString> text();
};
Modified: trunk/Source/WebCore/Modules/fetch/FetchBodyConsumer.cpp (221771 => 221772)
--- trunk/Source/WebCore/Modules/fetch/FetchBodyConsumer.cpp 2017-09-07 23:18:04 UTC (rev 221771)
+++ trunk/Source/WebCore/Modules/fetch/FetchBodyConsumer.cpp 2017-09-07 23:23:57 UTC (rev 221772)
@@ -117,6 +117,11 @@
return;
}
+ if (m_isLoading) {
+ m_consumePromise = WTFMove(promise);
+ return;
+ }
+
ASSERT(m_type != Type::None);
switch (m_type) {
case Type::ArrayBuffer:
@@ -207,6 +212,7 @@
void FetchBodyConsumer::loadingFailed()
{
+ m_isLoading = false;
if (m_consumePromise) {
m_consumePromise->reject();
m_consumePromise = nullptr;
@@ -219,6 +225,8 @@
void FetchBodyConsumer::loadingSucceeded()
{
+ m_isLoading = false;
+
if (m_consumePromise)
resolve(m_consumePromise.releaseNonNull(), nullptr);
if (m_source) {
Modified: trunk/Source/WebCore/Modules/fetch/FetchBodyConsumer.h (221771 => 221772)
--- trunk/Source/WebCore/Modules/fetch/FetchBodyConsumer.h 2017-09-07 23:18:04 UTC (rev 221771)
+++ trunk/Source/WebCore/Modules/fetch/FetchBodyConsumer.h 2017-09-07 23:23:57 UTC (rev 221772)
@@ -73,6 +73,8 @@
void setConsumePromise(Ref<DeferredPromise>&&);
void setSource(Ref<FetchBodySource>&&);
+ void setAsLoading() { m_isLoading = true; }
+
private:
Type m_type;
String m_contentType;
@@ -80,6 +82,7 @@
RefPtr<DeferredPromise> m_consumePromise;
RefPtr<ReadableStreamToSharedBufferSink> m_sink;
RefPtr<FetchBodySource> m_source;
+ bool m_isLoading { false };
};
} // namespace WebCore
Modified: trunk/Source/WebCore/Modules/fetch/FetchBodyOwner.cpp (221771 => 221772)
--- trunk/Source/WebCore/Modules/fetch/FetchBodyOwner.cpp 2017-09-07 23:18:04 UTC (rev 221771)
+++ trunk/Source/WebCore/Modules/fetch/FetchBodyOwner.cpp 2017-09-07 23:23:57 UTC (rev 221772)
@@ -93,7 +93,7 @@
void FetchBodyOwner::arrayBuffer(Ref<DeferredPromise>&& promise)
{
- if (isBodyNull()) {
+ if (isBodyNullOrOpaque()) {
fulfillPromiseWithArrayBuffer(WTFMove(promise), nullptr, 0);
return;
}
@@ -107,7 +107,7 @@
void FetchBodyOwner::blob(Ref<DeferredPromise>&& promise)
{
- if (isBodyNull()) {
+ if (isBodyNullOrOpaque()) {
promise->resolve<IDLInterface<Blob>>(Blob::create({ }, Blob::normalizedContentType(extractMIMETypeFromMediaType(m_contentType))));
return;
}
@@ -153,30 +153,9 @@
m_body->consumeOnceLoadingFinished(type, WTFMove(promise), m_contentType);
}
-void FetchBodyOwner::consumeNullBody(FetchBodyConsumer::Type consumerType, Ref<DeferredPromise>&& promise)
-{
- switch (consumerType) {
- case FetchBodyConsumer::Type::ArrayBuffer:
- fulfillPromiseWithArrayBuffer(WTFMove(promise), nullptr, 0);
- return;
- case FetchBodyConsumer::Type::Blob:
- promise->resolve<IDLInterface<Blob>>(Blob::create({ }, String()));
- return;
- case FetchBodyConsumer::Type::JSON:
- promise->reject(SyntaxError);
- return;
- case FetchBodyConsumer::Type::Text:
- promise->resolve<IDLDOMString>({ });
- return;
- case FetchBodyConsumer::Type::None:
- ASSERT_NOT_REACHED();
- return;
- }
-}
-
void FetchBodyOwner::formData(Ref<DeferredPromise>&& promise)
{
- if (isBodyNull()) {
+ if (isBodyNullOrOpaque()) {
promise->reject();
return;
}
@@ -190,7 +169,7 @@
void FetchBodyOwner::json(Ref<DeferredPromise>&& promise)
{
- if (isBodyNull()) {
+ if (isBodyNullOrOpaque()) {
promise->reject(SyntaxError);
return;
}
@@ -204,7 +183,7 @@
void FetchBodyOwner::text(Ref<DeferredPromise>&& promise)
{
- if (isBodyNull()) {
+ if (isBodyNullOrOpaque()) {
promise->resolve<IDLDOMString>({ });
return;
}
@@ -313,8 +292,13 @@
if (!m_body->hasReadableStream()) {
ASSERT(!m_readableStreamSource);
- m_readableStreamSource = adoptRef(*new FetchBodySource(*this));
- m_body->setReadableStream(ReadableStream::create(state, m_readableStreamSource));
+ if (isDisturbed()) {
+ m_body->setReadableStream(ReadableStream::create(state, nullptr));
+ m_body->readableStream()->lock();
+ } else {
+ m_readableStreamSource = adoptRef(*new FetchBodySource(*this));
+ m_body->setReadableStream(ReadableStream::create(state, m_readableStreamSource));
+ }
}
return m_body->readableStream();
}
Modified: trunk/Source/WebCore/Modules/fetch/FetchBodyOwner.h (221771 => 221772)
--- trunk/Source/WebCore/Modules/fetch/FetchBodyOwner.h 2017-09-07 23:18:04 UTC (rev 221771)
+++ trunk/Source/WebCore/Modules/fetch/FetchBodyOwner.h 2017-09-07 23:23:57 UTC (rev 221772)
@@ -68,12 +68,12 @@
const FetchBody& body() const { return *m_body; }
FetchBody& body() { return *m_body; }
bool isBodyNull() const { return !m_body; }
+ bool isBodyNullOrOpaque() const { return !m_body || m_isBodyOpaque; }
void cloneBody(FetchBodyOwner&);
void extractBody(ScriptExecutionContext&, FetchBody::Init&&);
void updateContentType();
void consumeOnceLoadingFinished(FetchBodyConsumer::Type, Ref<DeferredPromise>&&);
- void consumeNullBody(FetchBodyConsumer::Type, Ref<DeferredPromise>&&);
void setBody(FetchBody&& body) { m_body = WTFMove(body); }
@@ -82,6 +82,9 @@
void setDisturbed() { m_isDisturbed = true; }
+ void setBodyAsOpaque() { m_isBodyOpaque = true; }
+ bool isBodyOpaque() const { return m_isBodyOpaque; }
+
private:
// Blob loading routines
void blobChunk(const char*, size_t);
@@ -113,6 +116,7 @@
private:
std::optional<BlobLoader> m_blobLoader;
+ bool m_isBodyOpaque { false };
};
} // namespace WebCore
Modified: trunk/Source/WebCore/Modules/fetch/FetchInternals.js (221771 => 221772)
--- trunk/Source/WebCore/Modules/fetch/FetchInternals.js 2017-09-07 23:18:04 UTC (rev 221771)
+++ trunk/Source/WebCore/Modules/fetch/FetchInternals.js 2017-09-07 23:23:57 UTC (rev 221772)
@@ -53,27 +53,3 @@
@Headers.prototype.@appendFromJS.@call(headers, name, headersInit[name]);
}
}
-
-function consumeStream(response, type)
-{
- @assert(response instanceof @Response);
- @assert(response.@body instanceof @ReadableStream);
-
- if (@isReadableStreamDisturbed(response.@body))
- return @Promise.@reject(new @TypeError("Cannot consume a disturbed Response body ReadableStream"));
-
- try {
- let reader = new @ReadableStreamDefaultReader(response.@body);
-
- @Response.prototype.@startConsumingStream.@call(response, type);
- let pull = (result) => {
- if (result.done)
- return @Response.prototype.@finishConsumingStream.@call(response);
- @Response.prototype.@consumeChunk.@call(response, result.value);
- return @Promise.prototype.@then.@call(@readableStreamDefaultReaderRead(reader), pull);
- }
- return @Promise.prototype.@then.@call(@readableStreamDefaultReaderRead(reader), pull);
- } catch (e) {
- return @Promise.@reject(e);
- }
-}
Modified: trunk/Source/WebCore/Modules/fetch/FetchResponse.cpp (221771 => 221772)
--- trunk/Source/WebCore/Modules/fetch/FetchResponse.cpp 2017-09-07 23:18:04 UTC (rev 221771)
+++ trunk/Source/WebCore/Modules/fetch/FetchResponse.cpp 2017-09-07 23:23:57 UTC (rev 221772)
@@ -85,14 +85,20 @@
{
}
-Ref<FetchResponse> FetchResponse::cloneForJS()
+ExceptionOr<Ref<FetchResponse>> FetchResponse::clone(ScriptExecutionContext& context)
{
+ if (isDisturbedOrLocked())
+ return Exception { TypeError };
+
ASSERT(scriptExecutionContext());
- ASSERT(!isDisturbedOrLocked());
- auto clone = adoptRef(*new FetchResponse(*scriptExecutionContext(), std::nullopt, FetchHeaders::create(headers()), ResourceResponse(m_response)));
+ // If loading, let's create a stream so that data is teed on both clones.
+ if (isLoading())
+ readableStream(*context.execState());
+
+ auto clone = adoptRef(*new FetchResponse(context, std::nullopt, FetchHeaders::create(headers()), ResourceResponse(m_response)));
clone->cloneBody(*this);
- return clone;
+ return WTFMove(clone);
}
void FetchResponse::fetch(ScriptExecutionContext& context, FetchRequest& request, NotificationCallback&& responseCallback)
@@ -102,8 +108,10 @@
responseCallback(Exception { NotSupportedError, "ReadableStream uploading is not supported" });
return;
}
- auto response = adoptRef(*new FetchResponse(context, FetchBody::loadingBody(), FetchHeaders::create(FetchHeaders::Guard::Immutable), { }));
+ auto response = adoptRef(*new FetchResponse(context, FetchBody { }, FetchHeaders::create(FetchHeaders::Guard::Immutable), { }));
+ response->body().consumer().setAsLoading();
+
response->m_bodyLoader.emplace(response.get(), WTFMove(responseCallback));
if (!response->m_bodyLoader->start(context, request))
response->m_bodyLoader = std::nullopt;
@@ -173,7 +181,8 @@
void FetchResponse::BodyLoader::didReceiveResponse(const ResourceResponse& resourceResponse)
{
m_response.m_response = ResourceResponseBase::filter(resourceResponse);
- m_response.m_shouldExposeBody = resourceResponse.tainting() != ResourceResponse::Tainting::Opaque;
+ if (resourceResponse.tainting() == ResourceResponse::Tainting::Opaque)
+ m_response.setBodyAsOpaque();
m_response.m_headers->filterAndFill(m_response.m_response.httpHeaderFields(), FetchHeaders::Guard::Response);
m_response.updateContentType();
@@ -222,40 +231,6 @@
m_loader->stop();
}
-void FetchResponse::consume(unsigned type, Ref<DeferredPromise>&& wrapper)
-{
- ASSERT(type <= static_cast<unsigned>(FetchBodyConsumer::Type::Text));
- auto consumerType = static_cast<FetchBodyConsumer::Type>(type);
-
- if (!m_shouldExposeBody) {
- consumeNullBody(consumerType, WTFMove(wrapper));
- return;
- }
-
- if (isLoading()) {
- consumeOnceLoadingFinished(consumerType, WTFMove(wrapper));
- return;
- }
-
- switch (consumerType) {
- case FetchBodyConsumer::Type::ArrayBuffer:
- arrayBuffer(WTFMove(wrapper));
- return;
- case FetchBodyConsumer::Type::Blob:
- blob(WTFMove(wrapper));
- return;
- case FetchBodyConsumer::Type::JSON:
- json(WTFMove(wrapper));
- return;
- case FetchBodyConsumer::Type::Text:
- text(WTFMove(wrapper));
- return;
- case FetchBodyConsumer::Type::None:
- ASSERT_NOT_REACHED();
- return;
- }
-}
-
FetchResponse::ResponseData FetchResponse::consumeBody()
{
ASSERT(!isLoading());
@@ -294,38 +269,24 @@
{
WTF::switchOn(data, [this](Ref<FormData>& formData) {
if (isBodyNull())
- setBody(FetchBody::loadingBody());
+ setBody({ });
body().setAsFormData(WTFMove(formData));
}, [this](Ref<SharedBuffer>& buffer) {
if (isBodyNull())
- setBody(FetchBody::loadingBody());
+ setBody({ });
body().consumer().setData(WTFMove(buffer));
}, [](std::nullptr_t&) { });
}
#if ENABLE(STREAMS_API)
-void FetchResponse::startConsumingStream(unsigned type)
-{
- m_isDisturbed = true;
- auto consumerType = static_cast<FetchBodyConsumer::Type>(type);
- m_consumer.setType(consumerType);
- if (consumerType == FetchBodyConsumer::Type::Blob)
- m_consumer.setContentType(Blob::normalizedContentType(extractMIMETypeFromMediaType(m_contentType)));
-}
-
void FetchResponse::consumeChunk(Ref<JSC::Uint8Array>&& chunk)
{
- m_consumer.append(chunk->data(), chunk->byteLength());
+ body().consumer().append(chunk->data(), chunk->byteLength());
}
-void FetchResponse::finishConsumingStream(Ref<DeferredPromise>&& promise)
-{
- m_consumer.resolve(WTFMove(promise), nullptr);
-}
-
void FetchResponse::consumeBodyAsStream()
{
- ASSERT(m_shouldExposeBody);
+ ASSERT(!isBodyOpaque());
ASSERT(m_readableStreamSource);
if (!isLoading()) {
FetchBodyOwner::consumeBodyAsStream();
@@ -334,10 +295,6 @@
ASSERT(m_bodyLoader);
- if (isBodyNull())
- setBody(FetchBody::loadingBody());
- updateContentType();
-
auto data = ""
if (data) {
if (!m_readableStreamSource->enqueue(data->tryCreateArrayBuffer())) {
@@ -375,14 +332,6 @@
closeStream();
}
-RefPtr<ReadableStream> FetchResponse::createReadableStream(JSC::ExecState& state)
-{
- if (!m_shouldExposeBody)
- return nullptr;
-
- return FetchBodyOwner::readableStream(state);
-}
-
RefPtr<SharedBuffer> FetchResponse::BodyLoader::startStreaming()
{
ASSERT(m_loader);
Modified: trunk/Source/WebCore/Modules/fetch/FetchResponse.h (221771 => 221772)
--- trunk/Source/WebCore/Modules/fetch/FetchResponse.h 2017-09-07 23:18:04 UTC (rev 221771)
+++ trunk/Source/WebCore/Modules/fetch/FetchResponse.h 2017-09-07 23:23:57 UTC (rev 221772)
@@ -62,7 +62,6 @@
using NotificationCallback = WTF::Function<void(ExceptionOr<FetchResponse&>&&)>;
static void fetch(ScriptExecutionContext&, FetchRequest&, NotificationCallback&&);
- void consume(unsigned, Ref<DeferredPromise>&&);
#if ENABLE(STREAMS_API)
void startConsumingStream(unsigned);
void consumeChunk(Ref<JSC::Uint8Array>&&);
@@ -81,10 +80,9 @@
const FetchHeaders& headers() const { return m_headers; }
FetchHeaders& headers() { return m_headers; }
- Ref<FetchResponse> cloneForJS();
+ ExceptionOr<Ref<FetchResponse>> clone(ScriptExecutionContext&);
#if ENABLE(STREAMS_API)
- RefPtr<ReadableStream> createReadableStream(JSC::ExecState&);
void consumeBodyAsStream() final;
void feedStream() final;
void cancel() final;
@@ -143,9 +141,6 @@
ResourceResponse m_response;
std::optional<BodyLoader> m_bodyLoader;
mutable String m_responseURL;
- bool m_shouldExposeBody { true };
-
- FetchBodyConsumer m_consumer { FetchBodyConsumer::Type::ArrayBuffer };
};
} // namespace WebCore
Modified: trunk/Source/WebCore/Modules/fetch/FetchResponse.idl (221771 => 221772)
--- trunk/Source/WebCore/Modules/fetch/FetchResponse.idl 2017-09-07 23:18:04 UTC (rev 221771)
+++ trunk/Source/WebCore/Modules/fetch/FetchResponse.idl 2017-09-07 23:23:57 UTC (rev 221772)
@@ -45,8 +45,6 @@
InterfaceName=Response,
JSBuiltinConstructor,
// Constructor(optional BodyInit? body = null, optional FetchResponseInit init)
- PrivateIdentifier,
- PublicIdentifier,
] interface FetchResponse {
[CallWith=ScriptExecutionContext, NewObject] static FetchResponse error();
[CallWith=ScriptExecutionContext, MayThrowException, NewObject] static FetchResponse redirect(USVString url, optional unsigned short status = 302);
@@ -62,27 +60,10 @@
// FIXME: Add support for trailers.
// readonly attribute Promise<Headers> trailer;
- [JSBuiltin] FetchResponse clone();
+ [CallWith=ScriptExecutionContext, MayThrowException, NewObject] FetchResponse clone();
-
- // FIXME: Copy of FetchBody IDL as we want to implement some of these as built-ins.
- // This should be a FetchResponse implements FetchBody;
- [JSBuiltin] readonly attribute ReadableStream? body;
- [JSBuiltin] readonly attribute boolean bodyUsed;
- [JSBuiltin] Promise<ArrayBuffer> arrayBuffer();
- [JSBuiltin] Promise<Blob> blob();
- [JSBuiltin] Promise<Blob> formData();
- [JSBuiltin] Promise<any> json();
- [JSBuiltin] Promise<USVString> text();
-
- [NewObject, PrivateIdentifier] FetchResponse cloneForJS();
- [Conditional=STREAMS_API, PrivateIdentifier] void startConsumingStream(unsigned short type);
- [Conditional=STREAMS_API, PrivateIdentifier] void consumeChunk(Uint8Array chunk);
- [Conditional=STREAMS_API, PrivateIdentifier] Promise<any> finishConsumingStream();
- [PrivateIdentifier] Promise<any> consume(unsigned short type);
- [PrivateIdentifier] boolean isLoading();
[MayThrowException, PrivateIdentifier] void setStatus(unsigned short status, DOMString statusText);
[PrivateIdentifier] void initializeWith(BodyInit body);
- [CallWith=ScriptState, NewObject, PrivateIdentifier] ReadableStream? createReadableStream();
- [PrivateIdentifier] boolean isDisturbed();
};
+
+FetchResponse implements FetchBody;
Modified: trunk/Source/WebCore/Modules/fetch/FetchResponse.js (221771 => 221772)
--- trunk/Source/WebCore/Modules/fetch/FetchResponse.js 2017-09-07 23:18:04 UTC (rev 221771)
+++ trunk/Source/WebCore/Modules/fetch/FetchResponse.js 2017-09-07 23:23:57 UTC (rev 221772)
@@ -47,118 +47,8 @@
if (status === 101 || status === 204 || status === 205 || status === 304)
@throwTypeError("Response cannot have a body with the given status");
- // FIXME: Use @isReadableStream once it is no longer guarded by STREAMS_API compilation guard.
- let isBodyReadableStream = (@isObject(body) && !!body.@readableStreamController);
- if (isBodyReadableStream)
- this.@body = body;
this.@initializeWith(body);
}
return this;
}
-
-@getter
-function bodyUsed()
-{
- if (!(this instanceof @Response))
- throw @makeGetterTypeError("Response", "bodyUsed");
-
- if (this.@body)
- return @isReadableStreamDisturbed(this.@body);
-
- return @Response.prototype.@isDisturbed.@call(this);
-}
-
-@getter
-function body()
-{
- if (!(this instanceof @Response))
- throw @makeGetterTypeError("Response", "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
- this.@body = @Response.prototype.@createReadableStream.@call(this);
- }
- return this.@body;
-}
-
-function clone()
-{
- if (!(this instanceof @Response))
- throw @makeThisTypeError("Response", "clone");
-
- if (@Response.prototype.@isDisturbed.@call(this) || (this.@body && @isReadableStreamLocked(this.@body)))
- @throwTypeError("Cannot clone a disturbed Response");
-
- // Let's create @body if response body is loading to provide data to both clones.
- if (@Response.prototype.@isLoading.@call(this) && this.@body === @undefined)
- this.@body = @Response.prototype.@createReadableStream.@call(this);
-
- var cloned = @Response.prototype.@cloneForJS.@call(this);
-
- // Let's refresh @body with the cloned stream.
- this.@body = @Response.prototype.@createReadableStream.@call(this);
-
- return cloned;
-}
-
-// consume and consumeStream single parameter should be kept in sync with FetchBodyConsumer::Type.
-function arrayBuffer()
-{
- if (!(this instanceof @Response))
- return @Promise.@reject(@makeThisTypeError("Response", "arrayBuffer"));
-
- const arrayBufferConsumerType = 1;
- if (!this.@body)
- return @Response.prototype.@consume.@call(this, arrayBufferConsumerType);
-
- return @consumeStream(this, arrayBufferConsumerType);
-}
-
-function blob()
-{
- if (!(this instanceof @Response))
- return @Promise.@reject(@makeThisTypeError("Response", "blob"));
-
- const blobConsumerType = 2;
- if (!this.@body)
- return @Response.prototype.@consume.@call(this, blobConsumerType);
-
- return @consumeStream(this, blobConsumerType);
-}
-
-function formData()
-{
- if (!(this instanceof @Response))
- return @Promise.@reject(@makeThisTypeError("Response", "formData"));
-
- return @Promise.@reject("Not implemented");
-}
-
-function json()
-{
- if (!(this instanceof @Response))
- return @Promise.@reject(@makeThisTypeError("Response", "json"));
-
- const jsonConsumerType = 3;
- if (!this.@body)
- return @Response.prototype.@consume.@call(this, jsonConsumerType);
-
- return @consumeStream(this, jsonConsumerType);
-}
-
-function text()
-{
- if (!(this instanceof @Response))
- return @Promise.@reject(@makeThisTypeError("Response", "text"));
-
- const textConsumerType = 4;
- if (!this.@body)
- return @Response.prototype.@consume.@call(this, textConsumerType);
-
- return @consumeStream(this, textConsumerType);
-}
Modified: trunk/Source/WebCore/bindings/js/ReadableStream.cpp (221771 => 221772)
--- trunk/Source/WebCore/bindings/js/ReadableStream.cpp 2017-09-07 23:18:04 UTC (rev 221771)
+++ trunk/Source/WebCore/bindings/js/ReadableStream.cpp 2017-09-07 23:23:57 UTC (rev 221772)
@@ -38,6 +38,8 @@
Ref<ReadableStream> ReadableStream::create(JSC::ExecState& execState, RefPtr<ReadableStreamSource>&& source)
{
VM& vm = execState.vm();
+ auto scope = DECLARE_CATCH_SCOPE(vm);
+
auto& clientData = *static_cast<JSVMClientData*>(vm.clientData);
auto& globalObject = *JSC::jsCast<JSDOMGlobalObject*>(execState.lexicalGlobalObject());
@@ -51,6 +53,7 @@
args.append(source ? toJSNewlyCreated(&execState, &globalObject, source.releaseNonNull()) : JSC::jsUndefined());
auto newReadableStream = jsDynamicDowncast<JSReadableStream*>(vm, JSC::construct(&execState, constructor, constructType, constructData, args));
+ scope.assertNoException();
return create(globalObject, *newReadableStream);
}
@@ -101,6 +104,27 @@
return std::make_pair(results[0].releaseNonNull(), results[1].releaseNonNull());
}
+void ReadableStream::lock()
+{
+ auto& state = *m_globalObject->globalExec();
+ VM& vm = state.vm();
+ auto scope = DECLARE_CATCH_SCOPE(vm);
+
+ auto& clientData = *static_cast<JSVMClientData*>(vm.clientData);
+
+ auto* constructor = JSC::asObject(m_globalObject->get(&state, clientData.builtinNames().ReadableStreamDefaultReaderPrivateName()));
+
+ ConstructData constructData;
+ ConstructType constructType = constructor->methodTable(vm)->getConstructData(constructor, constructData);
+ ASSERT(constructType != ConstructType::None);
+
+ MarkedArgumentBuffer args;
+ args.append(readableStream());
+
+ JSC::construct(&state, constructor, constructType, constructData, args);
+ scope.assertNoException();
+}
+
static inline bool checkReadableStream(JSDOMGlobalObject& globalObject, JSReadableStream* readableStream, JSC::JSValue function)
{
auto& state = *globalObject.globalExec();
Modified: trunk/Source/WebCore/bindings/js/ReadableStream.h (221771 => 221772)
--- trunk/Source/WebCore/bindings/js/ReadableStream.h 2017-09-07 23:18:04 UTC (rev 221771)
+++ trunk/Source/WebCore/bindings/js/ReadableStream.h 2017-09-07 23:23:57 UTC (rev 221772)
@@ -45,6 +45,7 @@
std::pair<Ref<ReadableStream>, Ref<ReadableStream>> tee();
+ void lock();
void pipeTo(ReadableStreamSink&);
bool isLocked() const;
bool isDisturbed() const;
Modified: trunk/Source/WebCore/bindings/js/WebCoreBuiltinNames.h (221771 => 221772)
--- trunk/Source/WebCore/bindings/js/WebCoreBuiltinNames.h 2017-09-07 23:18:04 UTC (rev 221771)
+++ trunk/Source/WebCore/bindings/js/WebCoreBuiltinNames.h 2017-09-07 23:23:57 UTC (rev 221772)
@@ -167,7 +167,6 @@
macro(caches) \
macro(cancel) \
macro(cloneArrayBuffer) \
- macro(cloneForJS) \
macro(close) \
macro(closeRequested) \
macro(closed) \