[Wasm] Support external vararg
Initial implementation copies Wasm array to JS array and spreads it
This commit is contained in:
committed by
Space Team
parent
99de93bbd6
commit
1564de5859
@@ -211,6 +211,10 @@ class WasmSymbols(
|
||||
val nullableDoubleIeee754Equals = getInternalFunction("nullableDoubleIeee754Equals")
|
||||
|
||||
val unsafeGetScratchRawMemory = getInternalFunction("unsafeGetScratchRawMemory")
|
||||
|
||||
val newJsArray = getInternalFunction("newJsArray")
|
||||
val jsArrayPush = getInternalFunction("jsArrayPush")
|
||||
|
||||
val startCoroutineUninterceptedOrReturnIntrinsics =
|
||||
(0..2).map { getInternalFunction("startCoroutineUninterceptedOrReturnIntrinsic$it") }
|
||||
|
||||
|
||||
+18
-4
@@ -183,7 +183,7 @@ class ComplexExternalDeclarationsToTopLevelFunctionsLowering(val context: WasmBa
|
||||
val jsFun = function.getJsFunAnnotation()
|
||||
// Wrap external functions without @JsFun to lambdas `foo` -> `(a, b) => foo(a, b)`.
|
||||
// This way we wouldn't fail if we don't call them.
|
||||
if (jsFun != null && function.valueParameters.all { it.defaultValue == null })
|
||||
if (jsFun != null && function.valueParameters.all { it.defaultValue == null && it.varargElementType == null })
|
||||
return
|
||||
processFunctionOrConstructor(
|
||||
function = function,
|
||||
@@ -241,9 +241,23 @@ class ComplexExternalDeclarationsToTopLevelFunctionsLowering(val context: WasmBa
|
||||
}
|
||||
append(jsFunctionReference)
|
||||
append("(")
|
||||
appendParameterList(numValueParameters - numDefaultParameters, isEnd = numDefaultParameters == 0)
|
||||
|
||||
val numNonDefaultParamters = numValueParameters - numDefaultParameters
|
||||
repeat(numNonDefaultParamters) {
|
||||
if (function.valueParameters[it].isVararg) {
|
||||
append("...")
|
||||
}
|
||||
append("p$it")
|
||||
if (numDefaultParameters != 0 || it + 1 < numNonDefaultParamters)
|
||||
append(", ")
|
||||
}
|
||||
repeat(numDefaultParameters) {
|
||||
append("isDefault$it ? undefined : p${numValueParameters - numDefaultParameters + it}, ")
|
||||
if (function.valueParameters[numNonDefaultParamters + it].isVararg) {
|
||||
append("...")
|
||||
} else {
|
||||
append("isDefault$it ? undefined : ")
|
||||
}
|
||||
append("p${numNonDefaultParamters + it}, ")
|
||||
}
|
||||
append(")")
|
||||
}
|
||||
@@ -276,7 +290,7 @@ class ComplexExternalDeclarationsToTopLevelFunctionsLowering(val context: WasmBa
|
||||
if (dispatchReceiver != null) {
|
||||
res.addValueParameter("_this", dispatchReceiver.type)
|
||||
}
|
||||
function.valueParameters.forEach { res.addValueParameter(it.name, it.type) }
|
||||
function.valueParameters.forEach { res.addValueParameter(it.name, it.type).apply { varargElementType = it.varargElementType } }
|
||||
// Using Int type with 0 and 1 values to prevent overhead of converting Boolean to true and false
|
||||
repeat(numDefaultParameters) { res.addValueParameter("isDefault$it", context.irBuiltIns.intType) }
|
||||
externalFunToTopLevelMapping[function] = res
|
||||
|
||||
+83
-13
@@ -23,12 +23,14 @@ import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.IrBody
|
||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrInstanceInitializerCallImpl
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
import kotlin.math.absoluteValue
|
||||
|
||||
/**
|
||||
@@ -89,8 +91,13 @@ class JsInteropFunctionsLowering(val context: WasmBackendContext) : DeclarationT
|
||||
// Patch function types for Number parameters as double
|
||||
function.returnType = doubleIfNumber(function.returnType)
|
||||
|
||||
val valueParametersAdapters = function.valueParameters.map {
|
||||
it.type.kotlinToJsAdapterIfNeeded(isReturn = false)
|
||||
val valueParametersAdapters = function.valueParameters.map { parameter ->
|
||||
val varargElementType = parameter.varargElementType
|
||||
if (varargElementType != null) {
|
||||
CopyToJsArrayAdapter(parameter.type, varargElementType)
|
||||
} else {
|
||||
parameter.type.kotlinToJsAdapterIfNeeded(isReturn = false)
|
||||
}
|
||||
}
|
||||
val resultAdapter =
|
||||
function.returnType.jsToKotlinAdapterIfNeeded(isReturn = true)
|
||||
@@ -191,6 +198,16 @@ class JsInteropFunctionsLowering(val context: WasmBackendContext) : DeclarationT
|
||||
)
|
||||
}
|
||||
|
||||
val primitivesToExternRefAdapters: Map<IrType, InteropTypeAdapter> = mapOf(
|
||||
builtIns.byteType to adapters.kotlinByteToExternRefAdapter,
|
||||
builtIns.shortType to adapters.kotlinShortToExternRefAdapter,
|
||||
builtIns.charType to adapters.kotlinCharToExternRefAdapter,
|
||||
builtIns.intType to adapters.kotlinIntToExternRefAdapter,
|
||||
builtIns.longType to adapters.kotlinLongToExternRefAdapter,
|
||||
builtIns.floatType to adapters.kotlinFloatToExternRefAdapter,
|
||||
builtIns.doubleType to adapters.kotlinDoubleToExternRefAdapter,
|
||||
).mapValues { FunctionBasedAdapter(it.value.owner) }
|
||||
|
||||
private fun IrType.kotlinToJsAdapterIfNeeded(isReturn: Boolean): InteropTypeAdapter? {
|
||||
if (isReturn && this == builtIns.unitType)
|
||||
return null
|
||||
@@ -213,18 +230,9 @@ class JsInteropFunctionsLowering(val context: WasmBackendContext) : DeclarationT
|
||||
)
|
||||
}
|
||||
|
||||
val primitiveToExternRefAdapter = when (notNullType) {
|
||||
builtIns.byteType -> adapters.kotlinByteToExternRefAdapter.owner
|
||||
builtIns.shortType -> adapters.kotlinShortToExternRefAdapter.owner
|
||||
builtIns.charType -> adapters.kotlinCharToExternRefAdapter.owner
|
||||
builtIns.intType -> adapters.kotlinIntToExternRefAdapter.owner
|
||||
builtIns.longType -> adapters.kotlinLongToExternRefAdapter.owner
|
||||
builtIns.floatType -> adapters.kotlinFloatToExternRefAdapter.owner
|
||||
builtIns.doubleType -> adapters.kotlinDoubleToExternRefAdapter.owner
|
||||
else -> null
|
||||
}
|
||||
val primitiveToExternRefAdapter = primitivesToExternRefAdapters[notNullType]
|
||||
|
||||
val typeAdapter = primitiveToExternRefAdapter?.let(::FunctionBasedAdapter)
|
||||
val typeAdapter = primitiveToExternRefAdapter
|
||||
?: notNullType.kotlinToJsAdapterIfNeededNotNullable(isReturn)
|
||||
?: return null
|
||||
|
||||
@@ -770,6 +778,68 @@ class JsInteropFunctionsLowering(val context: WasmBackendContext) : DeclarationT
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Vararg parameter adapter
|
||||
*/
|
||||
inner class CopyToJsArrayAdapter(
|
||||
override val fromType: IrType,
|
||||
private val fromElementType: IrType,
|
||||
) : InteropTypeAdapter {
|
||||
override val toType: IrType =
|
||||
context.wasmSymbols.externalInterfaceType
|
||||
|
||||
private val elementAdapter =
|
||||
primitivesToExternRefAdapters[fromElementType]
|
||||
?: fromElementType.kotlinToJsAdapterIfNeeded(false)
|
||||
|
||||
private val arrayClass = fromType.classOrNull!!
|
||||
private val getMethod = arrayClass.getSimpleFunction("get")!!.owner
|
||||
private val sizeMethod = arrayClass.getPropertyGetter("size")!!.owner
|
||||
|
||||
override fun adapt(expression: IrExpression, builder: IrBuilderWithScope): IrExpression {
|
||||
return builder.irComposite {
|
||||
val originalArrayVar = irTemporary(expression)
|
||||
|
||||
// val newJsArray = []
|
||||
// var index = 0
|
||||
// while(index != size) {
|
||||
// newJsArray.push(adapt(originalArray[index]));
|
||||
// index++
|
||||
// }
|
||||
val newJsArrayVar = irTemporary(irCall(symbols.newJsArray))
|
||||
val indexVar = irTemporary(irInt(0), isMutable = true)
|
||||
val arraySizeVar = irTemporary(irCall(sizeMethod).apply { dispatchReceiver = irGet(originalArrayVar) })
|
||||
|
||||
+irWhile().apply {
|
||||
condition = irNotEquals(irGet(indexVar), irGet(arraySizeVar))
|
||||
body = irBlock {
|
||||
val adaptedValue = elementAdapter.adaptIfNeeded(
|
||||
irImplicitCast(
|
||||
irCall(getMethod).apply {
|
||||
dispatchReceiver = irGet(originalArrayVar)
|
||||
putValueArgument(0, irGet(indexVar))
|
||||
},
|
||||
fromElementType
|
||||
),
|
||||
this@irBlock
|
||||
)
|
||||
+irCall(symbols.jsArrayPush).apply {
|
||||
putValueArgument(0, irGet(newJsArrayVar))
|
||||
putValueArgument(1, adaptedValue)
|
||||
}
|
||||
val inc = indexVar.type.getClass()!!.functions.single { it.name == OperatorNameConventions.INC }
|
||||
+irSet(
|
||||
indexVar,
|
||||
irCallOp(inc.symbol, indexVar.type, irGet(indexVar)),
|
||||
origin = IrStatementOrigin.PREFIX_INCR
|
||||
)
|
||||
}
|
||||
}
|
||||
+irGet(newJsArrayVar)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal fun StringBuilder.appendParameterList(size: Int, name: String = "p", isEnd: Boolean = true) =
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
function paramCount() {
|
||||
return arguments.length
|
||||
}
|
||||
|
||||
function Bar(size, order) {
|
||||
this.size = size;
|
||||
Bar.checkOrder(order);
|
||||
}
|
||||
|
||||
Bar.order = 0;
|
||||
Bar.hasOrderProblem = false;
|
||||
Bar.checkOrder = function (expectedOrder) {
|
||||
var curOrder = Bar.order++;
|
||||
Bar.hasOrderProblem = Bar.hasOrderProblem || curOrder !== expectedOrder;
|
||||
};
|
||||
|
||||
Bar.startNewTest = function () {
|
||||
Bar.hasOrderProblem = false;
|
||||
Bar.order = 0;
|
||||
return true;
|
||||
};
|
||||
|
||||
|
||||
Bar.prototype.test = function (order, dummy /*, args */) {
|
||||
Bar.checkOrder(order);
|
||||
return dummy === 1 && (arguments.length - 2) === this.size;
|
||||
};
|
||||
Bar.prototype.test2 = Bar.prototype.test;
|
||||
|
||||
function test3(bar, dummy /*, args */) {
|
||||
return dummy === 1 && (arguments.length - 2) === bar.size;
|
||||
}
|
||||
|
||||
var obj = {
|
||||
test: function (size /*, args */) {
|
||||
return (arguments.length - 1) === size;
|
||||
}
|
||||
};
|
||||
|
||||
function testNativeVarargWithFunLit(/* args, f */) {
|
||||
var args = Array.prototype.slice.call(arguments, 0, arguments.length - 1);
|
||||
var f = arguments[arguments.length - 1];
|
||||
return typeof f === "function" && f(args);
|
||||
}
|
||||
|
||||
function sumOfParameters() {
|
||||
var size = arguments.length;
|
||||
var result = 0;
|
||||
for (var i = 0; i < size; i++) {
|
||||
result += arguments[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function sumFunValuesOnParameters() {
|
||||
var size = arguments.length - 1;
|
||||
var f = arguments[arguments.length - 1];
|
||||
var result = 0;
|
||||
for (var i = 0; i < size; i++) {
|
||||
var u = arguments[i];
|
||||
result += f(u);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function idArrayVarArg() {
|
||||
var args = Array.prototype.slice.call(arguments, 0, arguments.length);
|
||||
return args;
|
||||
}
|
||||
|
||||
function join(...args) {
|
||||
return args.join("-");
|
||||
}
|
||||
|
||||
function mapJoin(f, ...args) {
|
||||
return args.map(x => f(x)).join("-")
|
||||
}
|
||||
@@ -0,0 +1,197 @@
|
||||
// IGNORE_BACKEND_K2: JS_IR
|
||||
|
||||
// Partial copy of js/js.translator/testData/box/native/vararg.kt
|
||||
// With some additions for concrete number types, strings and function references
|
||||
|
||||
package foo
|
||||
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
external fun paramCount(vararg a: Int): Int = definedExternally
|
||||
|
||||
@JsName("paramCount")
|
||||
external fun anotherParamCount(vararg a: Int): Int = definedExternally
|
||||
|
||||
// test spread operator
|
||||
fun count(vararg a: Int) = paramCount(*a)
|
||||
|
||||
// test spread operator
|
||||
fun anotherCount(vararg a: Int) = anotherParamCount(*a)
|
||||
|
||||
external fun test3(bar: Bar, dummy: Int, vararg args: Int): Boolean = definedExternally
|
||||
|
||||
external class Bar(size: Int, order: Int = definedExternally) {
|
||||
val size: Int
|
||||
fun test(order: Int, dummy: Int, vararg args: Int): Boolean = definedExternally
|
||||
companion object {
|
||||
fun startNewTest(): Boolean = definedExternally
|
||||
var hasOrderProblem: Boolean = definedExternally
|
||||
}
|
||||
}
|
||||
|
||||
external object obj {
|
||||
fun test(size: Int, vararg args: Int): Boolean = definedExternally
|
||||
}
|
||||
|
||||
fun spreadInMethodCall(size: Int, vararg args: Int) = Bar(size).test(0, 1, *args)
|
||||
|
||||
fun spreadInObjectMethodCall(size: Int, vararg args: Int) = obj.test(size, *args)
|
||||
|
||||
fun spreadInPackageMethodCall(size: Int, vararg args: Int) = test3(Bar(size), 1, *args)
|
||||
|
||||
fun testSpreadOperatorWithSafeCall(a: Bar?, expected: Boolean?, vararg args: Int): Boolean {
|
||||
return a?.test(0, 1, *args) == expected
|
||||
}
|
||||
|
||||
fun testSpreadOperatorWithSureCall(a: Bar?, vararg args: Int): Boolean {
|
||||
return a!!.test(0, 1, *args)
|
||||
}
|
||||
|
||||
fun testCallOrder(vararg args: Int) =
|
||||
Bar.startNewTest() &&
|
||||
Bar(args.size, 0).test(1, 1, *args) && Bar(args.size, 2).test(3, 1, *args) &&
|
||||
!Bar.hasOrderProblem
|
||||
|
||||
external fun sumOfParameters(x: Int, y: Int, vararg a: Int): Int = definedExternally
|
||||
|
||||
external fun sumFunValuesOnParameters(x: Int, y: Int, vararg a: Int, f: (Int) -> Int): Int = definedExternally
|
||||
|
||||
fun runCallable(fn: (Int, Int, Int, Int, Int) -> Int, a1: Int, a2: Int, a3: Int, a4: Int, a5: Int): Int = fn(a1, a2, a3, a4, a5)
|
||||
|
||||
@JsName("join")
|
||||
external fun joinBoolean(vararg x: Boolean): String
|
||||
|
||||
@JsName("join")
|
||||
external fun joinByte(vararg x: Byte): String
|
||||
|
||||
@JsName("join")
|
||||
external fun joinChar(vararg x: Char): String
|
||||
|
||||
@JsName("join")
|
||||
external fun joinShort(vararg x: Short): String
|
||||
|
||||
@JsName("join")
|
||||
external fun joinInt(vararg x: Int): String
|
||||
|
||||
@JsName("join")
|
||||
external fun joinLong(vararg x: Long): String
|
||||
|
||||
@JsName("join")
|
||||
external fun joinFloat(vararg x: Float): String
|
||||
|
||||
@JsName("join")
|
||||
external fun joinDouble(vararg x: Double): String
|
||||
|
||||
@JsName("join")
|
||||
external fun joinString(vararg x: String): String
|
||||
|
||||
@JsName("mapJoin")
|
||||
external fun mapJoin(f: ((String) -> String) -> String, vararg x: (String) -> String): String
|
||||
|
||||
@JsName("join")
|
||||
external fun joinWithDefault(a: Int = definedExternally, b: Int = definedExternally, vararg c: Int, d: Int = definedExternally): String
|
||||
|
||||
fun box(): String {
|
||||
if (paramCount() != 0)
|
||||
return "failed when call native function without args"
|
||||
|
||||
if (paramCount(1) != 1) return "failed when call native function with single vararg"
|
||||
|
||||
if (paramCount(1, 2, 3) != 3)
|
||||
return "failed when call native function with some args"
|
||||
|
||||
if (anotherParamCount(1, 2, 3) != 3)
|
||||
return "failed when call native function with some args witch declareted with custom name"
|
||||
|
||||
if (count() != 0)
|
||||
return "failed when call native function without args using spread operator"
|
||||
|
||||
if (count(1, 1, 1, 1) != 4)
|
||||
return "failed when call native function with some args using spread operator"
|
||||
|
||||
if (anotherCount(1, 2, 3) != 3)
|
||||
return "failed when call native function with some args using spread operator witch declareted with custom name"
|
||||
|
||||
if (!Bar(5).test(0, 1, 1, 2, 3, 4, 5))
|
||||
return "failed when call method with some args"
|
||||
|
||||
if (!spreadInMethodCall(2, 1, 2))
|
||||
return "failed when call method using spread operator"
|
||||
|
||||
if (!Bar(1).test(0, 1, 1))
|
||||
return "failed when call method with single arg"
|
||||
|
||||
if (!spreadInMethodCall(2, 1, 2))
|
||||
return "failed when call method using spread operator"
|
||||
|
||||
if (!(obj.test(5, 1, 2, 3, 4, 5)))
|
||||
return "failed when call method of object"
|
||||
|
||||
if (!(spreadInObjectMethodCall(2, 1, 2)))
|
||||
return "failed when call method of object using spread operator"
|
||||
|
||||
if (!spreadInPackageMethodCall(2, 1, 2))
|
||||
return "failed when call package method using spread operator"
|
||||
|
||||
if (!(testSpreadOperatorWithSafeCall(null, null)))
|
||||
return "failed when test spread operator with SafeCall (?.) using null receiver"
|
||||
|
||||
if (!(testSpreadOperatorWithSafeCall(Bar(3), true, 1, 2, 3)))
|
||||
return "failed when test spread operator with SafeCall (?.)"
|
||||
|
||||
if (!(testSpreadOperatorWithSureCall(Bar(3), 1, 2, 3)))
|
||||
return "failed when test spread operator with SureCall (!!)"
|
||||
|
||||
if (!(testCallOrder()))
|
||||
return "failed when test calling order when using spread operator without args"
|
||||
|
||||
if (!(testCallOrder(1, 2, 3, 4)))
|
||||
return "failed when test calling order when using spread operator with some args"
|
||||
|
||||
val baz: Bar? = Bar(1)
|
||||
if (!(baz!!)?.test(0, 1, 1)!!)
|
||||
return "failed when combined SureCall and SafeCall, maybe we lost cached expression"
|
||||
|
||||
assertEquals(45, sumOfParameters(1, 2, 3, 4, 5, 6, 7, 8, 9))
|
||||
assertEquals(45, sumOfParameters(1, 2, *intArrayOf(3, 4, 5, 6, 7, 8, 9)))
|
||||
assertEquals(45, sumOfParameters(1, 2, a = *intArrayOf(3, 4, 5, 6, 7, 8, 9)))
|
||||
assertEquals(45, sumOfParameters(1, 2, a = intArrayOf(3, 4, 5, 6, 7, 8, 9)))
|
||||
assertEquals(45, sumOfParameters(1, 2, 3, 4, *intArrayOf(5, 6, 7, 8, 9)))
|
||||
assertEquals(90, sumFunValuesOnParameters(1, 2, 3, 4, 5, 6, 7, 8, 9) { 2*it })
|
||||
assertEquals(90, sumFunValuesOnParameters(1, 2, *intArrayOf(3, 4, 5, 6, 7, 8, 9)) { 2*it })
|
||||
assertEquals(90, sumFunValuesOnParameters(1, 2, a = *intArrayOf(3, 4, 5, 6, 7, 8, 9)) { 2*it })
|
||||
assertEquals(90, sumFunValuesOnParameters(1, 2, a = intArrayOf(3, 4, 5, 6, 7, 8, 9)) { 2*it })
|
||||
assertEquals(90, sumFunValuesOnParameters(1, 2, 3, 4, *intArrayOf(5, 6, 7, 8, 9)) { 2*it })
|
||||
assertEquals(90, sumFunValuesOnParameters(1, 2, *intArrayOf(3, 4, 5, 6, 7), 8, 9) { 2*it })
|
||||
assertEquals(90, sumFunValuesOnParameters(1, 2, *intArrayOf(3, 4, 5), *intArrayOf(6, 7, 8, 9)) { 2*it })
|
||||
assertEquals(90, sumFunValuesOnParameters(1, 2, *intArrayOf(3, 4), 5, 6, *intArrayOf(7, 8, 9)) { 2*it })
|
||||
|
||||
assertEquals(5, runCallable(::paramCount, 1, 2, 3, 4, 5))
|
||||
assertEquals(5, runCallable(::anotherParamCount, 1, 2, 3, 4, 5))
|
||||
assertEquals(5, runCallable(::anotherCount, 1, 2, 3, 4, 5))
|
||||
assertEquals(11111, runCallable(::sumOfParameters, 1, 10, 100, 1000, 10000))
|
||||
|
||||
if (joinBoolean(true, false, true) != "true-false-true") return "Fail1"
|
||||
if (joinByte(10.toByte(), 20.toByte(), 30.toByte()) != "10-20-30") return "Fail2"
|
||||
if (joinChar(10.toChar(), 20.toChar(), 30.toChar()) != "10-20-30") return "Fail3"
|
||||
if (joinShort(10.toShort(), 20.toShort(), 30.toShort()) != "10-20-30") return "Fail4"
|
||||
if (joinInt(10.toInt(), 20.toInt(), 30.toInt()) != "10-20-30") return "Fail5"
|
||||
if (joinLong(10.toLong(), 20.toLong(), 30.toLong()) != "10-20-30") return "Fail6"
|
||||
if (joinFloat(10.toFloat(), 20.toFloat(), 30.toFloat()) != "10-20-30") return "Fail7"
|
||||
if (joinDouble(10.toDouble(), 20.toDouble(), 30.toDouble()) != "10-20-30") return "Fail8"
|
||||
|
||||
if (joinString("a", "b", "c") != "a-b-c") return "Fail9"
|
||||
|
||||
if (
|
||||
mapJoin(
|
||||
f = { f -> f("a")},
|
||||
{ it + "10" },
|
||||
{ it + "20" },
|
||||
{ it + "30" }
|
||||
) != "a10-a20-a30"
|
||||
) { return "Fail10" }
|
||||
|
||||
if (joinWithDefault(10, 20, 30, 40, d = 50) != "10-20-30-40-50") return "Fail11"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
Generated
+6
@@ -84,4 +84,10 @@ public class FirJsCodegenWasmJsInteropTestGenerated extends AbstractFirJsCodegen
|
||||
public void testTypes() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxWasmJsInterop/types.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("vararg.kt")
|
||||
public void testVararg() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxWasmJsInterop/vararg.kt");
|
||||
}
|
||||
}
|
||||
|
||||
Generated
+6
@@ -84,4 +84,10 @@ public class IrCodegenWasmJsInteropJsTestGenerated extends AbstractIrCodegenWasm
|
||||
public void testTypes() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxWasmJsInterop/types.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("vararg.kt")
|
||||
public void testVararg() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxWasmJsInterop/vararg.kt");
|
||||
}
|
||||
}
|
||||
|
||||
+5
@@ -100,6 +100,11 @@ public class IrCodegenWasmJsInteropWasmTestGenerated extends AbstractIrCodegenWa
|
||||
runTest("compiler/testData/codegen/boxWasmJsInterop/types.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("vararg.kt")
|
||||
public void testVararg() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxWasmJsInterop/vararg.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("wasmImport.kt")
|
||||
public void testWasmImport() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxWasmJsInterop/wasmImport.kt");
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: WASM
|
||||
// EXPECTED_REACHABLE_NODES: 1281
|
||||
import Test.test
|
||||
|
||||
|
||||
@@ -324,3 +324,9 @@ internal fun kotlinShortToExternRefAdapter(x: Short): ExternalInterfaceType =
|
||||
|
||||
internal fun kotlinCharToExternRefAdapter(x: Char): ExternalInterfaceType =
|
||||
intToExternref(x.toInt())
|
||||
|
||||
@JsFun("() => []")
|
||||
internal external fun newJsArray(): ExternalInterfaceType
|
||||
|
||||
@JsFun("(array, element) => { array.push(element); }")
|
||||
internal external fun jsArrayPush(array: ExternalInterfaceType, element: ExternalInterfaceType)
|
||||
Reference in New Issue
Block a user