| // TARGET_BACKEND: WASM |
| // WITH_STDLIB |
| |
| @file:OptIn(ExperimentalAssociatedObjects::class) |
| |
| package wasmjsstrings |
| |
| import kotlin.reflect.AssociatedObjectKey |
| import kotlin.reflect.ExperimentalAssociatedObjects |
| import kotlin.reflect.KClass |
| import kotlin.reflect.findAssociatedObject |
| |
| @JsFun("""(s) => typeof s === "string" && !(s instanceof String)""") |
| external fun jsIsPrimitiveString(s: String): Boolean |
| |
| @AssociatedObjectKey |
| @Retention(AnnotationRetention.BINARY) |
| annotation class Associated(val kClass: KClass<*>) |
| |
| object AssociatedMarker |
| |
| @Associated(AssociatedMarker::class) |
| class Holder { |
| class Nested |
| } |
| |
| fun box(): String { |
| val holderName = Holder::class.qualifiedName ?: return "Fail missing Holder qualifiedName" |
| if (holderName != "wasmjsstrings.Holder") return "Fail Holder qualifiedName: <$holderName>" |
| if (!jsIsPrimitiveString(holderName)) return "Fail Holder name is not primitive" |
| |
| val nestedName = Holder.Nested::class.qualifiedName ?: return "Fail missing Nested qualifiedName" |
| if (nestedName != "wasmjsstrings.Holder.Nested") return "Fail Nested qualifiedName: <$nestedName>" |
| if (!jsIsPrimitiveString(nestedName)) return "Fail Nested name is not primitive" |
| |
| if (Holder::class.findAssociatedObject<Associated>() !== AssociatedMarker) return "Fail associated object" |
| |
| val value: Any = 42 |
| val castMessage = try { |
| value as Holder |
| return "Fail expected ClassCastException" |
| } catch (e: ClassCastException) { |
| e.message ?: return "Fail missing cast message" |
| } |
| |
| if (!castMessage.contains("kotlin.Int")) return "Fail cast source: <$castMessage>" |
| if (!castMessage.contains("wasmjsstrings.Holder")) return "Fail cast target: <$castMessage>" |
| if (!jsIsPrimitiveString(castMessage)) return "Fail cast message is not primitive" |
| |
| return "OK" |
| } |