summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShreck Ye <ShreckYe@gmail.com>2023-07-12 20:58:30 +0800
committerGitHub <noreply@github.com>2023-07-12 14:58:30 +0200
commitb8de86f0e351f1099d2afb03ff92e2ef6256cbc7 (patch)
tree6527b6c563ef694f145d08f083c3d85805ac2132
parent782b9f3be9970e0fd36215a86bf7fdba9f2bfe83 (diff)
downloadkotlinx.serialization-b8de86f0e351f1099d2afb03ff92e2ef6256cbc7.tar.gz
Support Serializer for Nothing on the JS target (#2330)
Workaround for KT-51333: serialization of `Nothing` on the JS target and related tests See also #932 Co-authored-by: Leonid Startsev <sandwwraith@users.noreply.github.com>
-rw-r--r--core/commonTest/src/kotlinx/serialization/SerializersModuleTest.kt24
-rw-r--r--core/jsMain/src/kotlinx/serialization/internal/Platform.kt7
-rw-r--r--formats/protobuf/commonTest/src/kotlinx/serialization/protobuf/ProtobufNothingTest.kt30
3 files changed, 59 insertions, 2 deletions
diff --git a/core/commonTest/src/kotlinx/serialization/SerializersModuleTest.kt b/core/commonTest/src/kotlinx/serialization/SerializersModuleTest.kt
index 079792e6..db996a75 100644
--- a/core/commonTest/src/kotlinx/serialization/SerializersModuleTest.kt
+++ b/core/commonTest/src/kotlinx/serialization/SerializersModuleTest.kt
@@ -37,6 +37,9 @@ class SerializersModuleTest {
@Serializable
class Parametrized<T : Any>(val a: T)
+ @Serializable
+ class ParametrizedOfNullable<T>(val a: T)
+
class ContextualType(val i: Int)
@Serializer(forClass = ContextualType::class)
@@ -81,6 +84,27 @@ class SerializersModuleTest {
assertEquals(PrimitiveKind.INT, mapSerializer.descriptor.getElementDescriptor(1).kind)
}
+ @Suppress("UNCHECKED_CAST")
+ @Test
+ fun testNothingAndParameterizedOfNothing() {
+ assertEquals(NothingSerializer, Nothing::class.serializer())
+ //assertEquals(NothingSerializer, serializer<Nothing>()) // prohibited by compiler
+ assertEquals(NothingSerializer, serializer(Nothing::class, emptyList(), false) as KSerializer<Nothing>)
+ //assertEquals(NullableSerializer(NothingSerializer), serializer<Nothing?>()) // prohibited by compiler
+ assertEquals(
+ NullableSerializer(NothingSerializer),
+ serializer(Nothing::class, emptyList(), true) as KSerializer<Nothing?>
+ )
+
+ val parameterizedNothingSerializer = serializer<Parametrized<Nothing>>()
+ val nothingDescriptor = parameterizedNothingSerializer.descriptor.getElementDescriptor(0)
+ assertEquals(NothingSerialDescriptor, nothingDescriptor)
+
+ val parameterizedNullableNothingSerializer = serializer<ParametrizedOfNullable<Nothing?>>()
+ val nullableNothingDescriptor = parameterizedNullableNothingSerializer.descriptor.getElementDescriptor(0)
+ assertEquals(SerialDescriptorForNullable(NothingSerialDescriptor), nullableNothingDescriptor)
+ }
+
@Test
fun testUnsupportedArray() {
assertFails {
diff --git a/core/jsMain/src/kotlinx/serialization/internal/Platform.kt b/core/jsMain/src/kotlinx/serialization/internal/Platform.kt
index d2659fe4..6bd63391 100644
--- a/core/jsMain/src/kotlinx/serialization/internal/Platform.kt
+++ b/core/jsMain/src/kotlinx/serialization/internal/Platform.kt
@@ -16,9 +16,12 @@ internal actual fun BooleanArray.getChecked(index: Int): Boolean {
if (index !in indices) throw IndexOutOfBoundsException("Index $index out of bounds $indices")
return get(index)
}
-@Suppress("UNCHECKED_CAST")
+
internal actual fun <T : Any> KClass<T>.compiledSerializerImpl(): KSerializer<T>? =
- this.constructSerializerForGivenTypeArgs() ?: this.js.asDynamic().Companion?.serializer() as? KSerializer<T>
+ this.constructSerializerForGivenTypeArgs() ?: (
+ if (this === Nothing::class) NothingSerializer // Workaround for KT-51333
+ else this.js.asDynamic().Companion?.serializer()
+ ) as? KSerializer<T>
internal actual fun <T> createCache(factory: (KClass<*>) -> KSerializer<T>?): SerializerCache<T> {
return object: SerializerCache<T> {
diff --git a/formats/protobuf/commonTest/src/kotlinx/serialization/protobuf/ProtobufNothingTest.kt b/formats/protobuf/commonTest/src/kotlinx/serialization/protobuf/ProtobufNothingTest.kt
new file mode 100644
index 00000000..9c97b5ec
--- /dev/null
+++ b/formats/protobuf/commonTest/src/kotlinx/serialization/protobuf/ProtobufNothingTest.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2017-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+
+package kotlinx.serialization.protobuf
+
+import kotlinx.serialization.*
+import kotlinx.serialization.test.*
+import kotlin.test.*
+
+class ProtobufNothingTest {
+ @Serializable
+ /*private*/ data class NullableNothingBox(val value: Nothing?) // `private` doesn't work on the JS legacy target
+
+ @Serializable
+ private data class ParameterizedBox<T : Any>(val value: T?)
+
+ private inline fun <reified T> testConversion(data: T, expectedHexString: String) {
+ val string = ProtoBuf.encodeToHexString(data).uppercase()
+ assertEquals(expectedHexString, string)
+ assertEquals(data, ProtoBuf.decodeFromHexString(string))
+ }
+
+ @Test
+ fun testNothing() {
+ testConversion(NullableNothingBox(null), "")
+ if (isJsLegacy()) return
+ testConversion(ParameterizedBox(null), "")
+ }
+} \ No newline at end of file