Skip to content

Commit

Permalink
Fix JS websocket throws an ISE on error on Safari and Firefox
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 1, 2024
1 parent 8ed420a commit ae01091
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 ae01091

Please sign in to comment.