// META: global=window,worker async function readAllChunks(stream) { const reader = stream.getReader(); const chunks = []; while (true) { const {done, value} = await reader.read(); if (done) { break; } chunks.push(value); } return chunks; } test(() => { assert_true('textStream' in Response.prototype, "textStream exists on Response.prototype"); assert_true('textStream' in Request.prototype, "textStream exists on Request.prototype"); assert_equals(typeof Response.prototype.textStream, "function", "Response.prototype.textStream is a function"); assert_equals(typeof Request.prototype.textStream, "function", "Request.prototype.textStream is a function"); }, "textStream method existence"); promise_test(async () => { const response = new Response("hello world"); assert_false(response.bodyUsed, "bodyUsed is false initially"); const stream = response.textStream(); assert_true(stream instanceof ReadableStream, "textStream() returns a ReadableStream"); assert_true(response.bodyUsed, "bodyUsed becomes true immediately after calling textStream()"); const chunks = await readAllChunks(stream); assert_greater_than(chunks.length, 0); for (const chunk of chunks) { assert_equals(typeof chunk, "string", "each chunk should be a string"); } assert_equals(chunks.join(""), "hello world", "concatenated chunks match the body content"); }, "Response.textStream() basic functionality"); promise_test(async () => { const request = new Request("https://example.com", { method: "POST", body: "hello world" }); assert_false(request.bodyUsed, "bodyUsed is false initially"); const stream = request.textStream(); assert_true(stream instanceof ReadableStream, "textStream() returns a ReadableStream"); assert_true(request.bodyUsed, "bodyUsed becomes true immediately after calling textStream()"); const chunks = await readAllChunks(stream); assert_greater_than(chunks.length, 0); for (const chunk of chunks) { assert_equals(typeof chunk, "string", "each chunk should be a string"); } assert_equals(chunks.join(""), "hello world", "concatenated chunks match the body content"); }, "Request.textStream() basic functionality"); promise_test(async () => { const stream = new ReadableStream({ start(controller) { controller.enqueue(new TextEncoder().encode("hello ")); controller.enqueue(new TextEncoder().encode("world")); controller.close(); } }); const response = new Response(stream); const textStream = response.textStream(); const chunks = await readAllChunks(textStream); assert_greater_than(chunks.length, 0); for (const chunk of chunks) { assert_equals(typeof chunk, "string"); } assert_equals(chunks.join(""), "hello world"); }, "textStream() handles chunked byte stream input"); test(() => { const response = new Response("hello"); response.text(); // consumes body assert_throws_js(TypeError, () => response.textStream()); }, "Response.textStream() on consumed body throws TypeError"); test(() => { const request = new Request("https://example.com", { method: "POST", body: "hello" }); request.text(); // consumes body assert_throws_js(TypeError, () => request.textStream()); }, "Request.textStream() on consumed body throws TypeError"); test(() => { const response = new Response("hello"); const reader = response.body.getReader(); // locks body assert_throws_js(TypeError, () => response.textStream()); }, "Response.textStream() on locked body throws TypeError"); test(() => { const request = new Request("https://example.com", { method: "POST", body: "hello" }); const reader = request.body.getReader(); // locks body assert_throws_js(TypeError, () => request.textStream()); }, "Request.textStream() on locked body throws TypeError"); promise_test(async () => { const response = new Response(); assert_equals(response.body, null); const stream = response.textStream(); assert_true(stream instanceof ReadableStream); const chunks = await readAllChunks(stream); assert_equals(chunks.length, 0, "no chunks should be read from null body textStream"); }, "Response.textStream() with null body"); promise_test(async () => { const request = new Request("https://example.com"); assert_equals(request.body, null); const stream = request.textStream(); assert_true(stream instanceof ReadableStream); const chunks = await readAllChunks(stream); assert_equals(chunks.length, 0, "no chunks should be read from null body textStream"); }, "Request.textStream() with null body"); promise_test(async () => { const response = new Response(""); assert_false(response.bodyUsed); const stream = response.textStream(); assert_true(stream instanceof ReadableStream); assert_true(response.bodyUsed); const chunks = await readAllChunks(stream); assert_equals(chunks.length, 0, "no chunks should be read from empty stream"); }, "Response.textStream() with empty body"); promise_test(async () => { const buffer = new Uint8Array([0x68, 0x00, 0x65, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x6f, 0x00]); // "hello" in UTF-16LE const response = new Response(buffer, { headers: { "Content-Type": "text/plain; charset=utf-16le" } }); const stream = response.textStream(); const chunks = await readAllChunks(stream); assert_equals(chunks.join(""), "h\0e\0l\0l\0o\0", "ignores charset=utf-16le and decodes as UTF-8"); }, "Response.textStream() ignores Content-Type charset (UTF-16LE)"); promise_test(async () => { const buffer = new Uint8Array([0x68, 0x00, 0x65, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x6f, 0x00]); // "hello" in UTF-16LE const request = new Request("https://example.com", { method: "POST", body: buffer, headers: { "Content-Type": "text/plain; charset=utf-16le" } }); const stream = request.textStream(); const chunks = await readAllChunks(stream); assert_equals(chunks.join(""), "h\0e\0l\0l\0o\0", "ignores charset=utf-16le and decodes as UTF-8"); }, "Request.textStream() ignores Content-Type charset (UTF-16LE)"); promise_test(async () => { const response = new Response(new TextEncoder().encode("hello"), { headers: { "Content-Type": "text/plain; charset=invalid-charset" } }); const stream = response.textStream(); const chunks = await readAllChunks(stream); assert_equals(chunks.join(""), "hello", "ignores invalid-charset and decodes as UTF-8"); }, "Response.textStream() ignores invalid Content-Type charset (invalid-charset)");