Skip to content

Commit

Permalink
Fix JS websocket throws an ISE on error on Safari and Firefox (#5670)
Browse files Browse the repository at this point in the history
We're seeing the error event fire when the websocket closes as a result
of a network error on Safari and Firefox. Since the socket has already
been opened, the coroutine has already been resumed and this throws an
IllegalStateException ("Already resumed").
  • Loading branch information
baconz committed Mar 4, 2024
1 parent f2dc563 commit 36c152b
Showing 1 changed file with 24 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -101,26 +101,40 @@ actual class DefaultWebSocketEngine : WebSocketEngine {
private suspend fun WebSocket.awaitConnection(): WebSocket = suspendCancellableCoroutine { continuation ->
if (continuation.isCancelled) return@suspendCancellableCoroutine

val eventListener = { event: Event ->
when (event.type) {
"open" -> continuation.resume(this)
"error" -> {
continuation.resumeWithException(IllegalStateException(event.asString()))
var eventListener: ((Event) -> Unit)? = null
val removeEventListeners = {
removeEventListener("open", callback = eventListener)
removeEventListener("error", callback = eventListener)
}

eventListener = { event: Event ->
if (!continuation.isCancelled) {
when (event.type) {
"open" -> {
continuation.resume(this)
/**
* If the websocket fires an error after it has been connected we don't want to
* pick that up here because we've already resumed the coroutine.
*/
removeEventListeners()
}
"error" -> {
continuation.resumeWithException(IllegalStateException(event.asString()))
}
}
}
}

addEventListener("open", callback = eventListener)
addEventListener("error", callback = eventListener)

continuation.invokeOnCancellation {
removeEventListener("open", callback = eventListener)
removeEventListener("error", callback = eventListener)
removeEventListeners()

if (it != null) {
this@awaitConnection.close()
}
}

addEventListener("open", callback = eventListener)
addEventListener("error", callback = eventListener)
}

private fun Event.asString(): String = buildString {
Expand Down

0 comments on commit 36c152b

Please sign in to comment.