[JS IR] Introduce special setMetadataFor*() for synthetic classes
^KT-63436 Fixed
This commit is contained in:
committed by
Space Team
parent
9af681e234
commit
45c166abf8
@@ -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")
|
||||
|
||||
+12
-4
@@ -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")
|
||||
|
||||
+1
-1
@@ -42,7 +42,7 @@ abstract class AbstractSuspendFunctionsLowering<C : CommonBackendContext>(val co
|
||||
|
||||
private var IrFunction.coroutineConstructor by context.mapping.suspendFunctionToCoroutineConstructor
|
||||
|
||||
protected companion object {
|
||||
companion object {
|
||||
val DECLARATION_ORIGIN_COROUTINE_IMPL = IrDeclarationOriginImpl("COROUTINE_IMPL")
|
||||
}
|
||||
|
||||
|
||||
+53
-28
@@ -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? {
|
||||
|
||||
+2
-2
@@ -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
|
||||
|
||||
+2
-2
@@ -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
|
||||
|
||||
+2
-2
@@ -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: <this>=A, $completion=$foo1COROUTINE$0
|
||||
// test.kt:6 foo: <this>=A, $completion=Coroutine
|
||||
// test.kt:9 doResume:
|
||||
// test.kt:6 foo: <this>=A, $completion=$foo1COROUTINE$0
|
||||
// test.kt:6 foo: <this>=A, $completion=Coroutine
|
||||
// test.kt:10 doResume:
|
||||
// test.kt:11 doResume: dead=kotlin.Long
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+1
-1
@@ -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:
|
||||
|
||||
@@ -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<Int>() + 1
|
||||
return globalInterfaceId.unsafeCast<Int>()
|
||||
}
|
||||
|
||||
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<dynamic>?,
|
||||
suspendArity: Array<Int>?,
|
||||
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<dynamic>?,
|
||||
suspendArity: Array<Int>?,
|
||||
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<dynamic>?,
|
||||
suspendArity: Array<Int>?,
|
||||
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<dynamic>?,
|
||||
suspendArity: Array<Int>?,
|
||||
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<dynamic>?, suspendArity: Array<Int>?) {
|
||||
initMetadataForClass(ctor, "Lambda", VOID, parent, interfaces, suspendArity, VOID, VOID)
|
||||
}
|
||||
|
||||
internal fun initMetadataForFunctionReference(ctor: Ctor, parent: Ctor?, interfaces: Array<dynamic>?, suspendArity: Array<Int>?) {
|
||||
initMetadataForClass(ctor, "FunctionReference", VOID, parent, interfaces, suspendArity, VOID, VOID)
|
||||
}
|
||||
|
||||
internal fun initMetadataForCoroutine(ctor: Ctor, parent: Ctor?, interfaces: Array<dynamic>?, suspendArity: Array<Int>?) {
|
||||
initMetadataForClass(ctor, "Coroutine", VOID, parent, interfaces, suspendArity, VOID, VOID)
|
||||
}
|
||||
|
||||
internal fun initMetadataForCompanion(ctor: Ctor, parent: Ctor?, interfaces: Array<dynamic>?, suspendArity: Array<Int>?) {
|
||||
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<Int>?,
|
||||
): 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<Int>?
|
||||
val iid: Int?
|
||||
|
||||
var `$kClass$`: dynamic
|
||||
val defaultConstructor: dynamic
|
||||
|
||||
var errorInfo: Int? // Bits set for overridden properties: "message" => 0x1, "cause" => 0x2
|
||||
}
|
||||
@@ -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<Int>() + 1
|
||||
return iid.unsafeCast<Int>()
|
||||
}
|
||||
|
||||
|
||||
internal fun interfaceMeta(
|
||||
name: String?,
|
||||
defaultConstructor: dynamic,
|
||||
@@ -53,7 +40,7 @@ internal fun interfaceMeta(
|
||||
associatedObjects: dynamic,
|
||||
suspendArity: Array<Int>?
|
||||
): 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<Int>?
|
||||
): 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<Int>?
|
||||
): 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<Int>?,
|
||||
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<Int>?
|
||||
val iid: Int?
|
||||
|
||||
var `$kClass$`: dynamic
|
||||
val defaultConstructor: dynamic
|
||||
|
||||
var errorInfo: Int? // Bits set for overridden properties: "message" => 0x1, "cause" => 0x2
|
||||
}
|
||||
@@ -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<Int?>() ?: 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))
|
||||
jsEqeqeq(value, ktExternalObject) || (jsTypeOf(ktExternalObject) == "function" && jsInstanceOf(value, ktExternalObject))
|
||||
|
||||
Reference in New Issue
Block a user