JS IR: fix throwable descendants
^ KT-43490 fixed
This commit is contained in:
committed by
Space Team
parent
48ed6c4cc7
commit
b0de442d76
+44
-7
@@ -2,20 +2,57 @@
|
|||||||
|
|
||||||
open class Ex0(msg: String, cs: Throwable): Throwable(msg, cs)
|
open class Ex0(msg: String, cs: Throwable): Throwable(msg, cs)
|
||||||
|
|
||||||
class Ex1: Ex0("A", Error("fail2")) {
|
open class Ex1: Ex0("A", Error("fail2")) {
|
||||||
override val cause = Error("B")
|
override val cause = Error("B")
|
||||||
}
|
}
|
||||||
|
|
||||||
class Ex2: Ex0("fail3", Error("C")) {
|
open class Ex2: Ex0("fail3", Error("C")) {
|
||||||
override val message = "D"
|
override val message = "D"
|
||||||
}
|
}
|
||||||
|
|
||||||
fun box(): String {
|
open class Ex3: Ex0("fail", Error("fail")) {
|
||||||
val ex1: Throwable = Ex1()
|
override val message get() = "O"
|
||||||
val ex2: Throwable = Ex2()
|
|
||||||
|
|
||||||
val r = ex1.message + ex1.cause?.message + ex2.cause?.message + ex2.message
|
override val cause get() = Error("K")
|
||||||
if (r != "ABCD") return "Fail: $r"
|
}
|
||||||
|
|
||||||
|
open class Ex4: Ex3()
|
||||||
|
|
||||||
|
class Ex5: Ex4() {
|
||||||
|
override val message: String
|
||||||
|
get() = "!"
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsExport
|
||||||
|
open class A : Throwable("AM", Error("AC"))
|
||||||
|
|
||||||
|
@JsExport
|
||||||
|
open class B : A() {
|
||||||
|
override val message = "BM"
|
||||||
|
|
||||||
|
override val cause = Error("BC")
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsExport
|
||||||
|
class C : B()
|
||||||
|
|
||||||
|
fun Throwable.check(expectedMessage: String, expectedCauseMessage: String?) {
|
||||||
|
assertEquals(expectedMessage, message)
|
||||||
|
assertEquals(expectedCauseMessage, cause?.message)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
|
||||||
|
Ex1().check("A", "B")
|
||||||
|
Ex2().check("D", "C")
|
||||||
|
|
||||||
|
Ex3().check("O", "K")
|
||||||
|
Ex4().check("O", "K")
|
||||||
|
Ex5().check("!", "K")
|
||||||
|
|
||||||
|
A().check("AM", "AC")
|
||||||
|
B().check("BM", "BC")
|
||||||
|
C().check("BM", "BC")
|
||||||
|
|
||||||
return "OK"
|
return "OK"
|
||||||
}
|
}
|
||||||
@@ -103,7 +103,8 @@ internal fun extendThrowable(this_: dynamic, message: String?, cause: Throwable?
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal fun setPropertiesToThrowableInstance(this_: dynamic, message: String?, cause: Throwable?) {
|
internal fun setPropertiesToThrowableInstance(this_: dynamic, message: String?, cause: Throwable?) {
|
||||||
if (!hasOwnPrototypeProperty(this_, "message")) {
|
val errorInfo = calculateErrorInfo(JsObject.getPrototypeOf(this_))
|
||||||
|
if ((errorInfo and 0x1) == 0) {
|
||||||
@Suppress("IfThenToElvis")
|
@Suppress("IfThenToElvis")
|
||||||
this_.message = if (message == null) {
|
this_.message = if (message == null) {
|
||||||
@Suppress("SENSELESS_COMPARISON")
|
@Suppress("SENSELESS_COMPARISON")
|
||||||
@@ -116,7 +117,7 @@ internal fun setPropertiesToThrowableInstance(this_: dynamic, message: String?,
|
|||||||
}
|
}
|
||||||
} else message
|
} else message
|
||||||
}
|
}
|
||||||
if (!hasOwnPrototypeProperty(this_, "cause")) {
|
if ((errorInfo and 0x2) == 0) {
|
||||||
this_.cause = cause
|
this_.cause = cause
|
||||||
}
|
}
|
||||||
this_.name = JsObject.getPrototypeOf(this_).constructor.name
|
this_.name = JsObject.getPrototypeOf(this_).constructor.name
|
||||||
|
|||||||
@@ -90,6 +90,8 @@ internal external interface Metadata {
|
|||||||
val iid: Int?
|
val iid: Int?
|
||||||
|
|
||||||
var `$kClass$`: dynamic
|
var `$kClass$`: dynamic
|
||||||
|
|
||||||
|
var errorInfo: Int? // Bits set for overridden properties: "message" => 0x1, "cause" => 0x2
|
||||||
}
|
}
|
||||||
|
|
||||||
internal external interface Ctor {
|
internal external interface Ctor {
|
||||||
@@ -99,9 +101,32 @@ internal external interface Ctor {
|
|||||||
val prototype: dynamic
|
val prototype: dynamic
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("UNUSED_PARAMETER")
|
private fun hasProp(proto: dynamic, propName: String): Boolean = proto.hasOwnProperty(propName)
|
||||||
private fun getPrototypeOf(obj: dynamic) =
|
|
||||||
js("Object.getPrototypeOf(obj)")
|
internal fun calculateErrorInfo(proto: dynamic): Int {
|
||||||
|
val metadata: Metadata? = proto.constructor?.`$metadata$`
|
||||||
|
|
||||||
|
metadata?.errorInfo?.let { return it } // cached
|
||||||
|
|
||||||
|
var result = 0
|
||||||
|
if (hasProp(proto, "message")) result = result or 0x1
|
||||||
|
if (hasProp(proto, "cause")) result = result or 0x2
|
||||||
|
|
||||||
|
if (result != 0x3) { //
|
||||||
|
val parentProto = getPrototypeOf(proto)
|
||||||
|
if (parentProto != js("Error").prototype) {
|
||||||
|
result = result or calculateErrorInfo(parentProto)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (metadata != null) {
|
||||||
|
metadata.errorInfo = result
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getPrototypeOf(obj: dynamic) = JsObject.getPrototypeOf(obj)
|
||||||
|
|
||||||
private fun searchForMetadata(obj: dynamic): Metadata? {
|
private fun searchForMetadata(obj: dynamic): Metadata? {
|
||||||
if (obj == null) {
|
if (obj == null) {
|
||||||
|
|||||||
Reference in New Issue
Block a user