diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsClassGenerator.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsClassGenerator.kt index 58dc913e054..843b9838f75 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsClassGenerator.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsClassGenerator.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs +import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.DescriptorVisibilities import org.jetbrains.kotlin.ir.backend.js.export.isExported import org.jetbrains.kotlin.ir.backend.js.utils.* @@ -142,6 +143,10 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo return this.overriddenSymbols.any { it.owner.overridesExternal() } } + private fun IrClass.shouldCopyFrom(): Boolean { + return isInterface && !isEffectivelyExternal() + } + private fun generateMemberFunction(declaration: IrSimpleFunction): Pair { val memberName = context.getNameForMemberFunction(declaration.realOverrideTarget) val memberRef = JsNameRef(memberName, classPrototypeRef) @@ -158,10 +163,10 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo // interface II : I // II.prototype.foo = I.prototype.foo if (!irClass.isInterface) { - declaration.realOverrideTarget.let { it -> + declaration.realOverrideTarget.let { val implClassDeclaration = it.parent as IrClass - if (!implClassDeclaration.defaultType.isAny() && !it.isEffectivelyExternal()) { + if (implClassDeclaration.shouldCopyFrom()) { val implMethodName = context.getNameForMemberFunction(it) val implClassName = context.getNameForClass(implClassDeclaration) diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrBoxJsES6TestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrBoxJsES6TestGenerated.java index 52090674916..ef593b685e6 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrBoxJsES6TestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrBoxJsES6TestGenerated.java @@ -3470,6 +3470,11 @@ public class IrBoxJsES6TestGenerated extends AbstractIrBoxJsES6Test { runTest("js/js.translator/testData/box/inheritance/baseClassDefinedAfterDerived.kt"); } + @TestMetadata("childPrototype.kt") + public void testChildPrototype() throws Exception { + runTest("js/js.translator/testData/box/inheritance/childPrototype.kt"); + } + @TestMetadata("complexInitializationOrder.kt") public void testComplexInitializationOrder() throws Exception { runTest("js/js.translator/testData/box/inheritance/complexInitializationOrder.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrBoxJsTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrBoxJsTestGenerated.java index 9bc0e102973..eb89de9f159 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrBoxJsTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrBoxJsTestGenerated.java @@ -3470,6 +3470,11 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest { runTest("js/js.translator/testData/box/inheritance/baseClassDefinedAfterDerived.kt"); } + @TestMetadata("childPrototype.kt") + public void testChildPrototype() throws Exception { + runTest("js/js.translator/testData/box/inheritance/childPrototype.kt"); + } + @TestMetadata("complexInitializationOrder.kt") public void testComplexInitializationOrder() throws Exception { runTest("js/js.translator/testData/box/inheritance/complexInitializationOrder.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java index c85dde4dc75..4e8759e734f 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java @@ -3485,6 +3485,11 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest { runTest("js/js.translator/testData/box/inheritance/baseClassDefinedAfterDerived.kt"); } + @TestMetadata("childPrototype.kt") + public void testChildPrototype() throws Exception { + runTest("js/js.translator/testData/box/inheritance/childPrototype.kt"); + } + @TestMetadata("complexInitializationOrder.kt") public void testComplexInitializationOrder() throws Exception { runTest("js/js.translator/testData/box/inheritance/complexInitializationOrder.kt"); diff --git a/js/js.translator/testData/box/inheritance/childPrototype.kt b/js/js.translator/testData/box/inheritance/childPrototype.kt new file mode 100644 index 00000000000..60ee1821c8d --- /dev/null +++ b/js/js.translator/testData/box/inheritance/childPrototype.kt @@ -0,0 +1,32 @@ +// EXPECTED_REACHABLE_NODES: 1251 + +// KT-41227 + +var result = "" + +open class A { + @JsName("foo") + fun foo() { result += "A" } + @JsName("boo") + open fun boo() { result += "FAIL" } +} + +class B : A() { + override fun boo() { result += "B" } + @JsName("bar") + fun bar() { result += "C" } +} + +fun box(): String { + val b = B() + b.boo() + b.foo() + b.bar() + if (result != "BAC") return "FAIL: $result" + + return "OK" +} + +// PROPERTY_WRITE_COUNT: name=foo count=1 +// PROPERTY_WRITE_COUNT: name=boo count=2 +// PROPERTY_WRITE_COUNT: name=bar count=1 \ No newline at end of file