mirror of
https://github.com/denoland/deno.git
synced 2024-11-22 15:06:54 -05:00
feat(core): support AbortSignal in readFile (#10943)
This commit is contained in:
parent
9c0b41e24b
commit
20b0a5125a
4 changed files with 53 additions and 9 deletions
19
cli/dts/lib.deno.ns.d.ts
vendored
19
cli/dts/lib.deno.ns.d.ts
vendored
|
@ -861,6 +861,15 @@ declare namespace Deno {
|
||||||
mode?: number;
|
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.
|
* Check if a given resource id (`rid`) is a TTY.
|
||||||
|
@ -1385,7 +1394,10 @@ declare namespace Deno {
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* Requires `allow-read` permission. */
|
* 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
|
/** 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
|
* of bytes. `TextDecoder` can be used to transform the bytes to string if
|
||||||
|
@ -1411,7 +1423,10 @@ declare namespace Deno {
|
||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
* Requires `allow-read` permission. */
|
* 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`,
|
/** A FileInfo describes a file and is returned by `stat`, `lstat`,
|
||||||
* `statSync`, `lstatSync`. */
|
* `statSync`, `lstatSync`. */
|
||||||
|
|
|
@ -95,3 +95,25 @@ unitTest(
|
||||||
assertEquals(resourcesBefore, Deno.resources());
|
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 });
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
|
@ -110,9 +110,12 @@
|
||||||
const READ_PER_ITER = 32 * 1024;
|
const READ_PER_ITER = 32 * 1024;
|
||||||
|
|
||||||
async function readAll(r) {
|
async function readAll(r) {
|
||||||
|
return await readAllInner(r);
|
||||||
|
}
|
||||||
|
async function readAllInner(r, options) {
|
||||||
const buffers = [];
|
const buffers = [];
|
||||||
|
const signal = options?.signal ?? null;
|
||||||
while (true) {
|
while (!signal?.aborted) {
|
||||||
const buf = new Uint8Array(READ_PER_ITER);
|
const buf = new Uint8Array(READ_PER_ITER);
|
||||||
const read = await r.read(buf);
|
const read = await r.read(buf);
|
||||||
if (typeof read == "number") {
|
if (typeof read == "number") {
|
||||||
|
@ -121,6 +124,9 @@
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (signal?.aborted) {
|
||||||
|
throw new DOMException("The read operation was aborted.", "AbortError");
|
||||||
|
}
|
||||||
|
|
||||||
let totalLen = 0;
|
let totalLen = 0;
|
||||||
for (const buf of buffers) {
|
for (const buf of buffers) {
|
||||||
|
@ -177,6 +183,7 @@
|
||||||
write,
|
write,
|
||||||
writeSync,
|
writeSync,
|
||||||
readAll,
|
readAll,
|
||||||
|
readAllInner,
|
||||||
readAllSync,
|
readAllSync,
|
||||||
};
|
};
|
||||||
})(this);
|
})(this);
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
((window) => {
|
((window) => {
|
||||||
const core = window.Deno.core;
|
const core = window.Deno.core;
|
||||||
const { open, openSync } = window.__bootstrap.files;
|
const { open, openSync } = window.__bootstrap.files;
|
||||||
const { readAll, readAllSync } = window.__bootstrap.io;
|
const { readAllInner, readAllSync } = window.__bootstrap.io;
|
||||||
|
|
||||||
function readFileSync(path) {
|
function readFileSync(path) {
|
||||||
const file = openSync(path);
|
const file = openSync(path);
|
||||||
|
@ -16,10 +16,10 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function readFile(path) {
|
async function readFile(path, options) {
|
||||||
const file = await open(path);
|
const file = await open(path);
|
||||||
try {
|
try {
|
||||||
const contents = await readAll(file);
|
const contents = await readAllInner(file, options);
|
||||||
return contents;
|
return contents;
|
||||||
} finally {
|
} finally {
|
||||||
file.close();
|
file.close();
|
||||||
|
@ -36,10 +36,10 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function readTextFile(path) {
|
async function readTextFile(path, options) {
|
||||||
const file = await open(path);
|
const file = await open(path);
|
||||||
try {
|
try {
|
||||||
const contents = await readAll(file);
|
const contents = await readAllInner(file, options);
|
||||||
return core.decode(contents);
|
return core.decode(contents);
|
||||||
} finally {
|
} finally {
|
||||||
file.close();
|
file.close();
|
||||||
|
|
Loading…
Reference in a new issue