From 7d8636aac47dbf813ca3559d56f50e4586bb7b2c Mon Sep 17 00:00:00 2001 From: Ilya Goncharov Date: Thu, 29 Sep 2022 16:12:19 +0000 Subject: [PATCH] [JS] Keep interfaces ^KT-54173 fixed --- .../js/dce/JsUsefulDeclarationProcessor.kt | 3 +- .../js/dce/UselessDeclarationsRemover.kt | 2 +- .../kotlin/js/test/ir/FirJsTestGenerated.java | 12 +++++++ .../js/test/ir/IrBoxJsTestGenerated.java | 12 +++++++ .../testData/box/keep/keepInterface.kt | 34 +++++++++++++++++++ .../box/keep/keepVarAnonymousClass.kt | 26 ++++++++++++++ 6 files changed, 87 insertions(+), 2 deletions(-) create mode 100644 js/js.translator/testData/box/keep/keepInterface.kt create mode 100644 js/js.translator/testData/box/keep/keepVarAnonymousClass.kt 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 d506257c7b4..8dc774074e0 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 @@ -127,7 +127,8 @@ internal class JsUsefulDeclarationProcessor( override fun processSuperTypes(irClass: IrClass) { irClass.superTypes.forEach { - if (!it.isInterface()) { + val shouldClassBeKept = it.classOrNull?.let { context.keeper.shouldKeep(it.owner) } ?: false + if (!it.isInterface() || shouldClassBeKept) { (it.classifierOrNull as? IrClassSymbol)?.owner?.enqueue(irClass, "superTypes") } } diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/dce/UselessDeclarationsRemover.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/dce/UselessDeclarationsRemover.kt index a6335593944..cd2ad7d3721 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/dce/UselessDeclarationsRemover.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/dce/UselessDeclarationsRemover.kt @@ -63,7 +63,7 @@ class UselessDeclarationsRemover( private fun IrClassSymbol.collectUsedSuperTypes(): Set { return savedTypesCache.getOrPut(this) { - if (owner in usefulDeclarations) { + if (owner in usefulDeclarations || context.keeper.shouldKeep(owner)) { setOf(this) } else { owner.superTypes diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/FirJsTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/FirJsTestGenerated.java index a855a1d34ce..c44378b665c 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/FirJsTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/FirJsTestGenerated.java @@ -7290,6 +7290,12 @@ public class FirJsTestGenerated extends AbstractFirJsTest { runTest("js/js.translator/testData/box/keep/keepClass.kt"); } + @Test + @TestMetadata("keepInterface.kt") + public void testKeepInterface() throws Exception { + runTest("js/js.translator/testData/box/keep/keepInterface.kt"); + } + @Test @TestMetadata("keepMethod.kt") public void testKeepMethod() throws Exception { @@ -7313,6 +7319,12 @@ public class FirJsTestGenerated extends AbstractFirJsTest { public void testKeepOverriddenMethod() throws Exception { runTest("js/js.translator/testData/box/keep/keepOverriddenMethod.kt"); } + + @Test + @TestMetadata("keepVarAnonymousClass.kt") + public void testKeepVarAnonymousClass() throws Exception { + runTest("js/js.translator/testData/box/keep/keepVarAnonymousClass.kt"); + } } @Nested diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrBoxJsTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrBoxJsTestGenerated.java index 8c161621938..076bf15c204 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrBoxJsTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrBoxJsTestGenerated.java @@ -7290,6 +7290,12 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest { runTest("js/js.translator/testData/box/keep/keepClass.kt"); } + @Test + @TestMetadata("keepInterface.kt") + public void testKeepInterface() throws Exception { + runTest("js/js.translator/testData/box/keep/keepInterface.kt"); + } + @Test @TestMetadata("keepMethod.kt") public void testKeepMethod() throws Exception { @@ -7313,6 +7319,12 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest { public void testKeepOverriddenMethod() throws Exception { runTest("js/js.translator/testData/box/keep/keepOverriddenMethod.kt"); } + + @Test + @TestMetadata("keepVarAnonymousClass.kt") + public void testKeepVarAnonymousClass() throws Exception { + runTest("js/js.translator/testData/box/keep/keepVarAnonymousClass.kt"); + } } @Nested diff --git a/js/js.translator/testData/box/keep/keepInterface.kt b/js/js.translator/testData/box/keep/keepInterface.kt new file mode 100644 index 00000000000..5c77c8fe41f --- /dev/null +++ b/js/js.translator/testData/box/keep/keepInterface.kt @@ -0,0 +1,34 @@ +// TARGET_BACKEND: JS_IR +// ONLY_IR_DCE +// RUN_PLAIN_BOX_FUNCTION +// INFER_MAIN_MODULE +// KEEP: DenotedFace + +// MODULE: keep_interface +// FILE: lib.kt + +interface DenotedFace { + fun keepMeA() = 7 + fun keepMeB(): Int +} + +class A : DenotedFace { + override fun keepMeB(): Int { + return 8 + } +} + +@JsExport +fun foo(): A { + return A() +} + +// FILE: test.js +function box() { + var a = this["keep_interface"].foo() + + if (a.keepMeA_ds0nq4_k$() != 7) return "fail 1" + if (a.keepMeB_ds0nq3_k$() != 8) return "fail 2" + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/box/keep/keepVarAnonymousClass.kt b/js/js.translator/testData/box/keep/keepVarAnonymousClass.kt new file mode 100644 index 00000000000..c8614dc34ea --- /dev/null +++ b/js/js.translator/testData/box/keep/keepVarAnonymousClass.kt @@ -0,0 +1,26 @@ +// TARGET_BACKEND: JS_IR +// ONLY_IR_DCE +// RUN_PLAIN_BOX_FUNCTION +// INFER_MAIN_MODULE +// KEEP: DenotedFace + +// MODULE: keep_var +// FILE: lib.kt + +interface DenotedFace { + fun keepMeA() = 7 + fun keepMeB(): Int +} + +@JsExport +val denotedFaceTrigger = object : DenotedFace { override fun keepMeB() = 8 } + +// FILE: test.js +function box() { + var a = this["keep_var"].denotedFaceTrigger + + if (a.keepMeA_ds0nq4_k$() != 7) return "fail 1" + if (a.keepMeB_ds0nq3_k$() != 8) return "fail 2" + + return "OK" +} \ No newline at end of file