diff --git a/LayoutTests/http/wpt/fetch/fetch-as-blob-expected.txt b/LayoutTests/http/wpt/fetch/fetch-as-blob-expected.txt
deleted file mode 100644
index c70b89c6e5cc..000000000000
--- a/LayoutTests/http/wpt/fetch/fetch-as-blob-expected.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-
-PASS MIME type for Blob from empty body
-PASS MIME type for Blob from empty body with Content-Type
-PASS MIME type for Blob
-PASS MIME type for Blob with non-empty type
-PASS Extract a MIME type with clone
-PASS MIME type unchanged if headers are modified after Request() constructor
-PASS Extract a MIME type (1)
-
diff --git a/LayoutTests/http/wpt/fetch/fetch-as-blob-worker-expected.txt b/LayoutTests/http/wpt/fetch/fetch-as-blob-worker-expected.txt
deleted file mode 100644
index c70b89c6e5cc..000000000000
--- a/LayoutTests/http/wpt/fetch/fetch-as-blob-worker-expected.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-
-PASS MIME type for Blob from empty body
-PASS MIME type for Blob from empty body with Content-Type
-PASS MIME type for Blob
-PASS MIME type for Blob with non-empty type
-PASS Extract a MIME type with clone
-PASS MIME type unchanged if headers are modified after Request() constructor
-PASS Extract a MIME type (1)
-
diff --git a/LayoutTests/http/wpt/fetch/fetch-as-blob-worker.html b/LayoutTests/http/wpt/fetch/fetch-as-blob-worker.html
deleted file mode 100644
index b5b6a160e174..000000000000
--- a/LayoutTests/http/wpt/fetch/fetch-as-blob-worker.html
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
-
- Response body used tests
-
-
-
-
-
-
-
-
-
-
diff --git a/LayoutTests/http/wpt/fetch/fetch-as-blob.html b/LayoutTests/http/wpt/fetch/fetch-as-blob.html
deleted file mode 100644
index a801e8102857..000000000000
--- a/LayoutTests/http/wpt/fetch/fetch-as-blob.html
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
- Response body used tests
-
-
-
-
-
-
-
-
-
diff --git a/LayoutTests/http/wpt/fetch/fetch-as-blob.js b/LayoutTests/http/wpt/fetch/fetch-as-blob.js
deleted file mode 100644
index 0130a8d8d07f..000000000000
--- a/LayoutTests/http/wpt/fetch/fetch-as-blob.js
+++ /dev/null
@@ -1,87 +0,0 @@
-if (self.importScripts) {
- importScripts('/resources/testharness.js');
-}
-
-promise_test(function(t) {
- var req = new Request('http://localhost/',
- {method: 'POST'});
- return req.blob()
- .then(function(blob) {
- assert_equals(blob.type, '');
- });
- }, 'MIME type for Blob from empty body');
-
-promise_test(function(t) {
- var req = new Request('http://localhost/',
- {method: 'POST', headers: [['Content-Type', 'Mytext/Plain']]});
- return req.blob()
- .then(function(blob) {
- assert_equals(blob.type, 'mytext/plain');
- });
- }, 'MIME type for Blob from empty body with Content-Type');
-
-// The 5 following tests are coming from Chromium see fetch/script-tests/request.js
-
-// Tests for MIME types.
-promise_test(function(t) {
- var req = new Request('http://localhost/',
- {method: 'POST', body: new Blob([''])});
- return req.blob()
- .then(function(blob) {
- assert_equals(blob.type, '');
- assert_equals(req.headers.get('Content-Type'), null);
- });
- }, 'MIME type for Blob');
-
-promise_test(function(t) {
- var req = new Request('http://localhost/',
- {method: 'POST',
- body: new Blob([''], {type: 'Text/Plain'})});
- return req.blob()
- .then(function(blob) {
- assert_equals(blob.type, 'text/plain');
- assert_equals(req.headers.get('Content-Type'), 'text/plain');
- });
- }, 'MIME type for Blob with non-empty type');
-
-promise_test(function(t) {
- var req = new Request('http://localhost/',
- {method: 'POST',
- body: new Blob([''], {type: 'Text/Plain'}),
- headers: [['Content-Type', 'Text/Html']]});
- var clone = req.clone();
- return Promise.all([req.blob(), clone.blob()])
- .then(function(blobs) {
- assert_equals(blobs[0].type, 'text/html');
- assert_equals(blobs[1].type, 'text/html');
- assert_equals(req.headers.get('Content-Type'), 'Text/Html');
- assert_equals(clone.headers.get('Content-Type'), 'Text/Html');
- });
- }, 'Extract a MIME type with clone');
-
-promise_test(function(t) {
- var req = new Request('http://localhost/',
- {method: 'POST',
- body: new Blob([''], {type: 'Text/Plain'})});
- req.headers.set('Content-Type', 'Text/Html');
- return req.blob()
- .then(function(blob) {
- assert_equals(blob.type, 'text/plain');
- assert_equals(req.headers.get('Content-Type'), 'Text/Html');
- });
- },
- 'MIME type unchanged if headers are modified after Request() constructor');
-
-promise_test(function(t) {
- var req = new Request('http://localhost/',
- {method: 'POST',
- body: new Blob([''], {type: 'Text/Plain'}),
- headers: [['Content-Type', 'Text/Html']]});
- return req.blob()
- .then(function(blob) {
- assert_equals(blob.type, 'text/html');
- assert_equals(req.headers.get('Content-Type'), 'Text/Html');
- });
- }, 'Extract a MIME type (1)');
-
-done();
diff --git a/LayoutTests/imported/w3c/resources/import-expectations.json b/LayoutTests/imported/w3c/resources/import-expectations.json
index 9be5fcdc7328..76bedf59ea61 100644
--- a/LayoutTests/imported/w3c/resources/import-expectations.json
+++ b/LayoutTests/imported/w3c/resources/import-expectations.json
@@ -236,6 +236,7 @@
"web-platform-tests/feature-policy/resources/": "import",
"web-platform-tests/fetch": "import",
"web-platform-tests/fetch/api": "import",
+ "web-platform-tests/fetch/api/body": "import",
"web-platform-tests/fetch/api/cors": "import",
"web-platform-tests/fetch/api/redirect": "import",
"web-platform-tests/fetch/api/resources": "import",
diff --git a/LayoutTests/imported/w3c/web-platform-tests/fetch/api/body/cloned-any.js b/LayoutTests/imported/w3c/web-platform-tests/fetch/api/body/cloned-any.js
new file mode 100644
index 000000000000..2bca96c7043d
--- /dev/null
+++ b/LayoutTests/imported/w3c/web-platform-tests/fetch/api/body/cloned-any.js
@@ -0,0 +1,50 @@
+// Changing the body after it have been passed to Response/Request
+// should not change the outcome of the consumed body
+
+const url = 'http://a';
+const method = 'post';
+
+promise_test(async t => {
+ const body = new FormData();
+ body.set('a', '1');
+ const res = new Response(body);
+ const req = new Request(url, { method, body });
+ body.set('a', '2');
+ assert_true((await res.formData()).get('a') === '1');
+ assert_true((await req.formData()).get('a') === '1');
+}, 'FormData is cloned');
+
+promise_test(async t => {
+ const body = new URLSearchParams({a: '1'});
+ const res = new Response(body);
+ const req = new Request(url, { method, body });
+ body.set('a', '2');
+ assert_true((await res.formData()).get('a') === '1');
+ assert_true((await req.formData()).get('a') === '1');
+}, 'URLSearchParams is cloned');
+
+promise_test(async t => {
+ const body = new Uint8Array([97]); // a
+ const res = new Response(body);
+ const req = new Request(url, { method, body });
+ body[0] = 98; // b
+ assert_true(await res.text() === 'a');
+ assert_true(await req.text() === 'a');
+}, 'TypedArray is cloned');
+
+promise_test(async t => {
+ const body = new Uint8Array([97]); // a
+ const res = new Response(body.buffer);
+ const req = new Request(url, { method, body: body.buffer });
+ body[0] = 98; // b
+ assert_true(await res.text() === 'a');
+ assert_true(await req.text() === 'a');
+}, 'ArrayBuffer is cloned');
+
+promise_test(async t => {
+ const body = new Blob(['a']);
+ const res = new Response(body);
+ const req = new Request(url, { method, body });
+ assert_true(await res.blob() !== body);
+ assert_true(await req.blob() !== body);
+}, 'Blob is cloned');
diff --git a/LayoutTests/imported/w3c/web-platform-tests/fetch/api/body/mime-type.any-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/fetch/api/body/mime-type.any-expected.txt
index 9c98917b4411..a1935e3a2fdb 100644
--- a/LayoutTests/imported/w3c/web-platform-tests/fetch/api/body/mime-type.any-expected.txt
+++ b/LayoutTests/imported/w3c/web-platform-tests/fetch/api/body/mime-type.any-expected.txt
@@ -1,8 +1,22 @@
-FAIL Request: overriding explicit Content-Type assert_equals: expected "test/test" but got "text/plain"
-FAIL Response: overriding explicit Content-Type assert_equals: expected "test/test" but got "text/plain"
-FAIL Request: removing implicit Content-Type assert_equals: expected "" but got "application/x-www-form-urlencoded;charset=utf-8"
-FAIL Response: removing implicit Content-Type assert_equals: expected "" but got "application/x-www-form-urlencoded;charset=utf-8"
-FAIL Request: setting missing Content-Type assert_equals: expected "test/test" but got ""
-FAIL Response: setting missing Content-Type assert_equals: expected "test/test" but got ""
+PASS Request: overriding explicit Content-Type
+PASS Response: overriding explicit Content-Type
+PASS Request: removing implicit Content-Type
+PASS Response: removing implicit Content-Type
+PASS Request: setting missing Content-Type
+PASS Response: setting missing Content-Type
+PASS Request: MIME type for Blob from empty body
+PASS Response: MIME type for Blob from empty body
+PASS Request: MIME type for Blob from empty body with Content-Type
+PASS Response: MIME type for Blob from empty body with Content-Type
+PASS Request: MIME type for Blob
+PASS Response: MIME type for Blob
+PASS Request: MIME type for Blob with non-empty type
+PASS Response: MIME type for Blob with non-empty type
+PASS Request: Extract a MIME type with clone
+FAIL Response: Extract a MIME type with clone assert_equals: expected "text/html" but got "text/plain"
+PASS Request: Content-Type in headers wins Blob"s type
+PASS Response: Content-Type in headers wins Blob"s type
+PASS Request: setting missing Content-Type in headers and it wins Blob"s type
+PASS Response: setting missing Content-Type in headers and it wins Blob"s type
diff --git a/LayoutTests/imported/w3c/web-platform-tests/fetch/api/body/mime-type.any.js b/LayoutTests/imported/w3c/web-platform-tests/fetch/api/body/mime-type.any.js
index a0f90a0abdfc..67c9af7da2dd 100644
--- a/LayoutTests/imported/w3c/web-platform-tests/fetch/api/body/mime-type.any.js
+++ b/LayoutTests/imported/w3c/web-platform-tests/fetch/api/body/mime-type.any.js
@@ -38,3 +38,90 @@
assert_equals(blob.type, newMIMEType);
}, `${bodyContainer.constructor.name}: setting missing Content-Type`);
});
+
+[
+ () => new Request("about:blank", { method: "POST" }),
+ () => new Response(),
+].forEach(bodyContainerCreator => {
+ const bodyContainer = bodyContainerCreator();
+ promise_test(async t => {
+ const blob = await bodyContainer.blob();
+ assert_equals(blob.type, "");
+ }, `${bodyContainer.constructor.name}: MIME type for Blob from empty body`);
+});
+
+[
+ () => new Request("about:blank", { method: "POST", headers: [["Content-Type", "Mytext/Plain"]] }),
+ () => new Response("", { headers: [["Content-Type", "Mytext/Plain"]] })
+].forEach(bodyContainerCreator => {
+ const bodyContainer = bodyContainerCreator();
+ promise_test(async t => {
+ const blob = await bodyContainer.blob();
+ assert_equals(blob.type, 'mytext/plain');
+ }, `${bodyContainer.constructor.name}: MIME type for Blob from empty body with Content-Type`);
+});
+
+[
+ () => new Request("about:blank", { body: new Blob([""]), method: "POST" }),
+ () => new Response(new Blob([""]))
+].forEach(bodyContainerCreator => {
+ const bodyContainer = bodyContainerCreator();
+ promise_test(async t => {
+ const blob = await bodyContainer.blob();
+ assert_equals(blob.type, "");
+ assert_equals(bodyContainer.headers.get("Content-Type"), null);
+ }, `${bodyContainer.constructor.name}: MIME type for Blob`);
+});
+
+[
+ () => new Request("about:blank", { body: new Blob([""], { type: "Text/Plain" }), method: "POST" }),
+ () => new Response(new Blob([""], { type: "Text/Plain" }))
+].forEach(bodyContainerCreator => {
+ const bodyContainer = bodyContainerCreator();
+ promise_test(async t => {
+ const blob = await bodyContainer.blob();
+ assert_equals(blob.type, "text/plain");
+ assert_equals(bodyContainer.headers.get("Content-Type"), "text/plain");
+ }, `${bodyContainer.constructor.name}: MIME type for Blob with non-empty type`);
+});
+
+[
+ () => new Request("about:blank", { method: "POST", body: new Blob([""], { type: "Text/Plain" }), headers: [["Content-Type", "Text/Html"]] }),
+ () => new Response(new Blob([""], { type: "Text/Plain" }, { headers: [["Content-Type", "Text/Html"]] }))
+].forEach(bodyContainerCreator => {
+ const bodyContainer = bodyContainerCreator();
+ const cloned = bodyContainer.clone();
+ promise_test(async t => {
+ const blobs = [await bodyContainer.blob(), await cloned.blob()];
+ assert_equals(blobs[0].type, "text/html");
+ assert_equals(blobs[1].type, "text/html");
+ assert_equals(bodyContainer.headers.get("Content-Type"), "Text/Html");
+ assert_equals(cloned.headers.get("Content-Type"), "Text/Html");
+ }, `${bodyContainer.constructor.name}: Extract a MIME type with clone`);
+});
+
+[
+ () => new Request("about:blank", { body: new Blob([], { type: "text/plain" }), method: "POST", headers: [["Content-Type", "text/html"]] }),
+ () => new Response(new Blob([], { type: "text/plain" }), { headers: [["Content-Type", "text/html"]] }),
+].forEach(bodyContainerCreator => {
+ const bodyContainer = bodyContainerCreator();
+ promise_test(async t => {
+ assert_equals(bodyContainer.headers.get("Content-Type"), "text/html");
+ const blob = await bodyContainer.blob();
+ assert_equals(blob.type, "text/html");
+ }, `${bodyContainer.constructor.name}: Content-Type in headers wins Blob"s type`);
+});
+
+[
+ () => new Request("about:blank", { body: new Blob([], { type: "text/plain" }), method: "POST" }),
+ () => new Response(new Blob([], { type: "text/plain" })),
+].forEach(bodyContainerCreator => {
+ const bodyContainer = bodyContainerCreator();
+ promise_test(async t => {
+ assert_equals(bodyContainer.headers.get("Content-Type"), "text/plain");
+ const newMIMEType = "text/html";
+ bodyContainer.headers.set("Content-Type", newMIMEType);
+ const blob = await bodyContainer.blob();
+ assert_equals(blob.type, newMIMEType);
+ }, `${bodyContainer.constructor.name}: setting missing Content-Type in headers and it wins Blob"s type`);
+});
diff --git a/LayoutTests/imported/w3c/web-platform-tests/fetch/api/body/mime-type.any.worker-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/fetch/api/body/mime-type.any.worker-expected.txt
index 9c98917b4411..a1935e3a2fdb 100644
--- a/LayoutTests/imported/w3c/web-platform-tests/fetch/api/body/mime-type.any.worker-expected.txt
+++ b/LayoutTests/imported/w3c/web-platform-tests/fetch/api/body/mime-type.any.worker-expected.txt
@@ -1,8 +1,22 @@
-FAIL Request: overriding explicit Content-Type assert_equals: expected "test/test" but got "text/plain"
-FAIL Response: overriding explicit Content-Type assert_equals: expected "test/test" but got "text/plain"
-FAIL Request: removing implicit Content-Type assert_equals: expected "" but got "application/x-www-form-urlencoded;charset=utf-8"
-FAIL Response: removing implicit Content-Type assert_equals: expected "" but got "application/x-www-form-urlencoded;charset=utf-8"
-FAIL Request: setting missing Content-Type assert_equals: expected "test/test" but got ""
-FAIL Response: setting missing Content-Type assert_equals: expected "test/test" but got ""
+PASS Request: overriding explicit Content-Type
+PASS Response: overriding explicit Content-Type
+PASS Request: removing implicit Content-Type
+PASS Response: removing implicit Content-Type
+PASS Request: setting missing Content-Type
+PASS Response: setting missing Content-Type
+PASS Request: MIME type for Blob from empty body
+PASS Response: MIME type for Blob from empty body
+PASS Request: MIME type for Blob from empty body with Content-Type
+PASS Response: MIME type for Blob from empty body with Content-Type
+PASS Request: MIME type for Blob
+PASS Response: MIME type for Blob
+PASS Request: MIME type for Blob with non-empty type
+PASS Response: MIME type for Blob with non-empty type
+PASS Request: Extract a MIME type with clone
+FAIL Response: Extract a MIME type with clone assert_equals: expected "text/html" but got "text/plain"
+PASS Request: Content-Type in headers wins Blob"s type
+PASS Response: Content-Type in headers wins Blob"s type
+PASS Request: setting missing Content-Type in headers and it wins Blob"s type
+PASS Response: setting missing Content-Type in headers and it wins Blob"s type
diff --git a/LayoutTests/imported/w3c/web-platform-tests/fetch/api/body/w3c-import.log b/LayoutTests/imported/w3c/web-platform-tests/fetch/api/body/w3c-import.log
index 91f2de82631f..0346e1cfb52f 100644
--- a/LayoutTests/imported/w3c/web-platform-tests/fetch/api/body/w3c-import.log
+++ b/LayoutTests/imported/w3c/web-platform-tests/fetch/api/body/w3c-import.log
@@ -14,5 +14,6 @@ Property values requiring vendor prefixes:
None
------------------------------------------------------------------------
List of files:
+/LayoutTests/imported/w3c/web-platform-tests/fetch/api/body/cloned-any.js
/LayoutTests/imported/w3c/web-platform-tests/fetch/api/body/formdata.any.js
/LayoutTests/imported/w3c/web-platform-tests/fetch/api/body/mime-type.any.js
diff --git a/LayoutTests/imported/w3c/web-platform-tests/service-workers/cache-storage/cache-match.https.any-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/service-workers/cache-storage/cache-match.https.any-expected.txt
index 57634659eda5..f9a2cdc81ee3 100644
--- a/LayoutTests/imported/w3c/web-platform-tests/service-workers/cache-storage/cache-match.https.any-expected.txt
+++ b/LayoutTests/imported/w3c/web-platform-tests/service-workers/cache-storage/cache-match.https.any-expected.txt
@@ -22,6 +22,6 @@ PASS Cache.match with a network error Response
PASS Cache produces large Responses that can be cloned and read correctly.
PASS cors-exposed header should be stored correctly.
PASS MIME type should be set from content-header correctly.
-FAIL MIME type should reflect Content-Type headers of response. assert_equals: mime type can be overridden expected "text/plain" but got "text/html"
+PASS MIME type should reflect Content-Type headers of response.
PASS Cache.match ignores vary headers on opaque response.
diff --git a/LayoutTests/imported/w3c/web-platform-tests/service-workers/cache-storage/cache-match.https.any.serviceworker-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/service-workers/cache-storage/cache-match.https.any.serviceworker-expected.txt
index 57634659eda5..f9a2cdc81ee3 100644
--- a/LayoutTests/imported/w3c/web-platform-tests/service-workers/cache-storage/cache-match.https.any.serviceworker-expected.txt
+++ b/LayoutTests/imported/w3c/web-platform-tests/service-workers/cache-storage/cache-match.https.any.serviceworker-expected.txt
@@ -22,6 +22,6 @@ PASS Cache.match with a network error Response
PASS Cache produces large Responses that can be cloned and read correctly.
PASS cors-exposed header should be stored correctly.
PASS MIME type should be set from content-header correctly.
-FAIL MIME type should reflect Content-Type headers of response. assert_equals: mime type can be overridden expected "text/plain" but got "text/html"
+PASS MIME type should reflect Content-Type headers of response.
PASS Cache.match ignores vary headers on opaque response.
diff --git a/LayoutTests/imported/w3c/web-platform-tests/service-workers/cache-storage/cache-match.https.any.sharedworker-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/service-workers/cache-storage/cache-match.https.any.sharedworker-expected.txt
index 57634659eda5..f9a2cdc81ee3 100644
--- a/LayoutTests/imported/w3c/web-platform-tests/service-workers/cache-storage/cache-match.https.any.sharedworker-expected.txt
+++ b/LayoutTests/imported/w3c/web-platform-tests/service-workers/cache-storage/cache-match.https.any.sharedworker-expected.txt
@@ -22,6 +22,6 @@ PASS Cache.match with a network error Response
PASS Cache produces large Responses that can be cloned and read correctly.
PASS cors-exposed header should be stored correctly.
PASS MIME type should be set from content-header correctly.
-FAIL MIME type should reflect Content-Type headers of response. assert_equals: mime type can be overridden expected "text/plain" but got "text/html"
+PASS MIME type should reflect Content-Type headers of response.
PASS Cache.match ignores vary headers on opaque response.
diff --git a/LayoutTests/imported/w3c/web-platform-tests/service-workers/cache-storage/cache-match.https.any.worker-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/service-workers/cache-storage/cache-match.https.any.worker-expected.txt
index 57634659eda5..f9a2cdc81ee3 100644
--- a/LayoutTests/imported/w3c/web-platform-tests/service-workers/cache-storage/cache-match.https.any.worker-expected.txt
+++ b/LayoutTests/imported/w3c/web-platform-tests/service-workers/cache-storage/cache-match.https.any.worker-expected.txt
@@ -22,6 +22,6 @@ PASS Cache.match with a network error Response
PASS Cache produces large Responses that can be cloned and read correctly.
PASS cors-exposed header should be stored correctly.
PASS MIME type should be set from content-header correctly.
-FAIL MIME type should reflect Content-Type headers of response. assert_equals: mime type can be overridden expected "text/plain" but got "text/html"
+PASS MIME type should reflect Content-Type headers of response.
PASS Cache.match ignores vary headers on opaque response.
diff --git a/LayoutTests/imported/w3c/web-platform-tests/service-workers/cache-storage/serviceworker/cache-match.https-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/service-workers/cache-storage/serviceworker/cache-match.https-expected.txt
index 081cf004e599..1343757c49fd 100644
--- a/LayoutTests/imported/w3c/web-platform-tests/service-workers/cache-storage/serviceworker/cache-match.https-expected.txt
+++ b/LayoutTests/imported/w3c/web-platform-tests/service-workers/cache-storage/serviceworker/cache-match.https-expected.txt
@@ -23,6 +23,6 @@ PASS Cache.match with a network error Response
PASS Cache produces large Responses that can be cloned and read correctly.
PASS cors-exposed header should be stored correctly.
PASS MIME type should be set from content-header correctly.
-FAIL MIME type should reflect Content-Type headers of response. assert_equals: mime type can be overridden expected "text/plain" but got "text/html"
+PASS MIME type should reflect Content-Type headers of response.
PASS Cache.match ignores vary headers on opaque response.
diff --git a/LayoutTests/imported/w3c/web-platform-tests/service-workers/cache-storage/window/cache-match.https-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/service-workers/cache-storage/window/cache-match.https-expected.txt
index 57634659eda5..f9a2cdc81ee3 100644
--- a/LayoutTests/imported/w3c/web-platform-tests/service-workers/cache-storage/window/cache-match.https-expected.txt
+++ b/LayoutTests/imported/w3c/web-platform-tests/service-workers/cache-storage/window/cache-match.https-expected.txt
@@ -22,6 +22,6 @@ PASS Cache.match with a network error Response
PASS Cache produces large Responses that can be cloned and read correctly.
PASS cors-exposed header should be stored correctly.
PASS MIME type should be set from content-header correctly.
-FAIL MIME type should reflect Content-Type headers of response. assert_equals: mime type can be overridden expected "text/plain" but got "text/html"
+PASS MIME type should reflect Content-Type headers of response.
PASS Cache.match ignores vary headers on opaque response.
diff --git a/LayoutTests/imported/w3c/web-platform-tests/service-workers/cache-storage/worker/cache-match.https-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/service-workers/cache-storage/worker/cache-match.https-expected.txt
index 57634659eda5..f9a2cdc81ee3 100644
--- a/LayoutTests/imported/w3c/web-platform-tests/service-workers/cache-storage/worker/cache-match.https-expected.txt
+++ b/LayoutTests/imported/w3c/web-platform-tests/service-workers/cache-storage/worker/cache-match.https-expected.txt
@@ -22,6 +22,6 @@ PASS Cache.match with a network error Response
PASS Cache produces large Responses that can be cloned and read correctly.
PASS cors-exposed header should be stored correctly.
PASS MIME type should be set from content-header correctly.
-FAIL MIME type should reflect Content-Type headers of response. assert_equals: mime type can be overridden expected "text/plain" but got "text/html"
+PASS MIME type should reflect Content-Type headers of response.
PASS Cache.match ignores vary headers on opaque response.
diff --git a/Source/WebCore/Modules/fetch/FetchBody.cpp b/Source/WebCore/Modules/fetch/FetchBody.cpp
index ea2029d22963..e9cf255496d9 100644
--- a/Source/WebCore/Modules/fetch/FetchBody.cpp
+++ b/Source/WebCore/Modules/fetch/FetchBody.cpp
@@ -106,10 +106,9 @@ void FetchBody::arrayBuffer(FetchBodyOwner& owner, Ref&& promis
consume(owner, WTFMove(promise));
}
-void FetchBody::blob(FetchBodyOwner& owner, Ref&& promise, const String& contentType)
+void FetchBody::blob(FetchBodyOwner& owner, Ref&& promise)
{
m_consumer.setType(FetchBodyConsumer::Type::Blob);
- m_consumer.setContentType(Blob::normalizedContentType(extractMIMETypeFromMediaType(contentType)));
consume(owner, WTFMove(promise));
}
@@ -139,12 +138,10 @@ void FetchBody::formData(FetchBodyOwner& owner, Ref&& promise)
consume(owner, WTFMove(promise));
}
-void FetchBody::consumeOnceLoadingFinished(FetchBodyConsumer::Type type, Ref&& promise, const String& contentType)
+void FetchBody::consumeOnceLoadingFinished(FetchBodyConsumer::Type type, Ref&& promise)
{
m_consumer.setType(type);
m_consumer.setConsumePromise(WTFMove(promise));
- if (type == FetchBodyConsumer::Type::Blob)
- m_consumer.setContentType(Blob::normalizedContentType(extractMIMETypeFromMediaType(contentType)));
}
void FetchBody::consume(FetchBodyOwner& owner, Ref&& promise)
diff --git a/Source/WebCore/Modules/fetch/FetchBody.h b/Source/WebCore/Modules/fetch/FetchBody.h
index 36e51b3e0196..39756a4ed3c1 100644
--- a/Source/WebCore/Modules/fetch/FetchBody.h
+++ b/Source/WebCore/Modules/fetch/FetchBody.h
@@ -46,7 +46,7 @@ class ScriptExecutionContext;
class FetchBody {
public:
void arrayBuffer(FetchBodyOwner&, Ref&&);
- void blob(FetchBodyOwner&, Ref&&, const String&);
+ void blob(FetchBodyOwner&, Ref&&);
void json(FetchBodyOwner&, Ref&&);
void text(FetchBodyOwner&, Ref&&);
void formData(FetchBodyOwner&, Ref&&);
@@ -78,7 +78,7 @@ class FetchBody {
void setAsFormData(Ref&& data) { m_data = WTFMove(data); }
FetchBodyConsumer& consumer() { return m_consumer; }
- void consumeOnceLoadingFinished(FetchBodyConsumer::Type, Ref&&, const String&);
+ void consumeOnceLoadingFinished(FetchBodyConsumer::Type, Ref&&);
void cleanConsumer() { m_consumer.clean(); }
FetchBody clone();
diff --git a/Source/WebCore/Modules/fetch/FetchBodyConsumer.cpp b/Source/WebCore/Modules/fetch/FetchBodyConsumer.cpp
index b7d745d9f5e3..c8fe60a2a347 100644
--- a/Source/WebCore/Modules/fetch/FetchBodyConsumer.cpp
+++ b/Source/WebCore/Modules/fetch/FetchBodyConsumer.cpp
@@ -229,8 +229,8 @@ static void resolveWithTypeAndData(Ref&& promise, FetchBodyCons
fulfillPromiseWithArrayBuffer(WTFMove(promise), data, length);
return;
case FetchBodyConsumer::Type::Blob:
- promise->resolveCallbackValueWithNewlyCreated>([&data, &length, &contentType, context](auto&) {
- return blobFromData(context, { data, length }, contentType);
+ promise->resolveCallbackValueWithNewlyCreated>([&data, &length, &contentType](auto& context) {
+ return blobFromData(&context, { data, length }, contentType);
});
return;
case FetchBodyConsumer::Type::JSON:
@@ -365,16 +365,14 @@ void FetchBodyConsumer::resolve(Ref&& promise, const String& co
return;
}
- auto* context = promise->scriptExecutionContext();
-
ASSERT(m_type != Type::None);
switch (m_type) {
case Type::ArrayBuffer:
fulfillPromiseWithArrayBuffer(WTFMove(promise), takeAsArrayBuffer().get());
return;
case Type::Blob:
- promise->resolveCallbackValueWithNewlyCreated>([this, context](auto&) {
- return takeAsBlob(context);
+ promise->resolveCallbackValueWithNewlyCreated>([this, &contentType](auto& context) {
+ return takeAsBlob(&context, contentType);
});
return;
case Type::JSON:
@@ -385,7 +383,7 @@ void FetchBodyConsumer::resolve(Ref&& promise, const String& co
return;
case FetchBodyConsumer::Type::FormData: {
auto buffer = takeData();
- if (auto formData = packageFormData(context, contentType, buffer ? buffer->makeContiguous()->data() : nullptr, buffer ? buffer->size() : 0))
+ if (auto formData = packageFormData(promise->scriptExecutionContext(), contentType, buffer ? buffer->makeContiguous()->data() : nullptr, buffer ? buffer->size() : 0))
promise->resolve>(*formData);
else
promise->reject(TypeError);
@@ -423,12 +421,14 @@ RefPtr FetchBodyConsumer::takeAsArrayBuffer()
return m_buffer.takeAsArrayBuffer();
}
-Ref FetchBodyConsumer::takeAsBlob(ScriptExecutionContext* context)
+Ref FetchBodyConsumer::takeAsBlob(ScriptExecutionContext* context, const String& contentType)
{
+ String normalizedContentType = Blob::normalizedContentType(extractMIMETypeFromMediaType(contentType));
+
if (!m_buffer)
- return Blob::create(context, Vector(), Blob::normalizedContentType(m_contentType));
+ return Blob::create(context, Vector(), normalizedContentType);
- return blobFromData(context, m_buffer.take()->extractData(), m_contentType);
+ return blobFromData(context, m_buffer.take()->extractData(), normalizedContentType);
}
String FetchBodyConsumer::takeAsText()
@@ -496,7 +496,6 @@ void FetchBodyConsumer::loadingSucceeded(const String& contentType)
FetchBodyConsumer FetchBodyConsumer::clone()
{
FetchBodyConsumer clone { m_type };
- clone.m_contentType = m_contentType;
clone.m_buffer = m_buffer;
return clone;
}
diff --git a/Source/WebCore/Modules/fetch/FetchBodyConsumer.h b/Source/WebCore/Modules/fetch/FetchBodyConsumer.h
index 865db62c8b43..75249b5e3f07 100644
--- a/Source/WebCore/Modules/fetch/FetchBodyConsumer.h
+++ b/Source/WebCore/Modules/fetch/FetchBodyConsumer.h
@@ -66,7 +66,6 @@ class FetchBodyConsumer {
RefPtr takeAsArrayBuffer();
String takeAsText();
- void setContentType(const String& contentType) { m_contentType = contentType; }
void setType(Type type) { m_type = type; }
void clean();
@@ -88,11 +87,10 @@ class FetchBodyConsumer {
static RefPtr packageFormData(ScriptExecutionContext*, const String& contentType, const uint8_t* data, size_t length);
private:
- Ref takeAsBlob(ScriptExecutionContext*);
+ Ref takeAsBlob(ScriptExecutionContext*, const String& contentType);
void resetConsumePromise();
Type m_type;
- String m_contentType;
SharedBufferBuilder m_buffer;
RefPtr m_consumePromise;
RefPtr m_sink;
diff --git a/Source/WebCore/Modules/fetch/FetchBodyOwner.cpp b/Source/WebCore/Modules/fetch/FetchBodyOwner.cpp
index 143340412dd1..b0c4209b2589 100644
--- a/Source/WebCore/Modules/fetch/FetchBodyOwner.cpp
+++ b/Source/WebCore/Modules/fetch/FetchBodyOwner.cpp
@@ -127,9 +127,8 @@ void FetchBodyOwner::blob(Ref&& promise)
}
if (isBodyNullOrOpaque()) {
- auto* context = promise->scriptExecutionContext();
- promise->resolveCallbackValueWithNewlyCreated>([this, context](auto&) {
- return Blob::create(context, Vector { }, Blob::normalizedContentType(extractMIMETypeFromMediaType(m_contentType)));
+ promise->resolveCallbackValueWithNewlyCreated>([this](auto& context) {
+ return Blob::create(&context, Vector { }, Blob::normalizedContentType(extractMIMETypeFromMediaType(contentType())));
});
return;
}
@@ -138,14 +137,12 @@ void FetchBodyOwner::blob(Ref&& promise)
return;
}
m_isDisturbed = true;
- m_body->blob(*this, WTFMove(promise), m_contentType);
+ m_body->blob(*this, WTFMove(promise));
}
void FetchBodyOwner::cloneBody(FetchBodyOwner& owner)
{
m_loadingError = owner.m_loadingError;
-
- m_contentType = owner.m_contentType;
if (owner.isBodyNull())
return;
m_body = owner.m_body->clone();
@@ -153,24 +150,20 @@ void FetchBodyOwner::cloneBody(FetchBodyOwner& owner)
ExceptionOr FetchBodyOwner::extractBody(FetchBody::Init&& value)
{
- auto result = FetchBody::extract(WTFMove(value), m_contentType);
+ auto currentContentType = contentType();
+ bool isContentTypeSet = !currentContentType.isNull();
+ auto result = FetchBody::extract(WTFMove(value), currentContentType);
+
+ // Initialize the Content-Type header if it didn't exist.
+ if (!isContentTypeSet && !currentContentType.isNull())
+ m_headers->fastSet(HTTPHeaderName::ContentType, currentContentType);
+
if (result.hasException())
return result.releaseException();
m_body = result.releaseReturnValue();
return { };
}
-void FetchBodyOwner::updateContentType()
-{
- String contentType = m_headers->fastGet(HTTPHeaderName::ContentType);
- if (!contentType.isNull()) {
- m_contentType = WTFMove(contentType);
- return;
- }
- if (!m_contentType.isNull())
- m_headers->fastSet(HTTPHeaderName::ContentType, m_contentType);
-}
-
void FetchBodyOwner::consumeOnceLoadingFinished(FetchBodyConsumer::Type type, Ref&& promise)
{
if (isDisturbedOrLocked()) {
@@ -178,7 +171,7 @@ void FetchBodyOwner::consumeOnceLoadingFinished(FetchBodyConsumer::Type type, Re
return;
}
m_isDisturbed = true;
- m_body->consumeOnceLoadingFinished(type, WTFMove(promise), m_contentType);
+ m_body->consumeOnceLoadingFinished(type, WTFMove(promise));
}
void FetchBodyOwner::formData(Ref&& promise)
@@ -196,7 +189,7 @@ void FetchBodyOwner::formData(Ref&& promise)
if (isBodyNullOrOpaque()) {
if (isBodyNull()) {
// If the content-type is 'application/x-www-form-urlencoded', a body is not required and we should package an empty byte sequence as per the specification.
- if (auto formData = FetchBodyConsumer::packageFormData(promise->scriptExecutionContext(), m_contentType, nullptr, 0)) {
+ if (auto formData = FetchBodyConsumer::packageFormData(promise->scriptExecutionContext(), contentType(), nullptr, 0)) {
promise->resolve>(*formData);
return;
}
diff --git a/Source/WebCore/Modules/fetch/FetchBodyOwner.h b/Source/WebCore/Modules/fetch/FetchBodyOwner.h
index 15a9b613a695..bb7678ae0119 100644
--- a/Source/WebCore/Modules/fetch/FetchBodyOwner.h
+++ b/Source/WebCore/Modules/fetch/FetchBodyOwner.h
@@ -75,7 +75,7 @@ class FetchBodyOwner : public RefCounted, public ActiveDOMObject
ResourceError loadingError() const;
std::optional loadingException() const;
- const String& contentType() const { return m_contentType; }
+ String contentType() const { return m_headers->fastGet(HTTPHeaderName::ContentType); }
protected:
FetchBodyOwner(ScriptExecutionContext*, std::optional&&, Ref&&);
@@ -87,7 +87,6 @@ class FetchBodyOwner : public RefCounted, public ActiveDOMObject
void cloneBody(FetchBodyOwner&);
ExceptionOr extractBody(FetchBody::Init&&);
- void updateContentType();
void consumeOnceLoadingFinished(FetchBodyConsumer::Type, Ref&&);
void setBody(FetchBody&& body) { m_body = WTFMove(body); }
@@ -129,7 +128,6 @@ class FetchBodyOwner : public RefCounted, public ActiveDOMObject
protected:
std::optional m_body;
- String m_contentType;
bool m_isDisturbed { false };
RefPtr m_readableStreamSource;
Ref m_headers;
diff --git a/Source/WebCore/Modules/fetch/FetchRequest.cpp b/Source/WebCore/Modules/fetch/FetchRequest.cpp
index b0be4ab265fd..c5b08822410e 100644
--- a/Source/WebCore/Modules/fetch/FetchRequest.cpp
+++ b/Source/WebCore/Modules/fetch/FetchRequest.cpp
@@ -141,7 +141,6 @@ inline FetchRequest::FetchRequest(ScriptExecutionContext& context, std::optional
, m_signal(AbortSignal::create(&context))
{
m_request.setRequester(ResourceRequestRequester::Fetch);
- updateContentType();
}
ExceptionOr FetchRequest::initializeOptions(const Init& init)
@@ -215,7 +214,6 @@ ExceptionOr FetchRequest::initializeWith(const String& url, Init&& init)
return setBodyResult.releaseException();
}
- updateContentType();
return { };
}
@@ -254,7 +252,6 @@ ExceptionOr FetchRequest::initializeWith(FetchRequest& input, Init&& init)
if (setBodyResult.hasException())
return setBodyResult;
- updateContentType();
return { };
}
diff --git a/Source/WebCore/Modules/fetch/FetchResponse.cpp b/Source/WebCore/Modules/fetch/FetchResponse.cpp
index 92509917cdbf..6426f9876c56 100644
--- a/Source/WebCore/Modules/fetch/FetchResponse.cpp
+++ b/Source/WebCore/Modules/fetch/FetchResponse.cpp
@@ -58,7 +58,6 @@ Ref FetchResponse::create(ScriptExecutionContext* context, std::o
auto fetchResponse = adoptRef(*new FetchResponse(context, WTFMove(body), WTFMove(headers), WTFMove(response)));
fetchResponse->suspendIfNeeded();
- fetchResponse->updateContentType();
if (!isSynthetic)
fetchResponse->m_filteredResponse = ResourceResponseBase::filter(fetchResponse->m_internalResponse, ResourceResponse::PerformExposeAllHeadersCheck::Yes);
if (isOpaque)
@@ -111,7 +110,6 @@ ExceptionOr[> FetchResponse::create(ScriptExecutionContext& co
auto r = adoptRef(*new FetchResponse(&context, WTFMove(body), WTFMove(headers), { }));
r->suspendIfNeeded();
- r->m_contentType = contentType;
AtomString mimeType { extractMIMETypeFromMediaType(contentType) };
r->m_internalResponse.setMimeType(mimeType.isEmpty() ? AtomString { defaultMIMEType() } : mimeType);
r->m_internalResponse.setTextEncodingName(extractCharsetFromMediaType(contentType).toAtomString());
@@ -208,6 +206,7 @@ ExceptionOr][> FetchResponse::clone()
auto clone = FetchResponse::create(scriptExecutionContext(), std::nullopt, headers().guard(), ResourceResponse { m_internalResponse });
clone->cloneBody(*this);
+ clone->m_headers = FetchHeaders::create(headers());
clone->m_opaqueLoadIdentifier = m_opaqueLoadIdentifier;
clone->m_bodySizeWithPadding = m_bodySizeWithPadding;
return clone;
@@ -341,7 +340,6 @@ void FetchResponse::setReceivedInternalResponse(const ResourceResponse& resource
}
m_headers->filterAndFill(m_filteredResponse->httpHeaderFields(), FetchHeaders::Guard::Response);
- updateContentType();
}
FetchResponse::Loader::Loader(FetchResponse& response, NotificationCallback&& responseCallback)
]