[K/JS] Capture stackTrace before the init function call ^Fixed KT-55315
This commit is contained in:
@@ -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,
|
||||
|
||||
+6
-2
@@ -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 {
|
||||
|
||||
+6
@@ -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 {
|
||||
|
||||
+6
@@ -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 {
|
||||
|
||||
+32
@@ -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"
|
||||
}
|
||||
Reference in New Issue
Block a user