package wazero

import (
	
	
	
	
	
	
	
	

	
	experimentalsys 
	
	
	
	internalsock 
	internalsys 
	
	
)

// 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 () RuntimeConfig {
	 := engineLessConfig.clone()
	.engineKind = engineKindAuto
	return 
}

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 (
	engineKindAuto engineKind = iota - 1
	engineKindCompiler
	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 () RuntimeConfig {
	 := engineLessConfig.clone()
	.engineKind = engineKindCompiler
	return 
}

// NewRuntimeConfigInterpreter interprets WebAssembly modules instead of compiling them into assembly.
func () RuntimeConfig {
	 := engineLessConfig.clone()
	.engineKind = engineKindInterpreter
	return 
}

// clone makes a deep copy of this runtime config.
func ( *runtimeConfig) () *runtimeConfig {
	 := * // copy except maps which share a ref
	return &
}

// WithCoreFeatures implements RuntimeConfig.WithCoreFeatures
func ( *runtimeConfig) ( api.CoreFeatures) RuntimeConfig {
	 := .clone()
	.enabledFeatures = 
	return 
}

// WithCloseOnContextDone implements RuntimeConfig.WithCloseOnContextDone
func ( *runtimeConfig) ( bool) RuntimeConfig {
	 := .clone()
	.ensureTermination = 
	return 
}

// WithMemoryLimitPages implements RuntimeConfig.WithMemoryLimitPages
func ( *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.WithCompilationCache
func ( *runtimeConfig) ( CompilationCache) RuntimeConfig {
	 := .clone()
	.cache = 
	return 
}

// WithMemoryCapacityFromMax implements RuntimeConfig.WithMemoryCapacityFromMax
func ( *runtimeConfig) ( bool) RuntimeConfig {
	 := .clone()
	.memoryCapacityFromMax = 
	return 
}

// WithDebugInfoEnabled implements RuntimeConfig.WithDebugInfoEnabled
func ( *runtimeConfig) ( bool) RuntimeConfig {
	 := .clone()
	.dwarfDisabled = !
	return 
}

// WithCustomSections implements RuntimeConfig.WithCustomSections
func ( *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 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 ( *compiledModule) () ( string) {
	if  := .module.NameSection;  != nil {
		 = .ModuleName
	}
	return
}

// Close implements CompiledModule.Close
func ( *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.ImportedFunctions
func ( *compiledModule) () []api.FunctionDefinition {
	return .module.ImportedFunctions()
}

// ExportedFunctions implements CompiledModule.ExportedFunctions
func ( *compiledModule) () map[string]api.FunctionDefinition {
	return .module.ExportedFunctions()
}

// ImportedMemories implements CompiledModule.ImportedMemories
func ( *compiledModule) () []api.MemoryDefinition {
	return .module.ImportedMemories()
}

// ExportedMemories implements CompiledModule.ExportedMemories
func ( *compiledModule) () map[string]api.MemoryDefinition {
	return .module.ExportedMemories()
}

// CustomSections implements CompiledModule.CustomSections
func ( *compiledModule) () []api.CustomSection {
	 := make([]api.CustomSection, len(.module.CustomSections))
	for ,  := range .module.CustomSections {
		[] = &customSection{data: .Data, name: .Name}
	}
	return 
}

// customSection implements wasm.CustomSection
type customSection struct {
	internalapi.WazeroOnlyType
	name string
	data []byte
}

// Name implements wasm.CustomSection.Name
func ( *customSection) () string {
	return .name
}

// Data implements wasm.CustomSection.Data
func ( *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_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 () 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.WithArgs
func ( *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.WithEnv
func ( *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.WithFS
func ( *moduleConfig) ( fs.FS) ModuleConfig {
	var  FSConfig
	if  != nil {
		 = NewFSConfig().WithFSMount(, "")
	}
	return .WithFSConfig()
}

// WithFSConfig implements ModuleConfig.WithFSConfig
func ( *moduleConfig) ( FSConfig) ModuleConfig {
	 := .clone()
	.fsConfig = 
	return 
}

// WithName implements ModuleConfig.WithName
func ( *moduleConfig) ( string) ModuleConfig {
	 := .clone()
	.nameSet = true
	.name = 
	return 
}

// WithStartFunctions implements ModuleConfig.WithStartFunctions
func ( *moduleConfig) ( ...string) ModuleConfig {
	 := .clone()
	.startFunctions = 
	return 
}

// WithStderr implements ModuleConfig.WithStderr
func ( *moduleConfig) ( io.Writer) ModuleConfig {
	 := .clone()
	.stderr = 
	return 
}

// WithStdin implements ModuleConfig.WithStdin
func ( *moduleConfig) ( io.Reader) ModuleConfig {
	 := .clone()
	.stdin = 
	return 
}

// WithStdout implements ModuleConfig.WithStdout
func ( *moduleConfig) ( io.Writer) ModuleConfig {
	 := .clone()
	.stdout = 
	return 
}

// WithWalltime implements ModuleConfig.WithWalltime
func ( *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.WithSysWalltime
func ( *moduleConfig) () ModuleConfig {
	return .WithWalltime(platform.Walltime, sys.ClockResolution(time.Microsecond.Nanoseconds()))
}

// WithNanotime implements ModuleConfig.WithNanotime
func ( *moduleConfig) ( sys.Nanotime,  sys.ClockResolution) ModuleConfig {
	 := .clone()
	.nanotime = 
	.nanotimeResolution = 
	return 
}

// WithSysNanotime implements ModuleConfig.WithSysNanotime
func ( *moduleConfig) () ModuleConfig {
	return .WithNanotime(platform.Nanotime, sys.ClockResolution(1))
}

// WithNanosleep implements ModuleConfig.WithNanosleep
func ( *moduleConfig) ( sys.Nanosleep) ModuleConfig {
	 := * // copy
	.nanosleep = 
	return &
}

// WithOsyield implements ModuleConfig.WithOsyield
func ( *moduleConfig) ( sys.Osyield) ModuleConfig {
	 := * // copy
	.osyield = 
	return &
}

// WithSysNanosleep implements ModuleConfig.WithSysNanosleep
func ( *moduleConfig) () ModuleConfig {
	return .WithNanosleep(platform.Nanosleep)
}

// WithRandSource implements ModuleConfig.WithRandSource
func ( *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 Linux
	for  := 0;  < len(.environ);  += 2 {
		,  := .environ[], .environ[+1]
		 := len()
		if  == 0 {
			 = errors.New("environ invalid: empty key")
			return
		}
		 := len()
		 := make([]byte, ++1)
		 := 0
		for ;  < ; ++ {
			if  := [];  == '=' { // NUL enforced in NewContext
				 = errors.New("environ invalid: key contains '=' character")
				return
			} else {
				[] = 
			}
		}
		[] = '='
		copy([+1:], )
		 = append(, )
	}

	var  []experimentalsys.FS
	var  []string
	if ,  := .fsConfig.(*fsConfig);  {
		,  = .preopens()
	}

	var  []*net.TCPListener
	if  := .sockConfig;  != nil {
		if ,  = .BuildTCPListeners();  != nil {
			return
		}
	}

	return internalsys.NewContext(
		math.MaxUint32,
		.args,
		,
		.stdin,
		.stdout,
		.stderr,
		.randSource,
		.walltime, .walltimeResolution,
		.nanotime, .nanotimeResolution,
		.nanosleep, .osyield,
		, ,
		,
	)
}