[WasmJs] Support catching JS exceptions
Fixed #KT-65660
This commit is contained in:
committed by
Space Team
parent
c6aac835e5
commit
8fe5cf2641
+10
-2
@@ -432,11 +432,18 @@ private val excludeDeclarationsFromCodegenPhase = makeCustomPhase<WasmBackendCon
|
|||||||
description = "Move excluded declarations to separate place"
|
description = "Move excluded declarations to separate place"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
private val jsExceptionReveal = makeIrModulePhase(
|
||||||
|
::JsExceptionRevealLowering,
|
||||||
|
name = "JsExceptionRevealLowering",
|
||||||
|
description = "Wraps try statement into try with revealed JS exception",
|
||||||
|
prerequisite = setOf(functionInliningPhase)
|
||||||
|
)
|
||||||
|
|
||||||
private val tryCatchCanonicalization = makeIrModulePhase(
|
private val tryCatchCanonicalization = makeIrModulePhase(
|
||||||
::TryCatchCanonicalization,
|
::TryCatchCanonicalization,
|
||||||
name = "TryCatchCanonicalization",
|
name = "TryCatchCanonicalization",
|
||||||
description = "Transforms try/catch statements into canonical form supported by the wasm codegen",
|
description = "Transforms try/catch statements into canonical form supported by the wasm codegen",
|
||||||
prerequisite = setOf(functionInliningPhase)
|
prerequisite = setOf(functionInliningPhase, jsExceptionReveal)
|
||||||
)
|
)
|
||||||
|
|
||||||
private val bridgesConstructionPhase = makeIrModulePhase(
|
private val bridgesConstructionPhase = makeIrModulePhase(
|
||||||
@@ -566,6 +573,7 @@ private val unhandledExceptionLowering = makeIrModulePhase(
|
|||||||
::UnhandledExceptionLowering,
|
::UnhandledExceptionLowering,
|
||||||
name = "UnhandledExceptionLowering",
|
name = "UnhandledExceptionLowering",
|
||||||
description = "Wrap JsExport functions with try-catch to convert unhandled Wasm exception into Js exception",
|
description = "Wrap JsExport functions with try-catch to convert unhandled Wasm exception into Js exception",
|
||||||
|
prerequisite = setOf(jsExceptionReveal)
|
||||||
)
|
)
|
||||||
|
|
||||||
private val propertyAccessorInlinerLoweringPhase = makeIrModulePhase(
|
private val propertyAccessorInlinerLoweringPhase = makeIrModulePhase(
|
||||||
@@ -699,8 +707,8 @@ val loweringList = listOf(
|
|||||||
|
|
||||||
invokeOnExportedFunctionExitLowering,
|
invokeOnExportedFunctionExitLowering,
|
||||||
|
|
||||||
|
jsExceptionReveal,
|
||||||
unhandledExceptionLowering,
|
unhandledExceptionLowering,
|
||||||
|
|
||||||
tryCatchCanonicalization,
|
tryCatchCanonicalization,
|
||||||
|
|
||||||
forLoopsLoweringPhase,
|
forLoopsLoweringPhase,
|
||||||
|
|||||||
@@ -410,6 +410,9 @@ class WasmSymbols(
|
|||||||
getInternalFunction("throwAsJsException")
|
getInternalFunction("throwAsJsException")
|
||||||
|
|
||||||
val kExternalClassImpl: IrClassSymbol = getInternalClass("KExternalClassImpl")
|
val kExternalClassImpl: IrClassSymbol = getInternalClass("KExternalClassImpl")
|
||||||
|
|
||||||
|
val jsException = getIrClass(FqName("kotlin.js.JsException"))
|
||||||
|
val throwJsException = getInternalFunction("throwJsException")
|
||||||
}
|
}
|
||||||
|
|
||||||
private val wasmExportClass = getIrClass(FqName("kotlin.wasm.WasmExport"))
|
private val wasmExportClass = getIrClass(FqName("kotlin.wasm.WasmExport"))
|
||||||
|
|||||||
@@ -64,6 +64,9 @@ private fun buildRoots(modules: List<IrModuleFragment>, context: WasmBackendCont
|
|||||||
add(context.fieldInitFunction)
|
add(context.fieldInitFunction)
|
||||||
add(context.findUnitInstanceField())
|
add(context.findUnitInstanceField())
|
||||||
add(context.irBuiltIns.unitClass.owner.primaryConstructor!!)
|
add(context.irBuiltIns.unitClass.owner.primaryConstructor!!)
|
||||||
|
if (context.isWasmJsTarget) {
|
||||||
|
add(context.wasmSymbols.jsRelatedSymbols.throwJsException.owner)
|
||||||
|
}
|
||||||
|
|
||||||
// Remove all functions used to call a kotlin closure from JS side, reachable ones will be added back later.
|
// Remove all functions used to call a kotlin closure from JS side, reachable ones will be added back later.
|
||||||
removeAll(context.closureCallExports.values)
|
removeAll(context.closureCallExports.values)
|
||||||
|
|||||||
+29
-10
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.backend.wasm.ir2wasm
|
|||||||
import org.jetbrains.kotlin.backend.common.ir.returnType
|
import org.jetbrains.kotlin.backend.common.ir.returnType
|
||||||
import org.jetbrains.kotlin.backend.wasm.WasmBackendContext
|
import org.jetbrains.kotlin.backend.wasm.WasmBackendContext
|
||||||
import org.jetbrains.kotlin.backend.wasm.WasmSymbols
|
import org.jetbrains.kotlin.backend.wasm.WasmSymbols
|
||||||
|
import org.jetbrains.kotlin.backend.wasm.lower.JsExceptionRevealOrigin
|
||||||
import org.jetbrains.kotlin.backend.wasm.utils.*
|
import org.jetbrains.kotlin.backend.wasm.utils.*
|
||||||
import org.jetbrains.kotlin.backend.wasm.utils.isCanonical
|
import org.jetbrains.kotlin.backend.wasm.utils.isCanonical
|
||||||
import org.jetbrains.kotlin.ir.IrBuiltIns
|
import org.jetbrains.kotlin.ir.IrBuiltIns
|
||||||
@@ -675,16 +676,7 @@ class BodyGenerator(
|
|||||||
functionContext.stepOutLastInlinedFunction()
|
functionContext.stepOutLastInlinedFunction()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitContainerExpression(expression: IrContainerExpression) {
|
private fun processContainerExpression(expression: IrContainerExpression) {
|
||||||
val statements = expression.statements
|
|
||||||
|
|
||||||
if (statements.isEmpty()) {
|
|
||||||
if (expression.type == irBuiltIns.unitType) {
|
|
||||||
body.buildGetUnit()
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (expression is IrReturnableBlock) {
|
if (expression is IrReturnableBlock) {
|
||||||
val inlineFunction = expression.symbol.owner.inlineFunction
|
val inlineFunction = expression.symbol.owner.inlineFunction
|
||||||
val correspondingProperty = (inlineFunction as? IrSimpleFunction)?.correspondingPropertySymbol
|
val correspondingProperty = (inlineFunction as? IrSimpleFunction)?.correspondingPropertySymbol
|
||||||
@@ -698,6 +690,7 @@ class BodyGenerator(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val statements = expression.statements
|
||||||
statements.forEachIndexed { i, statement ->
|
statements.forEachIndexed { i, statement ->
|
||||||
if (i != statements.lastIndex) {
|
if (i != statements.lastIndex) {
|
||||||
generateStatement(statement)
|
generateStatement(statement)
|
||||||
@@ -719,6 +712,32 @@ class BodyGenerator(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun visitContainerExpression(expression: IrContainerExpression) {
|
||||||
|
if (expression.statements.isEmpty()) {
|
||||||
|
if (expression.type == irBuiltIns.unitType) {
|
||||||
|
body.buildGetUnit()
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context.backendContext.isWasmJsTarget && expression.origin == JsExceptionRevealOrigin.JS_EXCEPTION_REVEAL) {
|
||||||
|
body.buildTry(null, context.transformBlockResultType(expression.type))
|
||||||
|
processContainerExpression(expression)
|
||||||
|
val revealLocation = SourceLocation.NoLocation("JS exception reveal")
|
||||||
|
body.buildCatch(functionContext.tagIdx)
|
||||||
|
body.buildInstr(WasmOp.RETHROW, revealLocation, WasmImmediate.LabelIdx(0))
|
||||||
|
body.buildCatchAll()
|
||||||
|
body.buildCall(
|
||||||
|
symbol = context.referenceFunction(context.backendContext.wasmSymbols.jsRelatedSymbols.throwJsException),
|
||||||
|
location = revealLocation
|
||||||
|
)
|
||||||
|
body.buildUnreachable(revealLocation)
|
||||||
|
body.buildEnd()
|
||||||
|
} else {
|
||||||
|
processContainerExpression(expression)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun visitBreak(jump: IrBreak) {
|
override fun visitBreak(jump: IrBreak) {
|
||||||
assert(jump.type == irBuiltIns.nothingType)
|
assert(jump.type == irBuiltIns.nothingType)
|
||||||
body.buildBr(functionContext.referenceLoopLevel(jump.loop, LoopLabelType.BREAK), jump.getSourceLocation())
|
body.buildBr(functionContext.referenceLoopLevel(jump.loop, LoopLabelType.BREAK), jump.getSourceLocation())
|
||||||
|
|||||||
+82
@@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.backend.wasm.lower
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.common.BodyLoweringPass
|
||||||
|
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
|
||||||
|
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||||
|
import org.jetbrains.kotlin.backend.wasm.WasmBackendContext
|
||||||
|
import org.jetbrains.kotlin.backend.wasm.lower.JsExceptionRevealOrigin.Companion.JS_EXCEPTION_REVEAL
|
||||||
|
import org.jetbrains.kotlin.ir.builders.irComposite
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||||
|
import org.jetbrains.kotlin.ir.types.defaultType
|
||||||
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
|
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wraps try block with finalizer and/or catch block for Throwable/JsException into JS reveal intrinsic
|
||||||
|
*
|
||||||
|
* try {
|
||||||
|
* foo()
|
||||||
|
* } catch(e: JsExpression) {
|
||||||
|
* bar()
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
// converts into
|
||||||
|
*
|
||||||
|
* try {
|
||||||
|
* composite { foo() } with origin JS_EXCEPTION_REVEAL
|
||||||
|
* } catch(e: JsExpression) {
|
||||||
|
* bar()
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
|
||||||
|
interface JsExceptionRevealOrigin : IrStatementOrigin {
|
||||||
|
companion object {
|
||||||
|
val JS_EXCEPTION_REVEAL by IrStatementOriginImpl
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class JsExceptionRevealLowering(private val context: WasmBackendContext) : BodyLoweringPass {
|
||||||
|
override fun lower(irBody: IrBody, container: IrDeclaration) {
|
||||||
|
if (context.isWasmJsTarget && !context.configuration.getBoolean(JSConfigurationKeys.WASM_USE_TRAPS_INSTEAD_OF_EXCEPTIONS)) {
|
||||||
|
irBody.transformChildrenVoid(JsExceptionRevealTransformer(context, container.symbol))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class JsExceptionRevealTransformer(
|
||||||
|
val context: WasmBackendContext,
|
||||||
|
val containerSymbol: IrSymbol,
|
||||||
|
) : IrElementTransformerVoidWithContext() {
|
||||||
|
|
||||||
|
private fun needToReveal(aTry: IrTry): Boolean {
|
||||||
|
if (aTry.finallyExpression != null) return true
|
||||||
|
val throwableType = context.irBuiltIns.throwableType
|
||||||
|
val jsExceptionType = context.wasmSymbols.jsRelatedSymbols.jsException.defaultType
|
||||||
|
return aTry.catches.any {
|
||||||
|
it.catchParameter.type.let { it == throwableType || it == jsExceptionType }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitTry(aTry: IrTry): IrExpression {
|
||||||
|
aTry.transformChildrenVoid(this)
|
||||||
|
|
||||||
|
if (!needToReveal(aTry)) return aTry
|
||||||
|
|
||||||
|
context.createIrBuilder(containerSymbol).run {
|
||||||
|
aTry.tryResult = irComposite(
|
||||||
|
resultType = aTry.tryResult.type,
|
||||||
|
origin = JS_EXCEPTION_REVEAL
|
||||||
|
) {
|
||||||
|
+aTry.tryResult
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return aTry
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
-2
@@ -1,9 +1,9 @@
|
|||||||
// TARGET_BACKEND: WASM
|
// TARGET_BACKEND: WASM
|
||||||
|
|
||||||
// RUN_THIRD_PARTY_OPTIMIZER
|
// RUN_THIRD_PARTY_OPTIMIZER
|
||||||
// WASM_DCE_EXPECTED_OUTPUT_SIZE: wasm 12_773
|
// WASM_DCE_EXPECTED_OUTPUT_SIZE: wasm 13_220
|
||||||
// WASM_DCE_EXPECTED_OUTPUT_SIZE: mjs 5_411
|
// WASM_DCE_EXPECTED_OUTPUT_SIZE: mjs 5_411
|
||||||
// WASM_OPT_EXPECTED_OUTPUT_SIZE: 2_640
|
// WASM_OPT_EXPECTED_OUTPUT_SIZE: 2_824
|
||||||
|
|
||||||
// FILE: test.kt
|
// FILE: test.kt
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -1,9 +1,9 @@
|
|||||||
// TARGET_BACKEND: WASM
|
// TARGET_BACKEND: WASM
|
||||||
|
|
||||||
// RUN_THIRD_PARTY_OPTIMIZER
|
// RUN_THIRD_PARTY_OPTIMIZER
|
||||||
// WASM_DCE_EXPECTED_OUTPUT_SIZE: wasm 35_154
|
// WASM_DCE_EXPECTED_OUTPUT_SIZE: wasm 35_681
|
||||||
// WASM_DCE_EXPECTED_OUTPUT_SIZE: mjs 5_431
|
// WASM_DCE_EXPECTED_OUTPUT_SIZE: mjs 5_431
|
||||||
// WASM_OPT_EXPECTED_OUTPUT_SIZE: 8_586
|
// WASM_OPT_EXPECTED_OUTPUT_SIZE: 8_830
|
||||||
|
|
||||||
fun box(): String {
|
fun box(): String {
|
||||||
println("Hello, World!")
|
println("Hello, World!")
|
||||||
|
|||||||
+2
-2
@@ -1,9 +1,9 @@
|
|||||||
// TARGET_BACKEND: WASM
|
// TARGET_BACKEND: WASM
|
||||||
|
|
||||||
// RUN_THIRD_PARTY_OPTIMIZER
|
// RUN_THIRD_PARTY_OPTIMIZER
|
||||||
// WASM_DCE_EXPECTED_OUTPUT_SIZE: wasm 14_178
|
// WASM_DCE_EXPECTED_OUTPUT_SIZE: wasm 14_584
|
||||||
// WASM_DCE_EXPECTED_OUTPUT_SIZE: mjs 5_968
|
// WASM_DCE_EXPECTED_OUTPUT_SIZE: mjs 5_968
|
||||||
// WASM_OPT_EXPECTED_OUTPUT_SIZE: 4_317
|
// WASM_OPT_EXPECTED_OUTPUT_SIZE: 4_570
|
||||||
|
|
||||||
// FILE: test.kt
|
// FILE: test.kt
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
// TARGET_BACKEND: WASM
|
// TARGET_BACKEND: WASM
|
||||||
|
|
||||||
// RUN_THIRD_PARTY_OPTIMIZER
|
// RUN_THIRD_PARTY_OPTIMIZER
|
||||||
// WASM_DCE_EXPECTED_OUTPUT_SIZE: wasm 17_907
|
// WASM_DCE_EXPECTED_OUTPUT_SIZE: wasm 18_320
|
||||||
// WASM_DCE_EXPECTED_OUTPUT_SIZE: mjs 5_277
|
// WASM_DCE_EXPECTED_OUTPUT_SIZE: mjs 5_277
|
||||||
// WASM_OPT_EXPECTED_OUTPUT_SIZE: 5_841
|
// WASM_OPT_EXPECTED_OUTPUT_SIZE: 6_095
|
||||||
|
|
||||||
object Simple
|
object Simple
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -1,8 +1,8 @@
|
|||||||
// TARGET_BACKEND: WASM
|
// TARGET_BACKEND: WASM
|
||||||
|
|
||||||
// RUN_THIRD_PARTY_OPTIMIZER
|
// RUN_THIRD_PARTY_OPTIMIZER
|
||||||
// WASM_DCE_EXPECTED_OUTPUT_SIZE: wasm 12_856
|
// WASM_DCE_EXPECTED_OUTPUT_SIZE: wasm 13_262
|
||||||
// WASM_DCE_EXPECTED_OUTPUT_SIZE: mjs 5_277
|
// WASM_DCE_EXPECTED_OUTPUT_SIZE: mjs 5_277
|
||||||
// WASM_OPT_EXPECTED_OUTPUT_SIZE: 3_743
|
// WASM_OPT_EXPECTED_OUTPUT_SIZE: 3_996
|
||||||
|
|
||||||
fun box() = "OK"
|
fun box() = "OK"
|
||||||
@@ -2,9 +2,9 @@
|
|||||||
// TARGET_BACKEND: WASM
|
// TARGET_BACKEND: WASM
|
||||||
|
|
||||||
// RUN_THIRD_PARTY_OPTIMIZER
|
// RUN_THIRD_PARTY_OPTIMIZER
|
||||||
// WASM_DCE_EXPECTED_OUTPUT_SIZE: wasm 13_321
|
// WASM_DCE_EXPECTED_OUTPUT_SIZE: wasm 13_769
|
||||||
// WASM_DCE_EXPECTED_OUTPUT_SIZE: mjs 5_277
|
// WASM_DCE_EXPECTED_OUTPUT_SIZE: mjs 5_277
|
||||||
// WASM_OPT_EXPECTED_OUTPUT_SIZE: 3_900
|
// WASM_OPT_EXPECTED_OUTPUT_SIZE: 4_153
|
||||||
|
|
||||||
interface I {
|
interface I {
|
||||||
fun foo() = "OK"
|
fun foo() = "OK"
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
// TARGET_BACKEND: WASM
|
||||||
|
|
||||||
|
fun throwSomeJsException(): Int = js("{ throw 42; }")
|
||||||
|
|
||||||
|
fun withFinally(): Boolean {
|
||||||
|
try {
|
||||||
|
throwSomeJsException()
|
||||||
|
return false
|
||||||
|
} finally {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
fun withThrowable(): Boolean {
|
||||||
|
try {
|
||||||
|
throwSomeJsException()
|
||||||
|
return false
|
||||||
|
} catch (_: Throwable) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
fun withJsException(): Boolean {
|
||||||
|
try {
|
||||||
|
throwSomeJsException()
|
||||||
|
return false
|
||||||
|
} catch (_: JsException) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
|
||||||
|
if (!withFinally()) return "FAIL1"
|
||||||
|
if (!withThrowable()) return "FAIL2"
|
||||||
|
if (!withJsException()) return "FAIL3"
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -19,3 +19,7 @@ private fun throwJsError(message: String?, wasmTypeName: String?, stack: Externa
|
|||||||
internal fun throwAsJsException(t: Throwable): Nothing {
|
internal fun throwAsJsException(t: Throwable): Nothing {
|
||||||
throwJsError(t.message, getSimpleName(t.typeInfo), t.jsStack)
|
throwJsError(t.message, getSimpleName(t.typeInfo), t.jsStack)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun throwJsException(): Nothing {
|
||||||
|
throw JsException()
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package kotlin.js
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exception thrown by the JavaScript code.
|
||||||
|
* All exceptions thrown by JS code are signalled to Wasm code as `JsException`.
|
||||||
|
* One can catch such exception in Wasm, but no details of the original exception can be retrieved from it.
|
||||||
|
* */
|
||||||
|
public class JsException : Throwable(message = "Exception was thrown while running JavaScript code")
|
||||||
@@ -139,6 +139,10 @@ abstract class WasmExpressionBuilder {
|
|||||||
buildInstrWithNoLocation(WasmOp.CATCH, WasmImmediate.TagIdx(tagIdx))
|
buildInstrWithNoLocation(WasmOp.CATCH, WasmImmediate.TagIdx(tagIdx))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun buildCatchAll() {
|
||||||
|
buildInstrWithNoLocation(WasmOp.CATCH_ALL)
|
||||||
|
}
|
||||||
|
|
||||||
fun buildBrIf(absoluteBlockLevel: Int, location: SourceLocation) {
|
fun buildBrIf(absoluteBlockLevel: Int, location: SourceLocation) {
|
||||||
buildBrInstr(WasmOp.BR_IF, absoluteBlockLevel, location)
|
buildBrInstr(WasmOp.BR_IF, absoluteBlockLevel, location)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -117,13 +117,13 @@ class WasmIrToText(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (op == WasmOp.END || op == WasmOp.ELSE || op == WasmOp.CATCH)
|
if (op == WasmOp.END || op == WasmOp.ELSE || op == WasmOp.CATCH || op == WasmOp.CATCH_ALL)
|
||||||
indent--
|
indent--
|
||||||
|
|
||||||
newLine()
|
newLine()
|
||||||
stringBuilder.append(wasmInstr.operator.mnemonic)
|
stringBuilder.append(wasmInstr.operator.mnemonic)
|
||||||
|
|
||||||
if (op == WasmOp.BLOCK || op == WasmOp.LOOP || op == WasmOp.IF || op == WasmOp.ELSE || op == WasmOp.CATCH || op == WasmOp.TRY)
|
if (op == WasmOp.BLOCK || op == WasmOp.LOOP || op == WasmOp.IF || op == WasmOp.ELSE || op == WasmOp.CATCH || op == WasmOp.CATCH_ALL || op == WasmOp.TRY)
|
||||||
indent++
|
indent++
|
||||||
|
|
||||||
if (wasmInstr.operator in setOf(WasmOp.CALL_INDIRECT, WasmOp.TABLE_INIT)) {
|
if (wasmInstr.operator in setOf(WasmOp.CALL_INDIRECT, WasmOp.TABLE_INIT)) {
|
||||||
|
|||||||
Generated
+6
@@ -84,6 +84,12 @@ public class FirWasmJsCodegenInteropTestGenerated extends AbstractFirWasmJsCodeg
|
|||||||
runTest("compiler/testData/codegen/boxWasmJsInterop/jsCode.kt");
|
runTest("compiler/testData/codegen/boxWasmJsInterop/jsCode.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("jsException.kt")
|
||||||
|
public void testJsException() {
|
||||||
|
runTest("compiler/testData/codegen/boxWasmJsInterop/jsException.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("jsExport.kt")
|
@TestMetadata("jsExport.kt")
|
||||||
public void testJsExport() {
|
public void testJsExport() {
|
||||||
|
|||||||
+6
@@ -84,6 +84,12 @@ public class K1WasmCodegenWasmJsInteropTestGenerated extends AbstractK1WasmCodeg
|
|||||||
runTest("compiler/testData/codegen/boxWasmJsInterop/jsCode.kt");
|
runTest("compiler/testData/codegen/boxWasmJsInterop/jsCode.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("jsException.kt")
|
||||||
|
public void testJsException() {
|
||||||
|
runTest("compiler/testData/codegen/boxWasmJsInterop/jsException.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("jsExport.kt")
|
@TestMetadata("jsExport.kt")
|
||||||
public void testJsExport() {
|
public void testJsExport() {
|
||||||
|
|||||||
Reference in New Issue
Block a user