From 9946feb66ce89d5f619497c5446ad3fb0b8cefd5 Mon Sep 17 00:00:00 2001 From: Roman Artemev Date: Thu, 21 Nov 2019 11:20:50 +0300 Subject: [PATCH] [JS IR] Fix name clash between class members defined on prototype - Fixes [KT-33327] --- .../backend/js/utils/StableNamesCollector.kt | 20 +++++++++++--- .../codegen/box/lazyCodegen/ifElse.kt | 2 -- compiler/testData/codegen/box/unit/ifElse.kt | 2 -- .../ir/semantics/IrBoxJsTestGenerated.java | 5 ++++ .../js/test/semantics/BoxJsTestGenerated.java | 5 ++++ .../box/inline/thisImplicitlyCaptured.kt | 3 --- .../box/propertyAccess/publicNameClash.kt | 27 +++++++++++++++++++ 7 files changed, 53 insertions(+), 11 deletions(-) create mode 100644 js/js.translator/testData/box/propertyAccess/publicNameClash.kt diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/StableNamesCollector.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/StableNamesCollector.kt index e49c05fc615..835acdb6f7e 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/StableNamesCollector.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/StableNamesCollector.kt @@ -9,6 +9,7 @@ import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.declarations.IrConstructor import org.jetbrains.kotlin.ir.declarations.IrDeclaration import org.jetbrains.kotlin.ir.declarations.IrDeclarationWithName +import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction import org.jetbrains.kotlin.ir.util.isEffectivelyExternal import org.jetbrains.kotlin.ir.util.isPropertyAccessor import org.jetbrains.kotlin.ir.util.isPropertyField @@ -35,8 +36,10 @@ class StableNamesCollector : IrElementVisitorVoid { if (declaration !is IrDeclarationWithName) return + val isStatic = declaration.hasStaticDispatch() + val scope = - if (declaration.hasStaticDispatch()) + if (isStatic) staticNames else memberNames @@ -45,13 +48,22 @@ class StableNamesCollector : IrElementVisitorVoid { if (declaration.isEffectivelyExternal()) stableNameForExternalDeclaration(declaration) else - stableNameForNonExternalDeclaration(declaration) + stableNameForNonExternalDeclaration(declaration, isStatic) scope.addIfNotNull(stableName) } - private fun stableNameForNonExternalDeclaration(declaration: IrDeclarationWithName): String? = - declaration.getJsName() + private fun stableNameForNonExternalDeclaration(declaration: IrDeclarationWithName, isStatic: Boolean): String? = + declaration.getJsName() ?: run { + // TODO: since following code affects local variable naming some weird behaviour of js("..") is possible + // Remove check once 1. `js` function is re-designed and re-implemented, 2. JsExport is properly implemented + if (!isStatic) { + // Make sure property defined on prototype has stable name + val simpleFunction = declaration as? IrSimpleFunction + val property = simpleFunction?.correspondingPropertySymbol?.owner + property?.getJsNameOrKotlinName()?.identifier + } else null + } private fun stableNameForExternalDeclaration(declaration: IrDeclarationWithName): String? { if (declaration.isPropertyAccessor || diff --git a/compiler/testData/codegen/box/lazyCodegen/ifElse.kt b/compiler/testData/codegen/box/lazyCodegen/ifElse.kt index 1bde5303a08..fa4f250e824 100644 --- a/compiler/testData/codegen/box/lazyCodegen/ifElse.kt +++ b/compiler/testData/codegen/box/lazyCodegen/ifElse.kt @@ -1,6 +1,4 @@ // IGNORE_BACKEND_FIR: JVM_IR -// Name clashes -// IGNORE_BACKEND: JS_IR class A (val p: String, p1: String, p2: String) { diff --git a/compiler/testData/codegen/box/unit/ifElse.kt b/compiler/testData/codegen/box/unit/ifElse.kt index 9c6da8029a9..414339d4b3d 100644 --- a/compiler/testData/codegen/box/unit/ifElse.kt +++ b/compiler/testData/codegen/box/unit/ifElse.kt @@ -1,6 +1,4 @@ // IGNORE_BACKEND_FIR: JVM_IR -// Name clashes -// IGNORE_BACKEND: JS_IR class A (val p: String, p1: String, p2: String) { 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 8932a5d2fcb..3ad3351e8cc 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 @@ -6514,6 +6514,11 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest { runTest("js/js.translator/testData/box/propertyAccess/propertyAssignment.kt"); } + @TestMetadata("publicNameClash.kt") + public void testPublicNameClash() throws Exception { + runTest("js/js.translator/testData/box/propertyAccess/publicNameClash.kt"); + } + @TestMetadata("setter.kt") public void testSetter() throws Exception { runTest("js/js.translator/testData/box/propertyAccess/setter.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 ff8a1459721..54d333e8e93 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 @@ -6544,6 +6544,11 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest { runTest("js/js.translator/testData/box/propertyAccess/propertyAssignment.kt"); } + @TestMetadata("publicNameClash.kt") + public void testPublicNameClash() throws Exception { + runTest("js/js.translator/testData/box/propertyAccess/publicNameClash.kt"); + } + @TestMetadata("setter.kt") public void testSetter() throws Exception { runTest("js/js.translator/testData/box/propertyAccess/setter.kt"); diff --git a/js/js.translator/testData/box/inline/thisImplicitlyCaptured.kt b/js/js.translator/testData/box/inline/thisImplicitlyCaptured.kt index 52273ac2c3f..1bec4a53582 100644 --- a/js/js.translator/testData/box/inline/thisImplicitlyCaptured.kt +++ b/js/js.translator/testData/box/inline/thisImplicitlyCaptured.kt @@ -1,6 +1,3 @@ -// Name clashes -// IGNORE_BACKEND: JS_IR - // EXPECTED_REACHABLE_NODES: 1295 package foo diff --git a/js/js.translator/testData/box/propertyAccess/publicNameClash.kt b/js/js.translator/testData/box/propertyAccess/publicNameClash.kt new file mode 100644 index 00000000000..9c1d2be5768 --- /dev/null +++ b/js/js.translator/testData/box/propertyAccess/publicNameClash.kt @@ -0,0 +1,27 @@ +// EXPECTED_REACHABLE_NODES: 1284 + +// KT-33327 + +class C { + var foo: String = "FAIL1" + + fun foo(foo: String): C { + this.foo = foo + return this + } + + @JsName("_bar") + var bar: String = "FAIL2" + + fun bar(bar: String): C { + this.bar = bar + return this + } +} + +fun box(): String { + val c = C() + c.foo("O").bar("K") + + return c.foo + c.bar +} \ No newline at end of file