Documentation ¶
Overview ¶
Package experimental includes features we aren't yet sure about. These are enabled with context.Context keys.
Note: All features here may be changed or deleted at any time, so use with caution!
Example (CustomListenerFactory) ¶
This shows how to make a listener that counts go function calls.
package main import ( "context" _ "embed" "fmt" "log" "sort" "github.com/tetratelabs/wazero" "github.com/tetratelabs/wazero/api" . "github.com/tetratelabs/wazero/experimental" "github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1" ) // listenerWasm was generated by the following: // // cd testdata; wat2wasm --debug-names listener.wat // //go:embed logging/testdata/listener.wasm var listenerWasm []byte // uniqGoFuncs implements both FunctionListenerFactory and FunctionListener type uniqGoFuncs map[string]struct{} // callees returns the go functions called. func (u uniqGoFuncs) callees() []string { ret := make([]string, 0, len(u)) for k := range u { ret = append(ret, k) } // Sort names for consistent iteration sort.Strings(ret) return ret } // NewListener implements FunctionListenerFactory.NewListener func (u uniqGoFuncs) NewListener(def api.FunctionDefinition) FunctionListener { if def.GoFunc() == nil { return nil // only track go funcs } return u } // Before implements FunctionListener.Before func (u uniqGoFuncs) Before(ctx context.Context, def api.FunctionDefinition, _ []uint64) context.Context { u[def.DebugName()] = struct{}{} return ctx } // After implements FunctionListener.After func (u uniqGoFuncs) After(context.Context, api.FunctionDefinition, error, []uint64) {} // This shows how to make a listener that counts go function calls. func main() { u := uniqGoFuncs{} // Set context to one that has an experimental listener ctx := context.WithValue(context.Background(), FunctionListenerFactoryKey{}, u) r := wazero.NewRuntimeWithConfig(ctx, wazero.NewRuntimeConfigInterpreter()) defer r.Close(ctx) // This closes everything this Runtime created. if _, err := wasi_snapshot_preview1.Instantiate(ctx, r); err != nil { log.Panicln(err) } // Compile the WebAssembly module using the default configuration. code, err := r.CompileModule(ctx, listenerWasm, wazero.NewCompileConfig()) if err != nil { log.Panicln(err) } mod, err := r.InstantiateModule(ctx, code, wazero.NewModuleConfig()) if err != nil { log.Panicln(err) } for i := 0; i < 5; i++ { if _, err = mod.ExportedFunction("rand").Call(ctx, 4); err != nil { log.Panicln(err) } } // A Go function was called multiple times, but we should only see it once. for _, f := range u.callees() { fmt.Println(f) } }
Output: wasi_snapshot_preview1.random_get
Example (WithCompilationCacheDirName) ¶
This is a basic example of using the file system compilation cache via WithCompilationCacheDirName. The main goal is to show how it is configured.
package main import ( "context" "log" "os" "github.com/tetratelabs/wazero" "github.com/tetratelabs/wazero/experimental" ) // This is a basic example of using the file system compilation cache via WithCompilationCacheDirName. // The main goal is to show how it is configured. func main() { // Prepare a cache directory. cacheDir, err := os.MkdirTemp("", "example") if err != nil { log.Panicln(err) } defer os.RemoveAll(cacheDir) // Append the directory into the context for configuration. ctx, err := experimental.WithCompilationCacheDirName(context.Background(), cacheDir) if err != nil { log.Panicln(err) } // Repeat newRuntimeCompileClose with the same cache directory. newRuntimeCompileClose(ctx) // Since the above stored compiled functions to dist, below won't compile. // Instead, code stored in the file cache is re-used. newRuntimeCompileClose(ctx) newRuntimeCompileClose(ctx) } // newRuntimeCompileDestroy creates a new wazero.Runtime, compile a binary, and then delete the runtime. func newRuntimeCompileClose(ctx context.Context) { r := wazero.NewRuntime(ctx) defer r.Close(ctx) // This closes everything this Runtime created except the file system cache. _, err := r.CompileModule(ctx, fsWasm, wazero.NewCompileConfig()) if err != nil { log.Panicln(err) } }
Output:
Example (WithFS) ¶
This is a basic example of overriding the file system via WithFS. The main goal is to show how it is configured.
package main import ( "context" _ "embed" "fmt" "log" "os" "github.com/tetratelabs/wazero" "github.com/tetratelabs/wazero/experimental" "github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1" ) // fsWasm was generated by the following: // // cd testdata; wat2wasm --debug-names fs.wat // //go:embed testdata/fs.wasm var fsWasm []byte // This is a basic example of overriding the file system via WithFS. The main // goal is to show how it is configured. func main() { ctx := context.Background() r := wazero.NewRuntime(ctx) defer r.Close(ctx) // This closes everything this Runtime created. if _, err := wasi_snapshot_preview1.Instantiate(ctx, r); err != nil { log.Panicln(err) } // Instantiate a module exporting a WASI function that uses the filesystem. mod, err := r.InstantiateModuleFromBinary(ctx, fsWasm) if err != nil { log.Panicln(err) } // Setup the filesystem overlay, noting that it can fail if the directory is // invalid and must be closed. ctx, closer := experimental.WithFS(ctx, os.DirFS(".")) defer closer.Close(ctx) fdPrestatDirName := mod.ExportedFunction("fd_prestat_dir_name") fd := 3 // after stderr pathLen := 1 // length we expect the path to be. pathOffset := 0 // where to write pathLen bytes. // By default, there are no pre-opened directories. If the configuration // was wrong, this call would fail. results, err := fdPrestatDirName.Call(ctx, uint64(fd), uint64(pathOffset), uint64(pathLen)) if err != nil { log.Panicln(err) } if results[0] != 0 { log.Panicf("received errno %d\n", results[0]) } // Try to read the path! if path, ok := mod.Memory().Read(ctx, uint32(pathOffset), uint32(pathLen)); !ok { log.Panicln("out of memory reading path") } else { fmt.Println(string(path)) } }
Output: /
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func WithCompilationCacheDirName ¶
WithCompilationCacheDirName configures the destination directory of the compilation cache. Regardless of the usage of this, the compiled functions are cached in memory, but its lifetime is bound to the lifetime of wazero.Runtime or wazero.CompiledModule.
If the dirname doesn't exist, this creates the directory.
With the given non-empty directory, wazero persists the cache into the directory and that cache will be used as long as the running wazero version match the version of compilation wazero.
A cache is only valid for use in one wazero.Runtime at a time. Concurrent use of a wazero.Runtime is supported, but multiple runtimes must not share the same directory.
Note: The embedder must safeguard this directory from external changes.
Usage:
ctx, _ := experimental.WithCompilationCacheDirName(context.Background(), "/home/me/.cache/wazero") r := wazero.NewRuntimeWithConfig(ctx, wazero.NewRuntimeConfigCompiler())
Types ¶
type FunctionListener ¶
type FunctionListener interface { // Before is invoked before a function is called. The returned context will // be used as the context of this function call. // // # Params // // - ctx: the context of the caller function which must be the same // instance or parent of the result. // - def: the function definition. // - paramValues: api.ValueType encoded parameters. Before(ctx context.Context, def api.FunctionDefinition, paramValues []uint64) context.Context // After is invoked after a function is called. // // # Params // // - ctx: the context returned by Before. // - def: the function definition. // - err: nil if the function didn't err // - resultValues: api.ValueType encoded results. After(ctx context.Context, def api.FunctionDefinition, err error, resultValues []uint64) }
FunctionListener can be registered for any function via FunctionListenerFactory to be notified when the function is called.
type FunctionListenerFactory ¶
type FunctionListenerFactory interface { // NewListener returns a FunctionListener for a defined function. If nil is // returned, no listener will be notified. NewListener(api.FunctionDefinition) FunctionListener }
FunctionListenerFactory returns FunctionListeners to be notified when a function is called.
type FunctionListenerFactoryKey ¶
type FunctionListenerFactoryKey struct{}
FunctionListenerFactoryKey is a context.Context Value key. Its associated value should be a FunctionListenerFactory.
Note: This is interpreter-only for now!