diff --git a/js/js.libraries/src/js/rtti.js b/js/js.libraries/src/js/rtti.js index 1ee914a0648..2b1f3f57b7c 100644 --- a/js/js.libraries/src/js/rtti.js +++ b/js/js.libraries/src/js/rtti.js @@ -22,34 +22,32 @@ Kotlin.Kind = { Kotlin.callGetter = function (thisObject, klass, propertyName) { var propertyDescriptor = Object.getOwnPropertyDescriptor(klass, propertyName); - if (propertyDescriptor != null) { - if (propertyDescriptor.get != null) { - return propertyDescriptor.get.call(thisObject); - } - else if ("value" in propertyDescriptor) { - return propertyDescriptor.value; - } + if (propertyDescriptor != null && propertyDescriptor.get != null) { + return propertyDescriptor.get.call(thisObject); } - else { - return Kotlin.callGetter(thisObject, Object.getPrototypeOf(klass), propertyName); + + propertyDescriptor = Object.getOwnPropertyDescriptor(thisObject, propertyName); + if (propertyDescriptor != null && "value" in propertyDescriptor) { + return thisObject[propertyName]; } - return null; + + return Kotlin.callGetter(thisObject, Object.getPrototypeOf(klass), propertyName); }; Kotlin.callSetter = function (thisObject, klass, propertyName, value) { var propertyDescriptor = Object.getOwnPropertyDescriptor(klass, propertyName); - if (propertyDescriptor != null) { - if (propertyDescriptor.set != null) { - propertyDescriptor.set.call(thisObject, value); - } - else if ("value" in propertyDescriptor) { - throw new Error("Assertion failed: Kotlin compiler should not generate simple JavaScript properties for overridable " + - "Kotlin properties."); - } + if (propertyDescriptor != null && propertyDescriptor.set != null) { + propertyDescriptor.set.call(thisObject, value); + return; } - else { - return Kotlin.callSetter(thisObject, Object.getPrototypeOf(klass), propertyName, value); + + propertyDescriptor = Object.getOwnPropertyDescriptor(thisObject, propertyName); + if (propertyDescriptor != null && "value" in propertyDescriptor) { + thisObject[propertyName] = value; + return } + + Kotlin.callSetter(thisObject, Object.getPrototypeOf(klass), propertyName, value); }; function isInheritanceFromInterface(ctor, iface) { 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 d9f8a42480c..fa9959a4270 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 @@ -8111,6 +8111,12 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest { doTest(fileName); } + @TestMetadata("propertySuperAccess.kt") + public void testPropertySuperAccess() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/superCall/propertySuperAccess.kt"); + doTest(fileName); + } + @TestMetadata("traitSuperCall.kt") public void testTraitSuperCall() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/superCall/traitSuperCall.kt"); diff --git a/js/js.translator/testData/box/superCall/propertySuperAccess.kt b/js/js.translator/testData/box/superCall/propertySuperAccess.kt new file mode 100644 index 00000000000..5e118c48e4d --- /dev/null +++ b/js/js.translator/testData/box/superCall/propertySuperAccess.kt @@ -0,0 +1,31 @@ +// EXPECTED_REACHABLE_NODES: 1140 +open class A { + val foo = "foo" + var bar = "bar" + + open val boo = "A.boo" +} + +class B : A() { + override val boo = "B.boo" + + fun test(): String { + var r = "" + r += super.foo + ";" + r += super.bar + ";" + super.bar = "baz" + r += super.bar + ";" + + r += super.boo + ";" + r += boo + ";" + + return r + } +} + +fun box(): String { + val r = B().test() + if (r != "foo;bar;baz;A.boo;B.boo;") return "fail: $r" + + return "OK" +} \ No newline at end of file