diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrBoxJsTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrBoxJsTestGenerated.java index 6ff215bd115..f9f0f583d38 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrBoxJsTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrBoxJsTestGenerated.java @@ -2697,6 +2697,11 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest { runTest("js/js.translator/testData/box/expression/try/nestedTryCatchInCatch.kt"); } + @TestMetadata("overrideThrowableProperties.kt") + public void testOverrideThrowableProperties() throws Exception { + runTest("js/js.translator/testData/box/expression/try/overrideThrowableProperties.kt"); + } + @TestMetadata("rethrowExceptionIfNotCaught.kt") public void testRethrowExceptionIfNotCaught() throws Exception { runTest("js/js.translator/testData/box/expression/try/rethrowExceptionIfNotCaught.kt"); 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 127c9bec5b9..cae4a2c4a6c 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 @@ -2712,6 +2712,11 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest { runTest("js/js.translator/testData/box/expression/try/nestedTryCatchInCatch.kt"); } + @TestMetadata("overrideThrowableProperties.kt") + public void testOverrideThrowableProperties() throws Exception { + runTest("js/js.translator/testData/box/expression/try/overrideThrowableProperties.kt"); + } + @TestMetadata("rethrowExceptionIfNotCaught.kt") public void testRethrowExceptionIfNotCaught() throws Exception { runTest("js/js.translator/testData/box/expression/try/rethrowExceptionIfNotCaught.kt"); diff --git a/js/js.translator/testData/box/expression/try/overrideThrowableProperties.kt b/js/js.translator/testData/box/expression/try/overrideThrowableProperties.kt new file mode 100644 index 00000000000..6f985a30695 --- /dev/null +++ b/js/js.translator/testData/box/expression/try/overrideThrowableProperties.kt @@ -0,0 +1,21 @@ +// EXPECTED_REACHABLE_NODES: 1315 + +open class Ex0(msg: String, cs: Throwable): Throwable(msg, cs) + +class Ex1: Ex0("A", Error("fail2")) { + override val cause = Error("B") +} + +class Ex2: Ex0("fail3", Error("C")) { + override val message = "D" +} + +fun box(): String { + val ex1: Throwable = Ex1() + val ex2: Throwable = Ex2() + + val r = ex1.message + ex1.cause?.message + ex2.cause?.message + ex2.message + if (r != "ABCD") return "Fail: $r" + + return "OK" +} \ No newline at end of file diff --git a/libraries/stdlib/js-ir/runtime/coreRuntime.kt b/libraries/stdlib/js-ir/runtime/coreRuntime.kt index 7350ed694d3..8558ed109da 100644 --- a/libraries/stdlib/js-ir/runtime/coreRuntime.kt +++ b/libraries/stdlib/js-ir/runtime/coreRuntime.kt @@ -38,6 +38,10 @@ fun toString(o: dynamic): String = when { fun anyToString(o: dynamic): String = js("Object").prototype.toString.call(o) +private fun hasOwnPrototypeProperty(o: Any, name: String): Boolean { + return JsObject.getPrototypeOf(o).hasOwnProperty(name).unsafeCast() +} + fun hashCode(obj: dynamic): Int { if (obj == null) return 0 @@ -95,8 +99,12 @@ internal fun newThrowable(message: String?, cause: Throwable?): Throwable { internal fun extendThrowable(this_: dynamic, message: String?, cause: Throwable?) { js("Error").call(this_) - this_.message = message ?: cause?.toString() ?: undefined - this_.cause = cause + if (!hasOwnPrototypeProperty(this_, "message")) { + this_.message = message ?: cause?.toString() ?: undefined + } + if (!hasOwnPrototypeProperty(this_, "cause")) { + this_.cause = cause + } this_.name = JsObject.getPrototypeOf(this_).constructor.name captureStack(this_) }