Makes it possible to implement FunctionListener and Factory (#716)
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>
This commit is contained in:
10
api/wasm.go
10
api/wasm.go
@@ -125,7 +125,7 @@ func ValueTypeName(t ValueType) string {
|
||||
|
||||
// Module return functions exported in a module, post-instantiation.
|
||||
//
|
||||
// Notes
|
||||
// # Notes
|
||||
//
|
||||
// - Closing the wazero.Runtime closes any Module it instantiated.
|
||||
// - This is an interface for decoupling, not third-party implementations. All implementations are in wazero.
|
||||
@@ -316,7 +316,7 @@ type MutableGlobal interface {
|
||||
|
||||
// Memory allows restricted access to a module's memory. Notably, this does not allow growing.
|
||||
//
|
||||
// Notes
|
||||
// # Notes
|
||||
//
|
||||
// - All functions accept a context.Context, which when nil, default to context.Background.
|
||||
// - This is an interface for decoupling, not third-party implementations. All implementations are in wazero.
|
||||
@@ -334,11 +334,11 @@ type Memory interface {
|
||||
// The return val is the previous memory size in pages, or false if the
|
||||
// delta was ignored as it exceeds max memory.
|
||||
//
|
||||
// Notes
|
||||
// # Notes
|
||||
//
|
||||
// * This is the same as the "memory.grow" instruction defined in the
|
||||
// - This is the same as the "memory.grow" instruction defined in the
|
||||
// WebAssembly Core Specification, except returns false instead of -1.
|
||||
// * When this returns true, any shared views via Read must be refreshed.
|
||||
// - When this returns true, any shared views via Read must be refreshed.
|
||||
//
|
||||
// See MemorySizer Read and https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#grow-mem
|
||||
Grow(ctx context.Context, deltaPages uint32) (previousPages uint32, ok bool)
|
||||
|
||||
@@ -47,7 +47,7 @@ const (
|
||||
// Instantiate instantiates the "env" module used by AssemblyScript into the
|
||||
// runtime default namespace.
|
||||
//
|
||||
// Notes
|
||||
// # Notes
|
||||
//
|
||||
// - Closing the wazero.Runtime has the same effect as closing the result.
|
||||
// - To add more functions to the "env" module, use FunctionExporter.
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
"github.com/tetratelabs/wazero"
|
||||
"github.com/tetratelabs/wazero/api"
|
||||
. "github.com/tetratelabs/wazero/experimental"
|
||||
"github.com/tetratelabs/wazero/experimental/logging"
|
||||
"github.com/tetratelabs/wazero/internal/testing/require"
|
||||
"github.com/tetratelabs/wazero/internal/u64"
|
||||
"github.com/tetratelabs/wazero/internal/wasm"
|
||||
@@ -398,7 +399,7 @@ func requireModule(t *testing.T, fns FunctionExporter, config wazero.ModuleConfi
|
||||
var log bytes.Buffer
|
||||
|
||||
// Set context to one that has an experimental listener
|
||||
ctx := context.WithValue(testCtx, FunctionListenerFactoryKey{}, NewLoggingListenerFactory(&log))
|
||||
ctx := context.WithValue(testCtx, FunctionListenerFactoryKey{}, logging.NewLoggingListenerFactory(&log))
|
||||
|
||||
r := wazero.NewRuntimeWithConfig(wazero.NewRuntimeConfigInterpreter())
|
||||
|
||||
|
||||
30
builder.go
30
builder.go
@@ -36,7 +36,7 @@ import (
|
||||
//
|
||||
// env2, _ := r.InstantiateModule(ctx, compiled, wazero.NewModuleConfig().WithName("env.2"))
|
||||
//
|
||||
// Notes
|
||||
// # Notes
|
||||
//
|
||||
// - ModuleBuilder is mutable: each method returns the same instance for
|
||||
// chaining.
|
||||
@@ -50,11 +50,11 @@ type ModuleBuilder interface {
|
||||
// ExportFunction adds a function written in Go, which a WebAssembly module can import.
|
||||
// If a function is already exported with the same name, this overwrites it.
|
||||
//
|
||||
// Parameters
|
||||
// # Parameters
|
||||
//
|
||||
// * exportName - The name to export. Ex "random_get"
|
||||
// * goFunc - The `func` to export.
|
||||
// * names - If present, the first is the api.FunctionDefinition name.
|
||||
// - exportName - The name to export. Ex "random_get"
|
||||
// - goFunc - The `func` to export.
|
||||
// - names - If present, the first is the api.FunctionDefinition name.
|
||||
// If any follow, they must match the count of goFunc's parameters.
|
||||
//
|
||||
// Ex.
|
||||
@@ -116,19 +116,19 @@ type ModuleBuilder interface {
|
||||
// ExportMemory adds linear memory, which a WebAssembly module can import and become available via api.Memory.
|
||||
// If a memory is already exported with the same name, this overwrites it.
|
||||
//
|
||||
// Parameters
|
||||
// # Parameters
|
||||
//
|
||||
// * name - the name to export. Ex "memory" for wasi_snapshot_preview1.ModuleSnapshotPreview1
|
||||
// * minPages - the possibly zero initial size in pages (65536 bytes per page).
|
||||
// - name - the name to export. Ex "memory" for wasi_snapshot_preview1.ModuleSnapshotPreview1
|
||||
// - minPages - the possibly zero initial size in pages (65536 bytes per page).
|
||||
//
|
||||
// For example, the WebAssembly 1.0 Text Format below is the equivalent of this builder method:
|
||||
// // (memory (export "memory") 1)
|
||||
// builder.ExportMemory(1)
|
||||
//
|
||||
// Notes
|
||||
// # Notes
|
||||
//
|
||||
// * This is allowed to grow to (4GiB) limited by api.MemorySizer. To bound it, use ExportMemoryWithMax.
|
||||
// * Version 1.0 (20191205) of the WebAssembly spec allows at most one memory per module.
|
||||
// - This is allowed to grow to (4GiB) limited by api.MemorySizer. To bound it, use ExportMemoryWithMax.
|
||||
// - Version 1.0 (20191205) of the WebAssembly spec allows at most one memory per module.
|
||||
//
|
||||
// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#memory-section%E2%91%A0
|
||||
ExportMemory(name string, minPages uint32) ModuleBuilder
|
||||
@@ -208,11 +208,11 @@ type ModuleBuilder interface {
|
||||
// ExportFunction("hello", hello).
|
||||
// Instantiate(ctx, r)
|
||||
//
|
||||
// Notes
|
||||
// # Notes
|
||||
//
|
||||
// * Closing the Namespace has the same effect as closing the result.
|
||||
// * Fields in the builder are copied during instantiation: Later changes do not affect the instantiated result.
|
||||
// * To avoid using configuration defaults, use Compile instead.
|
||||
// - Closing the Namespace has the same effect as closing the result.
|
||||
// - Fields in the builder are copied during instantiation: Later changes do not affect the instantiated result.
|
||||
// - To avoid using configuration defaults, use Compile instead.
|
||||
Instantiate(context.Context, Namespace) (api.Module, error)
|
||||
}
|
||||
|
||||
|
||||
82
config.go
82
config.go
@@ -31,10 +31,10 @@ type RuntimeConfig interface {
|
||||
// ("bulk-memory-operations"). This defaults to false as the feature was not finished in WebAssembly 1.0.
|
||||
//
|
||||
// Here are the notable effects:
|
||||
// * Adds `memory.fill`, `memory.init`, `memory.copy` and `data.drop` instructions.
|
||||
// * Adds `table.init`, `table.copy` and `elem.drop` instructions.
|
||||
// * Introduces a "passive" form of element and data segments.
|
||||
// * Stops checking "active" element and data segment boundaries at compile-time, meaning they can error at runtime.
|
||||
// - Adds `memory.fill`, `memory.init`, `memory.copy` and `data.drop` instructions.
|
||||
// - Adds `table.init`, `table.copy` and `elem.drop` instructions.
|
||||
// - Introduces a "passive" form of element and data segments.
|
||||
// - Stops checking "active" element and data segment boundaries at compile-time, meaning they can error at runtime.
|
||||
//
|
||||
// Note: "bulk-memory-operations" is mixed with the "reference-types" proposal
|
||||
// due to the WebAssembly Working Group merging them "mutually dependent".
|
||||
@@ -49,8 +49,8 @@ type RuntimeConfig interface {
|
||||
// finished in WebAssembly 1.0 (20191205).
|
||||
//
|
||||
// Here are the notable effects:
|
||||
// * Function (`func`) types allow more than one result
|
||||
// * Block types (`block`, `loop` and `if`) can be arbitrary function types
|
||||
// - Function (`func`) types allow more than one result
|
||||
// - Block types (`block`, `loop` and `if`) can be arbitrary function types
|
||||
//
|
||||
// See https://github.com/WebAssembly/spec/blob/main/proposals/multi-value/Overview.md
|
||||
WithFeatureMultiValue(bool) RuntimeConfig
|
||||
@@ -66,22 +66,22 @@ type RuntimeConfig interface {
|
||||
// ("nontrapping-float-to-int-conversion"). This defaults to false as the feature was not in WebAssembly 1.0.
|
||||
//
|
||||
// The only effect of enabling is allowing the following instructions, which return 0 on NaN instead of panicking.
|
||||
// * `i32.trunc_sat_f32_s`
|
||||
// * `i32.trunc_sat_f32_u`
|
||||
// * `i32.trunc_sat_f64_s`
|
||||
// * `i32.trunc_sat_f64_u`
|
||||
// * `i64.trunc_sat_f32_s`
|
||||
// * `i64.trunc_sat_f32_u`
|
||||
// * `i64.trunc_sat_f64_s`
|
||||
// * `i64.trunc_sat_f64_u`
|
||||
// - `i32.trunc_sat_f32_s`
|
||||
// - `i32.trunc_sat_f32_u`
|
||||
// - `i32.trunc_sat_f64_s`
|
||||
// - `i32.trunc_sat_f64_u`
|
||||
// - `i64.trunc_sat_f32_s`
|
||||
// - `i64.trunc_sat_f32_u`
|
||||
// - `i64.trunc_sat_f64_s`
|
||||
// - `i64.trunc_sat_f64_u`
|
||||
//
|
||||
// See https://github.com/WebAssembly/spec/blob/main/proposals/nontrapping-float-to-int-conversion/Overview.md
|
||||
WithFeatureNonTrappingFloatToIntConversion(bool) RuntimeConfig
|
||||
|
||||
// WithFeatureReferenceTypes enables various instructions and features related to table and new reference types.
|
||||
//
|
||||
// * Introduction of new value types: `funcref` and `externref`.
|
||||
// * Support for the following new instructions:
|
||||
// - Introduction of new value types: `funcref` and `externref`.
|
||||
// - Support for the following new instructions:
|
||||
// * `ref.null`
|
||||
// * `ref.func`
|
||||
// * `ref.is_null`
|
||||
@@ -90,7 +90,7 @@ type RuntimeConfig interface {
|
||||
// * `table.grow`
|
||||
// * `table.set`
|
||||
// * `table.size`
|
||||
// * Support for multiple tables per module:
|
||||
// - Support for multiple tables per module:
|
||||
// * `call_indirect`, `table.init`, `table.copy` and `elem.drop` instructions can take non-zero table index.
|
||||
// * Element segments can take non-zero table index.
|
||||
//
|
||||
@@ -107,7 +107,7 @@ type RuntimeConfig interface {
|
||||
// as the feature was not in WebAssembly 1.0.
|
||||
//
|
||||
// Here are the notable effects:
|
||||
// * Adds instructions `i32.extend8_s`, `i32.extend16_s`, `i64.extend8_s`, `i64.extend16_s` and `i64.extend32_s`
|
||||
// - Adds instructions `i32.extend8_s`, `i32.extend16_s`, `i64.extend8_s`, `i64.extend16_s` and `i64.extend32_s`
|
||||
//
|
||||
// See https://github.com/WebAssembly/spec/blob/main/proposals/sign-extension-ops/Overview.md
|
||||
WithFeatureSignExtensionOps(bool) RuntimeConfig
|
||||
@@ -451,11 +451,11 @@ type ModuleConfig interface {
|
||||
// WithStartFunctions configures the functions to call after the module is
|
||||
// instantiated. Defaults to "_start".
|
||||
//
|
||||
// Notes
|
||||
// # Notes
|
||||
//
|
||||
// * If any function doesn't exist, it is skipped. However, all functions
|
||||
// - If any function doesn't exist, it is skipped. However, all functions
|
||||
// that do exist are called in order.
|
||||
// * Some start functions may exit the module during instantiate with a
|
||||
// - Some start functions may exit the module during instantiate with a
|
||||
// sys.ExitError (ex. emscripten), preventing use of exported functions.
|
||||
WithStartFunctions(...string) ModuleConfig
|
||||
|
||||
@@ -464,10 +464,10 @@ type ModuleConfig interface {
|
||||
// This writer is most commonly used by the functions like "fd_write" in "wasi_snapshot_preview1" although it could
|
||||
// be used by functions imported from other modules.
|
||||
//
|
||||
// Notes
|
||||
// # Notes
|
||||
//
|
||||
// * The caller is responsible to close any io.Writer they supply: It is not closed on api.Module Close.
|
||||
// * This does not default to os.Stderr as that both violates sandboxing and prevents concurrent modules.
|
||||
// - The caller is responsible to close any io.Writer they supply: It is not closed on api.Module Close.
|
||||
// - This does not default to os.Stderr as that both violates sandboxing and prevents concurrent modules.
|
||||
//
|
||||
// See https://linux.die.net/man/3/stderr
|
||||
WithStderr(io.Writer) ModuleConfig
|
||||
@@ -477,10 +477,10 @@ type ModuleConfig interface {
|
||||
// This reader is most commonly used by the functions like "fd_read" in "wasi_snapshot_preview1" although it could
|
||||
// be used by functions imported from other modules.
|
||||
//
|
||||
// Notes
|
||||
// # Notes
|
||||
//
|
||||
// * The caller is responsible to close any io.Reader they supply: It is not closed on api.Module Close.
|
||||
// * This does not default to os.Stdin as that both violates sandboxing and prevents concurrent modules.
|
||||
// - The caller is responsible to close any io.Reader they supply: It is not closed on api.Module Close.
|
||||
// - This does not default to os.Stdin as that both violates sandboxing and prevents concurrent modules.
|
||||
//
|
||||
// See https://linux.die.net/man/3/stdin
|
||||
WithStdin(io.Reader) ModuleConfig
|
||||
@@ -490,10 +490,10 @@ type ModuleConfig interface {
|
||||
// This writer is most commonly used by the functions like "fd_write" in "wasi_snapshot_preview1" although it could
|
||||
// be used by functions imported from other modules.
|
||||
//
|
||||
// Notes
|
||||
// # Notes
|
||||
//
|
||||
// * The caller is responsible to close any io.Writer they supply: It is not closed on api.Module Close.
|
||||
// * This does not default to os.Stdout as that both violates sandboxing and prevents concurrent modules.
|
||||
// - The caller is responsible to close any io.Writer they supply: It is not closed on api.Module Close.
|
||||
// - This does not default to os.Stdout as that both violates sandboxing and prevents concurrent modules.
|
||||
//
|
||||
// See https://linux.die.net/man/3/stdout
|
||||
WithStdout(io.Writer) ModuleConfig
|
||||
@@ -528,11 +528,11 @@ type ModuleConfig interface {
|
||||
// return clock.nanotime()
|
||||
// }, sys.ClockResolution(time.Microsecond.Nanoseconds()))
|
||||
//
|
||||
// Notes:
|
||||
// * This does not default to time.Since as that violates sandboxing.
|
||||
// * Some compilers implement sleep by looping on sys.Nanotime (ex. Go).
|
||||
// * If you set this, you should probably set WithNanosleep also.
|
||||
// * Use WithSysNanotime for a usable implementation.
|
||||
// # Notes:
|
||||
// - This does not default to time.Since as that violates sandboxing.
|
||||
// - Some compilers implement sleep by looping on sys.Nanotime (ex. Go).
|
||||
// - If you set this, you should probably set WithNanosleep also.
|
||||
// - Use WithSysNanotime for a usable implementation.
|
||||
WithNanotime(sys.Nanotime, sys.ClockResolution) ModuleConfig
|
||||
|
||||
// WithSysNanotime uses time.Now for sys.Nanotime with a resolution of 1us.
|
||||
@@ -552,12 +552,12 @@ type ModuleConfig interface {
|
||||
// err := unix.ClockNanosleep(unix.CLOCK_MONOTONIC, 0, &rel, &remain)
|
||||
// --snip--
|
||||
//
|
||||
// Notes:
|
||||
// * This primarily supports `poll_oneoff` for relative clock events.
|
||||
// * This does not default to time.Sleep as that violates sandboxing.
|
||||
// * Some compilers implement sleep by looping on sys.Nanotime (ex. Go).
|
||||
// * If you set this, you should probably set WithNanotime also.
|
||||
// * Use WithSysNanosleep for a usable implementation.
|
||||
// # Notes:
|
||||
// - This primarily supports `poll_oneoff` for relative clock events.
|
||||
// - This does not default to time.Sleep as that violates sandboxing.
|
||||
// - Some compilers implement sleep by looping on sys.Nanotime (ex. Go).
|
||||
// - If you set this, you should probably set WithNanotime also.
|
||||
// - Use WithSysNanosleep for a usable implementation.
|
||||
WithNanosleep(sys.Nanosleep) ModuleConfig
|
||||
|
||||
// WithSysNanosleep uses time.Sleep for sys.Nanosleep.
|
||||
|
||||
@@ -23,7 +23,7 @@ import (
|
||||
// Instantiate instantiates the "env" module used by Emscripten into the
|
||||
// runtime default namespace.
|
||||
//
|
||||
// Notes
|
||||
// # Notes
|
||||
//
|
||||
// - Closing the wazero.Runtime has the same effect as closing the result.
|
||||
// - To add more functions to the "env" module, use FunctionExporter.
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
|
||||
"github.com/tetratelabs/wazero"
|
||||
. "github.com/tetratelabs/wazero/experimental"
|
||||
"github.com/tetratelabs/wazero/experimental/logging"
|
||||
"github.com/tetratelabs/wazero/internal/testing/require"
|
||||
"github.com/tetratelabs/wazero/sys"
|
||||
"github.com/tetratelabs/wazero/wasi_snapshot_preview1"
|
||||
@@ -26,7 +27,7 @@ func TestGrow(t *testing.T) {
|
||||
var log bytes.Buffer
|
||||
|
||||
// Set context to one that has an experimental listener
|
||||
ctx := context.WithValue(testCtx, FunctionListenerFactoryKey{}, NewLoggingListenerFactory(&log))
|
||||
ctx := context.WithValue(testCtx, FunctionListenerFactoryKey{}, logging.NewLoggingListenerFactory(&log))
|
||||
|
||||
r := wazero.NewRuntimeWithConfig(wazero.NewRuntimeConfigInterpreter())
|
||||
defer r.Close(ctx)
|
||||
|
||||
@@ -27,21 +27,23 @@ 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
|
||||
// # Params
|
||||
//
|
||||
// * ctx - the context of the caller function which must be the same
|
||||
// - ctx: the context of the caller function which must be the same
|
||||
// instance or parent of the result.
|
||||
// * paramValues - api.ValueType encoded parameters.
|
||||
Before(ctx context.Context, paramValues []uint64) context.Context
|
||||
// - 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
|
||||
// # Params
|
||||
//
|
||||
// * ctx - the context returned by Before.
|
||||
// * err - nil if the function didn't err
|
||||
// * resultValues - api.ValueType encoded results.
|
||||
After(ctx context.Context, err error, resultValues []uint64)
|
||||
// - 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)
|
||||
}
|
||||
|
||||
// TODO: We need to add tests to enginetest to ensure contexts nest. A good test can use a combination of call and call
|
||||
|
||||
92
experimental/listener_example_test.go
Normal file
92
experimental/listener_example_test.go
Normal file
@@ -0,0 +1,92 @@
|
||||
package experimental_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
_ "embed"
|
||||
"fmt"
|
||||
"log"
|
||||
"sort"
|
||||
|
||||
"github.com/tetratelabs/wazero"
|
||||
"github.com/tetratelabs/wazero/api"
|
||||
. "github.com/tetratelabs/wazero/experimental"
|
||||
"github.com/tetratelabs/wazero/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 Example_customListenerFactory() {
|
||||
u := uniqGoFuncs{}
|
||||
|
||||
// Set context to one that has an experimental listener
|
||||
ctx := context.WithValue(context.Background(), FunctionListenerFactoryKey{}, u)
|
||||
|
||||
r := wazero.NewRuntimeWithConfig(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
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package experimental
|
||||
package logging
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -8,12 +8,13 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/tetratelabs/wazero/api"
|
||||
"github.com/tetratelabs/wazero/experimental"
|
||||
"github.com/tetratelabs/wazero/internal/wasi_snapshot_preview1"
|
||||
)
|
||||
|
||||
// NewLoggingListenerFactory implements FunctionListenerFactory to log all
|
||||
// functions that have a name to the writer.
|
||||
func NewLoggingListenerFactory(writer io.Writer) FunctionListenerFactory {
|
||||
func NewLoggingListenerFactory(writer io.Writer) experimental.FunctionListenerFactory {
|
||||
return &loggingListenerFactory{writer}
|
||||
}
|
||||
|
||||
@@ -21,7 +22,7 @@ type loggingListenerFactory struct{ writer io.Writer }
|
||||
|
||||
// NewListener implements the same method as documented on
|
||||
// experimental.FunctionListener.
|
||||
func (f *loggingListenerFactory) NewListener(fnd api.FunctionDefinition) FunctionListener {
|
||||
func (f *loggingListenerFactory) NewListener(fnd api.FunctionDefinition) experimental.FunctionListener {
|
||||
return &loggingListener{writer: f.writer, fnd: fnd, isWasi: fnd.ModuleName() == "wasi_snapshot_preview1"}
|
||||
}
|
||||
|
||||
@@ -39,7 +40,7 @@ type loggingListener struct {
|
||||
|
||||
// Before logs to stdout the module and function name, prefixed with '-->' and
|
||||
// indented based on the call nesting level.
|
||||
func (l *loggingListener) Before(ctx context.Context, vals []uint64) context.Context {
|
||||
func (l *loggingListener) Before(ctx context.Context, _ api.FunctionDefinition, vals []uint64) context.Context {
|
||||
nestLevel, _ := ctx.Value(nestLevelKey{}).(int)
|
||||
|
||||
l.writeIndented(true, nil, vals, nestLevel+1)
|
||||
@@ -50,7 +51,7 @@ func (l *loggingListener) Before(ctx context.Context, vals []uint64) context.Con
|
||||
|
||||
// After logs to stdout the module and function name, prefixed with '<--' and
|
||||
// indented based on the call nesting level.
|
||||
func (l *loggingListener) After(ctx context.Context, err error, vals []uint64) {
|
||||
func (l *loggingListener) After(ctx context.Context, _ api.FunctionDefinition, err error, vals []uint64) {
|
||||
// Note: We use the nest level directly even though it is the "next" nesting level.
|
||||
// This works because our indent of zero nesting is one tab.
|
||||
l.writeIndented(false, err, vals, ctx.Value(nestLevelKey{}).(int))
|
||||
@@ -1,4 +1,4 @@
|
||||
package experimental_test
|
||||
package logging_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -7,7 +7,8 @@ import (
|
||||
"os"
|
||||
|
||||
"github.com/tetratelabs/wazero"
|
||||
. "github.com/tetratelabs/wazero/experimental"
|
||||
"github.com/tetratelabs/wazero/experimental"
|
||||
"github.com/tetratelabs/wazero/experimental/logging"
|
||||
"github.com/tetratelabs/wazero/wasi_snapshot_preview1"
|
||||
)
|
||||
|
||||
@@ -21,7 +22,7 @@ var listenerWasm []byte
|
||||
// This is a very basic integration of listener. The main goal is to show how it is configured.
|
||||
func Example_newLoggingListenerFactory() {
|
||||
// Set context to one that has an experimental listener
|
||||
ctx := context.WithValue(context.Background(), FunctionListenerFactoryKey{}, NewLoggingListenerFactory(os.Stdout))
|
||||
ctx := context.WithValue(context.Background(), experimental.FunctionListenerFactoryKey{}, logging.NewLoggingListenerFactory(os.Stdout))
|
||||
|
||||
r := wazero.NewRuntimeWithConfig(wazero.NewRuntimeConfigInterpreter())
|
||||
defer r.Close(ctx) // This closes everything this Runtime created.
|
||||
@@ -1,18 +1,22 @@
|
||||
package experimental_test
|
||||
package logging_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"io"
|
||||
"math"
|
||||
"testing"
|
||||
|
||||
"github.com/tetratelabs/wazero/api"
|
||||
"github.com/tetratelabs/wazero/experimental"
|
||||
"github.com/tetratelabs/wazero/experimental/logging"
|
||||
"github.com/tetratelabs/wazero/internal/testing/require"
|
||||
"github.com/tetratelabs/wazero/internal/wasm"
|
||||
"github.com/tetratelabs/wazero/wasi_snapshot_preview1"
|
||||
)
|
||||
|
||||
// testCtx is an arbitrary, non-default context. Non-nil also prevents linter errors.
|
||||
var testCtx = context.WithValue(context.Background(), struct{}{}, "arbitrary")
|
||||
|
||||
func Test_loggingListener(t *testing.T) {
|
||||
wasiFuncName := "random_get"
|
||||
wasiFuncType := &wasm.FunctionType{
|
||||
@@ -261,7 +265,7 @@ func Test_loggingListener(t *testing.T) {
|
||||
}
|
||||
|
||||
var out bytes.Buffer
|
||||
lf := experimental.NewLoggingListenerFactory(&out)
|
||||
lf := logging.NewLoggingListenerFactory(&out)
|
||||
fn := func() {}
|
||||
for _, tt := range tests {
|
||||
tc := tt
|
||||
@@ -288,11 +292,12 @@ func Test_loggingListener(t *testing.T) {
|
||||
m.CodeSection = []*wasm.Code{{Body: []byte{wasm.OpcodeEnd}}}
|
||||
}
|
||||
m.BuildFunctionDefinitions()
|
||||
def := m.FunctionDefinitionSection[0]
|
||||
l := lf.NewListener(m.FunctionDefinitionSection[0])
|
||||
|
||||
out.Reset()
|
||||
ctx := l.Before(testCtx, tc.params)
|
||||
l.After(ctx, tc.err, tc.results)
|
||||
ctx := l.Before(testCtx, def, tc.params)
|
||||
l.After(ctx, def, tc.err, tc.results)
|
||||
require.Equal(t, tc.expected, out.String())
|
||||
})
|
||||
}
|
||||
@@ -311,7 +316,7 @@ func toNameMap(names []string) wasm.NameMap {
|
||||
|
||||
func Test_loggingListener_indentation(t *testing.T) {
|
||||
out := bytes.NewBuffer(nil)
|
||||
lf := experimental.NewLoggingListenerFactory(out)
|
||||
lf := logging.NewLoggingListenerFactory(out)
|
||||
m := &wasm.Module{
|
||||
TypeSection: []*wasm.FunctionType{{}},
|
||||
FunctionSection: []wasm.Index{0, 0},
|
||||
@@ -322,13 +327,15 @@ func Test_loggingListener_indentation(t *testing.T) {
|
||||
},
|
||||
}
|
||||
m.BuildFunctionDefinitions()
|
||||
l1 := lf.NewListener(m.FunctionDefinitionSection[0])
|
||||
l2 := lf.NewListener(m.FunctionDefinitionSection[1])
|
||||
def1 := m.FunctionDefinitionSection[0]
|
||||
l1 := lf.NewListener(def1)
|
||||
def2 := m.FunctionDefinitionSection[1]
|
||||
l2 := lf.NewListener(def2)
|
||||
|
||||
ctx := l1.Before(testCtx, []uint64{})
|
||||
ctx1 := l2.Before(ctx, []uint64{})
|
||||
l2.After(ctx1, nil, []uint64{})
|
||||
l1.After(ctx, nil, []uint64{})
|
||||
ctx := l1.Before(testCtx, def1, []uint64{})
|
||||
ctx1 := l2.Before(ctx, def2, []uint64{})
|
||||
l2.After(ctx1, def2, nil, []uint64{})
|
||||
l1.After(ctx, def1, nil, []uint64{})
|
||||
require.Equal(t, `--> test.fn1()
|
||||
--> test.fn2()
|
||||
<-- ()
|
||||
@@ -692,9 +692,9 @@ const (
|
||||
// VCNT is the CNT instruction. https://developer.arm.com/documentation/dui0802/a/A64-Advanced-SIMD-Vector-Instructions/CNT--vector-
|
||||
VCNT
|
||||
// VMOV has different semantics depending on the types of operands:
|
||||
// * LDR(SIMD&FP) if the src is memory and dst is a vector: https://developer.arm.com/documentation/ddi0596/2020-12/SIMD-FP-Instructions/LDR--immediate--SIMD-FP---Load-SIMD-FP-Register--immediate-offset--
|
||||
// * LDR(literal, SIMD&FP) if the src is static const and dst is a vector: https://developer.arm.com/documentation/dui0801/h/A64-Floating-point-Instructions/LDR--literal--SIMD-and-FP-
|
||||
// * STR(SIMD&FP) if the dst is memory and src is a vector: https://developer.arm.com/documentation/ddi0596/2020-12/SIMD-FP-Instructions/STR--immediate--SIMD-FP---Store-SIMD-FP-register--immediate-offset--
|
||||
// - LDR(SIMD&FP) if the src is memory and dst is a vector: https://developer.arm.com/documentation/ddi0596/2020-12/SIMD-FP-Instructions/LDR--immediate--SIMD-FP---Load-SIMD-FP-Register--immediate-offset--
|
||||
// - LDR(literal, SIMD&FP) if the src is static const and dst is a vector: https://developer.arm.com/documentation/dui0801/h/A64-Floating-point-Instructions/LDR--literal--SIMD-and-FP-
|
||||
// - STR(SIMD&FP) if the dst is memory and src is a vector: https://developer.arm.com/documentation/ddi0596/2020-12/SIMD-FP-Instructions/STR--immediate--SIMD-FP---Store-SIMD-FP-register--immediate-offset--
|
||||
VMOV
|
||||
// UMOV is the UMOV instruction https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions/UMOV--Unsigned-Move-vector-element-to-general-purpose-register-?lang=en
|
||||
UMOV
|
||||
|
||||
@@ -811,7 +811,7 @@ func (ce *callEngine) callFunction(ctx context.Context, callCtx *wasm.CallContex
|
||||
func (ce *callEngine) callGoFunc(ctx context.Context, callCtx *wasm.CallContext, f *function, params []uint64) (results []uint64) {
|
||||
callCtx = callCtx.WithMemory(ce.callerMemory())
|
||||
if f.source.FunctionListener != nil {
|
||||
ctx = f.source.FunctionListener.Before(ctx, params)
|
||||
ctx = f.source.FunctionListener.Before(ctx, f.source.Definition(), params)
|
||||
}
|
||||
frame := &callFrame{f: f}
|
||||
ce.pushFrame(frame)
|
||||
@@ -819,7 +819,7 @@ func (ce *callEngine) callGoFunc(ctx context.Context, callCtx *wasm.CallContext,
|
||||
ce.popFrame()
|
||||
if f.source.FunctionListener != nil {
|
||||
// TODO: This doesn't get the error due to use of panic to propagate them.
|
||||
f.source.FunctionListener.After(ctx, nil, results)
|
||||
f.source.FunctionListener.After(ctx, f.source.Definition(), nil, results)
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -4299,10 +4299,10 @@ func i32Abs(v uint32) uint32 {
|
||||
}
|
||||
|
||||
func (ce *callEngine) callNativeFuncWithListener(ctx context.Context, callCtx *wasm.CallContext, f *function, fnl experimental.FunctionListener) context.Context {
|
||||
ctx = fnl.Before(ctx, ce.peekValues(len(f.source.Type.Params)))
|
||||
ctx = fnl.Before(ctx, f.source.Definition(), ce.peekValues(len(f.source.Type.Params)))
|
||||
ce.callNativeFunc(ctx, callCtx, f)
|
||||
// TODO: This doesn't get the error due to use of panic to propagate them.
|
||||
fnl.After(ctx, nil, ce.peekValues(len(f.source.Type.Results)))
|
||||
fnl.After(ctx, f.source.Definition(), nil, ce.peekValues(len(f.source.Type.Results)))
|
||||
return ctx
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"unsafe"
|
||||
|
||||
"github.com/tetratelabs/wazero/experimental"
|
||||
"github.com/tetratelabs/wazero/experimental/logging"
|
||||
"github.com/tetratelabs/wazero/internal/buildoptions"
|
||||
"github.com/tetratelabs/wazero/internal/testing/enginetest"
|
||||
"github.com/tetratelabs/wazero/internal/testing/require"
|
||||
@@ -65,7 +66,7 @@ func TestInterpreter_CallEngine_PushFrame_StackOverflow(t *testing.T) {
|
||||
// et is used for tests defined in the enginetest package.
|
||||
var et = &engineTester{}
|
||||
var functionLog bytes.Buffer
|
||||
var listenerFactory = experimental.NewLoggingListenerFactory(&functionLog)
|
||||
var listenerFactory = logging.NewLoggingListenerFactory(&functionLog)
|
||||
|
||||
// engineTester implements enginetest.EngineTester.
|
||||
type engineTester struct{}
|
||||
|
||||
@@ -38,10 +38,10 @@ type CallContext struct {
|
||||
// Sys is exposed for use in special imports such as WASI, assemblyscript
|
||||
// and wasm_exec.
|
||||
//
|
||||
// Notes
|
||||
// # Notes
|
||||
//
|
||||
// * This is a part of CallContext so that scope and Close is coherent.
|
||||
// * This is not exposed outside this repository (as a host function
|
||||
// - This is a part of CallContext so that scope and Close is coherent.
|
||||
// - This is not exposed outside this repository (as a host function
|
||||
// parameter) because we haven't thought through capabilities based
|
||||
// security implications.
|
||||
Sys *internalsys.Context
|
||||
|
||||
@@ -579,7 +579,7 @@ func (m *Module) buildGlobals(importedGlobals []*GlobalInstance) (globals []*Glo
|
||||
// BuildFunctions generates function instances for all host or wasm-defined
|
||||
// functions in this module.
|
||||
//
|
||||
// Notes
|
||||
// # Notes
|
||||
// - This relies on data generated by Module.BuildFunctionDefinitions.
|
||||
// - This is exported for tests that don't call Instantiate, notably only
|
||||
// enginetest.go.
|
||||
|
||||
@@ -22,9 +22,9 @@ type Namespace interface {
|
||||
// module, _ := n.InstantiateModule(ctx, compiled, wazero.NewModuleConfig().WithName("prod"))
|
||||
//
|
||||
// While CompiledModule is pre-validated, there are a few situations which can cause an error:
|
||||
// * The module name is already in use.
|
||||
// * The module has a table element initializer that resolves to an index outside the Table minimum size.
|
||||
// * The module has a start function, and it failed to execute.
|
||||
// - The module name is already in use.
|
||||
// - The module has a table element initializer that resolves to an index outside the Table minimum size.
|
||||
// - The module has a start function, and it failed to execute.
|
||||
InstantiateModule(ctx context.Context, compiled CompiledModule, config ModuleConfig) (api.Module, error)
|
||||
|
||||
// CloseWithExitCode closes all modules initialized in this Namespace with the provided exit code.
|
||||
|
||||
24
runtime.go
24
runtime.go
@@ -36,13 +36,13 @@ type Runtime interface {
|
||||
// Any pre-compilation done after decoding wasm is dependent on RuntimeConfig or CompileConfig.
|
||||
//
|
||||
// There are two main reasons to use CompileModule instead of InstantiateModuleFromBinary:
|
||||
// * Improve performance when the same module is instantiated multiple times under different names
|
||||
// * Reduce the amount of errors that can occur during InstantiateModule.
|
||||
// - Improve performance when the same module is instantiated multiple times under different names
|
||||
// - Reduce the amount of errors that can occur during InstantiateModule.
|
||||
//
|
||||
// Notes
|
||||
// # Notes
|
||||
//
|
||||
// * The resulting module name defaults to what was binary from the custom name section.
|
||||
// * Any pre-compilation done after decoding the source is dependent on RuntimeConfig or CompileConfig.
|
||||
// - The resulting module name defaults to what was binary from the custom name section.
|
||||
// - Any pre-compilation done after decoding the source is dependent on RuntimeConfig or CompileConfig.
|
||||
//
|
||||
// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#name-section%E2%91%A0
|
||||
CompileModule(ctx context.Context, binary []byte, config CompileConfig) (CompiledModule, error)
|
||||
@@ -57,11 +57,11 @@ type Runtime interface {
|
||||
//
|
||||
// module, _ := r.InstantiateModuleFromBinary(ctx, wasm)
|
||||
//
|
||||
// Notes
|
||||
// # Notes
|
||||
//
|
||||
// * This is a convenience utility that chains CompileModule with InstantiateModule. To instantiate the same
|
||||
// - This is a convenience utility that chains CompileModule with InstantiateModule. To instantiate the same
|
||||
// source multiple times, use CompileModule as InstantiateModule avoids redundant decoding and/or compilation.
|
||||
// * To avoid using configuration defaults, use InstantiateModule instead.
|
||||
// - To avoid using configuration defaults, use InstantiateModule instead.
|
||||
InstantiateModuleFromBinary(ctx context.Context, source []byte) (api.Module, error)
|
||||
|
||||
// Namespace is the default namespace of this runtime, and is embedded for convenience. Most users will only use the
|
||||
@@ -94,11 +94,11 @@ type Runtime interface {
|
||||
// _ = b.WithTraceToStdout().InstantiateModule(ctx, ns2)
|
||||
// m2, _ := ns2.InstantiateModule(ctx, compiled, config)
|
||||
//
|
||||
// Notes
|
||||
// # Notes
|
||||
//
|
||||
// * The returned namespace does not inherit any modules from the runtime default namespace.
|
||||
// * Closing the returned namespace closes any modules in it.
|
||||
// * Closing this runtime also closes the namespace returned from this function.
|
||||
// - The returned namespace does not inherit any modules from the runtime default namespace.
|
||||
// - Closing the returned namespace closes any modules in it.
|
||||
// - Closing this runtime also closes the namespace returned from this function.
|
||||
NewNamespace(context.Context) Namespace
|
||||
|
||||
// CloseWithExitCode closes all the modules that have been initialized in this Runtime with the provided exit code.
|
||||
|
||||
@@ -15,7 +15,7 @@ const (
|
||||
// argsGet is the WASI function named functionArgsGet that reads command-line
|
||||
// argument data.
|
||||
//
|
||||
// Parameters
|
||||
// # Parameters
|
||||
//
|
||||
// - argv: offset to begin writing argument offsets in uint32 little-endian
|
||||
// encoding to api.Memory
|
||||
@@ -58,7 +58,7 @@ var argsGet = wasm.NewGoFunc(
|
||||
// argsSizesGet is the WASI function named functionArgsSizesGet that reads
|
||||
// command-line argument sizes.
|
||||
//
|
||||
// Parameters
|
||||
// # Parameters
|
||||
//
|
||||
// - resultArgc: offset to write the argument count to api.Memory
|
||||
// - resultArgvBufSize: offset to write the null-terminated argument length to
|
||||
|
||||
@@ -28,7 +28,7 @@ const (
|
||||
// clockResGet is the WASI function named functionClockResGet that returns the
|
||||
// resolution of time values returned by clockTimeGet.
|
||||
//
|
||||
// Parameters
|
||||
// # Parameters
|
||||
//
|
||||
// - id: clock ID to use
|
||||
// - resultResolution: offset to write the resolution to api.Memory
|
||||
@@ -83,7 +83,7 @@ var clockResGet = wasm.NewGoFunc(
|
||||
// clockTimeGet is the WASI function named functionClockTimeGet that returns
|
||||
// the time value of a name (time.Now).
|
||||
//
|
||||
// Parameters
|
||||
// # Parameters
|
||||
//
|
||||
// - id: clock ID to use
|
||||
// - precision: maximum lag (exclusive) that the returned time value may have,
|
||||
|
||||
@@ -15,7 +15,7 @@ const (
|
||||
// environGet is the WASI function named functionEnvironGet that reads
|
||||
// environment variables.
|
||||
//
|
||||
// Parameters
|
||||
// # Parameters
|
||||
//
|
||||
// - environ: offset to begin writing environment offsets in uint32
|
||||
// little-endian encoding to api.Memory
|
||||
@@ -58,7 +58,7 @@ var environGet = wasm.NewGoFunc(
|
||||
// environSizesGet is the WASI function named functionEnvironSizesGet that
|
||||
// reads environment variable sizes.
|
||||
//
|
||||
// Parameters
|
||||
// # Parameters
|
||||
//
|
||||
// - resultEnvironc: offset to write the count of environment variables to
|
||||
// api.Memory
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
|
||||
// Errno are the error codes returned by WASI functions.
|
||||
//
|
||||
// Notes
|
||||
// # Notes
|
||||
//
|
||||
// - This is not always an error, as ErrnoSuccess is a valid code.
|
||||
// - Codes are defined even when not relevant to WASI for use in higher-level libraries or alignment with POSIX.
|
||||
|
||||
@@ -69,7 +69,7 @@ var fdAllocate = stubFunction(
|
||||
// fdClose is the WASI function named functionFdClose which closes a file
|
||||
// descriptor.
|
||||
//
|
||||
// Parameters
|
||||
// # Parameters
|
||||
//
|
||||
// - fd: file descriptor to close
|
||||
//
|
||||
@@ -107,7 +107,7 @@ var fdDatasync = stubFunction(
|
||||
// fdFdstatGet is the WASI function named functionFdFdstatGet which returns the
|
||||
// attributes of a file descriptor.
|
||||
//
|
||||
// Parameters
|
||||
// # Parameters
|
||||
//
|
||||
// - fd: file descriptor to get the fdstat attributes data
|
||||
// - resultFdstat: offset to write the result fdstat data
|
||||
@@ -219,7 +219,7 @@ var fdPread = stubFunction(
|
||||
// fdPrestatGet is the WASI function named functionFdPrestatGet which returns
|
||||
// the prestat data of a file descriptor.
|
||||
//
|
||||
// Parameters
|
||||
// # Parameters
|
||||
//
|
||||
// - fd: file descriptor to get the prestat
|
||||
// - resultPrestat: offset to write the result prestat data
|
||||
@@ -273,7 +273,7 @@ var fdPrestatGet = wasm.NewGoFunc(
|
||||
// fdPrestatDirName is the WASI function named functionFdPrestatDirName which
|
||||
// returns the path of the pre-opened directory of a file descriptor.
|
||||
//
|
||||
// Parameters
|
||||
// # Parameters
|
||||
//
|
||||
// - fd: file descriptor to get the path of the pre-opened directory
|
||||
// - path: offset in api.Memory to write the result path
|
||||
@@ -289,7 +289,7 @@ var fdPrestatGet = wasm.NewGoFunc(
|
||||
// - ErrnoNametoolong: `pathLen` is longer than the actual length of the result
|
||||
//
|
||||
// For example, the directory name corresponding with `fd` was "/tmp" and
|
||||
// parameters path=1 pathLen=4 (correct), this function will write the below to
|
||||
// # Parameters path=1 pathLen=4 (correct), this function will write the below to
|
||||
// api.Memory:
|
||||
//
|
||||
// pathLen
|
||||
@@ -335,7 +335,7 @@ var fdPwrite = stubFunction(functionFdPwrite,
|
||||
// fdRead is the WASI function named functionFdRead which reads from a file
|
||||
// descriptor.
|
||||
//
|
||||
// Parameters
|
||||
// # Parameters
|
||||
//
|
||||
// - fd: an opened file descriptor to read data from
|
||||
// - iovs: offset in api.Memory to read offset, size pairs representing where
|
||||
@@ -444,7 +444,7 @@ var fdRenumber = stubFunction(
|
||||
// fdSeek is the WASI function named functionFdSeek which moves the offset of a
|
||||
// file descriptor.
|
||||
//
|
||||
// Parameters
|
||||
// # Parameters
|
||||
//
|
||||
// - fd: file descriptor to move the offset of
|
||||
// - offset: signed int64, which is encoded as uint64, input argument to
|
||||
@@ -531,7 +531,7 @@ var fdTell = stubFunction(
|
||||
// fdWrite is the WASI function named functionFdWrite which writes to a file
|
||||
// descriptor.
|
||||
//
|
||||
// Parameters
|
||||
// # Parameters
|
||||
//
|
||||
// - fd: an opened file descriptor to write data to
|
||||
// - iovs: offset in api.Memory to read offset, size pairs representing the
|
||||
@@ -668,7 +668,7 @@ var pathLink = stubFunction(
|
||||
// pathOpen is the WASI function named functionPathOpen which opens a file or
|
||||
// directory. This returns ErrnoBadf if the fd is invalid.
|
||||
//
|
||||
// Parameters
|
||||
// # Parameters
|
||||
//
|
||||
// - fd: file descriptor of a directory that `path` is relative to
|
||||
// - dirflags: flags to indicate how to resolve `path`
|
||||
@@ -713,7 +713,7 @@ var pathLink = stubFunction(
|
||||
// []byte{ 0..6, ?, 5, 0, 0, 0, ?}
|
||||
// resultOpenedFd --^
|
||||
//
|
||||
// Notes
|
||||
// # Notes
|
||||
// - This is similar to `openat` in POSIX. https://linux.die.net/man/3/openat
|
||||
// - The returned file descriptor is not guaranteed to be the lowest-number
|
||||
// - Rights will never be implemented per https://github.com/WebAssembly/WASI/issues/469#issuecomment-1045251844
|
||||
|
||||
@@ -24,7 +24,7 @@ const (
|
||||
// pollOneoff is the WASI function named functionPollOneoff that concurrently
|
||||
// polls for the occurrence of a set of events.
|
||||
//
|
||||
// Parameters
|
||||
// # Parameters
|
||||
//
|
||||
// - in: pointer to the subscriptions (48 bytes each)
|
||||
// - out: pointer to the resulting events (32 bytes each)
|
||||
@@ -39,7 +39,7 @@ const (
|
||||
// - ErrnoFault: there is not enough memory to read the subscriptions or
|
||||
// write results.
|
||||
//
|
||||
// Notes
|
||||
// # Notes
|
||||
//
|
||||
// - Since the `out` pointer nests Errno, the result is always ErrnoSuccess.
|
||||
// - importPollOneoff shows this signature in the WebAssembly 1.0 Text Format.
|
||||
|
||||
@@ -17,7 +17,7 @@ const (
|
||||
// execution of the module with an exit code. The only successful exit code is
|
||||
// zero.
|
||||
//
|
||||
// Parameters
|
||||
// # Parameters
|
||||
//
|
||||
// - exitCode: exit code.
|
||||
//
|
||||
|
||||
@@ -13,7 +13,7 @@ const functionRandomGet = "random_get"
|
||||
// randomGet is the WASI function named functionRandomGet which writes random
|
||||
// data to a buffer.
|
||||
//
|
||||
// Parameters
|
||||
// # Parameters
|
||||
//
|
||||
// - buf: api.Memory offset to write random values
|
||||
// - bufLen: size of random data in bytes
|
||||
|
||||
@@ -33,7 +33,7 @@ const i32, i64 = wasm.ValueTypeI32, wasm.ValueTypeI64
|
||||
// Instantiate instantiates the ModuleName module into the runtime default
|
||||
// namespace.
|
||||
//
|
||||
// Notes
|
||||
// # Notes
|
||||
//
|
||||
// - Closing the wazero.Runtime has the same effect as closing the result.
|
||||
// - To instantiate into another wazero.Namespace, use NewBuilder instead.
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"github.com/tetratelabs/wazero"
|
||||
"github.com/tetratelabs/wazero/api"
|
||||
. "github.com/tetratelabs/wazero/experimental"
|
||||
"github.com/tetratelabs/wazero/experimental/logging"
|
||||
"github.com/tetratelabs/wazero/internal/testing/require"
|
||||
)
|
||||
|
||||
@@ -36,7 +37,7 @@ func requireModule(t *testing.T, config wazero.ModuleConfig) (api.Module, api.Cl
|
||||
var log bytes.Buffer
|
||||
|
||||
// Set context to one that has an experimental listener
|
||||
ctx := context.WithValue(testCtx, FunctionListenerFactoryKey{}, NewLoggingListenerFactory(&log))
|
||||
ctx := context.WithValue(testCtx, FunctionListenerFactoryKey{}, logging.NewLoggingListenerFactory(&log))
|
||||
|
||||
r := wazero.NewRuntimeWithConfig(wazero.NewRuntimeConfigInterpreter())
|
||||
|
||||
@@ -57,7 +58,7 @@ func requireErrnoNosys(t *testing.T, funcName string, params ...uint64) string {
|
||||
var log bytes.Buffer
|
||||
|
||||
// Set context to one that has an experimental listener
|
||||
ctx := context.WithValue(testCtx, FunctionListenerFactoryKey{}, NewLoggingListenerFactory(&log))
|
||||
ctx := context.WithValue(testCtx, FunctionListenerFactoryKey{}, logging.NewLoggingListenerFactory(&log))
|
||||
|
||||
r := wazero.NewRuntimeWithConfig(wazero.NewRuntimeConfigInterpreter())
|
||||
defer r.Close(ctx)
|
||||
|
||||
Reference in New Issue
Block a user