From 4e3ec478573ede7247fd306cad1ea5bf2d5c9565 Mon Sep 17 00:00:00 2001
From: Yoshiya Hinosawa <stibium121@gmail.com>
Date: Tue, 22 Jun 2021 15:17:44 +0900
Subject: [PATCH] fix(runtime): fix signal promise API (#11069)

---
 cli/tests/unit/signal_test.ts | 29 +++++++++++++++++++++++++++++
 runtime/js/40_signals.js      | 10 +++++++++-
 2 files changed, 38 insertions(+), 1 deletion(-)

diff --git a/cli/tests/unit/signal_test.ts b/cli/tests/unit/signal_test.ts
index 801e15d8b6b372..e0e94b49ab1d6a 100644
--- a/cli/tests/unit/signal_test.ts
+++ b/cli/tests/unit/signal_test.ts
@@ -154,6 +154,35 @@ unitTest(
   },
 );
 
+// https://github.com/denoland/deno/issues/9806
+unitTest(
+  { ignore: Deno.build.os === "windows", perms: { run: true } },
+  async function signalPromiseTest2(): Promise<void> {
+    const resolvable = deferred();
+    // This prevents the program from exiting.
+    const t = setInterval(() => {}, 1000);
+
+    let called = false;
+    const sig = Deno.signal(Deno.Signal.SIGUSR1);
+    sig.then(() => {
+      called = true;
+    });
+    setTimeout(() => {
+      sig.dispose();
+      setTimeout(() => {
+        resolvable.resolve();
+      }, 10);
+    }, 10);
+
+    clearInterval(t);
+    await resolvable;
+
+    // Promise callback is not called because it didn't get
+    // the corresponding signal.
+    assert(!called);
+  },
+);
+
 unitTest(
   { ignore: Deno.build.os === "windows", perms: { run: true } },
   function signalShorthandsTest(): void {
diff --git a/runtime/js/40_signals.js b/runtime/js/40_signals.js
index dfc60475906678..bf6be1263b1661 100644
--- a/runtime/js/40_signals.js
+++ b/runtime/js/40_signals.js
@@ -236,7 +236,15 @@
       f,
       g,
     ) {
-      return this.#pollingPromise.then(() => {}).then(f, g);
+      return this.#pollingPromise.then((done) => {
+        if (done) {
+          // If pollingPromise returns true, then
+          // this signal stream is finished and the promise API
+          // should never be resolved.
+          return new Promise(() => {});
+        }
+        return;
+      }).then(f, g);
     }
 
     async next() {