JS: use prototype when checking is against interface

See KT-20527
This commit is contained in:
Alexey Andreev
2017-10-11 12:20:11 +03:00
parent 279126ad7e
commit 06b1ba7c47
3 changed files with 45 additions and 17 deletions
+14 -17
View File
@@ -52,22 +52,22 @@ Kotlin.callSetter = function (thisObject, klass, propertyName, value) {
}
};
function isInheritanceFromInterface(metadata, iface) {
if (metadata == null) return false;
function isInheritanceFromInterface(ctor, iface) {
if (ctor === iface) return true;
var interfaces = metadata.interfaces;
var i;
for (i = 0; i < interfaces.length; i++) {
if (interfaces[i] === iface) {
return true;
var metadata = ctor.$metadata$;
if (metadata != null) {
var interfaces = metadata.interfaces;
for (var i = 0; i < interfaces.length; i++) {
if (isInheritanceFromInterface(interfaces[i], iface)) {
return true;
}
}
}
for (i = 0; i < interfaces.length; i++) {
if (isInheritanceFromInterface(interfaces[i].$metadata$, iface)) {
return true;
}
}
return false;
var superPrototype = ctor.prototype != null ? Object.getPrototypeOf(ctor.prototype) : null;
var superConstructor = superPrototype != null ? superPrototype.constructor : null;
return superConstructor != null && isInheritanceFromInterface(superConstructor, iface);
}
/**
@@ -114,10 +114,7 @@ Kotlin.isType = function (object, klass) {
}
if (klassMetadata.kind === Kotlin.Kind.INTERFACE && object.constructor != null) {
metadata = object.constructor.$metadata$;
if (metadata != null) {
return isInheritanceFromInterface(metadata, klass);
}
return isInheritanceFromInterface(object.constructor, klass);
}
return false;
@@ -7667,6 +7667,12 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
doTest(fileName);
}
@TestMetadata("prototypeUsedToFindInterface.kt")
public void testPrototypeUsedToFindInterface() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/rtti/prototypeUsedToFindInterface.kt");
doTest(fileName);
}
@TestMetadata("rttiForClass.kt")
public void testRttiForClass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/rtti/rttiForClass.kt");
@@ -0,0 +1,25 @@
// EXPECTED_REACHABLE_NODES: 1112
interface A {
fun foo(): String
}
class B : A {
override fun foo(): String = "OK"
}
fun box(): String {
val b = B::class.js
val c = js("""
function C() {
b.call(this);
};
C.prototype = Object.create(b.prototype);
C.prototype.constructor = C;
new C();
""")
if (c !is B) return "fail: c !is B"
if (c !is A) return "fail: c !is A"
return "OK"
}