-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix js + enable js tests + code clean #45
Conversation
…se of JS limitation
@@ -71,17 +71,19 @@ class EncodersTest { | |||
@Test | |||
fun testEncodeDecodedSealedClass() { | |||
val test = SealedClass.Test("Foo") | |||
val encoded = encode(test, false) | |||
val decoded = decode(encoded) as? SealedClass.Test | |||
val serializer = SealedClass.Test.serializer() // has to be used because of JS issue |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
legacy JS is not finding a serializer in serializer<T>()
call (see issue) and it seems unlikely to be fixed. the upstream repo is using legacy JS and not IR JS, so I don't consider migrating at the moment
firebase-common/src/androidMain/kotlin/dev/gitlive/firebase/_encoders.kt
Show resolved
Hide resolved
@@ -459,6 +461,8 @@ external object firebase { | |||
open class GeoPoint(latitude: Double, longitude: Double) { | |||
val latitude: Double | |||
val longitude: Double | |||
|
|||
fun isEqual(other: GeoPoint): Boolean |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unfortunately interops doesn't map it to equals
@@ -22,17 +22,3 @@ internal fun <T> encode(strategy: SerializationStrategy<T>, value: T, shouldEnco | |||
shouldEncodeElementDefault, | |||
FieldValue.serverTimestamp() | |||
) | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
android and ios indeed encode data as map, however JS encodes it to json. updated platform specific code (as mentioned above)
val serializedItem = encodeAsMap(strategy, data, encodeDefaults) | ||
val serializedFieldAndValues = encodeAsMap(fieldsAndValues = fieldsAndValues) | ||
|
||
val result = serializedItem + (serializedFieldAndValues ?: emptyMap()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
an implementation bug. it's not Map, but Json in JS
@@ -257,7 +255,15 @@ actual class DocumentReference(val js: firebase.firestore.DocumentReference) { | |||
actual suspend fun update(vararg fieldsAndValues: Pair<String, Any?>) = rethrow { | |||
fieldsAndValues.takeUnless { fieldsAndValues.isEmpty() } | |||
?.map { (field, value) -> field to encode(value, true) } | |||
?.let { encoded -> js.update(encoded.toMap()) } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
incorrect method was used for fields update. fixed by using the same approach update(vararg fieldsAndValues: Pair<FieldPath, Any?>)
does
} | ||
|
||
@Serializable | ||
data class TestDataWithDocumentReference( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
moved to common tests
|
||
/** A class representing a Firebase GeoPoint. */ | ||
@Serializable(with = GeoPointSerializer::class) | ||
actual class GeoPoint internal actual constructor(internal actual val platformValue: PlatformGeoPoint) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wrapper class allows using @Serializable
and overriding equals for JS
@Serializable(with = TimestampSerializer::class) | ||
actual class Timestamp private constructor( | ||
internal actual val platformValue: PlatformTimestamp, | ||
actual val isServerTimestamp: Boolean |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the approach with a boolean isServerTimestamp
is not super clean, but I don't like other options either.. for example if a sealed class is used - we'd won't have a simple constructor..
@@ -107,10 +107,12 @@ actual class WriteBatch(val android: com.google.firebase.firestore.WriteBatch) { | |||
merge: Boolean, | |||
vararg fieldsAndValues: Pair<String, Any?> | |||
): WriteBatch { | |||
val serializedItem = encodeAsMap(strategy, data, encodeDefaults) | |||
val serializedFieldAndValues = encodeAsMap(fieldsAndValues = fieldsAndValues) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
encodeAsMap
can't be used as JS doesn't encode to a map so I scraped it and put implementation here directly
actual fun arrayRemove(vararg elements: Any): Any = FieldValue.arrayRemove(*elements) | ||
actual fun delete(): Any = delete | ||
/** A class representing a platform specific Firebase FieldValue. */ | ||
internal typealias PlatformFieldValue = com.google.firebase.firestore.FieldValue |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wish I could use a common expect PlatformFieldValue
however in Android/JS it's an abstract class and in iOS it's not. this causes modality is different
error. any idea how I could trick the compiler?
if (encoder is FirebaseEncoder) { | ||
encoder.value = value.platformValue | ||
} else { | ||
throw IllegalArgumentException("This serializer must be used with FirebaseEncoder") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it'd be nice to serialize it, but FieldValue.arrayUnion
and arrayDelete
take Any
and I have no idea how to serialize it in a clean way.. use Json maybe?..
assertNotEquals(FieldValue.delete, FieldValue.serverTimestamp()) | ||
|
||
// Note: arrayUnion and arrayRemove can't be checked due to vararg to array conversion | ||
// assertEquals(FieldValue.arrayUnion(1, 2, 3), FieldValue.arrayUnion(1, 2, 3)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
any suggestions to have equality working as expected?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
assertContentEquals
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the thing is that an array is stored in a private field and the firebase FieldValue class does not implement override equals as it should
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you make Set out of Array?
override fun equals(other: Any?): Boolean = | ||
this === other || other is GeoPoint && platformValue.isEqual(other.platformValue) | ||
override fun hashCode(): Int = platformValue.hashCode() | ||
override fun toString(): String = "GeoPoint[lat=$latitude,long=$longitude]" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
JS lib does not provide a nice toString
hence implementing a custom representation
firebase-firestore/src/commonMain/kotlin/dev/gitlive/firebase/firestore/GeoPointSerializer.kt
Outdated
Show resolved
Hide resolved
firebase-firestore/src/commonMain/kotlin/dev/gitlive/firebase/firestore/Timestamp.kt
Outdated
Show resolved
Hide resolved
|
||
/** A base class that could be used to combine [Timestamp] and [Timestamp.ServerTimestamp] in the same field. */ | ||
@Serializable(with = BaseTimestampSerializer::class) | ||
actual sealed class BaseTimestamp |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting find. I have to use expect / actual sealed class because kotlin common and JS specific code are treated as different modules. this could be caused by the fact JS doesn't support packages.
unfortunately android studio check warns you to about exhaustive when
s in this case
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thats weird...
firebase-firestore/src/commonMain/kotlin/dev/gitlive/firebase/firestore/TimestampSerializer.kt
Show resolved
Hide resolved
firebase-firestore/src/commonMain/kotlin/dev/gitlive/firebase/firestore/TimestampSerializer.kt
Outdated
Show resolved
Hide resolved
firebase-firestore/src/commonTest/kotlin/dev/gitlive/firebase/firestore/firestore.kt
Outdated
Show resolved
Hide resolved
firebase-firestore/src/commonTest/kotlin/dev/gitlive/firebase/firestore/firestore.kt
Outdated
Show resolved
Hide resolved
firebase-firestore/src/commonTest/kotlin/dev/gitlive/firebase/firestore/firestore.kt
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Put some comments, overall looks good to me
the goal of this PR is to fix JS code and enable JS tests. what was done
FirebaseTimestamp
andFirebaseReference
deprecated in the previous PR. deletion shall not be done the way those classes provided and a cleaner alternative is available for the Timestampchallenges:
FieldValue.arrayUnion
andFieldValue.arrayRemove
are not working