How to call Kotlin WebAssembly functions from JavaScript?


#1

My goal is to write a Kotlin library, compile it to WebAssembly and call its functions from JS. Since a few hours I try to get a simple hello world to work. The documentation on this topic is either non existent or well hidden.

This is my kotlin file:

@Used
public fun hello() {
    println("Hello world!")
}

fun main(args: Array<String>) {
    println("main() function executed!")
}

When I compile it to WebAssembly, I get a hello.wasm and hello.wasm.js file.

First I tried to use something like this to execute the function:

WebAssembly.instantiateStreaming(fetch('hello.wasm'), importObject)
    .then(obj => obj.instance.exports.hello());

Then I understood that I need to pass the imports from my hello.wasm.js file in the importObject parameter. So I guess that I need to use the hello.wasm.js file to correctly initialize my wasm program.

When I load my wasm like the following, I don’t get any errors and the main() function is executed.

<script wasm="hello.wasm" src="hello.wasm.js"></script>

But how can I execute the hello() function from JavaScript? The only kotlin wasm examples I found are not calling specific functions but rendering something from the main() function.

In the end I want to have multiple functions (with parameters and return value) doing heavier calculations which I can call from my JS code if needed. The result is getting more accurate the longer the calculation runs, so I may want to update the DOM every now and then to update the displayed value. Is this even the right approach? Or would I rather create one wasm per calculation function?

Also any links to relevant documentation are very much appreciated.


UPDATE: I managed to execute the function, but I don’t believe this is the correct way:

<script wasm="hello.wasm" src="hello.wasm.js"></script>
<script>
WebAssembly.instantiateStreaming(fetch('hello.wasm'), konan_dependencies)
        .then(obj => obj.instance.exports['kfun:hello$ValueType']());
</script>

The problem is, that my wasm file is fetched two times if I do it like that.

Loading only the hello.wasm.js file without the wasm attribute gets me the following error:

Uncaught Error: Could not find the wasm attribute pointing to the WebAssembly binary.
    at Object.konan.moduleEntry (stats.wasm.js:433)
    at stats.wasm.js:532

#2

From where is the @Used attribute that you are using?