JS: use prototype when checking is against interface
See KT-20527
This commit is contained in:
@@ -52,22 +52,22 @@ Kotlin.callSetter = function (thisObject, klass, propertyName, value) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
function isInheritanceFromInterface(metadata, iface) {
|
function isInheritanceFromInterface(ctor, iface) {
|
||||||
if (metadata == null) return false;
|
if (ctor === iface) return true;
|
||||||
|
|
||||||
var interfaces = metadata.interfaces;
|
var metadata = ctor.$metadata$;
|
||||||
var i;
|
if (metadata != null) {
|
||||||
for (i = 0; i < interfaces.length; i++) {
|
var interfaces = metadata.interfaces;
|
||||||
if (interfaces[i] === iface) {
|
for (var i = 0; i < interfaces.length; i++) {
|
||||||
return true;
|
if (isInheritanceFromInterface(interfaces[i], iface)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (i = 0; i < interfaces.length; i++) {
|
|
||||||
if (isInheritanceFromInterface(interfaces[i].$metadata$, iface)) {
|
var superPrototype = ctor.prototype != null ? Object.getPrototypeOf(ctor.prototype) : null;
|
||||||
return true;
|
var superConstructor = superPrototype != null ? superPrototype.constructor : null;
|
||||||
}
|
return superConstructor != null && isInheritanceFromInterface(superConstructor, iface);
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -114,10 +114,7 @@ Kotlin.isType = function (object, klass) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (klassMetadata.kind === Kotlin.Kind.INTERFACE && object.constructor != null) {
|
if (klassMetadata.kind === Kotlin.Kind.INTERFACE && object.constructor != null) {
|
||||||
metadata = object.constructor.$metadata$;
|
return isInheritanceFromInterface(object.constructor, klass);
|
||||||
if (metadata != null) {
|
|
||||||
return isInheritanceFromInterface(metadata, klass);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -7667,6 +7667,12 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("rttiForClass.kt")
|
||||||
public void testRttiForClass() throws Exception {
|
public void testRttiForClass() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/rtti/rttiForClass.kt");
|
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"
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user