[JS IR BE] Fix exceptions
* set message property in the correct way * set proper name for each Throwable successor
This commit is contained in:
+59
-23
@@ -16,15 +16,15 @@ import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
|||||||
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
|
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl
|
import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrDelegatingConstructorCall
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl
|
import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl
|
||||||
import org.jetbrains.kotlin.ir.types.IrType
|
import org.jetbrains.kotlin.ir.types.IrType
|
||||||
import org.jetbrains.kotlin.ir.types.makeNotNull
|
import org.jetbrains.kotlin.ir.types.makeNotNull
|
||||||
|
import org.jetbrains.kotlin.ir.types.makeNullable
|
||||||
|
import org.jetbrains.kotlin.ir.util.defaultType
|
||||||
import org.jetbrains.kotlin.ir.util.isThrowable
|
import org.jetbrains.kotlin.ir.util.isThrowable
|
||||||
|
import org.jetbrains.kotlin.ir.util.isThrowableTypeOrSubtype
|
||||||
import org.jetbrains.kotlin.ir.visitors.*
|
import org.jetbrains.kotlin.ir.visitors.*
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
@@ -33,9 +33,11 @@ class ThrowableSuccessorsLowering(context: JsIrBackendContext) : FileLoweringPas
|
|||||||
private val nothingNType = context.irBuiltIns.nothingNType
|
private val nothingNType = context.irBuiltIns.nothingNType
|
||||||
private val nothingType = context.irBuiltIns.nothingType
|
private val nothingType = context.irBuiltIns.nothingType
|
||||||
private val stringType = context.irBuiltIns.stringType
|
private val stringType = context.irBuiltIns.stringType
|
||||||
|
private val booleanType = context.irBuiltIns.booleanType
|
||||||
|
|
||||||
private val propertyGetter = context.intrinsics.jsGetJSField.symbol
|
private val propertyGetter = context.intrinsics.jsGetJSField.symbol
|
||||||
private val propertySetter = context.intrinsics.jsSetJSField.symbol
|
private val propertySetter = context.intrinsics.jsSetJSField.symbol
|
||||||
|
private val eqeqeqSymbol = context.irBuiltIns.eqeqSymbol
|
||||||
|
|
||||||
private val messageName = JsIrBuilder.buildString(stringType, "message")
|
private val messageName = JsIrBuilder.buildString(stringType, "message")
|
||||||
private val causeName = JsIrBuilder.buildString(stringType, "cause")
|
private val causeName = JsIrBuilder.buildString(stringType, "cause")
|
||||||
@@ -71,10 +73,36 @@ class ThrowableSuccessorsLowering(context: JsIrBackendContext) : FileLoweringPas
|
|||||||
pendingSuperUsages.clear()
|
pendingSuperUsages.clear()
|
||||||
irFile.acceptChildrenVoid(ThrowableAccessorCreationVisitor())
|
irFile.acceptChildrenVoid(ThrowableAccessorCreationVisitor())
|
||||||
pendingSuperUsages.forEach { it.klass.transformChildren(ThrowableDirectSuccessorTransformer(it), it.klass) }
|
pendingSuperUsages.forEach { it.klass.transformChildren(ThrowableDirectSuccessorTransformer(it), it.klass) }
|
||||||
|
irFile.transformChildren(ThrowableNameSetterTransformer(), irFile)
|
||||||
irFile.transformChildrenVoid(ThrowablePropertiesUsageTransformer())
|
irFile.transformChildrenVoid(ThrowablePropertiesUsageTransformer())
|
||||||
irFile.transformChildrenVoid(ThrowableInstanceCreationLowering())
|
irFile.transformChildrenVoid(ThrowableInstanceCreationLowering())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inner class ThrowableNameSetterTransformer : IrElementTransformer<IrDeclarationParent> {
|
||||||
|
override fun visitClass(declaration: IrClass, data: IrDeclarationParent) = super.visitClass(declaration, declaration)
|
||||||
|
|
||||||
|
override fun visitConstructor(declaration: IrConstructor, data: IrDeclarationParent): IrStatement {
|
||||||
|
declaration.transformChildren(this, data)
|
||||||
|
|
||||||
|
if (!declaration.isPrimary) return declaration
|
||||||
|
|
||||||
|
val klass = data as IrClass
|
||||||
|
if (klass.defaultType.isThrowableTypeOrSubtype()) {
|
||||||
|
|
||||||
|
(declaration.body as? IrBlockBody)?.let {
|
||||||
|
it.statements += JsIrBuilder.buildCall(propertySetter, unitType).apply {
|
||||||
|
putValueArgument(0, JsIrBuilder.buildGetValue(klass.thisReceiver!!.symbol))
|
||||||
|
putValueArgument(1, nameName)
|
||||||
|
putValueArgument(2, JsIrBuilder.buildString(stringType, klass.name.asString()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return declaration
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
inner class ThrowableInstanceCreationLowering : IrElementTransformerVoid() {
|
inner class ThrowableInstanceCreationLowering : IrElementTransformerVoid() {
|
||||||
override fun visitCall(expression: IrCall): IrExpression {
|
override fun visitCall(expression: IrCall): IrExpression {
|
||||||
if (expression.symbol.owner !in throwableConstructors) return super.visitCall(expression)
|
if (expression.symbol.owner !in throwableConstructors) return super.visitCall(expression)
|
||||||
@@ -204,9 +232,7 @@ class ThrowableSuccessorsLowering(context: JsIrBackendContext) : FileLoweringPas
|
|||||||
val klass = successor.klass
|
val klass = successor.klass
|
||||||
val receiver = IrGetValueImpl(expression.startOffset, expression.endOffset, klass.thisReceiver!!.symbol)
|
val receiver = IrGetValueImpl(expression.startOffset, expression.endOffset, klass.thisReceiver!!.symbol)
|
||||||
|
|
||||||
val nameArg = JsIrBuilder.buildString(stringType, klass.name.asString())
|
val fillStatements = fillThrowableInstance(expression, receiver, messageArg, causeArg)
|
||||||
|
|
||||||
val fillStatements = fillThrowableInstance(expression, receiver, messageArg, causeArg, nameArg)
|
|
||||||
|
|
||||||
return expression.run {
|
return expression.run {
|
||||||
IrCompositeImpl(startOffset, endOffset, type, origin, paramStatements + newDelegation + fillStatements)
|
IrCompositeImpl(startOffset, endOffset, type, origin, paramStatements + newDelegation + fillStatements)
|
||||||
@@ -217,8 +243,7 @@ class ThrowableSuccessorsLowering(context: JsIrBackendContext) : FileLoweringPas
|
|||||||
expression: IrFunctionAccessExpression,
|
expression: IrFunctionAccessExpression,
|
||||||
receiver: IrExpression,
|
receiver: IrExpression,
|
||||||
messageArg: IrExpression,
|
messageArg: IrExpression,
|
||||||
causeArg: IrExpression,
|
causeArg: IrExpression
|
||||||
name: IrExpression
|
|
||||||
): List<IrStatement> {
|
): List<IrStatement> {
|
||||||
|
|
||||||
val setMessage = expression.run {
|
val setMessage = expression.run {
|
||||||
@@ -229,17 +254,11 @@ class ThrowableSuccessorsLowering(context: JsIrBackendContext) : FileLoweringPas
|
|||||||
IrSetFieldImpl(startOffset, endOffset, successor.cause.symbol, receiver, causeArg, unitType)
|
IrSetFieldImpl(startOffset, endOffset, successor.cause.symbol, receiver, causeArg, unitType)
|
||||||
}
|
}
|
||||||
|
|
||||||
val setName = IrCallImpl(expression.startOffset, expression.endOffset, unitType, propertySetter).apply {
|
|
||||||
putValueArgument(0, receiver)
|
|
||||||
putValueArgument(1, nameName)
|
|
||||||
putValueArgument(2, name)
|
|
||||||
}
|
|
||||||
|
|
||||||
val setStackTrace = IrCallImpl(expression.startOffset, expression.endOffset, unitType, captureStackFunction).apply {
|
val setStackTrace = IrCallImpl(expression.startOffset, expression.endOffset, unitType, captureStackFunction).apply {
|
||||||
putValueArgument(0, receiver)
|
putValueArgument(0, receiver)
|
||||||
}
|
}
|
||||||
|
|
||||||
return listOf(setMessage, setCause, setName, setStackTrace)
|
return listOf(setMessage, setCause, setStackTrace)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun extractConstructorParameters(
|
private fun extractConstructorParameters(
|
||||||
@@ -255,19 +274,25 @@ class ThrowableSuccessorsLowering(context: JsIrBackendContext) : FileLoweringPas
|
|||||||
val cus = expression.getValueArgument(1)!!
|
val cus = expression.getValueArgument(1)!!
|
||||||
val irValM = JsIrBuilder.buildVar(msg.type, parent, initializer = msg)
|
val irValM = JsIrBuilder.buildVar(msg.type, parent, initializer = msg)
|
||||||
val irValC = JsIrBuilder.buildVar(cus.type, parent, initializer = cus)
|
val irValC = JsIrBuilder.buildVar(cus.type, parent, initializer = cus)
|
||||||
Triple(JsIrBuilder.buildGetValue(irValM.symbol), JsIrBuilder.buildGetValue(irValC.symbol), listOf(irValM, irValC))
|
|
||||||
|
val check = JsIrBuilder.buildCall(eqeqeqSymbol, booleanType).apply {
|
||||||
|
putValueArgument(0, JsIrBuilder.buildGetValue(irValM.symbol))
|
||||||
|
putValueArgument(1, nullValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
val msgElvis = JsIrBuilder.buildIfElse(
|
||||||
|
stringType.makeNullable(), check,
|
||||||
|
safeCallToString(irValC), JsIrBuilder.buildGetValue(irValM.symbol)
|
||||||
|
)
|
||||||
|
|
||||||
|
Triple(msgElvis, JsIrBuilder.buildGetValue(irValC.symbol), listOf(irValM, irValC))
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
val arg = expression.getValueArgument(0)!!
|
val arg = expression.getValueArgument(0)!!
|
||||||
val irVal = JsIrBuilder.buildVar(arg.type, parent, initializer = arg)
|
val irVal = JsIrBuilder.buildVar(arg.type, parent, initializer = arg)
|
||||||
val argValue = JsIrBuilder.buildGetValue(irVal.symbol)
|
val argValue = JsIrBuilder.buildGetValue(irVal.symbol)
|
||||||
when {
|
when {
|
||||||
arg.type.makeNotNull().isThrowable() -> {
|
arg.type.makeNotNull().isThrowable() -> Triple(safeCallToString(irVal), argValue, listOf(irVal))
|
||||||
val messageExpr = JsIrBuilder.buildCall(toString.symbol, stringType).apply {
|
|
||||||
dispatchReceiver = argValue
|
|
||||||
}
|
|
||||||
Triple(messageExpr, argValue, listOf(irVal))
|
|
||||||
}
|
|
||||||
else -> Triple(argValue, nullValue, listOf(irVal))
|
else -> Triple(argValue, nullValue, listOf(irVal))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -275,6 +300,17 @@ class ThrowableSuccessorsLowering(context: JsIrBackendContext) : FileLoweringPas
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun safeCallToString(receiver: IrValueDeclaration): IrExpression {
|
||||||
|
val value = JsIrBuilder.buildGetValue(receiver.symbol)
|
||||||
|
val check = JsIrBuilder.buildCall(eqeqeqSymbol, booleanType).apply {
|
||||||
|
putValueArgument(0, value)
|
||||||
|
putValueArgument(1, JsIrBuilder.buildNull(value.type))
|
||||||
|
}
|
||||||
|
val value2 = JsIrBuilder.buildGetValue(receiver.symbol)
|
||||||
|
val call = JsIrBuilder.buildCall(toString.symbol, stringType).apply { dispatchReceiver = value2 }
|
||||||
|
return JsIrBuilder.buildIfElse(stringType.makeNullable(), check, JsIrBuilder.buildNull(stringType), call)
|
||||||
|
}
|
||||||
|
|
||||||
private fun isDirectChildOfThrowable(irClass: IrClass) = irClass.superTypes.any { it.isThrowable() }
|
private fun isDirectChildOfThrowable(irClass: IrClass) = irClass.superTypes.any { it.isThrowable() }
|
||||||
private fun ownPropertyAccessor(irClass: IrClass, irBase: IrFunction) =
|
private fun ownPropertyAccessor(irClass: IrClass, irBase: IrFunction) =
|
||||||
irClass.declarations.filterIsInstance<IrProperty>().mapNotNull { it.getter }
|
irClass.declarations.filterIsInstance<IrProperty>().mapNotNull { it.getter }
|
||||||
|
|||||||
Reference in New Issue
Block a user