design: add go:wasmexport proposal

Detailed proposal about issue https://golang.org/issue/42372

For golang/go#42372

Change-Id: I48f5d1d6b055349743e7018f8bc3ebe2fa2bcda1
GitHub-Last-Rev: d10c2d44921519cd0b1c2bffeaf184815b4720f8
GitHub-Pull-Request: golang/proposal#31
Reviewed-on: https://go-review.googlesource.com/c/proposal/+/278692
Reviewed-by: Ian Lance Taylor <iant@golang.org>
diff --git a/design/42372-wasmexport.md b/design/42372-wasmexport.md
new file mode 100644
index 0000000..6502cb9
--- /dev/null
+++ b/design/42372-wasmexport.md
@@ -0,0 +1,203 @@
+# Proposal: go:wasmexport directive
+
+Author: Francesco Guardiani
+
+Last updated: 2020-12-17
+
+Discussion at https://golang.org/issue/42372.
+
+## Abstract
+
+The goal of this proposal is to add a new compiler directive `go:wasmexport` to
+export Go functions when compiling to WebAssembly.
+
+This directive is similar to the `go:wasmimport` directive proposed in
+https://golang.org/issue/38248.
+
+## Background
+
+Wasm is a technology that allows users to execute instructions inside virtual
+machines sandboxed by default, that is the Wasm user by default cannot interact
+with the external world and viceversa.
+
+Wasm can be used in very different contexts and, recently, it's becoming more
+and more used as a technology to extend, at runtime, software running outside
+browsers.
+
+In order to do that, the extensible software provides to the "extension
+developers" ad-hoc libraries to develop Wasm modules.
+
+Thanks to an ABI well-defined, the extensible software will be able to access to
+the compiled Wasm module and execute the extension logic.
+
+Some systems that adopt this extension mechanism include
+[Istio](https://istio.io/latest/docs/concepts/wasm/) and
+[OPA](https://www.openpolicyagent.org/docs/v0.21.1/wasm/).
+
+In order to use Wasm modules in such environments, the developer should be able
+to define which Go functions can be accessible from the outside and what host
+functions can be accessible from within the Wasm module.
+
+While the latter need is already covered and implemented by the issue
+https://golang.org/issue/38248, this proposal tries to address the former need.
+
+### An example extension module
+
+As a complete example, assume there is a system that triggers some signals and
+that can be extended to develop applications based on these signals.
+
+The extension module is intended to be used just as "signal handler", maybe with
+some lifecycle methods (e.g. start and stop) to prepare the environment and to
+teardown it.
+
+The extension module, from a host perspective, is an actor that needs to be
+invoked on every this use case the module
+
+When the host wants to start using the module, the `start` export is invoked.
+
+`start` in its logic spawns, using the `go` instruction, a goroutine that loops
+on a global channel, like:
+
+```go
+for event := range eventsch {
+  // Process events
+}
+```
+
+Then each export eventually push messages in this `eventsch`:
+
+```go
+eventsch <- value
+```
+
+When `process_a` export is invoked, the value will be pushed inside the
+`eventsch` and the goroutine spawned by `start` will catch it.
+
+In other words, the interaction between host and module looks like this:
+
+![](https://user-images.githubusercontent.com/6706544/98349379-34159400-201a-11eb-8417-5d728ce141ca.png)
+
+## Proposal
+
+### Interface
+
+A new directive will allow users to define what functions should be exported in
+the Wasm module produced by the Go compiler. Given this code:
+
+```go
+//go:wasmexport hello_world
+func HelloWorld() {
+  println("Hello world!")
+}
+```
+
+The compiler will produce this Wasm module:
+
+```shell
+% wasm-nm -e sample/main.wasm
+e run
+e resume
+e getsp
+e hello_world
+```
+
+Note that the first 3 exports are the default hardcoded exports of Go ABI.
+
+### Execution
+
+Every time the module executor (also called host) will invoke the `hello_world`
+export, a new goroutine is spawned and immediately executed to run the
+instructions in `HelloWorld`.
+
+This wakes up the goroutine scheduler, which will try to run all the goroutines
+up to the point when they are all parked.
+
+When all goroutines are parked, the `hello_world` export will complete its
+execution and return the return value of `HelloWorld` back to the host.
+
+### Types
+
+The exported function can contain in its signature (parameters and return value)
+only Wasm supported types.
+
+## Rationale
+
+## Relation with `syscall/js.FuncOf`
+
+The functionality of defining exports already exists in Go, through the Go JS
+ABI. The cons of `syscall/js.FuncOf` are that is not idiomatic for Wasm users
+and assumes that the host is a Javascript environment.
+
+Because of the issues described above, It's complicated to support, from the
+extensible system perspective, Wasm Go modules, because it requires "faking" a
+Javascript environment to integrate with the Go ABI.
+
+### Relation with Wasm threads proposal
+
+This approach doesn't mandate any particular interaction style between host and
+module, nor the underlying threading system the host uses to execute the module.
+
+In fact, as of today, every Wasm module just assumes the underlying execution
+environment, that is the virtual machine that executes Wasm instructions, as
+sequential. There is no notion of parallelism.
+
+There is a proposal in the Wasm community, called
+[Wasm threads proposal](https://github.com/webassembly/threads), that allows
+Wasm virtual machines to be able to process instructions in parallel.
+
+The Go project could, at some point, evolve to support the Wasm Threads
+proposal, exposing an interface to execute the goroutine scheduler on multiple
+threads.
+
+This might affect or not (depending on the future decisions) the execution model
+of the export, but without effectively changing the semantics from the user
+point of view, nor the interface described above.
+
+For example, assume Go implements the goroutine scheduler on multiple Wasm
+threads, from the user perspective there is no semantic difference if the export
+function `hello_world` returns after all goroutines are parked or if it just
+returns as soon as `HelloWorld` completes.
+
+### Relation with Wasm interface types proposal
+
+The
+[Wasm interface types proposal](https://github.com/WebAssembly/interface-types/blob/master/proposals/interface-types/Explainer.md)
+aims to provide higher level typing in Wasm modules for imports and exports.
+
+Thanks to the _Wasm interface types_, we might be able in future to allow users
+to extend the set of supported types in the imports and exports signatures.
+
+## Compatibility
+
+Like https://golang.org/issue/38248, the `go:wasmexport` directive will not be
+covered by Go's compatibility promise as long as the Wasm architecture itself is
+not considered stable.
+
+## Implementation
+
+The implementation involves:
+
+1. Implement the `go:wasmexport` directive in the compiler and test the proper
+   compilation to a Wasm module including the export
+2. Implement the execution model of `go:wasmexport`
+3. (Optional) Remove the hardcoded exports and convert them to use the
+   `go:wasmexport` directive
+
+The step (1) should look very similar to the work already done for the
+`go:wasmimport` directive, available
+[here](https://go-review.googlesource.com/c/go/+/252828/).
+
+Step (2) will mostly require refactoring the runtime code already available to
+implement [`syscall/js.FuncOf`](https://golang.org/pkg/syscall/js/#FuncOf) (e.g.
+`runtime/rt0_js_wasm.s`), in order to generalize it to any export (and not just
+the built-in ones).
+
+Step (3) might be required or not, depending on the outcome of step (2), in
+order to keep a correct implementation of the Go JS ABI, without changing its
+behaviours.
+
+## Open issues (if applicable)
+
+- Should we allow users to control whether to execute all goroutines up to when
+  they're parked or to return immediately after the exported Go function (e.g.
+  `helloWorld`) completes?