summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Kettmeir <crowlkats@toaxl.com>2023-01-12 03:37:23 +0100
committerGitHub <noreply@github.com>2023-01-12 03:37:23 +0100
commita6b3910bdfe0183e458015d00a61295779e46eb1 (patch)
tree59d206d789c99a2f8f7e1bedf95914811f5a070c
parent692f9af14a6742cda7e24224eda6240e33d641d4 (diff)
feat: allow passing a ReadableStream to Deno.writeFile/Deno.writeTextFile (#17329)
Closes #13229
-rw-r--r--cli/tests/unit/write_file_test.ts16
-rw-r--r--cli/tests/unit/write_text_file_test.ts16
-rw-r--r--cli/tsc/dts/lib.deno.ns.d.ts4
-rw-r--r--runtime/js/40_write_file.js48
4 files changed, 70 insertions, 14 deletions
diff --git a/cli/tests/unit/write_file_test.ts b/cli/tests/unit/write_file_test.ts
index 0c3ff491d..78d0f5bad 100644
--- a/cli/tests/unit/write_file_test.ts
+++ b/cli/tests/unit/write_file_test.ts
@@ -393,3 +393,19 @@ function pathExists(path: string | URL) {
return false;
}
}
+
+Deno.test(
+ { permissions: { read: true, write: true } },
+ async function writeFileStream() {
+ const stream = new ReadableStream({
+ pull(controller) {
+ controller.enqueue(new Uint8Array([1]));
+ controller.enqueue(new Uint8Array([2]));
+ controller.close();
+ },
+ });
+ const filename = Deno.makeTempDirSync() + "/test.txt";
+ await Deno.writeFile(filename, stream);
+ assertEquals(Deno.readFileSync(filename), new Uint8Array([1, 2]));
+ },
+);
diff --git a/cli/tests/unit/write_text_file_test.ts b/cli/tests/unit/write_text_file_test.ts
index c83534928..ee9cac177 100644
--- a/cli/tests/unit/write_text_file_test.ts
+++ b/cli/tests/unit/write_text_file_test.ts
@@ -198,3 +198,19 @@ Deno.test(
assertEquals(Deno.readTextFileSync(filename), "Hello");
},
);
+
+Deno.test(
+ { permissions: { read: true, write: true } },
+ async function writeTextFileStream() {
+ const stream = new ReadableStream({
+ pull(controller) {
+ controller.enqueue("Hello");
+ controller.enqueue("World");
+ controller.close();
+ },
+ });
+ const filename = Deno.makeTempDirSync() + "/test.txt";
+ await Deno.writeTextFile(filename, stream);
+ assertEquals(Deno.readTextFileSync(filename), "HelloWorld");
+ },
+);
diff --git a/cli/tsc/dts/lib.deno.ns.d.ts b/cli/tsc/dts/lib.deno.ns.d.ts
index 5941a5d57..3ddd0263b 100644
--- a/cli/tsc/dts/lib.deno.ns.d.ts
+++ b/cli/tsc/dts/lib.deno.ns.d.ts
@@ -3364,7 +3364,7 @@ declare namespace Deno {
*/
export function writeFile(
path: string | URL,
- data: Uint8Array,
+ data: Uint8Array | ReadableStream<Uint8Array>,
options?: WriteFileOptions,
): Promise<void>;
@@ -3407,7 +3407,7 @@ declare namespace Deno {
*/
export function writeTextFile(
path: string | URL,
- data: string,
+ data: string | ReadableStream<string>,
options?: WriteFileOptions,
): Promise<void>;
diff --git a/runtime/js/40_write_file.js b/runtime/js/40_write_file.js
index f8d8b3ab7..a32ef441b 100644
--- a/runtime/js/40_write_file.js
+++ b/runtime/js/40_write_file.js
@@ -5,6 +5,9 @@
const ops = core.ops;
const { abortSignal } = window.__bootstrap;
const { pathFromURL } = window.__bootstrap.util;
+ const { open } = window.__bootstrap.files;
+ const { ReadableStreamPrototype } = window.__bootstrap.streams;
+ const { ObjectPrototypeIsPrototypeOf } = window.__bootstrap.primordials;
function writeFileSync(
path,
@@ -36,16 +39,29 @@
options.signal[abortSignal.add](abortHandler);
}
try {
- await core.opAsync(
- "op_write_file_async",
- pathFromURL(path),
- options.mode,
- options.append ?? false,
- options.create ?? true,
- options.createNew ?? false,
- data,
- cancelRid,
- );
+ if (ObjectPrototypeIsPrototypeOf(ReadableStreamPrototype, data)) {
+ const file = await open(path, {
+ mode: options.mode,
+ append: options.append ?? false,
+ create: options.create ?? true,
+ createNew: options.createNew ?? false,
+ write: true,
+ });
+ await data.pipeTo(file.writable, {
+ signal: options.signal,
+ });
+ } else {
+ await core.opAsync(
+ "op_write_file_async",
+ pathFromURL(path),
+ options.mode,
+ options.append ?? false,
+ options.create ?? true,
+ options.createNew ?? false,
+ data,
+ cancelRid,
+ );
+ }
} finally {
if (options.signal) {
options.signal[abortSignal.remove](abortHandler);
@@ -70,8 +86,16 @@
data,
options = {},
) {
- const encoder = new TextEncoder();
- return writeFile(path, encoder.encode(data), options);
+ if (ObjectPrototypeIsPrototypeOf(ReadableStreamPrototype, data)) {
+ return writeFile(
+ path,
+ data.pipeThrough(new TextEncoderStream()),
+ options,
+ );
+ } else {
+ const encoder = new TextEncoder();
+ return writeFile(path, encoder.encode(data), options);
+ }
}
window.__bootstrap.writeFile = {