[K/JS] Generate tests for K2 + ES-classes compilation
This commit is contained in:
+5
-1
@@ -35,6 +35,7 @@ object ES6_SYNTHETIC_EXPORT_CONSTRUCTOR: IrDeclarationOriginImpl("ES6_SYNTHETIC_
|
||||
object ES6_PRIMARY_CONSTRUCTOR_REPLACEMENT : IrDeclarationOriginImpl("ES6_PRIMARY_CONSTRUCTOR_REPLACEMENT")
|
||||
object ES6_INIT_FUNCTION : IrDeclarationOriginImpl("ES6_INIT_FUNCTION")
|
||||
object ES6_DELEGATING_CONSTRUCTOR_REPLACEMENT : IrStatementOriginImpl("ES6_DELEGATING_CONSTRUCTOR_REPLACEMENT")
|
||||
object ES6_DELEGATING_CONSTRUCTOR_CALL_REPLACEMENT : IrDeclarationOriginImpl("ES6_DELEGATING_CONSTRUCTOR_CALL_REPLACEMENT")
|
||||
|
||||
val IrDeclaration.isEs6ConstructorReplacement: Boolean
|
||||
get() = origin == ES6_CONSTRUCTOR_REPLACEMENT || origin == ES6_PRIMARY_CONSTRUCTOR_REPLACEMENT
|
||||
@@ -54,6 +55,9 @@ val IrFunctionAccessExpression.isInitCall: Boolean
|
||||
val IrDeclaration.isSyntheticConstructorForExport: Boolean
|
||||
get() = origin == ES6_SYNTHETIC_EXPORT_CONSTRUCTOR
|
||||
|
||||
val IrDeclaration.isEs6DelegatingConstructorCallReplacement: Boolean
|
||||
get() = origin == ES6_DELEGATING_CONSTRUCTOR_CALL_REPLACEMENT
|
||||
|
||||
class ES6ConstructorLowering(val context: JsIrBackendContext) : DeclarationTransformer {
|
||||
private var IrConstructor.constructorFactory by context.mapping.secondaryConstructorToFactory
|
||||
|
||||
@@ -161,7 +165,7 @@ class ES6ConstructorLowering(val context: JsIrBackendContext) : DeclarationTrans
|
||||
parent = this,
|
||||
name = Namer.SYNTHETIC_RECEIVER_NAME,
|
||||
initializer = initializer,
|
||||
origin = IrDeclarationOrigin.IR_TEMPORARY_VARIABLE
|
||||
origin = ES6_DELEGATING_CONSTRUCTOR_CALL_REPLACEMENT
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -339,10 +339,10 @@ class EnumEntryInstancesBodyLowering(val context: JsCommonBackendContext) : Body
|
||||
if (enum.isInstantiableEnum) {
|
||||
val entry = enum.declarations.findIsInstanceAnd<IrEnumEntry> { it.correspondingClass === entryClass }!!
|
||||
|
||||
//In ES6 using `this` before superCall is unavailable, so
|
||||
//need to find superCall and put `instance = this` after it
|
||||
// In ES6 using `this` before superCall is unavailable, so
|
||||
// need to find superCall and put `instance = this` after it
|
||||
val index = (irBody as IrBlockBody).statements
|
||||
.indexOfFirst { it is IrTypeOperatorCall && it.argument is IrDelegatingConstructorCall } + 1
|
||||
.indexOfFirst { it is IrDelegatingConstructorCall || it is IrTypeOperatorCall && it.argument is IrDelegatingConstructorCall } + 1
|
||||
|
||||
irBody.statements.add(index, context.createIrBuilder(container.symbol).run {
|
||||
irSetField(null, entry.correspondingField!!, irGet(entryClass.thisReceiver!!))
|
||||
|
||||
+22
-20
@@ -10,7 +10,6 @@ import org.jetbrains.kotlin.backend.common.getOrPut
|
||||
import org.jetbrains.kotlin.backend.common.ir.isPure
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.backend.js.JsCommonBackendContext
|
||||
import org.jetbrains.kotlin.ir.backend.js.JsLoweredDeclarationOrigin
|
||||
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.isObjectInstanceField
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.isObjectInstanceGetter
|
||||
@@ -24,21 +23,15 @@ class PurifyObjectInstanceGettersLowering(val context: JsCommonBackendContext) :
|
||||
private var IrClass.instanceField by context.mapping.objectToInstanceField
|
||||
|
||||
override fun transformFlat(declaration: IrDeclaration): List<IrDeclaration>? {
|
||||
if (
|
||||
!declaration.isObjectInstanceGetter() &&
|
||||
!declaration.isObjectInstanceField() &&
|
||||
!declaration.isObjectConstructor()
|
||||
) return null
|
||||
|
||||
return when (declaration) {
|
||||
is IrSimpleFunction -> declaration.purifyObjectGetterIfPossible()
|
||||
is IrField -> declaration.purifyObjectInstanceFieldIfPossible()
|
||||
is IrConstructor -> declaration.removeInstanceFieldInitializationIfPossible()
|
||||
else -> error("Unexpected IR type ${declaration::class.qualifiedName}")
|
||||
return when {
|
||||
(declaration is IrFunction && declaration.isObjectConstructor()) -> declaration.removeInstanceFieldInitializationIfPossible()
|
||||
(declaration is IrSimpleFunction && declaration.isObjectInstanceGetter()) -> declaration.purifyObjectGetterIfPossible()
|
||||
(declaration is IrField && declaration.isObjectInstanceField()) -> declaration.purifyObjectInstanceFieldIfPossible()
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrConstructor.removeInstanceFieldInitializationIfPossible(): List<IrDeclaration>? {
|
||||
private fun IrFunction.removeInstanceFieldInitializationIfPossible(): List<IrDeclaration>? {
|
||||
if (parentAsClass.isPureObject()) {
|
||||
(body as? IrBlockBody)?.statements?.removeIf {
|
||||
it is IrSetField && it.symbol.owner.isObjectInstanceField()
|
||||
@@ -70,30 +63,36 @@ class PurifyObjectInstanceGettersLowering(val context: JsCommonBackendContext) :
|
||||
val objectToCreate = type.classOrNull?.owner ?: return null
|
||||
|
||||
if (objectToCreate.isPureObject()) {
|
||||
val objectConstructor = objectToCreate.primaryConstructor ?: error("Object should contain a primary constructor")
|
||||
initializer = IrExpressionBodyImpl(JsIrBuilder.buildConstructorCall(objectConstructor.symbol))
|
||||
initializer = IrExpressionBodyImpl(
|
||||
objectToCreate.primaryConstructor?.let { JsIrBuilder.buildConstructorCall(it.symbol) }
|
||||
?: objectToCreate.primaryConstructorReplacement?.let { JsIrBuilder.buildCall(it.symbol) }
|
||||
?: error("Object should contain a primary constructor")
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
private fun IrDeclaration.isObjectConstructor(): Boolean {
|
||||
return this is IrConstructor && parentAsClass.isObject
|
||||
return (this is IrConstructor || isEs6ConstructorReplacement) && parentAsClass.isObject
|
||||
}
|
||||
|
||||
private fun IrClass.isPureObject(): Boolean {
|
||||
return context.mapping.objectsWithPureInitialization.getOrPut(this) {
|
||||
superClass == null && primaryConstructor?.body?.statements?.all { it.isPureStatementForObjectInitialization(this@isPureObject) } != false
|
||||
val constructor = primaryConstructor ?: primaryConstructorReplacement
|
||||
superClass == null && constructor?.body?.statements?.all { it.isPureStatementForObjectInitialization(this@isPureObject) } != false
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrStatement.isPureStatementForObjectInitialization(owner: IrClass): Boolean {
|
||||
return (
|
||||
// Only objects which don't have a class parent
|
||||
(this is IrDelegatingConstructorCall && symbol.owner.parent == context.irBuiltIns.anyClass.owner) ||
|
||||
this is IrReturn ||
|
||||
// Only objects which don't have a class parent
|
||||
(this is IrDelegatingConstructorCall && symbol.owner.parent == context.irBuiltIns.anyClass.owner) ||
|
||||
(this is IrExpression && isPure(anyVariable = true, checkFields = false, context = context)) ||
|
||||
(this is IrContainerExpression && statements.all { it.isPureStatementForObjectInitialization(owner) }) ||
|
||||
(this is IrVariable && initializer?.isPureStatementForObjectInitialization(owner) != false) ||
|
||||
(this is IrVariable && (isEs6DelegatingConstructorCallReplacement || initializer?.isPureStatementForObjectInitialization(owner) != false)) ||
|
||||
// Only fields of the objects are safe to not save an intermediate state of another class/object/global
|
||||
(this is IrGetField && receiver?.isPureStatementForObjectInitialization(owner) == true) ||
|
||||
(this is IrSetField && receiver?.isPureStatementForObjectInitialization(owner) == true && value.isPureStatementForObjectInitialization(owner)) ||
|
||||
@@ -103,4 +102,7 @@ class PurifyObjectInstanceGettersLowering(val context: JsCommonBackendContext) :
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
private val IrClass.primaryConstructorReplacement: IrSimpleFunction?
|
||||
get() = findDeclaration<IrSimpleFunction> { it.isEs6PrimaryConstructorReplacement }
|
||||
}
|
||||
|
||||
+2
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs
|
||||
import org.jetbrains.kotlin.ir.util.inlineFunction
|
||||
import org.jetbrains.kotlin.ir.util.innerInlinedBlockOrThis
|
||||
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
|
||||
import org.jetbrains.kotlin.ir.backend.js.lower.ES6_DELEGATING_CONSTRUCTOR_CALL_REPLACEMENT
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.JsGenerationContext
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.emptyScope
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.isTheLastReturnStatementIn
|
||||
@@ -171,6 +172,7 @@ class IrElementToJsStatementTransformer : BaseIrElementToJsNodeTransformer<JsSta
|
||||
is IrDeclarationOrigin.IR_TEMPORARY_VARIABLE -> true
|
||||
is IrDeclarationOrigin.IR_TEMPORARY_VARIABLE_FOR_INLINED_PARAMETER -> true
|
||||
is IrDeclarationOrigin.IR_TEMPORARY_VARIABLE_FOR_INLINED_EXTENSION_RECEIVER -> true
|
||||
is ES6_DELEGATING_CONSTRUCTOR_CALL_REPLACEMENT -> true
|
||||
else -> false
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user