[WasmJs] Add support for external class reflection
Fix #KT-64890
This commit is contained in:
@@ -305,7 +305,6 @@ class JsIntrinsics(private val irBuiltIns: IrBuiltIns, val context: JsIrBackendC
|
|||||||
override val getKClassFromExpression = getInternalWithoutPackage("getKClassFromExpression")
|
override val getKClassFromExpression = getInternalWithoutPackage("getKClassFromExpression")
|
||||||
override val primitiveClassesObject = context.getIrClass(FqName("kotlin.reflect.js.internal.PrimitiveClasses"))
|
override val primitiveClassesObject = context.getIrClass(FqName("kotlin.reflect.js.internal.PrimitiveClasses"))
|
||||||
override val kTypeClass: IrClassSymbol = context.getIrClass(FqName("kotlin.reflect.KType"))
|
override val kTypeClass: IrClassSymbol = context.getIrClass(FqName("kotlin.reflect.KType"))
|
||||||
override val getClassData: IrSimpleFunctionSymbol get() = jsClass
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val reflectionSymbols: JsReflectionSymbols = JsReflectionSymbols()
|
internal val reflectionSymbols: JsReflectionSymbols = JsReflectionSymbols()
|
||||||
|
|||||||
@@ -670,8 +670,8 @@ private val jsClassUsageInReflectionPhase = makeIrModulePhase(
|
|||||||
)
|
)
|
||||||
|
|
||||||
private val classReferenceLoweringPhase = makeIrModulePhase(
|
private val classReferenceLoweringPhase = makeIrModulePhase(
|
||||||
::ClassReferenceLowering,
|
::JsClassReferenceLowering,
|
||||||
name = "ClassReferenceLowering",
|
name = "JsClassReferenceLowering",
|
||||||
description = "Handle class references",
|
description = "Handle class references",
|
||||||
prerequisite = setOf(jsClassUsageInReflectionPhase)
|
prerequisite = setOf(jsClassUsageInReflectionPhase)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -56,4 +56,7 @@ class JsMapping : DefaultMapping() {
|
|||||||
|
|
||||||
val wasmExternalClassToInstanceCheck =
|
val wasmExternalClassToInstanceCheck =
|
||||||
DefaultDelegateFactory.newDeclarationToDeclarationMapping<IrClass, IrSimpleFunction>()
|
DefaultDelegateFactory.newDeclarationToDeclarationMapping<IrClass, IrSimpleFunction>()
|
||||||
|
|
||||||
|
val wasmGetJsClass =
|
||||||
|
DefaultDelegateFactory.newDeclarationToDeclarationMapping<IrClass, IrSimpleFunction>()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,12 +7,10 @@ package org.jetbrains.kotlin.ir.backend.js
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||||
import org.jetbrains.kotlin.ir.types.IrType
|
|
||||||
|
|
||||||
interface ReflectionSymbols {
|
interface ReflectionSymbols {
|
||||||
val getKClassFromExpression: IrSimpleFunctionSymbol
|
val getKClassFromExpression: IrSimpleFunctionSymbol
|
||||||
val getKClass: IrSimpleFunctionSymbol
|
val getKClass: IrSimpleFunctionSymbol
|
||||||
val getClassData: IrSimpleFunctionSymbol
|
|
||||||
val createKType: IrSimpleFunctionSymbol?
|
val createKType: IrSimpleFunctionSymbol?
|
||||||
val createDynamicKType: IrSimpleFunctionSymbol?
|
val createDynamicKType: IrSimpleFunctionSymbol?
|
||||||
val createKTypeParameter: IrSimpleFunctionSymbol?
|
val createKTypeParameter: IrSimpleFunctionSymbol?
|
||||||
|
|||||||
+33
-25
@@ -25,9 +25,36 @@ import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
|||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.types.*
|
import org.jetbrains.kotlin.types.*
|
||||||
|
|
||||||
class ClassReferenceLowering(val context: JsCommonBackendContext) : BodyLoweringPass {
|
class JsClassReferenceLowering(context: JsIrBackendContext) : ClassReferenceLowering(context) {
|
||||||
|
private val getClassData = context.intrinsics.jsClass
|
||||||
|
|
||||||
private val reflectionSymbols get() = context.reflectionSymbols
|
override fun callGetKClass(
|
||||||
|
returnType: IrType,
|
||||||
|
typeArgument: IrType
|
||||||
|
): IrCall {
|
||||||
|
val primitiveKClass =
|
||||||
|
getFinalPrimitiveKClass(returnType, typeArgument) ?: getOpenPrimitiveKClass(returnType, typeArgument)
|
||||||
|
|
||||||
|
if (primitiveKClass != null)
|
||||||
|
return primitiveKClass
|
||||||
|
|
||||||
|
return JsIrBuilder.buildCall(reflectionSymbols.getKClass, returnType, listOf(typeArgument))
|
||||||
|
.apply {
|
||||||
|
putValueArgument(0, callGetClassByType(typeArgument))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun callGetClassByType(type: IrType) =
|
||||||
|
JsIrBuilder.buildCall(
|
||||||
|
getClassData,
|
||||||
|
typeArguments = listOf(type),
|
||||||
|
origin = JsStatementOrigins.CLASS_REFERENCE
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class ClassReferenceLowering(val context: JsCommonBackendContext) : BodyLoweringPass {
|
||||||
|
|
||||||
|
protected val reflectionSymbols get() = context.reflectionSymbols
|
||||||
|
|
||||||
private val primitiveClassProperties by lazy(LazyThreadSafetyMode.NONE) {
|
private val primitiveClassProperties by lazy(LazyThreadSafetyMode.NONE) {
|
||||||
reflectionSymbols.primitiveClassesObject.owner.declarations.filterIsInstance<IrProperty>()
|
reflectionSymbols.primitiveClassesObject.owner.declarations.filterIsInstance<IrProperty>()
|
||||||
@@ -96,7 +123,7 @@ class ClassReferenceLowering(val context: JsCommonBackendContext) : BodyLowering
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getFinalPrimitiveKClass(returnType: IrType, typeArgument: IrType): IrCall? {
|
protected fun getFinalPrimitiveKClass(returnType: IrType, typeArgument: IrType): IrCall? {
|
||||||
for ((typePredicate, v) in finalPrimitiveClasses) {
|
for ((typePredicate, v) in finalPrimitiveClasses) {
|
||||||
if (typePredicate(typeArgument))
|
if (typePredicate(typeArgument))
|
||||||
return getPrimitiveClass(v, returnType)
|
return getPrimitiveClass(v, returnType)
|
||||||
@@ -106,7 +133,7 @@ class ClassReferenceLowering(val context: JsCommonBackendContext) : BodyLowering
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun getOpenPrimitiveKClass(returnType: IrType, typeArgument: IrType): IrCall? {
|
protected fun getOpenPrimitiveKClass(returnType: IrType, typeArgument: IrType): IrCall? {
|
||||||
for ((typePredicate, v) in openPrimitiveClasses) {
|
for ((typePredicate, v) in openPrimitiveClasses) {
|
||||||
if (typePredicate(typeArgument))
|
if (typePredicate(typeArgument))
|
||||||
return getPrimitiveClass(v, returnType)
|
return getPrimitiveClass(v, returnType)
|
||||||
@@ -123,28 +150,10 @@ class ClassReferenceLowering(val context: JsCommonBackendContext) : BodyLowering
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun callGetKClass(
|
abstract fun callGetKClass(
|
||||||
returnType: IrType = reflectionSymbols.getKClass.owner.returnType,
|
returnType: IrType = reflectionSymbols.getKClass.owner.returnType,
|
||||||
typeArgument: IrType
|
typeArgument: IrType
|
||||||
): IrCall {
|
): IrCall
|
||||||
val primitiveKClass =
|
|
||||||
getFinalPrimitiveKClass(returnType, typeArgument) ?: getOpenPrimitiveKClass(returnType, typeArgument)
|
|
||||||
|
|
||||||
if (primitiveKClass != null)
|
|
||||||
return primitiveKClass
|
|
||||||
|
|
||||||
return JsIrBuilder.buildCall(reflectionSymbols.getKClass, returnType, listOf(typeArgument))
|
|
||||||
.apply {
|
|
||||||
putValueArgument(0, callGetClassByType(typeArgument))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun callGetClassByType(type: IrType) =
|
|
||||||
JsIrBuilder.buildCall(
|
|
||||||
reflectionSymbols.getClassData,
|
|
||||||
typeArguments = listOf(type),
|
|
||||||
origin = JsStatementOrigins.CLASS_REFERENCE
|
|
||||||
)
|
|
||||||
|
|
||||||
private fun buildCall(name: IrSimpleFunctionSymbol, vararg args: IrExpression): IrExpression =
|
private fun buildCall(name: IrSimpleFunctionSymbol, vararg args: IrExpression): IrExpression =
|
||||||
JsIrBuilder.buildCall(name).apply {
|
JsIrBuilder.buildCall(name).apply {
|
||||||
@@ -154,7 +163,6 @@ class ClassReferenceLowering(val context: JsCommonBackendContext) : BodyLowering
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun createKType(type: IrType, visitedTypeParams: MutableSet<IrTypeParameter>): IrExpression {
|
private fun createKType(type: IrType, visitedTypeParams: MutableSet<IrTypeParameter>): IrExpression {
|
||||||
|
|
||||||
if (type is IrSimpleType)
|
if (type is IrSimpleType)
|
||||||
return createSimpleKType(type, visitedTypeParams)
|
return createSimpleKType(type, visitedTypeParams)
|
||||||
if (type is IrDynamicType)
|
if (type is IrDynamicType)
|
||||||
|
|||||||
+2
-2
@@ -470,8 +470,8 @@ private val staticMembersLoweringPhase = makeIrModulePhase(
|
|||||||
)
|
)
|
||||||
|
|
||||||
private val classReferenceLoweringPhase = makeIrModulePhase(
|
private val classReferenceLoweringPhase = makeIrModulePhase(
|
||||||
::ClassReferenceLowering,
|
::WasmClassReferenceLowering,
|
||||||
name = "ClassReferenceLowering",
|
name = "WasmClassReferenceLowering",
|
||||||
description = "Handle class references"
|
description = "Handle class references"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -52,10 +52,9 @@ class WasmSymbols(
|
|||||||
|
|
||||||
internal inner class WasmReflectionSymbols : ReflectionSymbols {
|
internal inner class WasmReflectionSymbols : ReflectionSymbols {
|
||||||
override val createKType: IrSimpleFunctionSymbol = getInternalFunction("createKType")
|
override val createKType: IrSimpleFunctionSymbol = getInternalFunction("createKType")
|
||||||
override val getClassData: IrSimpleFunctionSymbol = getInternalFunction("wasmGetTypeInfoData")
|
|
||||||
override val getKClass: IrSimpleFunctionSymbol = getInternalFunction("getKClass")
|
override val getKClass: IrSimpleFunctionSymbol = getInternalFunction("getKClass")
|
||||||
override val getKClassFromExpression: IrSimpleFunctionSymbol = getInternalFunction("getKClassFromExpression")
|
override val getKClassFromExpression: IrSimpleFunctionSymbol = getInternalFunction("getKClassFromExpression")
|
||||||
override val createDynamicKType: IrSimpleFunctionSymbol get() = error("Dynamic type is not supported by WASM")
|
override val createDynamicKType: IrSimpleFunctionSymbol get() = error("Dynamic type is not supported by Wasm")
|
||||||
override val createKTypeParameter: IrSimpleFunctionSymbol = getInternalFunction("createKTypeParameter")
|
override val createKTypeParameter: IrSimpleFunctionSymbol = getInternalFunction("createKTypeParameter")
|
||||||
override val getStarKTypeProjection = getInternalFunction("getStarKTypeProjection")
|
override val getStarKTypeProjection = getInternalFunction("getStarKTypeProjection")
|
||||||
override val createCovariantKTypeProjection = getInternalFunction("createCovariantKTypeProjection")
|
override val createCovariantKTypeProjection = getInternalFunction("createCovariantKTypeProjection")
|
||||||
@@ -67,6 +66,7 @@ class WasmSymbols(
|
|||||||
|
|
||||||
val getTypeInfoTypeDataByPtr: IrSimpleFunctionSymbol = getInternalFunction("getTypeInfoTypeDataByPtr")
|
val getTypeInfoTypeDataByPtr: IrSimpleFunctionSymbol = getInternalFunction("getTypeInfoTypeDataByPtr")
|
||||||
val wasmTypeInfoData: IrClassSymbol = getInternalClass("TypeInfoData")
|
val wasmTypeInfoData: IrClassSymbol = getInternalClass("TypeInfoData")
|
||||||
|
val kClassImpl: IrClassSymbol = getInternalClass("KClassImpl")
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val reflectionSymbols: WasmReflectionSymbols = WasmReflectionSymbols()
|
internal val reflectionSymbols: WasmReflectionSymbols = WasmReflectionSymbols()
|
||||||
@@ -408,6 +408,8 @@ class WasmSymbols(
|
|||||||
|
|
||||||
internal val throwAsJsException: IrSimpleFunctionSymbol =
|
internal val throwAsJsException: IrSimpleFunctionSymbol =
|
||||||
getInternalFunction("throwAsJsException")
|
getInternalFunction("throwAsJsException")
|
||||||
|
|
||||||
|
val kExternalClassImpl: IrClassSymbol = getInternalClass("KExternalClassImpl")
|
||||||
}
|
}
|
||||||
|
|
||||||
private val wasmExportClass = getIrClass(FqName("kotlin.wasm.WasmExport"))
|
private val wasmExportClass = getIrClass(FqName("kotlin.wasm.WasmExport"))
|
||||||
|
|||||||
+2
-1
@@ -63,6 +63,7 @@ class AssociatedObjectsLowering(val context: WasmBackendContext) : FileLoweringP
|
|||||||
for (klassAnnotation in declaration.annotations) {
|
for (klassAnnotation in declaration.annotations) {
|
||||||
val annotationClass = klassAnnotation.symbol.owner.parentClassOrNull ?: continue
|
val annotationClass = klassAnnotation.symbol.owner.parentClassOrNull ?: continue
|
||||||
if (klassAnnotation.valueArgumentsCount != 1) continue
|
if (klassAnnotation.valueArgumentsCount != 1) continue
|
||||||
|
if (declaration.isEffectivelyExternal()) continue
|
||||||
val associatedObject = klassAnnotation.associatedObject() ?: continue
|
val associatedObject = klassAnnotation.associatedObject() ?: continue
|
||||||
|
|
||||||
val builder = cachedBuilder ?: context.createIrBuilder(context.wasmSymbols.tryGetAssociatedObject)
|
val builder = cachedBuilder ?: context.createIrBuilder(context.wasmSymbols.tryGetAssociatedObject)
|
||||||
@@ -102,7 +103,7 @@ private fun IrBuilderWithScope.createAssociatedObjectSelector(
|
|||||||
condition = irEquals(classIdParam, classId),
|
condition = irEquals(classIdParam, classId),
|
||||||
thenPart = irIfThen(
|
thenPart = irIfThen(
|
||||||
condition = irEquals(keyIdParam, keyId),
|
condition = irEquals(keyIdParam, keyId),
|
||||||
thenPart = irReturn(irGetObjectValue(irBuiltIns.anyType, associatedObject))
|
thenPart = irReturn(irGetObjectValue(associatedObject.defaultType, associatedObject))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
+61
-24
@@ -12,21 +12,24 @@ import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
|||||||
import org.jetbrains.kotlin.backend.wasm.WasmBackendContext
|
import org.jetbrains.kotlin.backend.wasm.WasmBackendContext
|
||||||
import org.jetbrains.kotlin.config.AnalysisFlags
|
import org.jetbrains.kotlin.config.AnalysisFlags
|
||||||
import org.jetbrains.kotlin.config.languageVersionSettings
|
import org.jetbrains.kotlin.config.languageVersionSettings
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
|
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||||
import org.jetbrains.kotlin.ir.backend.js.lower.calls.EnumIntrinsicsUtils
|
import org.jetbrains.kotlin.ir.backend.js.lower.calls.EnumIntrinsicsUtils
|
||||||
import org.jetbrains.kotlin.ir.backend.js.utils.erasedUpperBound
|
import org.jetbrains.kotlin.ir.backend.js.utils.erasedUpperBound
|
||||||
import org.jetbrains.kotlin.ir.backend.js.utils.isEqualsInheritedFromAny
|
import org.jetbrains.kotlin.ir.backend.js.utils.isEqualsInheritedFromAny
|
||||||
import org.jetbrains.kotlin.ir.builders.*
|
import org.jetbrains.kotlin.ir.builders.*
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrConstructor
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.putClassTypeArgument
|
||||||
import org.jetbrains.kotlin.ir.util.toIrConst
|
import org.jetbrains.kotlin.ir.util.toIrConst
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||||
import org.jetbrains.kotlin.ir.types.*
|
import org.jetbrains.kotlin.ir.types.*
|
||||||
import org.jetbrains.kotlin.ir.util.*
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
|
|
||||||
import org.jetbrains.kotlin.js.config.WasmTarget
|
|
||||||
import org.jetbrains.kotlin.name.parentOrNull
|
import org.jetbrains.kotlin.name.parentOrNull
|
||||||
|
|
||||||
class BuiltInsLowering(val context: WasmBackendContext) : FileLoweringPass {
|
class BuiltInsLowering(val context: WasmBackendContext) : FileLoweringPass {
|
||||||
@@ -160,35 +163,35 @@ class BuiltInsLowering(val context: WasmBackendContext) : FileLoweringPass {
|
|||||||
val newSymbol = irBuiltins.suspendFunctionN(arity).getSimpleFunction("invoke")!!
|
val newSymbol = irBuiltins.suspendFunctionN(arity).getSimpleFunction("invoke")!!
|
||||||
return irCall(call, newSymbol, argumentsAsReceivers = true)
|
return irCall(call, newSymbol, argumentsAsReceivers = true)
|
||||||
}
|
}
|
||||||
symbols.reflectionSymbols.getClassData -> {
|
context.reflectionSymbols.getKClass -> {
|
||||||
val type = call.getTypeArgument(0)!!
|
val type = call.getTypeArgument(0)!!
|
||||||
val klass = type.classOrNull?.owner ?: error("Invalid type")
|
val klass = type.classOrNull?.owner ?: error("Invalid type")
|
||||||
|
|
||||||
val typeId = builder.irCall(symbols.wasmTypeId).also {
|
val constructorArgument: IrExpression
|
||||||
it.putTypeArgument(0, type)
|
val kclassConstructor: IrConstructor
|
||||||
|
if (klass.isEffectivelyExternal()) {
|
||||||
|
check(context.isWasmJsTarget) { "External classes reflection in WASI mode are not supported" }
|
||||||
|
kclassConstructor = symbols.jsRelatedSymbols.kExternalClassImpl.owner.constructors.first()
|
||||||
|
constructorArgument = getExternalKClassCtorArgument(type, builder)
|
||||||
|
} else {
|
||||||
|
kclassConstructor = symbols.reflectionSymbols.kClassImpl.owner.constructors.first()
|
||||||
|
constructorArgument = getKClassCtorArgument(type, builder)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!klass.isInterface) {
|
return IrConstructorCallImpl(
|
||||||
return builder.irCall(context.wasmSymbols.reflectionSymbols.getTypeInfoTypeDataByPtr).also {
|
startOffset = UNDEFINED_OFFSET,
|
||||||
it.putValueArgument(0, typeId)
|
endOffset = UNDEFINED_OFFSET,
|
||||||
}
|
type = kclassConstructor.returnType,
|
||||||
} else {
|
symbol = kclassConstructor.symbol,
|
||||||
val infoDataCtor = symbols.reflectionSymbols.wasmTypeInfoData.constructors.first()
|
typeArgumentsCount = 1,
|
||||||
val fqName = type.classFqName!!
|
valueArgumentsCount = 1,
|
||||||
val fqnShouldBeEmitted =
|
constructorTypeArgumentsCount = 0
|
||||||
context.configuration.languageVersionSettings.getFlag(AnalysisFlags.allowFullyQualifiedNameInKClass)
|
).also {
|
||||||
val packageName = if (fqnShouldBeEmitted) fqName.parentOrNull()?.asString() ?: "" else ""
|
it.putClassTypeArgument(0, type)
|
||||||
val typeName = fqName.shortName().asString()
|
it.putValueArgument(0, constructorArgument)
|
||||||
|
|
||||||
return with(builder) {
|
|
||||||
irCallConstructor(infoDataCtor, emptyList()).also {
|
|
||||||
it.putValueArgument(0, typeId)
|
|
||||||
it.putValueArgument(1, packageName.toIrConst(context.irBuiltIns.stringType))
|
|
||||||
it.putValueArgument(2, typeName.toIrConst(context.irBuiltIns.stringType))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
symbols.enumValueOfIntrinsic ->
|
symbols.enumValueOfIntrinsic ->
|
||||||
return EnumIntrinsicsUtils.transformEnumValueOfIntrinsic(call)
|
return EnumIntrinsicsUtils.transformEnumValueOfIntrinsic(call)
|
||||||
symbols.enumValuesIntrinsic ->
|
symbols.enumValuesIntrinsic ->
|
||||||
@@ -200,6 +203,40 @@ class BuiltInsLowering(val context: WasmBackendContext) : FileLoweringPass {
|
|||||||
return call
|
return call
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getKClassCtorArgument(type: IrType, builder: DeclarationIrBuilder): IrExpression {
|
||||||
|
val klass = type.classOrNull?.owner ?: error("Invalid type")
|
||||||
|
|
||||||
|
val typeId = builder.irCall(symbols.wasmTypeId).also {
|
||||||
|
it.putTypeArgument(0, type)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!klass.isInterface) {
|
||||||
|
return builder.irCall(context.wasmSymbols.reflectionSymbols.getTypeInfoTypeDataByPtr).also {
|
||||||
|
it.putValueArgument(0, typeId)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val fqName = type.classFqName!!
|
||||||
|
val fqnShouldBeEmitted =
|
||||||
|
context.configuration.languageVersionSettings.getFlag(AnalysisFlags.allowFullyQualifiedNameInKClass)
|
||||||
|
val packageName = if (fqnShouldBeEmitted) fqName.parentOrNull()?.asString() ?: "" else ""
|
||||||
|
val typeName = fqName.shortName().asString()
|
||||||
|
|
||||||
|
return builder.irCallConstructor(symbols.reflectionSymbols.wasmTypeInfoData.constructors.first(), emptyList()).also {
|
||||||
|
it.putValueArgument(0, typeId)
|
||||||
|
it.putValueArgument(1, packageName.toIrConst(context.irBuiltIns.stringType))
|
||||||
|
it.putValueArgument(2, typeName.toIrConst(context.irBuiltIns.stringType))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getExternalKClassCtorArgument(type: IrType, builder: DeclarationIrBuilder): IrExpression {
|
||||||
|
val klass = type.classOrNull?.owner ?: error("Invalid type")
|
||||||
|
check(klass.kind != ClassKind.INTERFACE) { "External interface must not be a class literal" }
|
||||||
|
val classGetClassFunction = context.mapping.wasmGetJsClass[klass]!!
|
||||||
|
val wrappedGetClassIfAny = context.mapping.wasmJsInteropFunctionToWrapper[classGetClassFunction] ?: classGetClassFunction
|
||||||
|
return builder.irCall(wrappedGetClassIfAny)
|
||||||
|
}
|
||||||
|
|
||||||
override fun lower(irFile: IrFile) {
|
override fun lower(irFile: IrFile) {
|
||||||
val builder = context.createIrBuilder(irFile.symbol)
|
val builder = context.createIrBuilder(irFile.symbol)
|
||||||
irFile.transformChildrenVoid(object : IrElementTransformerVoidWithContext() {
|
irFile.transformChildrenVoid(object : IrElementTransformerVoidWithContext() {
|
||||||
|
|||||||
+17
-5
@@ -15,10 +15,7 @@ import org.jetbrains.kotlin.backend.wasm.utils.getWasmImportDescriptor
|
|||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||||
import org.jetbrains.kotlin.ir.backend.js.utils.getJsModule
|
import org.jetbrains.kotlin.ir.backend.js.utils.*
|
||||||
import org.jetbrains.kotlin.ir.backend.js.utils.getJsNameOrKotlinName
|
|
||||||
import org.jetbrains.kotlin.ir.backend.js.utils.getJsQualifier
|
|
||||||
import org.jetbrains.kotlin.ir.backend.js.utils.realOverrideTarget
|
|
||||||
import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter
|
import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter
|
||||||
import org.jetbrains.kotlin.ir.builders.declarations.buildFun
|
import org.jetbrains.kotlin.ir.builders.declarations.buildFun
|
||||||
import org.jetbrains.kotlin.ir.builders.irCallConstructor
|
import org.jetbrains.kotlin.ir.builders.irCallConstructor
|
||||||
@@ -28,6 +25,7 @@ import org.jetbrains.kotlin.ir.expressions.*
|
|||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
||||||
import org.jetbrains.kotlin.ir.types.IrType
|
import org.jetbrains.kotlin.ir.types.IrType
|
||||||
|
import org.jetbrains.kotlin.ir.types.makeNullable
|
||||||
import org.jetbrains.kotlin.ir.util.*
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.ir.visitors.*
|
import org.jetbrains.kotlin.ir.visitors.*
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
@@ -96,8 +94,10 @@ class ComplexExternalDeclarationsToTopLevelFunctionsLowering(val context: WasmBa
|
|||||||
if (klass.kind == ClassKind.OBJECT)
|
if (klass.kind == ClassKind.OBJECT)
|
||||||
generateExternalObjectInstanceGetter(klass)
|
generateExternalObjectInstanceGetter(klass)
|
||||||
|
|
||||||
if (klass.kind != ClassKind.INTERFACE)
|
if (klass.kind != ClassKind.INTERFACE) {
|
||||||
generateInstanceCheckForExternalClass(klass)
|
generateInstanceCheckForExternalClass(klass)
|
||||||
|
generateGetClassForExternalClass(klass)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun processExternalProperty(property: IrProperty) {
|
fun processExternalProperty(property: IrProperty) {
|
||||||
@@ -374,6 +374,18 @@ class ComplexExternalDeclarationsToTopLevelFunctionsLowering(val context: WasmBa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun generateGetClassForExternalClass(klass: IrClass) {
|
||||||
|
context.mapping.wasmGetJsClass[klass] = createExternalJsFunction(
|
||||||
|
klass.name,
|
||||||
|
"_\$external_class_get",
|
||||||
|
resultType = context.wasmSymbols.jsRelatedSymbols.jsAnyType.makeNullable(),
|
||||||
|
jsCode = buildString {
|
||||||
|
append("() => ")
|
||||||
|
appendExternalClassReference(klass)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
private fun createExternalJsFunction(
|
private fun createExternalJsFunction(
|
||||||
originalName: Name,
|
originalName: Name,
|
||||||
suffix: String,
|
suffix: String,
|
||||||
|
|||||||
+29
@@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.backend.wasm.lower
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.wasm.WasmBackendContext
|
||||||
|
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
|
||||||
|
import org.jetbrains.kotlin.ir.backend.js.lower.ClassReferenceLowering
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||||
|
import org.jetbrains.kotlin.ir.types.IrType
|
||||||
|
|
||||||
|
class WasmClassReferenceLowering(context: WasmBackendContext) : ClassReferenceLowering(context) {
|
||||||
|
override fun callGetKClass(
|
||||||
|
returnType: IrType,
|
||||||
|
typeArgument: IrType
|
||||||
|
): IrCall {
|
||||||
|
val primitiveKClass =
|
||||||
|
getFinalPrimitiveKClass(returnType, typeArgument) ?: getOpenPrimitiveKClass(returnType, typeArgument)
|
||||||
|
|
||||||
|
if (primitiveKClass != null)
|
||||||
|
return primitiveKClass
|
||||||
|
|
||||||
|
return JsIrBuilder.buildCall(reflectionSymbols.getKClass, returnType).also {
|
||||||
|
it.putTypeArgument(0, typeArgument)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
// TARGET_BACKEND: WASM
|
||||||
|
|
||||||
|
// FILE: findAssociatedExternalObject.js
|
||||||
|
|
||||||
|
const JS_OBJECT = {}
|
||||||
|
|
||||||
|
// FILE: findAssociatedExternalObject.kt
|
||||||
|
|
||||||
|
import kotlin.reflect.*
|
||||||
|
|
||||||
|
@OptIn(ExperimentalAssociatedObjects::class)
|
||||||
|
@AssociatedObjectKey
|
||||||
|
@Retention(AnnotationRetention.BINARY)
|
||||||
|
annotation class Associated(val kClass: KClass<*>)
|
||||||
|
|
||||||
|
external object JS_OBJECT
|
||||||
|
|
||||||
|
@Associated(JS_OBJECT::class)
|
||||||
|
class ObjectKey
|
||||||
|
|
||||||
|
@OptIn(ExperimentalAssociatedObjects::class)
|
||||||
|
fun box(): String {
|
||||||
|
if (ObjectKey::class.findAssociatedObject<Associated>() !== JS_OBJECT) return "FAIL2"
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
// TARGET_BACKEND: WASM
|
||||||
|
|
||||||
|
// FILE: reflectionOnExternals.js
|
||||||
|
class Outer { }
|
||||||
|
|
||||||
|
Outer.Inner = Promise;
|
||||||
|
|
||||||
|
// FILE: reflectionOnExternals.kt
|
||||||
|
import kotlin.js.Promise
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
import kotlin.reflect.typeOf
|
||||||
|
|
||||||
|
@JsName("Promise")
|
||||||
|
external class PromiseAlias : JsAny
|
||||||
|
|
||||||
|
external class Outer : JsAny {
|
||||||
|
class Inner : JsAny
|
||||||
|
@JsName("Inner")
|
||||||
|
class InnerAlias : JsAny
|
||||||
|
}
|
||||||
|
|
||||||
|
fun checkPromise(kClass: KClass<*>, promiseObject: Any, nonPromiseObject: Any): String? {
|
||||||
|
if (kClass.simpleName != "Promise") return "FAIL1"
|
||||||
|
if (kClass != Promise::class) return "FAIL2"
|
||||||
|
if (Promise::class != kClass) return "FAIL3"
|
||||||
|
if (!kClass.isInstance(promiseObject)) return "FAIL4"
|
||||||
|
if (kClass.isInstance(nonPromiseObject)) return "FAIL5"
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val promiseObj: Any = Promise<JsAny> { resolve, reject -> Unit }
|
||||||
|
val someObject: Any = Any()
|
||||||
|
checkPromise(Promise::class, promiseObj, someObject)?.let { return "1_" + it }
|
||||||
|
checkPromise(PromiseAlias::class, promiseObj, someObject)?.let { return "2_" + it }
|
||||||
|
checkPromise(promiseObj::class, promiseObj, someObject)?.let { return "3_" + it }
|
||||||
|
checkPromise(Outer.Inner::class, promiseObj, someObject)?.let { return "4_" + it }
|
||||||
|
checkPromise(Outer.InnerAlias::class, promiseObj, someObject)?.let { return "5_" + it }
|
||||||
|
|
||||||
|
val typeOfPromiseClassifier = typeOf<Promise<*>>().classifier
|
||||||
|
if (typeOfPromiseClassifier !is KClass<*>) return "FAIL6"
|
||||||
|
checkPromise(typeOfPromiseClassifier, promiseObj, someObject)?.let { return "7_" + it }
|
||||||
|
|
||||||
|
val typeOfPromiseWithArguments = typeOf<Promise<Promise<*>>>()
|
||||||
|
if (typeOfPromiseWithArguments.arguments.size != 1) return "FAIL8"
|
||||||
|
val typeOfPromiseArgumentClassifier = typeOfPromiseWithArguments.arguments[0].type?.classifier
|
||||||
|
if (typeOfPromiseArgumentClassifier !is KClass<*>) return "FAIL9"
|
||||||
|
checkPromise(typeOfPromiseArgumentClassifier, promiseObj, someObject)?.let { return "10_" + it }
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
// IGNORE_BACKEND: WASM
|
|
||||||
// EXPECTED_REACHABLE_NODES: 1414
|
// EXPECTED_REACHABLE_NODES: 1414
|
||||||
// FILE: main.kt
|
// FILE: main.kt
|
||||||
|
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ internal fun <T> wasmIsInterface(obj: Any): Boolean =
|
|||||||
internal fun <T> wasmTypeId(): Int =
|
internal fun <T> wasmTypeId(): Int =
|
||||||
implementedAsIntrinsic
|
implementedAsIntrinsic
|
||||||
|
|
||||||
|
//TODO("Remove after bootstrap KT-65322")
|
||||||
@ExcludedFromCodegen
|
@ExcludedFromCodegen
|
||||||
internal fun <T> wasmGetTypeInfoData(): TypeInfoData =
|
internal fun <T> wasmGetTypeInfoData(): TypeInfoData =
|
||||||
implementedAsIntrinsic
|
implementedAsIntrinsic
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package kotlin.wasm.internal
|
||||||
|
|
||||||
|
import kotlin.reflect.*
|
||||||
|
|
||||||
|
@Suppress("UNUSED_PARAMETER")
|
||||||
|
private fun getJsClassName(jsKlass: JsAny): String? =
|
||||||
|
js("jsKlass.name")
|
||||||
|
|
||||||
|
@Suppress("UNUSED_PARAMETER")
|
||||||
|
private fun instanceOf(ref: JsAny, jsKlass: JsAny): Boolean =
|
||||||
|
js("ref instanceof jsKlass")
|
||||||
|
|
||||||
|
internal class KExternalClassImpl<T : Any> @WasmPrimitiveConstructor constructor(private val jsConstructor: JsAny) : KClass<T> {
|
||||||
|
override val simpleName: String? get() = getJsClassName(jsConstructor)
|
||||||
|
override val qualifiedName: String? get() = null
|
||||||
|
|
||||||
|
override fun isInstance(value: Any?): Boolean =
|
||||||
|
value is JsExternalBox && instanceOf(value.ref, jsConstructor)
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean =
|
||||||
|
other is KExternalClassImpl<*> && jsConstructor == other.jsConstructor
|
||||||
|
|
||||||
|
override fun hashCode(): Int = simpleName.hashCode()
|
||||||
|
|
||||||
|
override fun toString(): String = "class $simpleName"
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package kotlin.wasm.internal
|
||||||
|
|
||||||
|
import kotlin.reflect.*
|
||||||
|
|
||||||
|
@Suppress("UNUSED_PARAMETER")
|
||||||
|
private fun getConstructor(obj: JsAny): JsAny? =
|
||||||
|
js("obj.constructor")
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
internal actual fun <T : Any> getKClassForObject(obj: Any): KClass<T> {
|
||||||
|
if (obj !is JsExternalBox) return KClassImpl(getTypeInfoTypeDataByPtr(obj.typeInfo))
|
||||||
|
val jsConstructor = getConstructor(obj.ref) ?: error("JavaScript constructor is not defined")
|
||||||
|
return KExternalClassImpl(jsConstructor)
|
||||||
|
}
|
||||||
@@ -2,13 +2,9 @@
|
|||||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
package kotlin.reflect.wasm.internal
|
package kotlin.wasm.internal
|
||||||
|
|
||||||
import kotlin.reflect.*
|
import kotlin.reflect.KClass
|
||||||
import kotlin.wasm.internal.TypeInfoData
|
|
||||||
import kotlin.wasm.internal.getSuperTypeId
|
|
||||||
import kotlin.wasm.internal.isInterfaceById
|
|
||||||
import kotlin.wasm.internal.isInterfaceType
|
|
||||||
|
|
||||||
internal object NothingKClassImpl : KClass<Nothing> {
|
internal object NothingKClassImpl : KClass<Nothing> {
|
||||||
override val simpleName: String = "Nothing"
|
override val simpleName: String = "Nothing"
|
||||||
@@ -30,10 +26,10 @@ internal object ErrorKClass : KClass<Nothing> {
|
|||||||
override fun hashCode(): Int = super.hashCode() // KT-24971
|
override fun hashCode(): Int = super.hashCode() // KT-24971
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class KClassImpl<T : Any>(internal val typeData: TypeInfoData) : KClass<T> {
|
internal class KClassImpl<T : Any> @WasmPrimitiveConstructor constructor(internal val typeData: TypeInfoData) : KClass<T> {
|
||||||
override val simpleName: String get() = typeData.typeName
|
override val simpleName: String get() = typeData.typeName
|
||||||
override val qualifiedName: String =
|
override val qualifiedName: String
|
||||||
if (typeData.packageName.isEmpty()) typeData.typeName else "${typeData.packageName}.${typeData.typeName}"
|
get() = if (typeData.packageName.isEmpty()) typeData.typeName else "${typeData.packageName}.${typeData.typeName}"
|
||||||
|
|
||||||
private fun checkSuperTypeInstance(obj: Any): Boolean {
|
private fun checkSuperTypeInstance(obj: Any): Boolean {
|
||||||
var typeId = obj.typeInfo
|
var typeId = obj.typeInfo
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
package kotlin.wasm.internal
|
package kotlin.wasm.internal
|
||||||
|
|
||||||
import kotlin.reflect.wasm.internal.KClassImpl
|
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
@PublishedApi
|
@PublishedApi
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ package kotlin.wasm.internal
|
|||||||
|
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
import kotlin.reflect.KFunction
|
import kotlin.reflect.KFunction
|
||||||
import kotlin.reflect.wasm.internal.*
|
|
||||||
|
|
||||||
internal object PrimitiveClasses {
|
internal object PrimitiveClasses {
|
||||||
|
|
||||||
|
|||||||
@@ -3,12 +3,16 @@
|
|||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// a package is omitted to get declarations directly under the module
|
|
||||||
package kotlin.wasm.internal
|
package kotlin.wasm.internal
|
||||||
|
|
||||||
import kotlin.reflect.*
|
import kotlin.reflect.*
|
||||||
import kotlin.reflect.wasm.internal.*
|
|
||||||
|
|
||||||
|
internal expect fun <T : Any> getKClassForObject(obj: Any): KClass<T>
|
||||||
|
|
||||||
|
//TODO(Replace getKClass to intrinsic argument-less implementation after bootstrap KT-65322")
|
||||||
|
//@ExcludedFromCodegen
|
||||||
|
//internal fun <T : Any> getKClass(): KClass<T> =
|
||||||
|
// implementedAsIntrinsic
|
||||||
internal fun <T : Any> getKClass(typeInfoData: TypeInfoData): KClass<T> =
|
internal fun <T : Any> getKClass(typeInfoData: TypeInfoData): KClass<T> =
|
||||||
KClassImpl(typeInfoData)
|
KClassImpl(typeInfoData)
|
||||||
|
|
||||||
@@ -34,12 +38,12 @@ internal fun <T : Any> getKClassFromExpression(e: T): KClass<T> =
|
|||||||
is DoubleArray -> PrimitiveClasses.doubleArrayClass
|
is DoubleArray -> PrimitiveClasses.doubleArrayClass
|
||||||
is KClass<*> -> KClass::class
|
is KClass<*> -> KClass::class
|
||||||
is Array<*> -> PrimitiveClasses.arrayClass
|
is Array<*> -> PrimitiveClasses.arrayClass
|
||||||
else -> getKClass(getTypeInfoTypeDataByPtr(e.typeInfo))
|
else -> getKClassForObject(e)
|
||||||
} as KClass<T>
|
} as KClass<T>
|
||||||
|
|
||||||
@Suppress("REIFIED_TYPE_PARAMETER_NO_INLINE")
|
@Suppress("REIFIED_TYPE_PARAMETER_NO_INLINE")
|
||||||
internal inline fun <reified T : Any> wasmGetKClass(): KClass<T> =
|
internal inline fun <reified T : Any> wasmGetKClass(): KClass<T> =
|
||||||
KClassImpl(wasmGetTypeInfoData<T>())
|
KClassImpl(getTypeInfoTypeDataByPtr(wasmTypeId<T>()))
|
||||||
|
|
||||||
internal fun createKType(classifier: KClassifier, arguments: Array<KTypeProjection>, isMarkedNullable: Boolean): KType =
|
internal fun createKType(classifier: KClassifier, arguments: Array<KTypeProjection>, isMarkedNullable: Boolean): KType =
|
||||||
KTypeImpl(classifier, arguments.asList(), isMarkedNullable)
|
KTypeImpl(classifier, arguments.asList(), isMarkedNullable)
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// a package is omitted to get declarations directly under the module
|
||||||
|
package kotlin.wasm.internal
|
||||||
|
|
||||||
|
import kotlin.reflect.*
|
||||||
|
|
||||||
|
internal actual fun <T : Any> getKClassForObject(obj: Any): KClass<T> =
|
||||||
|
KClassImpl(getTypeInfoTypeDataByPtr(obj.typeInfo))
|
||||||
Generated
+12
@@ -24,6 +24,12 @@ public class FirWasmJsCodegenInteropTestGenerated extends AbstractFirWasmJsCodeg
|
|||||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxWasmJsInterop"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.WASM, true);
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxWasmJsInterop"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.WASM, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("associatedExternalObject.kt")
|
||||||
|
public void testAssociatedExternalObject() {
|
||||||
|
runTest("compiler/testData/codegen/boxWasmJsInterop/associatedExternalObject.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("callingWasmDirectly.kt")
|
@TestMetadata("callingWasmDirectly.kt")
|
||||||
public void testCallingWasmDirectly() {
|
public void testCallingWasmDirectly() {
|
||||||
@@ -162,6 +168,12 @@ public class FirWasmJsCodegenInteropTestGenerated extends AbstractFirWasmJsCodeg
|
|||||||
runTest("compiler/testData/codegen/boxWasmJsInterop/nullableExternRefs.kt");
|
runTest("compiler/testData/codegen/boxWasmJsInterop/nullableExternRefs.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("reflectionOnExternals.kt")
|
||||||
|
public void testReflectionOnExternals() {
|
||||||
|
runTest("compiler/testData/codegen/boxWasmJsInterop/reflectionOnExternals.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("types.kt")
|
@TestMetadata("types.kt")
|
||||||
public void testTypes() {
|
public void testTypes() {
|
||||||
|
|||||||
+12
@@ -24,6 +24,12 @@ public class K1WasmCodegenWasmJsInteropTestGenerated extends AbstractK1WasmCodeg
|
|||||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxWasmJsInterop"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.WASM, true);
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxWasmJsInterop"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.WASM, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("associatedExternalObject.kt")
|
||||||
|
public void testAssociatedExternalObject() {
|
||||||
|
runTest("compiler/testData/codegen/boxWasmJsInterop/associatedExternalObject.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("callingWasmDirectly.kt")
|
@TestMetadata("callingWasmDirectly.kt")
|
||||||
public void testCallingWasmDirectly() {
|
public void testCallingWasmDirectly() {
|
||||||
@@ -162,6 +168,12 @@ public class K1WasmCodegenWasmJsInteropTestGenerated extends AbstractK1WasmCodeg
|
|||||||
runTest("compiler/testData/codegen/boxWasmJsInterop/nullableExternRefs.kt");
|
runTest("compiler/testData/codegen/boxWasmJsInterop/nullableExternRefs.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("reflectionOnExternals.kt")
|
||||||
|
public void testReflectionOnExternals() {
|
||||||
|
runTest("compiler/testData/codegen/boxWasmJsInterop/reflectionOnExternals.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("types.kt")
|
@TestMetadata("types.kt")
|
||||||
public void testTypes() {
|
public void testTypes() {
|
||||||
|
|||||||
Reference in New Issue
Block a user