diff --git a/cli/tsc/dts/lib.dom.d.ts b/cli/tsc/dts/lib.dom.d.ts index 5d4aa12e9a..f0af1798cf 100644 --- a/cli/tsc/dts/lib.dom.d.ts +++ b/cli/tsc/dts/lib.dom.d.ts @@ -3156,6 +3156,8 @@ interface Body { arrayBuffer(): Promise; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Request/blob) */ blob(): Promise; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Request/bytes) */ + bytes(): Promise; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Request/formData) */ formData(): Promise; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Request/json) */ diff --git a/cli/tsc/dts/lib.webworker.d.ts b/cli/tsc/dts/lib.webworker.d.ts index 150ad5da79..7ffd63c4b2 100644 --- a/cli/tsc/dts/lib.webworker.d.ts +++ b/cli/tsc/dts/lib.webworker.d.ts @@ -1029,6 +1029,8 @@ interface Body { arrayBuffer(): Promise; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Request/blob) */ blob(): Promise; + /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Request/bytes) */ + bytes(): Promise; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Request/formData) */ formData(): Promise; /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Request/json) */ diff --git a/ext/fetch/22_body.js b/ext/fetch/22_body.js index e16fd4c54d..e9d4936586 100644 --- a/ext/fetch/22_body.js +++ b/ext/fetch/22_body.js @@ -296,6 +296,15 @@ function mixinBody(prototype, bodySymbol, mimeTypeSymbol) { configurable: true, enumerable: true, }, + bytes: { + /** @returns {Promise} */ + value: function bytes() { + return consumeBody(this, "bytes"); + }, + writable: true, + configurable: true, + enumerable: true, + }, formData: { /** @returns {Promise} */ value: function formData() { @@ -330,7 +339,7 @@ function mixinBody(prototype, bodySymbol, mimeTypeSymbol) { /** * https://fetch.spec.whatwg.org/#concept-body-package-data * @param {Uint8Array | string} bytes - * @param {"ArrayBuffer" | "Blob" | "FormData" | "JSON" | "text"} type + * @param {"ArrayBuffer" | "Blob" | "FormData" | "JSON" | "text" | "bytes"} type * @param {MimeType | null} [mimeType] */ function packageData(bytes, type, mimeType) { @@ -341,6 +350,8 @@ function packageData(bytes, type, mimeType) { return new Blob([bytes], { type: mimeType !== null ? mimesniff.serializeMimeType(mimeType) : "", }); + case "bytes": + return chunkToU8(bytes); case "FormData": { if (mimeType !== null) { const essence = mimesniff.essence(mimeType); diff --git a/ext/fetch/lib.deno_fetch.d.ts b/ext/fetch/lib.deno_fetch.d.ts index 4eb303e688..c27313903d 100644 --- a/ext/fetch/lib.deno_fetch.d.ts +++ b/ext/fetch/lib.deno_fetch.d.ts @@ -58,6 +58,10 @@ declare interface Body { * that resolves with a `Blob`. */ blob(): Promise; + /** Takes a `Response` stream and reads it to completion. It returns a promise + * that resolves with a `Uint8Array`. + */ + bytes(): Promise; /** Takes a `Response` stream and reads it to completion. It returns a promise * that resolves with a `FormData` object. */ diff --git a/tests/specs/run/045_proxy/proxy_test.ts b/tests/specs/run/045_proxy/proxy_test.ts index d3386f0d7b..582b0e6387 100644 --- a/tests/specs/run/045_proxy/proxy_test.ts +++ b/tests/specs/run/045_proxy/proxy_test.ts @@ -23,7 +23,7 @@ async function handler(req: Request): Promise { method: req.method, headers: headers, }); - return new Response(new Uint8Array(await resp.arrayBuffer()), { + return new Response(await resp.bytes(), { status: resp.status, headers: resp.headers, }); diff --git a/tests/testdata/fmt/with_config/subdir/a.ts b/tests/testdata/fmt/with_config/subdir/a.ts index 5474b3aa37..14f22d1b29 100644 --- a/tests/testdata/fmt/with_config/subdir/a.ts +++ b/tests/testdata/fmt/with_config/subdir/a.ts @@ -22,15 +22,11 @@ Deno.test( .statusText, ) const u8a = - new Uint8Array( - await response - .arrayBuffer(), - ) + await response + .bytes() const u8a1 = - new Uint8Array( - await response1 - .arrayBuffer(), - ) + await response1 + .bytes() for ( let i = 0; i < diff --git a/tests/unit/fetch_test.ts b/tests/unit/fetch_test.ts index 3202d40fa7..4176f39ace 100644 --- a/tests/unit/fetch_test.ts +++ b/tests/unit/fetch_test.ts @@ -243,8 +243,8 @@ Deno.test({ permissions: { net: true } }, async function responseClone() { assert(response !== response1); assertEquals(response.status, response1.status); assertEquals(response.statusText, response1.statusText); - const u8a = new Uint8Array(await response.arrayBuffer()); - const u8a1 = new Uint8Array(await response1.arrayBuffer()); + const u8a = await response.bytes(); + const u8a1 = await response1.bytes(); for (let i = 0; i < u8a.byteLength; i++) { assertEquals(u8a[i], u8a1[i]); } @@ -675,7 +675,7 @@ Deno.test( ["Foo", "Bar"], ], }); - await response.arrayBuffer(); + await response.body?.cancel(); assertEquals(response.status, 404); assertEquals(response.headers.get("Content-Length"), "2"); @@ -709,7 +709,7 @@ Deno.test( ["Accept-Language", "en-US"], ], }); - await response.arrayBuffer(); + await response.body?.cancel(); assertEquals(response.status, 404); assertEquals(response.headers.get("Content-Length"), "2"); @@ -743,7 +743,7 @@ Deno.test( ], body, }); - await response.arrayBuffer(); + await response.body?.cancel(); assertEquals(response.status, 404); assertEquals(response.headers.get("Content-Length"), "2"); @@ -782,7 +782,7 @@ Deno.test( ], body, }); - await response.arrayBuffer(); + await response.body?.cancel(); assertEquals(response.status, 404); assertEquals(response.headers.get("Content-Length"), "2"); @@ -816,7 +816,7 @@ Deno.test( ["Content-Length", "10"], ], }); - await response.arrayBuffer(); + await response.body?.cancel(); assertEquals(response.status, 404); assertEquals(response.headers.get("Content-Length"), "2"); @@ -847,7 +847,7 @@ Deno.test( ["Transfer-Encoding", "chunked"], ], }); - await response.arrayBuffer(); + await response.body?.cancel(); assertEquals(response.status, 404); assertEquals(response.headers.get("Content-Length"), "2"); @@ -933,7 +933,7 @@ Deno.test(function responseRedirectTakeURLObjectAsParameter() { Deno.test(async function responseWithoutBody() { const response = new Response(); - assertEquals(await response.arrayBuffer(), new ArrayBuffer(0)); + assertEquals(await response.bytes(), new Uint8Array(0)); const blob = await response.blob(); assertEquals(blob.size, 0); assertEquals(await blob.arrayBuffer(), new ArrayBuffer(0)); @@ -1214,7 +1214,7 @@ Deno.test( ], body: stream.readable, }); - await response.arrayBuffer(); + await response.body?.cancel(); assertEquals(response.status, 404); assertEquals(response.headers.get("Content-Length"), "2"); @@ -1793,10 +1793,9 @@ Deno.test( const listener = invalidServer(addr, body); const response = await fetch(`http://${addr}/`); - const res = await response.arrayBuffer(); + const res = await response.bytes(); const buf = new TextEncoder().encode(data); - assertEquals(res.byteLength, buf.byteLength); - assertEquals(new Uint8Array(res), buf); + assertEquals(res, buf); listener.close(); }, @@ -1850,10 +1849,10 @@ Deno.test( // If content-length < totalLength, a maximum of content-length bytes // should be returned. - const res = await response.arrayBuffer(); + const res = await response.bytes(); const buf = new TextEncoder().encode(data); assertEquals(res.byteLength, contentLength); - assertEquals(new Uint8Array(res), buf.subarray(contentLength)); + assertEquals(res, buf.subarray(contentLength)); listener.close(); }, @@ -2029,7 +2028,7 @@ Deno.test( Deno.test("Request with subarray TypedArray body", async () => { const body = new Uint8Array([1, 2, 3, 4, 5]).subarray(1); const req = new Request("https://example.com", { method: "POST", body }); - const actual = new Uint8Array(await req.arrayBuffer()); + const actual = await req.bytes(); const expected = new Uint8Array([2, 3, 4, 5]); assertEquals(actual, expected); }); @@ -2037,7 +2036,7 @@ Deno.test("Request with subarray TypedArray body", async () => { Deno.test("Response with subarray TypedArray body", async () => { const body = new Uint8Array([1, 2, 3, 4, 5]).subarray(1); const req = new Response(body); - const actual = new Uint8Array(await req.arrayBuffer()); + const actual = await req.bytes(); const expected = new Uint8Array([2, 3, 4, 5]); assertEquals(actual, expected); }); diff --git a/tests/unit/http_test.ts b/tests/unit/http_test.ts index 607f2fc6e4..f4fa62fa6b 100644 --- a/tests/unit/http_test.ts +++ b/tests/unit/http_test.ts @@ -239,7 +239,7 @@ Deno.test( headers: { "connection": "close" }, }); - await resp.arrayBuffer(); + await resp.body?.cancel(); await promise; }, ); @@ -963,7 +963,7 @@ Deno.test( await respondWith(new Response(f.readable, { status: 200 })); })(); const resp = await fetch(`http://127.0.0.1:${listenPort}/`); - const body = await resp.arrayBuffer(); + const body = await resp.bytes(); assertEquals(body.byteLength, 70 * 1024); await promise; httpConn!.close(); @@ -1293,8 +1293,8 @@ Deno.test( const resp = await fetch(`http://localhost:${listenPort}/`); assertEquals(resp.status, 200); - const body = await resp.arrayBuffer(); - assertEquals(new Uint8Array(body), new Uint8Array([128])); + const body = await resp.bytes(); + assertEquals(body, new Uint8Array([128])); await promise; httpConn!.close(); diff --git a/tests/unit/serve_test.ts b/tests/unit/serve_test.ts index 74628ace18..f7f01076be 100644 --- a/tests/unit/serve_test.ts +++ b/tests/unit/serve_test.ts @@ -340,7 +340,7 @@ Deno.test( }); const resp = await fetch(`http://localhost:${servePort}`); - dataPromise = resp.arrayBuffer(); + dataPromise = resp.bytes(); } assertEquals((await dataPromise).byteLength, 1048576); @@ -358,7 +358,7 @@ Deno.test( const [_, data] = await Promise.all([ server.shutdown(), - resp.arrayBuffer(), + resp.bytes(), ]); assertEquals(data.byteLength, 1048576); @@ -1861,13 +1861,12 @@ Deno.test( signal: ac.signal, }); const response = await fetch(`http://localhost:${servePort}/`); - const body = await response.arrayBuffer(); + const body = await response.bytes(); assertEquals(1024 * 1024, body.byteLength); - const buffer = new Uint8Array(body); for (let i = 0; i < 256; i++) { assertEquals( i, - buffer[i * 4096], + body[i * 4096], `sentinel mismatch at index ${i * 4096}`, ); } @@ -2078,8 +2077,8 @@ Deno.test( await deferred.promise; assertEquals(resp.status, 200); - const body = await resp.arrayBuffer(); - assertEquals(new Uint8Array(body), new Uint8Array([128])); + const body = await resp.bytes(); + assertEquals(body, new Uint8Array([128])); ac.abort(); await server.finished; @@ -2694,7 +2693,7 @@ for (const testCase of compressionTestCases) { headers: testCase.in as HeadersInit, }); await deferred.promise; - const body = await resp.arrayBuffer(); + const body = await resp.bytes(); if (testCase.expect == null) { assertEquals(body.byteLength, testCase.length); assertEquals( @@ -2731,7 +2730,7 @@ Deno.test( const server = Deno.serve({ handler: async (request) => { assertEquals( - new Uint8Array(await request.arrayBuffer()), + await request.bytes(), makeTempData(70 * 1024), ); deferred.resolve(); diff --git a/tests/unit/worker_test.ts b/tests/unit/worker_test.ts index 33e25f70eb..a66eb69a91 100644 --- a/tests/unit/worker_test.ts +++ b/tests/unit/worker_test.ts @@ -689,7 +689,7 @@ Deno.test({ assert(worker); const response = await fetch("http://localhost:4506"); - assert(await response.arrayBuffer()); + assert(await response.bytes()); worker.terminate(); }, }); diff --git a/tests/unit_node/http_test.ts b/tests/unit_node/http_test.ts index c57027549c..0518d935b4 100644 --- a/tests/unit_node/http_test.ts +++ b/tests/unit_node/http_test.ts @@ -174,7 +174,7 @@ Deno.test("[node/http] server can respond with 101, 204, 205, 304 status", async // deno-lint-ignore no-explicit-any `http://127.0.0.1:${(server.address() as any).port}/`, ); - await res.arrayBuffer(); + await res.body?.cancel(); assertEquals(res.status, status); server.close(() => resolve()); }); diff --git a/tests/wpt/runner/expectation.json b/tests/wpt/runner/expectation.json index 1f2dfa6847..e3f2ac9728 100644 --- a/tests/wpt/runner/expectation.json +++ b/tests/wpt/runner/expectation.json @@ -7153,6 +7153,12 @@ "response": { "json.any.html": true, "json.any.worker.html": true, + "response-blob-realm.any.html": [ + "realm of the Uint8Array from Response bytes()" + ], + "response-blob-realm.any.worker.html": [ + "realm of the Uint8Array from Response bytes()" + ], "response-init-001.any.html": true, "response-init-001.any.worker.html": true, "response-init-002.any.html": true, @@ -8148,7 +8154,11 @@ "HTTP/1.1 200 ", "HTTP/1.1 999 DOES IT MATTER " ], - "resources-with-0x00-in-header.window.html": false + "resources-with-0x00-in-header.window.html": [ + "Expect network error for script with 0x00 in a header", + "Expect network error for frame navigation to resource with 0x00 in a header", + "Expect network error for image with 0x00 in a header" + ] }, "range": { "general.any.html": [ @@ -12825,8 +12835,6 @@ "eventsource-onopen.any.worker.html": true, "eventsource-prototype.any.html": true, "eventsource-prototype.any.worker.html": true, - "eventsource-request-cancellation.window.any.html": false, - "eventsource-request-cancellation.window.any.worker.html": false, "eventsource-url.any.html": true, "eventsource-url.any.worker.html": true, "format-bom-2.any.html": true, @@ -12883,6 +12891,12 @@ "eventsource-constructor-stringify.window.html": false, "eventsource-cross-origin.window.html": false, "eventsource-reconnect.window.html": false, - "request-status-error.window.html": false + "request-status-error.window.html": false, + "eventsource-constructor-empty-url.any.serviceworker.html": false, + "eventsource-constructor-empty-url.any.sharedworker.html": false, + "eventsource-constructor-url-bogus.any.serviceworker.html": false, + "eventsource-constructor-url-bogus.any.sharedworker.html": false, + "request-credentials.window.html": false, + "request-redirect.window.html": false } -} +} \ No newline at end of file diff --git a/tests/wpt/suite b/tests/wpt/suite index 5e8f71d730..915d40b37f 160000 --- a/tests/wpt/suite +++ b/tests/wpt/suite @@ -1 +1 @@ -Subproject commit 5e8f71d73049d4fca2a8cbc62d40e821400f1624 +Subproject commit 915d40b37fbd3554548d5cbec9f335f329ccc944