JS backend: fixed using the stable mangling for extra cases.
This commit is contained in:
@@ -113,6 +113,10 @@ public class FunctionTest extends AbstractExpressionTest {
|
|||||||
fooBoxTest();
|
fooBoxTest();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testMangling() throws Exception {
|
||||||
|
checkFooBoxIsOk();
|
||||||
|
}
|
||||||
|
|
||||||
public void testManglingStability() throws Exception {
|
public void testManglingStability() throws Exception {
|
||||||
checkFooBoxIsOk();
|
checkFooBoxIsOk();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ import java.util.List;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.*;
|
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.*;
|
||||||
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.getFqName;
|
|
||||||
|
|
||||||
public final class JsDescriptorUtils {
|
public final class JsDescriptorUtils {
|
||||||
// TODO: maybe we should use external annotations or something else.
|
// TODO: maybe we should use external annotations or something else.
|
||||||
@@ -98,6 +97,10 @@ public final class JsDescriptorUtils {
|
|||||||
return (functionDescriptor.getReceiverParameter() != null);
|
return (functionDescriptor.getReceiverParameter() != null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isOverride(@NotNull CallableMemberDescriptor descriptor) {
|
||||||
|
return !descriptor.getOverriddenDescriptors().isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
//TODO: why callable descriptor
|
//TODO: why callable descriptor
|
||||||
@Nullable
|
@Nullable
|
||||||
public static DeclarationDescriptor getExpectedThisDescriptor(@NotNull CallableDescriptor callableDescriptor) {
|
public static DeclarationDescriptor getExpectedThisDescriptor(@NotNull CallableDescriptor callableDescriptor) {
|
||||||
|
|||||||
@@ -148,22 +148,44 @@ public final class TranslationUtils {
|
|||||||
return getSimpleMangledName(descriptor);
|
return getSimpleMangledName(descriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO extend logic for nested/inner declarations
|
||||||
private static boolean needsStableMangling(FunctionDescriptor descriptor) {
|
private static boolean needsStableMangling(FunctionDescriptor descriptor) {
|
||||||
if (descriptor.getVisibility() == Visibilities.PUBLIC || !descriptor.getOverriddenDescriptors().isEmpty()) {
|
// Use stable mangling for overrides because we use stable mangling a overridable declaration.
|
||||||
|
if (JsDescriptorUtils.isOverride(descriptor)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration();
|
DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration();
|
||||||
|
|
||||||
if (containingDeclaration instanceof PackageFragmentDescriptor) {
|
if (containingDeclaration instanceof PackageFragmentDescriptor) {
|
||||||
|
return descriptor.getVisibility().isPublicAPI();
|
||||||
|
}
|
||||||
|
else if (containingDeclaration instanceof ClassDescriptor) {
|
||||||
|
ClassDescriptor classDescriptor = (ClassDescriptor) containingDeclaration;
|
||||||
|
// Use stable mangling when it inside a overridable declaration for avoid clashing names when inheritance.
|
||||||
|
if (classDescriptor.getModality().isOverridable()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't use stable mangling when it inside a non-public API declaration.
|
||||||
|
if (!classDescriptor.getVisibility().isPublicAPI()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ignore the `protected` visibility because it can be use outside a containing declaration
|
||||||
|
// only when the containing declaration is overridable.
|
||||||
|
if (descriptor.getVisibility() == Visibilities.PUBLIC) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (containingDeclaration instanceof MemberDescriptor) {
|
assert containingDeclaration instanceof CallableMemberDescriptor :
|
||||||
return ((MemberDescriptor) containingDeclaration).getModality().isOverridable();
|
"containingDeclaration for descriptor have unsupported type for mangling, " +
|
||||||
}
|
"descriptor: " + descriptor + ", containingDeclaration: " + containingDeclaration;
|
||||||
|
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -413,6 +435,8 @@ public final class TranslationUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isNativeOrOverrideNative(FunctionDescriptor descriptor) {
|
private static boolean isNativeOrOverrideNative(FunctionDescriptor descriptor) {
|
||||||
|
if (AnnotationsUtils.isNativeObject(descriptor)) return true;
|
||||||
|
|
||||||
Set<FunctionDescriptor> declarations = BindingContextUtils.getAllOverriddenDeclarations(descriptor);
|
Set<FunctionDescriptor> declarations = BindingContextUtils.getAllOverriddenDeclarations(descriptor);
|
||||||
for (FunctionDescriptor memberDescriptor : declarations) {
|
for (FunctionDescriptor memberDescriptor : declarations) {
|
||||||
if (AnnotationsUtils.isNativeObject(memberDescriptor)) return true;
|
if (AnnotationsUtils.isNativeObject(memberDescriptor)) return true;
|
||||||
|
|||||||
@@ -0,0 +1,195 @@
|
|||||||
|
package foo
|
||||||
|
|
||||||
|
public fun public_baz(i: Int) {}
|
||||||
|
native public fun public_baz(a: String) {}
|
||||||
|
|
||||||
|
fun internal_baz(i: Int) {}
|
||||||
|
native fun internal_baz(a: String) {}
|
||||||
|
|
||||||
|
private fun private_baz(i: Int) {}
|
||||||
|
native private fun private_baz(a: String) {}
|
||||||
|
|
||||||
|
public class PublicClass {
|
||||||
|
public fun public_baz(i: Int) {}
|
||||||
|
native public fun public_baz(a: String) {}
|
||||||
|
|
||||||
|
fun internal_baz(i: Int) {}
|
||||||
|
native fun internal_baz(a: String) {}
|
||||||
|
|
||||||
|
private fun private_baz(i: Int) {}
|
||||||
|
native private fun private_baz(a: String) {}
|
||||||
|
|
||||||
|
val call_private_baz = { private_baz(0)}
|
||||||
|
val call_private_native_baz = { private_baz("native")}
|
||||||
|
}
|
||||||
|
|
||||||
|
class InternalClass {
|
||||||
|
public fun public_baz(i: Int) {}
|
||||||
|
native public fun public_baz(a: String) {}
|
||||||
|
|
||||||
|
fun internal_baz(i: Int) {}
|
||||||
|
native fun internal_baz(a: String) {}
|
||||||
|
|
||||||
|
private fun private_baz(i: Int) {}
|
||||||
|
native private fun private_baz(a: String) {}
|
||||||
|
|
||||||
|
val call_private_baz = { private_baz(0)}
|
||||||
|
val call_private_native_baz = { private_baz("native")}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class PrivateClass {
|
||||||
|
public fun public_baz(i: Int) {}
|
||||||
|
native public fun public_baz(a: String) {}
|
||||||
|
|
||||||
|
fun internal_baz(i: Int) {}
|
||||||
|
native fun internal_baz(a: String) {}
|
||||||
|
|
||||||
|
private fun private_baz(i: Int) {}
|
||||||
|
native private fun private_baz(a: String) {}
|
||||||
|
|
||||||
|
val call_private_baz = { private_baz(0)}
|
||||||
|
val call_private_native_baz = { private_baz("native")}
|
||||||
|
}
|
||||||
|
|
||||||
|
open public class OpenPublicClass {
|
||||||
|
public fun public_baz(i: Int) {}
|
||||||
|
native public fun public_baz(a: String) {}
|
||||||
|
|
||||||
|
fun internal_baz(i: Int) {}
|
||||||
|
native fun internal_baz(a: String) {}
|
||||||
|
|
||||||
|
private fun private_baz(i: Int) {}
|
||||||
|
native private fun private_baz(a: String) {}
|
||||||
|
|
||||||
|
val call_private_baz = { private_baz(0)}
|
||||||
|
val call_private_native_baz = { private_baz("native")}
|
||||||
|
}
|
||||||
|
|
||||||
|
open class OpenInternalClass {
|
||||||
|
public fun public_baz(i: Int) {}
|
||||||
|
native public fun public_baz(a: String) {}
|
||||||
|
|
||||||
|
fun internal_baz(i: Int) {}
|
||||||
|
native fun internal_baz(a: String) {}
|
||||||
|
|
||||||
|
private fun private_baz(i: Int) {}
|
||||||
|
native private fun private_baz(a: String) {}
|
||||||
|
|
||||||
|
val call_private_baz = { private_baz(0)}
|
||||||
|
val call_private_native_baz = { private_baz("native")}
|
||||||
|
}
|
||||||
|
|
||||||
|
open private class OpenPrivateClass {
|
||||||
|
public fun public_baz(i: Int) {}
|
||||||
|
native public fun public_baz(a: String) {}
|
||||||
|
|
||||||
|
fun internal_baz(i: Int) {}
|
||||||
|
native fun internal_baz(a: String) {}
|
||||||
|
|
||||||
|
private fun private_baz(i: Int) {}
|
||||||
|
native private fun private_baz(a: String) {}
|
||||||
|
|
||||||
|
val call_private_baz = { private_baz(0)}
|
||||||
|
val call_private_native_baz = { private_baz("native")}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helpers
|
||||||
|
|
||||||
|
native
|
||||||
|
fun String.search(regexp: RegExp): Int = noImpl
|
||||||
|
|
||||||
|
native
|
||||||
|
class RegExp(regexp: String, flags: String = "") {
|
||||||
|
fun exec(s: String): Array<String>? = noImpl
|
||||||
|
}
|
||||||
|
|
||||||
|
val CALEE_NAME = RegExp("""\b\w*(baz[^(]*)""")
|
||||||
|
|
||||||
|
fun Function0<Unit>.extractNames(): Array<String> {
|
||||||
|
val names = CALEE_NAME.exec(this.toString())
|
||||||
|
|
||||||
|
if (names == null || names.size != 2) {
|
||||||
|
throw Exception("Cannot extract function name, $names for actual = \"$this\"")
|
||||||
|
}
|
||||||
|
|
||||||
|
return names
|
||||||
|
}
|
||||||
|
|
||||||
|
// Testing
|
||||||
|
|
||||||
|
var testGroup = ""
|
||||||
|
|
||||||
|
fun test(expected: String, f: ()->Unit){
|
||||||
|
val actual = f.extractNames()
|
||||||
|
|
||||||
|
if (expected != actual[1]) {
|
||||||
|
throw Exception("Failed on '$testGroup' group: expected = \"$expected\", actual[1] = \"${actual[1]}\"\n actual = $actual")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public fun stable_mangled_baz(i: Int) {}
|
||||||
|
|
||||||
|
val SIMPLE = "baz"
|
||||||
|
val SIMPLE1 = "${SIMPLE}_1"
|
||||||
|
val NATIVE = SIMPLE
|
||||||
|
val STABLE = { stable_mangled_baz(0) }.extractNames()[1]
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
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") }
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user