diff options
-rw-r--r-- | cli/dts/lib.deno.ns.d.ts | 19 | ||||
-rw-r--r-- | cli/tests/unit/read_file_test.ts | 22 | ||||
-rw-r--r-- | runtime/js/12_io.js | 11 | ||||
-rw-r--r-- | runtime/js/40_read_file.js | 10 |
4 files changed, 53 insertions, 9 deletions
diff --git a/cli/dts/lib.deno.ns.d.ts b/cli/dts/lib.deno.ns.d.ts index 8ebf16150..da016db8a 100644 --- a/cli/dts/lib.deno.ns.d.ts +++ b/cli/dts/lib.deno.ns.d.ts @@ -861,6 +861,15 @@ declare namespace Deno { mode?: number; } + export interface ReadFileOptions { + /** + * An abort signal to allow cancellation of the file read operation. + * If the signal becomes aborted the readFile operation will be stopped + * and the promise returned will be rejected with an AbortError. + */ + signal?: AbortSignal; + } + /** * * Check if a given resource id (`rid`) is a TTY. @@ -1385,7 +1394,10 @@ declare namespace Deno { * ``` * * Requires `allow-read` permission. */ - export function readTextFile(path: string | URL): Promise<string>; + export function readTextFile( + path: string | URL, + options?: ReadFileOptions, + ): Promise<string>; /** Synchronously reads and returns the entire contents of a file as an array * of bytes. `TextDecoder` can be used to transform the bytes to string if @@ -1411,7 +1423,10 @@ declare namespace Deno { * ``` * * Requires `allow-read` permission. */ - export function readFile(path: string | URL): Promise<Uint8Array>; + export function readFile( + path: string | URL, + options?: ReadFileOptions, + ): Promise<Uint8Array>; /** A FileInfo describes a file and is returned by `stat`, `lstat`, * `statSync`, `lstatSync`. */ diff --git a/cli/tests/unit/read_file_test.ts b/cli/tests/unit/read_file_test.ts index 5f8ee2c11..d8d1cddf2 100644 --- a/cli/tests/unit/read_file_test.ts +++ b/cli/tests/unit/read_file_test.ts @@ -95,3 +95,25 @@ unitTest( assertEquals(resourcesBefore, Deno.resources()); }, ); + +unitTest( + { perms: { read: true } }, + async function readFileWithAbortSignal(): Promise<void> { + const ac = new AbortController(); + queueMicrotask(() => ac.abort()); + await assertThrowsAsync(async () => { + await Deno.readFile("cli/tests/fixture.json", { signal: ac.signal }); + }); + }, +); + +unitTest( + { perms: { read: true } }, + async function readTextileWithAbortSignal(): Promise<void> { + const ac = new AbortController(); + queueMicrotask(() => ac.abort()); + await assertThrowsAsync(async () => { + await Deno.readTextFile("cli/tests/fixture.json", { signal: ac.signal }); + }); + }, +); diff --git a/runtime/js/12_io.js b/runtime/js/12_io.js index 8df3de92f..d2b2127a6 100644 --- a/runtime/js/12_io.js +++ b/runtime/js/12_io.js @@ -110,9 +110,12 @@ const READ_PER_ITER = 32 * 1024; async function readAll(r) { + return await readAllInner(r); + } + async function readAllInner(r, options) { const buffers = []; - - while (true) { + const signal = options?.signal ?? null; + while (!signal?.aborted) { const buf = new Uint8Array(READ_PER_ITER); const read = await r.read(buf); if (typeof read == "number") { @@ -121,6 +124,9 @@ break; } } + if (signal?.aborted) { + throw new DOMException("The read operation was aborted.", "AbortError"); + } let totalLen = 0; for (const buf of buffers) { @@ -177,6 +183,7 @@ write, writeSync, readAll, + readAllInner, readAllSync, }; })(this); diff --git a/runtime/js/40_read_file.js b/runtime/js/40_read_file.js index 7eee28d89..75cfd8074 100644 --- a/runtime/js/40_read_file.js +++ b/runtime/js/40_read_file.js @@ -4,7 +4,7 @@ ((window) => { const core = window.Deno.core; const { open, openSync } = window.__bootstrap.files; - const { readAll, readAllSync } = window.__bootstrap.io; + const { readAllInner, readAllSync } = window.__bootstrap.io; function readFileSync(path) { const file = openSync(path); @@ -16,10 +16,10 @@ } } - async function readFile(path) { + async function readFile(path, options) { const file = await open(path); try { - const contents = await readAll(file); + const contents = await readAllInner(file, options); return contents; } finally { file.close(); @@ -36,10 +36,10 @@ } } - async function readTextFile(path) { + async function readTextFile(path, options) { const file = await open(path); try { - const contents = await readAll(file); + const contents = await readAllInner(file, options); return core.decode(contents); } finally { file.close(); |