summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cli/js/lib.deno.ns.d.ts5
-rw-r--r--cli/js/signals.ts5
-rw-r--r--std/signal/mod.ts28
-rw-r--r--std/signal/test.ts53
4 files changed, 87 insertions, 4 deletions
diff --git a/cli/js/lib.deno.ns.d.ts b/cli/js/lib.deno.ns.d.ts
index 0f6ea2221..6d06a8cd6 100644
--- a/cli/js/lib.deno.ns.d.ts
+++ b/cli/js/lib.deno.ns.d.ts
@@ -2146,14 +2146,15 @@ declare namespace Deno {
* SignalStream represents the stream of signals, implements both
* AsyncIterator and PromiseLike
*/
- export class SignalStream implements AsyncIterator<void>, PromiseLike<void> {
+ export class SignalStream
+ implements AsyncIterableIterator<void>, PromiseLike<void> {
constructor(signal: typeof Deno.Signal);
then<T, S>(
f: (v: void) => T | Promise<T>,
g?: (v: void) => S | Promise<S>
): Promise<T | S>;
next(): Promise<IteratorResult<void>>;
- [Symbol.asyncIterator](): AsyncIterator<void>;
+ [Symbol.asyncIterator](): AsyncIterableIterator<void>;
dispose(): void;
}
diff --git a/cli/js/signals.ts b/cli/js/signals.ts
index 02d52bc2f..9f47313d4 100644
--- a/cli/js/signals.ts
+++ b/cli/js/signals.ts
@@ -96,7 +96,8 @@ export const signals = {
/** SignalStream represents the stream of signals, implements both
* AsyncIterator and PromiseLike */
-export class SignalStream implements AsyncIterator<void>, PromiseLike<void> {
+export class SignalStream
+ implements AsyncIterableIterator<void>, PromiseLike<void> {
private rid: number;
/** The promise of polling the signal,
* resolves with false when it receives signal,
@@ -134,7 +135,7 @@ export class SignalStream implements AsyncIterator<void>, PromiseLike<void> {
return { done: await this.pollingPromise, value: undefined };
}
- [Symbol.asyncIterator](): AsyncIterator<void> {
+ [Symbol.asyncIterator](): AsyncIterableIterator<void> {
return this;
}
diff --git a/std/signal/mod.ts b/std/signal/mod.ts
new file mode 100644
index 000000000..e368edbd1
--- /dev/null
+++ b/std/signal/mod.ts
@@ -0,0 +1,28 @@
+import { MuxAsyncIterator } from "../util/async.ts";
+
+export function signal(
+ ...signos: [number, ...number[]]
+): AsyncIterable<void> & { dispose: () => void } {
+ const mux = new MuxAsyncIterator<void>();
+
+ if (signos.length < 1) {
+ throw new Error(
+ "No signals are given. You need to specify at least one signal to create a signal stream."
+ );
+ }
+
+ const streams = signos.map(Deno.signal);
+
+ streams.forEach(stream => {
+ mux.add(stream);
+ });
+
+ // Create dispose method for the muxer of signal streams.
+ const dispose = (): void => {
+ streams.forEach(stream => {
+ stream.dispose();
+ });
+ };
+
+ return Object.assign(mux, { dispose });
+}
diff --git a/std/signal/test.ts b/std/signal/test.ts
new file mode 100644
index 000000000..cff9672e5
--- /dev/null
+++ b/std/signal/test.ts
@@ -0,0 +1,53 @@
+import { test, assertEquals, assertThrows } from "../testing/mod.ts";
+import { delay } from "../util/async.ts";
+import { signal } from "./mod.ts";
+
+if (Deno.build.os !== "win") {
+ test("signal() throws when called with empty signals", (): void => {
+ assertThrows(
+ () => {
+ // @ts-ignore
+ signal();
+ },
+ Error,
+ "No signals are given. You need to specify at least one signal to create a signal stream."
+ );
+ });
+
+ test("signal() iterates for multiple signals", async (): Promise<void> => {
+ // This prevents the program from exiting.
+ const t = setInterval(() => {}, 1000);
+
+ let c = 0;
+ const sig = signal(
+ Deno.Signal.SIGUSR1,
+ Deno.Signal.SIGUSR2,
+ Deno.Signal.SIGINT
+ );
+
+ setTimeout(async () => {
+ await delay(20);
+ Deno.kill(Deno.pid, Deno.Signal.SIGINT);
+ await delay(20);
+ Deno.kill(Deno.pid, Deno.Signal.SIGUSR2);
+ await delay(20);
+ Deno.kill(Deno.pid, Deno.Signal.SIGUSR1);
+ await delay(20);
+ Deno.kill(Deno.pid, Deno.Signal.SIGUSR2);
+ await delay(20);
+ Deno.kill(Deno.pid, Deno.Signal.SIGUSR1);
+ await delay(20);
+ Deno.kill(Deno.pid, Deno.Signal.SIGINT);
+ await delay(20);
+ sig.dispose();
+ });
+
+ for await (const _ of sig) {
+ c += 1;
+ }
+
+ assertEquals(c, 6);
+
+ clearTimeout(t);
+ });
+}