Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
161 changes: 161 additions & 0 deletions fetch/api/body/textstream.tentative.any.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
// 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)");
Loading