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)