Skip to content

Commit 2b53602

Browse files
authored
feat: support AbortSignal in writeFile (#11568)
1 parent 466d3df commit 2b53602

File tree

3 files changed

+51
-1
lines changed

3 files changed

+51
-1
lines changed

cli/dts/lib.deno.ns.d.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1714,6 +1714,12 @@ declare namespace Deno {
17141714
create?: boolean;
17151715
/** Permissions always applied to file. */
17161716
mode?: number;
1717+
/**
1718+
* An abort signal to allow cancellation of the file write operation.
1719+
* If the signal becomes aborted the writeFile operation will be stopped
1720+
* and the promise returned will be rejected with an AbortError.
1721+
*/
1722+
signal?: AbortSignal;
17171723
}
17181724

17191725
/** Synchronously write `data` to the given `path`, by default creating a new

cli/tests/unit/write_file_test.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,3 +239,39 @@ unitTest(
239239
assertEquals("Hello", actual);
240240
},
241241
);
242+
243+
unitTest(
244+
{ perms: { read: true, write: true } },
245+
async function writeFileAbortSignal(): Promise<void> {
246+
const ac = new AbortController();
247+
const enc = new TextEncoder();
248+
const data = enc.encode("Hello");
249+
const filename = Deno.makeTempDirSync() + "/test.txt";
250+
queueMicrotask(() => ac.abort());
251+
try {
252+
await Deno.writeFile(filename, data, { signal: ac.signal });
253+
} catch (e) {
254+
assertEquals(e.name, "AbortError");
255+
}
256+
const stat = Deno.statSync(filename);
257+
assertEquals(stat.size, 0);
258+
},
259+
);
260+
261+
unitTest(
262+
{ perms: { read: true, write: true } },
263+
async function writeFileAbortSignalPreAborted(): Promise<void> {
264+
const ac = new AbortController();
265+
ac.abort();
266+
const enc = new TextEncoder();
267+
const data = enc.encode("Hello");
268+
const filename = Deno.makeTempDirSync() + "/test.txt";
269+
try {
270+
await Deno.writeFile(filename, data, { signal: ac.signal });
271+
} catch (e) {
272+
assertEquals(e.name, "AbortError");
273+
}
274+
const stat = Deno.statSync(filename);
275+
assertEquals(stat.size, 0);
276+
},
277+
);

runtime/js/40_write_file.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
data,
1414
options = {},
1515
) {
16+
if (options?.signal?.aborted) {
17+
throw new DOMException("The write operation was aborted.", "AbortError");
18+
}
1619
if (options.create !== undefined) {
1720
const create = !!options.create;
1821
if (!create) {
@@ -68,12 +71,17 @@
6871
await chmod(path, options.mode);
6972
}
7073

74+
const signal = options?.signal ?? null;
7175
let nwritten = 0;
72-
while (nwritten < data.length) {
76+
while (!signal?.aborted && nwritten < data.length) {
7377
nwritten += await file.write(TypedArrayPrototypeSubarray(data, nwritten));
7478
}
7579

7680
file.close();
81+
82+
if (signal?.aborted) {
83+
throw new DOMException("The write operation was aborted.", "AbortError");
84+
}
7785
}
7886

7987
function writeTextFileSync(

0 commit comments

Comments
 (0)