-
Notifications
You must be signed in to change notification settings - Fork 17.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
wasm: re-use //export mechanism for exporting identifiers within wasm modules #25612
Comments
I've hit the same rough patches after doing some "real" work with wasm in Go, and trying to integrate my module into a JS workflow. To me, the primary issue is how Go functions are provided to JS. Presently, it seems that polluting the global object ( func main() {
done := make(chan struct{})
js.Global().Set("protolock", make(map[string]interface{}))
module := js.Global().Get("protolock")
module.Set("initialize",
js.FuncOf(func(this js.Value, args []js.Value) interface{} {
if args == nil {
fmt.Println("initialize: not enough args")
return nil
}
return toJson(initialize(args[0].String()))
}),
)
module.Set("status",
js.FuncOf(func(this js.Value, args []js.Value) interface{} {
if args == nil || len(args) < 2 {
fmt.Println("status: not enough args")
return nil
}
return toJson(status(args[0].String(), args[1].String()))
}))
<-done
} While this works, it doesn't make for a very seamless integration with modern JS workflows. Ideally, we'd be able to generate at minimum a
This would make the interoperability between wasm modules in a JS environment much simpler, hiding the fact that a function is run in wasm. I'm not sure the Do we have a working doc/wiki anywhere to track this? I couldn't find anything in an admittedly rather shallow search. Happy to kick it off if one does not exist yet. |
After more digging and a quick browse through @neelance's wasm implementation as well as the disassembled .wat of a Go compiled .wasm binary, it's much more clear that the |
TinyGo exposes this functionality via a |
The meaning for each approach seems the same though: "This function should be included in the wasm exports list, and therefore callable from Javascript. Functions without it will not be". @johanbrandhorst When you say there's a way to do it in pure Go with |
|
I mean that you can also do js.Global().Set("myexport", js.FuncOf(func(this js.Value, args []js.Value) interface{} {
//stuff
}) |
the point of my original request is exactly to not only target and support |
It'll be hard to say whether we'll have the same capability to set exports via |
the wasm can't be used in webworker also. |
Why can’t the wasm be used in a webworker? |
@pkieltyka because the exported function is mounted on window or global variable, but in webworker, we should add it on self |
Shouldn't standard Go exporting rules be used? |
I was coming from the taking a regular Go package (non- |
Note that exporting all Go symbols starting with an uppercase character may drastically increase file size, as the linker won't be able to do dead code elimination. I'm not sure whether this is happening right now, but it's something to keep in mind. |
Agree, i would love to experiment golang wasm target for extending a golang software through a plugin like mechanism, running it in wasm intepreters like https://github.com/go-interpreter/wagon, https://github.com/perlin-network/life or https://github.com/wasmerio/go-ext-wasm. Is this worth another issue? |
I would imagine only the Go symbols in the root/main package would need to be exported. |
Another possible option would be a compiler(or linker) argument with a list of functions that need to be exported. |
Please see #38248, which I believe solves the same issue in a different way. |
I have been adding exports to the global |
There are some really great thoughts on this issue, but I'm curious about the current momentum on this topic. After scanning the open issues, I've come to the following two conclusions for myself:
Summary: it is currently painful to turn Go code into useful and concise WASM. The lack of idiomatic use of modules appears to be at the heart of that pain. |
Way late in the comment process, but the ability to mix host binary code along with WASM code linked into the same binary and not be forced to have 2 separate projects, each with its own GOOS= GOARCH= . Just my 2 cents here. |
I guess this ticket needs to be implemented, if we want to build a webassembly component in go, as the Imports and Exports of the webassembly module must be defined in the wasm file. |
@nilslice I know it has been a long, long time since you wrote this:
I'm currently looking at how to make it possible to mix wasm modules compiled with different versions of Go or TinyGo in the same application. I can't see any way to do this using the stock wasm_exec.js as long as Go() itself is a global. I'm considering starting a Go proposal which would completely remove globalThis from wasm_exec.js. Do you recall if you tried that yourself way back when? Extism completely bypasses this problem and enables both mixed-version as well as mixed-language apps via its plugins, right? Skimming through the code, it looks like you're using Rust as the runtime entrypoint, which gives you more flexibility in the first place versus what's implemented in Go's wasm_exec.js? |
😄 wow, has it really been nearly 5 years!? ...a long time indeed! To be honest, I'm not sure I tried TinyGo back then. I can see how what aiming to do is challenging though. If you're able to, it might help to drop support for anything
Yes, Extism bypasses this probelm entirely enabling precisely what you mention. However, in the browser, we have a pure TypeScript implementation of the Extism ABI / runtime. So it doesn't require Rust at all. Extism was created to solve the problem you describe, and normalize the guest/host environment to provide consistency -- not dissimilar to how jQuery smoothed over the nuances between browser APIs back in the day. We're currently in the midst of publishing a v1.0 of Extism and are near ready to release this JS SDK (which works universally in the browser, Node, Deno and Bun): https://github.com/extism/js-sdk If you're interested, it would be a great time to try this out and share feedback. For a JS host, please use this branch if you're also using the latest version of our PDKs. I don't mean to clog up this issue with Extism stuff, so if you'd like to chat more about it I'm always available on our Discord or on the repo issue tracker! |
I think this issue can be closed in favor of the new wasmexport proposal: #42372. |
#65199 is implemented. Closing this as a dup. Thanks. |
Right now, compiling the following piece of Go code:
like so:
will produce the following
foo.wasm
module:especially:
ie: the user can not control what is exported.
the recommended way to export something currently, is to use
js.NewCallback
.this is - mainly - because one needs to setup a few things for the Go and js runtimes to cooperate nicely together.
I would argue that, in the same spirit than when one compiles the same
main.go
file with-buildmode=c-shared
, it should be possible to achieve the same thing forGOOS=xyz GOARCH=wasm
, and only export what is//export
-ed.initialization of the runtime(s) would be performed via the wasm module's start function.
(this is a re-hash of neelance/go#22.)
The text was updated successfully, but these errors were encountered: