Fix Promise.await() never resuming if the promise rejected with a non-Throwable (#4120)

diff --git a/kotlinx-coroutines-core/js/src/Promise.kt b/kotlinx-coroutines-core/js/src/Promise.kt
index f84338a..5eb93d3 100644
--- a/kotlinx-coroutines-core/js/src/Promise.kt
+++ b/kotlinx-coroutines-core/js/src/Promise.kt
@@ -63,5 +63,5 @@
 public suspend fun <T> Promise<T>.await(): T = suspendCancellableCoroutine { cont: CancellableContinuation<T> ->
     this@await.then(
         onFulfilled = { cont.resume(it) },
-        onRejected = { cont.resumeWithException(it) })
+        onRejected = { cont.resumeWithException(it as? Throwable ?: Exception("Non-Kotlin exception $it")) })
 }
diff --git a/kotlinx-coroutines-core/js/test/PromiseTest.kt b/kotlinx-coroutines-core/js/test/PromiseTest.kt
index 319778d..f9cb0ed 100644
--- a/kotlinx-coroutines-core/js/test/PromiseTest.kt
+++ b/kotlinx-coroutines-core/js/test/PromiseTest.kt
@@ -83,4 +83,27 @@
             if (seq != 1) error("Unexpected result: $seq")
         }
     }
+
+    @Test
+    fun testAwaitPromiseRejectedWithNonKotlinException() = GlobalScope.promise {
+        lateinit var r: (dynamic) -> Unit
+        val toAwait = Promise<dynamic> { _, reject -> r = reject }
+        val throwable = async(start = CoroutineStart.UNDISPATCHED) {
+            assertFails { toAwait.await() }
+        }
+        r("Rejected")
+        assertContains(throwable.await().message ?: "", "Rejected")
+    }
+
+    @Test
+    fun testAwaitPromiseRejectedWithKotlinException() = GlobalScope.promise {
+        lateinit var r: (dynamic) -> Unit
+        val toAwait = Promise<dynamic> { _, reject -> r = reject }
+        val throwable = async(start = CoroutineStart.UNDISPATCHED) {
+            assertFails { toAwait.await() }
+        }
+        r(RuntimeException("Rejected"))
+        assertIs<RuntimeException>(throwable.await())
+        assertEquals("Rejected", throwable.await().message)
+    }
 }
diff --git a/kotlinx-coroutines-core/wasmJs/test/PromiseTest.kt b/kotlinx-coroutines-core/wasmJs/test/PromiseTest.kt
index 6355043..e72e661 100644
--- a/kotlinx-coroutines-core/wasmJs/test/PromiseTest.kt
+++ b/kotlinx-coroutines-core/wasmJs/test/PromiseTest.kt
@@ -84,4 +84,27 @@
             null
         }
     }
+
+    @Test
+    fun testAwaitPromiseRejectedWithNonKotlinException() = GlobalScope.promise {
+        lateinit var r: (JsAny) -> Unit
+        val toAwait = Promise<JsAny?> { _, reject -> r = reject }
+        val throwable = async(start = CoroutineStart.UNDISPATCHED) {
+            assertFails { toAwait.await<JsAny?>() }
+        }
+        r("Rejected".toJsString())
+        assertIs<JsException>(throwable.await())
+    }
+
+    @Test
+    fun testAwaitPromiseRejectedWithKotlinException() = GlobalScope.promise {
+        lateinit var r: (JsAny) -> Unit
+        val toAwait = Promise<JsAny?> { _, reject -> r = reject }
+        val throwable = async(start = CoroutineStart.UNDISPATCHED) {
+            assertFails { toAwait.await<JsAny?>() }
+        }
+        r(RuntimeException("Rejected").toJsReference())
+        assertIs<RuntimeException>(throwable.await())
+        assertEquals("Rejected", throwable.await().message)
+    }
 }