[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) prerequisite = setOf(functionInliningPhase)
) )
private val captureStackTraceInThrowablesPhase = makeBodyLoweringPhase(
::CaptureStackTraceInThrowables,
name = "CaptureStackTraceInThrowables",
description = "Capture stack trace in Throwable constructors"
)
private val throwableSuccessorsLoweringPhase = makeBodyLoweringPhase( private val throwableSuccessorsLoweringPhase = makeBodyLoweringPhase(
{ context -> { context ->
context.run { context.run {
@@ -289,7 +295,8 @@ private val throwableSuccessorsLoweringPhase = makeBodyLoweringPhase(
} }
}, },
name = "ThrowableLowering", 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( private val tailrecLoweringPhase = makeBodyLoweringPhase(
@@ -783,12 +790,6 @@ private val objectUsageLoweringPhase = makeBodyLoweringPhase(
description = "Transform IrGetObjectValue into instance generator call" 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( private val escapedIdentifiersLowering = makeBodyLoweringPhase(
::EscapedIdentifiersLowering, ::EscapedIdentifiersLowering,
name = "EscapedIdentifiersLowering", name = "EscapedIdentifiersLowering",
@@ -901,6 +902,7 @@ val loweringList = listOf<Lowering>(
defaultArgumentPatchOverridesPhase, defaultArgumentPatchOverridesPhase,
defaultParameterInjectorPhase, defaultParameterInjectorPhase,
defaultParameterCleanerPhase, defaultParameterCleanerPhase,
captureStackTraceInThrowablesPhase,
throwableSuccessorsLoweringPhase, throwableSuccessorsLoweringPhase,
es6AddInternalParametersToConstructorPhase, es6AddInternalParametersToConstructorPhase,
es6ConstructorLowering, es6ConstructorLowering,
@@ -921,7 +923,6 @@ val loweringList = listOf<Lowering>(
objectDeclarationLoweringPhase, objectDeclarationLoweringPhase,
invokeStaticInitializersPhase, invokeStaticInitializersPhase,
objectUsageLoweringPhase, objectUsageLoweringPhase,
captureStackTraceInThrowablesPhase,
callsLoweringPhase, callsLoweringPhase,
escapedIdentifiersLowering, escapedIdentifiersLowering,
implicitlyExportedDeclarationsMarkingLowering, implicitlyExportedDeclarationsMarkingLowering,
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.ir.declarations.IrConstructor
import org.jetbrains.kotlin.ir.declarations.IrDeclaration import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.expressions.IrBlockBody import org.jetbrains.kotlin.ir.expressions.IrBlockBody
import org.jetbrains.kotlin.ir.expressions.IrBody 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.expressions.impl.IrRawFunctionReferenceImpl
import org.jetbrains.kotlin.ir.util.isSubclassOf import org.jetbrains.kotlin.ir.util.isSubclassOf
import org.jetbrains.kotlin.ir.util.parentAsClass import org.jetbrains.kotlin.ir.util.parentAsClass
@@ -30,12 +31,15 @@ class CaptureStackTraceInThrowables(val context: JsIrBackendContext) : BodyLower
if (!klass.isSubclassOf(context.irBuiltIns.throwableClass.owner)) if (!klass.isSubclassOf(context.irBuiltIns.throwableClass.owner))
return 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(0, JsIrBuilder.buildGetValue(klass.thisReceiver!!.symbol))
call.putValueArgument( call.putValueArgument(
1, 1,
IrRawFunctionReferenceImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, context.irBuiltIns.anyType, container.symbol) 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"); 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 @Test
@TestMetadata("stackTraceCapturing.kt") @TestMetadata("stackTraceCapturing.kt")
public void testStackTraceCapturing() throws Exception { public void testStackTraceCapturing() throws Exception {
@@ -4249,6 +4249,12 @@ public class FirJsBoxTestGenerated extends AbstractFirJsBoxTest {
runTest("js/js.translator/testData/box/expression/misc/safeCallComputesExpressionOnlyOnce.kt"); 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 @Test
@TestMetadata("stackTraceCapturing.kt") @TestMetadata("stackTraceCapturing.kt")
public void testStackTraceCapturing() throws Exception { public void testStackTraceCapturing() throws Exception {
@@ -4249,6 +4249,12 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest {
runTest("js/js.translator/testData/box/expression/misc/safeCallComputesExpressionOnlyOnce.kt"); 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 @Test
@TestMetadata("stackTraceCapturing.kt") @TestMetadata("stackTraceCapturing.kt")
public void testStackTraceCapturing() throws Exception { 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"
}