[K/JS] Capture stackTrace before the init function call ^Fixed KT-55315

This commit is contained in:
Artem Kobzar
2022-12-20 18:15:02 +00:00
committed by Space Team
parent 48daf0befe
commit cd0ae20c38
6 changed files with 65 additions and 10 deletions
@@ -279,6 +279,12 @@ private val removeInlineDeclarationsWithReifiedTypeParametersLoweringPhase = mak
prerequisite = setOf(functionInliningPhase)
)
private val captureStackTraceInThrowablesPhase = makeBodyLoweringPhase(
::CaptureStackTraceInThrowables,
name = "CaptureStackTraceInThrowables",
description = "Capture stack trace in Throwable constructors"
)
private val throwableSuccessorsLoweringPhase = makeBodyLoweringPhase(
{ context ->
context.run {
@@ -289,7 +295,8 @@ private val throwableSuccessorsLoweringPhase = makeBodyLoweringPhase(
}
},
name = "ThrowableLowering",
description = "Link kotlin.Throwable and JavaScript Error together to provide proper interop between language and platform exceptions"
description = "Link kotlin.Throwable and JavaScript Error together to provide proper interop between language and platform exceptions",
prerequisite = setOf(captureStackTraceInThrowablesPhase)
)
private val tailrecLoweringPhase = makeBodyLoweringPhase(
@@ -783,12 +790,6 @@ private val objectUsageLoweringPhase = makeBodyLoweringPhase(
description = "Transform IrGetObjectValue into instance generator call"
)
private val captureStackTraceInThrowablesPhase = makeBodyLoweringPhase(
::CaptureStackTraceInThrowables,
name = "CaptureStackTraceInThrowables",
description = "Capture stack trace in Throwable constructors"
)
private val escapedIdentifiersLowering = makeBodyLoweringPhase(
::EscapedIdentifiersLowering,
name = "EscapedIdentifiersLowering",
@@ -901,6 +902,7 @@ val loweringList = listOf<Lowering>(
defaultArgumentPatchOverridesPhase,
defaultParameterInjectorPhase,
defaultParameterCleanerPhase,
captureStackTraceInThrowablesPhase,
throwableSuccessorsLoweringPhase,
es6AddInternalParametersToConstructorPhase,
es6ConstructorLowering,
@@ -921,7 +923,6 @@ val loweringList = listOf<Lowering>(
objectDeclarationLoweringPhase,
invokeStaticInitializersPhase,
objectUsageLoweringPhase,
captureStackTraceInThrowablesPhase,
callsLoweringPhase,
escapedIdentifiersLowering,
implicitlyExportedDeclarationsMarkingLowering,
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.ir.declarations.IrConstructor
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.expressions.IrBlockBody
import org.jetbrains.kotlin.ir.expressions.IrBody
import org.jetbrains.kotlin.ir.expressions.IrDelegatingConstructorCall
import org.jetbrains.kotlin.ir.expressions.impl.IrRawFunctionReferenceImpl
import org.jetbrains.kotlin.ir.util.isSubclassOf
import org.jetbrains.kotlin.ir.util.parentAsClass
@@ -30,12 +31,15 @@ class CaptureStackTraceInThrowables(val context: JsIrBackendContext) : BodyLower
if (!klass.isSubclassOf(context.irBuiltIns.throwableClass.owner))
return
(irBody as IrBlockBody).statements += JsIrBuilder.buildCall(context.intrinsics.captureStack).also { call ->
val statements = (irBody as IrBlockBody).statements
val delegatingConstructorCallIndex = statements.indexOfLast { it is IrDelegatingConstructorCall }
statements.add(delegatingConstructorCallIndex + 1, JsIrBuilder.buildCall(context.intrinsics.captureStack).also { call ->
call.putValueArgument(0, JsIrBuilder.buildGetValue(klass.thisReceiver!!.symbol))
call.putValueArgument(
1,
IrRawFunctionReferenceImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, context.irBuiltIns.anyType, container.symbol)
)
}
})
}
}
@@ -3627,6 +3627,12 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
runTest("js/js.translator/testData/box/expression/misc/safeCallComputesExpressionOnlyOnce.kt");
}
@Test
@TestMetadata("stackTraceAccessInsideInitBlock.kt")
public void testStackTraceAccessInsideInitBlock() throws Exception {
runTest("js/js.translator/testData/box/expression/misc/stackTraceAccessInsideInitBlock.kt");
}
@Test
@TestMetadata("stackTraceCapturing.kt")
public void testStackTraceCapturing() throws Exception {
@@ -4249,6 +4249,12 @@ public class FirJsBoxTestGenerated extends AbstractFirJsBoxTest {
runTest("js/js.translator/testData/box/expression/misc/safeCallComputesExpressionOnlyOnce.kt");
}
@Test
@TestMetadata("stackTraceAccessInsideInitBlock.kt")
public void testStackTraceAccessInsideInitBlock() throws Exception {
runTest("js/js.translator/testData/box/expression/misc/stackTraceAccessInsideInitBlock.kt");
}
@Test
@TestMetadata("stackTraceCapturing.kt")
public void testStackTraceCapturing() throws Exception {
@@ -4249,6 +4249,12 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest {
runTest("js/js.translator/testData/box/expression/misc/safeCallComputesExpressionOnlyOnce.kt");
}
@Test
@TestMetadata("stackTraceAccessInsideInitBlock.kt")
public void testStackTraceAccessInsideInitBlock() throws Exception {
runTest("js/js.translator/testData/box/expression/misc/stackTraceAccessInsideInitBlock.kt");
}
@Test
@TestMetadata("stackTraceCapturing.kt")
public void testStackTraceCapturing() throws Exception {
@@ -0,0 +1,32 @@
// EXPECTED_REACHABLE_NODES: 1462
// KJS_WITH_FULL_RUNTIME
// IGNORE_BACKEND: JS
// KT-55315
var stackTrace: String = ""
open class MyOwnException1: Throwable("Test message 1") {
init {
stackTrace = asDynamic().stack
}
}
class MyOwnException2: MyOwnException1() {
init {
stackTrace = asDynamic().stack
}
}
fun box(): String {
try {
throw MyOwnException1()
} catch (e: Throwable) {
if (!stackTrace.contains("MyOwnException1: Test message 1\n")) return "fail"
}
try {
throw MyOwnException2()
} catch (e: Throwable) {
if (!stackTrace.contains("MyOwnException2: Test message 1\n")) return "fail"
}
return "OK"
}