diff --git a/cli/dts/lib.deno.unstable.d.ts b/cli/dts/lib.deno.unstable.d.ts index 062ec79e7b..2904c14f32 100644 --- a/cli/dts/lib.deno.unstable.d.ts +++ b/cli/dts/lib.deno.unstable.d.ts @@ -1442,7 +1442,7 @@ declare namespace Deno { /** * Executes a subprocess, waiting for it to finish and * collecting all of its output. - * The stdio options are ignored. + * Will throw an error if `stdin: "piped"` is passed. * * ```ts * const { status, stdout, stderr } = await Deno.spawn(Deno.execPath(), { @@ -1464,7 +1464,7 @@ declare namespace Deno { /** * Synchronously executes a subprocess, waiting for it to finish and * collecting all of its output. - * The stdio options are ignored. + * Will throw an error if `stdin: "piped"` is passed. * * ```ts * const { status, stdout, stderr } = Deno.spawnSync(Deno.execPath(), { diff --git a/cli/tests/integration/run_tests.rs b/cli/tests/integration/run_tests.rs index 85363a27fb..e6004ba49a 100644 --- a/cli/tests/integration/run_tests.rs +++ b/cli/tests/integration/run_tests.rs @@ -2764,3 +2764,8 @@ itest!(report_error_handled { args: "run --quiet report_error_handled.ts", output: "report_error_handled.ts.out", }); + +itest!(spawn_stdout_inherit { + args: "run --quiet --unstable -A spawn_stdout_inherit.ts", + output: "spawn_stdout_inherit.ts.out", +}); diff --git a/cli/tests/testdata/spawn_stdout_inherit.ts b/cli/tests/testdata/spawn_stdout_inherit.ts new file mode 100644 index 0000000000..be5f9b7ef4 --- /dev/null +++ b/cli/tests/testdata/spawn_stdout_inherit.ts @@ -0,0 +1,8 @@ +await Deno.spawn(Deno.execPath(), { + args: ["eval", "--quiet", "console.log('Hello, world! 1')"], + stdout: "inherit", +}); +Deno.spawnSync(Deno.execPath(), { + args: ["eval", "--quiet", "console.log('Hello, world! 2')"], + stdout: "inherit", +}); diff --git a/cli/tests/testdata/spawn_stdout_inherit.ts.out b/cli/tests/testdata/spawn_stdout_inherit.ts.out new file mode 100644 index 0000000000..474891cf2d --- /dev/null +++ b/cli/tests/testdata/spawn_stdout_inherit.ts.out @@ -0,0 +1,2 @@ +Hello, world! 1 +Hello, world! 2 diff --git a/cli/tests/unit/command_test.ts b/cli/tests/unit/command_test.ts index f7213f0344..4b3d5bd11b 100644 --- a/cli/tests/unit/command_test.ts +++ b/cli/tests/unit/command_test.ts @@ -468,46 +468,6 @@ Deno.test( }, ); -Deno.test( - { permissions: { run: true, read: true } }, - async function spawnOverrideStdio() { - const { stdout, stderr } = await Deno.spawn(Deno.execPath(), { - args: [ - "eval", - "console.log('hello'); console.error('world')", - ], - stdin: "piped", - stdout: "null", - stderr: "null", - }); - - // @ts-ignore: for testing - assertEquals(new TextDecoder().decode(stdout), "hello\n"); - // @ts-ignore: for testing - assertEquals(new TextDecoder().decode(stderr), "world\n"); - }, -); - -Deno.test( - { permissions: { run: true, read: true } }, - function spawnSyncOverrideStdio() { - const { stdout, stderr } = Deno.spawnSync(Deno.execPath(), { - args: [ - "eval", - "console.log('hello'); console.error('world')", - ], - stdin: "piped", - stdout: "null", - stderr: "null", - }); - - // @ts-ignore: for testing - assertEquals(new TextDecoder().decode(stdout), "hello\n"); - // @ts-ignore: for testing - assertEquals(new TextDecoder().decode(stderr), "world\n"); - }, -); - Deno.test( { permissions: { run: true, read: true } }, async function spawnEnv() { @@ -685,3 +645,25 @@ Deno.test( } }, ); + +Deno.test(async function spawnStdinPipedFails() { + await assertRejects( + () => + Deno.spawn("id", { + stdin: "piped", + }), + TypeError, + "Piped stdin is not supported for this function, use 'Deno.spawnChild()' instead", + ); +}); + +Deno.test(function spawnSyncStdinPipedFails() { + assertThrows( + () => + Deno.spawnSync("id", { + stdin: "piped", + }), + TypeError, + "Piped stdin is not supported for this function, use 'Deno.spawnChild()' instead", + ); +}); diff --git a/runtime/js/40_spawn.js b/runtime/js/40_spawn.js index c55ce657de..3b609be8b1 100644 --- a/runtime/js/40_spawn.js +++ b/runtime/js/40_spawn.js @@ -166,13 +166,13 @@ } } - function spawn(command, options) { // TODO(@crowlKats): more options (like input)? - return spawnChild(command, { - ...options, - stdin: "null", - stdout: "piped", - stderr: "piped", - }).output(); + function spawn(command, options) { + if (options?.stdin === "piped") { + throw new TypeError( + "Piped stdin is not supported for this function, use 'Deno.spawnChild()' instead", + ); + } + return spawnChild(command, options).output(); } function spawnSync(command, { @@ -182,7 +182,15 @@ env = {}, uid = undefined, gid = undefined, - } = {}) { // TODO(@crowlKats): more options (like input)? + stdin = "null", + stdout = "piped", + stderr = "piped", + } = {}) { + if (stdin === "piped") { + throw new TypeError( + "Piped stdin is not supported for this function, use 'Deno.spawnChild()' instead", + ); + } return core.opSync("op_spawn_sync", { cmd: pathFromURL(command), args: ArrayPrototypeMap(args, String), @@ -191,9 +199,9 @@ env: ObjectEntries(env), uid, gid, - stdin: "null", - stdout: "piped", - stderr: "piped", + stdin, + stdout, + stderr, }); }