From 6c051b2be4d0e3bd18e74ce8bdde5e99a46df0d2 Mon Sep 17 00:00:00 2001 From: Ilya Goncharov Date: Wed, 3 Feb 2021 19:24:26 +0300 Subject: [PATCH] [JS IR] Override method are not exported [JS IR] Add test with jsexport overrides not js export method with stable name ^KT-44616 fixed --- .../backend/js/export/ExportModelGenerator.kt | 26 +++++++++--- .../semantics/IrBoxJsES6TestGenerated.java | 10 +++++ .../ir/semantics/IrBoxJsTestGenerated.java | 10 +++++ .../js/test/semantics/BoxJsTestGenerated.java | 10 +++++ ...rriddenExternalMethodWithSameNameMethod.kt | 38 +++++++++++++++++ ...nExternalMethodWithSameStableNameMethod.kt | 41 +++++++++++++++++++ 6 files changed, 130 insertions(+), 5 deletions(-) create mode 100644 js/js.translator/testData/box/export/overriddenExternalMethodWithSameNameMethod.kt create mode 100644 js/js.translator/testData/box/export/overriddenExternalMethodWithSameStableNameMethod.kt diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/export/ExportModelGenerator.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/export/ExportModelGenerator.kt index abbe7072fc8..b4f51ffc777 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/export/ExportModelGenerator.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/export/ExportModelGenerator.kt @@ -8,10 +8,12 @@ package org.jetbrains.kotlin.ir.backend.js.export import org.jetbrains.kotlin.backend.common.ir.isExpect import org.jetbrains.kotlin.config.CommonConfigurationKeys import org.jetbrains.kotlin.descriptors.ClassKind -import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.DescriptorVisibilities -import org.jetbrains.kotlin.ir.backend.js.* -import org.jetbrains.kotlin.ir.backend.js.lower.ES6AddInternalParametersToConstructorPhase.* +import org.jetbrains.kotlin.descriptors.Modality +import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext +import org.jetbrains.kotlin.ir.backend.js.JsLoweredDeclarationOrigin +import org.jetbrains.kotlin.ir.backend.js.lower.ES6AddInternalParametersToConstructorPhase.ES6_INIT_BOX_PARAMETER +import org.jetbrains.kotlin.ir.backend.js.lower.ES6AddInternalParametersToConstructorPhase.ES6_RESULT_TYPE_PARAMETER import org.jetbrains.kotlin.ir.backend.js.utils.getJsNameOrKotlinName import org.jetbrains.kotlin.ir.backend.js.utils.isJsExport import org.jetbrains.kotlin.ir.backend.js.utils.sanitizeName @@ -80,7 +82,7 @@ class ExportModelGenerator(val context: JsIrBackendContext) { private fun exportConstructor(constructor: IrConstructor): ExportedDeclaration? { if (!constructor.isPrimary) return null val allValueParameters = listOfNotNull(constructor.extensionReceiverParameter) + - constructor.valueParameters.filterNot { it.origin === ES6_RESULT_TYPE_PARAMETER || it.origin === ES6_INIT_BOX_PARAMETER } + constructor.valueParameters.filterNot { it.origin === ES6_RESULT_TYPE_PARAMETER || it.origin === ES6_INIT_BOX_PARAMETER } return ExportedConstructor(allValueParameters.map { exportParameter(it) }) } @@ -192,7 +194,7 @@ class ExportModelGenerator(val context: JsIrBackendContext) { ?.let { exportType(it).takeIf { it !is ExportedType.ErrorType } } val superInterfaces = klass.superTypes - .filter {it.classifierOrFail.isInterface } + .filter { it.classifierOrFail.isInterface } .map { exportType(it) } .filter { it !is ExportedType.ErrorType } @@ -398,6 +400,16 @@ private fun shouldDeclarationBeExported(declaration: IrDeclarationWithName, cont if (context?.additionalExportedDeclarations?.contains(declaration) == true) return true + if (declaration is IrSimpleFunction) { + val overriddenNonEmpty = declaration + .overriddenSymbols + .isNotEmpty() + + if (overriddenNonEmpty) { + return declaration.isOverriddenExported(context) + } + } + if (declaration.isJsExport()) return true @@ -408,6 +420,10 @@ private fun shouldDeclarationBeExported(declaration: IrDeclarationWithName, cont } } +private fun IrSimpleFunction.isOverriddenExported(context: JsIrBackendContext?): Boolean = + overriddenSymbols + .any { shouldDeclarationBeExported(it.owner, context) } + fun IrDeclaration.isExported(context: JsIrBackendContext?): Boolean { val candidate = getExportCandidate(this) ?: return false return shouldDeclarationBeExported(candidate, context) diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrBoxJsES6TestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrBoxJsES6TestGenerated.java index a2520f7fae2..6bab51ea5c6 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrBoxJsES6TestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrBoxJsES6TestGenerated.java @@ -1632,6 +1632,16 @@ public class IrBoxJsES6TestGenerated extends AbstractIrBoxJsES6Test { runTest("js/js.translator/testData/box/export/nonIndetifierModuleName.kt"); } + @TestMetadata("overriddenExternalMethodWithSameNameMethod.kt") + public void testOverriddenExternalMethodWithSameNameMethod() throws Exception { + runTest("js/js.translator/testData/box/export/overriddenExternalMethodWithSameNameMethod.kt"); + } + + @TestMetadata("overriddenExternalMethodWithSameStableNameMethod.kt") + public void testOverriddenExternalMethodWithSameStableNameMethod() throws Exception { + runTest("js/js.translator/testData/box/export/overriddenExternalMethodWithSameStableNameMethod.kt"); + } + @TestMetadata("overridenMethod.kt") public void testOverridenMethod() throws Exception { runTest("js/js.translator/testData/box/export/overridenMethod.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrBoxJsTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrBoxJsTestGenerated.java index 6a722ac2d4b..11901a52caa 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrBoxJsTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrBoxJsTestGenerated.java @@ -1632,6 +1632,16 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest { runTest("js/js.translator/testData/box/export/nonIndetifierModuleName.kt"); } + @TestMetadata("overriddenExternalMethodWithSameNameMethod.kt") + public void testOverriddenExternalMethodWithSameNameMethod() throws Exception { + runTest("js/js.translator/testData/box/export/overriddenExternalMethodWithSameNameMethod.kt"); + } + + @TestMetadata("overriddenExternalMethodWithSameStableNameMethod.kt") + public void testOverriddenExternalMethodWithSameStableNameMethod() throws Exception { + runTest("js/js.translator/testData/box/export/overriddenExternalMethodWithSameStableNameMethod.kt"); + } + @TestMetadata("overridenMethod.kt") public void testOverridenMethod() throws Exception { runTest("js/js.translator/testData/box/export/overridenMethod.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java index 4bffcc65168..da503f4f0b0 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java @@ -1637,6 +1637,16 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest { runTest("js/js.translator/testData/box/export/nonIndetifierModuleName.kt"); } + @TestMetadata("overriddenExternalMethodWithSameNameMethod.kt") + public void testOverriddenExternalMethodWithSameNameMethod() throws Exception { + runTest("js/js.translator/testData/box/export/overriddenExternalMethodWithSameNameMethod.kt"); + } + + @TestMetadata("overriddenExternalMethodWithSameStableNameMethod.kt") + public void testOverriddenExternalMethodWithSameStableNameMethod() throws Exception { + runTest("js/js.translator/testData/box/export/overriddenExternalMethodWithSameStableNameMethod.kt"); + } + @TestMetadata("overridenMethod.kt") public void testOverridenMethod() throws Exception { runTest("js/js.translator/testData/box/export/overridenMethod.kt"); diff --git a/js/js.translator/testData/box/export/overriddenExternalMethodWithSameNameMethod.kt b/js/js.translator/testData/box/export/overriddenExternalMethodWithSameNameMethod.kt new file mode 100644 index 00000000000..bc9a6222260 --- /dev/null +++ b/js/js.translator/testData/box/export/overriddenExternalMethodWithSameNameMethod.kt @@ -0,0 +1,38 @@ +// IGNORE_BACKEND: JS +// RUN_PLAIN_BOX_FUNCTION +// INFER_MAIN_MODULE + +// MODULE: overriden-external-method-with-same-name-method +// FILE: lib.kt +external abstract class Foo { + abstract fun o(): String +} + +abstract class Bar : Foo() { + abstract fun String.o(): String + + override fun o(): String { + return "O".o() + } +} + +@JsExport +class Baz : Bar() { + override fun String.o(): String { + return this + } +} + +// FILE: test.js +function Foo() {} +Foo.prototype.k = function() { + return "K" +} + +function box() { + return test(new this["overriden-external-method-with-same-name-method"].Baz()); +} + +function test(foo) { + return foo.o() + foo.k() +} \ No newline at end of file diff --git a/js/js.translator/testData/box/export/overriddenExternalMethodWithSameStableNameMethod.kt b/js/js.translator/testData/box/export/overriddenExternalMethodWithSameStableNameMethod.kt new file mode 100644 index 00000000000..3bc6dcae649 --- /dev/null +++ b/js/js.translator/testData/box/export/overriddenExternalMethodWithSameStableNameMethod.kt @@ -0,0 +1,41 @@ +// IGNORE_BACKEND: JS +// RUN_PLAIN_BOX_FUNCTION +// INFER_MAIN_MODULE + +// MODULE: overriden-external-method-with-same-stable-name-method +// FILE: lib.kt +external abstract class Foo { + abstract fun o(): String +} + +abstract class Bar : Foo() { + @JsName("oStable") + abstract fun String.o(): String + + override fun o(): String { + return "O".o() + } +} + +@JsExport +class Baz : Bar() { + override fun String.o(): String { + return this + } +} + +// FILE: test.js +function Foo() {} +Foo.prototype.k = function() { + return "K" +} + +function box() { + return test(new this["overriden-external-method-with-same-stable-name-method"].Baz()); +} + +function test(foo) { + const oStable = foo.oStable("OK") + if (oStable !== "OK") return "false: " + oStable + return foo.o() + foo.k() +} \ No newline at end of file