Source File
config.go
Belonging Package
github.com/tetratelabs/wazero
package wazeroimport (experimentalsysinternalsockinternalsys)// 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-memWithMemoryLimitPages(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 () RuntimeConfig {:= engineLessConfig.clone().engineKind = engineKindAutoreturn}type newEngine func(context.Context, api.CoreFeatures, filecache.Cache) wasm.Enginetype runtimeConfig struct {enabledFeatures api.CoreFeaturesmemoryLimitPages uint32memoryCapacityFromMax boolengineKind engineKinddwarfDisabled bool // negative as defaults to enablednewEngine newEnginecache CompilationCachestoreCustomSections boolensureTermination bool}// engineLessConfig helps avoid copy/pasting the wrong defaults.var engineLessConfig = &runtimeConfig{enabledFeatures: api.CoreFeaturesV2,memoryLimitPages: wasm.MemoryLimitPages,memoryCapacityFromMax: false,dwarfDisabled: false,}type engineKind intconst (engineKindAuto engineKind = iota - 1engineKindCompilerengineKindInterpreterengineKindCount)// 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-L36func () RuntimeConfig {:= engineLessConfig.clone().engineKind = engineKindCompilerreturn}// NewRuntimeConfigInterpreter interprets WebAssembly modules instead of compiling them into assembly.func () RuntimeConfig {:= engineLessConfig.clone().engineKind = engineKindInterpreterreturn}// clone makes a deep copy of this runtime config.func ( *runtimeConfig) () *runtimeConfig {:= * // copy except maps which share a refreturn &}// WithCoreFeatures implements RuntimeConfig.WithCoreFeaturesfunc ( *runtimeConfig) ( api.CoreFeatures) RuntimeConfig {:= .clone().enabledFeatures =return}// WithCloseOnContextDone implements RuntimeConfig.WithCloseOnContextDonefunc ( *runtimeConfig) ( bool) RuntimeConfig {:= .clone().ensureTermination =return}// WithMemoryLimitPages implements RuntimeConfig.WithMemoryLimitPagesfunc ( *runtimeConfig) ( uint32) RuntimeConfig {:= .clone()// This panics instead of returning an error as it is unlikely.if > wasm.MemoryLimitPages {panic(fmt.Errorf("memoryLimitPages invalid: %d > %d", , wasm.MemoryLimitPages))}.memoryLimitPages =return}// WithCompilationCache implements RuntimeConfig.WithCompilationCachefunc ( *runtimeConfig) ( CompilationCache) RuntimeConfig {:= .clone().cache =return}// WithMemoryCapacityFromMax implements RuntimeConfig.WithMemoryCapacityFromMaxfunc ( *runtimeConfig) ( bool) RuntimeConfig {:= .clone().memoryCapacityFromMax =return}// WithDebugInfoEnabled implements RuntimeConfig.WithDebugInfoEnabledfunc ( *runtimeConfig) ( bool) RuntimeConfig {:= .clone().dwarfDisabled = !return}// WithCustomSections implements RuntimeConfig.WithCustomSectionsfunc ( *runtimeConfig) ( bool) RuntimeConfig {:= .clone().storeCustomSections =return}// 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 CompiledModulevar _ 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 booltypeIDs []wasm.FunctionTypeID}// Name implements CompiledModule.Namefunc ( *compiledModule) () ( string) {if := .module.NameSection; != nil {= .ModuleName}return}// Close implements CompiledModule.Closefunc ( *compiledModule) (context.Context) error {.compiledEngine.DeleteCompiledModule(.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.ImportedFunctionsfunc ( *compiledModule) () []api.FunctionDefinition {return .module.ImportedFunctions()}// ExportedFunctions implements CompiledModule.ExportedFunctionsfunc ( *compiledModule) () map[string]api.FunctionDefinition {return .module.ExportedFunctions()}// ImportedMemories implements CompiledModule.ImportedMemoriesfunc ( *compiledModule) () []api.MemoryDefinition {return .module.ImportedMemories()}// ExportedMemories implements CompiledModule.ExportedMemoriesfunc ( *compiledModule) () map[string]api.MemoryDefinition {return .module.ExportedMemories()}// CustomSections implements CompiledModule.CustomSectionsfunc ( *compiledModule) () []api.CustomSection {:= make([]api.CustomSection, len(.module.CustomSections))for , := range .module.CustomSections {[] = &customSection{data: .Data, name: .Name}}return}// customSection implements wasm.CustomSectiontype customSection struct {internalapi.WazeroOnlyTypename stringdata []byte}// Name implements wasm.CustomSection.Namefunc ( *customSection) () string {return .name}// Data implements wasm.CustomSection.Datafunc ( *customSection) () []byte {return .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_stringWithArgs(...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_stringWithEnv(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/stderrWithStderr(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/stdinWithStdin(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/stdoutWithStdout(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 WithWalltimeWithSysWalltime() 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 WithNanotimeWithSysNanotime() 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 WithNanosleepWithSysNanosleep() 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 stringnameSet boolstartFunctions []stringstdin io.Readerstdout io.Writerstderr io.WriterrandSource io.Readerwalltime sys.WalltimewalltimeResolution sys.ClockResolutionnanotime sys.NanotimenanotimeResolution sys.ClockResolutionnanosleep sys.Nanosleeposyield sys.Osyieldargs [][]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 () ModuleConfig {return &moduleConfig{startFunctions: []string{"_start"},environKeys: map[string]int{},}}// clone makes a deep copy of this module config.func ( *moduleConfig) () *moduleConfig {:= * // copy except maps which share a ref.environKeys = make(map[string]int, len(.environKeys))for , := range .environKeys {.environKeys[] =}return &}// WithArgs implements ModuleConfig.WithArgsfunc ( *moduleConfig) ( ...string) ModuleConfig {:= .clone().args = toByteSlices()return}func toByteSlices( []string) ( [][]byte) {if len() == 0 {return}= make([][]byte, len())for , := range {[] = []byte()}return}// WithEnv implements ModuleConfig.WithEnvfunc ( *moduleConfig) (, string) ModuleConfig {:= .clone()// Check to see if this key already exists and update it.if , := .environKeys[]; {.environ[+1] = []byte() // environ is pair-indexed, so the value is 1 after the key.} else {.environKeys[] = len(.environ).environ = append(.environ, []byte(), []byte())}return}// WithFS implements ModuleConfig.WithFSfunc ( *moduleConfig) ( fs.FS) ModuleConfig {var FSConfigif != nil {= NewFSConfig().WithFSMount(, "")}return .WithFSConfig()}// WithFSConfig implements ModuleConfig.WithFSConfigfunc ( *moduleConfig) ( FSConfig) ModuleConfig {:= .clone().fsConfig =return}// WithName implements ModuleConfig.WithNamefunc ( *moduleConfig) ( string) ModuleConfig {:= .clone().nameSet = true.name =return}// WithStartFunctions implements ModuleConfig.WithStartFunctionsfunc ( *moduleConfig) ( ...string) ModuleConfig {:= .clone().startFunctions =return}// WithStderr implements ModuleConfig.WithStderrfunc ( *moduleConfig) ( io.Writer) ModuleConfig {:= .clone().stderr =return}// WithStdin implements ModuleConfig.WithStdinfunc ( *moduleConfig) ( io.Reader) ModuleConfig {:= .clone().stdin =return}// WithStdout implements ModuleConfig.WithStdoutfunc ( *moduleConfig) ( io.Writer) ModuleConfig {:= .clone().stdout =return}// WithWalltime implements ModuleConfig.WithWalltimefunc ( *moduleConfig) ( sys.Walltime, sys.ClockResolution) ModuleConfig {:= .clone().walltime =.walltimeResolution =return}// 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.WithSysWalltimefunc ( *moduleConfig) () ModuleConfig {return .WithWalltime(platform.Walltime, sys.ClockResolution(time.Microsecond.Nanoseconds()))}// WithNanotime implements ModuleConfig.WithNanotimefunc ( *moduleConfig) ( sys.Nanotime, sys.ClockResolution) ModuleConfig {:= .clone().nanotime =.nanotimeResolution =return}// WithSysNanotime implements ModuleConfig.WithSysNanotimefunc ( *moduleConfig) () ModuleConfig {return .WithNanotime(platform.Nanotime, sys.ClockResolution(1))}// WithNanosleep implements ModuleConfig.WithNanosleepfunc ( *moduleConfig) ( sys.Nanosleep) ModuleConfig {:= * // copy.nanosleep =return &}// WithOsyield implements ModuleConfig.WithOsyieldfunc ( *moduleConfig) ( sys.Osyield) ModuleConfig {:= * // copy.osyield =return &}// WithSysNanosleep implements ModuleConfig.WithSysNanosleepfunc ( *moduleConfig) () ModuleConfig {return .WithNanosleep(platform.Nanosleep)}// WithRandSource implements ModuleConfig.WithRandSourcefunc ( *moduleConfig) ( io.Reader) ModuleConfig {:= .clone().randSource =return}// toSysContext creates a baseline wasm.Context configured by ModuleConfig.func ( *moduleConfig) () ( *internalsys.Context, error) {var [][]byte // Intentionally doesn't pre-allocate to reduce logic to default to nil.// Same validation as syscall.Setenv for Linuxfor := 0; < len(.environ); += 2 {, := .environ[], .environ[+1]:= len()if == 0 {= errors.New("environ invalid: empty key")return}:= len():= make([]byte, ++1):= 0for ; < ; ++ {if := []; == '=' { // NUL enforced in NewContext= errors.New("environ invalid: key contains '=' character")return} else {[] =}}[] = '='copy([+1:], )= append(, )}var []experimentalsys.FSvar []stringif , := .fsConfig.(*fsConfig); {, = .preopens()}var []*net.TCPListenerif := .sockConfig; != nil {if , = .BuildTCPListeners(); != nil {return}}return internalsys.NewContext(math.MaxUint32,.args,,.stdin,.stdout,.stderr,.randSource,.walltime, .walltimeResolution,.nanotime, .nanotimeResolution,.nanosleep, .osyield,, ,,)}
![]() |
The pages are generated with Golds v0.8.2. (GOOS=linux GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds. |