Skip to content

Commit 0b015e1

Browse files
committed
Ignore NoClassDefFoundError when initializing builtins map for serializer() function.
Normally they should not occur, but in rare setups when runtime stdlib may be lower than 2.0, we may want to ignore errors about experimental classes. Fixes #2803
1 parent 8c84a5b commit 0b015e1

File tree

5 files changed

+164
-32
lines changed

5 files changed

+164
-32
lines changed

core/commonMain/src/kotlinx/serialization/internal/Primitives.kt

Lines changed: 3 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -15,38 +15,9 @@ import kotlin.reflect.*
1515
import kotlin.time.Duration
1616
import kotlin.uuid.*
1717

18-
@OptIn(ExperimentalUnsignedTypes::class, ExperimentalUuidApi::class)
19-
private val BUILTIN_SERIALIZERS = mapOf(
20-
String::class to String.serializer(),
21-
Char::class to Char.serializer(),
22-
CharArray::class to CharArraySerializer(),
23-
Double::class to Double.serializer(),
24-
DoubleArray::class to DoubleArraySerializer(),
25-
Float::class to Float.serializer(),
26-
FloatArray::class to FloatArraySerializer(),
27-
Long::class to Long.serializer(),
28-
LongArray::class to LongArraySerializer(),
29-
ULong::class to ULong.serializer(),
30-
ULongArray::class to ULongArraySerializer(),
31-
Int::class to Int.serializer(),
32-
IntArray::class to IntArraySerializer(),
33-
UInt::class to UInt.serializer(),
34-
UIntArray::class to UIntArraySerializer(),
35-
Short::class to Short.serializer(),
36-
ShortArray::class to ShortArraySerializer(),
37-
UShort::class to UShort.serializer(),
38-
UShortArray::class to UShortArraySerializer(),
39-
Byte::class to Byte.serializer(),
40-
ByteArray::class to ByteArraySerializer(),
41-
UByte::class to UByte.serializer(),
42-
UByteArray::class to UByteArraySerializer(),
43-
Boolean::class to Boolean.serializer(),
44-
BooleanArray::class to BooleanArraySerializer(),
45-
Unit::class to Unit.serializer(),
46-
Nothing::class to NothingSerializer(),
47-
Duration::class to Duration.serializer(),
48-
Uuid::class to Uuid.serializer()
49-
)
18+
private val BUILTIN_SERIALIZERS = initBuiltins()
19+
20+
internal expect fun initBuiltins(): Map<KClass<*>, KSerializer<*>>
5021

