diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIntrinsics.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIntrinsics.kt index dd1efe4bef0..3780cda7208 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIntrinsics.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIntrinsics.kt @@ -112,7 +112,14 @@ class JsIntrinsics(private val irBuiltIns: IrBuiltIns, val context: JsIrBackendC // RTTI: val implementSymbol = getInternalFunction("implement") - val setMetadataForSymbol = getInternalFunction("setMetadataFor") + val initMetadataForSymbol = getInternalFunction("initMetadataFor") + val initMetadataForClassSymbol = getInternalFunction("initMetadataForClass") + val initMetadataForObjectSymbol = getInternalFunction("initMetadataForObject") + val initMetadataForInterfaceSymbol = getInternalFunction("initMetadataForInterface") + val initMetadataForLambdaSymbol = getInternalFunction("initMetadataForLambda") + val initMetadataForCoroutineSymbol = getInternalFunction("initMetadataForCoroutine") + val initMetadataForFunctionReferenceSymbol = getInternalFunction("initMetadataForFunctionReference") + val initMetadataForCompanionSymbol = getInternalFunction("initMetadataForCompanion") val isInterfaceSymbol = getInternalFunction("isInterface") val isArraySymbol = getInternalFunction("isArray") @@ -198,10 +205,6 @@ class JsIntrinsics(private val irBuiltIns: IrBuiltIns, val context: JsIrBackendC getInternalClassWithoutPackage("kotlin.js.Promise") } - val metadataInterfaceConstructorSymbol = getInternalFunction("interfaceMeta") - val metadataObjectConstructorSymbol = getInternalFunction("objectMeta") - val metadataClassConstructorSymbol = getInternalFunction("classMeta") - val longToDouble = context.symbolTable.descriptorExtension.referenceSimpleFunction( context.getClass(FqName("kotlin.Long")).unsubstitutedMemberScope.findSingleFunction( Name.identifier("toDouble") diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/dce/JsUsefulDeclarationProcessor.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/dce/JsUsefulDeclarationProcessor.kt index 6350cf9f825..f9df8b1924f 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/dce/JsUsefulDeclarationProcessor.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/dce/JsUsefulDeclarationProcessor.kt @@ -154,17 +154,25 @@ internal class JsUsefulDeclarationProcessor( if (!irClass.containsMetadata()) return when { - irClass.isObject -> context.intrinsics.metadataObjectConstructorSymbol.owner.enqueue(irClass, "object metadata") + irClass.isObject -> { + context.intrinsics.initMetadataForCompanionSymbol.owner.enqueue(irClass, "object metadata") + context.intrinsics.initMetadataForObjectSymbol.owner.enqueue(irClass, "companion object metadata") + } irClass.isInterface -> { context.intrinsics.implementSymbol.owner.enqueue(irClass, "interface metadata") - context.intrinsics.metadataInterfaceConstructorSymbol.owner.enqueue(irClass, "interface metadata") + context.intrinsics.initMetadataForInterfaceSymbol.owner.enqueue(irClass, "interface metadata") } - else -> context.intrinsics.metadataClassConstructorSymbol.owner.enqueue(irClass, "class metadata") + else -> { + context.intrinsics.initMetadataForClassSymbol.owner.enqueue(irClass, "class metadata") + context.intrinsics.initMetadataForLambdaSymbol.owner.enqueue(irClass, "lambda metadata") + context.intrinsics.initMetadataForCoroutineSymbol.owner.enqueue(irClass, "coroutine metadata") + context.intrinsics.initMetadataForFunctionReferenceSymbol.owner.enqueue(irClass, "function reference metadata") + } } - context.intrinsics.setMetadataForSymbol.owner.enqueue(irClass, "metadata") + context.intrinsics.initMetadataForSymbol.owner.enqueue(irClass, "metadata") if (irClass.containsInterfaceDefaultImplementation()) { context.intrinsics.jsPrototypeOfSymbol.owner.enqueue(irClass, "interface default implementation") diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/coroutines/AbstractSuspendFunctionsLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/coroutines/AbstractSuspendFunctionsLowering.kt index 4eda4442c25..5f8cc105484 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/coroutines/AbstractSuspendFunctionsLowering.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/coroutines/AbstractSuspendFunctionsLowering.kt @@ -42,7 +42,7 @@ abstract class AbstractSuspendFunctionsLowering(val co private var IrFunction.coroutineConstructor by context.mapping.suspendFunctionToCoroutineConstructor - protected companion object { + companion object { val DECLARATION_ORIGIN_COROUTINE_IMPL = IrDeclarationOriginImpl("COROUTINE_IMPL") } diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsClassGenerator.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsClassGenerator.kt index f66026e1ab0..fd6085d9cb3 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsClassGenerator.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsClassGenerator.kt @@ -12,16 +12,20 @@ import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext import org.jetbrains.kotlin.ir.backend.js.export.isAllowedFakeOverriddenDeclaration import org.jetbrains.kotlin.ir.backend.js.export.isExported import org.jetbrains.kotlin.ir.backend.js.export.isOverriddenExported +import org.jetbrains.kotlin.ir.backend.js.lower.CallableReferenceLowering +import org.jetbrains.kotlin.ir.backend.js.lower.coroutines.AbstractSuspendFunctionsLowering import org.jetbrains.kotlin.ir.backend.js.lower.isEs6ConstructorReplacement import org.jetbrains.kotlin.ir.backend.js.utils.* import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol +import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.js.backend.ast.* import org.jetbrains.kotlin.js.backend.ast.JsVars.JsVar import org.jetbrains.kotlin.js.common.isValidES5Identifier +import org.jetbrains.kotlin.name.SpecialNames import org.jetbrains.kotlin.utils.addIfNotNull import org.jetbrains.kotlin.utils.addToStdlib.butIf import org.jetbrains.kotlin.utils.addToStdlib.runIf @@ -255,7 +259,7 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo val metadataPlace = if (es6mode) classModel.postDeclarationBlock else classModel.preDeclarationBlock - metadataPlace.statements += generateSetMetadataCall() + metadataPlace.statements += generateInitMetadataCall() context.staticContext.classModels[irClass.symbol] = classModel return classBlock @@ -371,39 +375,35 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo } } - private fun generateSetMetadataCall(): JsStatement { - val setMetadataFor = backendContext.intrinsics.setMetadataForSymbol.owner - + private fun generateInitMetadataCall(): JsStatement { val ctor = classNameRef val parent = baseClassRef?.takeIf { !es6mode } val name = generateSimpleName() val interfaces = generateInterfacesList() - val metadataConstructor = getMetadataConstructor() val defaultConstructor = runIf(irClass.isClass, ::findDefaultConstructor) val associatedObjectKey = generateAssociatedObjectKey() val associatedObjects = generateAssociatedObjects() val suspendArity = generateSuspendArity() - return JsInvocation( - JsNameRef(context.getNameForStaticFunction(setMetadataFor)), - listOf( - ctor, - name, - metadataConstructor, - parent, - interfaces, - defaultConstructor, - associatedObjectKey, - associatedObjects, - suspendArity - ) - .dropLastWhile { it == null } - .memoryOptimizedMap { it ?: jsUndefined } - ).makeStmt() + if (defaultConstructor == null && associatedObjectKey == null && associatedObjects == null) { + val initSpecialMetadata = getSpecialInitMetadata(name) + if (initSpecialMetadata != null) { + return initSpecialMetadata.invokeWithoutNullArgs(ctor, parent, interfaces, suspendArity) + } + } + return getInitMetadata().invokeWithoutNullArgs( + ctor, + name, + defaultConstructor, + parent, + interfaces, + suspendArity, + associatedObjectKey, + associatedObjects + ) } - private fun IrType.asConstructorRef(): JsExpression? { val ownerSymbol = classOrNull?.takeIf { !isAny() && !isFunctionType() && !it.owner.isEffectivelyExternal() @@ -418,16 +418,41 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo return irClass.name.takeIf { !it.isSpecial }?.let { JsStringLiteral(it.identifier) } } - private fun getMetadataConstructor(): JsNameRef { - val metadataConstructorSymbol = with(backendContext.intrinsics) { + private fun getInitMetadata(): IrSimpleFunctionSymbol { + return with(backendContext.intrinsics) { when { - irClass.isInterface -> metadataInterfaceConstructorSymbol - irClass.isObject -> metadataObjectConstructorSymbol - else -> metadataClassConstructorSymbol + irClass.isInterface -> initMetadataForInterfaceSymbol + irClass.isObject -> initMetadataForObjectSymbol + else -> initMetadataForClassSymbol } } + } - return JsNameRef(context.getNameForStaticFunction(metadataConstructorSymbol.owner)) + private fun getSpecialInitMetadata(name: JsStringLiteral?): IrSimpleFunctionSymbol? { + if (irClass.isCompanion && name?.value == SpecialNames.DEFAULT_NAME_FOR_COMPANION_OBJECT.asString()) { + return backendContext.intrinsics.initMetadataForCompanionSymbol + } + if (irClass.isClass) { + when (irClass.origin) { + CallableReferenceLowering.LAMBDA_IMPL -> { + return backendContext.intrinsics.initMetadataForLambdaSymbol + } + CallableReferenceLowering.FUNCTION_REFERENCE_IMPL -> { + return backendContext.intrinsics.initMetadataForFunctionReferenceSymbol + } + AbstractSuspendFunctionsLowering.DECLARATION_ORIGIN_COROUTINE_IMPL -> { + return backendContext.intrinsics.initMetadataForCoroutineSymbol + } + } + } + return null + } + + private fun IrSimpleFunctionSymbol.invokeWithoutNullArgs(vararg arguments: JsExpression?): JsStatement { + return JsInvocation( + JsNameRef(context.getNameForStaticFunction(owner)), + arguments.dropLastWhile { it == null }.memoryOptimizedMap { it ?: jsUndefined } + ).makeStmt() } private fun generateInterfacesList(): JsArrayLiteral? { diff --git a/compiler/testData/debug/localVariables/suspend/completion/nonStaticStateMachine.kt b/compiler/testData/debug/localVariables/suspend/completion/nonStaticStateMachine.kt index 0e6b007d3eb..8d8d5a74399 100644 --- a/compiler/testData/debug/localVariables/suspend/completion/nonStaticStateMachine.kt +++ b/compiler/testData/debug/localVariables/suspend/completion/nonStaticStateMachine.kt @@ -36,8 +36,8 @@ suspend fun box() { // test.kt:14 box: $completion=EmptyContinuation // test.kt:14 box: $completion=EmptyContinuation // test.kt:7 doResume: -// test.kt:5 foo: $completion=$foo1COROUTINE$0 +// test.kt:5 foo: $completion=Coroutine // test.kt:8 doResume: -// test.kt:5 foo: $completion=$foo1COROUTINE$0 +// test.kt:5 foo: $completion=Coroutine // test.kt:9 doResume: // test.kt:10 doResume: dead=kotlin.Long diff --git a/compiler/testData/debug/localVariables/suspend/completion/staticStateMachine.kt b/compiler/testData/debug/localVariables/suspend/completion/staticStateMachine.kt index 4b8499158f4..9e097811469 100644 --- a/compiler/testData/debug/localVariables/suspend/completion/staticStateMachine.kt +++ b/compiler/testData/debug/localVariables/suspend/completion/staticStateMachine.kt @@ -30,8 +30,8 @@ suspend fun box() { // test.kt:13 box: $completion=EmptyContinuation // test.kt:12 box: $completion=EmptyContinuation // test.kt:6 doResume: -// test.kt:4 foo: $completion=$foo1COROUTINE$0 +// test.kt:4 foo: $completion=Coroutine // test.kt:7 doResume: -// test.kt:4 foo: $completion=$foo1COROUTINE$0 +// test.kt:4 foo: $completion=Coroutine // test.kt:8 doResume: // test.kt:9 doResume: dead=kotlin.Long diff --git a/compiler/testData/debug/localVariables/suspend/completion/staticStateMachineReceiver.kt b/compiler/testData/debug/localVariables/suspend/completion/staticStateMachineReceiver.kt index 027608ce806..6cade55fff7 100644 --- a/compiler/testData/debug/localVariables/suspend/completion/staticStateMachineReceiver.kt +++ b/compiler/testData/debug/localVariables/suspend/completion/staticStateMachineReceiver.kt @@ -38,8 +38,8 @@ suspend fun box() { // test.kt:14 box: $completion=EmptyContinuation // test.kt:14 box: $completion=EmptyContinuation // test.kt:8 doResume: -// test.kt:6 foo: =A, $completion=$foo1COROUTINE$0 +// test.kt:6 foo: =A, $completion=Coroutine // test.kt:9 doResume: -// test.kt:6 foo: =A, $completion=$foo1COROUTINE$0 +// test.kt:6 foo: =A, $completion=Coroutine // test.kt:10 doResume: // test.kt:11 doResume: dead=kotlin.Long diff --git a/compiler/testData/debug/localVariables/suspend/inlineLocalsStateMachineTransform.kt b/compiler/testData/debug/localVariables/suspend/inlineLocalsStateMachineTransform.kt index 529e1974920..389059e93b5 100644 --- a/compiler/testData/debug/localVariables/suspend/inlineLocalsStateMachineTransform.kt +++ b/compiler/testData/debug/localVariables/suspend/inlineLocalsStateMachineTransform.kt @@ -34,7 +34,7 @@ suspend fun box() { // EXPECTATIONS JS_IR // test.kt:12 doResume: -// test.kt:8 h: $completion=$boxCOROUTINE$0 +// test.kt:8 h: $completion=Coroutine // test.kt:4 doResume: // test.kt:4 doResume: x=41:number // test.kt:19 doResume: x=41:number, x=41:number diff --git a/compiler/testData/debug/localVariables/suspend/localsStateMachineTransform.kt b/compiler/testData/debug/localVariables/suspend/localsStateMachineTransform.kt index cfbc6b9b75b..b17593501ad 100644 --- a/compiler/testData/debug/localVariables/suspend/localsStateMachineTransform.kt +++ b/compiler/testData/debug/localVariables/suspend/localsStateMachineTransform.kt @@ -48,7 +48,7 @@ suspend fun box() { // EXPECTATIONS JS_IR // test.kt:12 doResume: -// test.kt:6 h: $completion=$boxCOROUTINE$0 +// test.kt:6 h: $completion=Coroutine // test.kt:13 doResume: // test.kt:13 doResume: // test.kt:13 doResume: diff --git a/libraries/stdlib/js/runtime/metadataUtils.kt b/libraries/stdlib/js/runtime/metadataUtils.kt new file mode 100644 index 00000000000..5091e280efe --- /dev/null +++ b/libraries/stdlib/js/runtime/metadataUtils.kt @@ -0,0 +1,151 @@ +/* + * Copyright 2010-2023 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.js + +// There was a problem with per-module compilation (KT-55758) when the top-level state (globalInterfaceId) was reinitialized during stdlib module initialization +// As a result we miss already incremented globalInterfaceId and had the same interfaceIds in two different modules +// So, to keep the state consistent it was moved into the variable without initializer and function +@Suppress("MUST_BE_INITIALIZED") +private var globalInterfaceId: dynamic + +private fun generateInterfaceId(): Int { + if (globalInterfaceId === VOID) { + globalInterfaceId = 0 + } + globalInterfaceId = globalInterfaceId.unsafeCast() + 1 + return globalInterfaceId.unsafeCast() +} + +internal const val METADATA_KIND_INTERFACE = "interface" +internal const val METADATA_KIND_OBJECT = "object" +internal const val METADATA_KIND_CLASS = "class" + +internal fun initMetadataFor( + kind: String, + ctor: Ctor, + name: String?, + defaultConstructor: dynamic, + parent: Ctor?, + interfaces: Array?, + suspendArity: Array?, + associatedObjectKey: Number?, + associatedObjects: dynamic +) { + if (parent != null) { + js(""" + ctor.prototype = Object.create(parent.prototype) + ctor.prototype.constructor = ctor; + """) + } + + val metadata = createMetadata(kind, name, defaultConstructor, associatedObjectKey, associatedObjects, suspendArity) + ctor.`$metadata$` = metadata + + if (interfaces != null) { + val receiver = if (metadata.iid != VOID) ctor else ctor.prototype + receiver.`$imask$` = implement(interfaces) + } +} + +internal fun initMetadataForClass( + ctor: Ctor, + name: String?, + defaultConstructor: dynamic, + parent: Ctor?, + interfaces: Array?, + suspendArity: Array?, + associatedObjectKey: Number?, + associatedObjects: dynamic +) { + val kind = METADATA_KIND_CLASS + initMetadataFor(kind, ctor, name, defaultConstructor, parent, interfaces, suspendArity, associatedObjectKey, associatedObjects) +} + +internal fun initMetadataForObject( + ctor: Ctor, + name: String?, + defaultConstructor: dynamic, + parent: Ctor?, + interfaces: Array?, + suspendArity: Array?, + associatedObjectKey: Number?, + associatedObjects: dynamic +) { + val kind = METADATA_KIND_OBJECT + initMetadataFor(kind, ctor, name, defaultConstructor, parent, interfaces, suspendArity, associatedObjectKey, associatedObjects) +} + +internal fun initMetadataForInterface( + ctor: Ctor, + name: String?, + defaultConstructor: dynamic, + parent: Ctor?, + interfaces: Array?, + suspendArity: Array?, + associatedObjectKey: Number?, + associatedObjects: dynamic +) { + val kind = METADATA_KIND_INTERFACE + initMetadataFor(kind, ctor, name, defaultConstructor, parent, interfaces, suspendArity, associatedObjectKey, associatedObjects) +} + +internal fun initMetadataForLambda(ctor: Ctor, parent: Ctor?, interfaces: Array?, suspendArity: Array?) { + initMetadataForClass(ctor, "Lambda", VOID, parent, interfaces, suspendArity, VOID, VOID) +} + +internal fun initMetadataForFunctionReference(ctor: Ctor, parent: Ctor?, interfaces: Array?, suspendArity: Array?) { + initMetadataForClass(ctor, "FunctionReference", VOID, parent, interfaces, suspendArity, VOID, VOID) +} + +internal fun initMetadataForCoroutine(ctor: Ctor, parent: Ctor?, interfaces: Array?, suspendArity: Array?) { + initMetadataForClass(ctor, "Coroutine", VOID, parent, interfaces, suspendArity, VOID, VOID) +} + +internal fun initMetadataForCompanion(ctor: Ctor, parent: Ctor?, interfaces: Array?, suspendArity: Array?) { + initMetadataForObject(ctor, "Companion", VOID, parent, interfaces, suspendArity, VOID, VOID) +} + +// Seems like we need to disable this check if variables are used inside js annotation +@Suppress("UNUSED_PARAMETER", "UNUSED_VARIABLE") +internal fun createMetadata( + kind: String, + name: String?, + defaultConstructor: dynamic, + associatedObjectKey: Number?, + associatedObjects: dynamic, + suspendArity: Array?, +): Metadata { + val undef = VOID + val iid = if (kind == METADATA_KIND_INTERFACE) generateInterfaceId() else VOID + return js("""({ + kind: kind, + simpleName: name, + associatedObjectKey: associatedObjectKey, + associatedObjects: associatedObjects, + suspendArity: suspendArity, + ${'$'}kClass$: undef, + defaultConstructor: defaultConstructor, + iid: iid +})""") +} + +internal external interface Metadata { + // TODO: This field can be used from user libs, e.g. kotlinx.serialization: + // https://github.com/Kotlin/kotlinx.serialization/blob/b8de86f0e351f1099d2afb03ff92e2ef6256cbc7/core/jsMain/src/kotlinx/serialization/internal/Platform.kt#L74 + // This must be reworked + val kind: String + // This field gives fast access to the prototype of metadata owner (Object.getPrototypeOf()) + // Can be pre-initialized or lazy initialized and then should be immutable + val simpleName: String? + val associatedObjectKey: Number? + val associatedObjects: dynamic + val suspendArity: Array? + val iid: Int? + + var `$kClass$`: dynamic + val defaultConstructor: dynamic + + var errorInfo: Int? // Bits set for overridden properties: "message" => 0x1, "cause" => 0x2 +} diff --git a/libraries/stdlib/js/runtime/metadataUtilsOld.kt b/libraries/stdlib/js/runtime/metadataUtilsOld.kt index 5748d3e6a8d..22c8e5afa9a 100644 --- a/libraries/stdlib/js/runtime/metadataUtilsOld.kt +++ b/libraries/stdlib/js/runtime/metadataUtilsOld.kt @@ -4,6 +4,8 @@ */ package kotlin.js +// TODO: Remove this file after bootstrap + internal fun setMetadataFor( ctor: Ctor, name: String?, @@ -31,21 +33,6 @@ internal fun setMetadataFor( } } -// There was a problem with per-module compilation (KT-55758) when the top-level state (iid) was reinitialized during stdlib module initialization -// As a result we miss already incremented iid and had the same iids in two different modules -// So, to keep the state consistent it was moved into the variable without initializer and function -@Suppress("MUST_BE_INITIALIZED") -private var iid: dynamic - -private fun generateInterfaceId(): Int { - if (iid === VOID) { - iid = 0 - } - iid = iid.unsafeCast() + 1 - return iid.unsafeCast() -} - - internal fun interfaceMeta( name: String?, defaultConstructor: dynamic, @@ -53,7 +40,7 @@ internal fun interfaceMeta( associatedObjects: dynamic, suspendArity: Array? ): Metadata { - return createMetadata("interface", name, defaultConstructor, associatedObjectKey, associatedObjects, suspendArity, generateInterfaceId()) + return createMetadata(METADATA_KIND_INTERFACE, name, defaultConstructor, associatedObjectKey, associatedObjects, suspendArity) } internal fun objectMeta( @@ -63,7 +50,7 @@ internal fun objectMeta( associatedObjects: dynamic, suspendArity: Array? ): Metadata { - return createMetadata("object", name, defaultConstructor, associatedObjectKey, associatedObjects, suspendArity, null) + return createMetadata(METADATA_KIND_OBJECT, name, defaultConstructor, associatedObjectKey, associatedObjects, suspendArity) } internal fun classMeta( @@ -73,45 +60,5 @@ internal fun classMeta( associatedObjects: dynamic, suspendArity: Array? ): Metadata { - return createMetadata("class", name, defaultConstructor, associatedObjectKey, associatedObjects, suspendArity, null) + return createMetadata(METADATA_KIND_CLASS, name, defaultConstructor, associatedObjectKey, associatedObjects, suspendArity) } - -// Seems like we need to disable this check if variables are used inside js annotation -@Suppress("UNUSED_PARAMETER", "UNUSED_VARIABLE") -private fun createMetadata( - kind: String, - name: String?, - defaultConstructor: dynamic, - associatedObjectKey: Number?, - associatedObjects: dynamic, - suspendArity: Array?, - iid: Int? -): Metadata { - val undef = VOID - return js("""({ - kind: kind, - simpleName: name, - associatedObjectKey: associatedObjectKey, - associatedObjects: associatedObjects, - suspendArity: suspendArity, - ${'$'}kClass$: undef, - defaultConstructor: defaultConstructor, - iid: iid -})""") -} - -internal external interface Metadata { - val kind: String - // This field gives fast access to the prototype of metadata owner (Object.getPrototypeOf()) - // Can be pre-initialized or lazy initialized and then should be immutable - val simpleName: String? - val associatedObjectKey: Number? - val associatedObjects: dynamic - val suspendArity: Array? - val iid: Int? - - var `$kClass$`: dynamic - val defaultConstructor: dynamic - - var errorInfo: Int? // Bits set for overridden properties: "message" => 0x1, "cause" => 0x2 -} \ No newline at end of file diff --git a/libraries/stdlib/js/runtime/typeCheckUtils.kt b/libraries/stdlib/js/runtime/typeCheckUtils.kt index 2e497a71cc1..56e15752a08 100644 --- a/libraries/stdlib/js/runtime/typeCheckUtils.kt +++ b/libraries/stdlib/js/runtime/typeCheckUtils.kt @@ -114,7 +114,7 @@ internal fun jsIsType(obj: dynamic, jsClass: dynamic): Boolean { val constructor = if (jsClassType == "object") jsGetPrototypeOf(jsClass) else jsClass val klassMetadata = constructor.`$metadata$` - if (klassMetadata?.kind === "interface") { + if (klassMetadata?.kind === METADATA_KIND_INTERFACE) { val iid = klassMetadata.iid.unsafeCast() ?: return false return isInterfaceImpl(obj, iid) } @@ -141,4 +141,4 @@ internal fun isCharSequence(value: dynamic): Boolean = @OptIn(JsIntrinsic::class) internal fun isExternalObject(value: dynamic, ktExternalObject: dynamic) = - jsEqeqeq(value, ktExternalObject) || (jsTypeOf(ktExternalObject) == "function" && jsInstanceOf(value, ktExternalObject)) \ No newline at end of file + jsEqeqeq(value, ktExternalObject) || (jsTypeOf(ktExternalObject) == "function" && jsInstanceOf(value, ktExternalObject))