[Wasm] Support Number type for external functions
This commit is contained in:
@@ -287,6 +287,7 @@ class WasmSymbols(
|
||||
inner class JsInteropAdapters {
|
||||
val kotlinToJsStringAdapter = getInternalFunction("kotlinToJsStringAdapter")
|
||||
val kotlinToJsAnyAdapter = getInternalFunction("kotlinToJsAnyAdapter")
|
||||
val numberToDoubleAdapter = getInternalFunction("numberToDoubleAdapter")
|
||||
|
||||
val jsCheckIsNullOrUndefinedAdapter = getInternalFunction("jsCheckIsNullOrUndefinedAdapter")
|
||||
|
||||
|
||||
+21
@@ -65,6 +65,13 @@ class JsInteropFunctionsLowering(val context: WasmBackendContext) : DeclarationT
|
||||
return (newDeclarations ?: listOf(declaration)) + additionalDeclarations
|
||||
}
|
||||
|
||||
private fun doubleIfNumber(possiblyNumber: IrType): IrType {
|
||||
val isNullable = possiblyNumber.isNullable()
|
||||
val notNullType = possiblyNumber.makeNotNull()
|
||||
if (notNullType != builtIns.numberType) return possiblyNumber
|
||||
return if (isNullable) builtIns.doubleType.makeNullable() else builtIns.doubleType
|
||||
}
|
||||
|
||||
/**
|
||||
* external fun foo(x: KotlinType): KotlinType
|
||||
*
|
||||
@@ -79,6 +86,9 @@ class JsInteropFunctionsLowering(val context: WasmBackendContext) : DeclarationT
|
||||
if (function.valueParameters.any { it.defaultValue != null })
|
||||
return null
|
||||
|
||||
// Patch function types for Number parameters as double
|
||||
function.returnType = doubleIfNumber(function.returnType)
|
||||
|
||||
val valueParametersAdapters = function.valueParameters.map {
|
||||
it.type.kotlinToJsAdapterIfNeeded(isReturn = false)
|
||||
}
|
||||
@@ -193,6 +203,16 @@ class JsInteropFunctionsLowering(val context: WasmBackendContext) : DeclarationT
|
||||
}
|
||||
|
||||
val notNullType = makeNotNull()
|
||||
|
||||
if (notNullType == builtIns.numberType) {
|
||||
return NullOrAdapter(
|
||||
CombineAdapter(
|
||||
FunctionBasedAdapter(adapters.kotlinDoubleToExternRefAdapter.owner),
|
||||
FunctionBasedAdapter(adapters.numberToDoubleAdapter.owner)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
val primitiveToExternRefAdapter = when (notNullType) {
|
||||
builtIns.byteType -> adapters.kotlinByteToExternRefAdapter.owner
|
||||
builtIns.shortType -> adapters.kotlinShortToExternRefAdapter.owner
|
||||
@@ -222,6 +242,7 @@ class JsInteropFunctionsLowering(val context: WasmBackendContext) : DeclarationT
|
||||
builtIns.stringType -> return FunctionBasedAdapter(adapters.kotlinToJsStringAdapter.owner)
|
||||
builtIns.booleanType -> return FunctionBasedAdapter(adapters.kotlinBooleanToExternRefAdapter.owner)
|
||||
builtIns.anyType -> return FunctionBasedAdapter(adapters.kotlinToJsAnyAdapter.owner)
|
||||
builtIns.numberType -> return FunctionBasedAdapter(adapters.numberToDoubleAdapter.owner)
|
||||
|
||||
builtIns.byteType,
|
||||
builtIns.shortType,
|
||||
|
||||
@@ -149,6 +149,26 @@ fun testFloat() {
|
||||
check(null2Float() == null)
|
||||
}
|
||||
|
||||
|
||||
@JsFun("() => 123.5")
|
||||
external fun notNullNumber(): Number
|
||||
|
||||
@JsFun("() => null")
|
||||
external fun notNull2Number(): Number
|
||||
|
||||
@JsFun("() => 123.5")
|
||||
external fun nullNumber(): Number?
|
||||
|
||||
@JsFun("() => null")
|
||||
external fun null2Number(): Number?
|
||||
|
||||
fun testNumber() {
|
||||
check(notNullNumber() == 123.5)
|
||||
check(notNull2Number() == 0.0)
|
||||
check(nullNumber() == 123.5)
|
||||
check(null2Number() == null)
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
testString()
|
||||
testExterRef()
|
||||
@@ -157,5 +177,6 @@ fun box(): String {
|
||||
testBoolean()
|
||||
testShort()
|
||||
testFloat()
|
||||
testNumber()
|
||||
return "OK"
|
||||
}
|
||||
|
||||
@@ -114,6 +114,33 @@ fun testFloat() {
|
||||
null2Float(null)
|
||||
}
|
||||
|
||||
@JsFun("(x) => { if (x !== 123.5) throw 'error' }")
|
||||
external fun notNullNumber(x: Number)
|
||||
|
||||
@JsFun("(x) => { if (x !== 123.5) throw 'error' }")
|
||||
external fun nullNumber(x: Number?)
|
||||
|
||||
@JsFun("(x) => { if (x !== null) throw 'error' }")
|
||||
external fun null2Number(x: Number?)
|
||||
|
||||
@JsFun("(x) => { if (x !== 123) throw 'error' }")
|
||||
external fun byte2Number(x: Number)
|
||||
|
||||
@JsFun("(x) => { if (x !== 123) throw 'error' }")
|
||||
external fun notNullByte2Number(x: Number?)
|
||||
|
||||
@JsFun("(x) => { if (x !== null) throw 'error' }")
|
||||
external fun nullByte2Number(x: Number?)
|
||||
|
||||
fun testNumber() {
|
||||
notNullNumber(123.5)
|
||||
nullNumber(123.5)
|
||||
null2Number(null)
|
||||
byte2Number(123)
|
||||
notNullByte2Number(123)
|
||||
nullByte2Number(null)
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
testString()
|
||||
testExterRef()
|
||||
@@ -122,5 +149,6 @@ fun box(): String {
|
||||
testBoolean()
|
||||
testShort()
|
||||
testFloat()
|
||||
testNumber()
|
||||
return "OK"
|
||||
}
|
||||
@@ -261,6 +261,9 @@ private val jsEmptyString by lazy(::getJsEmptyString)
|
||||
private val jsTrue by lazy(::getJsTrue)
|
||||
private val jsFalse by lazy(::getJsFalse)
|
||||
|
||||
internal fun numberToDoubleAdapter(x: Number): Double =
|
||||
x.toDouble()
|
||||
|
||||
internal fun kotlinToJsAnyAdapter(x: Any?): ExternalInterfaceType? =
|
||||
if (x == null) null else anyToExternRef(x)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user