Skip to content

Commit 6b73546

Browse files
authored
Fix Promise.await() never resuming if the promise rejected with a non-Throwable (#4120)
1 parent 0e1c157 commit 6b73546

File tree

3 files changed

+47
-1
lines changed

3 files changed

+47
-1
lines changed

kotlinx-coroutines-core/js/src/Promise.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -63,5 +63,5 @@ public fun <T> Promise<T>.asDeferred(): Deferred<T> {
6363
public suspend fun <T> Promise<T>.await(): T = suspendCancellableCoroutine { cont: CancellableContinuation<T> ->
6464
this@await.then(
6565
onFulfilled = { cont.resume(it) },
66-
onRejected = { cont.resumeWithException(it) })
66+
onRejected = { cont.resumeWithException(it as? Throwable ?: Exception("Non-Kotlin exception $it")) })
6767
}

kotlinx-coroutines-core/js/test/PromiseTest.kt

+23
Original file line numberDiff line numberDiff line change
@@ -83,4 +83,27 @@ class PromiseTest : TestBase() {
8383
if (seq != 1) error("Unexpected result: $seq")
8484
}
8585
}
86+
87+
@Test
88+
fun testAwaitPromiseRejectedWithNonKotlinException() = GlobalScope.promise {
89+
lateinit var r: (dynamic) -> Unit
90+
val toAwait = Promise<dynamic> { _, reject -> r = reject }
91+
val throwable = async(start = CoroutineStart.UNDISPATCHED) {
92+
assertFails { toAwait.await() }
93+
}
94+
r("Rejected")
95+
assertContains(throwable.await().message ?: "", "Rejected")
96+
}
97+
98+
@Test
99+
fun testAwaitPromiseRejectedWithKotlinException() = GlobalScope.promise {
100+
lateinit var r: (dynamic) -> Unit
101+
val toAwait = Promise<dynamic> { _, reject -> r = reject }
102+
val throwable = async(start = CoroutineStart.UNDISPATCHED) {
103+
assertFails { toAwait.await() }
104+
}
105+
r(RuntimeException("Rejected"))
106+
assertIs<RuntimeException>(throwable.await())
107+
assertEquals("Rejected", throwable.await().message)
108+
}
86109
}

kotlinx-coroutines-core/wasmJs/test/PromiseTest.kt

+23
Original file line numberDiff line numberDiff line change
@@ -84,4 +84,27 @@ class PromiseTest : TestBase() {
8484
null
8585
}
8686
}
87+
88+
@Test
89+
fun testAwaitPromiseRejectedWithNonKotlinException() = GlobalScope.promise {
90+
lateinit var r: (JsAny) -> Unit
91+
val toAwait = Promise<JsAny?> { _, reject -> r = reject }
92+
val throwable = async(start = CoroutineStart.UNDISPATCHED) {
93+
assertFails { toAwait.await<JsAny?>() }
94+
}
95+
r("Rejected".toJsString())
96+
assertIs<JsException>(throwable.await())
97+
}
98+
99+
@Test
100+
fun testAwaitPromiseRejectedWithKotlinException() = GlobalScope.promise {
101+
lateinit var r: (JsAny) -> Unit
102+
val toAwait = Promise<JsAny?> { _, reject -> r = reject }
103+
val throwable = async(start = CoroutineStart.UNDISPATCHED) {
104+
assertFails { toAwait.await<JsAny?>() }
105+
}
106+
r(RuntimeException("Rejected").toJsReference())
107+
assertIs<RuntimeException>(throwable.await())
108+
assertEquals("Rejected", throwable.await().message)
109+
}
87110
}

0 commit comments

Comments
 (0)