summaryrefslogtreecommitdiff
path: root/vendor/github.com/tetratelabs/wazero/config.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/tetratelabs/wazero/config.go')
-rw-r--r--vendor/github.com/tetratelabs/wazero/config.go900
1 files changed, 0 insertions, 900 deletions
diff --git a/vendor/github.com/tetratelabs/wazero/config.go b/vendor/github.com/tetratelabs/wazero/config.go
deleted file mode 100644
index ea7b84f44..000000000
--- a/vendor/github.com/tetratelabs/wazero/config.go
+++ /dev/null
@@ -1,900 +0,0 @@
-package wazero
-
-import (
- "context"
- "errors"
- "fmt"
- "io"
- "io/fs"
- "math"
- "net"
- "time"
-
- "github.com/tetratelabs/wazero/api"
- experimentalsys "github.com/tetratelabs/wazero/experimental/sys"
- "github.com/tetratelabs/wazero/internal/engine/interpreter"
- "github.com/tetratelabs/wazero/internal/engine/wazevo"
- "github.com/tetratelabs/wazero/internal/filecache"
- "github.com/tetratelabs/wazero/internal/internalapi"
- "github.com/tetratelabs/wazero/internal/platform"
- internalsock "github.com/tetratelabs/wazero/internal/sock"
- internalsys "github.com/tetratelabs/wazero/internal/sys"
- "github.com/tetratelabs/wazero/internal/wasm"
- "github.com/tetratelabs/wazero/sys"
-)
-
-// RuntimeConfig controls runtime behavior, with the default implementation as
-// NewRuntimeConfig
-//
-// The example below explicitly limits to Wasm Core 1.0 features as opposed to
-// relying on defaults:
-//
-// rConfig = wazero.NewRuntimeConfig().WithCoreFeatures(api.CoreFeaturesV1)
-//
-// # Notes
-//
-// - This is an interface for decoupling, not third-party implementations.
-// All implementations are in wazero.
-// - RuntimeConfig is immutable. Each WithXXX function returns a new instance
-// including the corresponding change.
-type RuntimeConfig interface {
- // WithCoreFeatures sets the WebAssembly Core specification features this
- // runtime supports. Defaults to api.CoreFeaturesV2.
- //
- // Example of disabling a specific feature:
- // features := api.CoreFeaturesV2.SetEnabled(api.CoreFeatureMutableGlobal, false)
- // rConfig = wazero.NewRuntimeConfig().WithCoreFeatures(features)
- //
- // # Why default to version 2.0?
- //
- // Many compilers that target WebAssembly require features after
- // api.CoreFeaturesV1 by default. For example, TinyGo v0.24+ requires
- // api.CoreFeatureBulkMemoryOperations. To avoid runtime errors, wazero
- // defaults to api.CoreFeaturesV2, even though it is not yet a Web
- // Standard (REC).
- WithCoreFeatures(api.CoreFeatures) RuntimeConfig
-
- // WithMemoryLimitPages overrides the maximum pages allowed per memory. The
- // default is 65536, allowing 4GB total memory per instance if the maximum is
- // not encoded in a Wasm binary. Setting a value larger than default will panic.
- //
- // This example reduces the largest possible memory size from 4GB to 128KB:
- // rConfig = wazero.NewRuntimeConfig().WithMemoryLimitPages(2)
- //
- // Note: Wasm has 32-bit memory and each page is 65536 (2^16) bytes. This
- // implies a max of 65536 (2^16) addressable pages.
- // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#grow-mem
- WithMemoryLimitPages(memoryLimitPages uint32) RuntimeConfig
-
- // WithMemoryCapacityFromMax eagerly allocates max memory, unless max is
- // not defined. The default is false, which means minimum memory is
- // allocated and any call to grow memory results in re-allocations.
- //
- // This example ensures any memory.grow instruction will never re-allocate:
- // rConfig = wazero.NewRuntimeConfig().WithMemoryCapacityFromMax(true)
- //
- // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#grow-mem
- //
- // Note: if the memory maximum is not encoded in a Wasm binary, this
- // results in allocating 4GB. See the doc on WithMemoryLimitPages for detail.
- WithMemoryCapacityFromMax(memoryCapacityFromMax bool) RuntimeConfig
-
- // WithDebugInfoEnabled toggles DWARF based stack traces in the face of
- // runtime errors. Defaults to true.
- //
- // Those who wish to disable this, can like so:
- //
- // r := wazero.NewRuntimeWithConfig(wazero.NewRuntimeConfig().WithDebugInfoEnabled(false)
- //
- // When disabled, a stack trace message looks like:
- //
- // wasm stack trace:
- // .runtime._panic(i32)
- // .myFunc()
- // .main.main()
- // .runtime.run()
- // ._start()
- //
- // When enabled, the stack trace includes source code information:
- //
- // wasm stack trace:
- // .runtime._panic(i32)
- // 0x16e2: /opt/homebrew/Cellar/tinygo/0.26.0/src/runtime/runtime_tinygowasm.go:73:6
- // .myFunc()
- // 0x190b: /Users/XXXXX/wazero/internal/testing/dwarftestdata/testdata/main.go:19:7
- // .main.main()
- // 0x18ed: /Users/XXXXX/wazero/internal/testing/dwarftestdata/testdata/main.go:4:3
- // .runtime.run()
- // 0x18cc: /opt/homebrew/Cellar/tinygo/0.26.0/src/runtime/scheduler_none.go:26:10
- // ._start()
- // 0x18b6: /opt/homebrew/Cellar/tinygo/0.26.0/src/runtime/runtime_wasm_wasi.go:22:5
- //
- // Note: This only takes into effect when the original Wasm binary has the
- // DWARF "custom sections" that are often stripped, depending on
- // optimization flags passed to the compiler.
- WithDebugInfoEnabled(bool) RuntimeConfig
-
- // WithCompilationCache configures how runtime caches the compiled modules. In the default configuration, compilation results are
- // only in-memory until Runtime.Close is closed, and not shareable by multiple Runtime.
- //
- // Below defines the shared cache across multiple instances of Runtime:
- //
- // // Creates the new Cache and the runtime configuration with it.
- // cache := wazero.NewCompilationCache()
- // defer cache.Close()
- // config := wazero.NewRuntimeConfig().WithCompilationCache(c)
- //
- // // Creates two runtimes while sharing compilation caches.
- // foo := wazero.NewRuntimeWithConfig(context.Background(), config)
- // bar := wazero.NewRuntimeWithConfig(context.Background(), config)
- //
- // # Cache Key
- //
- // Cached files are keyed on the version of wazero. This is obtained from go.mod of your application,
- // and we use it to verify the compatibility of caches against the currently-running wazero.
- // However, if you use this in tests of a package not named as `main`, then wazero cannot obtain the correct
- // version of wazero due to the known issue of debug.BuildInfo function: https://github.com/golang/go/issues/33976.
- // As a consequence, your cache won't contain the correct version information and always be treated as `dev` version.
- // To avoid this issue, you can pass -ldflags "-X github.com/tetratelabs/wazero/internal/version.version=foo" when running tests.
- WithCompilationCache(CompilationCache) RuntimeConfig
-
- // WithCustomSections toggles parsing of "custom sections". Defaults to false.
- //
- // When enabled, it is possible to retrieve custom sections from a CompiledModule:
- //
- // config := wazero.NewRuntimeConfig().WithCustomSections(true)
- // r := wazero.NewRuntimeWithConfig(ctx, config)
- // c, err := r.CompileModule(ctx, wasm)
- // customSections := c.CustomSections()
- WithCustomSections(bool) RuntimeConfig
-
- // WithCloseOnContextDone ensures the executions of functions to be terminated under one of the following circumstances:
- //
- // - context.Context passed to the Call method of api.Function is canceled during execution. (i.e. ctx by context.WithCancel)
- // - context.Context passed to the Call method of api.Function reaches timeout during execution. (i.e. ctx by context.WithTimeout or context.WithDeadline)
- // - Close or CloseWithExitCode of api.Module is explicitly called during execution.
- //
- // This is especially useful when one wants to run untrusted Wasm binaries since otherwise, any invocation of
- // api.Function can potentially block the corresponding Goroutine forever. Moreover, it might block the
- // entire underlying OS thread which runs the api.Function call. See "Why it's safe to execute runtime-generated
- // machine codes against async Goroutine preemption" section in RATIONALE.md for detail.
- //
- // Upon the termination of the function executions, api.Module is closed.
- //
- // Note that this comes with a bit of extra cost when enabled. The reason is that internally this forces
- // interpreter and compiler runtimes to insert the periodical checks on the conditions above. For that reason,
- // this is disabled by default.
- //
- // See examples in context_done_example_test.go for the end-to-end demonstrations.
- //
- // When the invocations of api.Function are closed due to this, sys.ExitError is raised to the callers and
- // the api.Module from which the functions are derived is made closed.
- WithCloseOnContextDone(bool) RuntimeConfig
-}
-
-// NewRuntimeConfig returns a RuntimeConfig using the compiler if it is supported in this environment,
-// or the interpreter otherwise.
-func NewRuntimeConfig() RuntimeConfig {
- return newRuntimeConfig()
-}
-
-type newEngine func(context.Context, api.CoreFeatures, filecache.Cache) wasm.Engine
-
-type runtimeConfig struct {
- enabledFeatures api.CoreFeatures
- memoryLimitPages uint32
- memoryCapacityFromMax bool
- engineKind engineKind
- dwarfDisabled bool // negative as defaults to enabled
- newEngine newEngine
- cache CompilationCache
- storeCustomSections bool
- ensureTermination bool
-}
-
-// engineLessConfig helps avoid copy/pasting the wrong defaults.
-var engineLessConfig = &runtimeConfig{
- enabledFeatures: api.CoreFeaturesV2,
- memoryLimitPages: wasm.MemoryLimitPages,
- memoryCapacityFromMax: false,
- dwarfDisabled: false,
-}
-
-type engineKind int
-
-const (
- engineKindCompiler engineKind = iota
- engineKindInterpreter
- engineKindCount
-)
-
-// NewRuntimeConfigCompiler compiles WebAssembly modules into
-// runtime.GOARCH-specific assembly for optimal performance.
-//
-// The default implementation is AOT (Ahead of Time) compilation, applied at
-// Runtime.CompileModule. This allows consistent runtime performance, as well
-// the ability to reduce any first request penalty.
-//
-// Note: While this is technically AOT, this does not imply any action on your
-// part. wazero automatically performs ahead-of-time compilation as needed when
-// Runtime.CompileModule is invoked.
-//
-// # Warning
-//
-// - This panics at runtime if the runtime.GOOS or runtime.GOARCH does not
-// support compiler. Use NewRuntimeConfig to safely detect and fallback to
-// NewRuntimeConfigInterpreter if needed.
-//
-// - If you are using wazero in buildmode=c-archive or c-shared, make sure that you set up the alternate signal stack
-// by using, e.g. `sigaltstack` combined with `SA_ONSTACK` flag on `sigaction` on Linux,
-// before calling any api.Function. This is because the Go runtime does not set up the alternate signal stack
-// for c-archive or c-shared modes, and wazero uses the different stack than the calling Goroutine.
-// Hence, the signal handler might get invoked on the wazero's stack, which may cause a stack overflow.
-// https://github.com/tetratelabs/wazero/blob/2092c0a879f30d49d7b37f333f4547574b8afe0d/internal/integration_test/fuzz/fuzz/tests/sigstack.rs#L19-L36
-func NewRuntimeConfigCompiler() RuntimeConfig {
- ret := engineLessConfig.clone()
- ret.engineKind = engineKindCompiler
- ret.newEngine = wazevo.NewEngine
- return ret
-}
-
-// NewRuntimeConfigInterpreter interprets WebAssembly modules instead of compiling them into assembly.
-func NewRuntimeConfigInterpreter() RuntimeConfig {
- ret := engineLessConfig.clone()
- ret.engineKind = engineKindInterpreter
- ret.newEngine = interpreter.NewEngine
- return ret
-}
-
-// clone makes a deep copy of this runtime config.
-func (c *runtimeConfig) clone() *runtimeConfig {
- ret := *c // copy except maps which share a ref
- return &ret
-}
-
-// WithCoreFeatures implements RuntimeConfig.WithCoreFeatures
-func (c *runtimeConfig) WithCoreFeatures(features api.CoreFeatures) RuntimeConfig {
- ret := c.clone()
- ret.enabledFeatures = features
- return ret
-}
-
-// WithCloseOnContextDone implements RuntimeConfig.WithCloseOnContextDone
-func (c *runtimeConfig) WithCloseOnContextDone(ensure bool) RuntimeConfig {
- ret := c.clone()
- ret.ensureTermination = ensure
- return ret
-}
-
-// WithMemoryLimitPages implements RuntimeConfig.WithMemoryLimitPages
-func (c *runtimeConfig) WithMemoryLimitPages(memoryLimitPages uint32) RuntimeConfig {
- ret := c.clone()
- // This panics instead of returning an error as it is unlikely.
- if memoryLimitPages > wasm.MemoryLimitPages {
- panic(fmt.Errorf("memoryLimitPages invalid: %d > %d", memoryLimitPages, wasm.MemoryLimitPages))
- }
- ret.memoryLimitPages = memoryLimitPages
- return ret
-}
-
-// WithCompilationCache implements RuntimeConfig.WithCompilationCache
-func (c *runtimeConfig) WithCompilationCache(ca CompilationCache) RuntimeConfig {
- ret := c.clone()
- ret.cache = ca
- return ret
-}
-
-// WithMemoryCapacityFromMax implements RuntimeConfig.WithMemoryCapacityFromMax
-func (c *runtimeConfig) WithMemoryCapacityFromMax(memoryCapacityFromMax bool) RuntimeConfig {
- ret := c.clone()
- ret.memoryCapacityFromMax = memoryCapacityFromMax
- return ret
-}
-
-// WithDebugInfoEnabled implements RuntimeConfig.WithDebugInfoEnabled
-func (c *runtimeConfig) WithDebugInfoEnabled(dwarfEnabled bool) RuntimeConfig {
- ret := c.clone()
- ret.dwarfDisabled = !dwarfEnabled
- return ret
-}
-
-// WithCustomSections implements RuntimeConfig.WithCustomSections
-func (c *runtimeConfig) WithCustomSections(storeCustomSections bool) RuntimeConfig {
- ret := c.clone()
- ret.storeCustomSections = storeCustomSections
- return ret
-}
-
-// CompiledModule is a WebAssembly module ready to be instantiated (Runtime.InstantiateModule) as an api.Module.
-//
-// In WebAssembly terminology, this is a decoded, validated, and possibly also compiled module. wazero avoids using
-// the name "Module" for both before and after instantiation as the name conflation has caused confusion.
-// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#semantic-phases%E2%91%A0
-//
-// # Notes
-//
-// - This is an interface for decoupling, not third-party implementations.
-// All implementations are in wazero.
-// - Closing the wazero.Runtime closes any CompiledModule it compiled.
-type CompiledModule interface {
- // Name returns the module name encoded into the binary or empty if not.
- Name() string
-
- // ImportedFunctions returns all the imported functions
- // (api.FunctionDefinition) in this module or nil if there are none.
- //
- // Note: Unlike ExportedFunctions, there is no unique constraint on
- // imports.
- ImportedFunctions() []api.FunctionDefinition
-
- // ExportedFunctions returns all the exported functions
- // (api.FunctionDefinition) in this module keyed on export name.
- ExportedFunctions() map[string]api.FunctionDefinition
-
- // ImportedMemories returns all the imported memories
- // (api.MemoryDefinition) in this module or nil if there are none.
- //
- // ## Notes
- // - As of WebAssembly Core Specification 2.0, there can be at most one
- // memory.
- // - Unlike ExportedMemories, there is no unique constraint on imports.
- ImportedMemories() []api.MemoryDefinition
-
- // ExportedMemories returns all the exported memories
- // (api.MemoryDefinition) in this module keyed on export name.
- //
- // Note: As of WebAssembly Core Specification 2.0, there can be at most one
- // memory.
- ExportedMemories() map[string]api.MemoryDefinition
-
- // CustomSections returns all the custom sections
- // (api.CustomSection) in this module keyed on the section name.
- CustomSections() []api.CustomSection
-
- // Close releases all the allocated resources for this CompiledModule.
- //
- // Note: It is safe to call Close while having outstanding calls from an
- // api.Module instantiated from this.
- Close(context.Context) error
-}
-
-// compile-time check to ensure compiledModule implements CompiledModule
-var _ CompiledModule = &compiledModule{}
-
-type compiledModule struct {
- module *wasm.Module
- // compiledEngine holds an engine on which `module` is compiled.
- compiledEngine wasm.Engine
- // closeWithModule prevents leaking compiled code when a module is compiled implicitly.
- closeWithModule bool
- typeIDs []wasm.FunctionTypeID
-}
-
-// Name implements CompiledModule.Name
-func (c *compiledModule) Name() (moduleName string) {
- if ns := c.module.NameSection; ns != nil {
- moduleName = ns.ModuleName
- }
- return
-}
-
-// Close implements CompiledModule.Close
-func (c *compiledModule) Close(context.Context) error {
- c.compiledEngine.DeleteCompiledModule(c.module)
- // It is possible the underlying may need to return an error later, but in any case this matches api.Module.Close.
- return nil
-}
-
-// ImportedFunctions implements CompiledModule.ImportedFunctions
-func (c *compiledModule) ImportedFunctions() []api.FunctionDefinition {
- return c.module.ImportedFunctions()
-}
-
-// ExportedFunctions implements CompiledModule.ExportedFunctions
-func (c *compiledModule) ExportedFunctions() map[string]api.FunctionDefinition {
- return c.module.ExportedFunctions()
-}
-
-// ImportedMemories implements CompiledModule.ImportedMemories
-func (c *compiledModule) ImportedMemories() []api.MemoryDefinition {
- return c.module.ImportedMemories()
-}
-
-// ExportedMemories implements CompiledModule.ExportedMemories
-func (c *compiledModule) ExportedMemories() map[string]api.MemoryDefinition {
- return c.module.ExportedMemories()
-}
-
-// CustomSections implements CompiledModule.CustomSections
-func (c *compiledModule) CustomSections() []api.CustomSection {
- ret := make([]api.CustomSection, len(c.module.CustomSections))
- for i, d := range c.module.CustomSections {
- ret[i] = &customSection{data: d.Data, name: d.Name}
- }
- return ret
-}
-
-// customSection implements wasm.CustomSection
-type customSection struct {
- internalapi.WazeroOnlyType
- name string
- data []byte
-}
-
-// Name implements wasm.CustomSection.Name
-func (c *customSection) Name() string {
- return c.name
-}
-
-// Data implements wasm.CustomSection.Data
-func (c *customSection) Data() []byte {
- return c.data
-}
-
-// ModuleConfig configures resources needed by functions that have low-level interactions with the host operating
-// system. Using this, resources such as STDIN can be isolated, so that the same module can be safely instantiated
-// multiple times.
-//
-// Here's an example:
-//
-// // Initialize base configuration:
-// config := wazero.NewModuleConfig().WithStdout(buf).WithSysNanotime()
-//
-// // Assign different configuration on each instantiation
-// mod, _ := r.InstantiateModule(ctx, compiled, config.WithName("rotate").WithArgs("rotate", "angle=90", "dir=cw"))
-//
-// While wazero supports Windows as a platform, host functions using ModuleConfig follow a UNIX dialect.
-// See RATIONALE.md for design background and relationship to WebAssembly System Interfaces (WASI).
-//
-// # Notes
-//
-// - This is an interface for decoupling, not third-party implementations.
-// All implementations are in wazero.
-// - ModuleConfig is immutable. Each WithXXX function returns a new instance
-// including the corresponding change.
-type ModuleConfig interface {
- // WithArgs assigns command-line arguments visible to an imported function that reads an arg vector (argv). Defaults to
- // none. Runtime.InstantiateModule errs if any arg is empty.
- //
- // These values are commonly read by the functions like "args_get" in "wasi_snapshot_preview1" although they could be
- // read by functions imported from other modules.
- //
- // Similar to os.Args and exec.Cmd Env, many implementations would expect a program name to be argv[0]. However, neither
- // WebAssembly nor WebAssembly System Interfaces (WASI) define this. Regardless, you may choose to set the first
- // argument to the same value set via WithName.
- //
- // Note: This does not default to os.Args as that violates sandboxing.
- //
- // See https://linux.die.net/man/3/argv and https://en.wikipedia.org/wiki/Null-terminated_string
- WithArgs(...string) ModuleConfig
-
- // WithEnv sets an environment variable visible to a Module that imports functions. Defaults to none.
- // Runtime.InstantiateModule errs if the key is empty or contains a NULL(0) or equals("") character.
- //
- // Validation is the same as os.Setenv on Linux and replaces any existing value. Unlike exec.Cmd Env, this does not
- // default to the current process environment as that would violate sandboxing. This also does not preserve order.
- //
- // Environment variables are commonly read by the functions like "environ_get" in "wasi_snapshot_preview1" although
- // they could be read by functions imported from other modules.
- //
- // While similar to process configuration, there are no assumptions that can be made about anything OS-specific. For
- // example, neither WebAssembly nor WebAssembly System Interfaces (WASI) define concerns processes have, such as
- // case-sensitivity on environment keys. For portability, define entries with case-insensitively unique keys.
- //
- // See https://linux.die.net/man/3/environ and https://en.wikipedia.org/wiki/Null-terminated_string
- WithEnv(key, value string) ModuleConfig
-
- // WithFS is a convenience that calls WithFSConfig with an FSConfig of the
- // input for the root ("/") guest path.
- WithFS(fs.FS) ModuleConfig
-
- // WithFSConfig configures the filesystem available to each guest
- // instantiated with this configuration. By default, no file access is
- // allowed, so functions like `path_open` result in unsupported errors
- // (e.g. syscall.ENOSYS).
- WithFSConfig(FSConfig) ModuleConfig
-
- // WithName configures the module name. Defaults to what was decoded from
- // the name section. Duplicate names are not allowed in a single Runtime.
- //
- // Calling this with the empty string "" makes the module anonymous.
- // That is useful when you want to instantiate the same CompiledModule multiple times like below:
- //
- // for i := 0; i < N; i++ {
- // // Instantiate a new Wasm module from the already compiled `compiledWasm` anonymously without a name.
- // instance, err := r.InstantiateModule(ctx, compiledWasm, wazero.NewModuleConfig().WithName(""))
- // // ....
- // }
- //
- // See the `concurrent-instantiation` example for a complete usage.
- //
- // Non-empty named modules are available for other modules to import by name.
- WithName(string) ModuleConfig
-
- // WithStartFunctions configures the functions to call after the module is
- // instantiated. Defaults to "_start".
- //
- // Clearing the default is supported, via `WithStartFunctions()`.
- //
- // # Notes
- //
- // - If a start function doesn't exist, it is skipped. However, any that
- // do exist are called in order.
- // - Start functions are not intended to be called multiple times.
- // Functions that should be called multiple times should be invoked
- // manually via api.Module's `ExportedFunction` method.
- // - Start functions commonly exit the module during instantiation,
- // preventing use of any functions later. This is the case in "wasip1",
- // which defines the default value "_start".
- // - See /RATIONALE.md for motivation of this feature.
- WithStartFunctions(...string) ModuleConfig
-
- // WithStderr configures where standard error (file descriptor 2) is written. Defaults to io.Discard.
- //
- // 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
- //
- // - 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
-
- // WithStdin configures where standard input (file descriptor 0) is read. Defaults to return io.EOF.
- //
- // 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
- //
- // - 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
-
- // WithStdout configures where standard output (file descriptor 1) is written. Defaults to io.Discard.
- //
- // 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
- //
- // - 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
-
- // WithWalltime configures the wall clock, sometimes referred to as the
- // real time clock. sys.Walltime returns the current unix/epoch time,
- // seconds since midnight UTC 1 January 1970, with a nanosecond fraction.
- // This defaults to a fake result that increases by 1ms on each reading.
- //
- // Here's an example that uses a custom clock:
- // moduleConfig = moduleConfig.
- // WithWalltime(func(context.Context) (sec int64, nsec int32) {
- // return clock.walltime()
- // }, sys.ClockResolution(time.Microsecond.Nanoseconds()))
- //
- // # Notes:
- // - This does not default to time.Now as that violates sandboxing.
- // - This is used to implement host functions such as WASI
- // `clock_time_get` with the `realtime` clock ID.
- // - Use WithSysWalltime for a usable implementation.
- WithWalltime(sys.Walltime, sys.ClockResolution) ModuleConfig
-
- // WithSysWalltime uses time.Now for sys.Walltime with a resolution of 1us
- // (1000ns).
- //
- // See WithWalltime
- WithSysWalltime() ModuleConfig
-
- // WithNanotime configures the monotonic clock, used to measure elapsed
- // time in nanoseconds. Defaults to a fake result that increases by 1ms
- // on each reading.
- //
- // Here's an example that uses a custom clock:
- // moduleConfig = moduleConfig.
- // WithNanotime(func(context.Context) int64 {
- // return clock.nanotime()
- // }, sys.ClockResolution(time.Microsecond.Nanoseconds()))
- //
- // # Notes:
- // - This does not default to time.Since as that violates sandboxing.
- // - This is used to implement host functions such as WASI
- // `clock_time_get` with the `monotonic` clock ID.
- // - Some compilers implement sleep by looping on sys.Nanotime (e.g. 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.
- //
- // See WithNanotime
- WithSysNanotime() ModuleConfig
-
- // WithNanosleep configures the how to pause the current goroutine for at
- // least the configured nanoseconds. Defaults to return immediately.
- //
- // This example uses a custom sleep function:
- // moduleConfig = moduleConfig.
- // WithNanosleep(func(ns int64) {
- // rel := unix.NsecToTimespec(ns)
- // remain := unix.Timespec{}
- // for { // loop until no more time remaining
- // err := unix.ClockNanosleep(unix.CLOCK_MONOTONIC, 0, &rel, &remain)
- // --snip--
- //
- // # Notes:
- // - This does not default to time.Sleep as that violates sandboxing.
- // - This is used to implement host functions such as WASI `poll_oneoff`.
- // - Some compilers implement sleep by looping on sys.Nanotime (e.g. Go).
- // - If you set this, you should probably set WithNanotime also.
- // - Use WithSysNanosleep for a usable implementation.
- WithNanosleep(sys.Nanosleep) ModuleConfig
-
- // WithOsyield yields the processor, typically to implement spin-wait
- // loops. Defaults to return immediately.
- //
- // # Notes:
- // - This primarily supports `sched_yield` in WASI
- // - This does not default to runtime.osyield as that violates sandboxing.
- WithOsyield(sys.Osyield) ModuleConfig
-
- // WithSysNanosleep uses time.Sleep for sys.Nanosleep.
- //
- // See WithNanosleep
- WithSysNanosleep() ModuleConfig
-
- // WithRandSource configures a source of random bytes. Defaults to return a
- // deterministic source. You might override this with crypto/rand.Reader
- //
- // This reader is most commonly used by the functions like "random_get" in
- // "wasi_snapshot_preview1", "seed" in AssemblyScript standard "env", and
- // "getRandomData" when runtime.GOOS is "js".
- //
- // Note: The caller is responsible to close any io.Reader they supply: It
- // is not closed on api.Module Close.
- WithRandSource(io.Reader) ModuleConfig
-}
-
-type moduleConfig struct {
- name string
- nameSet bool
- startFunctions []string
- stdin io.Reader
- stdout io.Writer
- stderr io.Writer
- randSource io.Reader
- walltime sys.Walltime
- walltimeResolution sys.ClockResolution
- nanotime sys.Nanotime
- nanotimeResolution sys.ClockResolution
- nanosleep sys.Nanosleep
- osyield sys.Osyield
- args [][]byte
- // environ is pair-indexed to retain order similar to os.Environ.
- environ [][]byte
- // environKeys allow overwriting of existing values.
- environKeys map[string]int
- // fsConfig is the file system configuration for ABI like WASI.
- fsConfig FSConfig
- // sockConfig is the network listener configuration for ABI like WASI.
- sockConfig *internalsock.Config
-}
-
-// NewModuleConfig returns a ModuleConfig that can be used for configuring module instantiation.
-func NewModuleConfig() ModuleConfig {
- return &moduleConfig{
- startFunctions: []string{"_start"},
- environKeys: map[string]int{},
- }
-}
-
-// clone makes a deep copy of this module config.
-func (c *moduleConfig) clone() *moduleConfig {
- ret := *c // copy except maps which share a ref
- ret.environKeys = make(map[string]int, len(c.environKeys))
- for key, value := range c.environKeys {
- ret.environKeys[key] = value
- }
- return &ret
-}
-
-// WithArgs implements ModuleConfig.WithArgs
-func (c *moduleConfig) WithArgs(args ...string) ModuleConfig {
- ret := c.clone()
- ret.args = toByteSlices(args)
- return ret
-}
-
-func toByteSlices(strings []string) (result [][]byte) {
- if len(strings) == 0 {
- return
- }
- result = make([][]byte, len(strings))
- for i, a := range strings {
- result[i] = []byte(a)
- }
- return
-}
-
-// WithEnv implements ModuleConfig.WithEnv
-func (c *moduleConfig) WithEnv(key, value string) ModuleConfig {
- ret := c.clone()
- // Check to see if this key already exists and update it.
- if i, ok := ret.environKeys[key]; ok {
- ret.environ[i+1] = []byte(value) // environ is pair-indexed, so the value is 1 after the key.
- } else {
- ret.environKeys[key] = len(ret.environ)
- ret.environ = append(ret.environ, []byte(key), []byte(value))
- }
- return ret
-}
-
-// WithFS implements ModuleConfig.WithFS
-func (c *moduleConfig) WithFS(fs fs.FS) ModuleConfig {
- var config FSConfig
- if fs != nil {
- config = NewFSConfig().WithFSMount(fs, "")
- }
- return c.WithFSConfig(config)
-}
-
-// WithFSConfig implements ModuleConfig.WithFSConfig
-func (c *moduleConfig) WithFSConfig(config FSConfig) ModuleConfig {
- ret := c.clone()
- ret.fsConfig = config
- return ret
-}
-
-// WithName implements ModuleConfig.WithName
-func (c *moduleConfig) WithName(name string) ModuleConfig {
- ret := c.clone()
- ret.nameSet = true
- ret.name = name
- return ret
-}
-
-// WithStartFunctions implements ModuleConfig.WithStartFunctions
-func (c *moduleConfig) WithStartFunctions(startFunctions ...string) ModuleConfig {
- ret := c.clone()
- ret.startFunctions = startFunctions
- return ret
-}
-
-// WithStderr implements ModuleConfig.WithStderr
-func (c *moduleConfig) WithStderr(stderr io.Writer) ModuleConfig {
- ret := c.clone()
- ret.stderr = stderr
- return ret
-}
-
-// WithStdin implements ModuleConfig.WithStdin
-func (c *moduleConfig) WithStdin(stdin io.Reader) ModuleConfig {
- ret := c.clone()
- ret.stdin = stdin
- return ret
-}
-
-// WithStdout implements ModuleConfig.WithStdout
-func (c *moduleConfig) WithStdout(stdout io.Writer) ModuleConfig {
- ret := c.clone()
- ret.stdout = stdout
- return ret
-}
-
-// WithWalltime implements ModuleConfig.WithWalltime
-func (c *moduleConfig) WithWalltime(walltime sys.Walltime, resolution sys.ClockResolution) ModuleConfig {
- ret := c.clone()
- ret.walltime = walltime
- ret.walltimeResolution = resolution
- return ret
-}
-
-// We choose arbitrary resolutions here because there's no perfect alternative. For example, according to the
-// source in time.go, windows monotonic resolution can be 15ms. This chooses arbitrarily 1us for wall time and
-// 1ns for monotonic. See RATIONALE.md for more context.
-
-// WithSysWalltime implements ModuleConfig.WithSysWalltime
-func (c *moduleConfig) WithSysWalltime() ModuleConfig {
- return c.WithWalltime(platform.Walltime, sys.ClockResolution(time.Microsecond.Nanoseconds()))
-}
-
-// WithNanotime implements ModuleConfig.WithNanotime
-func (c *moduleConfig) WithNanotime(nanotime sys.Nanotime, resolution sys.ClockResolution) ModuleConfig {
- ret := c.clone()
- ret.nanotime = nanotime
- ret.nanotimeResolution = resolution
- return ret
-}
-
-// WithSysNanotime implements ModuleConfig.WithSysNanotime
-func (c *moduleConfig) WithSysNanotime() ModuleConfig {
- return c.WithNanotime(platform.Nanotime, sys.ClockResolution(1))
-}
-
-// WithNanosleep implements ModuleConfig.WithNanosleep
-func (c *moduleConfig) WithNanosleep(nanosleep sys.Nanosleep) ModuleConfig {
- ret := *c // copy
- ret.nanosleep = nanosleep
- return &ret
-}
-
-// WithOsyield implements ModuleConfig.WithOsyield
-func (c *moduleConfig) WithOsyield(osyield sys.Osyield) ModuleConfig {
- ret := *c // copy
- ret.osyield = osyield
- return &ret
-}
-
-// WithSysNanosleep implements ModuleConfig.WithSysNanosleep
-func (c *moduleConfig) WithSysNanosleep() ModuleConfig {
- return c.WithNanosleep(platform.Nanosleep)
-}
-
-// WithRandSource implements ModuleConfig.WithRandSource
-func (c *moduleConfig) WithRandSource(source io.Reader) ModuleConfig {
- ret := c.clone()
- ret.randSource = source
- return ret
-}
-
-// toSysContext creates a baseline wasm.Context configured by ModuleConfig.
-func (c *moduleConfig) toSysContext() (sysCtx *internalsys.Context, err error) {
- var environ [][]byte // Intentionally doesn't pre-allocate to reduce logic to default to nil.
- // Same validation as syscall.Setenv for Linux
- for i := 0; i < len(c.environ); i += 2 {
- key, value := c.environ[i], c.environ[i+1]
- keyLen := len(key)
- if keyLen == 0 {
- err = errors.New("environ invalid: empty key")
- return
- }
- valueLen := len(value)
- result := make([]byte, keyLen+valueLen+1)
- j := 0
- for ; j < keyLen; j++ {
- if k := key[j]; k == '=' { // NUL enforced in NewContext
- err = errors.New("environ invalid: key contains '=' character")
- return
- } else {
- result[j] = k
- }
- }
- result[j] = '='
- copy(result[j+1:], value)
- environ = append(environ, result)
- }
-
- var fs []experimentalsys.FS
- var guestPaths []string
- if f, ok := c.fsConfig.(*fsConfig); ok {
- fs, guestPaths = f.preopens()
- }
-
- var listeners []*net.TCPListener
- if n := c.sockConfig; n != nil {
- if listeners, err = n.BuildTCPListeners(); err != nil {
- return
- }
- }
-
- return internalsys.NewContext(
- math.MaxUint32,
- c.args,
- environ,
- c.stdin,
- c.stdout,
- c.stderr,
- c.randSource,
- c.walltime, c.walltimeResolution,
- c.nanotime, c.nanotimeResolution,
- c.nanosleep, c.osyield,
- fs, guestPaths,
- listeners,
- )
-}