[JS IR] Add to IR keep possibility similar to legacy-dce one
It helps to: - keep declarations even if they are not reachable and not exported - not minify names of not exported declarations Compiler argument: -Xir-keep=A,B Can be used for top-level declarations or for member ^KT-54118 fixed
This commit is contained in:
@@ -593,7 +593,15 @@ class GenerateIrRuntime {
|
||||
private fun doBackEnd(
|
||||
module: IrModuleFragment, symbolTable: SymbolTable, irBuiltIns: IrBuiltIns, jsLinker: JsIrLinker
|
||||
): CompilerResult {
|
||||
val context = JsIrBackendContext(module.descriptor, irBuiltIns, symbolTable, module, emptySet(), configuration)
|
||||
val context = JsIrBackendContext(
|
||||
module.descriptor,
|
||||
irBuiltIns,
|
||||
symbolTable,
|
||||
module,
|
||||
additionalExportedDeclarationNames = emptySet(),
|
||||
keep = emptySet(),
|
||||
configuration
|
||||
)
|
||||
|
||||
ExternalDependenciesGenerator(symbolTable, listOf(jsLinker)).generateUnboundSymbolsAsDependencies()
|
||||
|
||||
|
||||
@@ -81,6 +81,7 @@ class JsIrBackendFacade(
|
||||
val splitPerFile = JsEnvironmentConfigurationDirectives.SPLIT_PER_FILE in module.directives
|
||||
val perModule = JsEnvironmentConfigurationDirectives.PER_MODULE in module.directives
|
||||
val runNewIr2Js = JsEnvironmentConfigurationDirectives.RUN_NEW_IR_2_JS in module.directives
|
||||
val keep = module.directives[JsEnvironmentConfigurationDirectives.KEEP].toSet()
|
||||
|
||||
val granularity = when {
|
||||
!firstTimeCompilation -> JsGenerationGranularity.WHOLE_PROGRAM
|
||||
@@ -145,6 +146,7 @@ class JsIrBackendFacade(
|
||||
deserializer,
|
||||
phaseConfig,
|
||||
exportedDeclarations = setOf(FqName.fromSegments(listOfNotNull(testPackage, TEST_FUNCTION))),
|
||||
keep = keep,
|
||||
dceRuntimeDiagnostic = null,
|
||||
es6mode = false,
|
||||
baseClassIntoMetadata = false,
|
||||
@@ -166,6 +168,7 @@ class JsIrBackendFacade(
|
||||
val mainArguments = JsEnvironmentConfigurator.getMainCallParametersForModule(module)
|
||||
.run { if (shouldBeGenerated()) arguments() else null }
|
||||
val runIrDce = JsEnvironmentConfigurationDirectives.RUN_IR_DCE in module.directives
|
||||
val onlyIrDce = JsEnvironmentConfigurationDirectives.ONLY_IR_DCE in module.directives
|
||||
val esModules = JsEnvironmentConfigurationDirectives.ES_MODULES in module.directives
|
||||
val runNewIr2Js = JsEnvironmentConfigurationDirectives.RUN_NEW_IR_2_JS in module.directives
|
||||
val perModuleOnly = JsEnvironmentConfigurationDirectives.SPLIT_PER_MODULE in module.directives
|
||||
@@ -180,7 +183,7 @@ class JsIrBackendFacade(
|
||||
// If perModuleOnly then skip whole program
|
||||
// (it.dce => runIrDce) && (perModuleOnly => it.perModule)
|
||||
val translationModes = TranslationMode.values()
|
||||
.filter { (!it.dce || runIrDce) && (!perModuleOnly || it.perModule) }
|
||||
.filter { (it.dce || !onlyIrDce) && (!it.dce || runIrDce) && (!perModuleOnly || it.perModule) }
|
||||
.filter { it.dce == it.minimizedMemberNames }
|
||||
.toSet()
|
||||
val compilationOut = transformer.generateModule(loweredIr.allModules, translationModes, false)
|
||||
|
||||
@@ -33,8 +33,9 @@ class JsMinifierRunner(testServices: TestServices) : AbstractJsArtifactsCollecto
|
||||
val dontRunGeneratedCode = globalDirectives[JsEnvironmentConfigurationDirectives.DONT_RUN_GENERATED_CODE]
|
||||
.contains(testServices.defaultsProvider.defaultTargetBackend?.name)
|
||||
val esModules = JsEnvironmentConfigurationDirectives.ES_MODULES in globalDirectives
|
||||
val onlyIrDce = JsEnvironmentConfigurationDirectives.ONLY_IR_DCE in globalDirectives
|
||||
|
||||
if (dontRunGeneratedCode || esModules) return
|
||||
if (dontRunGeneratedCode || esModules || onlyIrDce) return
|
||||
|
||||
val allJsFiles = getOnlyJsFilesForRunner(testServices, modulesToArtifact)
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@ import java.io.File
|
||||
class NodeJsGeneratorHandler(testServices: TestServices) : AbstractJsArtifactsCollector(testServices) {
|
||||
override fun processAfterAllModules(someAssertionWasFailed: Boolean) {
|
||||
if (someAssertionWasFailed) return
|
||||
val allJsFiles = getOnlyJsFilesForRunner(testServices, modulesToArtifact)
|
||||
|
||||
val globalDirectives = testServices.moduleStructure.allDirectives
|
||||
|
||||
@@ -31,8 +30,11 @@ class NodeJsGeneratorHandler(testServices: TestServices) : AbstractJsArtifactsCo
|
||||
val generateNodeJsRunner = JsEnvironmentConfigurationDirectives.GENERATE_NODE_JS_RUNNER in globalDirectives
|
||||
val skipNodeJs = JsEnvironmentConfigurationDirectives.SKIP_NODE_JS in globalDirectives
|
||||
val esModules = JsEnvironmentConfigurationDirectives.ES_MODULES in globalDirectives
|
||||
val onlyIrDce = JsEnvironmentConfigurationDirectives.ONLY_IR_DCE in globalDirectives
|
||||
|
||||
if (dontRunGeneratedCode || !generateNodeJsRunner || skipNodeJs || esModules) return
|
||||
if (dontRunGeneratedCode || !generateNodeJsRunner || skipNodeJs || esModules || onlyIrDce) return
|
||||
|
||||
val allJsFiles = getOnlyJsFilesForRunner(testServices, modulesToArtifact)
|
||||
|
||||
val mainModuleName = getMainModuleName(testServices)
|
||||
val outputDir = File(JsEnvironmentConfigurator.getJsArtifactsOutputDir(testServices).absolutePath)
|
||||
|
||||
@@ -136,10 +136,14 @@ fun getAllFilesForRunner(
|
||||
val artifactsPaths = modulesToArtifact.values.map { it.outputFile.absolutePath }.filter { !File(it).isDirectory }
|
||||
val allJsFiles = additionalFiles + inputJsFilesBefore +artifactsPaths + commonFiles + additionalMainFiles + inputJsFilesAfter
|
||||
|
||||
val result = mutableMapOf(TranslationMode.FULL to allJsFiles)
|
||||
val result = mutableMapOf<TranslationMode, List<String>>()
|
||||
|
||||
val globalDirectives = testServices.moduleStructure.allDirectives
|
||||
val runIrDce = JsEnvironmentConfigurationDirectives.RUN_IR_DCE in globalDirectives
|
||||
val onlyIrDce = JsEnvironmentConfigurationDirectives.ONLY_IR_DCE in globalDirectives
|
||||
if (!onlyIrDce) {
|
||||
result[TranslationMode.FULL] = allJsFiles
|
||||
}
|
||||
if (runIrDce) {
|
||||
val dceJsFiles = artifactsPaths.map { it.replace(outputDir.absolutePath, dceOutputDir.absolutePath) }
|
||||
val dceAllJsFiles = additionalFiles + inputJsFilesBefore + dceJsFiles + commonFiles + additionalMainFiles + inputJsFilesAfter
|
||||
|
||||
@@ -6797,6 +6797,16 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("js/js.translator/testData/box/keep")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class Keep {
|
||||
@Test
|
||||
public void testAllFilesPresentInKeep() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/keep"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS, true);
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("js/js.translator/testData/box/kotlin.test")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
|
||||
+40
@@ -7269,6 +7269,46 @@ public class FirJsTestGenerated extends AbstractFirJsTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("js/js.translator/testData/box/keep")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class Keep {
|
||||
@Test
|
||||
public void testAllFilesPresentInKeep() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/keep"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS_IR, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("keepClass.kt")
|
||||
public void testKeepClass() throws Exception {
|
||||
runTest("js/js.translator/testData/box/keep/keepClass.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("keepMethod.kt")
|
||||
public void testKeepMethod() throws Exception {
|
||||
runTest("js/js.translator/testData/box/keep/keepMethod.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("keepNestedClass.kt")
|
||||
public void testKeepNestedClass() throws Exception {
|
||||
runTest("js/js.translator/testData/box/keep/keepNestedClass.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("keepNestedClassIfKeptTopLevelClass.kt")
|
||||
public void testKeepNestedClassIfKeptTopLevelClass() throws Exception {
|
||||
runTest("js/js.translator/testData/box/keep/keepNestedClassIfKeptTopLevelClass.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("keepOverriddenMethod.kt")
|
||||
public void testKeepOverriddenMethod() throws Exception {
|
||||
runTest("js/js.translator/testData/box/keep/keepOverriddenMethod.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("js/js.translator/testData/box/kotlin.test")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
|
||||
+40
@@ -7269,6 +7269,46 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("js/js.translator/testData/box/keep")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class Keep {
|
||||
@Test
|
||||
public void testAllFilesPresentInKeep() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/keep"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS_IR, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("keepClass.kt")
|
||||
public void testKeepClass() throws Exception {
|
||||
runTest("js/js.translator/testData/box/keep/keepClass.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("keepMethod.kt")
|
||||
public void testKeepMethod() throws Exception {
|
||||
runTest("js/js.translator/testData/box/keep/keepMethod.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("keepNestedClass.kt")
|
||||
public void testKeepNestedClass() throws Exception {
|
||||
runTest("js/js.translator/testData/box/keep/keepNestedClass.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("keepNestedClassIfKeptTopLevelClass.kt")
|
||||
public void testKeepNestedClassIfKeptTopLevelClass() throws Exception {
|
||||
runTest("js/js.translator/testData/box/keep/keepNestedClassIfKeptTopLevelClass.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("keepOverriddenMethod.kt")
|
||||
public void testKeepOverriddenMethod() throws Exception {
|
||||
runTest("js/js.translator/testData/box/keep/keepOverriddenMethod.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("js/js.translator/testData/box/kotlin.test")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
// TARGET_BACKEND: JS_IR
|
||||
// ONLY_IR_DCE
|
||||
// RUN_PLAIN_BOX_FUNCTION
|
||||
// INFER_MAIN_MODULE
|
||||
// KEEP: A
|
||||
|
||||
// MODULE: keep_class
|
||||
// FILE: lib.kt
|
||||
|
||||
class A {
|
||||
fun foo(): String {
|
||||
return "foo"
|
||||
}
|
||||
|
||||
fun bar(): String {
|
||||
return "bar"
|
||||
}
|
||||
}
|
||||
|
||||
@JsExport
|
||||
fun bar(): A {
|
||||
return A()
|
||||
}
|
||||
|
||||
// FILE: test.js
|
||||
function box() {
|
||||
var a = this["keep_class"].bar()
|
||||
|
||||
if (a.foo_26di_k$() != "foo") return "fail 1"
|
||||
if (a.bar_232r_k$() != "bar") return "fail 2"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
// TARGET_BACKEND: JS_IR
|
||||
// ONLY_IR_DCE
|
||||
// RUN_PLAIN_BOX_FUNCTION
|
||||
// INFER_MAIN_MODULE
|
||||
// KEEP: A.foo
|
||||
|
||||
// MODULE: keep_method
|
||||
// FILE: lib.kt
|
||||
|
||||
class A {
|
||||
fun foo(): String {
|
||||
return "foo"
|
||||
}
|
||||
|
||||
fun bar(): String {
|
||||
return "bar"
|
||||
}
|
||||
}
|
||||
|
||||
@JsExport
|
||||
fun bar(): A {
|
||||
return A()
|
||||
}
|
||||
|
||||
// FILE: test.js
|
||||
function box() {
|
||||
var a = this["keep_method"].bar()
|
||||
|
||||
if (a.foo_26di_k$() != "foo") return "fail 1"
|
||||
if (typeof a.bar_232r_k$ !== "undefined") return "fail 2"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
// TARGET_BACKEND: JS_IR
|
||||
// ONLY_IR_DCE
|
||||
// RUN_PLAIN_BOX_FUNCTION
|
||||
// INFER_MAIN_MODULE
|
||||
// KEEP: A.B
|
||||
|
||||
// MODULE: keep_nested_class
|
||||
// FILE: lib.kt
|
||||
|
||||
class A {
|
||||
fun foo(): String {
|
||||
return "foo"
|
||||
}
|
||||
|
||||
fun bar(): String {
|
||||
return "bar"
|
||||
}
|
||||
|
||||
class B {
|
||||
fun baz() = "baz"
|
||||
}
|
||||
}
|
||||
|
||||
@JsExport
|
||||
fun barA(): A {
|
||||
return A()
|
||||
}
|
||||
|
||||
@JsExport
|
||||
fun bar(): A.B {
|
||||
return A.B()
|
||||
}
|
||||
|
||||
// FILE: test.js
|
||||
function box() {
|
||||
var a = this["keep_nested_class"].barA()
|
||||
var b = this["keep_nested_class"].bar()
|
||||
|
||||
if (typeof a.foo_26di_k$ !== "undefined") return "fail 1"
|
||||
if (typeof a.bar_232r_k$ !== "undefined") return "fail 2"
|
||||
if (b.baz_232z_k$() != "baz") return "fail 3"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
// TARGET_BACKEND: JS_IR
|
||||
// ONLY_IR_DCE
|
||||
// RUN_PLAIN_BOX_FUNCTION
|
||||
// INFER_MAIN_MODULE
|
||||
// KEEP: A
|
||||
|
||||
// MODULE: keep_nested_class_if_kept_top_level_class
|
||||
// FILE: lib.kt
|
||||
|
||||
class A {
|
||||
fun foo(): String {
|
||||
return "foo"
|
||||
}
|
||||
|
||||
fun bar(): String {
|
||||
return "bar"
|
||||
}
|
||||
|
||||
class B {
|
||||
fun baz() = "baz"
|
||||
}
|
||||
}
|
||||
|
||||
@JsExport
|
||||
fun barA(): A {
|
||||
return A()
|
||||
}
|
||||
|
||||
@JsExport
|
||||
fun bar(): A.B {
|
||||
return A.B()
|
||||
}
|
||||
|
||||
// FILE: test.js
|
||||
function box() {
|
||||
var a = this["keep_nested_class_if_kept_top_level_class"].barA()
|
||||
var b = this["keep_nested_class_if_kept_top_level_class"].bar()
|
||||
|
||||
if (a.foo_26di_k$() != "foo") return "fail 1"
|
||||
if (a.bar_232r_k$() != "bar") return "fail 2"
|
||||
if (b.baz_232z_k$() != "baz") return "fail 3"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
// TARGET_BACKEND: JS_IR
|
||||
// ONLY_IR_DCE
|
||||
// RUN_PLAIN_BOX_FUNCTION
|
||||
// INFER_MAIN_MODULE
|
||||
// KEEP: A.foo
|
||||
|
||||
// MODULE: keep_overridden_method
|
||||
// FILE: lib.kt
|
||||
|
||||
open class A {
|
||||
open fun foo(): String {
|
||||
return "foo"
|
||||
}
|
||||
|
||||
open fun bar(): String {
|
||||
return "bar"
|
||||
}
|
||||
}
|
||||
|
||||
open class B : A() {
|
||||
override fun foo(): String {
|
||||
return super.foo() + "!"
|
||||
}
|
||||
}
|
||||
|
||||
@JsExport
|
||||
fun bar(): B {
|
||||
return B()
|
||||
}
|
||||
|
||||
// FILE: test.js
|
||||
function box() {
|
||||
var b = this["keep_overridden_method"].bar()
|
||||
|
||||
if (b.foo_26di_k$() != "foo!") return "fail 1"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
Reference in New Issue
Block a user