experimental

package
v1.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 1, 2023 License: Apache-2.0 Imports: 2 Imported by: 13

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"
	"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)
	}

}
Output:

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{}
}
Output:

function: fn0 args [1 2 3]
function: fn1 args []
function: fn2 args [4]

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

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 added in v1.1.0

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 added in v1.0.2

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.

Directories

Path Synopsis
Package gojs allows you to run wasm binaries compiled by Go when `GOARCH=wasm GOOS=js`.
Package gojs allows you to run wasm binaries compiled by Go when `GOARCH=wasm GOOS=js`.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL