[JS IR BE] Fix Throwable ancestor transformation
Make sure that `message` and `cause` are properly configured - synchronize IR BE and Legacy behaviour - fix corresponding IR lowering - fix JS IR core runtime - add test - fix KT-39964
This commit is contained in:
+6
-4
@@ -24,12 +24,14 @@ class ThrowableLowering(
|
|||||||
val context: JsIrBackendContext,
|
val context: JsIrBackendContext,
|
||||||
val extendThrowableFunction: IrSimpleFunctionSymbol
|
val extendThrowableFunction: IrSimpleFunctionSymbol
|
||||||
) : BodyLoweringPass {
|
) : BodyLoweringPass {
|
||||||
private val nothingNType get() = context.irBuiltIns.nothingNType
|
private val nothingNType = context.irBuiltIns.nothingNType
|
||||||
|
|
||||||
private val throwableConstructors = context.throwableConstructors
|
private val throwableConstructors = context.throwableConstructors
|
||||||
private val newThrowableFunction = context.newThrowableSymbol
|
private val newThrowableFunction = context.newThrowableSymbol
|
||||||
|
private val jsUndefined = context.intrinsics.jsUndefined.symbol
|
||||||
|
|
||||||
fun nullValue(): IrExpression = IrConstImpl.constNull(UNDEFINED_OFFSET, UNDEFINED_OFFSET, nothingNType)
|
fun nullValue(): IrExpression = IrConstImpl.constNull(UNDEFINED_OFFSET, UNDEFINED_OFFSET, nothingNType)
|
||||||
|
fun undefinedValue(): IrExpression = IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, nothingNType, jsUndefined, 0, 0)
|
||||||
|
|
||||||
data class ThrowableArguments(
|
data class ThrowableArguments(
|
||||||
val message: IrExpression,
|
val message: IrExpression,
|
||||||
@@ -44,7 +46,7 @@ class ThrowableLowering(
|
|||||||
|
|
||||||
private fun IrFunctionAccessExpression.extractThrowableArguments(): ThrowableArguments =
|
private fun IrFunctionAccessExpression.extractThrowableArguments(): ThrowableArguments =
|
||||||
when (valueArgumentsCount) {
|
when (valueArgumentsCount) {
|
||||||
0 -> ThrowableArguments(nullValue(), nullValue())
|
0 -> ThrowableArguments(nullValue(), undefinedValue())
|
||||||
2 -> ThrowableArguments(
|
2 -> ThrowableArguments(
|
||||||
message = getValueArgument(0)!!,
|
message = getValueArgument(0)!!,
|
||||||
cause = getValueArgument(1)!!
|
cause = getValueArgument(1)!!
|
||||||
@@ -53,10 +55,10 @@ class ThrowableLowering(
|
|||||||
val arg = getValueArgument(0)!!
|
val arg = getValueArgument(0)!!
|
||||||
val parameter = symbol.owner.valueParameters[0]
|
val parameter = symbol.owner.valueParameters[0]
|
||||||
when {
|
when {
|
||||||
parameter.type.isNullableString() -> ThrowableArguments(message = arg, cause = nullValue())
|
parameter.type.isNullableString() -> ThrowableArguments(message = arg, cause = undefinedValue())
|
||||||
else -> {
|
else -> {
|
||||||
assert(parameter.type.makeNotNull().isThrowable())
|
assert(parameter.type.makeNotNull().isThrowable())
|
||||||
ThrowableArguments(message = nullValue(), cause = arg)
|
ThrowableArguments(message = undefinedValue(), cause = arg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
@@ -7675,6 +7675,11 @@ public class IrBoxJsES6TestGenerated extends AbstractIrBoxJsES6Test {
|
|||||||
public void testStringPlus() throws Exception {
|
public void testStringPlus() throws Exception {
|
||||||
runTest("js/js.translator/testData/box/standardClasses/stringPlus.kt");
|
runTest("js/js.translator/testData/box/standardClasses/stringPlus.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("throwableCtor.kt")
|
||||||
|
public void testThrowableCtor() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/standardClasses/throwableCtor.kt");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("js/js.translator/testData/box/superCall")
|
@TestMetadata("js/js.translator/testData/box/superCall")
|
||||||
|
|||||||
+5
@@ -7675,6 +7675,11 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest {
|
|||||||
public void testStringPlus() throws Exception {
|
public void testStringPlus() throws Exception {
|
||||||
runTest("js/js.translator/testData/box/standardClasses/stringPlus.kt");
|
runTest("js/js.translator/testData/box/standardClasses/stringPlus.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("throwableCtor.kt")
|
||||||
|
public void testThrowableCtor() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/standardClasses/throwableCtor.kt");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("js/js.translator/testData/box/superCall")
|
@TestMetadata("js/js.translator/testData/box/superCall")
|
||||||
|
|||||||
+5
@@ -7705,6 +7705,11 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
|
|||||||
public void testStringPlus() throws Exception {
|
public void testStringPlus() throws Exception {
|
||||||
runTest("js/js.translator/testData/box/standardClasses/stringPlus.kt");
|
runTest("js/js.translator/testData/box/standardClasses/stringPlus.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("throwableCtor.kt")
|
||||||
|
public void testThrowableCtor() throws Exception {
|
||||||
|
runTest("js/js.translator/testData/box/standardClasses/throwableCtor.kt");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("js/js.translator/testData/box/superCall")
|
@TestMetadata("js/js.translator/testData/box/superCall")
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
// EXPECTED_REACHABLE_NODES: 1237
|
||||||
|
|
||||||
|
// KT-39964
|
||||||
|
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val e = Throwable(null, IllegalStateException("fail"))
|
||||||
|
if (e.message != null) return "FAIL"
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -89,7 +89,7 @@ internal fun captureStack(instance: Throwable, constructorFunction: Any) {
|
|||||||
|
|
||||||
internal fun newThrowable(message: String?, cause: Throwable?): Throwable {
|
internal fun newThrowable(message: String?, cause: Throwable?): Throwable {
|
||||||
val throwable = js("new Error()")
|
val throwable = js("new Error()")
|
||||||
throwable.message = message ?: cause?.toString() ?: undefined
|
throwable.message = if (isUndefined(message)) cause?.toString() else message
|
||||||
throwable.cause = cause
|
throwable.cause = cause
|
||||||
throwable.name = "Throwable"
|
throwable.name = "Throwable"
|
||||||
return throwable.unsafeCast<Throwable>()
|
return throwable.unsafeCast<Throwable>()
|
||||||
@@ -102,7 +102,17 @@ 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")) {
|
if (!hasOwnPrototypeProperty(this_, "message")) {
|
||||||
this_.message = message ?: cause?.toString() ?: undefined
|
@Suppress("IfThenToElvis")
|
||||||
|
this_.message = if (message == null) {
|
||||||
|
@Suppress("SENSELESS_COMPARISON")
|
||||||
|
if (message !== null) {
|
||||||
|
// undefined
|
||||||
|
cause?.toString() ?: undefined
|
||||||
|
} else {
|
||||||
|
// real null
|
||||||
|
message
|
||||||
|
}
|
||||||
|
} else message
|
||||||
}
|
}
|
||||||
if (!hasOwnPrototypeProperty(this_, "cause")) {
|
if (!hasOwnPrototypeProperty(this_, "cause")) {
|
||||||
this_.cause = cause
|
this_.cause = cause
|
||||||
@@ -122,5 +132,8 @@ internal fun errorCode(description: String): Nothing {
|
|||||||
throw IllegalStateException(description)
|
throw IllegalStateException(description)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("SENSELESS_COMPARISON")
|
||||||
|
internal fun isUndefined(value: dynamic): Boolean = value === undefined
|
||||||
|
|
||||||
internal fun <T, R> boxIntrinsic(@Suppress("UNUSED_PARAMETER") x: T): R = error("Should be lowered")
|
internal fun <T, R> boxIntrinsic(@Suppress("UNUSED_PARAMETER") x: T): R = error("Should be lowered")
|
||||||
internal fun <T, R> unboxIntrinsic(@Suppress("UNUSED_PARAMETER") x: T): R = error("Should be lowered")
|
internal fun <T, R> unboxIntrinsic(@Suppress("UNUSED_PARAMETER") x: T): R = error("Should be lowered")
|
||||||
|
|||||||
Reference in New Issue
Block a user