[K/Wasm] Allow to export unsigned numbers
This commit is contained in:
+1
-1
@@ -72,5 +72,5 @@ private fun isTypeSupportedInWasmInterop(
|
||||
}
|
||||
|
||||
// Primitive numbers and Boolean are supported
|
||||
return type.isPrimitive && !type.isChar
|
||||
return (type.isPrimitive && !type.isChar) || type.isUnsignedType
|
||||
}
|
||||
+1
-1
@@ -122,7 +122,7 @@ private fun isTypeSupportedInJsInterop(
|
||||
|
||||
val nonNullable = type.withNullability(ConeNullability.NOT_NULL, session.typeContext)
|
||||
|
||||
if (nonNullable.isPrimitive || nonNullable.isString) {
|
||||
if (nonNullable.isPrimitive || nonNullable.isUnsignedType || nonNullable.isString) {
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
@@ -133,6 +133,12 @@ class WasmSymbols(
|
||||
val voidType by lazy { voidClass.defaultType }
|
||||
|
||||
private val consumeAnyIntoVoid = getInternalFunction("consumeAnyIntoVoid")
|
||||
|
||||
val uByteType by lazy { getIrClass(FqName("kotlin.UByte")).defaultType }
|
||||
val uShortType by lazy { getIrClass(FqName("kotlin.UShort")).defaultType }
|
||||
val uIntType by lazy { getIrClass(FqName("kotlin.UInt")).defaultType }
|
||||
val uLongType by lazy { getIrClass(FqName("kotlin.ULong")).defaultType }
|
||||
|
||||
private val consumePrimitiveIntoVoid = mapOf(
|
||||
context.irBuiltIns.booleanType to getInternalFunction("consumeBooleanIntoVoid"),
|
||||
context.irBuiltIns.byteType to getInternalFunction("consumeByteIntoVoid"),
|
||||
@@ -325,6 +331,11 @@ class WasmSymbols(
|
||||
val externRefToKotlinFloatAdapter = getInternalFunction("externRefToKotlinFloatAdapter")
|
||||
val externRefToKotlinDoubleAdapter = getInternalFunction("externRefToKotlinDoubleAdapter")
|
||||
|
||||
val externRefToKotlinUByteAdapter = getInternalFunction("externRefToKotlinUByteAdapter")
|
||||
val externRefToKotlinUShortAdapter = getInternalFunction("externRefToKotlinUShortAdapter")
|
||||
val externRefToKotlinUIntAdapter = getInternalFunction("externRefToKotlinUIntAdapter")
|
||||
val externRefToKotlinULongAdapter = getInternalFunction("externRefToKotlinULongAdapter")
|
||||
|
||||
val kotlinIntToExternRefAdapter = getInternalFunction("kotlinIntToExternRefAdapter")
|
||||
val kotlinBooleanToExternRefAdapter = getInternalFunction("kotlinBooleanToExternRefAdapter")
|
||||
val kotlinLongToExternRefAdapter = getInternalFunction("kotlinLongToExternRefAdapter")
|
||||
@@ -333,6 +344,11 @@ class WasmSymbols(
|
||||
val kotlinByteToExternRefAdapter = getInternalFunction("kotlinByteToExternRefAdapter")
|
||||
val kotlinShortToExternRefAdapter = getInternalFunction("kotlinShortToExternRefAdapter")
|
||||
val kotlinCharToExternRefAdapter = getInternalFunction("kotlinCharToExternRefAdapter")
|
||||
|
||||
val kotlinUByteToJsNumber = getInternalFunction("kotlinUByteToJsNumber")
|
||||
val kotlinUShortToJsNumber = getInternalFunction("kotlinUShortToJsNumber")
|
||||
val kotlinUIntToJsNumber = getInternalFunction("kotlinUIntToJsNumber")
|
||||
val kotlinULongToJsBigInt = getInternalFunction("kotlinULongToJsBigInt")
|
||||
}
|
||||
|
||||
inner class JsRelatedSymbols {
|
||||
|
||||
+40
-9
@@ -210,13 +210,19 @@ class JsInteropFunctionsLowering(val context: WasmBackendContext) : DeclarationT
|
||||
val primitivesToExternRefAdapters: Map<IrType, InteropTypeAdapter> by lazy {
|
||||
mapOf(
|
||||
builtIns.byteType to adapters.kotlinByteToExternRefAdapter,
|
||||
symbols.uByteType to adapters.kotlinUByteToJsNumber,
|
||||
builtIns.shortType to adapters.kotlinShortToExternRefAdapter,
|
||||
symbols.uShortType to adapters.kotlinUShortToJsNumber,
|
||||
builtIns.charType to adapters.kotlinCharToExternRefAdapter,
|
||||
builtIns.intType to adapters.kotlinIntToExternRefAdapter,
|
||||
symbols.uIntType to adapters.kotlinUIntToJsNumber,
|
||||
builtIns.longType to adapters.kotlinLongToExternRefAdapter,
|
||||
symbols.uLongType to adapters.kotlinULongToJsBigInt,
|
||||
builtIns.floatType to adapters.kotlinFloatToExternRefAdapter,
|
||||
builtIns.doubleType to adapters.kotlinDoubleToExternRefAdapter,
|
||||
).mapValues { FunctionBasedAdapter(it.value.owner) }
|
||||
).mapValues {
|
||||
FunctionBasedAdapter(it.value.owner)
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrType.kotlinToJsAdapterIfNeeded(isReturn: Boolean): InteropTypeAdapter? {
|
||||
@@ -263,6 +269,11 @@ class JsInteropFunctionsLowering(val context: WasmBackendContext) : DeclarationT
|
||||
builtIns.anyType -> return FunctionBasedAdapter(adapters.kotlinToJsAnyAdapter.owner)
|
||||
builtIns.numberType -> return FunctionBasedAdapter(adapters.numberToDoubleAdapter.owner)
|
||||
|
||||
symbols.uByteType -> return FunctionBasedAdapter(adapters.kotlinUByteToJsNumber.owner)
|
||||
symbols.uShortType -> return FunctionBasedAdapter(adapters.kotlinUShortToJsNumber.owner)
|
||||
symbols.uIntType -> return FunctionBasedAdapter(adapters.kotlinUIntToJsNumber.owner)
|
||||
symbols.uLongType -> return FunctionBasedAdapter(adapters.kotlinULongToJsBigInt.owner)
|
||||
|
||||
builtIns.byteType,
|
||||
builtIns.shortType,
|
||||
builtIns.charType,
|
||||
@@ -320,16 +331,28 @@ class JsInteropFunctionsLowering(val context: WasmBackendContext) : DeclarationT
|
||||
return SendKotlinObjectToJsAdapter(this)
|
||||
}
|
||||
|
||||
private fun createNullableAdapter(notNullType: IrType, isPrimitive: Boolean, valueAdapter: InteropTypeAdapter?): InteropTypeAdapter? {
|
||||
return if (isPrimitive) { //nullable primitive should be checked and adapt to target type
|
||||
private fun createNullableAdapter(
|
||||
notNullType: IrType,
|
||||
isPrimitiveOrUnsigned: Boolean,
|
||||
valueAdapter: InteropTypeAdapter?
|
||||
): InteropTypeAdapter? {
|
||||
return if (isPrimitiveOrUnsigned) { //nullable primitive should be checked and adapt to target type
|
||||
val externRefToPrimitiveAdapter = when (notNullType) {
|
||||
builtIns.floatType -> adapters.externRefToKotlinFloatAdapter.owner
|
||||
builtIns.doubleType -> adapters.externRefToKotlinDoubleAdapter.owner
|
||||
builtIns.longType -> adapters.externRefToKotlinLongAdapter.owner
|
||||
builtIns.booleanType -> adapters.externRefToKotlinBooleanAdapter.owner
|
||||
|
||||
symbols.uByteType -> adapters.externRefToKotlinUByteAdapter.owner
|
||||
symbols.uShortType -> adapters.externRefToKotlinUShortAdapter.owner
|
||||
symbols.uIntType -> adapters.externRefToKotlinUIntAdapter.owner
|
||||
symbols.uLongType -> adapters.externRefToKotlinULongAdapter.owner
|
||||
|
||||
else -> adapters.externRefToKotlinIntAdapter.owner
|
||||
}
|
||||
|
||||
val externalToPrimitiveAdapter = FunctionBasedAdapter(externRefToPrimitiveAdapter)
|
||||
|
||||
NullOrAdapter(
|
||||
adapter = valueAdapter?.let { CombineAdapter(it, externalToPrimitiveAdapter) } ?: externalToPrimitiveAdapter
|
||||
)
|
||||
@@ -342,9 +365,13 @@ class JsInteropFunctionsLowering(val context: WasmBackendContext) : DeclarationT
|
||||
}
|
||||
}
|
||||
|
||||
private fun createNotNullAdapter(notNullType: IrType, isPrimitive: Boolean, valueAdapter: InteropTypeAdapter?): InteropTypeAdapter? {
|
||||
private fun createNotNullAdapter(
|
||||
notNullType: IrType,
|
||||
isPrimitiveOrUnsigned: Boolean,
|
||||
valueAdapter: InteropTypeAdapter?
|
||||
): InteropTypeAdapter? {
|
||||
// !nullable primitive checked by wasm signature
|
||||
if (isPrimitive) return valueAdapter
|
||||
if (isPrimitiveOrUnsigned) return valueAdapter
|
||||
|
||||
// !nullable reference should be null checked
|
||||
// notNullAdapter((undefined -> null)!!)
|
||||
@@ -367,12 +394,12 @@ class JsInteropFunctionsLowering(val context: WasmBackendContext) : DeclarationT
|
||||
|
||||
val notNullType = makeNotNull()
|
||||
val valueAdapter = notNullType.jsToKotlinAdapterIfNeededNotNullable(isReturn)
|
||||
val isPrimitive = valueAdapter?.fromType?.isPrimitiveType() ?: notNullType.isPrimitiveType()
|
||||
val isPrimitiveOrUnsigned = (valueAdapter?.fromType ?: notNullType).let { it.isPrimitiveType() || it.isUnsigned() }
|
||||
|
||||
return if (isNullable())
|
||||
createNullableAdapter(notNullType, isPrimitive, valueAdapter)
|
||||
createNullableAdapter(notNullType, isPrimitiveOrUnsigned, valueAdapter)
|
||||
else
|
||||
createNotNullAdapter(notNullType, isPrimitive, valueAdapter)
|
||||
createNotNullAdapter(notNullType, isPrimitiveOrUnsigned, valueAdapter)
|
||||
}
|
||||
|
||||
private fun IrType.jsToKotlinAdapterIfNeededNotNullable(isReturn: Boolean): InteropTypeAdapter? {
|
||||
@@ -386,12 +413,16 @@ class JsInteropFunctionsLowering(val context: WasmBackendContext) : DeclarationT
|
||||
builtIns.shortType -> return FunctionBasedAdapter(adapters.jsToKotlinShortAdapter.owner)
|
||||
builtIns.charType -> return FunctionBasedAdapter(adapters.jsToKotlinCharAdapter.owner)
|
||||
|
||||
symbols.uByteType,
|
||||
symbols.uShortType,
|
||||
symbols.uIntType,
|
||||
symbols.uLongType,
|
||||
builtIns.booleanType,
|
||||
builtIns.intType,
|
||||
builtIns.longType,
|
||||
builtIns.floatType,
|
||||
builtIns.doubleType,
|
||||
context.wasmSymbols.voidType ->
|
||||
symbols.voidType ->
|
||||
return null
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,150 @@
|
||||
// TARGET_BACKEND: WASM
|
||||
// FILE: externals.js
|
||||
function provideUByte() { return -1 }
|
||||
function provideNullableUByte(nullable) { return nullable ? null : - 1 }
|
||||
|
||||
function consumeUByte(x) { return x.toString() }
|
||||
function consumeNullableUByte(x) { return x == null ? null : x.toString() }
|
||||
|
||||
function provideUShort() { return -1 }
|
||||
function provideNullableUShort(nullable) { return nullable ? null : - 1 }
|
||||
|
||||
function consumeUShort(x) { return x.toString() }
|
||||
function consumeNullableUShort(x) { return x == null ? null : x.toString() }
|
||||
|
||||
function provideUInt() { return -1 }
|
||||
function provideNullableUInt(nullable) { return nullable ? null : - 1 }
|
||||
|
||||
function consumeUInt(x) { return x.toString() }
|
||||
function consumeNullableUInt(x) { return x == null ? null : x.toString() }
|
||||
|
||||
function provideULong() { return -1n }
|
||||
function provideNullableULong(nullable) { return nullable ? null : - 1n }
|
||||
|
||||
function consumeULong(x) { return x.toString() }
|
||||
function consumeNullableULong(x) { return x == null ? null : x.toString() }
|
||||
|
||||
function consumeUByteVararg(x) { return x.toString() }
|
||||
function consumeNullableUByteVararg(x) { return x == null ? null : x.toString() }
|
||||
|
||||
function consumeUShortVararg(x) { return x.toString() }
|
||||
function consumeNullableUShortVararg(x) { return x == null ? null : x.toString() }
|
||||
|
||||
function consumeUIntVararg(x) { return x.toString() }
|
||||
function consumeNullableUIntVararg(x) { return x == null ? null : x.toString() }
|
||||
|
||||
function consumeULongVararg(x) { return x.toString() }
|
||||
function consumeNullableULongVararg(x) { return x == null ? null : x.toString() }
|
||||
|
||||
// FILE: externals.kt
|
||||
external fun provideUByte(): UByte
|
||||
|
||||
external fun provideNullableUByte(nullable: Boolean): UByte?
|
||||
|
||||
external fun consumeUByte(x: UByte): String
|
||||
|
||||
external fun consumeNullableUByte(x: UByte?): String?
|
||||
|
||||
external fun provideUShort(): UShort
|
||||
|
||||
external fun provideNullableUShort(nullable: Boolean): UShort?
|
||||
|
||||
external fun consumeUShort(x: UShort): String
|
||||
|
||||
external fun consumeNullableUShort(x: UShort?): String?
|
||||
|
||||
external fun provideUInt(): UInt
|
||||
|
||||
external fun provideNullableUInt(nullable: Boolean): UInt?
|
||||
|
||||
external fun consumeUInt(x: UInt): String
|
||||
|
||||
external fun consumeNullableUInt(x: UInt?): String?
|
||||
|
||||
external fun provideULong(): ULong
|
||||
|
||||
external fun provideNullableULong(nullable: Boolean): ULong?
|
||||
|
||||
external fun consumeULong(x: ULong): String
|
||||
|
||||
external fun consumeNullableULong(x: ULong?): String?
|
||||
|
||||
external fun consumeUByteVararg(vararg shorts: UByte): String
|
||||
|
||||
external fun consumeNullableUByteVararg(vararg shorts: UByte?): String?
|
||||
|
||||
external fun consumeUShortVararg(vararg shorts: UShort): String
|
||||
|
||||
external fun consumeNullableUShortVararg(vararg shorts: UShort?): String?
|
||||
|
||||
external fun consumeUIntVararg(vararg ints: UInt): String
|
||||
|
||||
external fun consumeNullableUIntVararg(vararg ints: UInt?): String?
|
||||
|
||||
external fun consumeULongVararg(vararg ints: ULong): String
|
||||
|
||||
external fun consumeNullableULongVararg(vararg ints: ULong?): String?
|
||||
|
||||
fun box(): String {
|
||||
if (provideUByte() != UByte.MAX_VALUE) return "Fail 1"
|
||||
if (provideNullableUByte(false) != UByte.MAX_VALUE) return "Fail 2"
|
||||
if (provideNullableUByte(true) != null) return "Fail 3"
|
||||
|
||||
if (provideUShort() != UShort.MAX_VALUE) return "Fail 4"
|
||||
if (provideNullableUShort(false) != UShort.MAX_VALUE) return "Fail 5"
|
||||
if (provideNullableUShort(true) != null) return "Fail 6"
|
||||
|
||||
if (provideUInt() != UInt.MAX_VALUE) return "Fail 7"
|
||||
if (provideNullableUInt(false) != UInt.MAX_VALUE) return "Fail 8"
|
||||
if (provideNullableUInt(true) != null) return "Fail 9"
|
||||
|
||||
if (provideULong() != ULong.MAX_VALUE) return "Fail 10"
|
||||
if (provideNullableULong(false) != ULong.MAX_VALUE) return "Fail 11"
|
||||
if (provideNullableULong(true) != null) return "Fail 12"
|
||||
|
||||
if (consumeUByte(UByte.MAX_VALUE) != "255") return "Fail 13"
|
||||
if (consumeNullableUByte(UByte.MAX_VALUE) != "255") return "Fail 14"
|
||||
if (consumeNullableUByte(null) != null) return "Fail 15"
|
||||
|
||||
if (consumeUShort(UShort.MAX_VALUE) != "65535") return "Fail 16"
|
||||
if (consumeNullableUShort(UShort.MAX_VALUE) != "65535") return "Fail 17"
|
||||
if (consumeNullableUShort(null) != null) return "Fail 18"
|
||||
|
||||
if (consumeUInt(UInt.MAX_VALUE) != "4294967295") return "Fail 19"
|
||||
if (consumeNullableUInt(UInt.MAX_VALUE) != "4294967295") return "Fail 20"
|
||||
if (consumeNullableUInt(null) != null) return "Fail 21"
|
||||
|
||||
if (consumeULong(ULong.MAX_VALUE) != "18446744073709551615") return "Fail 22"
|
||||
if (consumeNullableULong(ULong.MAX_VALUE) != "18446744073709551615") return "Fail 23"
|
||||
if (consumeNullableULong(null) != null) return "Fail 24"
|
||||
|
||||
if (provideUShort() != UShort.MAX_VALUE) return "Fail 25"
|
||||
if (provideNullableUShort(false) != UShort.MAX_VALUE) return "Fail 26"
|
||||
if (provideNullableUShort(true) != null) return "Fail 27"
|
||||
|
||||
if (provideUInt() != UInt.MAX_VALUE) return "Fail 28"
|
||||
if (provideNullableUInt(false) != UInt.MAX_VALUE) return "Fail 29"
|
||||
if (provideNullableUInt(true) != null) return "Fail 30"
|
||||
|
||||
if (provideULong() != ULong.MAX_VALUE) return "Fail 31"
|
||||
if (provideNullableULong(false) != ULong.MAX_VALUE) return "Fail 32"
|
||||
if (provideNullableULong(true) != null) return "Fail 33"
|
||||
|
||||
if (consumeUByteVararg(UByte.MAX_VALUE) != "255") return "Fail 34"
|
||||
if (consumeNullableUByteVararg(UByte.MAX_VALUE) != "255") return "Fail 35"
|
||||
if (consumeNullableUByteVararg(null) != null) return "Fail 36"
|
||||
|
||||
if (consumeUShortVararg(UShort.MAX_VALUE) != "65535") return "Fail 37"
|
||||
if (consumeNullableUShortVararg(UShort.MAX_VALUE) != "65535") return "Fail 38"
|
||||
if (consumeNullableUShortVararg(null) != null) return "Fail 39"
|
||||
|
||||
if (consumeUIntVararg(UInt.MAX_VALUE) != "4294967295") return "Fail 40"
|
||||
if (consumeNullableUIntVararg(UInt.MAX_VALUE) != "4294967295") return "Fail 41"
|
||||
if (consumeNullableUIntVararg(null) != null) return "Fail 42"
|
||||
|
||||
if (consumeULongVararg(ULong.MAX_VALUE) != "18446744073709551615") return "Fail 43"
|
||||
if (consumeNullableULongVararg(ULong.MAX_VALUE) != "18446744073709551615") return "Fail 44"
|
||||
if (consumeNullableULongVararg(null) != null) return "Fail 45"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+183
-1
@@ -24,6 +24,54 @@ fun eiAsAny(ei: EI): JsReference<Any> = ei.toJsReference()
|
||||
@JsExport
|
||||
fun anyAsEI(any: JsReference<Any>): EI = any.get() as EI
|
||||
|
||||
@JsExport
|
||||
fun provideUByte(): UByte = UByte.MAX_VALUE
|
||||
|
||||
@JsExport
|
||||
fun provideNullableUByte(nullable: Boolean): UByte? = if (nullable) null else UByte.MAX_VALUE
|
||||
|
||||
@JsExport
|
||||
fun consumeUByte(x: UByte) = x.toString()
|
||||
|
||||
@JsExport
|
||||
fun consumeNullableUByte(x: UByte?) = x?.toString()
|
||||
|
||||
@JsExport
|
||||
fun provideUShort(): UShort = UShort.MAX_VALUE
|
||||
|
||||
@JsExport
|
||||
fun provideNullableUShort(nullable: Boolean): UShort? = if (nullable) null else UShort.MAX_VALUE
|
||||
|
||||
@JsExport
|
||||
fun consumeUShort(x: UShort) = x.toString()
|
||||
|
||||
@JsExport
|
||||
fun consumeNullableUShort(x: UShort?) = x?.toString()
|
||||
|
||||
@JsExport
|
||||
fun provideUInt(): UInt = UInt.MAX_VALUE
|
||||
|
||||
@JsExport
|
||||
fun provideNullableUInt(nullable: Boolean): UInt? = if (nullable) null else UInt.MAX_VALUE
|
||||
|
||||
@JsExport
|
||||
fun consumeUInt(x: UInt) = x.toString()
|
||||
|
||||
@JsExport
|
||||
fun consumeNullableUInt(x: UInt?) = x?.toString()
|
||||
|
||||
@JsExport
|
||||
fun provideULong(): ULong = ULong.MAX_VALUE
|
||||
|
||||
@JsExport
|
||||
fun provideNullableULong(nullable: Boolean): ULong? = if (nullable) null else ULong.MAX_VALUE
|
||||
|
||||
@JsExport
|
||||
fun consumeULong(x: ULong) = x.toString()
|
||||
|
||||
@JsExport
|
||||
fun consumeNullableULong(x: ULong?) = x?.toString()
|
||||
|
||||
fun box(): String = "OK"
|
||||
|
||||
// FILE: entry.mjs
|
||||
@@ -45,4 +93,138 @@ if (main.isEven(31) !== false || main.isEven(10) !== true) {
|
||||
|
||||
if (main.anyAsEI(main.eiAsAny({x:10})).x !== 10) {
|
||||
throw "Fail 4";
|
||||
}
|
||||
}
|
||||
|
||||
if (main.provideUByte() != 255) {
|
||||
throw "Fail 5";
|
||||
}
|
||||
if (main.provideUShort() != 65535) {
|
||||
throw "Fail 6";
|
||||
}
|
||||
if (main.provideUInt() != 4294967295) {
|
||||
throw "Fail 7";
|
||||
}
|
||||
if (main.provideULong() != 18446744073709551615n) {
|
||||
throw "Fail 8";
|
||||
}
|
||||
|
||||
if (main.provideNullableUByte(false) != 255) {
|
||||
throw "Fail 9";
|
||||
}
|
||||
if (main.provideNullableUByte(true) != null) {
|
||||
throw "Fail 10";
|
||||
}
|
||||
if (main.provideNullableUShort(false) != 65535) {
|
||||
throw "Fail 11";
|
||||
}
|
||||
if (main.provideNullableUShort(true) != null) {
|
||||
throw "Fail 12";
|
||||
}
|
||||
if (main.provideNullableUInt(false) != 4294967295) {
|
||||
throw "Fail 13";
|
||||
}
|
||||
if (main.provideNullableUInt(true) != null) {
|
||||
throw "Fail 14";
|
||||
}
|
||||
if (main.provideNullableULong(false) != 18446744073709551615n) {
|
||||
throw "Fail 15";
|
||||
}
|
||||
if (main.provideNullableULong(true) != null) {
|
||||
throw "Fail 16";
|
||||
}
|
||||
|
||||
if (main.consumeUByte(-1) != "255") {
|
||||
throw "Fail 17";
|
||||
}
|
||||
if (main.consumeNullableUByte(-1) != "255") {
|
||||
throw "Fail 18";
|
||||
}
|
||||
if (main.consumeNullableUByte(null) != null) {
|
||||
throw "Fail 19";
|
||||
}
|
||||
|
||||
if (main.consumeUShort(-1) != "65535") {
|
||||
throw "Fail 20";
|
||||
}
|
||||
if (main.consumeNullableUShort(-1) != "65535") {
|
||||
throw "Fail 21";
|
||||
}
|
||||
if (main.consumeNullableUShort(null) != null) {
|
||||
throw "Fail 22";
|
||||
}
|
||||
|
||||
if (main.consumeUInt(-1) != "4294967295") {
|
||||
throw "Fail 23";
|
||||
}
|
||||
if (main.consumeNullableUInt(-1) != "4294967295") {
|
||||
throw "Fail 24";
|
||||
}
|
||||
if (main.consumeNullableUInt(null) != null) {
|
||||
throw "Fail 25";
|
||||
}
|
||||
|
||||
if (main.consumeULong(-1n) != "18446744073709551615") {
|
||||
throw "Fail 26";
|
||||
}
|
||||
if (main.consumeNullableULong(-1n) != "18446744073709551615") {
|
||||
throw "Fail 27";
|
||||
}
|
||||
if (main.consumeNullableULong(null) != null) {
|
||||
throw "Fail 28";
|
||||
}
|
||||
|
||||
if (main.consumeUByte(255) != "255") {
|
||||
throw "Fail 29";
|
||||
}
|
||||
if (main.consumeNullableUByte(255) != "255") {
|
||||
throw "Fail 30";
|
||||
}
|
||||
|
||||
if (main.consumeUShort(65535) != "65535") {
|
||||
throw "Fail 31";
|
||||
}
|
||||
if (main.consumeNullableUShort(65535) != "65535") {
|
||||
throw "Fail 32";
|
||||
}
|
||||
|
||||
if (main.consumeUInt(4294967295) != "4294967295") {
|
||||
throw "Fail 33";
|
||||
}
|
||||
if (main.consumeNullableUInt(4294967295) != "4294967295") {
|
||||
throw "Fail 34";
|
||||
}
|
||||
|
||||
if (main.consumeULong(18446744073709551615n) != "18446744073709551615") {
|
||||
throw "Fail 35";
|
||||
}
|
||||
if (main.consumeNullableULong(18446744073709551615n) != "18446744073709551615") {
|
||||
throw "Fail 36";
|
||||
}
|
||||
|
||||
if (main.consumeUByte(256) != "0") {
|
||||
throw "Fail 37";
|
||||
}
|
||||
if (main.consumeNullableUByte(256) != "0") {
|
||||
throw "Fail 38";
|
||||
}
|
||||
|
||||
if (main.consumeUShort(65536) != "0") {
|
||||
throw "Fail 39";
|
||||
}
|
||||
if (main.consumeNullableUShort(65536) != "0") {
|
||||
throw "Fail 40";
|
||||
}
|
||||
|
||||
if (main.consumeUInt(4294967296) != "0") {
|
||||
throw "Fail 41";
|
||||
}
|
||||
if (main.consumeNullableUInt(4294967296) != "0") {
|
||||
throw "Fail 42";
|
||||
}
|
||||
|
||||
if (main.consumeULong(18446744073709551616n) != "0") {
|
||||
throw "Fail 43";
|
||||
}
|
||||
if (main.consumeNullableULong(18446744073709551616n) != "0") {
|
||||
throw "Fail 44";
|
||||
}
|
||||
|
||||
+24
-5
@@ -2,18 +2,37 @@
|
||||
|
||||
import kotlin.wasm.WasmExport
|
||||
|
||||
@WasmExport
|
||||
fun exportDefaultName(): Boolean = true
|
||||
|
||||
fun checkDefaultName(): Boolean = js("typeof wasmExports.exportDefaultName() !== 'object'")
|
||||
|
||||
@WasmExport("exportOverriddenName")
|
||||
fun exportWithName(): Boolean = true
|
||||
|
||||
@WasmExport
|
||||
fun exportDefaultName(): Boolean = true
|
||||
|
||||
@WasmExport
|
||||
fun provideUByte(): UByte = UByte.MAX_VALUE
|
||||
|
||||
@WasmExport
|
||||
fun provideUShort(): UShort = UShort.MAX_VALUE
|
||||
|
||||
@WasmExport
|
||||
fun provideUInt(): UInt = UInt.MAX_VALUE
|
||||
|
||||
@WasmExport
|
||||
fun provideULong(): ULong = ULong.MAX_VALUE
|
||||
|
||||
fun checkDefaultName(): Boolean = js("typeof wasmExports.exportDefaultName() !== 'object'")
|
||||
fun checkOverriddenName(): Boolean = js("typeof wasmExports.exportOverriddenName() !== 'object'")
|
||||
fun checkProvideUByte(): Boolean = js("wasmExports.provideUByte() === -1")
|
||||
fun checkProvideUShort(): Boolean = js("wasmExports.provideUShort() === -1")
|
||||
fun checkProvideUInt(): Boolean = js("wasmExports.provideUInt() === -1")
|
||||
fun checkProvideULong(): Boolean = js("wasmExports.provideULong() === -1n")
|
||||
|
||||
fun box(): String {
|
||||
if (!checkDefaultName()) return "checkDefaultName fail"
|
||||
if (!checkOverriddenName()) return "checkOverriddenName fail"
|
||||
if (!checkProvideUByte()) return "checkProvideUByte fail"
|
||||
if (!checkProvideUShort()) return "checkProvideUShort fail"
|
||||
if (!checkProvideUInt()) return "checkProvideUInt fail"
|
||||
if (!checkProvideULong()) return "checkProvideULong fail"
|
||||
return "OK"
|
||||
}
|
||||
@@ -20,6 +20,16 @@ export { sub as "" }
|
||||
export { sub as "\n \r \t" }
|
||||
export default sub;
|
||||
|
||||
// FILE: 3.mjs
|
||||
|
||||
export function provideUByte() { return -1 }
|
||||
|
||||
export function provideUShort() { return -1 }
|
||||
|
||||
export function provideUInt() { return -1 }
|
||||
|
||||
export function provideULong() { return -1n }
|
||||
|
||||
// FILE: wasmImport.kt
|
||||
import kotlin.wasm.WasmImport
|
||||
|
||||
@@ -50,6 +60,18 @@ external fun sub5(x: Float, y: Float): Float
|
||||
@WasmImport("./2.mjs", "default")
|
||||
external fun sub6(x: Float, y: Float): Float
|
||||
|
||||
@WasmImport("./3.mjs", "provideUByte")
|
||||
external fun provideUByte(): UByte
|
||||
|
||||
@WasmImport("./3.mjs", "provideUShort")
|
||||
external fun provideUShort(): UShort
|
||||
|
||||
@WasmImport("./3.mjs", "provideUInt")
|
||||
external fun provideUInt(): UInt
|
||||
|
||||
@WasmImport("./3.mjs", "provideULong")
|
||||
external fun provideULong(): ULong
|
||||
|
||||
fun box(): String {
|
||||
if (addImportRenamed(5, 6) != 11) return "Fail1"
|
||||
if (add(5, 6) != 11) return "Fail1"
|
||||
@@ -62,5 +84,10 @@ fun box(): String {
|
||||
if (sub5(5f, 6f) != -1f) return "Fail6"
|
||||
if (sub6(5f, 6f) != -1f) return "Fail7"
|
||||
|
||||
if (provideUByte() != UByte.MAX_VALUE) return "Fail9"
|
||||
if (provideUShort() != UShort.MAX_VALUE) return "Fail10"
|
||||
if (provideUInt() != UInt.MAX_VALUE) return "Fail11"
|
||||
if (provideULong() != ULong.MAX_VALUE) return "Fail12"
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -24,3 +24,9 @@ class C2
|
||||
|
||||
<!WRONG_ANNOTATION_TARGET!>@JsExport<!>
|
||||
var p2: Int = 1
|
||||
|
||||
@JsExport
|
||||
fun fooUnsigned1(): UInt = 42u
|
||||
|
||||
@JsExport
|
||||
fun fooUnsigned2(): UByte = 42u
|
||||
|
||||
@@ -58,3 +58,9 @@ fun fooDeafultAndVararg(
|
||||
<!WASM_IMPORT_EXPORT_PARAMETER_DEFAULT_VALUE!>a: Int = <!CALL_TO_DEFINED_EXTERNALLY_FROM_NON_EXTERNAL_DECLARATION!>definedExternally<!><!>,
|
||||
<!WASM_IMPORT_EXPORT_UNSUPPORTED_PARAMETER_TYPE, WASM_IMPORT_EXPORT_VARARG_PARAMETER!>vararg b: Int<!>
|
||||
): Unit { b.toString() }
|
||||
|
||||
@WasmExport("a")
|
||||
fun fooUnsigned1(): UInt = 42u
|
||||
|
||||
@WasmExport()
|
||||
fun fooUnsigned2(): UByte = 42u
|
||||
|
||||
@@ -956,6 +956,10 @@ public abstract class KotlinBuiltIns {
|
||||
return type != null && isNotNullConstructedFromGivenClass(type, FqNames.string);
|
||||
}
|
||||
|
||||
public static boolean isUnsignedNumber(@Nullable KotlinType type) {
|
||||
return type != null && (isUByte(type) || isUShort(type) || isUInt(type) || isULong(type));
|
||||
}
|
||||
|
||||
public static boolean isCharSequenceOrNullableCharSequence(@Nullable KotlinType type) {
|
||||
return type != null && isConstructedFromGivenClass(type, FqNames.charSequence);
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@ object JsPlatformConfigurator : PlatformConfiguratorBase(
|
||||
JsRuntimeAnnotationChecker,
|
||||
JsDynamicDeclarationChecker,
|
||||
JsExportAnnotationChecker,
|
||||
JsExportDeclarationChecker
|
||||
),
|
||||
additionalCallCheckers = listOf(
|
||||
JsModuleCallChecker,
|
||||
@@ -52,6 +51,7 @@ object JsPlatformConfigurator : PlatformConfiguratorBase(
|
||||
container.useInstance(ExtensionFunctionToExternalIsInlinable)
|
||||
container.useInstance(JsQualifierChecker)
|
||||
container.useInstance(JsNativeDiagnosticSuppressor)
|
||||
container.useInstance(JsExportDeclarationChecker(includeUnsignedNumbers = false))
|
||||
}
|
||||
|
||||
override fun configureModuleDependentCheckers(container: StorageComponentContainer) {
|
||||
|
||||
+4
-3
@@ -33,7 +33,7 @@ import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.isDynamic
|
||||
import org.jetbrains.kotlin.types.typeUtil.*
|
||||
|
||||
object JsExportDeclarationChecker : DeclarationChecker {
|
||||
class JsExportDeclarationChecker(private val includeUnsignedNumbers: Boolean) : DeclarationChecker {
|
||||
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
|
||||
val trace = context.trace
|
||||
val bindingContext = trace.bindingContext
|
||||
@@ -190,8 +190,9 @@ object JsExportDeclarationChecker : DeclarationChecker {
|
||||
KotlinBuiltIns.isString(nonNullable) ||
|
||||
(nonNullable.isPrimitiveNumberOrNullableType() && !nonNullable.isLong()) ||
|
||||
nonNullable.isNothingOrNullableNothing() ||
|
||||
KotlinBuiltIns.isArray(this) ||
|
||||
KotlinBuiltIns.isPrimitiveArray(this)
|
||||
KotlinBuiltIns.isArray(nonNullable) ||
|
||||
KotlinBuiltIns.isPrimitiveArray(nonNullable) ||
|
||||
(includeUnsignedNumbers && KotlinBuiltIns.isUnsignedNumber(nonNullable))
|
||||
|
||||
if (isPrimitiveExportableType) return true
|
||||
|
||||
|
||||
@@ -91,11 +91,23 @@ private external fun externrefHashCode(ref: ExternalInterfaceType): Int
|
||||
private fun externrefToString(ref: ExternalInterfaceType): String =
|
||||
js("String(ref)")
|
||||
|
||||
private fun externrefToUByte(ref: ExternalInterfaceType): UByte =
|
||||
js("Number(ref)")
|
||||
|
||||
private fun externrefToUShort(ref: ExternalInterfaceType): UShort =
|
||||
js("Number(ref)")
|
||||
|
||||
private fun externrefToUInt(ref: ExternalInterfaceType): UInt =
|
||||
js("Number(ref)")
|
||||
|
||||
private fun externrefToULong(ref: ExternalInterfaceType): ULong =
|
||||
js("BigInt(ref)")
|
||||
|
||||
private fun externrefToInt(ref: ExternalInterfaceType): Int =
|
||||
js("Number(ref)")
|
||||
|
||||
private fun externrefToLong(ref: ExternalInterfaceType): Long =
|
||||
js("Number(ref)")
|
||||
js("BigInt(ref)")
|
||||
|
||||
private fun externrefToBoolean(ref: ExternalInterfaceType): Boolean =
|
||||
js("Boolean(ref)")
|
||||
@@ -314,6 +326,18 @@ internal fun jsToKotlinByteAdapter(x: Int): Byte = x.toByte()
|
||||
internal fun jsToKotlinShortAdapter(x: Int): Short = x.toShort()
|
||||
internal fun jsToKotlinCharAdapter(x: Int): Char = x.toChar()
|
||||
|
||||
internal fun externRefToKotlinUByteAdapter(x: ExternalInterfaceType): UByte =
|
||||
externrefToUByte(x)
|
||||
|
||||
internal fun externRefToKotlinUShortAdapter(x: ExternalInterfaceType): UShort =
|
||||
externrefToUShort(x)
|
||||
|
||||
internal fun externRefToKotlinUIntAdapter(x: ExternalInterfaceType): UInt =
|
||||
externrefToUInt(x)
|
||||
|
||||
internal fun externRefToKotlinULongAdapter(x: ExternalInterfaceType): ULong =
|
||||
externrefToULong(x)
|
||||
|
||||
internal fun externRefToKotlinIntAdapter(x: ExternalInterfaceType): Int =
|
||||
externrefToInt(x)
|
||||
|
||||
@@ -335,6 +359,30 @@ internal fun kotlinIntToExternRefAdapter(x: Int): JsNumber =
|
||||
internal fun kotlinBooleanToExternRefAdapter(x: Boolean): JsBoolean =
|
||||
if (x) jsTrue else jsFalse
|
||||
|
||||
private fun kotlinUByteToJsNumberUnsafe(x: Int): JsNumber =
|
||||
js("x & 0xFF")
|
||||
|
||||
private fun kotlinUShortToJsNumberUnsafe(x: Int): JsNumber =
|
||||
js("x & 0xFFFF")
|
||||
|
||||
private fun kotlinUIntToJsNumberUnsafe(x: Int): JsNumber =
|
||||
js("x >>> 0")
|
||||
|
||||
private fun kotlinULongToJsBigIntUnsafe(x: Long): ExternalInterfaceType =
|
||||
js("x & 0xFFFFFFFFFFFFFFFFn")
|
||||
|
||||
internal fun kotlinUByteToJsNumber(x: UByte): JsNumber =
|
||||
kotlinUByteToJsNumberUnsafe(x.toInt())
|
||||
|
||||
internal fun kotlinUShortToJsNumber(x: UShort): JsNumber =
|
||||
kotlinUShortToJsNumberUnsafe(x.toInt())
|
||||
|
||||
internal fun kotlinUIntToJsNumber(x: UInt): JsNumber =
|
||||
kotlinUIntToJsNumberUnsafe(x.toInt())
|
||||
|
||||
internal fun kotlinULongToJsBigInt(x: ULong): ExternalInterfaceType =
|
||||
kotlinULongToJsBigIntUnsafe(x.toLong())
|
||||
|
||||
internal fun kotlinLongToExternRefAdapter(x: Long): ExternalInterfaceType =
|
||||
longToExternref(x)
|
||||
|
||||
|
||||
+1
-1
@@ -26,7 +26,6 @@ object WasmJsPlatformConfigurator : PlatformConfiguratorBase(
|
||||
JsExternalChecker, WasmExternalInheritanceChecker,
|
||||
JsRuntimeAnnotationChecker,
|
||||
JsExportAnnotationChecker,
|
||||
JsExportDeclarationChecker,
|
||||
WasmExternalDeclarationChecker,
|
||||
WasmImportAnnotationChecker,
|
||||
WasmJsFunAnnotationChecker,
|
||||
@@ -51,6 +50,7 @@ object WasmJsPlatformConfigurator : PlatformConfiguratorBase(
|
||||
container.useInstance(ExtensionFunctionToExternalIsInlinable)
|
||||
container.useInstance(JsQualifierChecker)
|
||||
container.useInstance(WasmDiagnosticSuppressor)
|
||||
container.useInstance(JsExportDeclarationChecker(includeUnsignedNumbers = true))
|
||||
}
|
||||
|
||||
override fun configureModuleDependentCheckers(container: StorageComponentContainer) {
|
||||
|
||||
+2
-1
@@ -31,6 +31,7 @@ import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.typeUtil.isBoolean
|
||||
import org.jetbrains.kotlin.types.typeUtil.isPrimitiveNumberType
|
||||
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
||||
import org.jetbrains.kotlin.types.typeUtil.isUnsignedNumberType
|
||||
|
||||
object WasmImportAnnotationChecker : DeclarationChecker {
|
||||
private val wasmImportFqName = FqName("kotlin.wasm.WasmImport")
|
||||
@@ -54,7 +55,7 @@ object WasmImportAnnotationChecker : DeclarationChecker {
|
||||
}
|
||||
|
||||
private fun isParameterTypeSupported(type: KotlinType): Boolean =
|
||||
type.isPrimitiveNumberType() || type.isBoolean()
|
||||
type.isPrimitiveNumberType() || type.isUnsignedNumberType() || type.isBoolean()
|
||||
|
||||
private fun isReturnTypeSupported(type: KotlinType): Boolean =
|
||||
isParameterTypeSupported(type) || type.isUnit()
|
||||
|
||||
+1
@@ -113,6 +113,7 @@ private fun isTypeSupportedInJsInterop(
|
||||
val nonNullable = type.makeNotNullable()
|
||||
if (
|
||||
KotlinBuiltIns.isPrimitiveType(nonNullable) ||
|
||||
KotlinBuiltIns.isUnsignedNumber(nonNullable) ||
|
||||
KotlinBuiltIns.isString(nonNullable)
|
||||
) {
|
||||
return true
|
||||
|
||||
+6
@@ -49,6 +49,12 @@ public class FirWasmCodegenWasmJsInteropTestGenerated extends AbstractFirWasmCod
|
||||
runTest("compiler/testData/codegen/boxWasmJsInterop/externals.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("externalsWithUnsigned.kt")
|
||||
public void testExternalsWithUnsigned() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxWasmJsInterop/externalsWithUnsigned.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("functionTypes.kt")
|
||||
public void testFunctionTypes() throws Exception {
|
||||
|
||||
+6
@@ -49,6 +49,12 @@ public class K1WasmCodegenWasmJsInteropTestGenerated extends AbstractK1WasmCodeg
|
||||
runTest("compiler/testData/codegen/boxWasmJsInterop/externals.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("externalsWithUnsigned.kt")
|
||||
public void testExternalsWithUnsigned() throws Exception {
|
||||
runTest("compiler/testData/codegen/boxWasmJsInterop/externalsWithUnsigned.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("functionTypes.kt")
|
||||
public void testFunctionTypes() throws Exception {
|
||||
|
||||
Reference in New Issue
Block a user