diff --git a/compiler/testData/codegen/boxWasmJsInterop/functionTypes.kt b/compiler/testData/codegen/boxWasmJsInterop/functionTypes.kt index d531ac7812b..8162aa33f77 100644 --- a/compiler/testData/codegen/boxWasmJsInterop/functionTypes.kt +++ b/compiler/testData/codegen/boxWasmJsInterop/functionTypes.kt @@ -242,8 +242,9 @@ fun box(): String { } // TODO: Rewrite test to use module system -@JsFun("() => { globalThis.main = wasmExports; }") -external fun hackNonModuleExport() +fun hackNonModuleExport() { + js("globalThis.main = wasmExports;") +} fun main() { hackNonModuleExport() diff --git a/compiler/testData/codegen/boxWasmJsInterop/jsExport.kt b/compiler/testData/codegen/boxWasmJsInterop/jsExport.kt index 8bfd33cfd82..e9c0255ab9d 100644 --- a/compiler/testData/codegen/boxWasmJsInterop/jsExport.kt +++ b/compiler/testData/codegen/boxWasmJsInterop/jsExport.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JS_IR, JS // WASM_FAILS_IN: SM // MODULE: main // FILE: externals.kt @@ -29,8 +28,9 @@ fun box(): String = "OK" // TODO: Rewrite test to use module system -@JsFun("() => { globalThis.main = wasmExports; }") -external fun hackNonModuleExport() +fun hackNonModuleExport() { + js("globalThis.main = wasmExports;") +} fun main() { hackNonModuleExport() diff --git a/compiler/testData/codegen/boxWasmJsInterop/jsToKotlinAdapters.kt b/compiler/testData/codegen/boxWasmJsInterop/jsToKotlinAdapters.kt index e3d22b11d9e..b95eea9fcd6 100644 --- a/compiler/testData/codegen/boxWasmJsInterop/jsToKotlinAdapters.kt +++ b/compiler/testData/codegen/boxWasmJsInterop/jsToKotlinAdapters.kt @@ -11,17 +11,13 @@ inline fun checkNPE(body: () -> Unit) { check(throwed) } -@JsFun("() => 'abc'") -external fun notNullString(): String +fun notNullString(): String = js("'abc'") -@JsFun("() => null") -external fun notNull2String(): String +fun notNull2String(): String = js("null") -@JsFun("() => 'abc'") -external fun nullString(): String? +fun nullString(): String? = js("'abc'") -@JsFun("() => null") -external fun null2String(): String? +fun null2String(): String? = js("null") fun testString() { check(notNullString() == "abc") @@ -32,17 +28,13 @@ fun testString() { external interface ExternRef -@JsFun("() => 'abc'") -external fun notNullExternRef(): ExternRef +fun notNullExternRef(): ExternRef = js("'abc'") -@JsFun("() => null") -external fun notNull2ExternRef(): ExternRef +fun notNull2ExternRef(): ExternRef = js("null") -@JsFun("() => 'abc'") -external fun nullExternRef(): ExternRef? +fun nullExternRef(): ExternRef? = js("'abc'") -@JsFun("() => null") -external fun null2ExternRef(): ExternRef? +fun null2ExternRef(): ExternRef? = js("null") fun testExterRef() { @@ -54,17 +46,13 @@ fun testExterRef() { class DataRef -@JsFun("(x) => x") -external fun notNullDataRef(x: DataRef): DataRef +fun notNullDataRef(x: DataRef): DataRef = js("x") -@JsFun("(x) => null") -external fun notNull2DataRef(x: DataRef): DataRef +fun notNull2DataRef(x: DataRef): DataRef = js("null") -@JsFun("(x) => x") -external fun nullDataRef(x: DataRef): DataRef? +fun nullDataRef(x: DataRef): DataRef? = js("x") -@JsFun("(x) => null") -external fun null2DataRef(x: DataRef): DataRef? +fun null2DataRef(x: DataRef): DataRef? = js("null") fun testDataRef() { val dataRef = DataRef() @@ -74,17 +62,13 @@ fun testDataRef() { check (null2DataRef(dataRef) == null) } -@JsFun("() => 123") -external fun notNullInt(): Int +fun notNullInt(): Int = js("123") -@JsFun("() => null") -external fun notNull2Int(): Int +fun notNull2Int(): Int = js("null") -@JsFun("() => 123") -external fun nullInt(): Int? +fun nullInt(): Int? = js("123") -@JsFun("() => null") -external fun null2Int(): Int? +fun null2Int(): Int? = js("null") fun testInt() { check(notNullInt() == 123) @@ -93,17 +77,13 @@ fun testInt() { check(null2Int() == null) } -@JsFun("() => true") -external fun notNullBoolean(): Boolean +fun notNullBoolean(): Boolean = js("true") -@JsFun("() => null") -external fun notNull2Boolean(): Boolean +fun notNull2Boolean(): Boolean = js("null") -@JsFun("() => true") -external fun nullBoolean(): Boolean? +fun nullBoolean(): Boolean? = js("true") -@JsFun("() => null") -external fun null2Boolean(): Boolean? +fun null2Boolean(): Boolean? = js("null") fun testBoolean() { check(notNullBoolean() == true) @@ -112,17 +92,13 @@ fun testBoolean() { check(null2Boolean() == null) } -@JsFun("() => 123") -external fun notNullShort(): Short +fun notNullShort(): Short = js("123") -@JsFun("() => null") -external fun notNull2Short(): Short +fun notNull2Short(): Short = js("null") -@JsFun("() => 123") -external fun nullShort(): Short? +fun nullShort(): Short? = js("123") -@JsFun("() => null") -external fun null2Short(): Short? +fun null2Short(): Short? = js("null") fun testShort() { check(notNullShort() == 123.toShort()) @@ -131,17 +107,13 @@ fun testShort() { check(null2Short() == null) } -@JsFun("() => 123.5") -external fun notNullFloat(): Float +fun notNullFloat(): Float = js("123.5") -@JsFun("() => null") -external fun notNull2Float(): Float +fun notNull2Float(): Float = js("null") -@JsFun("() => 123.5") -external fun nullFloat(): Float? +fun nullFloat(): Float? = js("123.5") -@JsFun("() => null") -external fun null2Float(): Float? +fun null2Float(): Float? = js("null") fun testFloat() { check(notNullFloat() == 123.5f) @@ -151,17 +123,13 @@ fun testFloat() { } -@JsFun("() => 123.5") -external fun notNullNumber(): Number +fun notNullNumber(): Number = js("123.5") -@JsFun("() => null") -external fun notNull2Number(): Number +fun notNull2Number(): Number = js("null") -@JsFun("() => 123.5") -external fun nullNumber(): Number? +fun nullNumber(): Number? = js("123.5") -@JsFun("() => null") -external fun null2Number(): Number? +fun null2Number(): Number? = js("null") fun testNumber() { check(notNullNumber() == 123.5) diff --git a/compiler/testData/codegen/boxWasmJsInterop/kotlinToJsAdapters.kt b/compiler/testData/codegen/boxWasmJsInterop/kotlinToJsAdapters.kt index aa174ed9571..84eeb1cab1b 100644 --- a/compiler/testData/codegen/boxWasmJsInterop/kotlinToJsAdapters.kt +++ b/compiler/testData/codegen/boxWasmJsInterop/kotlinToJsAdapters.kt @@ -1,14 +1,16 @@ -// IGNORE_BACKEND: JS_IR, JS // WASM_FAILS_IN: SM -@JsFun("(x) => { if (x !== 'abc') throw 'error' }") -external fun notNullString(x: String) +fun notNullString(x: String) { + js("if (x !== 'abc') throw 'error'") +} -@JsFun("(x) => { if (x !== 'abc') throw 'error' }") -external fun nullString(x: String?) +fun nullString(x: String?) { + js("if (x !== 'abc') throw 'error'") +} -@JsFun("(x) => { if (x !== null) throw 'error' }") -external fun null2String(x: String?) +fun null2String(x: String?) { + js("if (x !== null) throw 'error'") +} fun testString() { notNullString("abc") @@ -18,17 +20,20 @@ fun testString() { external interface ExternRef -@JsFun("(x) => { if (x !== 'abc') throw 'error' }") -external fun notNullExternRef(x: ExternRef) +fun notNullExternRef(x: ExternRef) { + js("if (x !== 'abc') throw 'error'") +} -@JsFun("(x) => { if (x !== 'abc') throw 'error' }") -external fun nullExternRef(x: ExternRef?) +fun nullExternRef(x: ExternRef?) { + js("if (x !== 'abc') throw 'error'") +} -@JsFun("(x) => { if (x !== null) throw 'error' }") -external fun null2ExternRef(x: ExternRef?) +fun null2ExternRef(x: ExternRef?) { + js("if (x !== null) throw 'error'") +} -@JsFun("() => 'abc'") -external fun getExternRef(): ExternRef +fun getExternRef(): ExternRef = + js("'abc'") fun testExterRef() { val externRef = getExternRef() @@ -39,14 +44,17 @@ fun testExterRef() { class DataRef -@JsFun("(x, y) => { if (x === null) throw 'error' }") -external fun notNullDataRef(x: DataRef) +fun notNullDataRef(x: DataRef) { + js("if (x === null) throw 'error'") +} -@JsFun("(x, y) => { if (x === null) throw 'error' }") -external fun nullDataRef(x: DataRef?) +fun nullDataRef(x: DataRef?) { + js("if (x === null) throw 'error'") +} -@JsFun("(x, y) => { if (x !== null) throw 'error' }") -external fun null2DataRef(x: DataRef?) +fun null2DataRef(x: DataRef?) { + js("if (x !== null) throw 'error'") +} fun testDataRef() { val dataRef = DataRef() @@ -55,14 +63,17 @@ fun testDataRef() { null2DataRef(null) } -@JsFun("(x) => { if (x !== 123) throw 'error' }") -external fun notNullInt(x: Int) +fun notNullInt(x: Int) { + js("if (x !== 123) throw 'error'") +} -@JsFun("(x) => { if (x !== 123) throw 'error' }") -external fun nullInt(x: Int?) +fun nullInt(x: Int?) { + js("if (x !== 123) throw 'error'") +} -@JsFun("(x) => { if (x !== null) throw 'error' }") -external fun null2Int(x: Int?) +fun null2Int(x: Int?) { + js("if (x !== null) throw 'error'") +} fun testInt() { notNullInt(123) @@ -70,14 +81,17 @@ fun testInt() { null2Int(null) } -@JsFun("(x) => { if (x !== true) throw 'error' }") -external fun notNullBoolean(x: Boolean) +fun notNullBoolean(x: Boolean) { + js("if (x !== true) throw 'error'") +} -@JsFun("(x) => { if (x !== true) throw 'error' }") -external fun nullBoolean(x: Boolean?) +fun nullBoolean(x: Boolean?) { + js("if (x !== true) throw 'error'") +} -@JsFun("(x) => { if (x !== null) throw 'error' }") -external fun null2Boolean(x: Boolean?) +fun null2Boolean(x: Boolean?) { + js("if (x !== null) throw 'error'") +} fun testBoolean() { notNullBoolean(true) @@ -85,14 +99,17 @@ fun testBoolean() { null2Boolean(null) } -@JsFun("(x) => { x == 123 }") -external fun notNullShort(x: Short) +fun notNullShort(x: Short) { + js("x == 123") +} -@JsFun("(x) => { if (x !== 123) throw 'error' }") -external fun nullShort(x: Short?) +fun nullShort(x: Short?) { + js("if (x !== 123) throw 'error'") +} -@JsFun("(x) => { if (x !== null) throw 'error' }") -external fun null2Short(x: Short?) +fun null2Short(x: Short?) { + js("if (x !== null) throw 'error'") +} fun testShort() { notNullShort(123.toShort()) @@ -100,14 +117,17 @@ fun testShort() { null2Short(null) } -@JsFun("(x) => { if (x !== 123.5) throw 'error' }") -external fun notNullFloat(x: Float) +fun notNullFloat(x: Float) { + js("if (x !== 123.5) throw 'error'") +} -@JsFun("(x) => { if (x !== 123.5) throw 'error' }") -external fun nullFloat(x: Float?) +fun nullFloat(x: Float?) { + js("if (x !== 123.5) throw 'error'") +} -@JsFun("(x) => { if (x !== null) throw 'error' }") -external fun null2Float(x: Float?) +fun null2Float(x: Float?) { + js("if (x !== null) throw 'error'") +} fun testFloat() { notNullFloat(123.5f) @@ -115,23 +135,29 @@ fun testFloat() { null2Float(null) } -@JsFun("(x) => { if (x !== 123.5) throw 'error' }") -external fun notNullNumber(x: Number) +fun notNullNumber(x: Number) { + js("if (x !== 123.5) throw 'error'") +} -@JsFun("(x) => { if (x !== 123.5) throw 'error' }") -external fun nullNumber(x: Number?) +fun nullNumber(x: Number?) { + js("if (x !== 123.5) throw 'error'") +} -@JsFun("(x) => { if (x !== null) throw 'error' }") -external fun null2Number(x: Number?) +fun null2Number(x: Number?) { + js("if (x !== null) throw 'error'") +} -@JsFun("(x) => { if (x !== 123) throw 'error' }") -external fun byte2Number(x: Number) +fun byte2Number(x: Number) { + js("if (x !== 123) throw 'error'") +} -@JsFun("(x) => { if (x !== 123) throw 'error' }") -external fun notNullByte2Number(x: Number?) +fun notNullByte2Number(x: Number?) { + js("if (x !== 123) throw 'error'") +} -@JsFun("(x) => { if (x !== null) throw 'error' }") -external fun nullByte2Number(x: Number?) +fun nullByte2Number(x: Number?) { + js("if (x !== null) throw 'error'") +} fun testNumber() { notNullNumber(123.5) diff --git a/compiler/testData/codegen/boxWasmJsInterop/nullableExternRefs.kt b/compiler/testData/codegen/boxWasmJsInterop/nullableExternRefs.kt index 793b8245461..de050009eba 100644 --- a/compiler/testData/codegen/boxWasmJsInterop/nullableExternRefs.kt +++ b/compiler/testData/codegen/boxWasmJsInterop/nullableExternRefs.kt @@ -19,23 +19,23 @@ fun assertFalse(x: Boolean) { external interface EI -@JsFun("() => null") -external fun getNull(): EI? +fun getNull(): EI? = + js("null") -@JsFun("() => undefined") -external fun getUndefined(): EI? +fun getUndefined(): EI? = + js("undefined") -@JsFun("(ref) => ref === null") -external fun isJsNull(ref: EI?): Boolean +fun isJsNull(ref: EI?): Boolean = + js("ref === null") -@JsFun("(ref) => ref === undefined") -external fun isJsUndefined(ref: EI?): Boolean +fun isJsUndefined(ref: EI?): Boolean = + js("ref === undefined") -@JsFun("() => null") -external fun getJsNullAsNonNullable(): EI +fun getJsNullAsNonNullable(): EI = + js("null") -@JsFun("() => undefined") -external fun getJsUndefinedAsNonNullable(): EI +fun getJsUndefinedAsNonNullable(): EI = + js("undefined") inline fun checkNPE(body: () -> Unit) { var throwed = false diff --git a/libraries/kotlin.test/wasm/src/main/kotlin/kotlin/test/JasmineLikeAdapter.kt b/libraries/kotlin.test/wasm/src/main/kotlin/kotlin/test/JasmineLikeAdapter.kt index 7e95e835a5e..378b88485dc 100644 --- a/libraries/kotlin.test/wasm/src/main/kotlin/kotlin/test/JasmineLikeAdapter.kt +++ b/libraries/kotlin.test/wasm/src/main/kotlin/kotlin/test/JasmineLikeAdapter.kt @@ -9,23 +9,25 @@ import kotlin.test.FrameworkAdapter import kotlin.js.Promise // Need to wrap into additional lambdas so that js launcher will work without Mocha or any other testing framework -@JsFun("(name, fn) => describe(name, fn)") -private external fun describe(name: String, fn: () -> Unit) +private fun describe(name: String, fn: () -> Unit): Unit = + js("describe(name, fn)") -@JsFun("(name, fn) => xdescribe(name, fn)") -private external fun xdescribe(name: String, fn: () -> Unit) +private fun xdescribe(name: String, fn: () -> Unit): Unit = + js("xdescribe(name, fn)") -@JsFun("(name, fn) => it(name, fn)") -private external fun it(name: String, fn: () -> Any?) +private fun it(name: String, fn: () -> Any?): Unit = + js("it(name, fn)") -@JsFun("(name, fn) => xit(name, fn)") -private external fun xit(name: String, fn: () -> Any?) +private fun xit(name: String, fn: () -> Any?): Unit = + js("xit(name, fn)") -@JsFun("(e) => { throw e }") -private external fun jsThrow(jsException: Dynamic) +private fun jsThrow(jsException: Dynamic) { + js("throw e") +} -@JsFun("(message, stack) => { const e = new Error(); e.message = message; e.stack = stack; return e; }") -private external fun throwableToJsError(message: String, stack: String): Dynamic +private fun throwableToJsError(message: String, stack: String): Dynamic { + js("var e = new Error(); e.message = message; e.stack = stack; return e;") +} private fun Throwable.toJsError(): Dynamic = throwableToJsError(message ?: "", stackTraceToString()) diff --git a/libraries/kotlin.test/wasm/src/main/kotlin/kotlin/test/TestApi.kt b/libraries/kotlin.test/wasm/src/main/kotlin/kotlin/test/TestApi.kt index 79372f97692..321fc068aa5 100644 --- a/libraries/kotlin.test/wasm/src/main/kotlin/kotlin/test/TestApi.kt +++ b/libraries/kotlin.test/wasm/src/main/kotlin/kotlin/test/TestApi.kt @@ -39,8 +39,8 @@ internal fun test(name: String, ignored: Boolean, testFn: () -> Any?) { internal var currentAdapter: FrameworkAdapter? = null -@JsFun("() => typeof describe === 'function' && typeof it === 'function'") -private external fun isJasmine(): Boolean +private fun isJasmine(): Boolean = + js("typeof describe === 'function' && typeof it === 'function'") internal fun adapter(): FrameworkAdapter { val result = currentAdapter ?: if (isJasmine()) JasmineLikeAdapter() else TeamcityAdapter() diff --git a/libraries/stdlib/wasm/builtins/kotlin/Throwable.kt b/libraries/stdlib/wasm/builtins/kotlin/Throwable.kt index fd14cb7f1ce..3ab31a26a69 100644 --- a/libraries/stdlib/wasm/builtins/kotlin/Throwable.kt +++ b/libraries/stdlib/wasm/builtins/kotlin/Throwable.kt @@ -40,5 +40,5 @@ public open class Throwable(open val message: String?, open val cause: kotlin.Th } } -@JsFun("() => new Error().stack") -private external fun captureStackTrace(): ExternalInterfaceType \ No newline at end of file +private fun captureStackTrace(): ExternalInterfaceType = + js("new Error().stack") diff --git a/libraries/stdlib/wasm/internal/kotlin/wasm/internal/ExceptionHelpers.kt b/libraries/stdlib/wasm/internal/kotlin/wasm/internal/ExceptionHelpers.kt index ec0c255537c..24acc198bcf 100644 --- a/libraries/stdlib/wasm/internal/kotlin/wasm/internal/ExceptionHelpers.kt +++ b/libraries/stdlib/wasm/internal/kotlin/wasm/internal/ExceptionHelpers.kt @@ -5,16 +5,16 @@ package kotlin.wasm.internal -@JsFun( -"""(message, wasmTypeName, stack) => { - const error = new Error(); - error.message = message; - error.name = wasmTypeName; - error.stack = stack; - throw error; - }""" -) -private external fun throwJsError(message: String?, wasmTypeName: String?, stack: String): Nothing +@Suppress("UNUSED_PARAMETER") // TODO: Remove after bootstrap update +private fun throwJsError(message: String?, wasmTypeName: String?, stack: String): Nothing { + js(""" + const error = new Error(); + error.message = message; + error.name = wasmTypeName; + error.stack = stack; + throw error; + """) +} internal fun throwAsJsException(t: Throwable): Nothing { throwJsError(t.message, t::class.simpleName, t.stackTraceToString()) diff --git a/libraries/stdlib/wasm/internal/kotlin/wasm/internal/ExternalWrapper.kt b/libraries/stdlib/wasm/internal/kotlin/wasm/internal/ExternalWrapper.kt index 7997857f4dd..fbf62f22fa3 100644 --- a/libraries/stdlib/wasm/internal/kotlin/wasm/internal/ExternalWrapper.kt +++ b/libraries/stdlib/wasm/internal/kotlin/wasm/internal/ExternalWrapper.kt @@ -3,6 +3,8 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ +@file:Suppress("UNUSED_PARAMETER") // TODO: Remove after bootstrap update + package kotlin.wasm.internal import kotlin.wasm.internal.reftypes.anyref @@ -31,6 +33,7 @@ internal class JsExternalBox @WasmPrimitiveConstructor constructor(val ref: Exte } } +@Suppress("DEPRECATION") //language=js @JsFun(""" (() => { @@ -85,41 +88,41 @@ return (obj) => { ) private external fun externrefHashCode(ref: ExternalInterfaceType): Int -@JsFun("ref => String(ref)") -private external fun externrefToString(ref: ExternalInterfaceType): String +private fun externrefToString(ref: ExternalInterfaceType): String = + js("String(ref)") -@JsFun("ref => Number(ref)") -private external fun externrefToInt(ref: ExternalInterfaceType): Int +private fun externrefToInt(ref: ExternalInterfaceType): Int = + js("Number(ref)") -@JsFun("ref => Number(ref)") -private external fun externrefToLong(ref: ExternalInterfaceType): Long +private fun externrefToLong(ref: ExternalInterfaceType): Long = + js("Number(ref)") -@JsFun("ref => Boolean(ref)") -private external fun externrefToBoolean(ref: ExternalInterfaceType): Boolean +private fun externrefToBoolean(ref: ExternalInterfaceType): Boolean = + js("Boolean(ref)") -@JsFun("ref => Number(ref)") -private external fun externrefToFloat(ref: ExternalInterfaceType): Float +private fun externrefToFloat(ref: ExternalInterfaceType): Float = + js("Number(ref)") -@JsFun("ref => Number(ref)") -private external fun externrefToDouble(ref: ExternalInterfaceType): Double +private fun externrefToDouble(ref: ExternalInterfaceType): Double = + js("Number(ref)") -@JsFun("x => x") -private external fun intToExternref(x: Int): ExternalInterfaceType +private fun intToExternref(x: Int): ExternalInterfaceType = + js("x") -@JsFun("x => x") -private external fun longToExternref(x: Long): ExternalInterfaceType +private fun longToExternref(x: Long): ExternalInterfaceType = + js("x") -@JsFun("x => x") -private external fun booleanToExternref(x: Boolean): ExternalInterfaceType +private fun booleanToExternref(x: Boolean): ExternalInterfaceType = + js("x") -@JsFun("x => x") -private external fun floatToExternref(x: Float): ExternalInterfaceType +private fun floatToExternref(x: Float): ExternalInterfaceType = + js("x") -@JsFun("x => x") -private external fun doubleToExternref(x: Double): ExternalInterfaceType +private fun doubleToExternref(x: Double): ExternalInterfaceType = + js("x") -@JsFun("(lhs, rhs) => lhs === rhs") -private external fun externrefEquals(lhs: ExternalInterfaceType, rhs: ExternalInterfaceType): Boolean +private fun externrefEquals(lhs: ExternalInterfaceType, rhs: ExternalInterfaceType): Boolean = + js("lhs === rhs") private external fun tryGetOrSetExternrefBox(ref: ExternalInterfaceType, ifNotCached: JsExternalBox): JsExternalBox? @@ -136,8 +139,8 @@ private fun ExternalInterfaceType.externAsWasmAnyref(): anyref = private fun Any.asWasmExternRef(): ExternalInterfaceType = implementedAsIntrinsic -@JsFun("(ref) => ref == null") -internal external fun isNullish(ref: ExternalInterfaceType?): Boolean +internal fun isNullish(ref: ExternalInterfaceType?): Boolean = + js("ref == null") @Suppress("UNUSED_PARAMETER") @ExcludedFromCodegen @@ -179,18 +182,18 @@ internal fun anyToExternRef(x: Any): ExternalInterfaceType { x.asWasmExternRef() } -@JsFun("x => x.length") -internal external fun stringLength(x: ExternalInterfaceType): Int +internal fun stringLength(x: ExternalInterfaceType): Int = + js("x.length") // kotlin string to js string export // TODO Uint16Array may work with byte endian different with Wasm (i.e. little endian) -@JsFun("""(address, length, prefix) => { +internal fun importStringFromWasm(address: Int, length: Int, prefix: ExternalInterfaceType?): ExternalInterfaceType { + js(""" const mem16 = new Uint16Array(wasmExports.memory.buffer, address, length); const str = String.fromCharCode.apply(null, mem16); return (prefix == null) ? str : prefix + str; + """) } -""") -internal external fun importStringFromWasm(address: Int, length: Int, prefix: ExternalInterfaceType?): ExternalInterfaceType internal fun kotlinToJsStringAdapter(x: String?): ExternalInterfaceType? { // Using nullable String to represent default value @@ -224,21 +227,18 @@ internal fun jsCheckIsNullOrUndefinedAdapter(x: ExternalInterfaceType?): Externa // js string to kotlin string import // TODO Uint16Array may work with byte endian different with Wasm (i.e. little endian) -//language=js -@JsFun( - """ (src, srcOffset, srcLength, dstAddr) => { - const mem16 = new Uint16Array(wasmExports.memory.buffer, dstAddr, srcLength); - let arrayIndex = 0; - let srcIndex = srcOffset; - while (arrayIndex < srcLength) { - mem16.set([src.charCodeAt(srcIndex)], arrayIndex); - srcIndex++; - arrayIndex++; - } - } -""" -) -internal external fun jsExportStringToWasm(src: ExternalInterfaceType, srcOffset: Int, srcLength: Int, dstAddr: Int) +internal fun jsExportStringToWasm(src: ExternalInterfaceType, srcOffset: Int, srcLength: Int, dstAddr: Int) { + js(""" + const mem16 = new Uint16Array(wasmExports.memory.buffer, dstAddr, srcLength); + let arrayIndex = 0; + let srcIndex = srcOffset; + while (arrayIndex < srcLength) { + mem16.set([src.charCodeAt(srcIndex)], arrayIndex); + srcIndex++; + arrayIndex++; + } + """) +} private const val STRING_INTEROP_MEM_BUFFER_SIZE = 65_536 // 1 page 4KiB @@ -269,14 +269,14 @@ internal fun jsToKotlinStringAdapter(x: ExternalInterfaceType): String { } -@JsFun("() => ''") -private external fun getJsEmptyString(): ExternalInterfaceType +private fun getJsEmptyString(): ExternalInterfaceType = + js("''") -@JsFun("() => true") -private external fun getJsTrue(): ExternalInterfaceType +private fun getJsTrue(): ExternalInterfaceType = + js("true") -@JsFun("() => false") -private external fun getJsFalse(): ExternalInterfaceType +private fun getJsFalse(): ExternalInterfaceType = + js("false") private val jsEmptyString by lazy(::getJsEmptyString) private val jsTrue by lazy(::getJsTrue) @@ -335,8 +335,9 @@ internal fun kotlinShortToExternRefAdapter(x: Short): ExternalInterfaceType = internal fun kotlinCharToExternRefAdapter(x: Char): ExternalInterfaceType = intToExternref(x.toInt()) -@JsFun("() => []") -internal external fun newJsArray(): ExternalInterfaceType +internal fun newJsArray(): ExternalInterfaceType = + js("[]") -@JsFun("(array, element) => { array.push(element); }") -internal external fun jsArrayPush(array: ExternalInterfaceType, element: ExternalInterfaceType) \ No newline at end of file +internal fun jsArrayPush(array: ExternalInterfaceType, element: ExternalInterfaceType) { + js("array.push(element);") +} diff --git a/libraries/stdlib/wasm/src/kotlin/Dynamic.kt b/libraries/stdlib/wasm/src/kotlin/Dynamic.kt index 22552f18965..b19d02f93fb 100644 --- a/libraries/stdlib/wasm/src/kotlin/Dynamic.kt +++ b/libraries/stdlib/wasm/src/kotlin/Dynamic.kt @@ -3,87 +3,89 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ +@file:Suppress("UNUSED_PARAMETER") // TODO: Remove after bootstrap update + package kotlin.js @PublishedApi -@JsFun("(obj, index, value) => obj[index] = value") -internal external fun dynamicSetBoolean(obj: Dynamic, index: String, value: Boolean) +internal fun dynamicSetBoolean(obj: Dynamic, index: String, value: Boolean): Unit = + js("obj[index] = value") @PublishedApi -@JsFun("(obj, index, value) => obj[index] = value") -internal external fun dynamicSetByte(obj: Dynamic, index: String, value: Byte) +internal fun dynamicSetByte(obj: Dynamic, index: String, value: Byte): Unit = + js("obj[index] = value") @PublishedApi -@JsFun("(obj, index, value) => obj[index] = value") -internal external fun dynamicSetShort(obj: Dynamic, index: String, value: Short) +internal fun dynamicSetShort(obj: Dynamic, index: String, value: Short): Unit = + js("obj[index] = value") @PublishedApi -@JsFun("(obj, index, value) => obj[index] = value") -internal external fun dynamicSetChar(obj: Dynamic, index: String, value: Char) +internal fun dynamicSetChar(obj: Dynamic, index: String, value: Char): Unit = + js("obj[index] = value") @PublishedApi -@JsFun("(obj, index, value) => obj[index] = value") -internal external fun dynamicSetInt(obj: Dynamic, index: String, value: Int) +internal fun dynamicSetInt(obj: Dynamic, index: String, value: Int): Unit = + js("obj[index] = value") @PublishedApi -@JsFun("(obj, index, value) => obj[index] = value") -internal external fun dynamicSetLong(obj: Dynamic, index: String, value: Long) +internal fun dynamicSetLong(obj: Dynamic, index: String, value: Long): Unit = + js("obj[index] = value") @PublishedApi -@JsFun("(obj, index, value) => obj[index] = value") -internal external fun dynamicSetFloat(obj: Dynamic, index: String, value: Float) +internal fun dynamicSetFloat(obj: Dynamic, index: String, value: Float): Unit = + js("obj[index] = value") @PublishedApi -@JsFun("(obj, index, value) => obj[index] = value") -internal external fun dynamicSetDouble(obj: Dynamic, index: String, value: Double) +internal fun dynamicSetDouble(obj: Dynamic, index: String, value: Double): Unit = + js("obj[index] = value") @PublishedApi -@JsFun("(obj, index, value) => obj[index] = value") -internal external fun dynamicSetString(obj: Dynamic, index: String, value: String?) +internal fun dynamicSetString(obj: Dynamic, index: String, value: String?): Unit = + js("obj[index] = value") @PublishedApi -@JsFun("(obj, index, value) => obj[index] = value") -internal external fun dynamicSetAny(obj: Dynamic, index: String, value: Any?) +internal fun dynamicSetAny(obj: Dynamic, index: String, value: Any?): Unit = + js("obj[index] = value") @PublishedApi -@JsFun("(obj, index) => obj[index]") -internal external fun dynamicGetBoolean(obj: Dynamic, index: String): Boolean +internal fun dynamicGetBoolean(obj: Dynamic, index: String): Boolean = + js("obj[index]") @PublishedApi -@JsFun("(obj, index) => obj[index]") -internal external fun dynamicGetByte(obj: Dynamic, index: String): Byte +internal fun dynamicGetByte(obj: Dynamic, index: String): Byte = + js("obj[index]") @PublishedApi -@JsFun("(obj, index) => obj[index]") -internal external fun dynamicGetShort(obj: Dynamic, index: String): Short +internal fun dynamicGetShort(obj: Dynamic, index: String): Short = + js("obj[index]") @PublishedApi -@JsFun("(obj, index) => obj[index]") -internal external fun dynamicGetChar(obj: Dynamic, index: String): Char +internal fun dynamicGetChar(obj: Dynamic, index: String): Char = + js("obj[index]") @PublishedApi -@JsFun("(obj, index) => obj[index]") -internal external fun dynamicGetInt(obj: Dynamic, index: String): Int +internal fun dynamicGetInt(obj: Dynamic, index: String): Int = + js("obj[index]") @PublishedApi -@JsFun("(obj, index) => obj[index]") -internal external fun dynamicGetLong(obj: Dynamic, index: String): Long +internal fun dynamicGetLong(obj: Dynamic, index: String): Long = + js("obj[index]") @PublishedApi -@JsFun("(obj, index) => obj[index]") -internal external fun dynamicGetFloat(obj: Dynamic, index: String): Float +internal fun dynamicGetFloat(obj: Dynamic, index: String): Float = + js("obj[index]") @PublishedApi -@JsFun("(obj, index) => obj[index]") -internal external fun dynamicGetDouble(obj: Dynamic, index: String): Double +internal fun dynamicGetDouble(obj: Dynamic, index: String): Double = + js("obj[index]") @PublishedApi -@JsFun("(obj, index) => obj[index]") -internal external fun dynamicGetString(obj: Dynamic, index: String): String? +internal fun dynamicGetString(obj: Dynamic, index: String): String? = + js("obj[index]") @PublishedApi -@JsFun("(obj, index) => obj[index]") -internal external fun dynamicGetAny(obj: Dynamic, index: String): Any? +internal fun dynamicGetAny(obj: Dynamic, index: String): Any? = + js("obj[index]") @PublishedApi internal fun Dynamic.getBoolean(index: String): Boolean = dynamicGetBoolean(this, index) @@ -184,14 +186,12 @@ operator fun Dynamic.set(index: Int, value: Any?) { this[index.toString()] = value } -@JsFun("(x) => x") -private external fun unsafeCastJs(x: String): Dynamic +private fun unsafeCastJs(x: String): Dynamic = js("x") @Suppress("UNCHECKED_CAST") fun String.unsafeCast(): T = unsafeCastJs(this) as T -@JsFun("(x) => x") -private external fun unsafeCastJs(x: Boolean): Dynamic +private fun unsafeCastJs(x: Boolean): Dynamic = js("x") /** * Reinterprets boolean value as a value of the specified type [T] without any actual type checking. @@ -210,10 +210,12 @@ fun Nothing?.unsafeCast(): Dynamic? = null @Suppress("UNCHECKED_CAST") fun Dynamic.unsafeCast(): T = this as T -@JsFun("e => { throw e; }") -private external fun jsThrow(e: Dynamic) +private fun jsThrow(e: Dynamic) { + js("throw e;") +} -@JsFun("""(f) => { +private fun jsCatch(f: () -> Unit): Dynamic? { + js(""" let result = null; try { f(); @@ -221,8 +223,8 @@ private external fun jsThrow(e: Dynamic) result = e; } return result; -}""") -private external fun jsCatch(f: () -> Unit): Dynamic? + """) +} /** * For a Dynamic value caught in JS, returns the corresponding [Throwable] diff --git a/libraries/stdlib/wasm/src/kotlin/io.kt b/libraries/stdlib/wasm/src/kotlin/io.kt index ac34163de4b..4a058a9475f 100644 --- a/libraries/stdlib/wasm/src/kotlin/io.kt +++ b/libraries/stdlib/wasm/src/kotlin/io.kt @@ -3,18 +3,20 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ +@file:Suppress("UNUSED_PARAMETER") // TODO: Remove after bootstrap update + package kotlin.io import kotlin.wasm.internal.* -@JsFun("(error) => console.error(error)") -internal external fun printError(error: String?): Unit +internal fun printError(error: String?): Unit = + js("console.error(error)") -@JsFun("(message) => console.log(message)") -private external fun printlnImpl(message: String?): Unit +private fun printlnImpl(message: String?): Unit = + js("console.log(message)") -@JsFun("(message) => typeof write !== 'undefined' ? write(message) : console.log(message)") -private external fun printImpl(message: String?): Unit +private fun printImpl(message: String?): Unit = + js("typeof write !== 'undefined' ? write(message) : console.log(message)") /** Prints the line separator to the standard output stream. */ public actual fun println() { diff --git a/libraries/stdlib/wasm/src/kotlin/random/PlatformRandom.kt b/libraries/stdlib/wasm/src/kotlin/random/PlatformRandom.kt index 5a320d56e75..149f9873099 100644 --- a/libraries/stdlib/wasm/src/kotlin/random/PlatformRandom.kt +++ b/libraries/stdlib/wasm/src/kotlin/random/PlatformRandom.kt @@ -5,8 +5,8 @@ package kotlin.random -@JsFun("() => ((Math.random() * Math.pow(2, 32)) | 0)") -private external fun initialSeed(): Int +private fun initialSeed(): Int = + js("((Math.random() * Math.pow(2, 32)) | 0)") internal actual fun defaultPlatformRandom(): Random = Random(initialSeed()) diff --git a/libraries/stdlib/wasm/src/kotlin/time/Duration.kt b/libraries/stdlib/wasm/src/kotlin/time/Duration.kt index c35a207f63e..03edf9e9b48 100644 --- a/libraries/stdlib/wasm/src/kotlin/time/Duration.kt +++ b/libraries/stdlib/wasm/src/kotlin/time/Duration.kt @@ -3,17 +3,19 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ +@file:Suppress("UNUSED_PARAMETER") // TODO: Remove after bootstrap update + package kotlin.time import kotlin.math.* internal actual inline val durationAssertionsEnabled: Boolean get() = true -@JsFun("(value, decimals) => value.toFixed(decimals)") -private external fun toFixed(value: Double, decimals: Int): String +private fun toFixed(value: Double, decimals: Int): String = + js("value.toFixed(decimals)") -@JsFun("(value, decimals) => value.toPrecision(decimals)") -private external fun toPrecision(value: Double, decimals: Int): String +private fun toPrecision(value: Double, decimals: Int): String = + js("value.toPrecision(decimals)") internal actual fun formatToExactDecimals(value: Double, decimals: Int): String { val rounded = if (decimals == 0) { @@ -34,5 +36,5 @@ internal actual fun formatToExactDecimals(value: Double, decimals: Int): String } } -@JsFun("(value, decimals) => value.toLocaleString(\"en-us\", ({\"maximumFractionDigits\": decimals}))") -external internal actual fun formatUpToDecimals(value: Double, decimals: Int): String \ No newline at end of file +internal actual fun formatUpToDecimals(value: Double, decimals: Int): String = + js("(value, decimals) => value.toLocaleString(\"en-us\", ({\"maximumFractionDigits\": decimals}))") \ No newline at end of file diff --git a/libraries/stdlib/wasm/src/kotlin/time/TimeSources.kt b/libraries/stdlib/wasm/src/kotlin/time/TimeSources.kt index 68060b4d470..bf61e721b81 100644 --- a/libraries/stdlib/wasm/src/kotlin/time/TimeSources.kt +++ b/libraries/stdlib/wasm/src/kotlin/time/TimeSources.kt @@ -3,20 +3,22 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ +@file:Suppress("UNUSED_PARAMETER") // TODO: Remove after bootstrap advance + package kotlin.time import kotlin.wasm.internal.ExternalInterfaceType import kotlin.time.TimeSource.Monotonic.ValueTimeMark import kotlin.time.Duration.Companion.milliseconds -@JsFun("() => typeof globalThis !== 'undefined' && typeof globalThis.performance !== 'undefined' ? globalThis.performance : null") -private external fun tryGetPerformance(): ExternalInterfaceType? +private fun tryGetPerformance(): ExternalInterfaceType? = + js("typeof globalThis !== 'undefined' && typeof globalThis.performance !== 'undefined' ? globalThis.performance : null") -@JsFun("(performance) => performance.now()") -private external fun getPerformanceNow(performance: ExternalInterfaceType): Double +private fun getPerformanceNow(performance: ExternalInterfaceType): Double = + js("performance.now()") -@JsFun("() => Date.now()") -private external fun dateNow(): Double +private fun dateNow(): Double = + js("Date.now()") @SinceKotlin("1.3") @ExperimentalTime diff --git a/libraries/stdlib/wasm/src/kotlin/w3cSupport.kt b/libraries/stdlib/wasm/src/kotlin/w3cSupport.kt index 0d7e3982d22..11966e23aab 100644 --- a/libraries/stdlib/wasm/src/kotlin/w3cSupport.kt +++ b/libraries/stdlib/wasm/src/kotlin/w3cSupport.kt @@ -9,5 +9,5 @@ package kotlin.js internal val undefined: Nothing? = null @PublishedApi -@JsFun("() => ({})") -internal external fun newJsObject(): Dynamic \ No newline at end of file +internal fun newJsObject(): Dynamic = + js("({})") diff --git a/libraries/stdlib/wasm/test/js/AsyncTest.kt b/libraries/stdlib/wasm/test/js/AsyncTest.kt index e8f6563e709..2bc10248b9a 100644 --- a/libraries/stdlib/wasm/test/js/AsyncTest.kt +++ b/libraries/stdlib/wasm/test/js/AsyncTest.kt @@ -3,11 +3,11 @@ package test.js import kotlin.js.* import kotlin.test.* -@JsFun("async () => 'foo'") -internal external fun jsAsyncFoo(): Promise +internal fun jsAsyncFoo(): Promise = + js("(async () => 'foo')()") -@JsFun("() => 'foo'") -internal external fun jsFoo(): Dynamic +internal fun jsFoo(): Dynamic = + js("'foo'") var state: Dynamic? = null diff --git a/libraries/stdlib/wasm/test/unsafe/MemoryAllocationTest.kt b/libraries/stdlib/wasm/test/unsafe/MemoryAllocationTest.kt index 94836072550..d4563cca4c6 100644 --- a/libraries/stdlib/wasm/test/unsafe/MemoryAllocationTest.kt +++ b/libraries/stdlib/wasm/test/unsafe/MemoryAllocationTest.kt @@ -3,8 +3,8 @@ package test.wasm.unsafe import kotlin.wasm.unsafe.* import kotlin.test.* -@JsFun("(a, b) => a + b") -private external fun jsConcatStrings(a: String, b: String): String +private fun jsConcatStrings(a: String, b: String): String = + js("a + b") @OptIn(UnsafeWasmMemoryApi::class) class MemoryAllocationTest {