diff options
-rw-r--r-- | cli/dts/lib.deno.unstable.d.ts | 77 | ||||
-rw-r--r-- | cli/tests/testdata/045_proxy_test.ts | 20 | ||||
-rw-r--r-- | cli/tests/testdata/089_run_allow_list.ts | 4 | ||||
-rw-r--r-- | cli/tests/testdata/lock_write_fetch.ts | 6 | ||||
-rw-r--r-- | cli/tests/unit/chown_test.ts | 4 | ||||
-rw-r--r-- | cli/tests/unit/http_test.ts | 44 | ||||
-rw-r--r-- | cli/tests/unit/os_test.ts | 4 | ||||
-rw-r--r-- | cli/tests/unit/remove_test.ts | 8 | ||||
-rw-r--r-- | cli/tests/unit/signal_test.ts | 4 | ||||
-rw-r--r-- | cli/tests/unit/spawn_test.ts | 92 | ||||
-rw-r--r-- | cli/tests/unit/test_util.ts | 4 | ||||
-rw-r--r-- | cli/tests/unit/tls_test.ts | 6 | ||||
-rw-r--r-- | runtime/js/40_spawn.js | 52 | ||||
m--------- | test_util/std | 0 |
14 files changed, 176 insertions, 149 deletions
diff --git a/cli/dts/lib.deno.unstable.d.ts b/cli/dts/lib.deno.unstable.d.ts index 2b4e1015a..3bd990021 100644 --- a/cli/dts/lib.deno.unstable.d.ts +++ b/cli/dts/lib.deno.unstable.d.ts @@ -1136,7 +1136,11 @@ declare namespace Deno { /** * Spawns a child process. * - * If stdin is set to "piped", the stdin WritableStream needs to be closed manually. + * If any stdio options are not set to `"piped"`, accessing the corresponding + * field on the `Child` or its `SpawnOutput` will throw a `TypeError`. + * + * If stdin is set to `"piped"`, the stdin WritableStream needs to be closed + * manually. * * ```ts * const child = Deno.spawnChild(Deno.execPath(), { @@ -1155,25 +1159,21 @@ declare namespace Deno { * const status = await child.status; * ``` */ - export function spawnChild<T extends SpawnOptions = SpawnOptions>( + export function spawnChild( command: string | URL, - options?: T, - ): Child<T>; - - export class Child<T extends SpawnOptions> { - readonly stdin: T["stdin"] extends "piped" ? WritableStream<Uint8Array> - : null; - readonly stdout: T["stdout"] extends "inherit" | "null" ? null - : ReadableStream<Uint8Array>; - readonly stderr: T["stderr"] extends "inherit" | "null" ? null - : ReadableStream<Uint8Array>; + options?: SpawnOptions, + ): Child; + export class Child { + get stdin(): WritableStream<Uint8Array>; + get stdout(): ReadableStream<Uint8Array>; + get stderr(): ReadableStream<Uint8Array>; readonly pid: number; /** Get the status of the child. */ readonly status: Promise<ChildStatus>; /** Waits for the child to exit completely, returning all its output and status. */ - output(): Promise<SpawnOutput<T>>; + output(): Promise<SpawnOutput>; /** Kills the process with given Signal. Defaults to SIGTERM. */ kill(signo?: Signal): void; } @@ -1183,61 +1183,60 @@ declare namespace Deno { * collecting all of its output. * Will throw an error if `stdin: "piped"` is passed. * + * If options `stdout` or `stderr` are not set to `"piped"`, accessing the + * corresponding field on `SpawnOutput` will throw a `TypeError`. + * * ```ts - * const { status, stdout, stderr } = await Deno.spawn(Deno.execPath(), { + * const { code, stdout, stderr } = await Deno.spawn(Deno.execPath(), { * args: [ * "eval", * "console.log('hello'); console.error('world')", * ], * }); - * console.assert(status.code === 0); + * console.assert(code === 0); * console.assert("hello\n" === new TextDecoder().decode(stdout)); * console.assert("world\n" === new TextDecoder().decode(stderr)); * ``` */ - export function spawn<T extends SpawnOptions = SpawnOptions>( + export function spawn( command: string | URL, - options?: T, - ): Promise<SpawnOutput<T>>; + options?: SpawnOptions, + ): Promise<SpawnOutput>; /** * Synchronously executes a subprocess, waiting for it to finish and * collecting all of its output. * Will throw an error if `stdin: "piped"` is passed. * + * If options `stdout` or `stderr` are not set to `"piped"`, accessing the + * corresponding field on `SpawnOutput` will throw a `TypeError`. + * * ```ts - * const { status, stdout, stderr } = Deno.spawnSync(Deno.execPath(), { + * const { code, stdout, stderr } = Deno.spawnSync(Deno.execPath(), { * args: [ * "eval", * "console.log('hello'); console.error('world')", * ], * }); - * console.assert(status.code === 0); + * console.assert(code === 0); * console.assert("hello\n" === new TextDecoder().decode(stdout)); * console.assert("world\n" === new TextDecoder().decode(stderr)); * ``` */ - export function spawnSync<T extends SpawnOptions = SpawnOptions>( + export function spawnSync( command: string | URL, - options?: T, - ): SpawnOutput<T>; - - export type ChildStatus = - | { - success: true; - code: 0; - signal: null; - } - | { - success: false; - code: number; - signal: Signal | null; - }; + options?: SpawnOptions, + ): SpawnOutput; + + export interface ChildStatus { + success: boolean; + code: number; + signal: Signal | null; + } - export interface SpawnOutput<T extends SpawnOptions> { - status: ChildStatus; - stdout: T["stdout"] extends "inherit" | "null" ? null : Uint8Array; - stderr: T["stderr"] extends "inherit" | "null" ? null : Uint8Array; + export interface SpawnOutput extends ChildStatus { + get stdout(): Uint8Array; + get stderr(): Uint8Array; } } diff --git a/cli/tests/testdata/045_proxy_test.ts b/cli/tests/testdata/045_proxy_test.ts index 620e23e14..6a4e72aff 100644 --- a/cli/tests/testdata/045_proxy_test.ts +++ b/cli/tests/testdata/045_proxy_test.ts @@ -31,7 +31,7 @@ async function handler(req: Request): Promise<Response> { } async function testFetch() { - const { status } = await Deno.spawn(Deno.execPath(), { + const { code } = await Deno.spawn(Deno.execPath(), { args: [ "run", "--quiet", @@ -44,11 +44,11 @@ async function testFetch() { }, }); - assertEquals(status.code, 0); + assertEquals(code, 0); } async function testModuleDownload() { - const { status } = await Deno.spawn(Deno.execPath(), { + const { code } = await Deno.spawn(Deno.execPath(), { args: [ "cache", "--reload", @@ -60,11 +60,11 @@ async function testModuleDownload() { }, }); - assertEquals(status.code, 0); + assertEquals(code, 0); } async function testFetchNoProxy() { - const { status } = await Deno.spawn(Deno.execPath(), { + const { code } = await Deno.spawn(Deno.execPath(), { args: [ "run", "--quiet", @@ -78,11 +78,11 @@ async function testFetchNoProxy() { }, }); - assertEquals(status.code, 0); + assertEquals(code, 0); } async function testModuleDownloadNoProxy() { - const { status } = await Deno.spawn(Deno.execPath(), { + const { code } = await Deno.spawn(Deno.execPath(), { args: [ "cache", "--reload", @@ -95,11 +95,11 @@ async function testModuleDownloadNoProxy() { }, }); - assertEquals(status.code, 0); + assertEquals(code, 0); } async function testFetchProgrammaticProxy() { - const { status } = await Deno.spawn(Deno.execPath(), { + const { code } = await Deno.spawn(Deno.execPath(), { args: [ "run", "--quiet", @@ -109,7 +109,7 @@ async function testFetchProgrammaticProxy() { "045_programmatic_proxy_client.ts", ], }); - assertEquals(status.code, 0); + assertEquals(code, 0); } proxyServer(); diff --git a/cli/tests/testdata/089_run_allow_list.ts b/cli/tests/testdata/089_run_allow_list.ts index 0eb79dcc2..d7bc8e195 100644 --- a/cli/tests/testdata/089_run_allow_list.ts +++ b/cli/tests/testdata/089_run_allow_list.ts @@ -4,9 +4,9 @@ try { console.log(e); } -const { status } = await Deno.spawn("curl", { +const { success } = await Deno.spawn("curl", { args: ["--help"], stdout: "null", stderr: "inherit", }); -console.log(status.success); +console.log(success); diff --git a/cli/tests/testdata/lock_write_fetch.ts b/cli/tests/testdata/lock_write_fetch.ts index 7be6af84a..b403f5536 100644 --- a/cli/tests/testdata/lock_write_fetch.ts +++ b/cli/tests/testdata/lock_write_fetch.ts @@ -17,7 +17,7 @@ const fetchProc = await Deno.spawn(Deno.execPath(), { ], }); -console.log(`fetch code: ${fetchProc.status.code}`); +console.log(`fetch code: ${fetchProc.code}`); const fetchCheckProc = await Deno.spawn(Deno.execPath(), { stdout: "null", @@ -30,7 +30,7 @@ const fetchCheckProc = await Deno.spawn(Deno.execPath(), { ], }); -console.log(`fetch check code: ${fetchCheckProc.status.code}`); +console.log(`fetch check code: ${fetchCheckProc.code}`); Deno.removeSync("./lock_write_fetch.json"); @@ -47,6 +47,6 @@ const runProc = await Deno.spawn(Deno.execPath(), { ], }); -console.log(`run code: ${runProc.status.code}`); +console.log(`run code: ${runProc.code}`); Deno.removeSync("./lock_write_fetch.json"); diff --git a/cli/tests/unit/chown_test.ts b/cli/tests/unit/chown_test.ts index b9d40f525..2fa203e18 100644 --- a/cli/tests/unit/chown_test.ts +++ b/cli/tests/unit/chown_test.ts @@ -12,8 +12,8 @@ async function getUidAndGid(): Promise<{ uid: number; gid: number }> { args: ["-g"], }); - assertEquals(uidProc.status.code, 0); - assertEquals(gidProc.status.code, 0); + assertEquals(uidProc.code, 0); + assertEquals(gidProc.code, 0); const uid = parseInt(new TextDecoder("utf-8").decode(uidProc.stdout)); const gid = parseInt(new TextDecoder("utf-8").decode(gidProc.stdout)); diff --git a/cli/tests/unit/http_test.ts b/cli/tests/unit/http_test.ts index 9afe22553..b52fbdec9 100644 --- a/cli/tests/unit/http_test.ts +++ b/cli/tests/unit/http_test.ts @@ -1228,12 +1228,12 @@ Deno.test( async function client() { const url = `http://${hostname}:${port}/`; const args = ["-X", "DELETE", url]; - const { status } = await Deno.spawn("curl", { + const { success } = await Deno.spawn("curl", { args, stdout: "null", stderr: "null", }); - assert(status.success); + assert(success); } await Promise.all([server(), client()]); @@ -1350,11 +1350,11 @@ Deno.test({ "--header", "Accept-Encoding: gzip, deflate, br", ]; - const { status, stdout } = await Deno.spawn("curl", { + const { success, stdout } = await Deno.spawn("curl", { args, stderr: "null", }); - assert(status.success); + assert(success); const output = decoder.decode(stdout); assert(output.includes("vary: Accept-Encoding\r\n")); assert(output.includes("content-encoding: gzip\r\n")); @@ -1453,11 +1453,11 @@ Deno.test({ "--header", "Accept-Encoding: gzip, deflate, br", ]; - const { status, stdout } = await Deno.spawn("curl", { + const { success, stdout } = await Deno.spawn("curl", { args, stderr: "null", }); - assert(status.success); + assert(success); const output = decoder.decode(stdout).toLocaleLowerCase(); assert(output.includes("vary: accept-encoding\r\n")); assert(!output.includes("content-encoding: ")); @@ -1507,11 +1507,11 @@ Deno.test({ "--header", "Accept-Encoding: gzip;q=0.8, br;q=1.0, *;q=0.1", ]; - const { status, stdout } = await Deno.spawn("curl", { + const { success, stdout } = await Deno.spawn("curl", { args, stderr: "null", }); - assert(status.success); + assert(success); const output = decoder.decode(stdout); assert(output.includes("vary: Accept-Encoding\r\n")); assert(output.includes("content-encoding: br\r\n")); @@ -1558,11 +1558,11 @@ Deno.test({ "--header", "Accept-Encoding: gzip, deflate, br", ]; - const { status, stdout } = await Deno.spawn("curl", { + const { success, stdout } = await Deno.spawn("curl", { args, stderr: "null", }); - assert(status.success); + assert(success); const output = decoder.decode(stdout); assert(output.includes("vary: Accept-Encoding, Accept\r\n")); assert(output.includes("content-encoding: gzip\r\n")); @@ -1613,11 +1613,11 @@ Deno.test({ "--header", "Accept-Encoding: gzip, deflate, br", ]; - const { status, stdout } = await Deno.spawn("curl", { + const { success, stdout } = await Deno.spawn("curl", { args, stderr: "null", }); - assert(status.success); + assert(success); const output = decoder.decode(stdout); assert(output.includes("vary: Accept-Encoding\r\n")); assert( @@ -1670,11 +1670,11 @@ Deno.test({ "--header", "Accept-Encoding: gzip, deflate, br", ]; - const { status, stdout } = await Deno.spawn("curl", { + const { success, stdout } = await Deno.spawn("curl", { args, stderr: "null", }); - assert(status.success); + assert(success); const output = decoder.decode(stdout); assert(output.includes("vary: Accept-Encoding\r\n")); assert( @@ -1727,11 +1727,11 @@ Deno.test({ "--header", "Accept-Encoding: gzip, deflate, br", ]; - const { status, stdout } = await Deno.spawn("curl", { + const { success, stdout } = await Deno.spawn("curl", { args, stderr: "null", }); - assert(status.success); + assert(success); const output = decoder.decode(stdout); assert(output.includes("vary: Accept-Encoding\r\n")); assert(!output.includes("content-encoding: ")); @@ -1781,11 +1781,11 @@ Deno.test({ "--header", "Accept-Encoding: gzip, deflate, br", ]; - const { status, stdout } = await Deno.spawn("curl", { + const { success, stdout } = await Deno.spawn("curl", { args, stderr: "null", }); - assert(status.success); + assert(success); const output = decoder.decode(stdout); assert(output.includes("vary: Accept-Encoding\r\n")); assert(!output.includes("content-encoding: ")); @@ -1841,11 +1841,11 @@ Deno.test({ "--header", "Accept-Encoding: gzip, deflate, br", ]; - const { status, stdout } = await Deno.spawn("curl", { + const { success, stdout } = await Deno.spawn("curl", { args, stderr: "null", }); - assert(status.success); + assert(success); const output = decoder.decode(stdout); assert(output.includes("vary: Accept-Encoding\r\n")); assert(output.includes("content-encoding: gzip\r\n")); @@ -1963,11 +1963,11 @@ Deno.test({ "--header", "Accept-Encoding: gzip, deflate, br", ]; - const { status, stdout } = await Deno.spawn("curl", { + const { success, stdout } = await Deno.spawn("curl", { args, stderr: "null", }); - assert(status.success); + assert(success); const output = decoder.decode(stdout); assert(output.includes("vary: Accept-Encoding\r\n")); assert(output.includes("content-encoding: gzip\r\n")); diff --git a/cli/tests/unit/os_test.ts b/cli/tests/unit/os_test.ts index b5ff6f29f..3564ffa47 100644 --- a/cli/tests/unit/os_test.ts +++ b/cli/tests/unit/os_test.ts @@ -74,11 +74,11 @@ Deno.test( console.log( ${JSON.stringify(Object.keys(expectedEnv))}.map(k => Deno.env.get(k)) )`; - const { status, stdout } = await Deno.spawn(Deno.execPath(), { + const { success, stdout } = await Deno.spawn(Deno.execPath(), { args: ["eval", src], env: { ...inputEnv, NO_COLOR: "1" }, }); - assertEquals(status.success, true); + assertEquals(success, true); const expectedValues = Object.values(expectedEnv); const actualValues = JSON.parse(new TextDecoder().decode(stdout)); assertEquals(actualValues, expectedValues); diff --git a/cli/tests/unit/remove_test.ts b/cli/tests/unit/remove_test.ts index 365cc4e45..01f2e3fda 100644 --- a/cli/tests/unit/remove_test.ts +++ b/cli/tests/unit/remove_test.ts @@ -262,12 +262,12 @@ if (Deno.build.os === "windows") { Deno.test( { permissions: { run: true, write: true, read: true } }, async function removeFileSymlink() { - const { status } = await Deno.spawn("cmd", { + const { success } = await Deno.spawn("cmd", { args: ["/c", "mklink", "file_link", "bar"], stdout: "null", }); - assert(status.success); + assert(success); await Deno.remove("file_link"); await assertRejects(async () => { await Deno.lstat("file_link"); @@ -278,12 +278,12 @@ if (Deno.build.os === "windows") { Deno.test( { permissions: { run: true, write: true, read: true } }, async function removeDirSymlink() { - const { status } = await Deno.spawn("cmd", { + const { success } = await Deno.spawn("cmd", { args: ["/c", "mklink", "/d", "dir_link", "bar"], stdout: "null", }); - assert(status.success); + assert(success); await Deno.remove("dir_link"); await assertRejects(async () => { await Deno.lstat("dir_link"); diff --git a/cli/tests/unit/signal_test.ts b/cli/tests/unit/signal_test.ts index b8b473e6d..86092a298 100644 --- a/cli/tests/unit/signal_test.ts +++ b/cli/tests/unit/signal_test.ts @@ -185,14 +185,14 @@ Deno.test( permissions: { run: true, read: true }, }, async function canExitWhileListeningToSignal() { - const { status } = await Deno.spawn(Deno.execPath(), { + const { code } = await Deno.spawn(Deno.execPath(), { args: [ "eval", "--unstable", "Deno.addSignalListener('SIGINT', () => {})", ], }); - assertEquals(status.code, 0); + assertEquals(code, 0); }, ); diff --git a/cli/tests/unit/spawn_test.ts b/cli/tests/unit/spawn_test.ts index 10bcc597f..594597412 100644 --- a/cli/tests/unit/spawn_test.ts +++ b/cli/tests/unit/spawn_test.ts @@ -64,9 +64,8 @@ Deno.test( stderr: "null", }); - assert(child.stdin !== null); - assert(child.stdout === null); - assert(child.stderr === null); + assertThrows(() => child.stdout, TypeError, "stdout is not piped"); + assertThrows(() => child.stderr, TypeError, "stderr is not piped"); const msg = new TextEncoder().encode("hello"); const writer = child.stdin.getWriter(); @@ -92,9 +91,8 @@ Deno.test( stderr: "null", }); - assert(child.stdin === null); - assert(child.stdout !== null); - assert(child.stderr === null); + assertThrows(() => child.stdin, TypeError, "stdin is not piped"); + assertThrows(() => child.stderr, TypeError, "stderr is not piped"); const readable = child.stdout.pipeThrough(new TextDecoderStream()); const reader = readable.getReader(); @@ -122,13 +120,11 @@ Deno.test( "eval", "await Deno.stderr.write(new TextEncoder().encode('hello'))", ], - stderr: "piped", stdout: "null", }); - assert(child.stdin === null); - assert(child.stdout === null); - assert(child.stderr !== null); + assertThrows(() => child.stdin, TypeError, "stdin is not piped"); + assertThrows(() => child.stdout, TypeError, "stdout is not piped"); const readable = child.stderr.pipeThrough(new TextDecoderStream()); const reader = readable.getReader(); @@ -322,62 +318,62 @@ Deno.test( Deno.test( { permissions: { run: true, read: true } }, async function spawnSuccess() { - const { status } = await Deno.spawn(Deno.execPath(), { + const output = await Deno.spawn(Deno.execPath(), { args: ["eval", "console.log('hello world')"], }); - assertEquals(status.success, true); - assertEquals(status.code, 0); - assertEquals(status.signal, null); + assertEquals(output.success, true); + assertEquals(output.code, 0); + assertEquals(output.signal, null); }, ); Deno.test( { permissions: { run: true, read: true } }, function spawnSyncSuccess() { - const { status } = Deno.spawnSync(Deno.execPath(), { + const output = Deno.spawnSync(Deno.execPath(), { args: ["eval", "console.log('hello world')"], }); - assertEquals(status.success, true); - assertEquals(status.code, 0); - assertEquals(status.signal, null); + assertEquals(output.success, true); + assertEquals(output.code, 0); + assertEquals(output.signal, null); }, ); Deno.test( { permissions: { run: true, read: true } }, async function spawnUrl() { - const { status, stdout } = await Deno.spawn( + const output = await Deno.spawn( new URL(`file:///${Deno.execPath()}`), { args: ["eval", "console.log('hello world')"], }, ); - assertEquals(new TextDecoder().decode(stdout), "hello world\n"); + assertEquals(new TextDecoder().decode(output.stdout), "hello world\n"); - assertEquals(status.success, true); - assertEquals(status.code, 0); - assertEquals(status.signal, null); + assertEquals(output.success, true); + assertEquals(output.code, 0); + assertEquals(output.signal, null); }, ); Deno.test( { permissions: { run: true, read: true } }, function spawnSyncUrl() { - const { status, stdout } = Deno.spawnSync( + const output = Deno.spawnSync( new URL(`file:///${Deno.execPath()}`), { args: ["eval", "console.log('hello world')"], }, ); - assertEquals(new TextDecoder().decode(stdout), "hello world\n"); + assertEquals(new TextDecoder().decode(output.stdout), "hello world\n"); - assertEquals(status.success, true); - assertEquals(status.code, 0); - assertEquals(status.signal, null); + assertEquals(output.success, true); + assertEquals(output.code, 0); + assertEquals(output.signal, null); }, ); @@ -398,24 +394,24 @@ Deno.test({ permissions: { run: true } }, function spawnSyncNotFound() { Deno.test( { permissions: { run: true, read: true } }, async function spawnFailedWithCode() { - const { status } = await Deno.spawn(Deno.execPath(), { + const output = await Deno.spawn(Deno.execPath(), { args: ["eval", "Deno.exit(41 + 1)"], }); - assertEquals(status.success, false); - assertEquals(status.code, 42); - assertEquals(status.signal, null); + assertEquals(output.success, false); + assertEquals(output.code, 42); + assertEquals(output.signal, null); }, ); Deno.test( { permissions: { run: true, read: true } }, function spawnSyncFailedWithCode() { - const { status } = Deno.spawnSync(Deno.execPath(), { + const output = Deno.spawnSync(Deno.execPath(), { args: ["eval", "Deno.exit(41 + 1)"], }); - assertEquals(status.success, false); - assertEquals(status.code, 42); - assertEquals(status.signal, null); + assertEquals(output.success, false); + assertEquals(output.code, 42); + assertEquals(output.signal, null); }, ); @@ -424,16 +420,16 @@ Deno.test( permissions: { run: true, read: true }, }, async function spawnFailedWithSignal() { - const { status } = await Deno.spawn(Deno.execPath(), { + const output = await Deno.spawn(Deno.execPath(), { args: ["eval", "--unstable", "Deno.kill(Deno.pid, 'SIGKILL')"], }); - assertEquals(status.success, false); + assertEquals(output.success, false); if (Deno.build.os === "windows") { - assertEquals(status.code, 1); - assertEquals(status.signal, null); + assertEquals(output.code, 1); + assertEquals(output.signal, null); } else { - assertEquals(status.code, 128 + 9); - assertEquals(status.signal, "SIGKILL"); + assertEquals(output.code, 128 + 9); + assertEquals(output.signal, "SIGKILL"); } }, ); @@ -443,16 +439,16 @@ Deno.test( permissions: { run: true, read: true }, }, function spawnSyncFailedWithSignal() { - const { status } = Deno.spawnSync(Deno.execPath(), { + const output = Deno.spawnSync(Deno.execPath(), { args: ["eval", "--unstable", "Deno.kill(Deno.pid, 'SIGKILL')"], }); - assertEquals(status.success, false); + assertEquals(output.success, false); if (Deno.build.os === "windows") { - assertEquals(status.code, 1); - assertEquals(status.signal, null); + assertEquals(output.code, 1); + assertEquals(output.signal, null); } else { - assertEquals(status.code, 128 + 9); - assertEquals(status.signal, "SIGKILL"); + assertEquals(output.code, 128 + 9); + assertEquals(output.signal, "SIGKILL"); } }, ); diff --git a/cli/tests/unit/test_util.ts b/cli/tests/unit/test_util.ts index 18965fdab..4ad4b2575 100644 --- a/cli/tests/unit/test_util.ts +++ b/cli/tests/unit/test_util.ts @@ -31,7 +31,7 @@ export function pathToAbsoluteFileUrl(path: string): URL { const decoder = new TextDecoder(); export async function execCode(code: string): Promise<[number, string]> { - const { status, stdout } = await Deno.spawn(Deno.execPath(), { + const output = await Deno.spawn(Deno.execPath(), { args: [ "eval", "--unstable", @@ -39,5 +39,5 @@ export async function execCode(code: string): Promise<[number, string]> { code, ], }); - return [status.code, decoder.decode(stdout)]; + return [output.code, decoder.decode(output.stdout)]; } diff --git a/cli/tests/unit/tls_test.ts b/cli/tests/unit/tls_test.ts index c9f22b75b..a5b87239a 100644 --- a/cli/tests/unit/tls_test.ts +++ b/cli/tests/unit/tls_test.ts @@ -1019,12 +1019,12 @@ function createHttpsListener(port: number): Deno.Listener { } async function curl(url: string): Promise<string> { - const { status, stdout } = await Deno.spawn("curl", { + const { success, code, stdout } = await Deno.spawn("curl", { args: ["--insecure", url], }); - if (!status.success) { - throw new Error(`curl ${url} failed: ${status.code}`); + if (!success) { + throw new Error(`curl ${url} failed: ${code}`); } return new TextDecoder().decode(stdout); } diff --git a/runtime/js/40_spawn.js b/runtime/js/40_spawn.js index 7a2f06b6a..54914dc09 100644 --- a/runtime/js/40_spawn.js +++ b/runtime/js/40_spawn.js @@ -77,21 +77,27 @@ return this.#pid; } - #stdinRid; #stdin = null; get stdin() { + if (this.#stdin == null) { + throw new TypeError("stdin is not piped"); + } return this.#stdin; } - #stdoutRid; #stdout = null; get stdout() { + if (this.#stdout == null) { + throw new TypeError("stdout is not piped"); + } return this.#stdout; } - #stderrRid; #stderr = null; get stderr() { + if (this.#stderr == null) { + throw new TypeError("stderr is not piped"); + } return this.#stderr; } @@ -111,17 +117,14 @@ this.#pid = pid; if (stdinRid !== null) { - this.#stdinRid = stdinRid; this.#stdin = writableStreamForRid(stdinRid); } if (stdoutRid !== null) { - this.#stdoutRid = stdoutRid; this.#stdout = readableStreamForRid(stdoutRid); } if (stderrRid !== null) { - this.#stderrRid = stderrRid; this.#stderr = readableStreamForRid(stderrRid); } @@ -159,9 +162,21 @@ ]); return { - status, - stdout, - stderr, + success: status.success, + code: status.code, + signal: status.signal, + get stdout() { + if (stdout == null) { + throw new TypeError("stdout is not piped"); + } + return stdout; + }, + get stderr() { + if (stderr == null) { + throw new TypeError("stderr is not piped"); + } + return stderr; + }, }; } @@ -198,7 +213,7 @@ "Piped stdin is not supported for this function, use 'Deno.spawnChild()' instead", ); } - return core.opSync("op_spawn_sync", { + const result = core.opSync("op_spawn_sync", { cmd: pathFromURL(command), args: ArrayPrototypeMap(args, String), cwd: pathFromURL(cwd), @@ -210,6 +225,23 @@ stdout, stderr, }); + return { + success: result.status.success, + code: result.status.code, + signal: result.status.signal, + get stdout() { + if (result.stdout == null) { + throw new TypeError("stdout is not piped"); + } + return result.stdout; + }, + get stderr() { + if (result.stderr == null) { + throw new TypeError("stderr is not piped"); + } + return result.stderr; + }, + }; } window.__bootstrap.spawn = { diff --git a/test_util/std b/test_util/std -Subproject 2e180b039369a06d46adf506142b597c7ea28f3 +Subproject ec11374217b94e8d0ca604e669faabe5ade5d9a |