Parcel: Feature: Go Support (golang)

Created on 8 Apr 2019  ยท  2Comments  ยท  Source: parcel-bundler/parcel

๐Ÿ™‹ feature request

Similar to Rust support, it would be nice/interesting to see Go (golang) support.

๐Ÿค” Expected Behavior

import { foo } from 'file.go'

๐Ÿ˜ฏ Current Behavior

Currently unsupported

๐Ÿ’ Possible Solution

I'm not familiar enough with internals to know where to start, should build using Go model, but the injection points should be similar to Rusts's wasm file usage.

๐Ÿ”ฆ Context

It's not something that is directly impacting me currently. Given the communication models in Go, it may be a great fit.

๐Ÿ’ป Examples

N/A

Feature โœจ Parcel 2

Most helpful comment

I have actually tried to implement this before, but failed at importing the WASM modules as they are laid out differently than Rust (rather than exporting functions, it sets variables on the global object). Go also needs a JS loader file which is not currently supported AFAIK.

Some more details on this: Go treats a WASM as a whole program that gets executed rather than a collection of functions. (https://www.aaron-powell.com/posts/2019-02-05-golang-wasm-2-writing-go#conclusion). To start a Go WASM program you would actually do this:

<html>
    <head>
      <meta charset="utf-8">
      <script src="wasm_exec.js"></script>
      <script>
            async function init() {
                const go = new Go();
                let result = await WebAssembly.instantiateStreaming(fetch("main.wasm"), go.importObject)
                go.run(result.instance);
            }
            init();
       </script>
    </head>
    <body></body>
</html>

The Go required to register a math add function would look something like this

package main

import "syscall/js"

func add(i []js.Value) {
    js.Global().Set("output", js.ValueOf(i[0].Int()+i[1].Int()))
    println(js.ValueOf(i[0].Int() + i[1].Int()).String())
}

func registerCallbacks() {
    js.Global().Set("add", js.NewCallback(add))
}

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

    println("WASM Go Initialized")
    // register functions
    registerCallbacks()
    <-c
}

The main issue is not the building of the WASM but actually running and exposing functions. We would have to do some magic to expose the functions individually the same way as we do for Rust.

The building is actually way easier to implement than Rust. If I should make a PR to implement building the WASM modules, please let me know.

EDIT: I have an open issue regarding go supporting instance.exports: https://github.com/golang/go/issues/31574

All 2 comments

I have actually tried to implement this before, but failed at importing the WASM modules as they are laid out differently than Rust (rather than exporting functions, it sets variables on the global object). Go also needs a JS loader file which is not currently supported AFAIK.

Some more details on this: Go treats a WASM as a whole program that gets executed rather than a collection of functions. (https://www.aaron-powell.com/posts/2019-02-05-golang-wasm-2-writing-go#conclusion). To start a Go WASM program you would actually do this:

<html>
    <head>
      <meta charset="utf-8">
      <script src="wasm_exec.js"></script>
      <script>
            async function init() {
                const go = new Go();
                let result = await WebAssembly.instantiateStreaming(fetch("main.wasm"), go.importObject)
                go.run(result.instance);
            }
            init();
       </script>
    </head>
    <body></body>
</html>

The Go required to register a math add function would look something like this

package main

import "syscall/js"

func add(i []js.Value) {
    js.Global().Set("output", js.ValueOf(i[0].Int()+i[1].Int()))
    println(js.ValueOf(i[0].Int() + i[1].Int()).String())
}

func registerCallbacks() {
    js.Global().Set("add", js.NewCallback(add))
}

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

    println("WASM Go Initialized")
    // register functions
    registerCallbacks()
    <-c
}

The main issue is not the building of the WASM but actually running and exposing functions. We would have to do some magic to expose the functions individually the same way as we do for Rust.

The building is actually way easier to implement than Rust. If I should make a PR to implement building the WASM modules, please let me know.

EDIT: I have an open issue regarding go supporting instance.exports: https://github.com/golang/go/issues/31574

looks like that ticket got closed, see https://github.com/golang/go/issues/25612

Was this page helpful?
0 / 5 - 0 ratings