Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to execute Kotlin WebAssembly function from JavaScript?

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.

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
like image 390
Michael Kleimann Avatar asked Jan 10 '19 23:01

Michael Kleimann


People also ask

Can JavaScript run Kotlin?

You can freely talk to JavaScript from Kotlin via dynamic types. If you want to use the full power of the Kotlin type system, you can create external declarations for JavaScript libraries which will be understood by the Kotlin compiler and the surrounding tooling.

Does Kotlin compile to WebAssembly?

Kotlin-Native can be compiled to WebAssembly, but this method is going away. The new compiler is not yet readily available.

Is Kotlin client-side?

Yes. In addition to using for backend web, you can also use Kotlin/JS for client-side web. Kotlin can use definitions from DefinitelyTyped to get static typing for common JavaScript libraries, and it is compatible with existing module systems such as AMD and CommonJS.


1 Answers

I recently did some research into this myself and from my understanding, your usecase is not really supported so far. What you are looking for is essentially a library, yet if you look into the documentation of Kotlin/Native it states:

The following binary kinds are supported (note that not all the kinds are available for all native platforms):

[...]

sharedLib - a shared native library - all native targets except wasm32

staticLib - a static native library - all native targets except wasm32

From my understanding, the difficulty lies withing data passing between Javascript and WebAssembly as it only supports ints or the rather roundabout way via linear memory.

like image 62
kekx Avatar answered Sep 17 '22 17:09

kekx