Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to explicitly call an exported Go WebAssembly function from JS?

Is it possible to call a Go WebAssembly function, other than main, in Javascript?

Let me first show what I did. My Go functions are defined as follows:

package main

import "fmt"

func main() {
    fmt.Println("it works!")
}

func add(a, b int) int {
    return a + b
}

I can only invoke the main function:

const go = new Go();

const data   = await fetch("http://localhost:3333/main.wasm");
const result = await WebAssembly.instantiateStreaming(data, go.importObject);

go.run(result.instance);

which returns it works! as expected.

However, whenever I try to invoke the add function, I receive TypeError: Cannot read property 'add' of undefined at Welcome.getWasm, because both result.exports, result.instance.exports do not contain my function. I also tried capitalizing the Go function, but at no avail.

Thus, I started wondering what could be a problem – is it even possible to call a random Go function from Javascript? Or can I only call the default main() function?

like image 328
krlc Avatar asked May 31 '19 15:05

krlc


People also ask

Can go be compiled to Wasm?

To be able to compile it to WASM you need to add GOOS=js GOARCH=wasm to the build command. This tells Go to compile to a . wasm file.

Can JavaScript be compiled to WebAssembly?

Yes, it is totally possible to call JavaScript-functions from inside your running WebAssembly functions!

How do I run a WebAssembly code?

To use WebAssembly in JavaScript, you first need to pull your module into memory before compilation/instantiation. This article provides a reference for the different mechanisms that can be used to fetch WebAssembly bytecode, as well as how to compile/instantiate then run it.


Video Answer


1 Answers

Yes, it is possible. You can "export" a function to the global context (i.e. window in browser, global in nodejs):

js.Global().Set("add", js.FuncOf(addFunction))

Where "add" is the name that you can use to call the function from Javascript (window.add) and "addFunction" is a Go function in your Go code, next to your main.

Note that "addFunction" must follow that method signature:

package main

import (
    "syscall/js"
)

func addFunction(this js.Value, p []js.Value) interface{} {
    sum := p[0].Int() + p[1].Int()
    return js.ValueOf(sum)
}

func main() {
    c := make(chan struct{}, 0)

    js.Global().Set("add", js.FuncOf(addFunction))

    <-c
}

After "go.run(result.instance);" you can run.

go.run(result.instance);
add(100,200);
like image 132
jordiburgos Avatar answered Nov 15 '22 21:11

jordiburgos