summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cli/js/lib.deno.ns.d.ts10
-rw-r--r--cli/js/process.ts45
-rw-r--r--cli/tests/unit/process_test.ts18
-rw-r--r--std/examples/chat/server_test.ts10
-rw-r--r--std/examples/tests/catj_test.ts14
-rw-r--r--std/examples/tests/echo_server_test.ts4
-rw-r--r--std/http/file_server_test.ts2
-rw-r--r--std/http/racing_server_test.ts4
-rw-r--r--std/http/server_test.ts8
9 files changed, 61 insertions, 54 deletions
diff --git a/cli/js/lib.deno.ns.d.ts b/cli/js/lib.deno.ns.d.ts
index 63e9b342e..c79007ebd 100644
--- a/cli/js/lib.deno.ns.d.ts
+++ b/cli/js/lib.deno.ns.d.ts
@@ -1741,12 +1741,12 @@ declare namespace Deno {
options?: { recursive: boolean }
): AsyncIterableIterator<FsEvent>;
- export class Process {
+ export class Process<T extends RunOptions = RunOptions> {
readonly rid: number;
readonly pid: number;
- readonly stdin?: Writer & Closer;
- readonly stdout?: Reader & Closer;
- readonly stderr?: Reader & Closer;
+ readonly stdin: T["stdin"] extends "piped" ? Writer & Closer : null;
+ readonly stdout: T["stdout"] extends "piped" ? Reader & Closer : null;
+ readonly stderr: T["stderr"] extends "piped" ? Reader & Closer : null;
/** Resolves to the current status of the process. */
status(): Promise<ProcessStatus>;
/** Buffer the stdout until EOF and return it as `Uint8Array`.
@@ -1829,7 +1829,7 @@ declare namespace Deno {
* Details of the spawned process are returned.
*
* Requires `allow-run` permission. */
- export function run(opt: RunOptions): Process;
+ export function run<T extends RunOptions = RunOptions>(opt: T): Process<T>;
interface InspectOptions {
depth?: number;
diff --git a/cli/js/process.ts b/cli/js/process.ts
index c8627f86d..cfae7fe56 100644
--- a/cli/js/process.ts
+++ b/cli/js/process.ts
@@ -5,17 +5,15 @@ import { Closer, Reader, Writer } from "./io.ts";
import { readAll } from "./buffer.ts";
import { kill, runStatus as runStatusOp, run as runOp } from "./ops/process.ts";
-export type ProcessStdio = "inherit" | "piped" | "null";
-
// TODO Maybe extend VSCode's 'CommandOptions'?
// See https://code.visualstudio.com/docs/editor/tasks-appendix#_schema-for-tasksjson
export interface RunOptions {
cmd: string[];
cwd?: string;
env?: { [key: string]: string };
- stdout?: ProcessStdio | number;
- stderr?: ProcessStdio | number;
- stdin?: ProcessStdio | number;
+ stdout?: "inherit" | "piped" | "null" | number;
+ stderr?: "inherit" | "piped" | "null" | number;
+ stdin?: "inherit" | "piped" | "null" | number;
}
async function runStatus(rid: number): Promise<ProcessStatus> {
@@ -30,12 +28,12 @@ async function runStatus(rid: number): Promise<ProcessStatus> {
}
}
-export class Process {
+export class Process<T extends RunOptions = RunOptions> {
readonly rid: number;
readonly pid: number;
- readonly stdin?: Writer & Closer;
- readonly stdout?: Reader & Closer;
- readonly stderr?: Reader & Closer;
+ readonly stdin!: T["stdin"] extends "piped" ? Writer & Closer : null;
+ readonly stdout!: T["stdout"] extends "piped" ? Reader & Closer : null;
+ readonly stderr!: T["stderr"] extends "piped" ? Reader & Closer : null;
// @internal
constructor(res: RunResponse) {
@@ -43,15 +41,19 @@ export class Process {
this.pid = res.pid;
if (res.stdinRid && res.stdinRid > 0) {
- this.stdin = new File(res.stdinRid);
+ this.stdin = (new File(res.stdinRid) as unknown) as Process<T>["stdin"];
}
if (res.stdoutRid && res.stdoutRid > 0) {
- this.stdout = new File(res.stdoutRid);
+ this.stdout = (new File(res.stdoutRid) as unknown) as Process<
+ T
+ >["stdout"];
}
if (res.stderrRid && res.stderrRid > 0) {
- this.stderr = new File(res.stderrRid);
+ this.stderr = (new File(res.stderrRid) as unknown) as Process<
+ T
+ >["stderr"];
}
}
@@ -61,23 +63,23 @@ export class Process {
async output(): Promise<Uint8Array> {
if (!this.stdout) {
- throw new Error("Process.output: stdout is undefined");
+ throw new TypeError("stdout was not piped");
}
try {
- return await readAll(this.stdout);
+ return await readAll(this.stdout as Reader & Closer);
} finally {
- this.stdout.close();
+ (this.stdout as Reader & Closer).close();
}
}
async stderrOutput(): Promise<Uint8Array> {
if (!this.stderr) {
- throw new Error("Process.stderrOutput: stderr is undefined");
+ throw new TypeError("stderr was not piped");
}
try {
- return await readAll(this.stderr);
+ return await readAll(this.stderr as Reader & Closer);
} finally {
- this.stderr.close();
+ (this.stderr as Reader & Closer).close();
}
}
@@ -107,14 +109,15 @@ interface RunResponse {
stdoutRid: number | null;
stderrRid: number | null;
}
-export function run({
+
+export function run<T extends RunOptions = RunOptions>({
cmd,
cwd = undefined,
env = {},
stdout = "inherit",
stderr = "inherit",
stdin = "inherit",
-}: RunOptions): Process {
+}: T): Process<T> {
const res = runOp({
cmd: cmd.map(String),
cwd,
@@ -126,5 +129,5 @@ export function run({
stdoutRid: isRid(stdout) ? stdout : 0,
stderrRid: isRid(stderr) ? stderr : 0,
}) as RunResponse;
- return new Process(res);
+ return new Process<T>(res);
}
diff --git a/cli/tests/unit/process_test.ts b/cli/tests/unit/process_test.ts
index abd845041..79e36dc4b 100644
--- a/cli/tests/unit/process_test.ts
+++ b/cli/tests/unit/process_test.ts
@@ -36,7 +36,7 @@ unitTest({ perms: { run: true } }, async function runSuccess(): Promise<void> {
assertEquals(status.success, true);
assertEquals(status.code, 0);
assertEquals(status.signal, undefined);
- p.stdout!.close();
+ p.stdout.close();
p.close();
});
@@ -141,7 +141,7 @@ unitTest({ perms: { run: true } }, async function runStdinPiped(): Promise<
const n = await p.stdin.write(msg);
assertEquals(n, msg.byteLength);
- p.stdin!.close();
+ p.stdin.close();
const status = await p.status();
assertEquals(status.success, true);
@@ -161,16 +161,16 @@ unitTest({ perms: { run: true } }, async function runStdoutPiped(): Promise<
assert(!p.stderr);
const data = new Uint8Array(10);
- let r = await p.stdout!.read(data);
+ let r = await p.stdout.read(data);
if (r === null) {
throw new Error("p.stdout.read(...) should not be null");
}
assertEquals(r, 5);
const s = new TextDecoder().decode(data.subarray(0, r));
assertEquals(s, "hello");
- r = await p.stdout!.read(data);
+ r = await p.stdout.read(data);
assertEquals(r, null);
- p.stdout!.close();
+ p.stdout.close();
const status = await p.status();
assertEquals(status.success, true);
@@ -190,14 +190,14 @@ unitTest({ perms: { run: true } }, async function runStderrPiped(): Promise<
assert(!p.stdout);
const data = new Uint8Array(10);
- let r = await p.stderr!.read(data);
+ let r = await p.stderr.read(data);
if (r === null) {
throw new Error("p.stderr.read should not return null here");
}
assertEquals(r, 5);
const s = new TextDecoder().decode(data.subarray(0, r));
assertEquals(s, "hello");
- r = await p.stderr!.read(data);
+ r = await p.stderr.read(data);
assertEquals(r, null);
p.stderr!.close();
@@ -320,9 +320,9 @@ unitTest({ perms: { run: true } }, async function runClose(): Promise<void> {
p.close();
const data = new Uint8Array(10);
- const r = await p.stderr!.read(data);
+ const r = await p.stderr.read(data);
assertEquals(r, null);
- p.stderr!.close();
+ p.stderr.close();
});
unitTest(function signalNumbers(): void {
diff --git a/std/examples/chat/server_test.ts b/std/examples/chat/server_test.ts
index 7375de47a..8e04b71d8 100644
--- a/std/examples/chat/server_test.ts
+++ b/std/examples/chat/server_test.ts
@@ -7,7 +7,9 @@ import { delay } from "../../async/delay.ts";
const { test } = Deno;
-async function startServer(): Promise<Deno.Process> {
+async function startServer(): Promise<
+ Deno.Process<Deno.RunOptions & { stdout: "piped" }>
+> {
const server = Deno.run({
// TODO(lucacasonato): remove unstable once possible
cmd: [
@@ -27,7 +29,7 @@ async function startServer(): Promise<Deno.Process> {
const s = await r.readLine();
assert(s !== null && s.includes("chat server starting"));
} catch (err) {
- server.stdout!.close();
+ server.stdout.close();
server.close();
}
@@ -46,7 +48,7 @@ test({
assert(html.includes("ws chat example"), "body is ok");
} finally {
server.close();
- server.stdout!.close();
+ server.stdout.close();
}
await delay(10);
},
@@ -66,7 +68,7 @@ test({
assertEquals((await it.next()).value, "[1]: Hello");
} finally {
server.close();
- server.stdout!.close();
+ server.stdout.close();
ws!.conn.close();
}
},
diff --git a/std/examples/tests/catj_test.ts b/std/examples/tests/catj_test.ts
index a859db0c1..58533ab60 100644
--- a/std/examples/tests/catj_test.ts
+++ b/std/examples/tests/catj_test.ts
@@ -17,7 +17,7 @@ Deno.test("[examples/catj] print an array", async () => {
assertStrictEquals(actual, expected);
} finally {
- process.stdin!.close();
+ process.stdin.close();
process.close();
}
});
@@ -36,7 +36,7 @@ Deno.test("[examples/catj] print an object", async () => {
assertStrictEquals(actual, expected);
} finally {
- process.stdin!.close();
+ process.stdin.close();
process.close();
}
});
@@ -54,7 +54,7 @@ Deno.test("[examples/catj] print multiple files", async () => {
assertStrictEquals(actual, expected);
} finally {
- process.stdin!.close();
+ process.stdin.close();
process.close();
}
});
@@ -64,8 +64,8 @@ Deno.test("[examples/catj] read from stdin", async () => {
const process = catj("-");
const input = `{ "foo": "bar" }`;
try {
- await process.stdin!.write(new TextEncoder().encode(input));
- process.stdin!.close();
+ await process.stdin.write(new TextEncoder().encode(input));
+ process.stdin.close();
const output = await process.output();
const actual = decoder.decode(output).trim();
@@ -75,7 +75,9 @@ Deno.test("[examples/catj] read from stdin", async () => {
}
});
-function catj(...files: string[]): Deno.Process {
+function catj(
+ ...files: string[]
+): Deno.Process<Deno.RunOptions & { stdin: "piped"; stdout: "piped" }> {
return Deno.run({
cmd: [Deno.execPath(), "run", "--allow-read", "catj.ts", ...files],
cwd: "examples",
diff --git a/std/examples/tests/echo_server_test.ts b/std/examples/tests/echo_server_test.ts
index 475b0f73f..2cf52e466 100644
--- a/std/examples/tests/echo_server_test.ts
+++ b/std/examples/tests/echo_server_test.ts
@@ -13,7 +13,7 @@ Deno.test("[examples/echo_server]", async () => {
let conn: Deno.Conn | undefined;
try {
- const processReader = new BufReader(process.stdout!);
+ const processReader = new BufReader(process.stdout);
const message = await processReader.readLine();
assertNotEquals(message, null);
@@ -38,7 +38,7 @@ Deno.test("[examples/echo_server]", async () => {
assertStrictEquals(actualResponse, expectedResponse);
} finally {
conn?.close();
- process.stdout!.close();
+ process.stdout.close();
process.close();
}
});
diff --git a/std/http/file_server_test.ts b/std/http/file_server_test.ts
index dbbaf81ff..ceea566fa 100644
--- a/std/http/file_server_test.ts
+++ b/std/http/file_server_test.ts
@@ -5,7 +5,7 @@ import { TextProtoReader } from "../textproto/mod.ts";
import { ServerRequest } from "./server.ts";
import { serveFile } from "./file_server.ts";
const { test } = Deno;
-let fileServer: Deno.Process;
+let fileServer: Deno.Process<Deno.RunOptions & { stdout: "piped" }>;
type FileServerCfg = {
target?: string;
diff --git a/std/http/racing_server_test.ts b/std/http/racing_server_test.ts
index 845e5a490..054dfc385 100644
--- a/std/http/racing_server_test.ts
+++ b/std/http/racing_server_test.ts
@@ -3,7 +3,7 @@ import { BufReader, BufWriter } from "../io/bufio.ts";
import { TextProtoReader } from "../textproto/mod.ts";
const { connect, run, test } = Deno;
-let server: Deno.Process;
+let server: Deno.Process<Deno.RunOptions & { stdout: "piped" }>;
async function startServer(): Promise<void> {
server = run({
// TODO(lucacasonato): remove unstable when stabilized
@@ -18,7 +18,7 @@ async function startServer(): Promise<void> {
}
function killServer(): void {
server.close();
- server.stdout?.close();
+ server.stdout.close();
}
const input = [
diff --git a/std/http/server_test.ts b/std/http/server_test.ts
index d522b9a8f..2d911c450 100644
--- a/std/http/server_test.ts
+++ b/std/http/server_test.ts
@@ -372,7 +372,7 @@ test({
.catch((_): void => {}); // Ignores the error when closing the process.
try {
- const r = new TextProtoReader(new BufReader(p.stdout!));
+ const r = new TextProtoReader(new BufReader(p.stdout));
const s = await r.readLine();
assert(s !== null && s.includes("server listening"));
await delay(100);
@@ -387,7 +387,7 @@ test({
// Stops the sever and allows `p.status()` promise to resolve
Deno.kill(p.pid, Deno.Signal.SIGKILL);
await statusPromise;
- p.stdout!.close();
+ p.stdout.close();
p.close();
}
},
@@ -417,7 +417,7 @@ test({
.catch((_): void => {}); // Ignores the error when closing the process.
try {
- const r = new TextProtoReader(new BufReader(p.stdout!));
+ const r = new TextProtoReader(new BufReader(p.stdout));
const s = await r.readLine();
assert(
s !== null && s.includes("server listening"),
@@ -444,7 +444,7 @@ test({
// Stops the sever and allows `p.status()` promise to resolve
Deno.kill(p.pid, Deno.Signal.SIGKILL);
await statusPromise;
- p.stdout!.close();
+ p.stdout.close();
p.close();
}
},