package experimental
import "github.com/tetratelabs/wazero/experimental"
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!
This shows how to make a listener that counts go function calls.
Code:play
Output: Code:play
Output:Example (CustomListenerFactory)¶
package main
import (
"context"
"fmt"
"log"
"sort"
_ "embed"
"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.Strings(ret)
return ret
}
// NewListener implements FunctionListenerFactory.NewListener
func (u uniqGoFuncs) NewListener(def api.FunctionDefinition) experimental.FunctionListener {
if def.GoFunction() == nil {
return nil
}
return u
}
// Before implements FunctionListener.Before
func (u uniqGoFuncs) Before(ctx context.Context, _ api.Module, def api.FunctionDefinition, _ []uint64, _ experimental.StackIterator) context.Context {
u[def.DebugName()] = struct{}{}
return ctx
}
// After implements FunctionListener.After
func (u uniqGoFuncs) After(context.Context, api.Module, api.FunctionDefinition, error, []uint64) {}
func main() {
u := uniqGoFuncs{}
// Set context to one that has an experimental listener
ctx := context.WithValue(context.Background(), experimental.FunctionListenerFactoryKey{}, u)
r := wazero.NewRuntime(ctx)
defer r.Close(ctx) // This closes everything this Runtime created.
wasi_snapshot_preview1.MustInstantiate(ctx, r)
mod, err := r.Instantiate(ctx, listenerWasm)
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)
}
}
wasi_snapshot_preview1.fd_write
wasi_snapshot_preview1.random_get
Example (StackIterator)¶
package main
import (
"fmt"
_ "embed"
"github.com/tetratelabs/wazero/api"
"github.com/tetratelabs/wazero/internal/wasm"
)
func main() {
it := &fakeStackIterator{}
for it.Next() {
fmt.Println("function:", it.FunctionDefinition().DebugName(), "args", it.Args())
}
}
type fakeStackIterator struct {
iteration int
def api.FunctionDefinition
args []uint64
}
func (s *fakeStackIterator) Next() bool {
switch s.iteration {
case 0:
s.def = &mockFunctionDefinition{debugName: "fn0"}
s.args = []uint64{1, 2, 3}
case 1:
s.def = &mockFunctionDefinition{debugName: "fn1"}
s.args = []uint64{}
case 2:
s.def = &mockFunctionDefinition{debugName: "fn2"}
s.args = []uint64{4}
case 3:
return false
}
s.iteration++
return true
}
func (s *fakeStackIterator) FunctionDefinition() api.FunctionDefinition {
return s.def
}
func (s *fakeStackIterator) Args() []uint64 {
return s.args
}
type mockFunctionDefinition struct {
debugName string
*wasm.FunctionDefinition
}
func (f *mockFunctionDefinition) DebugName() string {
return f.debugName
}
func (f *mockFunctionDefinition) ParamTypes() []wasm.ValueType {
return []wasm.ValueType{}
}
func (f *mockFunctionDefinition) ResultTypes() []wasm.ValueType {
return []wasm.ValueType{}
}
function: fn0 args [1 2 3]
function: fn1 args []
function: fn2 args [4]
Index ¶
- type FunctionListener
- type FunctionListenerFactory
- type FunctionListenerFactoryKey
- type InternalModule
- type StackIterator
Examples ¶
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. // - mod: the calling module. // - def: the function definition. // - paramValues: api.ValueType encoded parameters. // - stackIterator: iterator on the call stack. At least one entry is // guaranteed (the called function), whose Args() will be equal to // paramValues. The iterator will be reused between calls to Before. // // Note: api.Memory is meant for inspection, not modification. // mod can be cast to InternalModule to read non-exported globals. Before(ctx context.Context, mod api.Module, def api.FunctionDefinition, paramValues []uint64, stackIterator StackIterator) context.Context // After is invoked after a function is called. // // # Params // // - ctx: the context returned by Before. // - mod: the calling module. // - def: the function definition. // - err: nil if the function didn't err // - resultValues: api.ValueType encoded results. // // Note: api.Memory is meant for inspection, not modification. After(ctx context.Context, mod api.Module, 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.
See https://github.com/tetratelabs/wazero/issues/451
type InternalModule ¶
type InternalModule interface { api.Module // NumGlobal returns the count of all globals in the // module. NumGlobal() int // Global provides a read-only view for a given global // index. Panics if idx > GlobalsCount(). Global(idx int) api.Global }
InternalModule is an api.Module that exposes additional information.
type StackIterator ¶
type StackIterator interface { // Next moves the iterator to the next function in the stack. Returns false // if it reached the bottom of the stack. Next() bool // FunctionDefinition returns the function type of the current function. FunctionDefinition() api.FunctionDefinition // Parameters returns api.ValueType-encoded parameters of the current // function. Do not modify the content of the slice, and copy out any value // you need. Parameters() []uint64 }
StackIterator allows iterating on each function of the call stack, starting from the top. At least one call to Next() is required to start the iteration.
Note: The iterator provides a view of the call stack at the time of iteration. As a result, parameter values may be different than the ones their function was called with.
Source Files ¶
Directories ¶
Path | Synopsis |
---|---|
experimental/gojs | Package gojs allows you to run wasm binaries compiled by Go when `GOARCH=wasm GOOS=js`. |
experimental/gojs/example | |
experimental/logging |
- Version
- v1.1.0
- Published
- May 1, 2023
- Platform
- linux/amd64
- Imports
- 2 packages
- Last checked
- 2 hours ago –
Tools for package owners.