We at one point considered making `ModuleBuilder` create complete WebAssembly binaries. However, we recently spun out [wabin](https://github.com/tetratelabs/wabin), which allows this. Meanwhile, the features in `ModuleBuilder` were confusing and misused. For example, the only two cases memory was exported on GitHub were done by accident. This is because host functions act on the guest's memory, not their own. Hence, this removes memory and globals from host side definitions, and renames the type to HostModuleBuilder to clarify this is not ever going to be used to construct normal Wasm binaries. Most importantly, this simplifies the API and reduces a lot of code. It is important to make changes like this, particularly deleting any experimental things that didn't end up useful. Signed-off-by: Adrian Cole <adrian@tetrate.io> Co-authored-by: Anuraag Agrawal <anuraaga@gmail.com>
82 lines
3.0 KiB
Go
82 lines
3.0 KiB
Go
// Package emscripten contains Go-defined special functions imported by
|
|
// Emscripten under the module name "env".
|
|
//
|
|
// Emscripten has many imports which are triggered on build flags. Use
|
|
// FunctionExporter, instead of Instantiate, to define more "env" functions.
|
|
//
|
|
// # Relationship to WASI
|
|
//
|
|
// Emscripten typically requires wasi_snapshot_preview1 to implement exit.
|
|
//
|
|
// See wasi_snapshot_preview1.Instantiate and
|
|
// https://github.com/emscripten-core/emscripten/wiki/WebAssembly-Standalone
|
|
package emscripten
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/tetratelabs/wazero"
|
|
"github.com/tetratelabs/wazero/api"
|
|
"github.com/tetratelabs/wazero/internal/wasm"
|
|
)
|
|
|
|
// Instantiate instantiates the "env" module used by Emscripten into the
|
|
// runtime default namespace.
|
|
//
|
|
// # Notes
|
|
//
|
|
// - Closing the wazero.Runtime has the same effect as closing the result.
|
|
// - To add more functions to the "env" module, use FunctionExporter.
|
|
// - To instantiate into another wazero.Namespace, use FunctionExporter.
|
|
func Instantiate(ctx context.Context, r wazero.Runtime) (api.Closer, error) {
|
|
builder := r.NewHostModuleBuilder("env")
|
|
NewFunctionExporter().ExportFunctions(builder)
|
|
return builder.Instantiate(ctx, r)
|
|
}
|
|
|
|
// FunctionExporter configures the functions in the "env" module used by
|
|
// Emscripten.
|
|
type FunctionExporter interface {
|
|
// ExportFunctions builds functions to export with a wazero.HostModuleBuilder
|
|
// named "env".
|
|
ExportFunctions(builder wazero.HostModuleBuilder)
|
|
}
|
|
|
|
// NewFunctionExporter returns a FunctionExporter object with trace disabled.
|
|
func NewFunctionExporter() FunctionExporter {
|
|
return &functionExporter{}
|
|
}
|
|
|
|
type functionExporter struct{}
|
|
|
|
// ExportFunctions implements FunctionExporter.ExportFunctions
|
|
func (e *functionExporter) ExportFunctions(builder wazero.HostModuleBuilder) {
|
|
builder.ExportFunction(notifyMemoryGrowth.Name, notifyMemoryGrowth)
|
|
}
|
|
|
|
// emscriptenNotifyMemoryGrowth is called when wasm is compiled with
|
|
// `-s ALLOW_MEMORY_GROWTH` and a "memory.grow" instruction succeeded.
|
|
// The memoryIndex parameter will be zero until "multi-memory" is implemented.
|
|
//
|
|
// Note: This implementation is a no-op and can be overridden by users manually
|
|
// by redefining the same function. wazero will likely implement a generic
|
|
// memory growth hook obviating this as well.
|
|
//
|
|
// Here's the import in a user's module that ends up using this, in WebAssembly
|
|
// 1.0 (MVP) Text Format:
|
|
//
|
|
// (import "env" "emscripten_notify_memory_growth"
|
|
// (func $emscripten_notify_memory_growth (param $memory_index i32)))
|
|
//
|
|
// See https://github.com/emscripten-core/emscripten/blob/3.1.16/system/lib/standalone/standalone.c#L118
|
|
// and https://emscripten.org/docs/api_reference/emscripten.h.html#abi-functions
|
|
const functionNotifyMemoryGrowth = "emscripten_notify_memory_growth"
|
|
|
|
var notifyMemoryGrowth = &wasm.HostFunc{
|
|
ExportNames: []string{functionNotifyMemoryGrowth},
|
|
Name: functionNotifyMemoryGrowth,
|
|
ParamTypes: []wasm.ValueType{wasm.ValueTypeI32},
|
|
ParamNames: []string{"memory_index"},
|
|
Code: &wasm.Code{IsHostFunction: true, Body: []byte{wasm.OpcodeEnd}},
|
|
}
|