[JS IR & WASM] Fix executing init blocks for enums with nested objects
This commit is contained in:
@@ -755,7 +755,8 @@ private val staticMembersLoweringPhase = makeDeclarationTransformerPhase(
|
||||
private val objectDeclarationLoweringPhase = makeDeclarationTransformerPhase(
|
||||
::ObjectDeclarationLowering,
|
||||
name = "ObjectDeclarationLowering",
|
||||
description = "Create lazy object instance generator functions"
|
||||
description = "Create lazy object instance generator functions",
|
||||
prerequisite = setOf(enumClassCreateInitializerLoweringPhase)
|
||||
)
|
||||
|
||||
private val invokeStaticInitializersPhase = makeBodyLoweringPhase(
|
||||
|
||||
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
|
||||
class ObjectDeclarationLowering(
|
||||
val context: JsCommonBackendContext
|
||||
@@ -34,6 +35,11 @@ class ObjectDeclarationLowering(
|
||||
private var IrClass.instanceField by context.mapping.objectToInstanceField
|
||||
private var IrClass.syntheticPrimaryConstructor by context.mapping.classToSyntheticPrimaryConstructor
|
||||
|
||||
/**
|
||||
* If the object being lowered is nested inside an enum class, we want to also initialize the enum entries when initializing the object.
|
||||
*/
|
||||
private var IrClass.initEntryInstancesFun: IrSimpleFunction? by context.mapping.enumClassToInitEntryInstancesFun
|
||||
|
||||
override fun transformFlat(declaration: IrDeclaration): List<IrDeclaration>? {
|
||||
if (declaration !is IrClass || declaration.kind != ClassKind.OBJECT || declaration.isEffectivelyExternal())
|
||||
return null
|
||||
@@ -54,8 +60,12 @@ class ObjectDeclarationLowering(
|
||||
|
||||
val primaryConstructor = declaration.primaryConstructor ?: declaration.syntheticPrimaryConstructor!!
|
||||
|
||||
val initEntryInstancesFun = declaration.parent.safeAs<IrClass>()?.initEntryInstancesFun
|
||||
|
||||
getInstanceFun.body = context.irFactory.createBlockBody(UNDEFINED_OFFSET, UNDEFINED_OFFSET) {
|
||||
statements += context.createIrBuilder(getInstanceFun.symbol).irBlockBody(getInstanceFun) {
|
||||
if (initEntryInstancesFun != null)
|
||||
+irCall(initEntryInstancesFun)
|
||||
+irIfThen(
|
||||
irEqualsNull(irGetField(null, instanceField)),
|
||||
// Instance field initialized inside constructor
|
||||
|
||||
+2
-1
@@ -421,7 +421,8 @@ private val builtInsLoweringPhase = makeWasmModulePhase(
|
||||
private val objectDeclarationLoweringPhase = makeWasmModulePhase(
|
||||
::ObjectDeclarationLowering,
|
||||
name = "ObjectDeclarationLowering",
|
||||
description = "Create lazy object instance generator functions"
|
||||
description = "Create lazy object instance generator functions",
|
||||
prerequisite = setOf(enumClassCreateInitializerLoweringPhase)
|
||||
)
|
||||
|
||||
private val objectUsageLoweringPhase = makeWasmModulePhase(
|
||||
|
||||
+27
-6
@@ -1,7 +1,7 @@
|
||||
// IGNORE_BACKEND: WASM
|
||||
// WASM_MUTE_REASON: IGNORED_IN_JS
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
// IGNORE_BACKEND: JS_IR_ES6
|
||||
// DONT_TARGET_EXACT_BACKEND: JS
|
||||
// DONT_TARGET_EXACT_BACKEND: JS_IR
|
||||
// DONT_TARGET_EXACT_BACKEND: JS_IR_ES6
|
||||
// DONT_TARGET_EXACT_BACKEND: WASM
|
||||
// IGNORE_BACKEND: NATIVE
|
||||
var result = ""
|
||||
|
||||
@@ -41,11 +41,32 @@ enum class F(a: String) {
|
||||
}
|
||||
}
|
||||
|
||||
enum class G(a: String) {
|
||||
X("x"),
|
||||
Y("y");
|
||||
|
||||
init {
|
||||
result += "G.init($a);"
|
||||
}
|
||||
|
||||
object O {
|
||||
init {
|
||||
result += "G.O.init;"
|
||||
}
|
||||
|
||||
fun foo() {
|
||||
result += "G.O.foo();$X;"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val y = E.Y
|
||||
result += "${y.name};"
|
||||
F.foo()
|
||||
if (result != "E.init(x);E.init(y);E.companion.init;X;Y;F.init(x);F.init(y);F.companion.init;F.foo();X;") return "fail: $result"
|
||||
G.O.foo()
|
||||
if (result != "E.init(x);E.init(y);E.companion.init;X;Y;F.init(x);F.init(y);F.companion.init;F.foo();X;G.O.init;G.O.foo();X;")
|
||||
return "fail: $result"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
// TARGET_BACKEND: JS
|
||||
// TARGET_BACKEND: JS_IR
|
||||
// TARGET_BACKEND: JS_IR_ES6
|
||||
// TARGET_BACKEND: WASM
|
||||
// WITH_RUNTIME
|
||||
var result = ""
|
||||
|
||||
enum class E(a: String) {
|
||||
X("x"),
|
||||
Y("y");
|
||||
|
||||
init {
|
||||
result += "E.init($a);"
|
||||
}
|
||||
|
||||
companion object {
|
||||
init {
|
||||
result += "E.companion.init;"
|
||||
val value = E.values()[0].name
|
||||
result += "$value;"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum class F(a: String) {
|
||||
X("x"),
|
||||
Y("y");
|
||||
|
||||
init {
|
||||
result += "F.init($a);"
|
||||
}
|
||||
|
||||
companion object {
|
||||
init {
|
||||
result += "F.companion.init;"
|
||||
}
|
||||
|
||||
fun foo() {
|
||||
result += "F.foo();$X;"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum class G(a: String) {
|
||||
X("x"),
|
||||
Y("y");
|
||||
|
||||
init {
|
||||
result += "G.init($a);"
|
||||
}
|
||||
|
||||
object O {
|
||||
init {
|
||||
result += "G.O.init;"
|
||||
}
|
||||
|
||||
fun foo() {
|
||||
result += "G.O.foo();$X;"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val y = E.Y
|
||||
result += "${y.name};"
|
||||
F.foo()
|
||||
G.O.foo()
|
||||
if (result != "E.init(x);E.init(y);E.companion.init;X;Y;F.init(x);F.init(y);F.companion.init;F.foo();X;G.init(x);G.init(y);G.O.init;G.O.foo();X;")
|
||||
return "fail: $result"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -1,4 +1,7 @@
|
||||
// IGNORE_BACKEND: JS
|
||||
// DONT_TARGET_EXACT_BACKEND: JS
|
||||
// DONT_TARGET_EXACT_BACKEND: JS_IR
|
||||
// DONT_TARGET_EXACT_BACKEND: JS_IR_ES6
|
||||
// DONT_TARGET_EXACT_BACKEND: WASM
|
||||
|
||||
var l = ""
|
||||
enum class Foo {
|
||||
@@ -16,4 +19,4 @@ enum class Foo {
|
||||
fun box(): String {
|
||||
Foo.L
|
||||
return if (l != "Foo.CO;") "FAIL: ${l}" else "OK"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
// TARGET_BACKEND: JS
|
||||
// TARGET_BACKEND: JS_IR
|
||||
// TARGET_BACKEND: JS_IR_ES6
|
||||
// TARGET_BACKEND: WASM
|
||||
|
||||
var l = ""
|
||||
enum class Foo {
|
||||
F;
|
||||
init {
|
||||
l += "Foo;"
|
||||
}
|
||||
object L {
|
||||
init {
|
||||
l += "Foo.CO;"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
Foo.L
|
||||
return if (l != "Foo;Foo.CO;") "FAIL: ${l}" else "OK"
|
||||
}
|
||||
js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java
Generated
+6
-6
@@ -10991,9 +10991,9 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes
|
||||
runTest("compiler/testData/codegen/box/enum/emptyEnumValuesValueOf.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("enumCompanionInit.kt")
|
||||
public void testEnumCompanionInit() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/enum/enumCompanionInit.kt");
|
||||
@TestMetadata("enumCompanionInitJsAndWasm.kt")
|
||||
public void testEnumCompanionInitJsAndWasm() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/enum/enumCompanionInitJsAndWasm.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("enumConstructorParameterClashWithDefaults.kt")
|
||||
@@ -11076,9 +11076,9 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes
|
||||
runTest("compiler/testData/codegen/box/enum/initEntriesInValueOf.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("initEnumAfterObjectAccess.kt")
|
||||
public void testInitEnumAfterObjectAccess() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/enum/initEnumAfterObjectAccess.kt");
|
||||
@TestMetadata("initEnumAfterObjectAccessJsAndWasm.kt")
|
||||
public void testInitEnumAfterObjectAccessJsAndWasm() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/enum/initEnumAfterObjectAccessJsAndWasm.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inner.kt")
|
||||
|
||||
Generated
+6
-6
@@ -10397,9 +10397,9 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/enum/emptyEnumValuesValueOf.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("enumCompanionInit.kt")
|
||||
public void testEnumCompanionInit() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/enum/enumCompanionInit.kt");
|
||||
@TestMetadata("enumCompanionInitJsAndWasm.kt")
|
||||
public void testEnumCompanionInitJsAndWasm() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/enum/enumCompanionInitJsAndWasm.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("enumConstructorParameterClashWithDefaults.kt")
|
||||
@@ -10482,9 +10482,9 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/enum/initEntriesInValueOf.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("initEnumAfterObjectAccess.kt")
|
||||
public void testInitEnumAfterObjectAccess() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/enum/initEnumAfterObjectAccess.kt");
|
||||
@TestMetadata("initEnumAfterObjectAccessJsAndWasm.kt")
|
||||
public void testInitEnumAfterObjectAccessJsAndWasm() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/enum/initEnumAfterObjectAccessJsAndWasm.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inner.kt")
|
||||
|
||||
Generated
+6
-6
@@ -10362,9 +10362,9 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/enum/emptyEnumValuesValueOf.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("enumCompanionInit.kt")
|
||||
public void testEnumCompanionInit() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/enum/enumCompanionInit.kt");
|
||||
@TestMetadata("enumCompanionInitJsAndWasm.kt")
|
||||
public void testEnumCompanionInitJsAndWasm() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/enum/enumCompanionInitJsAndWasm.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("enumConstructorParameterClashWithDefaults.kt")
|
||||
@@ -10447,9 +10447,9 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/enum/initEntriesInValueOf.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("initEnumAfterObjectAccess.kt")
|
||||
public void testInitEnumAfterObjectAccess() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/enum/initEnumAfterObjectAccess.kt");
|
||||
@TestMetadata("initEnumAfterObjectAccessJsAndWasm.kt")
|
||||
public void testInitEnumAfterObjectAccessJsAndWasm() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/enum/initEnumAfterObjectAccessJsAndWasm.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inner.kt")
|
||||
|
||||
js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java
Generated
+6
-6
@@ -9658,9 +9658,9 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest
|
||||
runTest("compiler/testData/codegen/box/enum/emptyEnumValuesValueOf.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("enumCompanionInit.kt")
|
||||
public void testEnumCompanionInit() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/enum/enumCompanionInit.kt");
|
||||
@TestMetadata("enumCompanionInitJsAndWasm.kt")
|
||||
public void testEnumCompanionInitJsAndWasm() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/enum/enumCompanionInitJsAndWasm.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("enumConstructorParameterClashWithDefaults.kt")
|
||||
@@ -9743,9 +9743,9 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest
|
||||
runTest("compiler/testData/codegen/box/enum/initEntriesInValueOf.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("initEnumAfterObjectAccess.kt")
|
||||
public void testInitEnumAfterObjectAccess() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/enum/initEnumAfterObjectAccess.kt");
|
||||
@TestMetadata("initEnumAfterObjectAccessJsAndWasm.kt")
|
||||
public void testInitEnumAfterObjectAccessJsAndWasm() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/enum/initEnumAfterObjectAccessJsAndWasm.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("inner.kt")
|
||||
|
||||
Reference in New Issue
Block a user