[Wasm] Fix access to WebIDL dictionary members

Evaluate external interface companion objects as an empty JS object
instead of null due to null checks on interop boundary.

^KT-59082 Fixed
This commit is contained in:
Svyatoslav Kuzmich
2023-07-25 10:47:53 +02:00
committed by Space Team
parent 92de137cd6
commit 384c700a85
4 changed files with 48 additions and 0 deletions
@@ -156,6 +156,27 @@ class ComplexExternalDeclarationsToTopLevelFunctionsLowering(val context: WasmBa
private fun StringBuilder.appendExternalClassReference(klass: IrClass) {
val parent = klass.parent
if (parent is IrClass) {
// This is hack to support Kotlin/JS like implementation of IDL string enums bindings
// with error suppression:
//
// @JsName("null")
// @Suppress("NESTED_CLASS_IN_EXTERNAL_INTERFACE")
// public external interface CanvasFillRule {
// companion object
// }
// public inline val CanvasFillRule.Companion.NONZERO: CanvasFillRule get() = "nonzero".asDynamic().unsafeCast<CanvasFillRule>()
//
// Kotlin/JS translates access to CanvasFillRule.Companion as `null` due to @JsName("null"),
// but Kotlin/Wasm fails to do this due to stricter null checks on interop boundary.
//
// Instead, as a temporary solution, we evaluate such companion object to an empty JS object.
// TODO: Optimize (KT-60661)
if (parent.isInterface) {
append("({})")
return
}
appendExternalClassReference(parent)
if (klass.isCompanion) {
// Reference to external companion object is reference to its parent class
+15
View File
@@ -0,0 +1,15 @@
// TARGET_BACKEND: WASM
@JsName("null")
@Suppress("NESTED_CLASS_IN_EXTERNAL_INTERFACE")
public external interface CanvasFillRule : JsAny {
companion object
}
public inline val CanvasFillRule.Companion.EVENODD: CanvasFillRule get() =
"evenodd".toJsString().unsafeCast<CanvasFillRule>()
fun box(): String {
if (CanvasFillRule.EVENODD.toString() != "evenodd") return "Fail 1"
return "OK"
}
@@ -115,6 +115,12 @@ public class FirWasmCodegenWasmJsInteropTestGenerated extends AbstractFirWasmCod
runTest("compiler/testData/codegen/boxWasmJsInterop/kotlinToJsAdapters.kt");
}
@Test
@TestMetadata("kt59082.kt")
public void testKt59082() throws Exception {
runTest("compiler/testData/codegen/boxWasmJsInterop/kt59082.kt");
}
@Test
@TestMetadata("lambdaAdapterNameClash.kt")
public void testLambdaAdapterNameClash() throws Exception {
@@ -115,6 +115,12 @@ public class K1WasmCodegenWasmJsInteropTestGenerated extends AbstractK1WasmCodeg
runTest("compiler/testData/codegen/boxWasmJsInterop/kotlinToJsAdapters.kt");
}
@Test
@TestMetadata("kt59082.kt")
public void testKt59082() throws Exception {
runTest("compiler/testData/codegen/boxWasmJsInterop/kt59082.kt");
}
@Test
@TestMetadata("lambdaAdapterNameClash.kt")
public void testLambdaAdapterNameClash() throws Exception {