diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/DelegationTranslator.kt b/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/DelegationTranslator.kt index 938b30cfcc9..6271dca51c5 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/DelegationTranslator.kt +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/declaration/DelegationTranslator.kt @@ -62,7 +62,6 @@ class DelegationTranslator( } else { val classFqName = DescriptorUtils.getFqName(classDescriptor) - val typeFqName = DescriptorUtils.getFqName(descriptor) val idForMangling = classFqName.asString() val suggestedName = NameSuggestion.getStableMangledName(Namer.getDelegatePrefix(), idForMangling) val delegateName = context.getScopeForDescriptor(classDescriptor).declareFreshName("${suggestedName}_0") diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/functions/factories/TopLevelFIF.java b/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/functions/factories/TopLevelFIF.java index 149bb0fed18..dd233f1df55 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/functions/factories/TopLevelFIF.java +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/intrinsic/functions/factories/TopLevelFIF.java @@ -18,15 +18,12 @@ package org.jetbrains.kotlin.js.translate.intrinsic.functions.factories; import com.google.dart.compiler.backend.js.ast.JsExpression; import com.google.dart.compiler.backend.js.ast.JsInvocation; -import com.google.dart.compiler.backend.js.ast.JsNew; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.kotlin.builtins.PrimitiveType; import org.jetbrains.kotlin.descriptors.CallableDescriptor; import org.jetbrains.kotlin.descriptors.DeclarationDescriptor; import org.jetbrains.kotlin.descriptors.PropertyDescriptor; import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor; -import org.jetbrains.kotlin.js.descriptorUtils.DescriptorUtilsKt; import org.jetbrains.kotlin.js.patterns.DescriptorPredicate; import org.jetbrains.kotlin.js.patterns.NamePredicate; import org.jetbrains.kotlin.js.resolve.JsPlatform; @@ -38,7 +35,6 @@ import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils; import org.jetbrains.kotlin.js.translate.utils.BindingUtils; import org.jetbrains.kotlin.js.translate.utils.JsAstUtils; import org.jetbrains.kotlin.js.translate.utils.UtilsKt; -import org.jetbrains.kotlin.name.Name; import org.jetbrains.kotlin.psi.KtExpression; import org.jetbrains.kotlin.psi.KtQualifiedExpression; import org.jetbrains.kotlin.psi.KtReferenceExpression; @@ -52,8 +48,8 @@ import java.util.Map; import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.FQ_NAMES; import static org.jetbrains.kotlin.js.patterns.PatternBuilder.pattern; -import static org.jetbrains.kotlin.js.translate.intrinsic.functions.basic.FunctionIntrinsic.CallParametersAwareFunctionIntrinsic; import static org.jetbrains.kotlin.js.translate.context.Namer.getStableMangledNameForDescriptor; +import static org.jetbrains.kotlin.js.translate.intrinsic.functions.basic.FunctionIntrinsic.CallParametersAwareFunctionIntrinsic; public final class TopLevelFIF extends CompositeFIF { public static final DescriptorPredicate EQUALS_IN_ANY = pattern("kotlin", "Any", "equals"); diff --git a/js/js.translator/testData/box/expression/function/mangling.kt b/js/js.translator/testData/box/expression/function/mangling.kt index 11878735360..98df9032eee 100644 --- a/js/js.translator/testData/box/expression/function/mangling.kt +++ b/js/js.translator/testData/box/expression/function/mangling.kt @@ -161,72 +161,83 @@ fun test(expected: String, f: () -> Unit) { } } +val privateMangledRegex = Regex("baz_[0-9a-zA-Z]+\\\$_0") + +fun testMangledPrivate(f: () -> Unit) { + val actual = f.extractNames() + + if (!privateMangledRegex.matches(actual[1])) { + fail("Failed on '$testGroup' group: actual[1] = \"${actual[1]}\"\n actual = $actual, should look like 'baz__0'") + } + if ("_za3lpa\$" in actual[1]) { + fail("Failed on '$testGroup' group: actual[1] = \"${actual[1]}\"\n actual = $actual, should not contains 'za3lpa\$'") + } +} + public fun stable_mangled_baz(i: Int) { } val SIMPLE = "baz" -val SIMPLE1 = "${SIMPLE}_1" +val SIMPLE0 = "${SIMPLE}_0" val NATIVE = SIMPLE val STABLE = { stable_mangled_baz(0) }.extractNames()[1] fun box(): String { - // TODO: these tests are too fragile - testGroup = "Top Level" test(STABLE) { public_baz(0) } test(NATIVE) { public_baz("native") } - //test(SIMPLE1) { internal_baz(0) } - //test(NATIVE) { internal_baz("native") } - //test(SIMPLE1) { private_baz(0) } - //test(NATIVE) { private_baz("native") } + test(SIMPLE0) { internal_baz(0) } + test(NATIVE) { internal_baz("native") } + test(SIMPLE0) { private_baz(0) } + test(NATIVE) { private_baz("native") } testGroup = "Public Class" test(STABLE) { PublicClass().public_baz(0) } test(NATIVE) { PublicClass().public_baz("native") } - //test(SIMPLE1) { PublicClass().internal_baz(0) } - //test(NATIVE) { PublicClass().internal_baz("native") } - //test(SIMPLE1, PublicClass().call_private_baz) - //test(NATIVE, PublicClass().call_private_native_baz) + test(SIMPLE0) { PublicClass().internal_baz(0) } + test(NATIVE) { PublicClass().internal_baz("native") } + test(SIMPLE0, PublicClass().call_private_baz) + test(NATIVE, PublicClass().call_private_native_baz) testGroup = "Internal Class" - //test(SIMPLE1) { InternalClass().public_baz(0) } - //test(NATIVE) { InternalClass().public_baz("native") } - //test(SIMPLE1) { InternalClass().internal_baz(0) } - //test(NATIVE) { InternalClass().internal_baz("native") } - //test(SIMPLE1, InternalClass().call_private_baz) - //test(NATIVE, InternalClass().call_private_native_baz) + test(STABLE) { InternalClass().public_baz(0) } + test(NATIVE) { InternalClass().public_baz("native") } + test(SIMPLE0) { InternalClass().internal_baz(0) } + test(NATIVE) { InternalClass().internal_baz("native") } + test(SIMPLE0, InternalClass().call_private_baz) + test(NATIVE, InternalClass().call_private_native_baz) testGroup = "Private Class" - //test(SIMPLE1) { PrivateClass().public_baz(0) } - //test(NATIVE) { PrivateClass().public_baz("native") } - //test(SIMPLE1) { PrivateClass().internal_baz(0) } - //test(NATIVE) { PrivateClass().internal_baz("native") } - //test(SIMPLE1, PrivateClass().call_private_baz) - //test(NATIVE, PrivateClass().call_private_native_baz) + test(STABLE) { PrivateClass().public_baz(0) } + test(NATIVE) { PrivateClass().public_baz("native") } + test(SIMPLE0) { PrivateClass().internal_baz(0) } + test(NATIVE) { PrivateClass().internal_baz("native") } + test(SIMPLE0, PrivateClass().call_private_baz) + test(NATIVE, PrivateClass().call_private_native_baz) testGroup = "Open Public Class" test(STABLE) { OpenPublicClass().public_baz(0) } test(NATIVE) { OpenPublicClass().public_baz("native") } - //test(STABLE) { OpenPublicClass().internal_baz(0) } - //test(NATIVE) { OpenPublicClass().internal_baz("native") } - //test(STABLE, OpenPublicClass().call_private_baz) - //test(NATIVE, OpenPublicClass().call_private_native_baz) + testMangledPrivate { OpenPublicClass().internal_baz(0) } + test(NATIVE) { OpenPublicClass().internal_baz("native") } + testMangledPrivate(OpenPublicClass().call_private_baz) + test(NATIVE, OpenPublicClass().call_private_native_baz) testGroup = "Open Internal Class" - //test(STABLE) { OpenInternalClass().public_baz(0) } - //test(NATIVE) { OpenInternalClass().public_baz("native") } - //test(STABLE) { OpenInternalClass().internal_baz(0) } - //test(NATIVE) { OpenInternalClass().internal_baz("native") } - //test(STABLE, OpenInternalClass().call_private_baz) - //test(NATIVE, OpenInternalClass().call_private_native_baz) + test(STABLE) { OpenInternalClass().public_baz(0) } + test(NATIVE) { OpenInternalClass().public_baz("native") } + test(SIMPLE0) { OpenInternalClass().internal_baz(0) } + test(NATIVE) { OpenInternalClass().internal_baz("native") } + test(SIMPLE0, OpenInternalClass().call_private_baz) + test(NATIVE, OpenInternalClass().call_private_native_baz) testGroup = "Open Private Class" - //test(STABLE) { OpenPrivateClass().public_baz(0) } - //test(NATIVE) { OpenPrivateClass().public_baz("native") } - //test(STABLE) { OpenPrivateClass().internal_baz(0) } - //test(NATIVE) { OpenPrivateClass().internal_baz("native") } - //test(STABLE, OpenPrivateClass().call_private_baz) - //test(NATIVE, OpenPrivateClass().call_private_native_baz) + test(STABLE) { OpenPrivateClass().public_baz(0) } + test(NATIVE) { OpenPrivateClass().public_baz("native") } + test(SIMPLE0) { OpenPrivateClass().internal_baz(0) } + test(NATIVE) { OpenPrivateClass().internal_baz("native") } + test(SIMPLE0, OpenPrivateClass().call_private_baz) + test(NATIVE, OpenPrivateClass().call_private_native_baz) return "OK" } diff --git a/js/js.translator/testData/box/expression/function/manglingAnyMethods.kt b/js/js.translator/testData/box/expression/function/manglingAnyMethods.kt index 7f70920944a..762d61c3865 100644 --- a/js/js.translator/testData/box/expression/function/manglingAnyMethods.kt +++ b/js/js.translator/testData/box/expression/function/manglingAnyMethods.kt @@ -3,6 +3,9 @@ package foo public fun equals(a: Any?): Boolean = true public fun hashCode(): Int = 0 public fun toString(): String = "" +fun equals(a: Any?, b: Any?): Boolean = true +fun hashCode(i: Int): Int = 0 +fun toString(s: String): String = "" public class PublicClass { override fun equals(a: Any?): Boolean = this === a @@ -58,12 +61,12 @@ fun test(expected: String, f: () -> Unit) { } } -val SIMPLE_EQUALS = "equals" -val SIMPLE_HASH_CODE_1 = "hashCode_1" -val SIMPLE_TO_STRING_1 = "toString_1" val STABLE_EQUALS = { equals(0) }.extractNames()[1] val STABLE_HASH_CODE = { hashCode() }.extractNames()[1] val STABLE_TO_STRING = { toString() }.extractNames()[1] +val STABLE_EQUALS_2 = { equals(0, 0) }.extractNames()[1] +val STABLE_HASH_CODE_2 = { hashCode(0) }.extractNames()[1] +val STABLE_TO_STRING_2 = { toString("") }.extractNames()[1] fun box(): String { testGroup = "Public Class" @@ -75,17 +78,17 @@ fun box(): String { test(STABLE_EQUALS) { InternalClass().equals(0) } test(STABLE_HASH_CODE) { InternalClass().hashCode() } test(STABLE_TO_STRING) { InternalClass().toString() } - //test(SIMPLE_EQUALS) { InternalClass().equals(0, 1) } - //test(SIMPLE_HASH_CODE_1) { InternalClass().hashCode(2) } - //test(SIMPLE_TO_STRING_1) { InternalClass().toString("3") } + test(STABLE_EQUALS_2) { InternalClass().equals(0, 1) } + test(STABLE_HASH_CODE_2) { InternalClass().hashCode(2) } + test(STABLE_TO_STRING_2) { InternalClass().toString("3") } testGroup = "Private Class" test(STABLE_EQUALS) { PrivateClass().equals(0) } test(STABLE_HASH_CODE) { PrivateClass().hashCode() } test(STABLE_TO_STRING) { PrivateClass().toString() } - //test(SIMPLE_EQUALS) { PrivateClass().equals(0, 1) } - //test(SIMPLE_HASH_CODE_1) { PrivateClass().hashCode(2) } - //test(SIMPLE_TO_STRING_1) { PrivateClass().toString("3") } + test(STABLE_EQUALS_2) { PrivateClass().equals(0, 1) } + test(STABLE_HASH_CODE_2) { PrivateClass().hashCode(2) } + test(STABLE_TO_STRING_2) { PrivateClass().toString("3") } return "OK" } diff --git a/js/js.translator/testData/box/expression/function/manglingStability.kt b/js/js.translator/testData/box/expression/function/manglingStability.kt index 11aba29b43f..4065021c8f2 100644 --- a/js/js.translator/testData/box/expression/function/manglingStability.kt +++ b/js/js.translator/testData/box/expression/function/manglingStability.kt @@ -31,9 +31,9 @@ private fun private_foo(): Int = 1 private fun private_foo(i: Int): Int = 2 @native private fun private_boo(a: Array): String = "should be ignored" +private fun private_boo(): Int = 1 private fun private_boo(i: Int): Int = 2 private fun private_boo(s: String): Int = 3 -private fun private_boo(): Int = 1 val private_f = { private_foo() + private_foo(1) } val private_b = { private_boo() + private_boo(1) } @@ -56,12 +56,12 @@ val mixed_b = { mixed_boo() + mixed_boo(1) + mixed_boo("str") + mixed_boo("str", class TestInternal { - @JsName("foo") internal fun foo(): Int = 1 - @JsName("foo_2") internal fun foo(i: Int): Int = 2 + internal fun foo(): Int = 1 + internal fun foo(i: Int): Int = 2 - @JsName("boo_2") internal fun boo(i: Int): Int = 2 - @JsName("boo_3") internal fun boo(s: String): Int = 3 - @JsName("boo") internal fun boo(): Int = 1 + internal fun boo(): Int = 1 + internal fun boo(i: Int): Int = 2 + internal fun boo(s: String): Int = 3 } val internal_in_class_f = { TestInternal().foo() + TestInternal().foo(1) } @@ -85,9 +85,9 @@ class TestPrivate { private fun foo(): Int = 1 private fun foo(i: Int): Int = 2 + private fun boo(): Int = 1 private fun boo(i: Int): Int = 2 private fun boo(s: String): Int = 3 - private fun boo(): Int = 1 val f = { foo() + foo(1) } val b = { boo() + boo(1) } @@ -149,12 +149,12 @@ fun test(testName: String, ff: Any, fb: Any) { fun box(): String { test("internal", internal_f, internal_b) test("public", public_f, public_b) - //test("private", private_f, private_b) + test("private", private_f, private_b) test("mixed", mixed_f, mixed_b) test("internal_in_class", internal_in_class_f, internal_in_class_b) test("public_in_class", public_in_class_f, public_in_class_b) - //test("private_in_class", private_in_class_f, private_in_class_b) + test("private_in_class", private_in_class_f, private_in_class_b) test("mixed_in_class", mixed_in_class_f, mixed_in_class_b) test("public_ext_prop", public_ext_f, public_ext_b) diff --git a/js/js.translator/testData/box/multiModule/_common.kt b/js/js.translator/testData/box/multiModule/_common.kt new file mode 100644 index 00000000000..8cc2d5747cf --- /dev/null +++ b/js/js.translator/testData/box/multiModule/_common.kt @@ -0,0 +1,19 @@ +package helpers + +fun checkJsNames(base: String, o: Any) { + val regex = Regex("^$base(_[0-9a-zA-Z]+\\\$)?(_[0-9])?$") + + val properties = getAllProperties(o).filter { it.startsWith("$base") } + val distinctProperties = properties.mapNotNull { regex.match(it)?.groupValues?.get(1) }.distinct() + if (distinctProperties.size != 2) { + fail("Two distinct properties expected, ${properties.size} occurred: " + properties) + } +} + +fun getAllProperties(o: dynamic): Array = js(""" + var properties = []; + for (property in o) { + properties.push(property); + } + return properties; +""") \ No newline at end of file diff --git a/js/js.translator/testData/box/multiModule/privateInterfaceNameClash.kt b/js/js.translator/testData/box/multiModule/privateInterfaceNameClash.kt index 2318bb24c9e..2fc1e7e129e 100644 --- a/js/js.translator/testData/box/multiModule/privateInterfaceNameClash.kt +++ b/js/js.translator/testData/box/multiModule/privateInterfaceNameClash.kt @@ -24,6 +24,7 @@ package main import lib1.A import lib2.B +import helpers.checkJsNames class Derived1 : A, B { override fun bar() = super.bar() @@ -33,13 +34,6 @@ class Derived2 : A, B { override fun bar() = super.bar() } -// NOTE. This test is fragile, it may fail due to unexpected (and correct) changes in algorithm that assigns -// unique identifiers to non-public declarations. However, we don't see any way of doing such test so that -// it won't report false positives eventually. So be patient and just update this test whenever you changed -// algorithm of assigning unique identifiers. -// Please, check that A.foo and B.foo have different JS names. -private fun checkJsNames(o: dynamic): Boolean = "foo_2pru9n\$_0" in o && "foo_2psha1\$_0" in o - fun box(): String { val a = Derived1() if (a.bar() != "A.foo") return "fail1: ${a.bar()}" @@ -47,8 +41,8 @@ fun box(): String { val b = Derived2() if (b.bar() != "B.foo") return "fail2: ${b.bar()}" - if (!checkJsNames(a)) return "fail3" - if (!checkJsNames(b)) return "fail4" + checkJsNames("foo", a) + checkJsNames("foo", b) return "OK" } \ No newline at end of file diff --git a/js/js.translator/testData/box/multiModule/privateNameClash.kt b/js/js.translator/testData/box/multiModule/privateNameClash.kt index b4cc23089d7..d9a4a6f64a6 100644 --- a/js/js.translator/testData/box/multiModule/privateNameClash.kt +++ b/js/js.translator/testData/box/multiModule/privateNameClash.kt @@ -24,6 +24,7 @@ package main import lib.A import lib.check +import helpers.checkJsNames class B : A() { private var x = 42 @@ -31,13 +32,6 @@ class B : A() { fun bar() = x } -// NOTE. This test is fragile, it may fail due to unexpected (and correct) changes in algorithm that assigns -// unique identifiers to non-public declarations. However, we don't see any way of doing such test so that -// it won't report false positives eventually. So be patient and just update this test whenever you changed -// algorithm of assigning unique identifiers. -// Please, check that A.x and B.x have different JS names. -private fun checkJsNames(o: dynamic): Boolean = "x_i8qwny\$_0" in o && "x_0" in o - fun box(): String { if (!check()) return "check failed: did not compile against old library" @@ -47,7 +41,7 @@ fun box(): String { val b = B() if (b.foo() != 23) return "fail2: ${b.foo()}" if (b.bar() != 42) return "fail3: ${b.bar()}" - if (!checkJsNames(b)) return "fail4" + checkJsNames("x", b) return "OK" } \ No newline at end of file