forked from mirrors/gecko-dev
1. Adding mAsyncWaitAlgorithms to match mAsyncWaitWorkerRef and keep the algorithms object just like how the workerref is kept right now. 2. Closing mInput also on the window teardown, to prevent memory leak as Fetch does not close the stream automatically. Depends on D193295 Differential Revision: https://phabricator.services.mozilla.com/D190058
94 lines
3.1 KiB
JavaScript
94 lines
3.1 KiB
JavaScript
// META: title=Blob Stream
|
|
// META: script=../support/Blob.js
|
|
// META: script=/common/gc.js
|
|
'use strict';
|
|
|
|
// Helper function that triggers garbage collection while reading a chunk
|
|
// if perform_gc is true.
|
|
async function read_and_gc(reader, perform_gc) {
|
|
// Passing Uint8Array for byte streams; non-byte streams will simply ignore it
|
|
const read_promise = reader.read(new Uint8Array(64));
|
|
if (perform_gc) {
|
|
await garbageCollect();
|
|
}
|
|
return read_promise;
|
|
}
|
|
|
|
// Takes in a ReadableStream and reads from it until it is done, returning
|
|
// an array that contains the results of each read operation. If perform_gc
|
|
// is true, garbage collection is triggered while reading every chunk.
|
|
async function read_all_chunks(stream, { perform_gc = false, mode } = {}) {
|
|
assert_true(stream instanceof ReadableStream);
|
|
assert_true('getReader' in stream);
|
|
const reader = stream.getReader({ mode });
|
|
|
|
assert_true('read' in reader);
|
|
let read_value = await read_and_gc(reader, perform_gc);
|
|
|
|
let out = [];
|
|
let i = 0;
|
|
while (!read_value.done) {
|
|
for (let val of read_value.value) {
|
|
out[i++] = val;
|
|
}
|
|
read_value = await read_and_gc(reader, perform_gc);
|
|
}
|
|
return out;
|
|
}
|
|
|
|
promise_test(async () => {
|
|
const blob = new Blob(["PASS"]);
|
|
const stream = blob.stream();
|
|
const chunks = await read_all_chunks(stream);
|
|
for (let [index, value] of chunks.entries()) {
|
|
assert_equals(value, "PASS".charCodeAt(index));
|
|
}
|
|
}, "Blob.stream()")
|
|
|
|
promise_test(async () => {
|
|
const blob = new Blob();
|
|
const stream = blob.stream();
|
|
const chunks = await read_all_chunks(stream);
|
|
assert_array_equals(chunks, []);
|
|
}, "Blob.stream() empty Blob")
|
|
|
|
promise_test(async () => {
|
|
const input_arr = [8, 241, 48, 123, 151];
|
|
const typed_arr = new Uint8Array(input_arr);
|
|
const blob = new Blob([typed_arr]);
|
|
const stream = blob.stream();
|
|
const chunks = await read_all_chunks(stream);
|
|
assert_array_equals(chunks, input_arr);
|
|
}, "Blob.stream() non-unicode input")
|
|
|
|
promise_test(async() => {
|
|
const input_arr = [8, 241, 48, 123, 151];
|
|
const typed_arr = new Uint8Array(input_arr);
|
|
let blob = new Blob([typed_arr]);
|
|
const stream = blob.stream();
|
|
blob = null;
|
|
await garbageCollect();
|
|
const chunks = await read_all_chunks(stream, { perform_gc: true });
|
|
assert_array_equals(chunks, input_arr);
|
|
}, "Blob.stream() garbage collection of blob shouldn't break stream " +
|
|
"consumption")
|
|
|
|
promise_test(async() => {
|
|
const input_arr = [8, 241, 48, 123, 151];
|
|
const typed_arr = new Uint8Array(input_arr);
|
|
let blob = new Blob([typed_arr]);
|
|
const chunksPromise = read_all_chunks(blob.stream());
|
|
// It somehow matters to do GC here instead of doing `perform_gc: true`
|
|
await garbageCollect();
|
|
assert_array_equals(await chunksPromise, input_arr);
|
|
}, "Blob.stream() garbage collection of stream shouldn't break stream " +
|
|
"consumption")
|
|
|
|
promise_test(async () => {
|
|
const input_arr = [8, 241, 48, 123, 151];
|
|
const typed_arr = new Uint8Array(input_arr);
|
|
let blob = new Blob([typed_arr]);
|
|
const stream = blob.stream();
|
|
const chunks = await read_all_chunks(stream, { mode: "byob" });
|
|
assert_array_equals(chunks, input_arr);
|
|
}, "Reading Blob.stream() with BYOB reader")
|