This simplifies FunctionListener definition by making it possible to implement both interfaces without intermediate state. Passing the function definition to the before/after callbacks is the key. This also continues efforts towards Go 1.19 doc formatting. Signed-off-by: Adrian Cole <adrian@tetrate.io>
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.NewModuleBuilder("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.ModuleBuilder
|
|
// named "env".
|
|
ExportFunctions(builder wazero.ModuleBuilder)
|
|
}
|
|
|
|
// 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.ModuleBuilder) {
|
|
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}},
|
|
}
|