5122
internal class PrimitiveSerialDescriptor(
5223
override val serialName: String,

core/jsMain/src/kotlinx/serialization/internal/Platform.kt

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@
55
package kotlinx.serialization.internal
66

77
import kotlinx.serialization.*
8+
import kotlinx.serialization.builtins.*
89
import kotlin.reflect.*
10+
import kotlin.time.*
11+
import kotlin.uuid.*
912

1013
internal actual fun <T> Array<T>.getChecked(index: Int): T {
1114
if (index !in indices) throw IndexOutOfBoundsException("Index $index out of bounds $indices")
@@ -77,3 +80,36 @@ private val KClass<*>.isInterface: Boolean
7780
if (this === Nothing::class) return false
7881
return js.asDynamic().`$metadata$`?.kind == "interface"
7982
}
83+
84+
@OptIn(ExperimentalUnsignedTypes::class, ExperimentalUuidApi::class, ExperimentalSerializationApi::class)
85+
internal actual fun initBuiltins(): Map<KClass<*>, KSerializer<*>> = mapOf(
86+
String::class to String.serializer(),
87+
Char::class to Char.serializer(),
88+
CharArray::class to CharArraySerializer(),
89+
Double::class to Double.serializer(),
90+
DoubleArray::class to DoubleArraySerializer(),
91+
Float::class to Float.serializer(),
92+
FloatArray::class to FloatArraySerializer(),
93+
Long::class to Long.serializer(),
94+
LongArray::class to LongArraySerializer(),
95+
ULong::class to ULong.serializer(),
96+
ULongArray::class to ULongArraySerializer(),
97+
Int::class to Int.serializer(),
98+
IntArray::class to IntArraySerializer(),
99+
UInt::class to UInt.serializer(),
100+
UIntArray::class to UIntArraySerializer(),
101+
Short::class to Short.serializer(),
102+
ShortArray::class to ShortArraySerializer(),
103+
UShort::class to UShort.serializer(),
104+
UShortArray::class to UShortArraySerializer(),
105+
Byte::class to Byte.serializer(),
106+
ByteArray::class to ByteArraySerializer(),
107+
UByte::class to UByte.serializer(),
108+
UByteArray::class to UByteArraySerializer(),
109+
Boolean::class to Boolean.serializer(),
110+
BooleanArray::class to BooleanArraySerializer(),
111+
Unit::class to Unit.serializer(),
112+
Nothing::class to NothingSerializer(),
113+
Duration::class to Duration.serializer(),
114+
Uuid::class to Uuid.serializer()
115+
)

core/jvmMain/src/kotlinx/serialization/internal/Platform.kt

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,11 @@
55
package kotlinx.serialization.internal
66

77
import kotlinx.serialization.*
8+
import kotlinx.serialization.builtins.*
89
import java.lang.reflect.*
910
import kotlin.reflect.*
11+
import kotlin.time.*
12+
import kotlin.uuid.*
1013

1114
@Suppress("NOTHING_TO_INLINE")
1215
internal actual inline fun <T> Array<T>.getChecked(index: Int): T {
@@ -158,3 +161,53 @@ private fun <T : Any> Class<T>.findObjectSerializer(): KSerializer<T>? {
158161
}
159162

160163
internal actual fun isReferenceArray(rootClass: KClass<Any>): Boolean = rootClass.java.isArray
164+
165+
@OptIn(ExperimentalSerializationApi::class)
166+
internal actual fun initBuiltins(): Map<KClass<*>, KSerializer<*>> = buildMap {
167+
// Standard classes are always present
168+
put(String::class, String.serializer())
169+
put(Char::class, Char.serializer())
170+
put(CharArray::class, CharArraySerializer())
171+
put(Double::class, Double.serializer())
172+
put(DoubleArray::class, DoubleArraySerializer())
173+
put(Float::class, Float.serializer())
174+
put(FloatArray::class, FloatArraySerializer())
175+
put(Long::class, Long.serializer())
176+
put(LongArray::class, LongArraySerializer())
177+
put(ULong::class, ULong.serializer())
178+
put(Int::class, Int.serializer())
179+
put(IntArray::class, IntArraySerializer())
180+
put(UInt::class, UInt.serializer())
181+
put(Short::class, Short.serializer())
182+
put(ShortArray::class, ShortArraySerializer())
183+
put(UShort::class, UShort.serializer())
184+
put(Byte::class, Byte.serializer())
185+
put(ByteArray::class, ByteArraySerializer())
186+
put(UByte::class, UByte.serializer())
187+
put(Boolean::class, Boolean.serializer())
188+
put(BooleanArray::class, BooleanArraySerializer())
189+
put(Unit::class, Unit.serializer())
190+
put(Nothing::class, NothingSerializer())
191+
192+
// Duration is a stable class, but may be missing in very old stdlibs
193+
loadSafe { put(Duration::class, Duration.serializer()) }
194+
195+
// Experimental types that may be missing
196+
@OptIn(ExperimentalUnsignedTypes::class) run {
197+
loadSafe { put(ULongArray::class, ULongArraySerializer()) }
198+
loadSafe { put(UIntArray::class, UIntArraySerializer()) }
199+
loadSafe { put(UShortArray::class, UShortArraySerializer()) }
200+
loadSafe { put(UByteArray::class, UByteArraySerializer()) }
201+
}
202+
@OptIn(ExperimentalUuidApi::class)
203+
loadSafe { put(Uuid::class, Uuid.serializer()) }
204+
}
205+
206+
// Reference classes in [block] ignoring any exceptions related to class loading
207+
private inline fun loadSafe(block: () -> Unit) {
208+
try {
209+
block()
210+
} catch (_: NoClassDefFoundError) {
211+
} catch (_: ClassNotFoundException) {
212+
}
213+
}

core/nativeMain/src/kotlinx/serialization/internal/Platform.kt

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@
55
package kotlinx.serialization.internal
66

77
import kotlinx.serialization.*
8+
import kotlinx.serialization.builtins.*
89
import kotlin.reflect.*
10+
import kotlin.time.*
11+
import kotlin.uuid.*
912

1013
@Suppress("NOTHING_TO_INLINE")
1114
internal actual inline fun <T> Array<T>.getChecked(index: Int): T {
@@ -71,3 +74,36 @@ internal actual fun <T : Any, E : T?> ArrayList<E>.toNativeArrayImpl(eClass: KCl
7174
private fun <T> arrayOfAnyNulls(size: Int): Array<T> = arrayOfNulls<Any>(size) as Array<T>
7275

7376
internal actual fun isReferenceArray(rootClass: KClass<Any>): Boolean = rootClass == Array::class
77+
78+
@OptIn(ExperimentalUnsignedTypes::class, ExperimentalUuidApi::class, ExperimentalSerializationApi::class)
79+
internal actual fun initBuiltins(): Map<KClass<*>, KSerializer<*>> = mapOf(
80+
String::class to String.serializer(),
81+
Char::class to Char.serializer(),
82+
CharArray::class to CharArraySerializer(),
83+
Double::class to Double.serializer(),
84+
DoubleArray::class to DoubleArraySerializer(),
85+
Float::class to Float.serializer(),
86+
FloatArray::class to FloatArraySerializer(),
87+
Long::class to Long.serializer(),
88+
LongArray::class to LongArraySerializer(),
89+
ULong::class to ULong.serializer(),
90+
ULongArray::class to ULongArraySerializer(),
91+
Int::class to Int.serializer(),
92+
IntArray::class to IntArraySerializer(),
93+
UInt::class to UInt.serializer(),
94+
UIntArray::class to UIntArraySerializer(),
95+
Short::class to Short.serializer(),
96+
ShortArray::class to ShortArraySerializer(),
97+
UShort::class to UShort.serializer(),
98+
UShortArray::class to UShortArraySerializer(),
99+
Byte::class to Byte.serializer(),
100+
ByteArray::class to ByteArraySerializer(),
101+
UByte::class to UByte.serializer(),
102+
UByteArray::class to UByteArraySerializer(),
103+
Boolean::class to Boolean.serializer(),
104+
BooleanArray::class to BooleanArraySerializer(),
105+
Unit::class to Unit.serializer(),
106+
Nothing::class to NothingSerializer(),
107+
Duration::class to Duration.serializer(),
108+
Uuid::class to Uuid.serializer()
109+
)

core/wasmMain/src/kotlinx/serialization/internal/Platform.kt

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@
55
package kotlinx.serialization.internal
66

77
import kotlinx.serialization.*
8+
import kotlinx.serialization.builtins.*
89
import kotlin.reflect.*
10+
import kotlin.time.*
11+
import kotlin.uuid.*
912

1013
@Suppress("NOTHING_TO_INLINE")
1114
internal actual inline fun <T> Array<T>.getChecked(index: Int): T {
@@ -61,3 +64,36 @@ internal actual fun <T> createParametrizedCache(factory: (KClass<Any>, List<KTyp
6164
internal actual fun <T : Any, E : T?> ArrayList<E>.toNativeArrayImpl(eClass: KClass<T>): Array<E> = toTypedArray()
6265

6366
internal actual fun isReferenceArray(rootClass: KClass<Any>): Boolean = rootClass == Array::class
67+
68+
@OptIn(ExperimentalUnsignedTypes::class, ExperimentalUuidApi::class, ExperimentalSerializationApi::class)
69+
internal actual fun initBuiltins(): Map<KClass<*>, KSerializer<*>> = mapOf(
70+
String::class to String.serializer(),
71+
Char::class to Char.serializer(),
72+
CharArray::class to CharArraySerializer(),
73+
Double::class to Double.serializer(),
74+
DoubleArray::class to DoubleArraySerializer(),
75+
Float::class to Float.serializer(),
76+
FloatArray::class to FloatArraySerializer(),
77+
Long::class to Long.serializer(),
78+
LongArray::class to LongArraySerializer(),
79+
ULong::class to ULong.serializer(),
80+
ULongArray::class to ULongArraySerializer(),
81+
Int::class to Int.serializer(),
82+
IntArray::class to IntArraySerializer(),
83+
UInt::class to UInt.serializer(),
84+
UIntArray::class to UIntArraySerializer(),
85+
Short::class to Short.serializer(),
86+
ShortArray::class to ShortArraySerializer(),
87+
UShort::class to UShort.serializer(),
88+
UShortArray::class to UShortArraySerializer(),
89+
Byte::class to Byte.serializer(),
90+
ByteArray::class to ByteArraySerializer(),
91+
UByte::class to UByte.serializer(),
92+
UByteArray::class to UByteArraySerializer(),
93+
Boolean::class to Boolean.serializer(),
94+
BooleanArray::class to BooleanArraySerializer(),
95+
Unit::class to Unit.serializer(),
96+
Nothing::class to NothingSerializer(),
97+
Duration::class to Duration.serializer(),
98+
Uuid::class to Uuid.serializer()
99+
)

0 commit comments

Comments
 (0)