Easily create Kotlin Web Assembly project from these multiplatform boilerplate Gradle DSL
This code involves Custom JavaScript - to - Kotlin - to - JavaScript stub
Kotlin Code
package wasm
import kotlinx.interop.wasm.dom.*
import kotlinx.wasm.jsinterop.*
import kotlinx.cinterop.*
import mymod.*
fun main() {
//simple method call to a kotlin custom code
mod.sayHello(" hello")
//library method from "kotlinx.interop.wasm.dom"
var div = document.getElementById("mydiv")
//stub the div as object from "mymod"
div = div.asDOMDiv
//advanced property method call from "mymod"
div.innerHTML = "Kotlin WebAssembly Accessing HTML DOM"
}
JavaScript Code
No need write the WASM loader, simply add this html
<script src="build/bin/wasm/releaseExecutable/sboot_wasm_dom.wasm.js" wasm="build/bin/wasm/releaseExecutable/sboot_wasm_dom.wasm"> </script>
To access DOM you need to write a kotlin+js stub and compile it to .klib
JavaScript Stub Code
konan.libraries.push ({
sayHello: function(arena, obj, idPtr, idLen, resultArena) {
var text1 = toUTF16String(idPtr, idLen);
console.log("stub: " + text1);
},
getMyModule: function(resultArena) {
if(!window['mymodule']) window['mymodule'] = {}
return toArena(resultArena, window['mymodule']);
},
getInnerHTML: function(arena, obj) {
var result = kotlinObject(arena, obj).innerHTML;
return result;
},
setInnerHTML: function(arena, obj, idPtr, idLen, resultArena) {
var text1 = toUTF16String(idPtr, idLen);
kotlinObject(arena, obj).innerHTML = text1;
}
})
Kotlin Stub Code
package mymod
import kotlinx.wasm.jsinterop.*
@SymbolName("sayHello")
external public fun sayHello(arena: Int, index: Int, idPtr: Int, idLen: Int, resultArena: Int): Unit
@SymbolName("getMyModule")
external public fun getMyModule(resultArena: Int): Int
@SymbolName("getInnerHTML")
external public fun getInnerHTML(arena: Int, index: Int, resultArena: Int): String
@SymbolName("setInnerHTML")
external public fun setInnerHTML(arena: Int, index: Int, idPtr: Int, idLen: Int, resultArena: Int): Unit
open class MyModule(arena: Int, index: Int): JsValue(arena, index) {
constructor(jsValue: JsValue): this(jsValue.arena, jsValue.index)
fun sayHello(id: String): Unit {
sayHello(this.arena, this.index, stringPointer(id), stringLengthBytes(id), ArenaManager.currentArena)
}
companion object {
}
}
val JsValue.asMyModule: MyModule
get() {
return MyModule(this.arena, this.index)
}
val mod: MyModule
get() {
val wasmRetVal = getMyModule(ArenaManager.currentArena)
return MyModule(ArenaManager.currentArena, wasmRetVal)
}
open class DOMDiv(arena: Int, index: Int): JsValue(arena, index) {
constructor(jsValue: JsValue): this(jsValue.arena, jsValue.index)
var innerHTML: String
get() {
val wasmRetVal = getInnerHTML(this.arena, this.index, ArenaManager.currentArena)
return wasmRetVal
}
set(value: String) {
setInnerHTML(this.arena, this.index, stringPointer(value), stringLengthBytes(value), ArenaManager.currentArena)
}
companion object {
}
}
val JsValue.asDOMDiv: DOMDiv
get() {
return DOMDiv(this.arena, this.index)
}
Run gradle command
gradle assemble
Run gradle command
gradle run
Browse http://localhost:8080/index.html
Output 1: Check your browser console for text output "stub: hello" which will be the output from Web Assembly Code
Output 2: Check your browser the DIV tag updated using innerHTML - "Kotlin WebAssembly Accessing HTML DOM"
Spring Boot is used as a server to give MIME content-type as "application/wasm" , currently browsers does not recognize .wasm files with that MIME
Note:
The .klib file is auto generated in this project gradle task using kotlinc commandline, A typical example command line for generating klib in common is as below
kotlinc -include-binary t1.js -produce library -o t1.klib -target wasm32 t1.kt
Where t1.js which has JS stub and t1.kt has Kotlin code and corresponding Stub code
End Of Article