Skip to content

Commit d49eb50

Browse files
committed
Fixed Coroutine Cancellation Exception for concurrent close and offer
1 parent 5844b72 commit d49eb50

File tree

7 files changed

+20
-17
lines changed
  • firebase-auth/src
    • androidMain/kotlin/dev/gitlive/firebase/auth
    • iosMain/kotlin/dev/gitlive/firebase/auth
    • jsMain/kotlin/dev/gitlive/firebase/auth
  • firebase-database/src
    • androidMain/kotlin/dev/gitlive/firebase/database
    • iosMain/kotlin/dev/gitlive/firebase/database
    • jsMain/kotlin/dev/gitlive/firebase/database
  • firebase-firestore/src/jsMain/kotlin/dev/gitlive/firebase/firestore

7 files changed

+20
-17
lines changed

firebase-auth/src/androidMain/kotlin/dev/gitlive/firebase/auth/auth.kt

+2-2
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,14 @@ actual class FirebaseAuth internal constructor(val android: com.google.firebase.
2626
get() = android.currentUser?.let { FirebaseUser(it) }
2727

2828
actual val authStateChanged get() = callbackFlow {
29-
val listener = AuthStateListener { auth -> offer(auth.currentUser?.let { FirebaseUser(it) }) }
29+
val listener = AuthStateListener { auth -> if (!isClosedForSend) offer(auth.currentUser?.let { FirebaseUser(it) }) }
3030
android.addAuthStateListener(listener)
3131
awaitClose { android.removeAuthStateListener(listener) }
3232
}
3333

3434
actual val idTokenChanged: Flow<FirebaseUser?>
3535
get() = callbackFlow {
36-
val listener = com.google.firebase.auth.FirebaseAuth.IdTokenListener { auth -> offer(auth.currentUser?.let { FirebaseUser(it) })}
36+
val listener = com.google.firebase.auth.FirebaseAuth.IdTokenListener { auth -> if (!isClosedForSend) offer(auth.currentUser?.let { FirebaseUser(it) })}
3737
android.addIdTokenListener(listener)
3838
awaitClose { android.removeIdTokenListener(listener) }
3939
}

firebase-auth/src/iosMain/kotlin/dev/gitlive/firebase/auth/auth.kt

+2-2
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,12 @@ actual class FirebaseAuth internal constructor(val ios: FIRAuth) {
2727
get() = ios.currentUser?.let { FirebaseUser(it) }
2828

2929
actual val authStateChanged get() = callbackFlow {
30-
val handle = ios.addAuthStateDidChangeListener { _, user -> offer(user?.let { FirebaseUser(it) }) }
30+
val handle = ios.addAuthStateDidChangeListener { _, user -> if (!isClosedForSend) offer(user?.let { FirebaseUser(it) }) }
3131
awaitClose { ios.removeAuthStateDidChangeListener(handle) }
3232
}
3333

3434
actual val idTokenChanged get() = callbackFlow {
35-
val handle = ios.addIDTokenDidChangeListener { _, user -> offer(user?.let { FirebaseUser(it) }) }
35+
val handle = ios.addIDTokenDidChangeListener { _, user -> if (!isClosedForSend) offer(user?.let { FirebaseUser(it) }) }
3636
awaitClose { ios.removeIDTokenDidChangeListener(handle) }
3737
}
3838

firebase-auth/src/jsMain/kotlin/dev/gitlive/firebase/auth/auth.kt

+4-2
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,16 @@ actual class FirebaseAuth internal constructor(val js: firebase.auth.Auth) {
2222

2323
actual val authStateChanged get() = callbackFlow {
2424
val unsubscribe = js.onAuthStateChanged {
25-
offer(it?.let { FirebaseUser(it) })
25+
if (!isClosedForSend)
26+
offer(it?.let { FirebaseUser(it) })
2627
}
2728
awaitClose { unsubscribe() }
2829
}
2930

3031
actual val idTokenChanged get() = callbackFlow {
3132
val unsubscribe = js.onIdTokenChanged {
32-
offer(it?.let { FirebaseUser(it) })
33+
if (!isClosedForSend)
34+
offer(it?.let { FirebaseUser(it) })
3335
}
3436
awaitClose { unsubscribe() }
3537
}

firebase-database/src/androidMain/kotlin/dev/gitlive/firebase/database/database.kt

+6-5
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,8 @@ actual open class Query internal constructor(
9191
get() = callbackFlow {
9292
val listener = object : ValueEventListener {
9393
override fun onDataChange(snapshot: com.google.firebase.database.DataSnapshot) {
94-
offer(DataSnapshot(snapshot))
94+
if (!isClosedForSend)
95+
offer(DataSnapshot(snapshot))
9596
}
9697

9798
override fun onCancelled(error: com.google.firebase.database.DatabaseError) {
@@ -107,22 +108,22 @@ actual open class Query internal constructor(
107108

108109
val moved by lazy { types.contains(Type.MOVED) }
109110
override fun onChildMoved(snapshot: com.google.firebase.database.DataSnapshot, previousChildName: String?) {
110-
if(moved) offer(ChildEvent(DataSnapshot(snapshot), Type.MOVED, previousChildName))
111+
if(moved && !isClosedForSend) offer(ChildEvent(DataSnapshot(snapshot), Type.MOVED, previousChildName))
111112
}
112113

113114
val changed by lazy { types.contains(Type.CHANGED) }
114115
override fun onChildChanged(snapshot: com.google.firebase.database.DataSnapshot, previousChildName: String?) {
115-
if(changed) offer(ChildEvent(DataSnapshot(snapshot), Type.CHANGED, previousChildName))
116+
if(changed && !isClosedForSend) offer(ChildEvent(DataSnapshot(snapshot), Type.CHANGED, previousChildName))
116117
}
117118

118119
val added by lazy { types.contains(Type.ADDED) }
119120
override fun onChildAdded(snapshot: com.google.firebase.database.DataSnapshot, previousChildName: String?) {
120-
if(added) offer(ChildEvent(DataSnapshot(snapshot), Type.ADDED, previousChildName))
121+
if(added && !isClosedForSend) offer(ChildEvent(DataSnapshot(snapshot), Type.ADDED, previousChildName))
121122
}
122123

123124
val removed by lazy { types.contains(Type.REMOVED) }
124125
override fun onChildRemoved(snapshot: com.google.firebase.database.DataSnapshot) {
125-
if(removed) offer(ChildEvent(DataSnapshot(snapshot), Type.REMOVED, null))
126+
if(removed && !isClosedForSend) offer(ChildEvent(DataSnapshot(snapshot), Type.REMOVED, null))
126127
}
127128

128129
override fun onCancelled(error: com.google.firebase.database.DatabaseError) {

firebase-database/src/iosMain/kotlin/dev/gitlive/firebase/database/database.kt

+2-2
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ actual open class Query internal constructor(
7878
actual val valueEvents get() = callbackFlow {
7979
val handle = ios.observeEventType(
8080
FIRDataEventTypeValue,
81-
withBlock = { offer(DataSnapshot(it!!)) }
81+
withBlock = { if (!isClosedForSend) offer(DataSnapshot(it!!)) }
8282
) { close(DatabaseException(it.toString())) }
8383
awaitClose { ios.removeObserverWithHandle(handle) }
8484
}
@@ -87,7 +87,7 @@ actual open class Query internal constructor(
8787
val handles = types.map { type ->
8888
ios.observeEventType(
8989
type.toEventType(),
90-
andPreviousSiblingKeyWithBlock = { it, key -> offer(ChildEvent(DataSnapshot(it!!), type, key)) }
90+
andPreviousSiblingKeyWithBlock = { it, key -> if (!isClosedForSend) offer(ChildEvent(DataSnapshot(it!!), type, key)) }
9191
) { close(DatabaseException(it.toString())) }
9292
}
9393
awaitClose {

firebase-database/src/jsMain/kotlin/dev/gitlive/firebase/database/database.kt

+2-2
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ actual open class Query internal constructor(open val js: firebase.database.Quer
4444
val listener = rethrow {
4545
js.on(
4646
"value",
47-
{ it, _ -> offer(DataSnapshot(it)) },
47+
{ it, _ -> if (!isClosedForSend) offer(DataSnapshot(it)) },
4848
{ close(DatabaseException(it)).run { Unit } }
4949
)
5050
}
@@ -58,7 +58,7 @@ actual open class Query internal constructor(open val js: firebase.database.Quer
5858
eventType to js.on(
5959
eventType,
6060
{ snapshot, previousChildName ->
61-
offer(
61+
if (!isClosedForSend) offer(
6262
ChildEvent(
6363
DataSnapshot(snapshot),
6464
type,

firebase-firestore/src/jsMain/kotlin/dev/gitlive/firebase/firestore/firestore.kt

+2-2
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ actual class DocumentReference(val js: firebase.firestore.DocumentReference) {
238238

239239
actual val snapshots get() = callbackFlow {
240240
val unsubscribe = js.onSnapshot(
241-
{ offer(DocumentSnapshot(it)) },
241+
{ if (!isClosedForSend) offer(DocumentSnapshot(it)) },
242242
{ close(errorToException(it)) }
243243
)
244244
awaitClose { unsubscribe() }
@@ -289,7 +289,7 @@ actual open class Query(open val js: firebase.firestore.Query) {
289289
actual val snapshots get() = callbackFlow {
290290
val unsubscribe = rethrow {
291291
js.onSnapshot(
292-
{ offer(QuerySnapshot(it)) },
292+
{ if (!isClosedForSend) offer(QuerySnapshot(it)) },
293293
{ close(errorToException(it)) }
294294
)
295295
}

0 commit comments

Comments
 (0)