summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cli/bench/command.js (renamed from cli/bench/spawn.js)6
-rw-r--r--cli/tests/unit/spawn_test.ts831
-rw-r--r--cli/tsc/dts/lib.deno.unstable.d.ts164
-rw-r--r--runtime/js/40_spawn.js9
-rw-r--r--runtime/js/99_main.js75
-rw-r--r--runtime/ops/spawn.rs6
6 files changed, 38 insertions, 1053 deletions
diff --git a/cli/bench/spawn.js b/cli/bench/command.js
index f5a658f3f..5b57dd4f6 100644
--- a/cli/bench/spawn.js
+++ b/cli/bench/command.js
@@ -1,11 +1,11 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
Deno.bench("echo deno", async () => {
- await Deno.spawn("echo", { args: ["deno"] });
+ await new Deno.Command("echo", { args: ["deno"] }).output();
});
Deno.bench("cat 128kb", async () => {
- await Deno.spawn("cat", {
+ await new Deno.Command("cat", {
args: ["./cli/bench/testdata/128k.bin"],
- });
+ }).output();
});
diff --git a/cli/tests/unit/spawn_test.ts b/cli/tests/unit/spawn_test.ts
deleted file mode 100644
index 10095be95..000000000
--- a/cli/tests/unit/spawn_test.ts
+++ /dev/null
@@ -1,831 +0,0 @@
-// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
-import {
- assert,
- assertEquals,
- assertRejects,
- assertStringIncludes,
- assertThrows,
-} from "./test_util.ts";
-
-Deno.test(
- { permissions: { write: true, run: true, read: true } },
- async function spawnWithCwdIsAsync() {
- const enc = new TextEncoder();
- const cwd = await Deno.makeTempDir({ prefix: "deno_command_test" });
-
- const exitCodeFile = "deno_was_here";
- const programFile = "poll_exit.ts";
- const program = `
-async function tryExit() {
- try {
- const code = parseInt(await Deno.readTextFile("${exitCodeFile}"));
- Deno.exit(code);
- } catch {
- // Retry if we got here before deno wrote the file.
- setTimeout(tryExit, 0.01);
- }
-}
-
-tryExit();
-`;
-
- Deno.writeFileSync(`${cwd}/${programFile}`, enc.encode(program));
-
- const child = Deno.spawnChild(Deno.execPath(), {
- cwd,
- args: ["run", "--allow-read", programFile],
- stdout: "inherit",
- stderr: "inherit",
- });
-
- // Write the expected exit code *after* starting deno.
- // This is how we verify that `Child` is actually asynchronous.
- const code = 84;
- Deno.writeFileSync(`${cwd}/${exitCodeFile}`, enc.encode(`${code}`));
-
- const status = await child.status;
- await Deno.remove(cwd, { recursive: true });
- assertEquals(status.success, false);
- assertEquals(status.code, code);
- assertEquals(status.signal, null);
- },
-);
-
-Deno.test(
- { permissions: { run: true, read: true } },
- async function spawnStdinPiped() {
- const child = Deno.spawnChild(Deno.execPath(), {
- args: [
- "eval",
- "if (new TextDecoder().decode(await Deno.readAll(Deno.stdin)) !== 'hello') throw new Error('Expected \\'hello\\'')",
- ],
- stdin: "piped",
- stdout: "null",
- 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();
- await writer.write(msg);
- writer.releaseLock();
-
- await child.stdin.close();
- const status = await child.status;
- assertEquals(status.success, true);
- assertEquals(status.code, 0);
- assertEquals(status.signal, null);
- },
-);
-
-Deno.test(
- { permissions: { run: true, read: true } },
- async function spawnStdoutPiped() {
- const child = Deno.spawnChild(Deno.execPath(), {
- args: [
- "eval",
- "await Deno.stdout.write(new TextEncoder().encode('hello'))",
- ],
- 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();
- const res = await reader.read();
- assert(!res.done);
- assertEquals(res.value, "hello");
-
- const resEnd = await reader.read();
- assert(resEnd.done);
- assertEquals(resEnd.value, undefined);
- reader.releaseLock();
-
- const status = await child.status;
- assertEquals(status.success, true);
- assertEquals(status.code, 0);
- assertEquals(status.signal, null);
- },
-);
-
-Deno.test(
- { permissions: { run: true, read: true } },
- async function spawnStderrPiped() {
- const child = Deno.spawnChild(Deno.execPath(), {
- args: [
- "eval",
- "await Deno.stderr.write(new TextEncoder().encode('hello'))",
- ],
- stdout: "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();
- const res = await reader.read();
- assert(!res.done);
- assertEquals(res.value, "hello");
-
- const resEnd = await reader.read();
- assert(resEnd.done);
- assertEquals(resEnd.value, undefined);
- reader.releaseLock();
-
- const status = await child.status;
- assertEquals(status.success, true);
- assertEquals(status.code, 0);
- assertEquals(status.signal, null);
- },
-);
-
-Deno.test(
- { permissions: { run: true, write: true, read: true } },
- async function spawnRedirectStdoutStderr() {
- const tempDir = await Deno.makeTempDir();
- const fileName = tempDir + "/redirected_stdio.txt";
- const file = await Deno.open(fileName, {
- create: true,
- write: true,
- });
-
- const child = Deno.spawnChild(Deno.execPath(), {
- args: [
- "eval",
- "Deno.stderr.write(new TextEncoder().encode('error\\n')); Deno.stdout.write(new TextEncoder().encode('output\\n'));",
- ],
- });
- await child.stdout.pipeTo(file.writable, {
- preventClose: true,
- });
- await child.stderr.pipeTo(file.writable);
- await child.status;
-
- const fileContents = await Deno.readFile(fileName);
- const decoder = new TextDecoder();
- const text = decoder.decode(fileContents);
-
- assertStringIncludes(text, "error");
- assertStringIncludes(text, "output");
- },
-);
-
-Deno.test(
- { permissions: { run: true, write: true, read: true } },
- async function spawnRedirectStdin() {
- const tempDir = await Deno.makeTempDir();
- const fileName = tempDir + "/redirected_stdio.txt";
- const encoder = new TextEncoder();
- await Deno.writeFile(fileName, encoder.encode("hello"));
- const file = await Deno.open(fileName);
-
- const child = Deno.spawnChild(Deno.execPath(), {
- args: [
- "eval",
- "if (new TextDecoder().decode(await Deno.readAll(Deno.stdin)) !== 'hello') throw new Error('Expected \\'hello\\'')",
- ],
- stdin: "piped",
- stdout: "null",
- stderr: "null",
- });
- await file.readable.pipeTo(child.stdin, {
- preventClose: true,
- });
-
- await child.stdin.close();
- const status = await child.status;
- assertEquals(status.code, 0);
- },
-);
-
-Deno.test(
- { permissions: { run: true, read: true } },
- async function spawnKillSuccess() {
- const child = Deno.spawnChild(Deno.execPath(), {
- args: ["eval", "setTimeout(() => {}, 10000)"],
- stdout: "null",
- stderr: "null",
- });
-
- child.kill("SIGKILL");
- const status = await child.status;
-
- assertEquals(status.success, false);
- if (Deno.build.os === "windows") {
- assertEquals(status.code, 1);
- assertEquals(status.signal, null);
- } else {
- assertEquals(status.code, 137);
- assertEquals(status.signal, "SIGKILL");
- }
- },
-);
-
-Deno.test(
- { permissions: { run: true, read: true } },
- async function spawnKillFailed() {
- const child = Deno.spawnChild(Deno.execPath(), {
- args: ["eval", "setTimeout(() => {}, 5000)"],
- stdout: "null",
- stderr: "null",
- });
-
- assertThrows(() => {
- // @ts-expect-error testing runtime error of bad signal
- child.kill("foobar");
- }, TypeError);
-
- await child.status;
- },
-);
-
-Deno.test(
- { permissions: { run: true, read: true } },
- async function spawnKillOptional() {
- const child = Deno.spawnChild(Deno.execPath(), {
- args: ["eval", "setTimeout(() => {}, 10000)"],
- stdout: "null",
- stderr: "null",
- });
-
- child.kill();
- const status = await child.status;
-
- assertEquals(status.success, false);
- if (Deno.build.os === "windows") {
- assertEquals(status.code, 1);
- assertEquals(status.signal, null);
- } else {
- assertEquals(status.code, 143);
- assertEquals(status.signal, "SIGTERM");
- }
- },
-);
-
-Deno.test(
- { permissions: { run: true, read: true } },
- async function spawnAbort() {
- const ac = new AbortController();
- const child = Deno.spawnChild(Deno.execPath(), {
- args: [
- "eval",
- "setTimeout(console.log, 1e8)",
- ],
- signal: ac.signal,
- stdout: "null",
- stderr: "null",
- });
- queueMicrotask(() => ac.abort());
- const status = await child.status;
- assertEquals(status.success, false);
- if (Deno.build.os === "windows") {
- assertEquals(status.code, 1);
- assertEquals(status.signal, null);
- } else {
- assertEquals(status.success, false);
- assertEquals(status.code, 143);
- }
- },
-);
-
-Deno.test(
- { permissions: { read: true, run: false } },
- async function spawnPermissions() {
- await assertRejects(async () => {
- await Deno.spawn(Deno.execPath(), {
- args: ["eval", "console.log('hello world')"],
- });
- }, Deno.errors.PermissionDenied);
- },
-);
-
-Deno.test(
- { permissions: { read: true, run: false } },
- function spawnSyncPermissions() {
- assertThrows(() => {
- Deno.spawnSync(Deno.execPath(), {
- args: ["eval", "console.log('hello world')"],
- });
- }, Deno.errors.PermissionDenied);
- },
-);
-
-Deno.test(
- { permissions: { run: true, read: true } },
- async function spawnSuccess() {
- const output = await Deno.spawn(Deno.execPath(), {
- args: ["eval", "console.log('hello world')"],
- });
-
- assertEquals(output.success, true);
- assertEquals(output.code, 0);
- assertEquals(output.signal, null);
- },
-);
-
-Deno.test(
- { permissions: { run: true, read: true } },
- function spawnSyncSuccess() {
- const output = Deno.spawnSync(Deno.execPath(), {
- args: ["eval", "console.log('hello world')"],
- });
-
- assertEquals(output.success, true);
- assertEquals(output.code, 0);
- assertEquals(output.signal, null);
- },
-);
-
-Deno.test(
- { permissions: { run: true, read: true } },
- async function spawnUrl() {
- const output = await Deno.spawn(
- new URL(`file:///${Deno.execPath()}`),
- {
- args: ["eval", "console.log('hello world')"],
- },
- );
-
- assertEquals(new TextDecoder().decode(output.stdout), "hello world\n");
-
- assertEquals(output.success, true);
- assertEquals(output.code, 0);
- assertEquals(output.signal, null);
- },
-);
-
-Deno.test(
- { permissions: { run: true, read: true } },
- function spawnSyncUrl() {
- const output = Deno.spawnSync(
- new URL(`file:///${Deno.execPath()}`),
- {
- args: ["eval", "console.log('hello world')"],
- },
- );
-
- assertEquals(new TextDecoder().decode(output.stdout), "hello world\n");
-
- assertEquals(output.success, true);
- assertEquals(output.code, 0);
- assertEquals(output.signal, null);
- },
-);
-
-Deno.test({ permissions: { run: true } }, function spawnNotFound() {
- assertThrows(
- () => Deno.spawn("this file hopefully doesn't exist"),
- Deno.errors.NotFound,
- );
-});
-
-Deno.test({ permissions: { run: true } }, function spawnSyncNotFound() {
- assertThrows(
- () => Deno.spawnSync("this file hopefully doesn't exist"),
- Deno.errors.NotFound,
- );
-});
-
-Deno.test(
- { permissions: { run: true, read: true } },
- async function spawnFailedWithCode() {
- const output = await Deno.spawn(Deno.execPath(), {
- args: ["eval", "Deno.exit(41 + 1)"],
- });
- assertEquals(output.success, false);
- assertEquals(output.code, 42);
- assertEquals(output.signal, null);
- },
-);
-
-Deno.test(
- { permissions: { run: true, read: true } },
- function spawnSyncFailedWithCode() {
- const output = Deno.spawnSync(Deno.execPath(), {
- args: ["eval", "Deno.exit(41 + 1)"],
- });
- assertEquals(output.success, false);
- assertEquals(output.code, 42);
- assertEquals(output.signal, null);
- },
-);
-
-Deno.test(
- {
- permissions: { run: true, read: true },
- },
- async function spawnFailedWithSignal() {
- const output = await Deno.spawn(Deno.execPath(), {
- args: ["eval", "--unstable", "Deno.kill(Deno.pid, 'SIGKILL')"],
- });
- assertEquals(output.success, false);
- if (Deno.build.os === "windows") {
- assertEquals(output.code, 1);
- assertEquals(output.signal, null);
- } else {
- assertEquals(output.code, 128 + 9);
- assertEquals(output.signal, "SIGKILL");
- }
- },
-);
-
-Deno.test(
- {
- permissions: { run: true, read: true },
- },
- function spawnSyncFailedWithSignal() {
- const output = Deno.spawnSync(Deno.execPath(), {
- args: ["eval", "--unstable", "Deno.kill(Deno.pid, 'SIGKILL')"],
- });
- assertEquals(output.success, false);
- if (Deno.build.os === "windows") {
- assertEquals(output.code, 1);
- assertEquals(output.signal, null);
- } else {
- assertEquals(output.code, 128 + 9);
- assertEquals(output.signal, "SIGKILL");
- }
- },
-);
-
-Deno.test(
- { permissions: { run: true, read: true } },
- async function spawnOutput() {
- const { stdout } = await Deno.spawn(Deno.execPath(), {
- args: [
- "eval",
- "await Deno.stdout.write(new TextEncoder().encode('hello'))",
- ],
- });
-
- const s = new TextDecoder().decode(stdout);
- assertEquals(s, "hello");
- },
-);
-
-Deno.test(
- { permissions: { run: true, read: true } },
- function spawnSyncOutput() {
- const { stdout } = Deno.spawnSync(Deno.execPath(), {
- args: [
- "eval",
- "await Deno.stdout.write(new TextEncoder().encode('hello'))",
- ],
- });
-
- const s = new TextDecoder().decode(stdout);
- assertEquals(s, "hello");
- },
-);
-
-Deno.test(
- { permissions: { run: true, read: true } },
- async function spawnStderrOutput() {
- const { stderr } = await Deno.spawn(Deno.execPath(), {
- args: [
- "eval",
- "await Deno.stderr.write(new TextEncoder().encode('error'))",
- ],
- });
-
- const s = new TextDecoder().decode(stderr);
- assertEquals(s, "error");
- },
-);
-
-Deno.test(
- { permissions: { run: true, read: true } },
- function spawnSyncStderrOutput() {
- const { stderr } = Deno.spawnSync(Deno.execPath(), {
- args: [
- "eval",
- "await Deno.stderr.write(new TextEncoder().encode('error'))",
- ],
- });
-
- const s = new TextDecoder().decode(stderr);
- assertEquals(s, "error");
- },
-);
-
-Deno.test(
- { permissions: { run: true, read: true } },
- async function spawnEnv() {
- const { stdout } = await Deno.spawn(Deno.execPath(), {
- args: [
- "eval",
- "Deno.stdout.write(new TextEncoder().encode(Deno.env.get('FOO') + Deno.env.get('BAR')))",
- ],
- env: {
- FOO: "0123",
- BAR: "4567",
- },
- });
- const s = new TextDecoder().decode(stdout);
- assertEquals(s, "01234567");
- },
-);
-
-Deno.test(
- { permissions: { run: true, read: true } },
- function spawnSyncEnv() {
- const { stdout } = Deno.spawnSync(Deno.execPath(), {
- args: [
- "eval",
- "Deno.stdout.write(new TextEncoder().encode(Deno.env.get('FOO') + Deno.env.get('BAR')))",
- ],
- env: {
- FOO: "0123",
- BAR: "4567",
- },
- });
- const s = new TextDecoder().decode(stdout);
- assertEquals(s, "01234567");
- },
-);
-
-Deno.test(
- { permissions: { run: true, read: true, env: true } },
- async function spawnClearEnv() {
- const { stdout } = await Deno.spawn(Deno.execPath(), {
- args: [
- "eval",
- "-p",
- "JSON.stringify(Deno.env.toObject())",
- ],
- clearEnv: true,
- env: {
- FOO: "23147",
- },
- });
-
- const obj = JSON.parse(new TextDecoder().decode(stdout));
-
- // can't check for object equality because the OS may set additional env
- // vars for processes, so we check if PATH isn't present as that is a common
- // env var across OS's and isn't set for processes.
- assertEquals(obj.FOO, "23147");
- assert(!("PATH" in obj));
- },
-);
-
-Deno.test(
- { permissions: { run: true, read: true, env: true } },
- function spawnSyncClearEnv() {
- const { stdout } = Deno.spawnSync(Deno.execPath(), {
- args: [
- "eval",
- "-p",
- "JSON.stringify(Deno.env.toObject())",
- ],
- clearEnv: true,
- env: {
- FOO: "23147",
- },
- });
-
- const obj = JSON.parse(new TextDecoder().decode(stdout));
-
- // can't check for object equality because the OS may set additional env
- // vars for processes, so we check if PATH isn't present as that is a common
- // env var across OS's and isn't set for processes.
- assertEquals(obj.FOO, "23147");
- assert(!("PATH" in obj));
- },
-);
-
-Deno.test(
- {
- permissions: { run: true, read: true },
- ignore: Deno.build.os === "windows",
- },
- async function spawnUid() {
- const { stdout } = await Deno.spawn("id", {
- args: ["-u"],
- });
-
- const currentUid = new TextDecoder().decode(stdout);
-
- if (currentUid !== "0") {
- await assertRejects(async () => {
- await Deno.spawn("echo", {
- args: ["fhqwhgads"],
- uid: 0,
- });
- }, Deno.errors.PermissionDenied);
- }
- },
-);
-
-Deno.test(
- {
- permissions: { run: true, read: true },
- ignore: Deno.build.os === "windows",
- },
- function spawnSyncUid() {
- const { stdout } = Deno.spawnSync("id", {
- args: ["-u"],
- });
-
- const currentUid = new TextDecoder().decode(stdout);
-
- if (currentUid !== "0") {
- assertThrows(() => {
- Deno.spawnSync("echo", {
- args: ["fhqwhgads"],
- uid: 0,
- });
- }, Deno.errors.PermissionDenied);
- }
- },
-);
-
-Deno.test(
- {
- permissions: { run: true, read: true },
- ignore: Deno.build.os === "windows",
- },
- async function spawnGid() {
- const { stdout } = await Deno.spawn("id", {
- args: ["-g"],
- });
-
- const currentGid = new TextDecoder().decode(stdout);
-
- if (currentGid !== "0") {
- await assertRejects(async () => {
- await Deno.spawn("echo", {
- args: ["fhqwhgads"],
- gid: 0,
- });
- }, Deno.errors.PermissionDenied);
- }
- },
-);
-
-Deno.test(
- {
- permissions: { run: true, read: true },
- ignore: Deno.build.os === "windows",
- },
- function spawnSyncGid() {
- const { stdout } = Deno.spawnSync("id", {
- args: ["-g"],
- });
-
- const currentGid = new TextDecoder().decode(stdout);
-
- if (currentGid !== "0") {
- assertThrows(() => {
- Deno.spawnSync("echo", {
- args: ["fhqwhgads"],
- gid: 0,
- });
- }, Deno.errors.PermissionDenied);
- }
- },
-);
-
-Deno.test(function spawnStdinPipedFails() {
- assertThrows(
- () =>
- 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",
- );
-});
-
-Deno.test(
- // TODO(bartlomieju): this test became flaky on Windows CI
- // raising "PermissionDenied" instead of "NotFound".
- {
- ignore: Deno.build.os === "windows",
- permissions: { write: true, run: true, read: true },
- },
- async function spawnChildUnref() {
- const enc = new TextEncoder();
- const cwd = await Deno.makeTempDir({ prefix: "deno_command_test" });
-
- const programFile = "unref.ts";
- const program = `
-const child = await Deno.spawnChild(Deno.execPath(), {
- cwd: Deno.args[0],
- stdout: "piped",
- args: ["run", "-A", "--unstable", Deno.args[1]],
-});
-const readable = child.stdout.pipeThrough(new TextDecoderStream());
-const reader = readable.getReader();
-// set up an interval that will end after reading a few messages from stdout,
-// to verify that stdio streams are properly unrefed
-let count = 0;
-let interval;
-interval = setInterval(async () => {
- count += 1;
- if (count > 10) {
- clearInterval(interval);
- console.log("cleared interval");
- }
- const res = await reader.read();
- if (res.done) {
- throw new Error("stream shouldn't be done");
- }
- if (res.value.trim() != "hello from interval") {
- throw new Error("invalid message received");
- }
-}, 120);
-console.log("spawned pid", child.pid);
-child.unref();
-`;
-
- const childProgramFile = "unref_child.ts";
- const childProgram = `
-setInterval(() => {
- console.log("hello from interval");
-}, 100);
-`;
- Deno.writeFileSync(`${cwd}/${programFile}`, enc.encode(program));
- Deno.writeFileSync(`${cwd}/${childProgramFile}`, enc.encode(childProgram));
- // In this subprocess we are spawning another subprocess which has
- // an infite interval set. Following call would never resolve unless
- // child process gets unrefed.
- const { success, stdout, stderr } = await Deno.spawn(Deno.execPath(), {
- cwd,
- args: ["run", "-A", "--unstable", programFile, cwd, childProgramFile],
- });
-
- assert(success);
- const stdoutText = new TextDecoder().decode(stdout);
- const stderrText = new TextDecoder().decode(stderr);
- assert(stderrText.length == 0);
- const [line1, line2] = stdoutText.split("\n");
- const pidStr = line1.split(" ").at(-1);
- assert(pidStr);
- assertEquals(line2, "cleared interval");
- const pid = Number.parseInt(pidStr, 10);
- await Deno.remove(cwd, { recursive: true });
- // Child process should have been killed when parent process exits.
- assertThrows(() => {
- Deno.kill(pid, "SIGTERM");
- }, Deno.errors.NotFound);
- },
-);
-
-Deno.test(
- { ignore: Deno.build.os !== "windows" },
- async function spawnWindowsRawArguments() {
- let { success, stdout } = await Deno.spawn("cmd", {
- args: ["/d", "/s", "/c", '"deno ^"--version^""'],
- windowsRawArguments: true,
- });
- assert(success);
- let stdoutText = new TextDecoder().decode(stdout);
- assertStringIncludes(stdoutText, "deno");
- assertStringIncludes(stdoutText, "v8");
- assertStringIncludes(stdoutText, "typescript");
-
- ({ success, stdout } = Deno.spawnSync("cmd", {
- args: ["/d", "/s", "/c", '"deno ^"--version^""'],
- windowsRawArguments: true,
- }));
- assert(success);
- stdoutText = new TextDecoder().decode(stdout);
- assertStringIncludes(stdoutText, "deno");
- assertStringIncludes(stdoutText, "v8");
- assertStringIncludes(stdoutText, "typescript");
- },
-);
-
-Deno.test(
- { permissions: { read: true, run: true } },
- async function spawnWithPromisePrototypeThenOverride() {
- const originalThen = Promise.prototype.then;
- try {
- Promise.prototype.then = () => {
- throw new Error();
- };
- await Deno.spawn(Deno.execPath(), {
- args: ["eval", "console.log('hello world')"],
- });
- } finally {
- Promise.prototype.then = originalThen;
- }
- },
-);
diff --git a/cli/tsc/dts/lib.deno.unstable.d.ts b/cli/tsc/dts/lib.deno.unstable.d.ts
index 9e91c8800..d3bf8a91b 100644
--- a/cli/tsc/dts/lib.deno.unstable.d.ts
+++ b/cli/tsc/dts/lib.deno.unstable.d.ts
@@ -1470,170 +1470,6 @@ declare namespace Deno {
/** **UNSTABLE**: New API, yet to be vetted.
*
- * @deprecated Use the Deno.Command API instead.
- *
- * Spawns a child process.
- *
- * 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` {@linkcode WritableStream}
- * needs to be closed manually.
- *
- * ```ts
- * const child = Deno.spawnChild(Deno.execPath(), {
- * args: [
- * "eval",
- * "console.log('Hello World')",
- * ],
- * stdin: "piped",
- * });
- *
- * // open a file and pipe the subprocess output to it.
- * child.stdout.pipeTo(Deno.openSync("output").writable);
- *
- * // manually close stdin
- * child.stdin.close();
- * const status = await child.status;
- * ```
- *
- * @category Sub Process
- */
- export function spawnChild(
- command: string | URL,
- options?: SpawnOptions,
- ): Child;
-
- /** **UNSTABLE**: New API, yet to be vetted.
- *
- * @deprecated Use the Deno.Command API instead.
- *
- * The interface for handling a child process returned from
- * {@linkcode Deno.spawnChild}.
- *
- * @category Sub Process
- */
- 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>;
- /** Kills the process with given {@linkcode Deno.Signal}. Defaults to
- * `"SIGTERM"`. */
- kill(signo?: Signal): void;
-
- /** Ensure that the status of the child process prevents the Deno process
- * from exiting. */
- ref(): void;
- /** Ensure that the status of the child process does not block the Deno
- * process from exiting. */
- unref(): void;
- }
-
- /** **UNSTABLE**: New API, yet to be vetted.
- *
- * @deprecated Use the Deno.Command API instead.
- *
- * 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 { code, stdout, stderr } = await Deno.spawn(Deno.execPath(), {
- * args: [
- * "eval",
- * "console.log('hello'); console.error('world')",
- * ],
- * });
- * console.assert(code === 0);
- * console.assert("hello\n" === new TextDecoder().decode(stdout));
- * console.assert("world\n" === new TextDecoder().decode(stderr));
- * ```
- *
- * @category Sub Process
- */
- export function spawn(
- command: string | URL,
- options?: SpawnOptions,
- ): Promise<SpawnOutput>;
-
- /** **UNSTABLE**: New API, yet to be vetted.
- *
- * @deprecated Use the Deno.Command API instead.
- *
- * 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 { code, stdout, stderr } = Deno.spawnSync(Deno.execPath(), {
- * args: [
- * "eval",
- * "console.log('hello'); console.error('world')",
- * ],
- * });
- * console.assert(code === 0);
- * console.assert("hello\n" === new TextDecoder().decode(stdout));
- * console.assert("world\n" === new TextDecoder().decode(stderr));
- * ```
- *
- * @category Sub Process
- */
- export function spawnSync(
- command: string | URL,
- options?: SpawnOptions,
- ): SpawnOutput;
-
- /** **UNSTABLE**: New API, yet to be vetted.
- *
- * @deprecated Use the Deno.Command API instead.
- *
- * @category Sub Process
- */
- export interface ChildStatus {
- /** If the child process exits with a 0 status code, `success` will be set
- * to `true`, otherwise `false`. */
- success: boolean;
- /** The exit code of the child process. */
- code: number;
- /** The signal associated with the child process, present if
- * {@linkcode Deno.spawn} was called. */
- signal: Signal | null;
- }
-
- /** **UNSTABLE**: New API, yet to be vetted.
- *
- * @deprecated Use the Deno.Command API instead.
- *
- * The interface returned from calling {@linkcode Deno.spawn} or
- * {@linkcode Deno.spawnSync} which represents the result of spawning the
- * child process.
- *
- * @category Sub Process
- */
- export interface SpawnOutput extends ChildStatus {
- /** The buffered output from the child processes `stdout`. */
- readonly stdout: Uint8Array;
- /** The buffered output from the child processes `stderr`. */
- readonly stderr: Uint8Array;
- }
-
- /** **UNSTABLE**: New API, yet to be vetted.
- *
* Create a child process.
*
* If any stdio options are not set to `"piped"`, accessing the corresponding
diff --git a/runtime/js/40_spawn.js b/runtime/js/40_spawn.js
index 863063e3f..ea6b409a3 100644
--- a/runtime/js/40_spawn.js
+++ b/runtime/js/40_spawn.js
@@ -60,7 +60,7 @@
function createSpawnChild(opFn) {
return function spawnChild(command, options = {}) {
- return spawnChildInner(opFn, command, "Deno.spawnChild()", options);
+ return spawnChildInner(opFn, command, "Deno.Command().spawn()", options);
};
}
@@ -219,10 +219,11 @@
return function spawn(command, options) {
if (options?.stdin === "piped") {
throw new TypeError(
- "Piped stdin is not supported for this function, use 'Deno.spawnChild()' instead",
+ "Piped stdin is not supported for this function, use 'Deno.Command().spawn()' instead",
);
}
- return spawnChildInner(opFn, command, "Deno.spawn()", options).output();
+ return spawnChildInner(opFn, command, "Deno.Command().output()", options)
+ .output();
};
}
@@ -241,7 +242,7 @@
} = {}) {
if (stdin === "piped") {
throw new TypeError(
- "Piped stdin is not supported for this function, use 'Deno.spawnChild()' instead",
+ "Piped stdin is not supported for this function, use 'Deno.Command().spawn()' instead",
);
}
const result = opFn({
diff --git a/runtime/js/99_main.js b/runtime/js/99_main.js
index adfc0d360..1eb71339f 100644
--- a/runtime/js/99_main.js
+++ b/runtime/js/99_main.js
@@ -466,12 +466,14 @@ delete Intl.v8BreakIterator;
// a snapshot
ObjectAssign(internals, {
nodeUnstable: {
- spawnChild: __bootstrap.spawn.createSpawnChild(
- ops.op_node_unstable_spawn_child,
- ),
- spawn: __bootstrap.spawn.createSpawn(ops.op_node_unstable_spawn_child),
- spawnSync: __bootstrap.spawn.createSpawnSync(
- ops.op_node_unstable_spawn_sync,
+ Command: __bootstrap.spawn.createCommand(
+ __bootstrap.spawn.createSpawn(ops.op_node_unstable_spawn_child),
+ __bootstrap.spawn.createSpawnSync(
+ ops.op_node_unstable_spawn_sync,
+ ),
+ __bootstrap.spawn.createSpawnChild(
+ ops.op_node_unstable_spawn_child,
+ ),
),
serve: __bootstrap.flash.createServe(ops.op_node_unstable_flash_serve),
upgradeHttpRaw: __bootstrap.flash.upgradeHttpRaw,
@@ -482,14 +484,6 @@ delete Intl.v8BreakIterator;
},
});
- ObjectAssign(internals.nodeUnstable, {
- Command: __bootstrap.spawn.createCommand(
- internals.nodeUnstable.spawn,
- internals.nodeUnstable.spawnSync,
- internals.nodeUnstable.spawnChild,
- ),
- });
-
const finalDenoNs = {
core,
internal: internalSymbol,
@@ -512,23 +506,17 @@ delete Intl.v8BreakIterator;
// the op function that needs to be passed will be invalidated by creating
// a snapshot
ObjectAssign(finalDenoNs, {
- spawnChild: __bootstrap.spawn.createSpawnChild(ops.op_spawn_child),
- spawn: __bootstrap.spawn.createSpawn(ops.op_spawn_child),
- spawnSync: __bootstrap.spawn.createSpawnSync(ops.op_spawn_sync),
+ Command: __bootstrap.spawn.createCommand(
+ __bootstrap.spawn.createSpawn(ops.op_spawn_child),
+ __bootstrap.spawn.createSpawnSync(ops.op_spawn_sync),
+ __bootstrap.spawn.createSpawnChild(ops.op_spawn_child),
+ ),
serve: __bootstrap.flash.createServe(ops.op_flash_serve),
listenDatagram: __bootstrap.net.createListenDatagram(
ops.op_net_listen_udp,
ops.op_net_listen_unixpacket,
),
});
-
- ObjectAssign(finalDenoNs, {
- Command: __bootstrap.spawn.createCommand(
- finalDenoNs.spawn,
- finalDenoNs.spawnSync,
- finalDenoNs.spawnChild,
- ),
- });
}
// Setup `Deno` global - we're actually overriding already existing global
@@ -617,12 +605,14 @@ delete Intl.v8BreakIterator;
// a snapshot
ObjectAssign(internals, {
nodeUnstable: {
- spawnChild: __bootstrap.spawn.createSpawnChild(
- ops.op_node_unstable_spawn_child,
- ),
- spawn: __bootstrap.spawn.createSpawn(ops.op_node_unstable_spawn_child),
- spawnSync: __bootstrap.spawn.createSpawnSync(
- ops.op_node_unstable_spawn_sync,
+ Command: __bootstrap.spawn.createCommand(
+ __bootstrap.spawn.createSpawn(ops.op_node_unstable_spawn_child),
+ __bootstrap.spawn.createSpawnSync(
+ ops.op_node_unstable_spawn_sync,
+ ),
+ __bootstrap.spawn.createSpawnChild(
+ ops.op_node_unstable_spawn_child,
+ ),
),
serve: __bootstrap.flash.createServe(ops.op_node_unstable_flash_serve),
upgradeHttpRaw: __bootstrap.flash.upgradeHttpRaw,
@@ -633,14 +623,6 @@ delete Intl.v8BreakIterator;
},
});
- ObjectAssign(internals.nodeUnstable, {
- Command: __bootstrap.spawn.createCommand(
- internals.nodeUnstable.spawn,
- internals.nodeUnstable.spawnSync,
- internals.nodeUnstable.spawnChild,
- ),
- });
-
const finalDenoNs = {
core,
internal: internalSymbol,
@@ -655,22 +637,17 @@ delete Intl.v8BreakIterator;
// the op function that needs to be passed will be invalidated by creating
// a snapshot
ObjectAssign(finalDenoNs, {
- spawnChild: __bootstrap.spawn.createSpawnChild(ops.op_spawn_child),
- spawn: __bootstrap.spawn.createSpawn(ops.op_spawn_child),
- spawnSync: __bootstrap.spawn.createSpawnSync(ops.op_spawn_sync),
+ Command: __bootstrap.spawn.createCommand(
+ __bootstrap.spawn.createSpawn(ops.op_spawn_child),
+ __bootstrap.spawn.createSpawnSync(ops.op_spawn_sync),
+ __bootstrap.spawn.createSpawnChild(ops.op_spawn_child),
+ ),
serve: __bootstrap.flash.createServe(ops.op_flash_serve),
listenDatagram: __bootstrap.net.createListenDatagram(
ops.op_net_listen_udp,
ops.op_net_listen_unixpacket,
),
});
- ObjectAssign(finalDenoNs, {
- Command: __bootstrap.spawn.createCommand(
- finalDenoNs.spawn,
- finalDenoNs.spawnSync,
- finalDenoNs.spawnChild,
- ),
- });
}
ObjectDefineProperties(finalDenoNs, {
pid: util.readOnly(runtimeOptions.pid),
diff --git a/runtime/ops/spawn.rs b/runtime/ops/spawn.rs
index 03ab7d5c2..11940013c 100644
--- a/runtime/ops/spawn.rs
+++ b/runtime/ops/spawn.rs
@@ -350,7 +350,8 @@ fn op_spawn_sync(
) -> Result<SpawnOutput, AnyError> {
let stdout = matches!(args.stdio.stdout, Stdio::Piped);
let stderr = matches!(args.stdio.stderr, Stdio::Piped);
- let output = create_command(state, args, "Deno.spawnSync()")?.output()?;
+ let output =
+ create_command(state, args, "Deno.Command().outputSync()")?.output()?;
Ok(SpawnOutput {
status: output.status.try_into()?,
@@ -375,7 +376,8 @@ fn op_node_unstable_spawn_sync(
let stdout = matches!(args.stdio.stdout, Stdio::Piped);
let stderr = matches!(args.stdio.stderr, Stdio::Piped);
let output =
- node_unstable_create_command(state, args, "Deno.spawnSync()")?.output()?;
+ node_unstable_create_command(state, args, "Deno.Command().outputSync()")?
+ .output()?;
Ok(SpawnOutput {
status: output.status.try_into()?,