From 2664b1eb62a2ab2e136dcab59235bb45d5d2c503 Mon Sep 17 00:00:00 2001 From: Crypt Keeper <64215+codefromthecrypt@users.noreply.github.com> Date: Sat, 2 Apr 2022 06:42:36 +0800 Subject: [PATCH] Simplifies API per feedback (#427) During #425, @neilalexander gave constructive feedback that the API is both moving fast, and not good enough yet. This attempts to reduce the incidental complexity at the cost of a little conflation. ### odd presence of `wasm` and `wasi` packages -> `api` package We had public API packages in wasm and wasi, which helped us avoid leaking too many internals as public. That these had names that look like there should be implementations in them cause unnecessary confusion. This squashes both into one package "api" which has no package collission with anything. We've long struggled with the poorly specified and non-uniformly implemented WASI specification. Trying to bring visibility to its constraints knowing they are routinely invalid taints our API for no good reason. This removes all `WASI` commands for a default to invoke the function `_start` if it exists. In doing so, there's only one path to start a module. Moreover, this puts all wasi code in a top-level package "wasi" as it isn't re-imported by any internal types. ### Reuse of Module for pre and post instantiation to `Binary` -> `Module` Module is defined by WebAssembly in many phases, from decoded to instantiated. However, using the same noun in multiple packages is very confusing. We at one point tried a name "DecodedModule" or "InstantiatedModule", but this is a fools errand. By deviating slightly from the spec we can make it unambiguous what a module is. This make a result of compilation a `Binary`, retaining `Module` for an instantiated one. In doing so, there's no longer any name conflicts whatsoever. ### Confusion about config -> `ModuleConfig` Also caused by splitting wasm into wasm+wasi is configuration. This conflates both into the same type `ModuleConfig` as it is simpler than trying to explain a "will never be finished" api of wasi snapshot-01 in routine use of WebAssembly. In other words, this further moves WASI out of the foreground as it has been nothing but burden. ```diff --- a/README.md +++ b/README.md @@ -49,8 +49,8 @@ For example, here's how you can allow WebAssembly modules to read -wm, err := r.InstantiateModule(wazero.WASISnapshotPreview1()) -defer wm.Close() +wm, err := wasi.InstantiateSnapshotPreview1(r) +defer wm.Close() -sysConfig := wazero.NewSysConfig().WithFS(os.DirFS("/work/home")) -module, err := wazero.StartWASICommandWithConfig(r, compiled, sysConfig) +config := wazero.ModuleConfig().WithFS(os.DirFS("/work/home")) +module, err := r.InstantiateModule(binary, config) defer module.Close() ... ``` --- RATIONALE.md | 50 +- README.md | 10 +- {wasm => api}/wasm.go | 12 +- {wasm => api}/wasm_test.go | 18 +- builder.go | 36 +- builder_test.go | 106 +- config.go | 155 +- config_test.go | 80 +- examples/add_test.go | 2 +- examples/fibonacci_test.go | 7 +- examples/file_system_test.go | 13 +- examples/host_func_test.go | 25 +- examples/simple_test.go | 2 +- examples/stdio_test.go | 13 +- examples/wasi_test.go | 16 +- internal/asm/amd64/impl.go | 2 +- internal/asm/arm64/consts.go | 3 + internal/testing/enginetest/enginetest.go | 18 +- internal/wasi/wasi.go | 1555 --------------- internal/wasm/binary/code.go | 2 +- internal/wasm/binary/code_test.go | 2 +- internal/wasm/binary/const_expr.go | 2 +- internal/wasm/binary/data.go | 2 +- internal/wasm/binary/decoder.go | 4 +- internal/wasm/binary/decoder_test.go | 2 +- internal/wasm/binary/element.go | 2 +- internal/wasm/binary/encoder.go | 2 +- internal/wasm/binary/encoder_test.go | 2 +- internal/wasm/binary/export.go | 4 +- internal/wasm/binary/export_test.go | 2 +- internal/wasm/binary/function.go | 8 +- internal/wasm/binary/function_test.go | 2 +- internal/wasm/binary/global.go | 6 +- internal/wasm/binary/global_test.go | 2 +- internal/wasm/binary/import.go | 4 +- internal/wasm/binary/import_test.go | 2 +- internal/wasm/binary/memory.go | 6 +- internal/wasm/binary/memory_test.go | 6 +- internal/wasm/binary/names.go | 4 +- internal/wasm/binary/names_test.go | 2 +- internal/wasm/binary/section.go | 20 +- internal/wasm/binary/section_test.go | 2 +- internal/wasm/binary/table.go | 4 +- internal/wasm/binary/table_test.go | 2 +- internal/wasm/binary/value.go | 2 +- internal/wasm/binary/value_test.go | 2 +- internal/wasm/counts.go | 2 +- internal/wasm/counts_test.go | 6 +- internal/wasm/engine.go | 6 +- internal/wasm/errors.go | 2 +- internal/wasm/features.go | 4 +- internal/wasm/features_test.go | 2 +- internal/wasm/func_validation.go | 2 +- internal/wasm/func_validation_test.go | 2 +- internal/wasm/global.go | 64 +- internal/wasm/global_test.go | 44 +- internal/wasm/gofunc.go | 6 +- internal/wasm/gofunc_test.go | 14 +- internal/wasm/host.go | 2 +- internal/wasm/host_test.go | 15 +- internal/wasm/instruction.go | 2 +- internal/wasm/interpreter/interpreter.go | 16 +- internal/wasm/interpreter/interpreter_test.go | 2 +- internal/wasm/jit/arch_amd64.go | 2 +- internal/wasm/jit/arch_arm64.go | 2 +- internal/wasm/jit/arch_other.go | 2 +- internal/wasm/jit/compiler.go | 134 +- internal/wasm/jit/engine.go | 24 +- internal/wasm/jit/engine_test.go | 2 +- internal/wasm/jit/jit_controlflow_test.go | 2 +- internal/wasm/jit/jit_global_test.go | 2 +- internal/wasm/jit/jit_impl_amd64.go | 2 +- internal/wasm/jit/jit_impl_amd64_test.go | 2 +- internal/wasm/jit/jit_impl_arm64.go | 2 +- internal/wasm/jit/jit_initialization_test.go | 2 +- internal/wasm/jit/jit_memory_test.go | 2 +- internal/wasm/jit/jit_test.go | 2 +- internal/wasm/jit/jit_value_location.go | 76 +- internal/wasm/memory.go | 30 +- internal/wasm/memory_test.go | 2 +- internal/wasm/module.go | 26 +- internal/wasm/module_context.go | 56 +- internal/wasm/module_context_test.go | 2 +- internal/wasm/module_test.go | 6 +- internal/wasm/store.go | 10 +- internal/wasm/store_test.go | 30 +- internal/wasm/sys.go | 2 +- internal/wasm/sys_test.go | 2 +- internal/wasm/table.go | 2 +- internal/wasm/table_test.go | 2 +- internal/wasm/text/decoder.go | 14 +- internal/wasm/text/decoder_test.go | 55 +- internal/wasm/text/errors.go | 2 +- internal/wasm/text/errors_test.go | 2 +- internal/wasm/text/func_parser.go | 4 +- internal/wasm/text/func_parser_test.go | 2 +- internal/wasm/text/index_namespace.go | 6 +- internal/wasm/text/index_namespace_test.go | 2 +- internal/wasm/text/memory_parser.go | 8 +- internal/wasm/text/memory_parser_test.go | 2 +- internal/wasm/text/type_parser.go | 6 +- internal/wasm/text/type_parser_test.go | 2 +- internal/wasm/text/typeuse_parser.go | 8 +- internal/wasm/text/typeuse_parser_test.go | 2 +- internal/wazeroir/compiler.go | 2 +- internal/wazeroir/signature.go | 2 +- internal/wazeroir/wazeroir.go | 2 +- sys/sys.go | 6 +- tests/bench/bench_test.go | 24 +- tests/bench/memory_bench_test.go | 2 +- tests/engine/adhoc_test.go | 40 +- tests/engine/hammer_test.go | 18 +- tests/post1_0/post1_0_test.go | 6 +- tests/spectest/spec_test.go | 14 +- vs/bench_fac_iter_test.go | 8 +- vs/codec_test.go | 14 +- wasi.go | 120 -- wasi/errno.go | 261 +++ {examples => wasi}/testdata/wasi_arg.wasm | Bin {examples => wasi}/testdata/wasi_arg.wat | 0 wasi/usage_test.go | 42 + wasi/wasi.go | 1774 ++++++++++++++--- .../wasi_test.go => wasi/wasi_bench_test.go | 20 +- {internal/wasi => wasi}/wasi_test.go | 687 +++---- wasi_test.go | 93 - wasm.go | 121 +- wasm_test.go | 170 +- 127 files changed, 3153 insertions(+), 3230 deletions(-) rename {wasm => api}/wasm.go (96%) rename {wasm => api}/wasm_test.go (75%) delete mode 100644 internal/wasi/wasi.go delete mode 100644 wasi.go create mode 100644 wasi/errno.go rename {examples => wasi}/testdata/wasi_arg.wasm (100%) rename {examples => wasi}/testdata/wasi_arg.wat (100%) create mode 100644 wasi/usage_test.go rename tests/bench/wasi_test.go => wasi/wasi_bench_test.go (70%) rename {internal/wasi => wasi}/wasi_test.go (71%) delete mode 100644 wasi_test.go diff --git a/RATIONALE.md b/RATIONALE.md index ff6a0d31..5e1aea21 100644 --- a/RATIONALE.md +++ b/RATIONALE.md @@ -4,7 +4,7 @@ wazero uses internal packages extensively to balance API compatability desires for end users with the need to safely share internals between compilers. -The end-user API includes the packages `wazero` `wasm` `wasi` with `Config` structs. Everything else is internal. +End-user packages include `wazero`,with `Config` structs, and `api`, with shared types. Everything else is internal. ### Internal packages Most code in wazero is internal, and it is acknowledged that this prevents external implementation of facets such as @@ -12,7 +12,7 @@ compilers or decoding. It also prevents splitting this code into separate reposi This also adds work as more code needs to be centrally reviewed. However, the alternative is neither secure nor viable. To allow external implementation would require exporting symbols -public, such as the `CodeSection`, which can easily create bugs. Moreover there's a high drift risk for any attempt at +public, such as the `CodeSection`, which can easily create bugs. Moreover, there's a high drift risk for any attempt at external implementations, compounded not just by wazero's code organization, but also the fast moving Wasm and WASI specifications. @@ -29,19 +29,18 @@ codebase productive. ### Avoiding cyclic dependencies wazero shares constants and interfaces with internal code by a sharing pattern described below: -* shared interfaces and constants go in a package under root. - * Ex. package `wasi` -> `/wasi/*.go` -* user code that refer to that package go into the flat root package `wazero`. - * Ex. `StartWASICommand` -> `/wasi.go` -* implementation code begin in a corresponding package under `/internal`. - * Ex package `internalwasi` -> `/internal/wasi/*.go` +* shared interfaces and constants go in one package under root: `api`. +* user APIs and structs depend on `api` and go into the root package `wazero`. + * Ex. `InstantiateModule` -> `/wasm.go` depends on the type `api.Module`. +* implementation code can also depend on `api` in a corresponding package under `/internal`. + * Ex package `wasm` -> `/internal/wasm/*.go` and can depend on the type `api.Module`. The above guarantees no cyclic dependencies at the cost of having to re-define symbols that exist in both packages. -For example, if `Store` is a type the user needs access to, it is narrowed by a cover type in the `wazero` package: +For example, if `wasm.Store` is a type the user needs access to, it is narrowed by a cover type in the `wazero`: ```go -type Store struct { - s *internalwasm.Store +type Runtime struct { + s *wasm.Store } ``` @@ -51,17 +50,24 @@ limited to only a few functions. ### Avoiding security bugs In order to avoid security flaws such as code insertion, nothing in the public API is permitted to write directly to any -mutable symbol in the internal package. For example, the packages `wasi` and `wasm` are shared internally. To ensure -immutability, these are not allowed to contain any mutable public symbol, such as a slice or a struct with an exported +mutable symbol in the internal package. For example, the package `api` is shared with internal code. To ensure +immutability, the `api` package cannot contain any mutable public symbol, such as a slice or a struct with an exported field. In practice, this means shared functionality like memory mutation need to be implemented by interfaces. -Ex. `wasm.Memory` protects access by exposing functions like `WriteFloat64Le` instead of exporting a buffer (`[]byte`). +Ex. `api.Memory` protects access by exposing functions like `WriteFloat64Le` instead of exporting a buffer (`[]byte`). Ex. There is no exported symbol for the `[]byte` representing the `CodeSection` Besides security, this practice prevents other bugs and allows centralization of validation logic such as decoding Wasm. +## Why does InstantiateModule call "_start" by default? +We formerly had functions like `StartWASICommand` that would verify preconditions and start WASI's "_start" command. +However, this caused confusion because both many languages compiled a WASI dependency, and many did so inconsistently. + +That said, if "_start" isn't called, it causes issues in TinyGo, as it needs this in order to implement panic. To deal +with this a different way, we have a configuration to call any start functions that exist, which defaults to "_start". + ## Runtime == Engine+Store wazero defines a single user-type which combines the specification concept of `Store` with the unspecified `Engine` which manages them. @@ -93,7 +99,7 @@ Unfortunately, (WASI Snapshot Preview 1)[https://github.com/WebAssembly/WASI/blo This section describes how Wazero interprets and implements the semantics of several WASI APIs that may be interpreted differently by different wasm runtimes. Those APIs may affect the portability of a WASI application. -### Why aren't all WASI rules enforced? +### Why aren't WASI rules enforced? The [snapshot-01](https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md) version of WASI has a number of rules for a "command module", but only the memory export rule is enforced. If a "_start" function exists, it @@ -106,7 +112,7 @@ The reason for the exceptions are that implementations aren't following the rule loaded by wapc-go don't always define a "_start" function. Since "snapshot-01" is not a proper version, and certainly not a W3C recommendation, there's no sense in breaking users over matters like this. -### Why is `SysConfig` decoupled from WASI? +### Why is I/O configuration not coupled to WASI? WebAssembly System Interfaces (WASI) is a formalization of a practice that can be done anyway: Define a host function to access a system interface, such as writing to STDOUT. WASI stalled at snapshot-01 and as of early 2022, is being @@ -117,11 +123,11 @@ decoupling. For example, if code uses two different functions to call `fd_write` centralized and decoupled. Otherwise, calls using the same file descriptor number will end up writing to different places. -In short, wazero defined system configuration in `SysConfig`, not a WASI type. This allows end-users to switch from +In short, wazero defined system configuration in `ModuleConfig`, not a WASI type. This allows end-users to switch from one spec to another with minimal impact. This has other helpful benefits, as centralized resources are simpler to close coherently (ex via `Module.Close`). -### Background on `SysConfig` design +### Background on `ModuleConfig` design WebAssembly 1.0 (20191205) specifies some aspects to control isolation between modules ([sandboxing](https://en.wikipedia.org/wiki/Sandbox_(computer_security))). For example, `wasm.Memory` has size constraints and each instance of it is isolated from each other. While `wasm.Memory` can be shared, by exporting it, it is not exported by default. In fact a WebAssembly Module (Wasm) has no memory by @@ -148,10 +154,10 @@ WASI has reached a stage near W3C recommendation. Even if it did, module authors write to console, as they can define their own host functions, such as they did before WASI existed. wazero aims to serve Go developers as a primary function, and help them transition between WASI specifications. In -order to do this, we have to allow top-level configuration. To ensure isolation by default, `SysConfig` has WithXXX -that override defaults to no-op or empty. One `SysConfig` instance is used regardless of how many times the same WASI +order to do this, we have to allow top-level configuration. To ensure isolation by default, `ModuleConfig` has WithXXX +that override defaults to no-op or empty. One `ModuleConfig` instance is used regardless of how many times the same WASI functions are imported. The nil defaults allow safe concurrency in these situations, as well lower the cost when they -are never used. Finally, a one-to-one mapping with `Module` allows the module to close the `SysConfig` instead of +are never used. Finally, a one-to-one mapping with `Module` allows the module to close the `ModuleConfig` instead of confusing users with another API to close. Naming, defaults and validation rules of aspects like `STDIN` and `Environ` are intentionally similar to other Go @@ -161,7 +167,7 @@ working with real system calls are neither relevant nor safe to inherit: For exa from a real file descriptor ("/dev/null"). Defaulting to this, vs reading `io.EOF`, would be unsafe as it can exhaust file descriptors if resources aren't managed properly. In other words, blind copying of defaults isn't wise as it can violate isolation or endanger the embedding process. In summary, we try to be similar to normal Go code, but often need -act differently and document `SysConfig` is more about emulating, not necessarily performing real system calls. +act differently and document `ModuleConfig` is more about emulating, not necessarily performing real system calls. ### FdPrestatDirName diff --git a/README.md b/README.md index 8656f215..362ceb6e 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ func main() { source, _ := os.ReadFile("./tests/bench/testdata/fac.wasm") // Instantiate the module and return its exported functions - module, _ := wazero.NewRuntime().InstantiateModuleFromSource(source) + module, _ := wazero.NewRuntime().InstantiateModuleFromCode(source) defer module.Close() // Discover 7! is 5040 @@ -46,11 +46,11 @@ how WebAssembly programs interact with the host embedding them. For example, here's how you can allow WebAssembly modules to read "/work/home/a.txt" as "/a.txt" or "./a.txt": ```go -wasi, err := r.InstantiateModule(wazero.WASISnapshotPreview1()) -defer wasi.Close() +wm, err := wasi.InstantiateSnapshotPreview1(r) +defer wm.Close() -sysConfig := wazero.NewSysConfig().WithFS(os.DirFS("/work/home")) -module, err := wazero.StartWASICommandWithConfig(r, compiled, sysConfig) +config := wazero.ModuleConfig().WithFS(os.DirFS("/work/home")) +module, err := r.InstantiateModule(binary, config) defer module.Close() ... ``` diff --git a/wasm/wasm.go b/api/wasm.go similarity index 96% rename from wasm/wasm.go rename to api/wasm.go index 5645f915..9a6e25fa 100644 --- a/wasm/wasm.go +++ b/api/wasm.go @@ -1,5 +1,5 @@ -// Package wasm includes constants and interfaces used by both public and internal APIs. -package wasm +// Package api includes constants and interfaces used by both end-users and internal implementations. +package api import ( "context" @@ -23,8 +23,8 @@ import ( // // Ex. Given a Text Format type use (param f64) (result f64), conversion is necessary. // -// results, _ := fn(ctx, wasm.EncodeF64(input)) -// result := wasm.DecodeF64(result[0]) +// results, _ := fn(ctx, api.EncodeF64(input)) +// result := api.DecodeF64(result[0]) // // Note: This is a type alias as it is easier to encode and decode in the binary format. // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#binary-valtype @@ -133,7 +133,7 @@ type Function interface { // --snip-- // // To ensure context propagation in a host function body, pass the `ctx` parameter: - // hostFunction := func(m wasm.Module, offset, byteCount uint32) uint32 { + // hostFunction := func(m api.Module, offset, byteCount uint32) uint32 { // fn = m.ExportedFunction("__read") // results, err := fn(m, offset, byteCount) // --snip-- @@ -154,7 +154,7 @@ type Function interface { // safe cast to find out if the value can change. Ex. // // offset := module.ExportedGlobal("memory.offset") -// if _, ok := offset.(wasm.MutableGlobal); ok { +// if _, ok := offset.(api.MutableGlobal); ok { // // value can change // } else { // // value is constant diff --git a/wasm/wasm_test.go b/api/wasm_test.go similarity index 75% rename from wasm/wasm_test.go rename to api/wasm_test.go index 2e5c6953..9d0d82f7 100644 --- a/wasm/wasm_test.go +++ b/api/wasm_test.go @@ -1,4 +1,4 @@ -package wasm +package api import ( "fmt" @@ -40,11 +40,11 @@ func TestEncodeDecodeF32(t *testing.T) { } { t.Run(fmt.Sprintf("%f", v), func(t *testing.T) { encoded := EncodeF32(v) - decoded := DecodeF32(encoded) - if math.IsNaN(float64(decoded)) { // NaN cannot be compared with themselves, so we have to use IsNaN - require.True(t, math.IsNaN(float64(decoded))) + binary := DecodeF32(encoded) + if math.IsNaN(float64(binary)) { // NaN cannot be compared with themselves, so we have to use IsNaN + require.True(t, math.IsNaN(float64(binary))) } else { - require.Equal(t, v, decoded) + require.Equal(t, v, binary) } }) } @@ -64,11 +64,11 @@ func TestEncodeDecodeF64(t *testing.T) { } { t.Run(fmt.Sprintf("%f", v), func(t *testing.T) { encoded := EncodeF64(v) - decoded := DecodeF64(encoded) - if math.IsNaN(decoded) { // cannot use require.Equal as NaN by definition doesn't equal itself - require.True(t, math.IsNaN(decoded)) + binary := DecodeF64(encoded) + if math.IsNaN(binary) { // cannot use require.Equal as NaN by definition doesn't equal itself + require.True(t, math.IsNaN(binary)) } else { - require.Equal(t, v, decoded) + require.Equal(t, v, binary) } }) } diff --git a/builder.go b/builder.go index 0cc42a1b..1fd36290 100644 --- a/builder.go +++ b/builder.go @@ -1,8 +1,8 @@ package wazero import ( - internalwasm "github.com/tetratelabs/wazero/internal/wasm" - "github.com/tetratelabs/wazero/wasm" + "github.com/tetratelabs/wazero/api" + "github.com/tetratelabs/wazero/internal/wasm" ) // ModuleBuilder is a way to define a WebAssembly 1.0 (20191205) in Go. @@ -25,7 +25,7 @@ import ( // Note: Insertion order is not retained. Anything defined by this builder is sorted lexicographically on Build. type ModuleBuilder interface { - // ExportFunction adds a function written in Go, which a WebAssembly Module can import. + // ExportFunction adds a function written in Go, which a WebAssembly module can import. // // * name - the name to export. Ex "random_get" // * goFunc - the `func` to export. @@ -39,24 +39,24 @@ type ModuleBuilder interface { // return x + y // } // - // Host functions may also have an initial parameter (param[0]) of type context.Context or wasm.Module. + // Host functions may also have an initial parameter (param[0]) of type context.Context or api.Module. // // Ex. This uses a Go Context: // - // addInts := func(ctx context.Context, x uint32, uint32) uint32 { + // addInts := func(m context.Context, x uint32, uint32) uint32 { // // add a little extra if we put some in the context! - // return x + y + ctx.Value(extraKey).(uint32) + // return x + y + m.Value(extraKey).(uint32) // } // - // The most sophisticated context is wasm.Module, which allows access to the Go context, but also + // The most sophisticated context is api.Module, which allows access to the Go context, but also // allows writing to memory. This is important because there are only numeric types in Wasm. The only way to share other // data is via writing memory and sharing offsets. // // Ex. This reads the parameters from! // - // addInts := func(ctx wasm.Module, offset uint32) uint32 { - // x, _ := ctx.Memory().ReadUint32Le(offset) - // y, _ := ctx.Memory().ReadUint32Le(offset + 4) // 32 bits == 4 bytes! + // addInts := func(m api.Module, offset uint32) uint32 { + // x, _ := m.Memory().ReadUint32Le(offset) + // y, _ := m.Memory().ReadUint32Le(offset + 4) // 32 bits == 4 bytes! // return x + y // } // @@ -67,13 +67,13 @@ type ModuleBuilder interface { // ExportFunctions is a convenience that calls ExportFunction for each key/value in the provided map. ExportFunctions(nameToGoFunc map[string]interface{}) ModuleBuilder - // Build returns a Module to instantiate, or returns an error if any of the configuration is invalid. - Build() (*Module, error) + // Build returns a module to instantiate, or returns an error if any of the configuration is invalid. + Build() (*CompiledCode, error) // Instantiate is a convenience that calls Build, then Runtime.InstantiateModule // // Note: Fields in the builder are copied during instantiation: Later changes do not affect the instantiated result. - Instantiate() (wasm.Module, error) + Instantiate() (api.Module, error) } // moduleBuilder implements ModuleBuilder @@ -107,20 +107,20 @@ func (b *moduleBuilder) ExportFunctions(nameToGoFunc map[string]interface{}) Mod } // Build implements ModuleBuilder.Build -func (b *moduleBuilder) Build() (*Module, error) { +func (b *moduleBuilder) Build() (*CompiledCode, error) { // TODO: we can use r.enabledFeatures to fail early on things like mutable globals - if module, err := internalwasm.NewHostModule(b.moduleName, b.nameToGoFunc); err != nil { + if module, err := wasm.NewHostModule(b.moduleName, b.nameToGoFunc); err != nil { return nil, err } else { - return &Module{name: b.moduleName, module: module}, nil + return &CompiledCode{module: module}, nil } } // Instantiate implements ModuleBuilder.Instantiate -func (b *moduleBuilder) Instantiate() (wasm.Module, error) { +func (b *moduleBuilder) Instantiate() (api.Module, error) { if module, err := b.Build(); err != nil { return nil, err } else { - return b.r.InstantiateModule(module) + return b.r.InstantiateModuleWithConfig(module, NewModuleConfig().WithName(b.moduleName)) } } diff --git a/builder_test.go b/builder_test.go index e66a49d4..cac69b14 100644 --- a/builder_test.go +++ b/builder_test.go @@ -6,13 +6,13 @@ import ( "github.com/stretchr/testify/require" - internalwasm "github.com/tetratelabs/wazero/internal/wasm" - "github.com/tetratelabs/wazero/wasm" + "github.com/tetratelabs/wazero/api" + "github.com/tetratelabs/wazero/internal/wasm" ) // TestNewModuleBuilder_Build only covers a few scenarios to avoid duplicating tests in internal/wasm/host_test.go func TestNewModuleBuilder_Build(t *testing.T) { - i32, i64 := wasm.ValueTypeI32, wasm.ValueTypeI64 + i32, i64 := api.ValueTypeI32, api.ValueTypeI64 uint32_uint32 := func(uint32) uint32 { return 0 @@ -26,38 +26,38 @@ func TestNewModuleBuilder_Build(t *testing.T) { tests := []struct { name string input func(Runtime) ModuleBuilder - expected *internalwasm.Module + expected *wasm.Module }{ { name: "empty", input: func(r Runtime) ModuleBuilder { return r.NewModuleBuilder("") }, - expected: &internalwasm.Module{}, + expected: &wasm.Module{}, }, { name: "only name", input: func(r Runtime) ModuleBuilder { return r.NewModuleBuilder("env") }, - expected: &internalwasm.Module{NameSection: &internalwasm.NameSection{ModuleName: "env"}}, + expected: &wasm.Module{NameSection: &wasm.NameSection{ModuleName: "env"}}, }, { name: "ExportFunction", input: func(r Runtime) ModuleBuilder { return r.NewModuleBuilder("").ExportFunction("1", uint32_uint32) }, - expected: &internalwasm.Module{ - TypeSection: []*internalwasm.FunctionType{ - {Params: []wasm.ValueType{i32}, Results: []wasm.ValueType{i32}}, + expected: &wasm.Module{ + TypeSection: []*wasm.FunctionType{ + {Params: []api.ValueType{i32}, Results: []api.ValueType{i32}}, }, - FunctionSection: []internalwasm.Index{0}, + FunctionSection: []wasm.Index{0}, HostFunctionSection: []*reflect.Value{&fnUint32_uint32}, - ExportSection: map[string]*internalwasm.Export{ - "1": {Name: "1", Type: internalwasm.ExternTypeFunc, Index: 0}, + ExportSection: map[string]*wasm.Export{ + "1": {Name: "1", Type: wasm.ExternTypeFunc, Index: 0}, }, - NameSection: &internalwasm.NameSection{ - FunctionNames: internalwasm.NameMap{{Index: 0, Name: "1"}}, + NameSection: &wasm.NameSection{ + FunctionNames: wasm.NameMap{{Index: 0, Name: "1"}}, }, }, }, @@ -66,17 +66,17 @@ func TestNewModuleBuilder_Build(t *testing.T) { input: func(r Runtime) ModuleBuilder { return r.NewModuleBuilder("").ExportFunction("1", uint32_uint32).ExportFunction("1", uint64_uint32) }, - expected: &internalwasm.Module{ - TypeSection: []*internalwasm.FunctionType{ - {Params: []wasm.ValueType{i64}, Results: []wasm.ValueType{i32}}, + expected: &wasm.Module{ + TypeSection: []*wasm.FunctionType{ + {Params: []api.ValueType{i64}, Results: []api.ValueType{i32}}, }, - FunctionSection: []internalwasm.Index{0}, + FunctionSection: []wasm.Index{0}, HostFunctionSection: []*reflect.Value{&fnUint64_uint32}, - ExportSection: map[string]*internalwasm.Export{ - "1": {Name: "1", Type: internalwasm.ExternTypeFunc, Index: 0}, + ExportSection: map[string]*wasm.Export{ + "1": {Name: "1", Type: wasm.ExternTypeFunc, Index: 0}, }, - NameSection: &internalwasm.NameSection{ - FunctionNames: internalwasm.NameMap{{Index: 0, Name: "1"}}, + NameSection: &wasm.NameSection{ + FunctionNames: wasm.NameMap{{Index: 0, Name: "1"}}, }, }, }, @@ -86,19 +86,19 @@ func TestNewModuleBuilder_Build(t *testing.T) { // Intentionally out of order return r.NewModuleBuilder("").ExportFunction("2", uint64_uint32).ExportFunction("1", uint32_uint32) }, - expected: &internalwasm.Module{ - TypeSection: []*internalwasm.FunctionType{ - {Params: []wasm.ValueType{i32}, Results: []wasm.ValueType{i32}}, - {Params: []wasm.ValueType{i64}, Results: []wasm.ValueType{i32}}, + expected: &wasm.Module{ + TypeSection: []*wasm.FunctionType{ + {Params: []api.ValueType{i32}, Results: []api.ValueType{i32}}, + {Params: []api.ValueType{i64}, Results: []api.ValueType{i32}}, }, - FunctionSection: []internalwasm.Index{0, 1}, + FunctionSection: []wasm.Index{0, 1}, HostFunctionSection: []*reflect.Value{&fnUint32_uint32, &fnUint64_uint32}, - ExportSection: map[string]*internalwasm.Export{ - "1": {Name: "1", Type: internalwasm.ExternTypeFunc, Index: 0}, - "2": {Name: "2", Type: internalwasm.ExternTypeFunc, Index: 1}, + ExportSection: map[string]*wasm.Export{ + "1": {Name: "1", Type: wasm.ExternTypeFunc, Index: 0}, + "2": {Name: "2", Type: wasm.ExternTypeFunc, Index: 1}, }, - NameSection: &internalwasm.NameSection{ - FunctionNames: internalwasm.NameMap{{Index: 0, Name: "1"}, {Index: 1, Name: "2"}}, + NameSection: &wasm.NameSection{ + FunctionNames: wasm.NameMap{{Index: 0, Name: "1"}, {Index: 1, Name: "2"}}, }, }, }, @@ -110,19 +110,19 @@ func TestNewModuleBuilder_Build(t *testing.T) { "2": uint64_uint32, }) }, - expected: &internalwasm.Module{ - TypeSection: []*internalwasm.FunctionType{ - {Params: []wasm.ValueType{i32}, Results: []wasm.ValueType{i32}}, - {Params: []wasm.ValueType{i64}, Results: []wasm.ValueType{i32}}, + expected: &wasm.Module{ + TypeSection: []*wasm.FunctionType{ + {Params: []api.ValueType{i32}, Results: []api.ValueType{i32}}, + {Params: []api.ValueType{i64}, Results: []api.ValueType{i32}}, }, - FunctionSection: []internalwasm.Index{0, 1}, + FunctionSection: []wasm.Index{0, 1}, HostFunctionSection: []*reflect.Value{&fnUint32_uint32, &fnUint64_uint32}, - ExportSection: map[string]*internalwasm.Export{ - "1": {Name: "1", Type: internalwasm.ExternTypeFunc, Index: 0}, - "2": {Name: "2", Type: internalwasm.ExternTypeFunc, Index: 1}, + ExportSection: map[string]*wasm.Export{ + "1": {Name: "1", Type: wasm.ExternTypeFunc, Index: 0}, + "2": {Name: "2", Type: wasm.ExternTypeFunc, Index: 1}, }, - NameSection: &internalwasm.NameSection{ - FunctionNames: internalwasm.NameMap{{Index: 0, Name: "1"}, {Index: 1, Name: "2"}}, + NameSection: &wasm.NameSection{ + FunctionNames: wasm.NameMap{{Index: 0, Name: "1"}, {Index: 1, Name: "2"}}, }, }, }, @@ -135,19 +135,19 @@ func TestNewModuleBuilder_Build(t *testing.T) { "2": uint64_uint32, }) }, - expected: &internalwasm.Module{ - TypeSection: []*internalwasm.FunctionType{ - {Params: []wasm.ValueType{i32}, Results: []wasm.ValueType{i32}}, - {Params: []wasm.ValueType{i64}, Results: []wasm.ValueType{i32}}, + expected: &wasm.Module{ + TypeSection: []*wasm.FunctionType{ + {Params: []api.ValueType{i32}, Results: []api.ValueType{i32}}, + {Params: []api.ValueType{i64}, Results: []api.ValueType{i32}}, }, - FunctionSection: []internalwasm.Index{0, 1}, + FunctionSection: []wasm.Index{0, 1}, HostFunctionSection: []*reflect.Value{&fnUint32_uint32, &fnUint64_uint32}, - ExportSection: map[string]*internalwasm.Export{ - "1": {Name: "1", Type: internalwasm.ExternTypeFunc, Index: 0}, - "2": {Name: "2", Type: internalwasm.ExternTypeFunc, Index: 1}, + ExportSection: map[string]*wasm.Export{ + "1": {Name: "1", Type: wasm.ExternTypeFunc, Index: 0}, + "2": {Name: "2", Type: wasm.ExternTypeFunc, Index: 1}, }, - NameSection: &internalwasm.NameSection{ - FunctionNames: internalwasm.NameMap{{Index: 0, Name: "1"}, {Index: 1, Name: "2"}}, + NameSection: &wasm.NameSection{ + FunctionNames: wasm.NameMap{{Index: 0, Name: "1"}, {Index: 1, Name: "2"}}, }, }, }, @@ -185,7 +185,7 @@ func TestNewModuleBuilder_InstantiateModule_Errors(t *testing.T) { } // requireHostModuleEquals is redefined from internal/wasm/host_test.go to avoid an import cycle extracting it. -func requireHostModuleEquals(t *testing.T, expected, actual *internalwasm.Module) { +func requireHostModuleEquals(t *testing.T, expected, actual *wasm.Module) { // `require.Equal(t, expected, actual)` fails reflect pointers don't match, so brute compare: require.Equal(t, expected.TypeSection, actual.TypeSection) require.Equal(t, expected.ImportSection, actual.ImportSection) diff --git a/config.go b/config.go index d1469774..9d747bf1 100644 --- a/config.go +++ b/config.go @@ -8,24 +8,24 @@ import ( "io/fs" "math" - internalwasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm" "github.com/tetratelabs/wazero/internal/wasm/interpreter" "github.com/tetratelabs/wazero/internal/wasm/jit" ) // RuntimeConfig controls runtime behavior, with the default implementation as NewRuntimeConfig type RuntimeConfig struct { - newEngine func() internalwasm.Engine + newEngine func() wasm.Engine ctx context.Context - enabledFeatures internalwasm.Features + enabledFeatures wasm.Features memoryMaxPages uint32 } // engineLessConfig helps avoid copy/pasting the wrong defaults. var engineLessConfig = &RuntimeConfig{ ctx: context.Background(), - enabledFeatures: internalwasm.Features20191205, - memoryMaxPages: internalwasm.MemoryMaxPages, + enabledFeatures: wasm.Features20191205, + memoryMaxPages: wasm.MemoryMaxPages, } // clone ensures all fields are coped even if nil. @@ -59,8 +59,8 @@ func NewRuntimeConfigInterpreter() *RuntimeConfig { // // Notes: // * If the Module defines a start function, this is used to invoke it. -// * This is the outer-most ancestor of wasm.Module Context() during wasm.Function invocations. -// * This is the default context of wasm.Function when callers pass nil. +// * This is the outer-most ancestor of api.Module Context() during api.Function invocations. +// * This is the default context of api.Function when callers pass nil. // // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#start-function%E2%91%A0 func (c *RuntimeConfig) WithContext(ctx context.Context) *RuntimeConfig { @@ -91,11 +91,11 @@ func (c *RuntimeConfig) WithMemoryMaxPages(memoryMaxPages uint32) *RuntimeConfig // WithFeatureMutableGlobal allows globals to be mutable. This defaults to true as the feature was finished in // WebAssembly 1.0 (20191205). // -// When false, a wasm.Global can never be cast to a wasm.MutableGlobal, and any source that includes global vars +// When false, a api.Global can never be cast to a api.MutableGlobal, and any source that includes global vars // will fail to parse. func (c *RuntimeConfig) WithFeatureMutableGlobal(enabled bool) *RuntimeConfig { ret := c.clone() - ret.enabledFeatures = ret.enabledFeatures.Set(internalwasm.FeatureMutableGlobal, enabled) + ret.enabledFeatures = ret.enabledFeatures.Set(wasm.FeatureMutableGlobal, enabled) return ret } @@ -105,14 +105,54 @@ func (c *RuntimeConfig) WithFeatureMutableGlobal(enabled bool) *RuntimeConfig { // See https://github.com/WebAssembly/spec/blob/main/proposals/sign-extension-ops/Overview.md func (c *RuntimeConfig) WithFeatureSignExtensionOps(enabled bool) *RuntimeConfig { ret := c.clone() - ret.enabledFeatures = ret.enabledFeatures.Set(internalwasm.FeatureSignExtensionOps, enabled) + ret.enabledFeatures = ret.enabledFeatures.Set(wasm.FeatureSignExtensionOps, enabled) return ret } -// Module is a WebAssembly 1.0 (20191205) module to instantiate. -type Module struct { - name string - module *internalwasm.Module +// CompiledCode is a WebAssembly 1.0 (20191205) module ready to be instantiated (Runtime.InstantiateModule) as an\ +// api.Module. +// +// Note: In WebAssembly language, 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 +type CompiledCode struct { + module *wasm.Module +} + +// 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 (ex via StartWASICommandWithConfig), so that the same module can +// be safely instantiated multiple times. +// +// Note: 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). +type ModuleConfig struct { + name string + startFunctions []string + stdin io.Reader + stdout io.Writer + stderr io.Writer + args []string + // environ is pair-indexed to retain order similar to os.Environ. + environ []string + // environKeys allow overwriting of existing values. + environKeys map[string]int + + // preopenFD has the next FD number to use + preopenFD uint32 + // preopens are keyed on file descriptor and only include the Path and FS fields. + preopens map[uint32]*wasm.FileEntry + // preopenPaths allow overwriting of existing paths. + preopenPaths map[string]uint32 +} + +func NewModuleConfig() *ModuleConfig { + return &ModuleConfig{ + startFunctions: []string{"_start"}, + environKeys: map[string]int{}, + preopenFD: uint32(3), // after stdin/stdout/stderr + preopens: map[uint32]*wasm.FileEntry{}, + preopenPaths: map[string]uint32{}, + } } // WithName configures the module name. Defaults to what was decoded from the module source. @@ -125,79 +165,54 @@ type Module struct { // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#name-section%E2%91%A0 // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#custom-section%E2%91%A0 // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#modules%E2%91%A0%E2%91%A2 -func (m *Module) WithName(name string) *Module { - m.name = name - return m +func (c *ModuleConfig) WithName(name string) *ModuleConfig { + c.name = name + return c } -// SysConfig configures resources needed by functions that have low-level interactions with the host operating system. -// Using this, resources such as STDIN can be isolated (ex via StartWASICommandWithConfig), so that the same module can -// be safely instantiated multiple times. +// WithStartFunctions configures the functions to call after the module is instantiated. Defaults to "_start". // -// Note: While wazero supports Windows as a platform, host functions using SysConfig follow a UNIX dialect. -// See RATIONALE.md for design background and relationship to WebAssembly System Interfaces (WASI). -type SysConfig struct { - stdin io.Reader - stdout io.Writer - stderr io.Writer - args []string - // environ is pair-indexed to retain order similar to os.Environ. - environ []string - // environKeys allow overwriting of existing values. - environKeys map[string]int - - // preopenFD has the next FD number to use - preopenFD uint32 - // preopens are keyed on file descriptor and only include the Path and FS fields. - preopens map[uint32]*internalwasm.FileEntry - // preopenPaths allow overwriting of existing paths. - preopenPaths map[string]uint32 -} - -func NewSysConfig() *SysConfig { - return &SysConfig{ - environKeys: map[string]int{}, - preopenFD: uint32(3), // after stdin/stdout/stderr - preopens: map[uint32]*internalwasm.FileEntry{}, - preopenPaths: map[string]uint32{}, - } +// Note: If any function doesn't exist, it is skipped. However, all functions that do exist are called in order. +func (c *ModuleConfig) WithStartFunctions(startFunctions ...string) *ModuleConfig { + c.startFunctions = startFunctions + return c } // 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.ModuleSnapshotPreview1 although it could be +// 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. // -// Note: The caller is responsible to close any io.Reader they supply: It is not closed on wasm.Module Close. +// Note: The caller is responsible to close any io.Reader they supply: It is not closed on api.Module Close. // Note: This does not default to os.Stdin as that both violates sandboxing and prevents concurrent modules. // See https://linux.die.net/man/3/stdin -func (c *SysConfig) WithStdin(stdin io.Reader) *SysConfig { +func (c *ModuleConfig) WithStdin(stdin io.Reader) *ModuleConfig { c.stdin = stdin return c } // 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.ModuleSnapshotPreview1 although it could +// 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. // -// Note: The caller is responsible to close any io.Writer they supply: It is not closed on wasm.Module Close. +// Note: The caller is responsible to close any io.Writer they supply: It is not closed on api.Module Close. // Note: This does not default to os.Stdout as that both violates sandboxing and prevents concurrent modules. // See https://linux.die.net/man/3/stdout -func (c *SysConfig) WithStdout(stdout io.Writer) *SysConfig { +func (c *ModuleConfig) WithStdout(stdout io.Writer) *ModuleConfig { c.stdout = stdout return c } // 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.ModuleSnapshotPreview1 although it could +// 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. // -// Note: The caller is responsible to close any io.Writer they supply: It is not closed on wasm.Module Close. +// Note: The caller is responsible to close any io.Writer they supply: It is not closed on api.Module Close. // Note: This does not default to os.Stderr as that both violates sandboxing and prevents concurrent modules. // See https://linux.die.net/man/3/stderr -func (c *SysConfig) WithStderr(stderr io.Writer) *SysConfig { +func (c *ModuleConfig) WithStderr(stderr io.Writer) *ModuleConfig { c.stderr = stderr return c } @@ -205,7 +220,7 @@ func (c *SysConfig) WithStderr(stderr io.Writer) *SysConfig { // WithArgs assigns command-line arguments visible to an imported function that reads an arg vector (argv). Defaults to // none. // -// These values are commonly read by the functions like "args_get" in wasi.ModuleSnapshotPreview1 although they could be +// 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 @@ -216,7 +231,7 @@ func (c *SysConfig) WithStderr(stderr io.Writer) *SysConfig { // Note: Runtime.InstantiateModule errs if any value is empty. // See https://linux.die.net/man/3/argv // See https://en.wikipedia.org/wiki/Null-terminated_string -func (c *SysConfig) WithArgs(args ...string) *SysConfig { +func (c *ModuleConfig) WithArgs(args ...string) *ModuleConfig { c.args = args return c } @@ -226,7 +241,7 @@ func (c *SysConfig) WithArgs(args ...string) *SysConfig { // 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.ModuleSnapshotPreview1 although +// 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 @@ -236,7 +251,7 @@ func (c *SysConfig) WithArgs(args ...string) *SysConfig { // Note: Runtime.InstantiateModule errs if the key is empty or contains a NULL(0) or equals("") character. // See https://linux.die.net/man/3/environ // See https://en.wikipedia.org/wiki/Null-terminated_string -func (c *SysConfig) WithEnv(key, value string) *SysConfig { +func (c *ModuleConfig) WithEnv(key, value string) *ModuleConfig { // Check to see if this key already exists and update it. if i, ok := c.environKeys[key]; ok { c.environ[i+1] = value // environ is pair-indexed, so the value is 1 after the key. @@ -258,10 +273,10 @@ func (c *SysConfig) WithEnv(key, value string) *SysConfig { // require.NoError(t, err) // // // "index.html" is accessible as both "/index.html" and "./index.html" because we didn't use WithWorkDirFS. -// sysConfig := wazero.NewSysConfig().WithFS(rooted) +// config := wazero.NewModuleConfig().WithFS(rooted) // // Note: This sets WithWorkDirFS to the same file-system unless already set. -func (c *SysConfig) WithFS(fs fs.FS) *SysConfig { +func (c *ModuleConfig) WithFS(fs fs.FS) *ModuleConfig { c.setFS("/", fs) return c } @@ -274,19 +289,19 @@ func (c *SysConfig) WithFS(fs fs.FS) *SysConfig { // var rootFS embed.FS // // // Files relative to this source under appA are available under "/" and files relative to "/work/appA" under ".". -// sysConfig := wazero.NewSysConfig().WithFS(rootFS).WithWorkDirFS(os.DirFS("/work/appA")) +// config := wazero.NewModuleConfig().WithFS(rootFS).WithWorkDirFS(os.DirFS("/work/appA")) // // Note: os.DirFS documentation includes important notes about isolation, which also applies to fs.Sub. As of Go 1.18, // the built-in file-systems are not jailed (chroot). See https://github.com/golang/go/issues/42322 -func (c *SysConfig) WithWorkDirFS(fs fs.FS) *SysConfig { +func (c *ModuleConfig) WithWorkDirFS(fs fs.FS) *ModuleConfig { c.setFS(".", fs) return c } // setFS maps a path to a file-system. This is only used for base paths: "/" and ".". -func (c *SysConfig) setFS(path string, fs fs.FS) { +func (c *ModuleConfig) setFS(path string, fs fs.FS) { // Check to see if this key already exists and update it. - entry := &internalwasm.FileEntry{Path: path, FS: fs} + entry := &wasm.FileEntry{Path: path, FS: fs} if fd, ok := c.preopenPaths[path]; ok { c.preopens[fd] = entry } else { @@ -296,8 +311,8 @@ func (c *SysConfig) setFS(path string, fs fs.FS) { } } -// toSysContext creates a baseline internalwasm.SysContext configured by SysConfig. -func (c *SysConfig) toSysContext() (sys *internalwasm.SysContext, err error) { +// toSysContext creates a baseline wasm.SysContext configured by ModuleConfig. +func (c *ModuleConfig) toSysContext() (sys *wasm.SysContext, err error) { var environ []string // 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 { @@ -332,8 +347,8 @@ func (c *SysConfig) toSysContext() (sys *internalwasm.SysContext, err error) { // Default the working directory to the root FS if it exists. if rootFD != 0 && !setWorkDirFS { - preopens[c.preopenFD] = &internalwasm.FileEntry{Path: ".", FS: preopens[rootFD].FS} + preopens[c.preopenFD] = &wasm.FileEntry{Path: ".", FS: preopens[rootFD].FS} } - return internalwasm.NewSysContext(math.MaxUint32, c.args, environ, c.stdin, c.stdout, c.stderr, preopens) + return wasm.NewSysContext(math.MaxUint32, c.args, environ, c.stdin, c.stdout, c.stderr, preopens) } diff --git a/config_test.go b/config_test.go index 6a81259e..6765909f 100644 --- a/config_test.go +++ b/config_test.go @@ -9,7 +9,7 @@ import ( "github.com/stretchr/testify/require" - internalwasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm" ) func TestRuntimeConfig(t *testing.T) { @@ -51,7 +51,7 @@ func TestRuntimeConfig(t *testing.T) { return c.WithFeatureMutableGlobal(true) }, expected: &RuntimeConfig{ - enabledFeatures: internalwasm.FeatureMutableGlobal, + enabledFeatures: wasm.FeatureMutableGlobal, }, }, { @@ -60,7 +60,7 @@ func TestRuntimeConfig(t *testing.T) { return c.WithFeatureSignExtensionOps(true) }, expected: &RuntimeConfig{ - enabledFeatures: internalwasm.FeatureSignExtensionOps, + enabledFeatures: wasm.FeatureSignExtensionOps, }, }, } @@ -80,13 +80,13 @@ func TestRuntimeConfig(t *testing.T) { func TestRuntimeConfig_FeatureToggle(t *testing.T) { tests := []struct { name string - feature internalwasm.Features + feature wasm.Features expectDefault bool setFeature func(*RuntimeConfig, bool) *RuntimeConfig }{ { name: "mutable-global", - feature: internalwasm.FeatureMutableGlobal, + feature: wasm.FeatureMutableGlobal, expectDefault: true, setFeature: func(c *RuntimeConfig, v bool) *RuntimeConfig { return c.WithFeatureMutableGlobal(v) @@ -94,7 +94,7 @@ func TestRuntimeConfig_FeatureToggle(t *testing.T) { }, { name: "sign-extension-ops", - feature: internalwasm.FeatureSignExtensionOps, + feature: wasm.FeatureSignExtensionOps, expectDefault: false, setFeature: func(c *RuntimeConfig, v bool) *RuntimeConfig { return c.WithFeatureSignExtensionOps(v) @@ -124,18 +124,18 @@ func TestRuntimeConfig_FeatureToggle(t *testing.T) { } } -func TestSysConfig_toSysContext(t *testing.T) { +func TestModuleConfig_toSysContext(t *testing.T) { testFS := fstest.MapFS{} testFS2 := fstest.MapFS{} tests := []struct { name string - input *SysConfig - expected *internalwasm.SysContext + input *ModuleConfig + expected *wasm.SysContext }{ { name: "empty", - input: NewSysConfig(), + input: NewModuleConfig(), expected: requireSysContext(t, math.MaxUint32, // max nil, // args @@ -148,7 +148,7 @@ func TestSysConfig_toSysContext(t *testing.T) { }, { name: "WithArgs", - input: NewSysConfig().WithArgs("a", "bc"), + input: NewModuleConfig().WithArgs("a", "bc"), expected: requireSysContext(t, math.MaxUint32, // max []string{"a", "bc"}, // args @@ -161,7 +161,7 @@ func TestSysConfig_toSysContext(t *testing.T) { }, { name: "WithArgs - empty ok", // Particularly argv[0] can be empty, and we have no rules about others. - input: NewSysConfig().WithArgs("", "bc"), + input: NewModuleConfig().WithArgs("", "bc"), expected: requireSysContext(t, math.MaxUint32, // max []string{"", "bc"}, // args @@ -174,7 +174,7 @@ func TestSysConfig_toSysContext(t *testing.T) { }, { name: "WithArgs - second call overwrites", - input: NewSysConfig().WithArgs("a", "bc").WithArgs("bc", "a"), + input: NewModuleConfig().WithArgs("a", "bc").WithArgs("bc", "a"), expected: requireSysContext(t, math.MaxUint32, // max []string{"bc", "a"}, // args @@ -187,7 +187,7 @@ func TestSysConfig_toSysContext(t *testing.T) { }, { name: "WithEnv", - input: NewSysConfig().WithEnv("a", "b"), + input: NewModuleConfig().WithEnv("a", "b"), expected: requireSysContext(t, math.MaxUint32, // max nil, // args @@ -200,7 +200,7 @@ func TestSysConfig_toSysContext(t *testing.T) { }, { name: "WithEnv - empty value", - input: NewSysConfig().WithEnv("a", ""), + input: NewModuleConfig().WithEnv("a", ""), expected: requireSysContext(t, math.MaxUint32, // max nil, // args @@ -213,7 +213,7 @@ func TestSysConfig_toSysContext(t *testing.T) { }, { name: "WithEnv twice", - input: NewSysConfig().WithEnv("a", "b").WithEnv("c", "de"), + input: NewModuleConfig().WithEnv("a", "b").WithEnv("c", "de"), expected: requireSysContext(t, math.MaxUint32, // max nil, // args @@ -226,7 +226,7 @@ func TestSysConfig_toSysContext(t *testing.T) { }, { name: "WithEnv overwrites", - input: NewSysConfig().WithEnv("a", "bc").WithEnv("c", "de").WithEnv("a", "de"), + input: NewModuleConfig().WithEnv("a", "bc").WithEnv("c", "de").WithEnv("a", "de"), expected: requireSysContext(t, math.MaxUint32, // max nil, // args @@ -240,7 +240,7 @@ func TestSysConfig_toSysContext(t *testing.T) { { name: "WithEnv twice", - input: NewSysConfig().WithEnv("a", "b").WithEnv("c", "de"), + input: NewModuleConfig().WithEnv("a", "b").WithEnv("c", "de"), expected: requireSysContext(t, math.MaxUint32, // max nil, // args @@ -253,7 +253,7 @@ func TestSysConfig_toSysContext(t *testing.T) { }, { name: "WithFS", - input: NewSysConfig().WithFS(testFS), + input: NewModuleConfig().WithFS(testFS), expected: requireSysContext(t, math.MaxUint32, // max nil, // args @@ -261,7 +261,7 @@ func TestSysConfig_toSysContext(t *testing.T) { nil, // stdin nil, // stdout nil, // stderr - map[uint32]*internalwasm.FileEntry{ // openedFiles + map[uint32]*wasm.FileEntry{ // openedFiles 3: {Path: "/", FS: testFS}, 4: {Path: ".", FS: testFS}, }, @@ -269,7 +269,7 @@ func TestSysConfig_toSysContext(t *testing.T) { }, { name: "WithFS - overwrites", - input: NewSysConfig().WithFS(testFS).WithFS(testFS2), + input: NewModuleConfig().WithFS(testFS).WithFS(testFS2), expected: requireSysContext(t, math.MaxUint32, // max nil, // args @@ -277,7 +277,7 @@ func TestSysConfig_toSysContext(t *testing.T) { nil, // stdin nil, // stdout nil, // stderr - map[uint32]*internalwasm.FileEntry{ // openedFiles + map[uint32]*wasm.FileEntry{ // openedFiles 3: {Path: "/", FS: testFS2}, 4: {Path: ".", FS: testFS2}, }, @@ -285,7 +285,7 @@ func TestSysConfig_toSysContext(t *testing.T) { }, { name: "WithWorkDirFS", - input: NewSysConfig().WithWorkDirFS(testFS), + input: NewModuleConfig().WithWorkDirFS(testFS), expected: requireSysContext(t, math.MaxUint32, // max nil, // args @@ -293,14 +293,14 @@ func TestSysConfig_toSysContext(t *testing.T) { nil, // stdin nil, // stdout nil, // stderr - map[uint32]*internalwasm.FileEntry{ // openedFiles + map[uint32]*wasm.FileEntry{ // openedFiles 3: {Path: ".", FS: testFS}, }, ), }, { name: "WithFS and WithWorkDirFS", - input: NewSysConfig().WithFS(testFS).WithWorkDirFS(testFS2), + input: NewModuleConfig().WithFS(testFS).WithWorkDirFS(testFS2), expected: requireSysContext(t, math.MaxUint32, // max nil, // args @@ -308,7 +308,7 @@ func TestSysConfig_toSysContext(t *testing.T) { nil, // stdin nil, // stdout nil, // stderr - map[uint32]*internalwasm.FileEntry{ // openedFiles + map[uint32]*wasm.FileEntry{ // openedFiles 3: {Path: "/", FS: testFS}, 4: {Path: ".", FS: testFS2}, }, @@ -316,7 +316,7 @@ func TestSysConfig_toSysContext(t *testing.T) { }, { name: "WithWorkDirFS and WithFS", - input: NewSysConfig().WithWorkDirFS(testFS).WithFS(testFS2), + input: NewModuleConfig().WithWorkDirFS(testFS).WithFS(testFS2), expected: requireSysContext(t, math.MaxUint32, // max nil, // args @@ -324,7 +324,7 @@ func TestSysConfig_toSysContext(t *testing.T) { nil, // stdin nil, // stdout nil, // stderr - map[uint32]*internalwasm.FileEntry{ // openedFiles + map[uint32]*wasm.FileEntry{ // openedFiles 3: {Path: ".", FS: testFS}, 4: {Path: "/", FS: testFS2}, }, @@ -342,45 +342,45 @@ func TestSysConfig_toSysContext(t *testing.T) { } } -func TestSysConfig_toSysContext_Errors(t *testing.T) { +func TestModuleConfig_toSysContext_Errors(t *testing.T) { tests := []struct { name string - input *SysConfig + input *ModuleConfig expectedErr string }{ { name: "WithArgs - arg contains NUL", - input: NewSysConfig().WithArgs("", string([]byte{'a', 0})), + input: NewModuleConfig().WithArgs("", string([]byte{'a', 0})), expectedErr: "args invalid: contains NUL character", }, { name: "WithEnv - key contains NUL", - input: NewSysConfig().WithEnv(string([]byte{'a', 0}), "a"), + input: NewModuleConfig().WithEnv(string([]byte{'a', 0}), "a"), expectedErr: "environ invalid: contains NUL character", }, { name: "WithEnv - value contains NUL", - input: NewSysConfig().WithEnv("a", string([]byte{'a', 0})), + input: NewModuleConfig().WithEnv("a", string([]byte{'a', 0})), expectedErr: "environ invalid: contains NUL character", }, { name: "WithEnv - key contains equals", - input: NewSysConfig().WithEnv("a=", "a"), + input: NewModuleConfig().WithEnv("a=", "a"), expectedErr: "environ invalid: key contains '=' character", }, { name: "WithEnv - empty key", - input: NewSysConfig().WithEnv("", "a"), + input: NewModuleConfig().WithEnv("", "a"), expectedErr: "environ invalid: empty key", }, { name: "WithFS - nil", - input: NewSysConfig().WithFS(nil), + input: NewModuleConfig().WithFS(nil), expectedErr: "FS for / is nil", }, { name: "WithWorkDirFS - nil", - input: NewSysConfig().WithWorkDirFS(nil), + input: NewModuleConfig().WithWorkDirFS(nil), expectedErr: "FS for . is nil", }, } @@ -394,9 +394,9 @@ func TestSysConfig_toSysContext_Errors(t *testing.T) { } } -// requireSysContext ensures internalwasm.NewSysContext doesn't return an error, which makes it usable in test matrices. -func requireSysContext(t *testing.T, max uint32, args, environ []string, stdin io.Reader, stdout, stderr io.Writer, openedFiles map[uint32]*internalwasm.FileEntry) *internalwasm.SysContext { - sys, err := internalwasm.NewSysContext(max, args, environ, stdin, stdout, stderr, openedFiles) +// requireSysContext ensures wasm.NewSysContext doesn't return an error, which makes it usable in test matrices. +func requireSysContext(t *testing.T, max uint32, args, environ []string, stdin io.Reader, stdout, stderr io.Writer, openedFiles map[uint32]*wasm.FileEntry) *wasm.SysContext { + sys, err := wasm.NewSysContext(max, args, environ, stdin, stdout, stderr, openedFiles) require.NoError(t, err) return sys } diff --git a/examples/add_test.go b/examples/add_test.go index 121acbc8..ddcab30b 100644 --- a/examples/add_test.go +++ b/examples/add_test.go @@ -11,7 +11,7 @@ import ( // Test_AddInt shows how you can define a function in text format and have it compiled inline. // See https://github.com/summerwind/the-art-of-webassembly-go/blob/main/chapter1/addint/addint.wat func Test_AddInt(t *testing.T) { - module, err := wazero.NewRuntime().InstantiateModuleFromSource([]byte(`(module $test + module, err := wazero.NewRuntime().InstantiateModuleFromCode([]byte(`(module $test (func $addInt ;; TODO: function module (export "AddInt") (param $value_1 i32) (param $value_2 i32) (result i32) diff --git a/examples/fibonacci_test.go b/examples/fibonacci_test.go index 419aa98c..f2a95464 100644 --- a/examples/fibonacci_test.go +++ b/examples/fibonacci_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/require" "github.com/tetratelabs/wazero" + "github.com/tetratelabs/wazero/wasi" ) // fibWasm was compiled from TinyGo testdata/fibonacci.go @@ -17,11 +18,11 @@ func Test_fibonacci(t *testing.T) { r := wazero.NewRuntime() // Note: fibonacci.go doesn't directly use WASI, but TinyGo needs to be initialized as a WASI Command. - wasi, err := r.InstantiateModule(wazero.WASISnapshotPreview1()) + wm, err := wasi.InstantiateSnapshotPreview1(r) require.NoError(t, err) - defer wasi.Close() + defer wm.Close() - module, err := wazero.StartWASICommandFromSource(r, fibWasm) + module, err := r.InstantiateModuleFromCode(fibWasm) require.NoError(t, err) defer module.Close() diff --git a/examples/file_system_test.go b/examples/file_system_test.go index 54bc4b8c..f1c585e7 100644 --- a/examples/file_system_test.go +++ b/examples/file_system_test.go @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/require" "github.com/tetratelabs/wazero" + "github.com/tetratelabs/wazero/wasi" ) // catFS is an embedded filesystem limited to cat.go @@ -39,21 +40,21 @@ func Test_Cat(t *testing.T) { require.NoError(t, err) // Combine the above into our baseline config, overriding defaults (which discard stdout and have no file system). - sysConfig := wazero.NewSysConfig().WithStdout(stdoutBuf).WithFS(rooted) + config := wazero.NewModuleConfig().WithStdout(stdoutBuf).WithFS(rooted) // Compile the `cat` module. - compiled, err := r.CompileModule(catWasm) + code, err := r.CompileModule(catWasm) require.NoError(t, err) // Instantiate WASI, which implements system I/O such as console output. - wasi, err := r.InstantiateModule(wazero.WASISnapshotPreview1()) + wm, err := wasi.InstantiateSnapshotPreview1(r) require.NoError(t, err) - defer wasi.Close() + defer wm.Close() - // StartWASICommand runs the "_start" function which is what TinyGo compiles "main" to. + // InstantiateModuleWithConfig by default runs the "_start" function which is what TinyGo compiles "main" to. // * Set the program name (arg[0]) to "cat" and add args to write "cat.go" to stdout twice. // * We use both "/cat.go" and "./cat.go" because WithFS by default maps the workdir "." to "/". - cat, err := wazero.StartWASICommandWithConfig(r, compiled, sysConfig.WithArgs("cat", "/cat.go", "./cat.go")) + cat, err := r.InstantiateModuleWithConfig(code, config.WithArgs("cat", "/cat.go", "./cat.go")) require.NoError(t, err) defer cat.Close() diff --git a/examples/host_func_test.go b/examples/host_func_test.go index fc675785..aa037d55 100644 --- a/examples/host_func_test.go +++ b/examples/host_func_test.go @@ -12,7 +12,8 @@ import ( "github.com/stretchr/testify/require" "github.com/tetratelabs/wazero" - "github.com/tetratelabs/wazero/wasm" + "github.com/tetratelabs/wazero/api" + "github.com/tetratelabs/wazero/wasi" ) type testKey struct{} @@ -24,14 +25,14 @@ var hostFuncWasm []byte func Test_hostFunc(t *testing.T) { // The function for allocating the in-Wasm memory region. // We resolve this function after main module instantiation. - allocateInWasmBuffer := func(wasm.Module, uint32) uint32 { + allocateInWasmBuffer := func(api.Module, uint32) uint32 { panic("unimplemented") } var expectedBase64String string // Host-side implementation of get_random_string on Wasm import. - getRandomBytes := func(ctx wasm.Module, retBufPtr uint32, retBufSize uint32) { + getRandomBytes := func(ctx api.Module, retBufPtr uint32, retBufSize uint32) { // Assert that context values passed in from CallFunctionContext are accessible. contextValue := ctx.Context().Value(testKey{}).(int64) require.Equal(t, int64(12345), contextValue) @@ -60,34 +61,34 @@ func Test_hostFunc(t *testing.T) { require.NoError(t, err) // Compile the `hostFunc` module. - compiled, err := r.CompileModule(hostFuncWasm) + code, err := r.CompileModule(hostFuncWasm) require.NoError(t, err) // Configure stdout (console) to write to a buffer. stdout := bytes.NewBuffer(nil) - config := wazero.NewSysConfig().WithStdout(stdout) + config := wazero.NewModuleConfig().WithStdout(stdout) // Instantiate WASI, which implements system I/O such as console output. - wasi, err := r.InstantiateModule(wazero.WASISnapshotPreview1()) + wm, err := wasi.InstantiateSnapshotPreview1(r) require.NoError(t, err) - defer wasi.Close() + defer wm.Close() - // StartWASICommand runs the "_start" function which is what TinyGo compiles "main" to. - module, err := wazero.StartWASICommandWithConfig(r, compiled, config) + // InstantiateModuleWithConfig runs the "_start" function which is what TinyGo compiles "main" to. + module, err := r.InstantiateModuleWithConfig(code, config) require.NoError(t, err) - defer wasi.Close() + defer wm.Close() allocateInWasmBufferFn := module.ExportedFunction("allocate_buffer") require.NotNil(t, allocateInWasmBuffer) // Implement the function pointer. This mainly shows how you can decouple a module function dependency. - allocateInWasmBuffer = func(ctx wasm.Module, size uint32) uint32 { + allocateInWasmBuffer = func(ctx api.Module, size uint32) uint32 { res, err := allocateInWasmBufferFn.Call(ctx, uint64(size)) require.NoError(t, err) return uint32(res[0]) } - // Set a context variable that should be available in wasm.Module. + // Set a context variable that should be available in a wasm.Function. ctx := context.WithValue(context.Background(), testKey{}, int64(12345)) // Invoke a module-defined function that depends on a host function import diff --git a/examples/simple_test.go b/examples/simple_test.go index 43d7965e..46d71e80 100644 --- a/examples/simple_test.go +++ b/examples/simple_test.go @@ -26,7 +26,7 @@ func Test_Simple(t *testing.T) { // The "hello" function was imported as $hello in Wasm. Since it was marked as the start // function, it is invoked on instantiation. Ensure that worked: "hello" was called! - mod, err := r.InstantiateModuleFromSource([]byte(`(module $test + mod, err := r.InstantiateModuleFromCode([]byte(`(module $test (import "" "hello" (func $hello)) (start $hello) )`)) diff --git a/examples/stdio_test.go b/examples/stdio_test.go index 33cc2372..360eb3e6 100644 --- a/examples/stdio_test.go +++ b/examples/stdio_test.go @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/require" "github.com/tetratelabs/wazero" + "github.com/tetratelabs/wazero/wasi" ) // stdioWasm was compiled from TinyGo testdata/stdio.go @@ -19,22 +20,22 @@ func Test_stdio(t *testing.T) { r := wazero.NewRuntime() // Compile the `stdioWasm` module. - compiled, err := r.CompileModule(stdioWasm) + code, err := r.CompileModule(stdioWasm) require.NoError(t, err) // Configure standard I/O (ex stdout) to write to buffers instead of no-op. stdinBuf := bytes.NewBuffer([]byte("WASI\n")) stdoutBuf := bytes.NewBuffer(nil) stderrBuf := bytes.NewBuffer(nil) - config := wazero.NewSysConfig().WithStdin(stdinBuf).WithStdout(stdoutBuf).WithStderr(stderrBuf) + config := wazero.NewModuleConfig().WithStdin(stdinBuf).WithStdout(stdoutBuf).WithStderr(stderrBuf) // Instantiate WASI, which implements system I/O such as console output. - wasi, err := r.InstantiateModule(wazero.WASISnapshotPreview1()) + wm, err := wasi.InstantiateSnapshotPreview1(r) require.NoError(t, err) - defer wasi.Close() + defer wm.Close() - // StartWASICommand runs the "_start" function which is what TinyGo compiles "main" to. - module, err := wazero.StartWASICommandWithConfig(r, compiled, config) + // InstantiateModuleWithConfig runs the "_start" function which is what TinyGo compiles "main" to. + module, err := r.InstantiateModuleWithConfig(code, config) require.NoError(t, err) defer module.Close() diff --git a/examples/wasi_test.go b/examples/wasi_test.go index d6864b6e..50b7c046 100644 --- a/examples/wasi_test.go +++ b/examples/wasi_test.go @@ -8,18 +8,18 @@ import ( "github.com/stretchr/testify/require" "github.com/tetratelabs/wazero" + "github.com/tetratelabs/wazero/api" "github.com/tetratelabs/wazero/wasi" - "github.com/tetratelabs/wazero/wasm" ) func Test_WASI(t *testing.T) { // built-in WASI function to write a random value to memory - randomGet := func(ctx wasm.Module, buf, bufLen uint32) wasi.Errno { + randomGet := func(ctx api.Module, buf, bufLen uint32) wasi.Errno { panic("unimplemented") } stdout := new(bytes.Buffer) - random := func(ctx wasm.Module) { + random := func(ctx api.Module) { // Write 8 random bytes to memory using WASI. errno := randomGet(ctx, 0, 8) require.Equal(t, wasi.ErrnoSuccess, errno) @@ -38,14 +38,14 @@ func Test_WASI(t *testing.T) { defer host.Close() // Configure WASI and implement the function to use it - we, err := r.InstantiateModule(wazero.WASISnapshotPreview1()) + wm, err := wasi.InstantiateSnapshotPreview1(r) require.NoError(t, err) - defer we.Close() + defer wm.Close() - randomGetFn := we.ExportedFunction("random_get") + randomGetFn := wm.ExportedFunction("random_get") // Implement the function pointer. This mainly shows how you can decouple a host function dependency. - randomGet = func(ctx wasm.Module, buf, bufLen uint32) wasi.Errno { + randomGet = func(ctx api.Module, buf, bufLen uint32) wasi.Errno { res, err := randomGetFn.Call(ctx, uint64(buf), uint64(bufLen)) require.NoError(t, err) return wasi.Errno(res[0]) @@ -53,7 +53,7 @@ func Test_WASI(t *testing.T) { // The "random" function was imported as $random in Wasm. Since it was marked as the start // function, it is invoked on instantiation. Ensure that worked: "random" was called! - mod, err := r.InstantiateModuleFromSource([]byte(`(module $wasi + mod, err := r.InstantiateModuleFromCode([]byte(`(module $wasi (import "wasi_snapshot_preview1" "random_get" (func $wasi.random_get (param $buf i32) (param $buf_len i32) (result (;errno;) i32))) (import "" "random" (func $random)) diff --git a/internal/asm/amd64/impl.go b/internal/asm/amd64/impl.go index 90e88485..f57082e4 100644 --- a/internal/asm/amd64/impl.go +++ b/internal/asm/amd64/impl.go @@ -78,7 +78,7 @@ func (n *NodeImpl) AssignJumpTarget(target asm.Node) { n.JumpTarget = target.(*NodeImpl) } -// AssignSourceConstant implements asm.Node.AssignSourceConstant. +// AssignDestinationConstant implements asm.Node.AssignDestinationConstant. func (n *NodeImpl) AssignDestinationConstant(value asm.ConstantValue) { n.DstConst = value } diff --git a/internal/asm/arm64/consts.go b/internal/asm/arm64/consts.go index e63a8ad1..55e0e26c 100644 --- a/internal/asm/arm64/consts.go +++ b/internal/asm/arm64/consts.go @@ -31,6 +31,7 @@ const ( // Note: naming convension is exactly the same as Go assembler: https://go.dev/doc/asm const ( // Integer registers. + REG_R0 asm.Register = asm.NilRegister + 1 + iota REG_R1 REG_R2 @@ -65,6 +66,7 @@ const ( REGZERO // Scalar floating point registers. + REG_F0 REG_F1 REG_F2 @@ -99,6 +101,7 @@ const ( REG_F31 // Floating point status register. + REG_FPSR ) diff --git a/internal/testing/enginetest/enginetest.go b/internal/testing/enginetest/enginetest.go index 57dce169..29242c8a 100644 --- a/internal/testing/enginetest/enginetest.go +++ b/internal/testing/enginetest/enginetest.go @@ -1,4 +1,4 @@ -// Package enginetest contains tests common to any internalwasm.Engine implementation. Defining these as top-level +// Package enginetest contains tests common to any wasm.Engine implementation. Defining these as top-level // functions is less burden than copy/pasting the implementations, while still allowing test caching to operate. // // Ex. In simplest case, dispatch: @@ -12,8 +12,8 @@ // enginetest.RunTestModuleEngine_Call(t, NewEngine) // } // -// Note: These tests intentionally avoid using internalwasm.Store as it is important to know both the dependencies and -// the capabilities at the internalwasm.Engine abstraction. +// Note: These tests intentionally avoid using wasm.Store as it is important to know both the dependencies and +// the capabilities at the wasm.Engine abstraction. package enginetest import ( @@ -23,8 +23,8 @@ import ( "github.com/stretchr/testify/require" - wasm "github.com/tetratelabs/wazero/internal/wasm" - publicwasm "github.com/tetratelabs/wazero/wasm" + "github.com/tetratelabs/wazero/api" + "github.com/tetratelabs/wazero/internal/wasm" ) type EngineTester interface { @@ -179,8 +179,8 @@ func RunTestEngine_NewModuleEngine_InitTable(t *testing.T, et EngineTester) { func RunTestModuleEngine_Call_HostFn(t *testing.T, et EngineTester) { memory := &wasm.MemoryInstance{} - var ctxMemory publicwasm.Memory - hostFn := reflect.ValueOf(func(ctx publicwasm.Module, v uint64) uint64 { + var ctxMemory api.Memory + hostFn := reflect.ValueOf(func(ctx api.Module, v uint64) uint64 { ctxMemory = ctx.Memory() return v }) @@ -231,12 +231,12 @@ func addFunction(module *wasm.ModuleInstance, fn *wasm.FunctionInstance) { fn.Module = module } -// newModuleContext creates an internalwasm.ModuleContext for unit tests. +// newModuleContext creates an wasm.ModuleContext for unit tests. // // Note: This sets fields that are not needed in the interpreter, but are required by code compiled by JIT. If a new // test here passes in the interpreter and segmentation faults in JIT, check for a new field offset or a change in JIT // (ex. jit.TestVerifyOffsetValue). It is possible for all other tests to pass as that field is implicitly set by -// internalwasm.Store: store isn't used here for unit test precision. +// wasm.Store: store isn't used here for unit test precision. func newModuleContext(module *wasm.ModuleInstance, engine wasm.ModuleEngine) *wasm.ModuleContext { // moduleInstanceEngineOffset module.Engine = engine diff --git a/internal/wasi/wasi.go b/internal/wasi/wasi.go deleted file mode 100644 index 96a24eb7..00000000 --- a/internal/wasi/wasi.go +++ /dev/null @@ -1,1555 +0,0 @@ -package internalwasi - -import ( - crand "crypto/rand" - "errors" - "fmt" - "io" - "io/fs" - "path" - "time" - - internalwasm "github.com/tetratelabs/wazero/internal/wasm" - "github.com/tetratelabs/wazero/wasi" - "github.com/tetratelabs/wazero/wasm" -) - -const ( - // FunctionStart is the name of the nullary function a module must export if it is a WASI Command Module. - // - // Note: When this is exported FunctionInitialize must not be. - // See https://github.com/WebAssembly/WASI/blob/snapshot-01/design/application-abi.md#current-unstable-abi - FunctionStart = "_start" - - // FunctionInitialize is the name of the nullary function a module must export if it is a WASI Reactor Module. - // - // Note: When this is exported FunctionStart must not be. - // See https://github.com/WebAssembly/WASI/blob/snapshot-01/design/application-abi.md#current-unstable-abi - FunctionInitialize = "_initialize" - - // FunctionArgsGet reads command-line argument data. - // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-args_getargv-pointerpointeru8-argv_buf-pointeru8---errno - FunctionArgsGet = "args_get" - - // ImportArgsGet is the WebAssembly 1.0 (20191205) Text format import of FunctionArgsGet. - ImportArgsGet = `(import "wasi_snapshot_preview1" "args_get" - (func $wasi.args_get (param $argv i32) (param $argv_buf i32) (result (;errno;) i32)))` - - // FunctionArgsSizesGet returns command-line argument data sizes. - // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-args_sizes_get---errno-size-size - FunctionArgsSizesGet = "args_sizes_get" - - // ImportArgsSizesGet is the WebAssembly 1.0 (20191205) Text format import of FunctionArgsSizesGet. - ImportArgsSizesGet = `(import "wasi_snapshot_preview1" "args_sizes_get" - (func $wasi.args_sizes_get (param $result.argc i32) (param $result.argv_buf_size i32) (result (;errno;) i32)))` - - // FunctionEnvironGet reads environment variable data. - // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-environ_getenviron-pointerpointeru8-environ_buf-pointeru8---errno - FunctionEnvironGet = "environ_get" - - // ImportEnvironGet is the WebAssembly 1.0 (20191205) Text format import of FunctionEnvironGet. - ImportEnvironGet = `(import "wasi_snapshot_preview1" "environ_get" - (func $wasi.environ_get (param $environ i32) (param $environ_buf i32) (result (;errno;) i32)))` - - // FunctionEnvironSizesGet returns environment variable data sizes. - // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-environ_sizes_get---errno-size-size - FunctionEnvironSizesGet = "environ_sizes_get" - - // ImportEnvironSizesGet is the WebAssembly 1.0 (20191205) Text format import of FunctionEnvironSizesGet. - ImportEnvironSizesGet = `(import "wasi_snapshot_preview1" "environ_sizes_get" - (func $wasi.environ_sizes_get (param $result.environc i32) (param $result.environBufSize i32) (result (;errno;) i32)))` - - // FunctionClockResGet returns the resolution of a clock. - // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-clock_res_getid-clockid---errno-timestamp - FunctionClockResGet = "clock_res_get" - - // ImportClockResGet is the WebAssembly 1.0 (20191205) Text format import of FunctionClockResGet. - ImportClockResGet = `(import "wasi_snapshot_preview1" "clock_res_get" - (func $wasi.clock_res_get (param $id i32) (param $result.resolution i32) (result (;errno;) i32)))` - - // FunctionClockTimeGet returns the time value of a clock. - // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-clock_time_getid-clockid-precision-timestamp---errno-timestamp - FunctionClockTimeGet = "clock_time_get" - - // ImportClockTimeGet is the WebAssembly 1.0 (20191205) Text format import of FunctionClockTimeGet. - ImportClockTimeGet = `(import "wasi_snapshot_preview1" "clock_time_get" - (func $wasi.clock_time_get (param $id i32) (param $precision i64) (param $result.timestamp i32) (result (;errno;) i32)))` - - // FunctionFdAdvise provides file advisory information on a file descriptor. - // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-fd_advisefd-fd-offset-filesize-len-filesize-advice-advice---errno - FunctionFdAdvise = "fd_advise" - - // ImportFdAdvise is the WebAssembly 1.0 (20191205) Text format import of FunctionFdAdvise. - ImportFdAdvise = `(import "wasi_snapshot_preview1" "fd_advise" - (func $wasi.fd_advise (param $fd i32) (param $offset i64) (param $len i64) (param $result.advice i32) (result (;errno;) i32)))` - - // FunctionFdAllocate forces the allocation of space in a file. - // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-fd_allocatefd-fd-offset-filesize-len-filesize---errno - FunctionFdAllocate = "fd_allocate" - - // ImportFdAllocate is the WebAssembly 1.0 (20191205) Text format import of FunctionFdAllocate. - ImportFdAllocate = `(import "wasi_snapshot_preview1" "fd_allocate" - (func $wasi.fd_allocate (param $fd i32) (param $offset i64) (param $len i64) (result (;errno;) i32)))` - - // FunctionFdClose closes a file descriptor. - // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#fd_close - FunctionFdClose = "fd_close" - - // ImportFdClose is the WebAssembly 1.0 (20191205) Text format import of FunctionFdClose. - ImportFdClose = `(import "wasi_snapshot_preview1" "fd_close" - (func $wasi.fd_close (param $fd i32) (result (;errno;) i32)))` - - // FunctionFdDatasync synchronizes the data of a file to disk. - // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#fd_close - FunctionFdDatasync = "fd_datasync" - - // ImportFdDatasync is the WebAssembly 1.0 (20191205) Text format import of FunctionFdDatasync. - ImportFdDatasync = `(import "wasi_snapshot_preview1" "fd_datasync" - (func $wasi.fd_datasync (param $fd i32) (result (;errno;) i32)))` - - // FunctionFdFdstatGet gets the attributes of a file descriptor. - // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-fd_fdstat_getfd-fd---errno-fdstat - FunctionFdFdstatGet = "fd_fdstat_get" - - // ImportFdFdstatGet is the WebAssembly 1.0 (20191205) Text format import of FunctionFdFdstatGet. - ImportFdFdstatGet = `(import "wasi_snapshot_preview1" "fd_fdstat_get" - (func $wasi.fd_fdstat_get (param $fd i32) (param $result.stat i32) (result (;errno;) i32)))` - - // FunctionFdFdstatSetFlags adjusts the flags associated with a file descriptor. - // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-fd_fdstat_set_flagsfd-fd-flags-fdflags---errno - FunctionFdFdstatSetFlags = "fd_fdstat_set_flags" - - // ImportFdFdstatSetFlags is the WebAssembly 1.0 (20191205) Text format import of FunctionFdFdstatSetFlags. - ImportFdFdstatSetFlags = `(import "wasi_snapshot_preview1" "fd_fdstat_set_flags" - (func $wasi.fd_fdstat_set_flags (param $fd i32) (param $flags i32) (result (;errno;) i32)))` - - // FunctionFdFdstatSetRights adjusts the rights associated with a file descriptor. - // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-fd_fdstat_set_rightsfd-fd-fs_rights_base-rights-fs_rights_inheriting-rights---errno - FunctionFdFdstatSetRights = "fd_fdstat_set_rights" - - // ImportFdFdstatSetRights is the WebAssembly 1.0 (20191205) Text format import of FunctionFdFdstatSetRights. - ImportFdFdstatSetRights = `(import "wasi_snapshot_preview1" "fd_fdstat_set_rights" - (func $wasi.fd_fdstat_set_rights (param $fd i32) (param $fs_rights_base i64) (param $fs_rights_inheriting i64) (result (;errno;) i32)))` - - // FunctionFdFilestatGet returns the attributes of an open file. - // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-fd_filestat_getfd-fd---errno-filestat - FunctionFdFilestatGet = "fd_filestat_get" - - // ImportFdFilestatGet is the WebAssembly 1.0 (20191205) Text format import of FunctionFdFilestatGet. - ImportFdFilestatGet = `(import "wasi_snapshot_preview1" "fd_filestat_get" - (func $wasi.fd_filestat_get (param $fd i32) (param $result.buf i32) (result (;errno;) i32)))` - - // FunctionFdFilestatSetSize adjusts the size of an open file. - // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-fd_filestat_set_sizefd-fd-size-filesize---errno - FunctionFdFilestatSetSize = "fd_filestat_set_size" - - // ImportFdFilestatSetSize is the WebAssembly 1.0 (20191205) Text format import of FunctionFdFilestatSetSize. - ImportFdFilestatSetSize = `(import "wasi_snapshot_preview1" "fd_filestat_set_size" - (func $wasi.fd_filestat_set_size (param $fd i32) (param $size i64) (result (;errno;) i32)))` - - // FunctionFdFilestatSetTimes adjusts the times of an open file. - // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-fd_filestat_set_timesfd-fd-atim-timestamp-mtim-timestamp-fst_flags-fstflags---errno - FunctionFdFilestatSetTimes = "fd_filestat_set_times" - - // ImportFdFilestatSetTimes is the WebAssembly 1.0 (20191205) Text format import of FunctionFdFilestatSetTimes. - ImportFdFilestatSetTimes = `(import "wasi_snapshot_preview1" "fd_filestat_set_times" - (func $wasi.fd_filestat_set_times (param $fd i32) (param $atim i64) (param $mtim i64) (param $fst_flags i32) (result (;errno;) i32)))` - - // FunctionFdPread reads from a file descriptor, without using and updating the file descriptor's offset. - // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-fd_preadfd-fd-iovs-iovec_array-offset-filesize---errno-size - FunctionFdPread = "fd_pread" - - // ImportFdPread is the WebAssembly 1.0 (20191205) Text format import of FunctionFdPread. - ImportFdPread = `(import "wasi_snapshot_preview1" "fd_pread" - (func $wasi.fd_pread (param $fd i32) (param $iovs i32) (param $iovs_len i32) (param $offset i64) (param $result.nread i32) (result (;errno;) i32)))` - - // FunctionFdPrestatGet returns the prestat data of a file descriptor. - // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#fd_prestat_get - FunctionFdPrestatGet = "fd_prestat_get" - - // ImportFdPrestatGet is the WebAssembly 1.0 (20191205) Text format import of FunctionFdPrestatGet. - ImportFdPrestatGet = `(import "wasi_snapshot_preview1" "fd_prestat_get" - (func $wasi.fd_prestat_get (param $fd i32) (param $result.prestat i32) (result (;errno;) i32)))` - - // FunctionFdPrestatDirName returns the path of the pre-opened directory of a file descriptor. - // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#fd_prestat_dir_name - FunctionFdPrestatDirName = "fd_prestat_dir_name" - - // ImportFdPrestatDirName is the WebAssembly 1.0 (20191205) Text format import of FunctionFdPrestatDirName. - ImportFdPrestatDirName = `(import "wasi_snapshot_preview1" "fd_prestat_dir_name" - (func $wasi.fd_prestat_dir_name (param $fd i32) (param $path i32) (param $path_len i32) (result (;errno;) i32)))` - - // FunctionFdPwrite writes to a file descriptor, without using and updating the file descriptor's offset. - // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-fd_pwritefd-fd-iovs-ciovec_array-offset-filesize---errno-size - FunctionFdPwrite = "fd_pwrite" - - // ImportFdPwrite is the WebAssembly 1.0 (20191205) Text format import of FunctionFdPwrite. - ImportFdPwrite = `(import "wasi_snapshot_preview1" "fd_pwrite" - (func $wasi.fd_pwrite (param $fd i32) (param $iovs i32) (param $iovs_len i32) (param $offset i64) (param $result.nwritten i32) (result (;errno;) i32)))` - - // FunctionFdRead read bytes from a file descriptor. - // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#fd_read - FunctionFdRead = "fd_read" - - // ImportFdRead is the WebAssembly 1.0 (20191205) Text format import of FunctionFdRead. - ImportFdRead = `(import "wasi_snapshot_preview1" "fd_read" - (func $wasi.fd_read (param $fd i32) (param $iovs i32) (param $iovs_len i32) (param $result.size i32) (result (;errno;) i32)))` - - // FunctionFdReaddir reads directory entries from a directory. - // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-fd_readdirfd-fd-buf-pointeru8-buf_len-size-cookie-dircookie---errno-size - FunctionFdReaddir = "fd_readdir" - - // ImportFdReaddir is the WebAssembly 1.0 (20191205) Text format import of FunctionFdReaddir. - ImportFdReaddir = `(import "wasi_snapshot_preview1" "fd_readdir" - (func $wasi.fd_readdir (param $fd i32) (param $buf i32) (param $buf_len i32) (param $cookie i64) (param $result.bufused i32) (result (;errno;) i32)))` - - // FunctionFdRenumber atomically replaces a file descriptor by renumbering another file descriptor. - // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-fd_renumberfd-fd-to-fd---errno - FunctionFdRenumber = "fd_renumber" - - // ImportFdRenumber is the WebAssembly 1.0 (20191205) Text format import of FunctionFdRenumber. - ImportFdRenumber = `(import "wasi_snapshot_preview1" "fd_renumber" - (func $wasi.fd_renumber (param $fd i32) (param $to i32) (result (;errno;) i32)))` - - // FunctionFdSeek moves the offset of a file descriptor. - // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-fd_seekfd-fd-offset-filedelta-whence-whence---errno-filesize - FunctionFdSeek = "fd_seek" - - // ImportFdSeek is the WebAssembly 1.0 (20191205) Text format import of FunctionFdSeek. - ImportFdSeek = `(import "wasi_snapshot_preview1" "fd_seek" - (func $wasi.fd_seek (param $fd i32) (param $offset i64) (param $whence i32) (param $result.newoffset i32) (result (;errno;) i32)))` - - // FunctionFdSync synchronizes the data and metadata of a file to disk. - // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-fd_syncfd-fd---errno - FunctionFdSync = "fd_sync" - - // ImportFdSync is the WebAssembly 1.0 (20191205) Text format import of FunctionFdSync. - ImportFdSync = `(import "wasi_snapshot_preview1" "fd_sync" - (func $wasi.fd_sync (param $fd i32) (result (;errno;) i32)))` - - // FunctionFdTell returns the current offset of a file descriptor. - // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-fd_tellfd-fd---errno-filesize - FunctionFdTell = "fd_tell" - - // ImportFdTell is the WebAssembly 1.0 (20191205) Text format import of FunctionFdTell. - ImportFdTell = `(import "wasi_snapshot_preview1" "fd_tell" - (func $wasi.fd_tell (param $fd i32) (param $result.offset i32) (result (;errno;) i32)))` - - // FunctionFdWrite write bytes to a file descriptor. - // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#fd_write - FunctionFdWrite = "fd_write" - - // ImportFdWrite is the WebAssembly 1.0 (20191205) Text format import of FunctionFdWrite. - ImportFdWrite = `(import "wasi_snapshot_preview1" "fd_write" - (func $wasi.fd_write (param $fd i32) (param $iovs i32) (param $iovs_len i32) (param $result.size i32) (result (;errno;) i32)))` - - // FunctionPathCreateDirectory creates a directory. - // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-path_create_directoryfd-fd-path-string---errno - FunctionPathCreateDirectory = "path_create_directory" - - // ImportPathCreateDirectory is the WebAssembly 1.0 (20191205) Text format import of FunctionPathCreateDirectory. - ImportPathCreateDirectory = `(import "wasi_snapshot_preview1" "path_create_directory" - (func $wasi.path_create_directory (param $fd i32) (param $path i32) (param $path_len i32) (result (;errno;) i32)))` - - // FunctionPathFilestatGet returns the attributes of a file or directory. - // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-path_filestat_getfd-fd-flags-lookupflags-path-string---errno-filestat - FunctionPathFilestatGet = "path_filestat_get" - - // ImportPathFilestatGet is the WebAssembly 1.0 (20191205) Text format import of FunctionPathFilestatGet. - ImportPathFilestatGet = `(import "wasi_snapshot_preview1" "path_filestat_get" - (func $wasi.path_filestat_get (param $fd i32) (param $flags i32) (param $path i32) (param $path_len i32) (param $result.buf i32) (result (;errno;) i32)))` - - // FunctionPathFilestatSetTimes adjusts the timestamps of a file or directory. - // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-path_filestat_set_timesfd-fd-flags-lookupflags-path-string-atim-timestamp-mtim-timestamp-fst_flags-fstflags---errno - FunctionPathFilestatSetTimes = "path_filestat_set_times" - - // ImportPathFilestatSetTimes is the WebAssembly 1.0 (20191205) Text format import of FunctionPathFilestatSetTimes. - ImportPathFilestatSetTimes = `(import "wasi_snapshot_preview1" "path_filestat_set_times" - (func $wasi.path_filestat_set_times (param $fd i32) (param $flags i32) (param $path i32) (param $path_len i32) (param $atim i64) (param $mtim i64) (param $fst_flags i32) (result (;errno;) i32)))` - - // FunctionPathLink adjusts the timestamps of a file or directory. - // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#path_link - FunctionPathLink = "path_link" - - // ImportPathLink is the WebAssembly 1.0 (20191205) Text format import of FunctionPathLink. - ImportPathLink = `(import "wasi_snapshot_preview1" "path_link" - (func $wasi.path_link (param $old_fd i32) (param $old_flags i32) (param $old_path i32) (param $old_path_len i32) (param $new_fd i32) (param $new_path i32) (param $new_path_len i32) (result (;errno;) i32)))` - - // FunctionPathOpen opens a file or directory. - // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-path_openfd-fd-dirflags-lookupflags-path-string-oflags-oflags-fs_rights_base-rights-fs_rights_inheriting-rights-fdflags-fdflags---errno-fd - FunctionPathOpen = "path_open" - - // ImportPathOpen is the WebAssembly 1.0 (20191205) Text format import of FunctionPathOpen. - ImportPathOpen = `(import "wasi_snapshot_preview1" "path_open" - (func $wasi.path_open (param $fd i32) (param $dirflags i32) (param $path i32) (param $path_len i32) (param $oflags i32) (param $fs_rights_base i64) (param $fs_rights_inheriting i64) (param $fdflags i32) (param $result.opened_fd i32) (result (;errno;) i32)))` - - // FunctionPathReadlink reads the contents of a symbolic link. - // See: https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-path_readlinkfd-fd-path-string-buf-pointeru8-buf_len-size---errno-size - FunctionPathReadlink = "path_readlink" - - // ImportPathReadlink is the WebAssembly 1.0 (20191205) Text format import of FunctionPathReadlink. - ImportPathReadlink = `(import "wasi_snapshot_preview1" "path_readlink" - (func $wasi.path_readlink (param $fd i32) (param $path i32) (param $path_len i32) (param $buf i32) (param $buf_len i32) (param $result.bufused i32) (result (;errno;) i32)))` - - // FunctionPathRemoveDirectory removes a directory. - // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-path_remove_directoryfd-fd-path-string---errno - FunctionPathRemoveDirectory = "path_remove_directory" - - // ImportPathRemoveDirectory is the WebAssembly 1.0 (20191205) Text format import of FunctionPathRemoveDirectory. - ImportPathRemoveDirectory = `(import "wasi_snapshot_preview1" "path_remove_directory" - (func $wasi.path_remove_directory (param $fd i32) (param $path i32) (param $path_len i32) (result (;errno;) i32)))` - - // FunctionPathRename renames a file or directory. - // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-path_renamefd-fd-old_path-string-new_fd-fd-new_path-string---errno - FunctionPathRename = "path_rename" - - // ImportPathRename is the WebAssembly 1.0 (20191205) Text format import of FunctionPathRename. - ImportPathRename = `(import "wasi_snapshot_preview1" "path_rename" - (func $wasi.path_rename (param $fd i32) (param $old_path i32) (param $old_path_len i32) (param $new_fd i32) (param $new_path i32) (param $new_path_len i32) (result (;errno;) i32)))` - - // FunctionPathSymlink creates a symbolic link. - // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#path_symlink - FunctionPathSymlink = "path_symlink" - - // ImportPathSymlink is the WebAssembly 1.0 (20191205) Text format import of FunctionPathSymlink. - ImportPathSymlink = `(import "wasi_snapshot_preview1" "path_symlink" - (func $wasi.path_symlink (param $old_path i32) (param $old_path_len i32) (param $fd i32) (param $new_path i32) (param $new_path_len i32) (result (;errno;) i32)))` - - // FunctionPathUnlinkFile unlinks a file. - // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-path_unlink_filefd-fd-path-string---errno - FunctionPathUnlinkFile = "path_unlink_file" - - // ImportPathUnlinkFile is the WebAssembly 1.0 (20191205) Text format import of FunctionPathUnlinkFile. - ImportPathUnlinkFile = `(import "wasi_snapshot_preview1" "path_unlink_file" - (func $wasi.path_unlink_file (param $fd i32) (param $path i32) (param $path_len i32) (result (;errno;) i32)))` - - // FunctionPollOneoff unlinks a file. - // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-poll_oneoffin-constpointersubscription-out-pointerevent-nsubscriptions-size---errno-size - FunctionPollOneoff = "poll_oneoff" - - // ImportPollOneoff is the WebAssembly 1.0 (20191205) Text format import of FunctionPollOneoff. - ImportPollOneoff = `(import "wasi_snapshot_preview1" "poll_oneoff" - (func $wasi.poll_oneoff (param $in i32) (param $out i32) (param $nsubscriptions i32) (param $result.nevents i32) (result (;errno;) i32)))` - - // FunctionProcExit terminates the execution of the module with an exit code. - // See https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md#proc_exit - FunctionProcExit = "proc_exit" - - // ImportProcExit is the WebAssembly 1.0 (20191205) Text format import of FunctionProcExit. - // - // See ImportProcExit - // See SnapshotPreview1.ProcExit - // See FunctionProcExit - // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#proc_exit - ImportProcExit = `(import "wasi_snapshot_preview1" "proc_exit" - (func $wasi.proc_exit (param $rval i32)))` - - // FunctionProcRaise sends a signal to the process of the calling thread. - // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-proc_raisesig-signal---errno - FunctionProcRaise = "proc_raise" - - // ImportProcRaise is the WebAssembly 1.0 (20191205) Text format import of FunctionProcRaise. - ImportProcRaise = `(import "wasi_snapshot_preview1" "proc_raise" - (func $wasi.proc_raise (param $sig i32) (result (;errno;) i32)))` - - // FunctionSchedYield temporarily yields execution of the calling thread. - // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-sched_yield---errno - FunctionSchedYield = "sched_yield" - - // ImportSchedYield is the WebAssembly 1.0 (20191205) Text format import of FunctionSchedYield. - ImportSchedYield = `(import "wasi_snapshot_preview1" "sched_yield" - (func $wasi.sched_yield (result (;errno;) i32)))` - - // FunctionRandomGet writes random data in buffer. - // See: https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-random_getbuf-pointeru8-buf_len-size---errno - FunctionRandomGet = "random_get" - - // ImportRandomGet is the WebAssembly 1.0 (20191205) Text format import of FunctionRandomGet. - ImportRandomGet = `(import "wasi_snapshot_preview1" "random_get" - (func $wasi.random_get (param $buf i32) (param $buf_len i32) (result (;errno;) i32)))` - - // FunctionSockRecv receives a message from a socket. - // See: https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-sock_recvfd-fd-ri_data-iovec_array-ri_flags-riflags---errno-size-roflags - FunctionSockRecv = "sock_recv" - - // ImportSockRecv is the WebAssembly 1.0 (20191205) Text format import of FunctionSockRecv. - ImportSockRecv = `(import "wasi_snapshot_preview1" "sock_recv" - (func $wasi.sock_recv (param $fd i32) (param $ri_data i32) (param $ri_data_count i32) (param $ri_flags i32) (param $result.ro_datalen i32) (param $result.ro_flags i32) (result (;errno;) i32)))` - - // FunctionSockSend sends a message on a socket. - // See: https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-sock_sendfd-fd-si_data-ciovec_array-si_flags-siflags---errno-size - FunctionSockSend = "sock_send" - - // ImportSockSend is the WebAssembly 1.0 (20191205) Text format import of FunctionSockSend. - ImportSockSend = `(import "wasi_snapshot_preview1" "sock_send" - (func $wasi.sock_send (param $fd i32) (param $si_data i32) (param $si_data_count i32) (param $si_flags i32) (param $result.so_datalen i32) (result (;errno;) i32)))` - - // FunctionSockShutdown shuts down socket send and receive channels. - // See: https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-sock_shutdownfd-fd-how-sdflags---errno - FunctionSockShutdown = "sock_shutdown" - - // ImportSockShutdown is the WebAssembly 1.0 (20191205) Text format import of FunctionSockShutdown. - ImportSockShutdown = `(import "wasi_snapshot_preview1" "sock_shutdown" - (func $wasi.sock_shutdown (param $fd i32) (param $how i32) (result (;errno;) i32)))` -) - -// SnapshotPreview1 includes all host functions to export for WASI version wasi.ModuleSnapshotPreview1. -// -// ## Translation notes -// ### String -// WebAssembly 1.0 (20191205) has no string type, so any string input parameter expands to two uint32 parameters: offset -// and length. -// -// ### iovec_array -// `iovec_array` is encoded as two uin32le values (i32): offset and count. -// -// ### Result -// Each result besides wasi.Errno is always an uint32 parameter. WebAssembly 1.0 (20191205) can have up to one result, -// which is already used by wasi.Errno. This forces other results to be parameters. A result parameter is a memory -// offset to write the result to. As memory offsets are uint32, each parameter representing a result is uint32. -// -// ### Errno -// The WASI specification is sometimes ambiguous resulting in some runtimes interpreting the same function ways. -// wasi.Errno mappings are not defined in WASI, yet, so these mappings are best efforts by maintainers. When in doubt -// about portability, first look at internal/wasi/RATIONALE.md and if needed an issue on -// https://github.com/WebAssembly/WASI/issues -// -// ## Memory -// In WebAssembly 1.0 (20191205), there may be up to one Memory per store, which means wasm.Memory is always the -// wasm.Store Memories index zero: `store.Memories[0].Buffer` -// -// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md -// See https://github.com/WebAssembly/WASI/issues/215 -// See https://wwa.w3.org/TR/2019/REC-wasm-core-1-20191205/#memory-instances%E2%91%A0. -type SnapshotPreview1 interface { - // ArgsGet is the WASI function that reads command-line argument data (WithArgs). - // - // There are two parameters. Both are offsets in wasm.Module Memory. If either are invalid due to - // memory constraints, this returns ErrnoFault. - // - // * argv - is the offset to begin writing argument offsets in uint32 little-endian encoding. - // * ArgsSizesGet result argc * 4 bytes are written to this offset - // * argvBuf - is the offset to write the null terminated arguments to m.Memory - // * ArgsSizesGet result argv_buf_size bytes are written to this offset - // - // For example, if ArgsSizesGet wrote argc=2 and argvBufSize=5 for arguments: "a" and "bc" - // parameters argv=7 and argvBuf=1, this function writes the below to `m.Memory`: - // - // argvBufSize uint32le uint32le - // +----------------+ +--------+ +--------+ - // | | | | | | - // []byte{?, 'a', 0, 'b', 'c', 0, ?, 1, 0, 0, 0, 3, 0, 0, 0, ?} - // argvBuf --^ ^ ^ - // argv --| | - // offset that begins "a" --+ | - // offset that begins "bc" --+ - // - // Note: ImportArgsGet shows this signature in the WebAssembly 1.0 (20191205) Text Format. - // See ArgsSizesGet - // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#args_get - // See https://en.wikipedia.org/wiki/Null-terminated_string - ArgsGet(m wasm.Module, argv, argvBuf uint32) wasi.Errno - - // ArgsSizesGet is the WASI function named FunctionArgsSizesGet that reads command-line argument data (WithArgs) - // sizes. - // - // There are two result parameters: these are offsets in the wasm.Module Memory to write - // corresponding sizes in uint32 little-endian encoding. If either are invalid due to memory constraints, this - // returns ErrnoFault. - // - // * resultArgc - is the offset to write the argument count to m.Memory - // * resultArgvBufSize - is the offset to write the null-terminated argument length to m.Memory - // - // For example, if WithArgs are []string{"a","bc"} and - // parameters resultArgc=1 and resultArgvBufSize=6, this function writes the below to `m.Memory`: - // - // uint32le uint32le - // +--------+ +--------+ - // | | | | - // []byte{?, 2, 0, 0, 0, ?, 5, 0, 0, 0, ?} - // resultArgc --^ ^ - // 2 args --+ | - // resultArgvBufSize --| - // len([]byte{'a',0,'b',c',0}) --+ - // - // Note: ImportArgsSizesGet shows this signature in the WebAssembly 1.0 (20191205) Text Format. - // See ArgsGet - // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#args_sizes_get - // See https://en.wikipedia.org/wiki/Null-terminated_string - ArgsSizesGet(m wasm.Module, resultArgc, resultArgvBufSize uint32) wasi.Errno - - // EnvironGet is the WASI function named FunctionEnvironGet that reads environment variables. (WithEnviron) - // - // There are two parameters. Both are offsets in wasm.Module Memory. If either are invalid due to - // memory constraints, this returns ErrnoFault. - // - // * environ - is the offset to begin writing environment variables offsets in uint32 little-endian encoding. - // * EnvironSizesGet result environc * 4 bytes are written to this offset - // * environBuf - is the offset to write the environment variables to m.Memory - // * the format is the same as os.Environ, null terminated "key=val" entries - // * EnvironSizesGet result environBufSize bytes are written to this offset - // - // For example, if EnvironSizesGet wrote environc=2 and environBufSize=9 for environment variables: "a=b", "b=cd" - // and parameters environ=11 and environBuf=1, this function writes the below to `m.Memory`: - // - // environBufSize uint32le uint32le - // +------------------------------------+ +--------+ +--------+ - // | | | | | | - // []byte{?, 'a', '=', 'b', 0, 'b', '=', 'c', 'd', 0, ?, 1, 0, 0, 0, 5, 0, 0, 0, ?} - // environBuf --^ ^ ^ - // environ offset for "a=b" --+ | - // environ offset for "b=cd" --+ - // - // Note: ImportEnvironGet shows this signature in the WebAssembly 1.0 (20191205) Text Format. - // See EnvironSizesGet - // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#environ_get - // See https://en.wikipedia.org/wiki/Null-terminated_string - EnvironGet(m wasm.Module, environ, environBuf uint32) wasi.Errno - - // EnvironSizesGet is the WASI function named FunctionEnvironSizesGet that reads environment variable - // (WithEnviron) sizes. - // - // There are two result parameters: these are offsets in the wasi.Module Memory to write - // corresponding sizes in uint32 little-endian encoding. If either are invalid due to memory constraints, this - // returns ErrnoFault. - // - // * resultEnvironc - is the offset to write the environment variable count to m.Memory - // * resultEnvironBufSize - is the offset to write the null-terminated environment variable length to m.Memory - // - // For example, if WithEnviron is []string{"a=b","b=cd"} and - // parameters resultEnvironc=1 and resultEnvironBufSize=6, this function writes the below to `m.Memory`: - // - // uint32le uint32le - // +--------+ +--------+ - // | | | | - // []byte{?, 2, 0, 0, 0, ?, 9, 0, 0, 0, ?} - // resultEnvironc --^ ^ - // 2 variables --+ | - // resultEnvironBufSize --| - // len([]byte{'a','=','b',0, | - // 'b','=','c','d',0}) --+ - // - // Note: ImportEnvironGet shows this signature in the WebAssembly 1.0 (20191205) Text Format. - // See EnvironGet - // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#environ_sizes_get - // See https://en.wikipedia.org/wiki/Null-terminated_string - EnvironSizesGet(m wasm.Module, resultEnvironc, resultEnvironBufSize uint32) wasi.Errno - - // ClockResGet is the WASI function named FunctionClockResGet and is stubbed for GrainLang per #271 - ClockResGet(m wasm.Module, id uint32, resultResolution uint32) wasi.Errno - - // ClockTimeGet is the WASI function named FunctionClockTimeGet that returns the time value of a clock (time.Now). - // - // * id - The clock id for which to return the time. - // * precision - The maximum lag (exclusive) that the returned time value may have, compared to its actual value. - // * resultTimestamp - the offset to write the timestamp to m.Memory - // * the timestamp is epoch nanoseconds encoded as a uint64 little-endian encoding. - // - // For example, if time.Now returned exactly midnight UTC 2022-01-01 (1640995200000000000), and - // parameters resultTimestamp=1, this function writes the below to `m.Memory`: - // - // uint64le - // +------------------------------------------+ - // | | - // []byte{?, 0x0, 0x0, 0x1f, 0xa6, 0x70, 0xfc, 0xc5, 0x16, ?} - // resultTimestamp --^ - // - // Note: ImportClockTimeGet shows this signature in the WebAssembly 1.0 (20191205) Text Format. - // Note: This is similar to `clock_gettime` in POSIX. - // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-clock_time_getid-clockid-precision-timestamp---errno-timestamp - // See https://linux.die.net/man/3/clock_gettime - ClockTimeGet(m wasm.Module, id uint32, precision uint64, resultTimestamp uint32) wasi.Errno - - // FdAdvise is the WASI function named FunctionFdAdvise and is stubbed for GrainLang per #271 - FdAdvise(m wasm.Module, fd uint32, offset, len uint64, resultAdvice uint32) wasi.Errno - - // FdAllocate is the WASI function named FunctionFdAllocate and is stubbed for GrainLang per #271 - FdAllocate(m wasm.Module, fd uint32, offset, len uint64, resultAdvice uint32) wasi.Errno - - // FdClose is the WASI function to close a file descriptor. This returns ErrnoBadf if the fd is invalid. - // - // * fd - the file descriptor to close - // - // Note: ImportFdClose shows this signature in the WebAssembly 1.0 (20191205) Text Format. - // Note: This is similar to `close` in POSIX. - // See https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md#fd_close - // See https://linux.die.net/man/3/close - FdClose(m wasm.Module, fd uint32) wasi.Errno - - // FdDatasync is the WASI function named FunctionFdDatasync and is stubbed for GrainLang per #271 - FdDatasync(m wasm.Module, fd uint32) wasi.Errno - - // FdFdstatGet is the WASI function to return the attributes of a file descriptor. - // - // * fd - the file descriptor to get the fdstat attributes data - // * resultFdstat - the offset to write the result fdstat data - // - // The wasi.Errno returned is wasi.ErrnoSuccess except the following error conditions: - // * wasi.ErrnoBadf - if `fd` is invalid - // * wasi.ErrnoFault - if `resultFdstat` contains an invalid offset due to the memory constraint - // - // fdstat byte layout is 24-byte size, which as the following elements in order - // * fs_filetype 1 byte, to indicate the file type - // * fs_flags 2 bytes, to indicate the file descriptor flag - // * 5 pad bytes - // * fs_right_base 8 bytes, to indicate the current rights of the fd - // * fs_right_inheriting 8 bytes, to indicate the maximum rights of the fd - // - // For example, with a file corresponding with `fd` was a directory (=3) opened with `fd_read` right (=1) and no fs_flags (=0), - // parameter resultFdstat=1, this function writes the below to `m.Memory`: - // - // uint16le padding uint64le uint64le - // uint8 --+ +--+ +-----------+ +--------------------+ +--------------------+ - // | | | | | | | | | - // []byte{?, 3, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0} - // resultFdstat --^ ^-- fs_flags ^-- fs_right_base ^-- fs_right_inheriting - // | - // +-- fs_filetype - // - // Note: ImportFdFdstatGet shows this signature in the WebAssembly 1.0 (20191205) Text Format. - // Note: FdFdstatGet returns similar flags to `fsync(fd, F_GETFL)` in POSIX, as well as additional fields. - // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#fdstat - // See https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md#fd_fdstat_get - // See https://linux.die.net/man/3/fsync - FdFdstatGet(m wasm.Module, fd, resultFdstat uint32) wasi.Errno - - // FdFdstatSetFlags is the WASI function named FunctionFdFdstatSetFlags and is stubbed for GrainLang per #271 - FdFdstatSetFlags(m wasm.Module, fd uint32, flags uint32) wasi.Errno - - // FdFdstatSetRights is the WASI function named FunctionFdFdstatSetRights and is stubbed for GrainLang per #271 - FdFdstatSetRights(m wasm.Module, fd uint32, fsRightsBase, fsRightsInheriting uint64) wasi.Errno - - // FdFilestatGet is the WASI function named FunctionFdFilestatGet - FdFilestatGet(m wasm.Module, fd uint32, resultBuf uint32) wasi.Errno - - // FdFilestatSetSize is the WASI function named FunctionFdFilestatSetSize - FdFilestatSetSize(m wasm.Module, fd uint32, size uint64) wasi.Errno - - // FdFilestatSetTimes is the WASI function named FunctionFdFilestatSetTimes - FdFilestatSetTimes(m wasm.Module, fd uint32, atim, mtim uint64, fstFlags uint32) wasi.Errno - - // FdPread is the WASI function named FunctionFdPread - FdPread(m wasm.Module, fd, iovs uint32, offset uint64, resultNread uint32) wasi.Errno - - // FdPrestatGet is the WASI function to return the prestat data of a file descriptor. - // - // * fd - the file descriptor to get the prestat - // * resultPrestat - the offset to write the result prestat data - // - // The wasi.Errno returned is wasi.ErrnoSuccess except the following error conditions: - // * wasi.ErrnoBadf - if `fd` is invalid or the `fd` is not a pre-opened directory. - // * wasi.ErrnoFault - if `resultPrestat` is an invalid offset due to the memory constraint - // - // prestat byte layout is 8 bytes, beginning with an 8-bit tag and 3 pad bytes. The only valid tag is `prestat_dir`, - // which is tag zero. This simplifies the byte layout to 4 empty bytes followed by the uint32le encoded path length. - // - // For example, the directory name corresponding with `fd` was "/tmp" and - // parameter resultPrestat=1, this function writes the below to `m.Memory`: - // - // padding uint32le - // uint8 --+ +-----+ +--------+ - // | | | | | - // []byte{?, 0, 0, 0, 0, 4, 0, 0, 0, ?} - // resultPrestat --^ ^ - // tag --+ | - // +-- size in bytes of the string "/tmp" - // - // Note: ImportFdPrestatGet shows this signature in the WebAssembly 1.0 (20191205) Text Format. - // See FdPrestatDirName - // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#prestat - // See https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md#fd_prestat_get - FdPrestatGet(m wasm.Module, fd uint32, resultPrestat uint32) wasi.Errno - - // FdPrestatDirName is the WASI function to return the path of the pre-opened directory of a file descriptor. - // - // * fd - the file descriptor to get the path of the pre-opened directory - // * path - the offset in `m.Memory` to write the result path - // * pathLen - the count of bytes to write to `path` - // * This should match the uint32le FdPrestatGet writes to offset `resultPrestat`+4 - // - // The wasi.Errno returned is wasi.ErrnoSuccess except the following error conditions: - // * wasi.ErrnoBadf - if `fd` is invalid - // * wasi.ErrnoFault - if `path` is an invalid offset due to the memory constraint - // * wasi.ErrnoNametoolong - if `pathLen` is longer than the actual length of the result path - // - // For example, the directory name corresponding with `fd` was "/tmp" and - // parameters path=1 pathLen=4 (correct), this function will write the below to `m.Memory`: - // - // pathLen - // +--------------+ - // | | - // []byte{?, '/', 't', 'm', 'p', ?} - // path --^ - // - // Note: ImportFdPrestatDirName shows this signature in the WebAssembly 1.0 (20191205) Text Format. - // See FdPrestatGet - // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#fd_prestat_dir_name - FdPrestatDirName(m wasm.Module, fd, path, pathLen uint32) wasi.Errno - // TODO: FdPrestatDirName may have to return ErrnoNotdir if the type of the prestat data of `fd` is not a PrestatDir. - - // FdPwrite is the WASI function named FunctionFdPwrite - FdPwrite(m wasm.Module, fd, iovs uint32, offset uint64, resultNwritten uint32) wasi.Errno - - // FdRead is the WASI function to read from a file descriptor. - // - // * fd - an opened file descriptor to read data from - // * iovs - the offset in `m.Memory` to read offset, size pairs representing where to write file data. - // * Both offset and length are encoded as uint32le. - // * iovsCount - the count of memory offset, size pairs to read sequentially starting at iovs. - // * resultSize - the offset in `m.Memory` to write the number of bytes read - // - // The wasi.Errno returned is wasi.ErrnoSuccess except the following error conditions: - // * wasi.ErrnoBadf - if `fd` is invalid - // * wasi.ErrnoFault - if `iovs` or `resultSize` contain an invalid offset due to the memory constraint - // * wasi.ErrnoIo - if an IO related error happens during the operation - // - // For example, this function needs to first read `iovs` to determine where to write contents. If - // parameters iovs=1 iovsCount=2, this function reads two offset/length pairs from `m.Memory`: - // - // iovs[0] iovs[1] - // +---------------------+ +--------------------+ - // | uint32le uint32le| |uint32le uint32le| - // +---------+ +--------+ +--------+ +--------+ - // | | | | | | | | - // []byte{?, 18, 0, 0, 0, 4, 0, 0, 0, 23, 0, 0, 0, 2, 0, 0, 0, ?... } - // iovs --^ ^ ^ ^ - // | | | | - // offset --+ length --+ offset --+ length --+ - // - // If the contents of the `fd` parameter was "wazero" (6 bytes) and - // parameter resultSize=26, this function writes the below to `m.Memory`: - // - // iovs[0].length iovs[1].length - // +--------------+ +----+ uint32le - // | | | | +--------+ - // []byte{ 0..16, ?, 'w', 'a', 'z', 'e', ?, 'r', 'o', ?, 6, 0, 0, 0 } - // iovs[0].offset --^ ^ ^ - // iovs[1].offset --+ | - // resultSize --+ - // - // Note: ImportFdRead shows this signature in the WebAssembly 1.0 (20191205) Text Format. - // Note: This is similar to `readv` in POSIX. - // See FdWrite - // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#fd_read - // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#iovec - // See https://linux.die.net/man/3/readv - FdRead(m wasm.Module, fd, iovs, iovsCount, resultSize uint32) wasi.Errno - - // FdReaddir is the WASI function named FunctionFdReaddir - FdReaddir(m wasm.Module, fd, buf, bufLen uint32, cookie uint64, resultBufused uint32) wasi.Errno - - // FdRenumber is the WASI function named FunctionFdRenumber - FdRenumber(m wasm.Module, fd, to uint32) wasi.Errno - - // FdSeek is the WASI function to move the offset of a file descriptor. - // - // * fd: the file descriptor to move the offset of - // * offset: the signed int64, which is encoded as uint64, input argument to `whence`, which results in a new offset - // * whence: the operator that creates the new offset, given `offset` bytes - // * If io.SeekStart, new offset == `offset`. - // * If io.SeekCurrent, new offset == existing offset + `offset`. - // * If io.SeekEnd, new offset == file size of `fd` + `offset`. - // * resultNewoffset: the offset in `m.Memory` to write the new offset to, relative to start of the file - // - // The wasi.Errno returned is wasi.ErrnoSuccess except the following error conditions: - // * wasi.ErrnoBadf - if `fd` is invalid - // * wasi.ErrnoFault - if `resultNewoffset` is an invalid offset in `m.Memory` due to the memory constraint - // * wasi.ErrnoInval - if `whence` is an invalid value - // * wasi.ErrnoIo - if other error happens during the operation of the underying file system - // - // For example, if fd 3 is a file with offset 0, and - // parameters fd=3, offset=4, whence=0 (=io.SeekStart), resultNewOffset=1, - // this function writes the below to `m.Memory`: - // - // uint64le - // +--------------------+ - // | | - // []byte{?, 4, 0, 0, 0, 0, 0, 0, 0, ? } - // resultNewoffset --^ - // - // See io.Seeker - // Note: ImportFdSeek shows this signature in the WebAssembly 1.0 (20191205) Text Format. - // Note: This is similar to `lseek` in POSIX. - // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#fd_seek - // See https://linux.die.net/man/3/lseek - FdSeek(m wasm.Module, fd uint32, offset uint64, whence uint32, resultNewoffset uint32) wasi.Errno - - // FdSync is the WASI function named FunctionFdSync - FdSync(m wasm.Module, fd uint32) wasi.Errno - - // FdTell is the WASI function named FunctionFdTell - FdTell(m wasm.Module, fd, resultOffset uint32) wasi.Errno - - // FdWrite is the WASI function to write to a file descriptor. - // - // * fd - an opened file descriptor to write data to - // * iovs - the offset in `m.Memory` to read offset, size pairs representing the data to write to `fd` - // * Both offset and length are encoded as uint32le. - // * iovsCount - the count of memory offset, size pairs to read sequentially starting at iovs. - // * resultSize - the offset in `m.Memory` to write the number of bytes written - // - // The wasi.Errno returned is wasi.ErrnoSuccess except the following error conditions: - // * wasi.ErrnoBadf - if `fd` is invalid - // * wasi.ErrnoFault - if `iovs` or `resultSize` contain an invalid offset due to the memory constraint - // * wasi.ErrnoIo - if an IO related error happens during the operation - // - // For example, this function needs to first read `iovs` to determine what to write to `fd`. If - // parameters iovs=1 iovsCount=2, this function reads two offset/length pairs from `m.Memory`: - // - // iovs[0] iovs[1] - // +---------------------+ +--------------------+ - // | uint32le uint32le| |uint32le uint32le| - // +---------+ +--------+ +--------+ +--------+ - // | | | | | | | | - // []byte{?, 18, 0, 0, 0, 4, 0, 0, 0, 23, 0, 0, 0, 2, 0, 0, 0, ?... } - // iovs --^ ^ ^ ^ - // | | | | - // offset --+ length --+ offset --+ length --+ - // - // This function reads those chunks `m.Memory` into the `fd` sequentially. - // - // iovs[0].length iovs[1].length - // +--------------+ +----+ - // | | | | - // []byte{ 0..16, ?, 'w', 'a', 'z', 'e', ?, 'r', 'o', ? } - // iovs[0].offset --^ ^ - // iovs[1].offset --+ - // - // Since "wazero" was written, if parameter resultSize=26, this function writes the below to `m.Memory`: - // - // uint32le - // +--------+ - // | | - // []byte{ 0..24, ?, 6, 0, 0, 0', ? } - // resultSize --^ - // - // Note: ImportFdWrite shows this signature in the WebAssembly 1.0 (20191205) Text Format. - // Note: This is similar to `writev` in POSIX. - // See FdRead - // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#ciovec - // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#fd_write - // See https://linux.die.net/man/3/writev - FdWrite(m wasm.Module, fd, iovs, iovsCount, resultSize uint32) wasi.Errno - - // PathCreateDirectory is the WASI function named FunctionPathCreateDirectory - PathCreateDirectory(m wasm.Module, fd, path, pathLen uint32) wasi.Errno - - // PathFilestatGet is the WASI function named FunctionPathFilestatGet - PathFilestatGet(m wasm.Module, fd, flags, path, pathLen, resultBuf uint32) wasi.Errno - - // PathFilestatSetTimes is the WASI function named FunctionPathFilestatSetTimes - PathFilestatSetTimes(m wasm.Module, fd, flags, path, pathLen uint32, atim, mtime uint64, fstFlags uint32) wasi.Errno - - // PathLink is the WASI function named FunctionPathLink - PathLink(m wasm.Module, oldFd, oldFlags, oldPath, oldPathLen, newFd, newPath, newPathLen uint32) wasi.Errno - - // PathOpen is the WASI function to open a file or directory. This returns ErrnoBadf if the fd is invalid. - // - // * fd - the file descriptor of a directory that `path` is relative to - // * dirflags - flags to indicate how to resolve `path` - // * path - the offset in `m.Memory` to read the path string from - // * pathLen - the length of `path` - // * oFlags - the open flags to indicate the method by which to open the file - // * fsRightsBase - the rights of the newly created file descriptor for `path` - // * fsRightsInheriting - the rights of the file descriptors derived from the newly created file descriptor for `path` - // * fdFlags - the file descriptor flags - // * resultOpenedFd - the offset in `m.Memory` to write the newly created file descriptor to. - // * The result FD value is guaranteed to be less than 2**31 - // - // The wasi.Errno returned is wasi.ErrnoSuccess except the following error conditions: - // * wasi.ErrnoBadf - if `fd` is invalid - // * wasi.ErrnoFault - if `resultOpenedFd` contains an invalid offset due to the memory constraint - // * wasi.ErrnoNoent - if `path` does not exist. - // * wasi.ErrnoExist - if `path` exists, while `oFlags` requires that it must not. - // * wasi.ErrnoNotdir - if `path` is not a directory, while `oFlags` requires that it must be. - // * wasi.ErrnoIo - if other error happens during the operation of the underying file system. - // - // For example, this function needs to first read `path` to determine the file to open. - // If parameters `path` = 1, `pathLen` = 6, and the path is "wazero", PathOpen reads the path from `m.Memory`: - // - // pathLen - // +------------------------+ - // | | - // []byte{ ?, 'w', 'a', 'z', 'e', 'r', 'o', ?... } - // path --^ - // - // Then, if parameters resultOpenedFd = 8, and this function opened a new file descriptor 5 with the given flags, - // this function writes the blow to `m.Memory`: - // - // uint32le - // +--------+ - // | | - // []byte{ 0..6, ?, 5, 0, 0, 0, ?} - // resultOpenedFd --^ - // - // Note: ImportPathOpen shows this signature in the WebAssembly 1.0 (20191205) Text Format. - // Note: This is similar to `openat` in POSIX. - // Note: The returned file descriptor is not guaranteed to be the lowest-numbered file - // See https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md#path_open - // See https://linux.die.net/man/3/openat - PathOpen(m wasm.Module, fd, dirflags, path, pathLen, oflags uint32, fsRightsBase, fsRightsInheriting uint32, fdflags, resultOpenedFd uint32) wasi.Errno - - // PathReadlink is the WASI function named FunctionPathReadlink - PathReadlink(m wasm.Module, fd, path, pathLen, buf, bufLen, resultBufused uint32) wasi.Errno - - // PathRemoveDirectory is the WASI function named FunctionPathRemoveDirectory - PathRemoveDirectory(m wasm.Module, fd, path, pathLen uint32) wasi.Errno - - // PathRename is the WASI function named FunctionPathRename - PathRename(m wasm.Module, fd, oldPath, oldPathLen, newFd, newPath, newPathLen uint32) wasi.Errno - - // PathSymlink is the WASI function named FunctionPathSymlink - PathSymlink(m wasm.Module, oldPath, oldPathLen, fd, newPath, newPathLen uint32) wasi.Errno - - // PathUnlinkFile is the WASI function named FunctionPathUnlinkFile - PathUnlinkFile(m wasm.Module, fd, path, pathLen uint32) wasi.Errno - - // PollOneoff is the WASI function named FunctionPollOneoff - PollOneoff(m wasm.Module, in, out, nsubscriptions, resultNevents uint32) wasi.Errno - - // ProcExit is the WASI function that terminates the execution of the module with an exit code. - // An exit code of 0 indicates successful termination. The meanings of other values are not defined by WASI. - // - // * rval - The exit code. - // - // In wazero, this calls wasm.Module CloseWithExitCode. - // - // Note: ImportProcExit shows this signature in the WebAssembly 1.0 (20191205) Text Format. - // See https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md#proc_exit - ProcExit(m wasm.Module, rval uint32) - - // ProcRaise is the WASI function named FunctionProcRaise - ProcRaise(m wasm.Module, sig uint32) wasi.Errno - - // SchedYield is the WASI function named FunctionSchedYield - SchedYield(m wasm.Module) wasi.Errno - - // RandomGet is the WASI function named FunctionRandomGet that write random data in buffer (rand.Read()). - // - // * buf - is the m.Memory offset to write random values - // * bufLen - size of random data in bytes - // - // For example, if underlying random source was seeded like `rand.NewSource(42)`, we expect `m.Memory` to contain: - // - // bufLen (5) - // +--------------------------+ - // | | - // []byte{?, 0x53, 0x8c, 0x7f, 0x96, 0xb1, ?} - // buf --^ - // - // Note: ImportRandomGet shows this signature in the WebAssembly 1.0 (20191205) Text Format. - // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-random_getbuf-pointeru8-bufLen-size---errno - RandomGet(m wasm.Module, buf, bufLen uint32) wasi.Errno - - // SockRecv is the WASI function named FunctionSockRecv - SockRecv(m wasm.Module, fd, riData, riDataCount, riFlags, resultRoDataLen, resultRoFlags uint32) wasi.Errno - - // SockSend is the WASI function named FunctionSockSend - SockSend(m wasm.Module, fd, siData, siDataCount, siFlags, resultSoDataLen uint32) wasi.Errno - - // SockShutdown is the WASI function named FunctionSockShutdown - SockShutdown(m wasm.Module, fd, how uint32) wasi.Errno -} - -type wasiAPI struct { - // timeNowUnixNano is mutable for testing - timeNowUnixNano func() uint64 - randSource func([]byte) error -} - -// SnapshotPreview1Functions returns all go functions that implement SnapshotPreview1. -// These should be exported in the module named wasi.ModuleSnapshotPreview1. -// See internalwasm.NewHostModule -func SnapshotPreview1Functions() (a *wasiAPI, nameToGoFunc map[string]interface{}) { - a = NewAPI() - // Note: these are ordered per spec for consistency even if the resulting map can't guarantee that. - // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#functions - nameToGoFunc = map[string]interface{}{ - FunctionArgsGet: a.ArgsGet, - FunctionArgsSizesGet: a.ArgsSizesGet, - FunctionEnvironGet: a.EnvironGet, - FunctionEnvironSizesGet: a.EnvironSizesGet, - FunctionClockResGet: a.ClockResGet, - FunctionClockTimeGet: a.ClockTimeGet, - FunctionFdAdvise: a.FdAdvise, - FunctionFdAllocate: a.FdAllocate, - FunctionFdClose: a.FdClose, - FunctionFdDatasync: a.FdDatasync, - FunctionFdFdstatGet: a.FdFdstatGet, - FunctionFdFdstatSetFlags: a.FdFdstatSetFlags, - FunctionFdFdstatSetRights: a.FdFdstatSetRights, - FunctionFdFilestatGet: a.FdFilestatGet, - FunctionFdFilestatSetSize: a.FdFilestatSetSize, - FunctionFdFilestatSetTimes: a.FdFilestatSetTimes, - FunctionFdPread: a.FdPread, - FunctionFdPrestatGet: a.FdPrestatGet, - FunctionFdPrestatDirName: a.FdPrestatDirName, - FunctionFdPwrite: a.FdPwrite, - FunctionFdRead: a.FdRead, - FunctionFdReaddir: a.FdReaddir, - FunctionFdRenumber: a.FdRenumber, - FunctionFdSeek: a.FdSeek, - FunctionFdSync: a.FdSync, - FunctionFdTell: a.FdTell, - FunctionFdWrite: a.FdWrite, - FunctionPathCreateDirectory: a.PathCreateDirectory, - FunctionPathFilestatGet: a.PathFilestatGet, - FunctionPathFilestatSetTimes: a.PathFilestatSetTimes, - FunctionPathLink: a.PathLink, - FunctionPathOpen: a.PathOpen, - FunctionPathReadlink: a.PathReadlink, - FunctionPathRemoveDirectory: a.PathRemoveDirectory, - FunctionPathRename: a.PathRename, - FunctionPathSymlink: a.PathSymlink, - FunctionPathUnlinkFile: a.PathUnlinkFile, - FunctionPollOneoff: a.PollOneoff, - FunctionProcExit: a.ProcExit, - FunctionProcRaise: a.ProcRaise, - FunctionSchedYield: a.SchedYield, - FunctionRandomGet: a.RandomGet, - FunctionSockRecv: a.SockRecv, - FunctionSockSend: a.SockSend, - FunctionSockShutdown: a.SockShutdown, - } - return -} - -// ArgsGet implements SnapshotPreview1.ArgsGet -func (a *wasiAPI) ArgsGet(m wasm.Module, argv, argvBuf uint32) wasi.Errno { - sys := sysCtx(m) - return writeOffsetsAndNullTerminatedValues(m.Memory(), sys.Args(), argv, argvBuf) -} - -// ArgsSizesGet implements SnapshotPreview1.ArgsSizesGet -func (a *wasiAPI) ArgsSizesGet(m wasm.Module, resultArgc, resultArgvBufSize uint32) wasi.Errno { - sys := sysCtx(m) - mem := m.Memory() - - if !mem.WriteUint32Le(resultArgc, uint32(len(sys.Args()))) { - return wasi.ErrnoFault - } - if !mem.WriteUint32Le(resultArgvBufSize, sys.ArgsSize()) { - return wasi.ErrnoFault - } - return wasi.ErrnoSuccess -} - -// EnvironGet implements SnapshotPreview1.EnvironGet -func (a *wasiAPI) EnvironGet(m wasm.Module, environ uint32, environBuf uint32) wasi.Errno { - sys := sysCtx(m) - return writeOffsetsAndNullTerminatedValues(m.Memory(), sys.Environ(), environ, environBuf) -} - -// EnvironSizesGet implements SnapshotPreview1.EnvironSizesGet -func (a *wasiAPI) EnvironSizesGet(m wasm.Module, resultEnvironc uint32, resultEnvironBufSize uint32) wasi.Errno { - sys := sysCtx(m) - mem := m.Memory() - - if !mem.WriteUint32Le(resultEnvironc, uint32(len(sys.Environ()))) { - return wasi.ErrnoFault - } - if !mem.WriteUint32Le(resultEnvironBufSize, sys.EnvironSize()) { - return wasi.ErrnoFault - } - - return wasi.ErrnoSuccess -} - -// ClockResGet implements SnapshotPreview1.ClockResGet -func (a *wasiAPI) ClockResGet(m wasm.Module, id uint32, resultResolution uint32) wasi.Errno { - return wasi.ErrnoNosys // stubbed for GrainLang per #271 -} - -// ClockTimeGet implements SnapshotPreview1.ClockTimeGet -func (a *wasiAPI) ClockTimeGet(m wasm.Module, id uint32, precision uint64, resultTimestamp uint32) wasi.Errno { - // TODO: id and precision are currently ignored. - if !m.Memory().WriteUint64Le(resultTimestamp, a.timeNowUnixNano()) { - return wasi.ErrnoFault - } - return wasi.ErrnoSuccess -} - -// FdAdvise implements SnapshotPreview1.FdAdvise -func (a *wasiAPI) FdAdvise(m wasm.Module, fd uint32, offset, len uint64, resultAdvice uint32) wasi.Errno { - return wasi.ErrnoNosys // stubbed for GrainLang per #271 -} - -// FdAllocate implements SnapshotPreview1.FdAllocate -func (a *wasiAPI) FdAllocate(m wasm.Module, fd uint32, offset, len uint64) wasi.Errno { - return wasi.ErrnoNosys // stubbed for GrainLang per #271 -} - -// FdClose implements SnapshotPreview1.FdClose -func (a *wasiAPI) FdClose(m wasm.Module, fd uint32) wasi.Errno { - sys := sysCtx(m) - - if ok, err := sys.CloseFile(fd); err != nil { - return wasi.ErrnoIo - } else if !ok { - return wasi.ErrnoBadf - } - - return wasi.ErrnoSuccess -} - -// FdDatasync implements SnapshotPreview1.FdDatasync -func (a *wasiAPI) FdDatasync(m wasm.Module, fd uint32) wasi.Errno { - return wasi.ErrnoNosys // stubbed for GrainLang per #271 -} - -// FdFdstatGet implements SnapshotPreview1.FdFdstatGet -func (a *wasiAPI) FdFdstatGet(m wasm.Module, fd uint32, resultStat uint32) wasi.Errno { - sys := sysCtx(m) - - if _, ok := sys.OpenedFile(fd); !ok { - return wasi.ErrnoBadf - } - return wasi.ErrnoSuccess -} - -// FdPrestatGet implements SnapshotPreview1.FdPrestatGet -func (a *wasiAPI) FdPrestatGet(m wasm.Module, fd uint32, resultPrestat uint32) wasi.Errno { - sys := sysCtx(m) - - entry, ok := sys.OpenedFile(fd) - if !ok { - return wasi.ErrnoBadf - } - - // Zero-value 8-bit tag, and 3-byte zero-value paddings, which is uint32le(0) in short. - if !m.Memory().WriteUint32Le(resultPrestat, uint32(0)) { - return wasi.ErrnoFault - } - // Write the length of the directory name at offset 4. - if !m.Memory().WriteUint32Le(resultPrestat+4, uint32(len(entry.Path))) { - return wasi.ErrnoFault - } - - return wasi.ErrnoSuccess -} - -// FdFdstatSetFlags implements SnapshotPreview1.FdFdstatSetFlags -func (a *wasiAPI) FdFdstatSetFlags(m wasm.Module, fd uint32, flags uint32) wasi.Errno { - return wasi.ErrnoNosys // stubbed for GrainLang per #271 -} - -// FdFdstatSetRights implements SnapshotPreview1.FdFdstatSetRights -// Note: This will never be implemented per https://github.com/WebAssembly/WASI/issues/469#issuecomment-1045251844 -func (a *wasiAPI) FdFdstatSetRights(m wasm.Module, fd uint32, fsRightsBase, fsRightsInheriting uint64) wasi.Errno { - return wasi.ErrnoNosys // stubbed for GrainLang per #271 -} - -// FdFilestatGet implements SnapshotPreview1.FdFilestatGet -func (a *wasiAPI) FdFilestatGet(m wasm.Module, fd uint32, resultBuf uint32) wasi.Errno { - return wasi.ErrnoNosys // stubbed for GrainLang per #271 -} - -// FdFilestatSetSize implements SnapshotPreview1.FdFilestatSetSize -func (a *wasiAPI) FdFilestatSetSize(m wasm.Module, fd uint32, size uint64) wasi.Errno { - return wasi.ErrnoNosys // stubbed for GrainLang per #271 -} - -// FdFilestatSetTimes implements SnapshotPreview1.FdFilestatSetTimes -func (a *wasiAPI) FdFilestatSetTimes(m wasm.Module, fd uint32, atim, mtim uint64, fstFlags uint32) wasi.Errno { - return wasi.ErrnoNosys // stubbed for GrainLang per #271 -} - -// FdPread implements SnapshotPreview1.FdPread -func (a *wasiAPI) FdPread(m wasm.Module, fd, iovs, iovsCount uint32, offset uint64, resultNread uint32) wasi.Errno { - return wasi.ErrnoNosys // stubbed for GrainLang per #271 -} - -// FdPrestatDirName implements SnapshotPreview1.FdPrestatDirName -func (a *wasiAPI) FdPrestatDirName(m wasm.Module, fd uint32, pathPtr uint32, pathLen uint32) wasi.Errno { - sys := sysCtx(m) - - f, ok := sys.OpenedFile(fd) - if !ok { - return wasi.ErrnoBadf - } - - // Some runtimes may have another semantics. See internal/wasi/RATIONALE.md - if uint32(len(f.Path)) < pathLen { - return wasi.ErrnoNametoolong - } - - // TODO: FdPrestatDirName may have to return ErrnoNotdir if the type of the prestat data of `fd` is not a PrestatDir. - if !m.Memory().Write(pathPtr, []byte(f.Path)[:pathLen]) { - return wasi.ErrnoFault - } - return wasi.ErrnoSuccess -} - -// FdPwrite implements SnapshotPreview1.FdPwrite -func (a *wasiAPI) FdPwrite(m wasm.Module, fd, iovs, iovsCount uint32, offset uint64, resultNwritten uint32) wasi.Errno { - return wasi.ErrnoNosys // stubbed for GrainLang per #271 -} - -// FdRead implements SnapshotPreview1.FdRead -func (a *wasiAPI) FdRead(m wasm.Module, fd, iovs, iovsCount, resultSize uint32) wasi.Errno { - sys := sysCtx(m) - - var reader io.Reader - - if fd == fdStdin { - reader = sys.Stdin() - } else if f, ok := sys.OpenedFile(fd); !ok || f.File == nil { - return wasi.ErrnoBadf - } else { - reader = f.File - } - - var nread uint32 - for i := uint32(0); i < iovsCount; i++ { - iovPtr := iovs + i*8 - offset, ok := m.Memory().ReadUint32Le(iovPtr) - if !ok { - return wasi.ErrnoFault - } - l, ok := m.Memory().ReadUint32Le(iovPtr + 4) - if !ok { - return wasi.ErrnoFault - } - b, ok := m.Memory().Read(offset, l) - if !ok { - return wasi.ErrnoFault - } - n, err := reader.Read(b) - nread += uint32(n) - if errors.Is(err, io.EOF) { - break - } else if err != nil { - return wasi.ErrnoIo - } - } - if !m.Memory().WriteUint32Le(resultSize, nread) { - return wasi.ErrnoFault - } - return wasi.ErrnoSuccess -} - -// FdReaddir implements SnapshotPreview1.FdReaddir -func (a *wasiAPI) FdReaddir(m wasm.Module, fd, buf, bufLen uint32, cookie uint64, resultBufused uint32) wasi.Errno { - return wasi.ErrnoNosys // stubbed for GrainLang per #271 -} - -// FdRenumber implements SnapshotPreview1.FdRenumber -func (a *wasiAPI) FdRenumber(m wasm.Module, fd, to uint32) wasi.Errno { - return wasi.ErrnoNosys // stubbed for GrainLang per #271 -} - -// FdSeek implements SnapshotPreview1.FdSeek -func (a *wasiAPI) FdSeek(m wasm.Module, fd uint32, offset uint64, whence uint32, resultNewoffset uint32) wasi.Errno { - sys := sysCtx(m) - - var seeker io.Seeker - // Check to see if the file descriptor is available - if f, ok := sys.OpenedFile(fd); !ok || f.File == nil { - return wasi.ErrnoBadf - // fs.FS doesn't declare io.Seeker, but implementations such as os.File implement it. - } else if seeker, ok = f.File.(io.Seeker); !ok { - return wasi.ErrnoBadf - } - - if whence > io.SeekEnd /* exceeds the largest valid whence */ { - return wasi.ErrnoInval - } - newOffset, err := seeker.Seek(int64(offset), int(whence)) - if err != nil { - return wasi.ErrnoIo - } - - if !m.Memory().WriteUint32Le(resultNewoffset, uint32(newOffset)) { - return wasi.ErrnoFault - } - - return wasi.ErrnoSuccess -} - -// FdSync implements SnapshotPreview1.FdSync -func (a *wasiAPI) FdSync(m wasm.Module, fd uint32) wasi.Errno { - return wasi.ErrnoNosys // stubbed for GrainLang per #271 -} - -// FdTell implements SnapshotPreview1.FdTell -func (a *wasiAPI) FdTell(m wasm.Module, fd, resultOffset uint32) wasi.Errno { - return wasi.ErrnoNosys // stubbed for GrainLang per #271 -} - -// FdWrite implements SnapshotPreview1.FdWrite -func (a *wasiAPI) FdWrite(m wasm.Module, fd, iovs, iovsCount, resultSize uint32) wasi.Errno { - sys := sysCtx(m) - - var writer io.Writer - - switch fd { - case fdStdout: - writer = sys.Stdout() - case fdStderr: - writer = sys.Stderr() - default: - // Check to see if the file descriptor is available - if f, ok := sys.OpenedFile(fd); !ok || f.File == nil { - return wasi.ErrnoBadf - // fs.FS doesn't declare io.Writer, but implementations such as os.File implement it. - } else if writer, ok = f.File.(io.Writer); !ok { - return wasi.ErrnoBadf - } - } - - var nwritten uint32 - for i := uint32(0); i < iovsCount; i++ { - iovPtr := iovs + i*8 - offset, ok := m.Memory().ReadUint32Le(iovPtr) - if !ok { - return wasi.ErrnoFault - } - l, ok := m.Memory().ReadUint32Le(iovPtr + 4) - if !ok { - return wasi.ErrnoFault - } - b, ok := m.Memory().Read(offset, l) - if !ok { - return wasi.ErrnoFault - } - n, err := writer.Write(b) - if err != nil { - return wasi.ErrnoIo - } - nwritten += uint32(n) - } - if !m.Memory().WriteUint32Le(resultSize, nwritten) { - return wasi.ErrnoFault - } - return wasi.ErrnoSuccess -} - -// PathCreateDirectory implements SnapshotPreview1.PathCreateDirectory -func (a *wasiAPI) PathCreateDirectory(m wasm.Module, fd, path, pathLen uint32) wasi.Errno { - return wasi.ErrnoNosys // stubbed for GrainLang per #271 -} - -// PathFilestatGet implements SnapshotPreview1.PathFilestatGet -func (a *wasiAPI) PathFilestatGet(m wasm.Module, fd, flags, path, pathLen, resultBuf uint32) wasi.Errno { - return wasi.ErrnoNosys // stubbed for GrainLang per #271 -} - -// PathFilestatSetTimes implements SnapshotPreview1.PathFilestatSetTimes -func (a *wasiAPI) PathFilestatSetTimes(m wasm.Module, fd, flags, path, pathLen uint32, atim, mtime uint64, fstFlags uint32) wasi.Errno { - return wasi.ErrnoNosys // stubbed for GrainLang per #271 -} - -// PathLink implements SnapshotPreview1.PathLink -func (a *wasiAPI) PathLink(m wasm.Module, oldFd, oldFlags, oldPath, oldPathLen, newFd, newPath, newPathLen uint32) wasi.Errno { - return wasi.ErrnoNosys // stubbed for GrainLang per #271 -} - -// PathOpen implements SnapshotPreview1.PathOpen -// Note: Rights will never be implemented per https://github.com/WebAssembly/WASI/issues/469#issuecomment-1045251844 -func (a *wasiAPI) PathOpen(m wasm.Module, fd, dirflags, pathPtr, pathLen, oflags uint32, fsRightsBase, - fsRightsInheriting uint64, fdflags, resultOpenedFd uint32) (errno wasi.Errno) { - sys := sysCtx(m) - - dir, ok := sys.OpenedFile(fd) - if !ok || dir.FS == nil { - return wasi.ErrnoBadf - } - - b, ok := m.Memory().Read(pathPtr, pathLen) - if !ok { - return wasi.ErrnoFault - } - - // TODO: Consider dirflags and oflags. Also, allow non-read-only open based on config about the mount. - // Ex. allow os.O_RDONLY, os.O_WRONLY, or os.O_RDWR either by config flag or pattern on filename - // See #390 - entry, errno := openFileEntry(dir.FS, path.Join(dir.Path, string(b))) - if errno != wasi.ErrnoSuccess { - return errno - } - - if newFD, ok := sys.OpenFile(entry); !ok { - _ = entry.File.Close() - return wasi.ErrnoIo - } else if !m.Memory().WriteUint32Le(resultOpenedFd, newFD) { - _ = entry.File.Close() - return wasi.ErrnoFault - } - return wasi.ErrnoSuccess -} - -// PathReadlink implements SnapshotPreview1.PathReadlink -func (a *wasiAPI) PathReadlink(m wasm.Module, fd, path, pathLen, buf, bufLen, resultBufused uint32) wasi.Errno { - return wasi.ErrnoNosys // stubbed for GrainLang per #271 -} - -// PathRemoveDirectory implements SnapshotPreview1.PathRemoveDirectory -func (a *wasiAPI) PathRemoveDirectory(m wasm.Module, fd, path, pathLen uint32) wasi.Errno { - return wasi.ErrnoNosys // stubbed for GrainLang per #271 -} - -// PathRename implements SnapshotPreview1.PathRename -func (a *wasiAPI) PathRename(m wasm.Module, fd, oldPath, oldPathLen, newFd, newPath, newPathLen uint32) wasi.Errno { - return wasi.ErrnoNosys // stubbed for GrainLang per #271 -} - -// PathSymlink implements SnapshotPreview1.PathSymlink -func (a *wasiAPI) PathSymlink(m wasm.Module, oldPath, oldPathLen, fd, newPath, newPathLen uint32) wasi.Errno { - return wasi.ErrnoNosys // stubbed for GrainLang per #271 -} - -// PathUnlinkFile implements SnapshotPreview1.PathUnlinkFile -func (a *wasiAPI) PathUnlinkFile(m wasm.Module, fd, path, pathLen uint32) wasi.Errno { - return wasi.ErrnoNosys // stubbed for GrainLang per #271 -} - -// PollOneoff implements SnapshotPreview1.PollOneoff -func (a *wasiAPI) PollOneoff(m wasm.Module, in, out, nsubscriptions, resultNevents uint32) wasi.Errno { - return wasi.ErrnoNosys // stubbed for GrainLang per #271 -} - -// ProcExit implements SnapshotPreview1.ProcExit -func (a *wasiAPI) ProcExit(m wasm.Module, exitCode uint32) { - _ = m.CloseWithExitCode(exitCode) -} - -// ProcRaise implements SnapshotPreview1.ProcRaise -func (a *wasiAPI) ProcRaise(m wasm.Module, sig uint32) wasi.Errno { - return wasi.ErrnoNosys // stubbed for GrainLang per #271 -} - -// SchedYield implements SnapshotPreview1.SchedYield -func (a *wasiAPI) SchedYield(m wasm.Module) wasi.Errno { - return wasi.ErrnoNosys // stubbed for GrainLang per #271 -} - -// RandomGet implements SnapshotPreview1.RandomGet -func (a *wasiAPI) RandomGet(m wasm.Module, buf uint32, bufLen uint32) (errno wasi.Errno) { - randomBytes := make([]byte, bufLen) - err := a.randSource(randomBytes) - if err != nil { - // TODO: handle different errors that syscal to entropy source can return - return wasi.ErrnoIo - } - - if !m.Memory().Write(buf, randomBytes) { - return wasi.ErrnoFault - } - - return wasi.ErrnoSuccess -} - -// SockRecv implements SnapshotPreview1.SockRecv -func (a *wasiAPI) SockRecv(m wasm.Module, fd, riData, riDataCount, riFlags, resultRoDataLen, resultRoFlags uint32) wasi.Errno { - return wasi.ErrnoNosys // stubbed for GrainLang per #271 -} - -// SockSend implements SnapshotPreview1.SockSend -func (a *wasiAPI) SockSend(m wasm.Module, fd, siData, siDataCount, siFlags, resultSoDataLen uint32) wasi.Errno { - return wasi.ErrnoNosys // stubbed for GrainLang per #271 -} - -// SockShutdown implements SnapshotPreview1.SockShutdown -func (a *wasiAPI) SockShutdown(m wasm.Module, fd, how uint32) wasi.Errno { - return wasi.ErrnoNosys // stubbed for GrainLang per #271 -} - -const ( - fdStdin = 0 - fdStdout = 1 - fdStderr = 2 -) - -// NewAPI is exported for benchmarks -func NewAPI() *wasiAPI { - return &wasiAPI{ - timeNowUnixNano: func() uint64 { - return uint64(time.Now().UnixNano()) - }, - randSource: func(p []byte) error { - _, err := crand.Read(p) - return err - }, - } -} - -func sysCtx(m wasm.Module) *internalwasm.SysContext { - if internal, ok := m.(*internalwasm.ModuleContext); !ok { - panic(fmt.Errorf("unsupported wasm.Module implementation: %v", m)) - } else { - return internal.Sys() - } -} - -func openFileEntry(rootFS fs.FS, pathName string) (*internalwasm.FileEntry, wasi.Errno) { - f, err := rootFS.Open(pathName) - if err != nil { - switch { - case errors.Is(err, fs.ErrNotExist): - return nil, wasi.ErrnoNoent - case errors.Is(err, fs.ErrExist): - return nil, wasi.ErrnoExist - default: - return nil, wasi.ErrnoIo - } - } - - // TODO: verify if oflags is a directory and fail with wasi.ErrnoNotdir if not - // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-oflags-flagsu16 - - return &internalwasm.FileEntry{Path: pathName, FS: rootFS, File: f}, wasi.ErrnoSuccess -} - -func ValidateWASICommand(module *internalwasm.Module, moduleName string) error { - // The snapshot-01 specification requires a "_start" function, but we don't enforce it is present. We only enforce - // if present, it is valid. In practice, not all modules importing WASI define a "_start" function (ex. wapc-go). - if start, err := requireExport(module, moduleName, FunctionStart, internalwasm.ExternTypeFunc); err == nil { - // TODO: this should be verified during decode so that errors have the correct source positions - ft := module.TypeOfFunction(start.Index) - if ft == nil { - return fmt.Errorf("module[%s] function[%s] has an invalid type", moduleName, FunctionStart) - } - if len(ft.Params) > 0 || len(ft.Results) > 0 { - return fmt.Errorf("module[%s] function[%s] must have an empty (nullary) signature: %s", moduleName, FunctionStart, ft.String()) - } - } - if _, err := requireExport(module, moduleName, FunctionInitialize, internalwasm.ExternTypeFunc); err == nil { - return fmt.Errorf("module[%s] must not export func[%s]", moduleName, FunctionInitialize) - } - if _, err := requireExport(module, moduleName, "memory", internalwasm.ExternTypeMemory); err != nil { - return err - } - // TODO: the spec also requires export of "__indirect_function_table", but we aren't enforcing it, and doing so - // would break existing users of TinyGo who aren't exporting that. We could possibly scan to see if it is every used. - return nil -} - -func requireExport(module *internalwasm.Module, moduleName string, exportName string, kind internalwasm.ExternType) (*internalwasm.Export, error) { - exp, ok := module.ExportSection[exportName] - if !ok || exp.Type != kind { - return nil, fmt.Errorf("module[%s] does not export %s[%s]", moduleName, internalwasm.ExternTypeName(kind), exportName) - } - return exp, nil -} - -func writeOffsetsAndNullTerminatedValues(mem wasm.Memory, values []string, offsets, bytes uint32) wasi.Errno { - for _, value := range values { - // Write current offset and advance it. - if !mem.WriteUint32Le(offsets, bytes) { - return wasi.ErrnoFault - } - offsets += 4 // size of uint32 - - // Write the next value to memory with a NUL terminator - if !mem.Write(bytes, []byte(value)) { - return wasi.ErrnoFault - } - bytes += uint32(len(value)) - if !mem.WriteByte(bytes, 0) { - return wasi.ErrnoFault - } - bytes++ - } - - return wasi.ErrnoSuccess -} diff --git a/internal/wasm/binary/code.go b/internal/wasm/binary/code.go index 17ff1112..77c4e8cc 100644 --- a/internal/wasm/binary/code.go +++ b/internal/wasm/binary/code.go @@ -7,7 +7,7 @@ import ( "math" "github.com/tetratelabs/wazero/internal/leb128" - wasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm" ) func decodeCode(r *bytes.Reader) (*wasm.Code, error) { diff --git a/internal/wasm/binary/code_test.go b/internal/wasm/binary/code_test.go index bf26039c..dc698423 100644 --- a/internal/wasm/binary/code_test.go +++ b/internal/wasm/binary/code_test.go @@ -5,7 +5,7 @@ import ( "github.com/stretchr/testify/require" - wasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm" ) var addLocalZeroLocalTwo = []byte{wasm.OpcodeLocalGet, 0, wasm.OpcodeLocalGet, 2, wasm.OpcodeI32Add, wasm.OpcodeEnd} diff --git a/internal/wasm/binary/const_expr.go b/internal/wasm/binary/const_expr.go index 4eb6d05b..c9f9337d 100644 --- a/internal/wasm/binary/const_expr.go +++ b/internal/wasm/binary/const_expr.go @@ -6,7 +6,7 @@ import ( "github.com/tetratelabs/wazero/internal/ieee754" "github.com/tetratelabs/wazero/internal/leb128" - wasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm" ) func decodeConstantExpression(r *bytes.Reader) (*wasm.ConstantExpression, error) { diff --git a/internal/wasm/binary/data.go b/internal/wasm/binary/data.go index 2a6a848c..ebced30f 100644 --- a/internal/wasm/binary/data.go +++ b/internal/wasm/binary/data.go @@ -6,7 +6,7 @@ import ( "io" "github.com/tetratelabs/wazero/internal/leb128" - wasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm" ) func decodeDataSegment(r *bytes.Reader) (*wasm.DataSegment, error) { diff --git a/internal/wasm/binary/decoder.go b/internal/wasm/binary/decoder.go index 2f02c566..c09a21d3 100644 --- a/internal/wasm/binary/decoder.go +++ b/internal/wasm/binary/decoder.go @@ -6,10 +6,10 @@ import ( "io" "github.com/tetratelabs/wazero/internal/leb128" - wasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm" ) -// DecodeModule implements internalwasm.DecodeModule for the WebAssembly 1.0 (20191205) Binary Format +// DecodeModule implements wasm.DecodeModule for the WebAssembly 1.0 (20191205) Binary Format // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#binary-format%E2%91%A0 func DecodeModule(binary []byte, _ wasm.Features, memoryMaxPages uint32) (*wasm.Module, error) { r := bytes.NewReader(binary) diff --git a/internal/wasm/binary/decoder_test.go b/internal/wasm/binary/decoder_test.go index 8f3d4c1e..50b4bddb 100644 --- a/internal/wasm/binary/decoder_test.go +++ b/internal/wasm/binary/decoder_test.go @@ -5,7 +5,7 @@ import ( "github.com/stretchr/testify/require" - wasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm" ) // TestDecodeModule relies on unit tests for Module.Encode, specifically that the encoding is both known and correct. diff --git a/internal/wasm/binary/element.go b/internal/wasm/binary/element.go index fa0c5d06..e1c64310 100644 --- a/internal/wasm/binary/element.go +++ b/internal/wasm/binary/element.go @@ -5,7 +5,7 @@ import ( "fmt" "github.com/tetratelabs/wazero/internal/leb128" - wasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm" ) func decodeElementSegment(r *bytes.Reader) (*wasm.ElementSegment, error) { diff --git a/internal/wasm/binary/encoder.go b/internal/wasm/binary/encoder.go index e5b8d4d6..ee636c3e 100644 --- a/internal/wasm/binary/encoder.go +++ b/internal/wasm/binary/encoder.go @@ -1,7 +1,7 @@ package binary import ( - wasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm" ) var sizePrefixedName = []byte{4, 'n', 'a', 'm', 'e'} diff --git a/internal/wasm/binary/encoder_test.go b/internal/wasm/binary/encoder_test.go index d3319f1a..a3d6d0cb 100644 --- a/internal/wasm/binary/encoder_test.go +++ b/internal/wasm/binary/encoder_test.go @@ -6,7 +6,7 @@ import ( "github.com/stretchr/testify/require" - wasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm" ) func TestModule_Encode(t *testing.T) { diff --git a/internal/wasm/binary/export.go b/internal/wasm/binary/export.go index caeed77a..7b10d202 100644 --- a/internal/wasm/binary/export.go +++ b/internal/wasm/binary/export.go @@ -5,7 +5,7 @@ import ( "fmt" "github.com/tetratelabs/wazero/internal/leb128" - wasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm" ) func decodeExport(r *bytes.Reader) (i *wasm.Export, err error) { @@ -32,7 +32,7 @@ func decodeExport(r *bytes.Reader) (i *wasm.Export, err error) { return } -// encodeExport returns the internalwasm.Export encoded in WebAssembly 1.0 (20191205) Binary Format. +// encodeExport returns the wasm.Export encoded in WebAssembly 1.0 (20191205) Binary Format. // // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#export-section%E2%91%A0 func encodeExport(i *wasm.Export) []byte { diff --git a/internal/wasm/binary/export_test.go b/internal/wasm/binary/export_test.go index 3d853de2..24e2b5dd 100644 --- a/internal/wasm/binary/export_test.go +++ b/internal/wasm/binary/export_test.go @@ -5,7 +5,7 @@ import ( "github.com/stretchr/testify/require" - wasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm" ) func TestEncodeExport(t *testing.T) { diff --git a/internal/wasm/binary/function.go b/internal/wasm/binary/function.go index d2533080..c4c8c4da 100644 --- a/internal/wasm/binary/function.go +++ b/internal/wasm/binary/function.go @@ -1,12 +1,12 @@ package binary import ( - wasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm" ) var nullary = []byte{0x60, 0, 0} -// encodedOneParam is a cache of internalwasm.FunctionType values for param length 1 and result length 0 +// encodedOneParam is a cache of wasm.FunctionType values for param length 1 and result length 0 var encodedOneParam = map[wasm.ValueType][]byte{ wasm.ValueTypeI32: {0x60, 1, wasm.ValueTypeI32, 0}, wasm.ValueTypeI64: {0x60, 1, wasm.ValueTypeI64, 0}, @@ -14,7 +14,7 @@ var encodedOneParam = map[wasm.ValueType][]byte{ wasm.ValueTypeF64: {0x60, 1, wasm.ValueTypeF64, 0}, } -// encodedOneResult is a cache of internalwasm.FunctionType values for param length 0 and result length 1 +// encodedOneResult is a cache of wasm.FunctionType values for param length 0 and result length 1 var encodedOneResult = map[wasm.ValueType][]byte{ wasm.ValueTypeI32: {0x60, 0, 1, wasm.ValueTypeI32}, wasm.ValueTypeI64: {0x60, 0, 1, wasm.ValueTypeI64}, @@ -22,7 +22,7 @@ var encodedOneResult = map[wasm.ValueType][]byte{ wasm.ValueTypeF64: {0x60, 0, 1, wasm.ValueTypeF64}, } -// encodeFunctionType returns the internalwasm.FunctionType encoded in WebAssembly 1.0 (20191205) Binary Format. +// encodeFunctionType returns the wasm.FunctionType encoded in WebAssembly 1.0 (20191205) Binary Format. // // Note: Function types are encoded by the byte 0x60 followed by the respective vectors of parameter and result types. // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#function-types%E2%91%A4 diff --git a/internal/wasm/binary/function_test.go b/internal/wasm/binary/function_test.go index d056aed9..f61cf68f 100644 --- a/internal/wasm/binary/function_test.go +++ b/internal/wasm/binary/function_test.go @@ -5,7 +5,7 @@ import ( "github.com/stretchr/testify/require" - wasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm" ) func TestEncodeFunctionType(t *testing.T) { diff --git a/internal/wasm/binary/global.go b/internal/wasm/binary/global.go index e9c70a69..82c03b1e 100644 --- a/internal/wasm/binary/global.go +++ b/internal/wasm/binary/global.go @@ -4,10 +4,10 @@ import ( "bytes" "fmt" - wasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm" ) -// decodeGlobal returns the wasm.Global decoded with the WebAssembly 1.0 (20191205) Binary Format. +// decodeGlobal returns the api.Global decoded with the WebAssembly 1.0 (20191205) Binary Format. // // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#binary-global func decodeGlobal(r *bytes.Reader) (*wasm.Global, error) { @@ -52,7 +52,7 @@ func decodeGlobalType(r *bytes.Reader) (*wasm.GlobalType, error) { return ret, nil } -// encodeGlobal returns the internalwasm.Global encoded in WebAssembly 1.0 (20191205) Binary Format. +// encodeGlobal returns the wasm.Global encoded in WebAssembly 1.0 (20191205) Binary Format. // // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#global-section%E2%91%A0 func encodeGlobal(g *wasm.Global) []byte { diff --git a/internal/wasm/binary/global_test.go b/internal/wasm/binary/global_test.go index 8a50d179..5e1fe98a 100644 --- a/internal/wasm/binary/global_test.go +++ b/internal/wasm/binary/global_test.go @@ -5,7 +5,7 @@ import ( "github.com/stretchr/testify/require" - wasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm" ) func TestEncodeGlobal(t *testing.T) { diff --git a/internal/wasm/binary/import.go b/internal/wasm/binary/import.go index b4cd6bd6..d423f370 100644 --- a/internal/wasm/binary/import.go +++ b/internal/wasm/binary/import.go @@ -5,7 +5,7 @@ import ( "fmt" "github.com/tetratelabs/wazero/internal/leb128" - wasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm" ) func decodeImport(r *bytes.Reader, idx uint32, memoryMaxPages uint32) (i *wasm.Import, err error) { @@ -41,7 +41,7 @@ func decodeImport(r *bytes.Reader, idx uint32, memoryMaxPages uint32) (i *wasm.I return } -// encodeImport returns the internalwasm.Import encoded in WebAssembly 1.0 (20191205) Binary Format. +// encodeImport returns the wasm.Import encoded in WebAssembly 1.0 (20191205) Binary Format. // // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#binary-import func encodeImport(i *wasm.Import) []byte { diff --git a/internal/wasm/binary/import_test.go b/internal/wasm/binary/import_test.go index 69073438..ce721c2f 100644 --- a/internal/wasm/binary/import_test.go +++ b/internal/wasm/binary/import_test.go @@ -5,7 +5,7 @@ import ( "github.com/stretchr/testify/require" - wasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm" ) func TestEncodeImport(t *testing.T) { diff --git a/internal/wasm/binary/memory.go b/internal/wasm/binary/memory.go index d384582e..555fdc8a 100644 --- a/internal/wasm/binary/memory.go +++ b/internal/wasm/binary/memory.go @@ -4,10 +4,10 @@ import ( "bytes" "fmt" - wasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm" ) -// decodeMemory returns the wasm.Memory decoded with the WebAssembly 1.0 (20191205) Binary Format. +// decodeMemory returns the api.Memory decoded with the WebAssembly 1.0 (20191205) Binary Format. // // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#binary-memory func decodeMemory(r *bytes.Reader, memoryMaxPages uint32) (*wasm.Memory, error) { @@ -31,7 +31,7 @@ func decodeMemory(r *bytes.Reader, memoryMaxPages uint32) (*wasm.Memory, error) return &wasm.Memory{Min: min, Max: max}, nil } -// encodeMemory returns the internalwasm.Memory encoded in WebAssembly 1.0 (20191205) Binary Format. +// encodeMemory returns the wasm.Memory encoded in WebAssembly 1.0 (20191205) Binary Format. // // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#binary-memory func encodeMemory(i *wasm.Memory) []byte { diff --git a/internal/wasm/binary/memory_test.go b/internal/wasm/binary/memory_test.go index b3925afb..a7349492 100644 --- a/internal/wasm/binary/memory_test.go +++ b/internal/wasm/binary/memory_test.go @@ -7,7 +7,7 @@ import ( "github.com/stretchr/testify/require" - wasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm" ) func TestMemoryType(t *testing.T) { @@ -55,9 +55,9 @@ func TestMemoryType(t *testing.T) { }) t.Run(fmt.Sprintf("decode - %s", tc.name), func(t *testing.T) { - decoded, err := decodeMemory(bytes.NewReader(b), max) + binary, err := decodeMemory(bytes.NewReader(b), max) require.NoError(t, err) - require.Equal(t, decoded, tc.input) + require.Equal(t, binary, tc.input) }) } } diff --git a/internal/wasm/binary/names.go b/internal/wasm/binary/names.go index 883188b3..ab02ddc6 100644 --- a/internal/wasm/binary/names.go +++ b/internal/wasm/binary/names.go @@ -6,7 +6,7 @@ import ( "io" "github.com/tetratelabs/wazero/internal/leb128" - wasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm" ) const ( @@ -150,7 +150,7 @@ func decodeFunctionCount(r *bytes.Reader, subsectionID uint8) (uint32, error) { return functionCount, nil } -// encodeNameSectionData serializes the data for the "name" key in internalwasm.SectionIDCustom according to the +// encodeNameSectionData serializes the data for the "name" key in wasm.SectionIDCustom according to the // standard: // // Note: The result can be nil because this does not encode empty subsections diff --git a/internal/wasm/binary/names_test.go b/internal/wasm/binary/names_test.go index a3bdf46c..c399c595 100644 --- a/internal/wasm/binary/names_test.go +++ b/internal/wasm/binary/names_test.go @@ -6,7 +6,7 @@ import ( "github.com/stretchr/testify/require" - wasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm" ) func TestEncodeNameSectionData(t *testing.T) { diff --git a/internal/wasm/binary/section.go b/internal/wasm/binary/section.go index 23aa903f..77eb1940 100644 --- a/internal/wasm/binary/section.go +++ b/internal/wasm/binary/section.go @@ -5,7 +5,7 @@ import ( "fmt" "github.com/tetratelabs/wazero/internal/leb128" - wasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm" ) func decodeTypeSection(r *bytes.Reader) ([]*wasm.FunctionType, error) { @@ -209,7 +209,7 @@ func encodeSection(sectionID wasm.SectionID, contents []byte) []byte { return append([]byte{sectionID}, encodeSizePrefixed(contents)...) } -// encodeTypeSection encodes a internalwasm.SectionIDType for the given imports in WebAssembly 1.0 (20191205) Binary +// encodeTypeSection encodes a wasm.SectionIDType for the given imports in WebAssembly 1.0 (20191205) Binary // Format. // // See encodeFunctionType @@ -222,7 +222,7 @@ func encodeTypeSection(types []*wasm.FunctionType) []byte { return encodeSection(wasm.SectionIDType, contents) } -// encodeImportSection encodes a internalwasm.SectionIDImport for the given imports in WebAssembly 1.0 (20191205) Binary +// encodeImportSection encodes a wasm.SectionIDImport for the given imports in WebAssembly 1.0 (20191205) Binary // Format. // // See encodeImport @@ -235,7 +235,7 @@ func encodeImportSection(imports []*wasm.Import) []byte { return encodeSection(wasm.SectionIDImport, contents) } -// encodeFunctionSection encodes a internalwasm.SectionIDFunction for the type indices associated with module-defined +// encodeFunctionSection encodes a wasm.SectionIDFunction for the type indices associated with module-defined // functions in WebAssembly 1.0 (20191205) Binary Format. // // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#function-section%E2%91%A0 @@ -247,7 +247,7 @@ func encodeFunctionSection(typeIndices []wasm.Index) []byte { return encodeSection(wasm.SectionIDFunction, contents) } -// encodeCodeSection encodes a internalwasm.SectionIDCode for the module-defined function in WebAssembly 1.0 (20191205) +// encodeCodeSection encodes a wasm.SectionIDCode for the module-defined function in WebAssembly 1.0 (20191205) // Binary Format. // // See encodeCode @@ -260,7 +260,7 @@ func encodeCodeSection(code []*wasm.Code) []byte { return encodeSection(wasm.SectionIDCode, contents) } -// encodeTableSection encodes a internalwasm.SectionIDTable for the module-defined function in WebAssembly 1.0 +// encodeTableSection encodes a wasm.SectionIDTable for the module-defined function in WebAssembly 1.0 // (20191205) Binary Format. // // See encodeTable @@ -270,7 +270,7 @@ func encodeTableSection(table *wasm.Table) []byte { return encodeSection(wasm.SectionIDTable, contents) } -// encodeMemorySection encodes a internalwasm.SectionIDMemory for the module-defined function in WebAssembly 1.0 +// encodeMemorySection encodes a wasm.SectionIDMemory for the module-defined function in WebAssembly 1.0 // (20191205) Binary Format. // // See encodeMemory @@ -280,7 +280,7 @@ func encodeMemorySection(memory *wasm.Memory) []byte { return encodeSection(wasm.SectionIDMemory, contents) } -// encodeGlobalSection encodes a internalwasm.SectionIDGlobal for the given globals in WebAssembly 1.0 (20191205) Binary +// encodeGlobalSection encodes a wasm.SectionIDGlobal for the given globals in WebAssembly 1.0 (20191205) Binary // Format. // // See encodeGlobal @@ -293,7 +293,7 @@ func encodeGlobalSection(globals []*wasm.Global) []byte { return encodeSection(wasm.SectionIDGlobal, contents) } -// encodeExportSection encodes a internalwasm.SectionIDExport for the given exports in WebAssembly 1.0 (20191205) Binary +// encodeExportSection encodes a wasm.SectionIDExport for the given exports in WebAssembly 1.0 (20191205) Binary // Format. // // See encodeExport @@ -306,7 +306,7 @@ func encodeExportSection(exports map[string]*wasm.Export) []byte { return encodeSection(wasm.SectionIDExport, contents) } -// encodeStartSection encodes a internalwasm.SectionIDStart for the given function index in WebAssembly 1.0 (20191205) +// encodeStartSection encodes a wasm.SectionIDStart for the given function index in WebAssembly 1.0 (20191205) // Binary Format. // // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#start-section%E2%91%A0 diff --git a/internal/wasm/binary/section_test.go b/internal/wasm/binary/section_test.go index 58321112..c49f2720 100644 --- a/internal/wasm/binary/section_test.go +++ b/internal/wasm/binary/section_test.go @@ -6,7 +6,7 @@ import ( "github.com/stretchr/testify/require" - wasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm" ) func TestTableSection(t *testing.T) { diff --git a/internal/wasm/binary/table.go b/internal/wasm/binary/table.go index 89a86c33..e81739e7 100644 --- a/internal/wasm/binary/table.go +++ b/internal/wasm/binary/table.go @@ -4,7 +4,7 @@ import ( "bytes" "fmt" - wasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm" ) // decodeTable returns the wasm.Table decoded with the WebAssembly 1.0 (20191205) Binary Format. @@ -37,7 +37,7 @@ func decodeTable(r *bytes.Reader) (*wasm.Table, error) { return &wasm.Table{Min: min, Max: max}, nil } -// encodeTable returns the internalwasm.Table encoded in WebAssembly 1.0 (20191205) Binary Format. +// encodeTable returns the wasm.Table encoded in WebAssembly 1.0 (20191205) Binary Format. // // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#binary-table func encodeTable(i *wasm.Table) []byte { diff --git a/internal/wasm/binary/table_test.go b/internal/wasm/binary/table_test.go index 4b91770e..e7bde28b 100644 --- a/internal/wasm/binary/table_test.go +++ b/internal/wasm/binary/table_test.go @@ -7,7 +7,7 @@ import ( "github.com/stretchr/testify/require" - wasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm" ) func TestTableType(t *testing.T) { diff --git a/internal/wasm/binary/value.go b/internal/wasm/binary/value.go index 947d8f4e..16246874 100644 --- a/internal/wasm/binary/value.go +++ b/internal/wasm/binary/value.go @@ -7,7 +7,7 @@ import ( "unicode/utf8" "github.com/tetratelabs/wazero/internal/leb128" - wasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm" ) var noValType = []byte{0} diff --git a/internal/wasm/binary/value_test.go b/internal/wasm/binary/value_test.go index 455dc7cf..b1f63bb0 100644 --- a/internal/wasm/binary/value_test.go +++ b/internal/wasm/binary/value_test.go @@ -5,7 +5,7 @@ import ( "github.com/stretchr/testify/require" - wasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm" ) func TestEncodeValTypes(t *testing.T) { diff --git a/internal/wasm/counts.go b/internal/wasm/counts.go index 34d21e37..46288711 100644 --- a/internal/wasm/counts.go +++ b/internal/wasm/counts.go @@ -1,4 +1,4 @@ -package internalwasm +package wasm import "fmt" diff --git a/internal/wasm/counts_test.go b/internal/wasm/counts_test.go index 78489ed5..c920fa64 100644 --- a/internal/wasm/counts_test.go +++ b/internal/wasm/counts_test.go @@ -1,4 +1,4 @@ -package internalwasm +package wasm import ( "reflect" @@ -6,7 +6,7 @@ import ( "github.com/stretchr/testify/require" - "github.com/tetratelabs/wazero/wasm" + "github.com/tetratelabs/wazero/api" ) func TestModule_ImportFuncCount(t *testing.T) { @@ -204,7 +204,7 @@ func TestModule_SectionElementCount(t *testing.T) { i32, f32 := ValueTypeI32, ValueTypeF32 zero := uint32(0) empty := &ConstantExpression{Opcode: OpcodeI32Const, Data: []byte{0x00}} - fn := reflect.ValueOf(func(wasm.Module) {}) + fn := reflect.ValueOf(func(api.Module) {}) tests := []struct { name string diff --git a/internal/wasm/engine.go b/internal/wasm/engine.go index bbb88c02..bff97921 100644 --- a/internal/wasm/engine.go +++ b/internal/wasm/engine.go @@ -1,4 +1,4 @@ -package internalwasm +package wasm // Engine is a Store-scoped mechanism to compile functions declared or imported by a module. // This is a top-level type implemented by an interpreter or JIT compiler. @@ -11,7 +11,7 @@ type Engine interface { // * table: a possibly shared table used by this module. When nil tableInit will be nil. // * tableInit: a mapping of TableInstance.Table index to the function index it should point to. // - // Note: Input parameters must be pre-validated with internalwasm.Module Validate, to ensure no fields are invalid + // Note: Input parameters must be pre-validated with wasm.Module Validate, to ensure no fields are invalid // due to reasons such as out-of-bounds. NewModuleEngine(name string, importedFunctions, moduleFunctions []*FunctionInstance, table *TableInstance, tableInit map[Index]Index) (ModuleEngine, error) } @@ -23,7 +23,7 @@ type ModuleEngine interface { // Call invokes a function instance f with given parameters. // Returns the results from the function. - // The ctx's context.Context will be the outer-most ancestor of the argument to wasm.Function. + // The ctx's context.Context will be the outer-most ancestor of the argument to api.Function. Call(ctx *ModuleContext, f *FunctionInstance, params ...uint64) (results []uint64, err error) // CloseWithExitCode releases the resources allocated by functions in this ModuleEngine and ensures new calls (Call) diff --git a/internal/wasm/errors.go b/internal/wasm/errors.go index bf212d8c..c0df2708 100644 --- a/internal/wasm/errors.go +++ b/internal/wasm/errors.go @@ -1,4 +1,4 @@ -package internalwasm +package wasm import "errors" diff --git a/internal/wasm/features.go b/internal/wasm/features.go index 5d537a10..c97e1d3f 100644 --- a/internal/wasm/features.go +++ b/internal/wasm/features.go @@ -1,4 +1,4 @@ -package internalwasm +package wasm import ( "fmt" @@ -20,7 +20,7 @@ const ( // See https://github.com/WebAssembly/mutable-global FeatureMutableGlobal Features = 1 << iota - // FeatureSignExtensionOps decides if parsing should succeed on internalwasm.GlobalType Mutable + // FeatureSignExtensionOps decides if parsing should succeed on wasm.GlobalType Mutable // See https://github.com/WebAssembly/spec/blob/main/proposals/sign-extension-ops/Overview.md FeatureSignExtensionOps ) diff --git a/internal/wasm/features_test.go b/internal/wasm/features_test.go index fca50ba5..c6adb557 100644 --- a/internal/wasm/features_test.go +++ b/internal/wasm/features_test.go @@ -1,4 +1,4 @@ -package internalwasm +package wasm import ( "testing" diff --git a/internal/wasm/func_validation.go b/internal/wasm/func_validation.go index 264c8969..caa66fc3 100644 --- a/internal/wasm/func_validation.go +++ b/internal/wasm/func_validation.go @@ -1,4 +1,4 @@ -package internalwasm +package wasm import ( "bytes" diff --git a/internal/wasm/func_validation_test.go b/internal/wasm/func_validation_test.go index ec9b6e9d..91b9e634 100644 --- a/internal/wasm/func_validation_test.go +++ b/internal/wasm/func_validation_test.go @@ -1,4 +1,4 @@ -package internalwasm +package wasm import ( "fmt" diff --git a/internal/wasm/global.go b/internal/wasm/global.go index 6c453748..b0882071 100644 --- a/internal/wasm/global.go +++ b/internal/wasm/global.go @@ -1,29 +1,29 @@ -package internalwasm +package wasm import ( "fmt" - publicwasm "github.com/tetratelabs/wazero/wasm" + "github.com/tetratelabs/wazero/api" ) type mutableGlobal struct { g *GlobalInstance } -// compile-time check to ensure mutableGlobal is a wasm.Global -var _ publicwasm.Global = &mutableGlobal{} +// compile-time check to ensure mutableGlobal is a api.Global +var _ api.Global = &mutableGlobal{} -// Type implements wasm.Global Type -func (g *mutableGlobal) Type() publicwasm.ValueType { +// Type implements api.Global Type +func (g *mutableGlobal) Type() api.ValueType { return g.g.Type.ValType } -// Get implements wasm.Global Get +// Get implements api.Global Get func (g *mutableGlobal) Get() uint64 { return g.g.Val } -// Set implements wasm.MutableGlobal Set +// Set implements api.MutableGlobal Set func (g *mutableGlobal) Set(v uint64) { g.g.Val = v } @@ -34,9 +34,9 @@ func (g *mutableGlobal) String() string { case ValueTypeI32, ValueTypeI64: return fmt.Sprintf("global(%d)", g.Get()) case ValueTypeF32: - return fmt.Sprintf("global(%f)", publicwasm.DecodeF32(g.Get())) + return fmt.Sprintf("global(%f)", api.DecodeF32(g.Get())) case ValueTypeF64: - return fmt.Sprintf("global(%f)", publicwasm.DecodeF64(g.Get())) + return fmt.Sprintf("global(%f)", api.DecodeF64(g.Get())) default: panic(fmt.Errorf("BUG: unknown value type %X", g.Type())) } @@ -44,15 +44,15 @@ func (g *mutableGlobal) String() string { type globalI32 uint64 -// compile-time check to ensure globalI32 is a wasm.Global -var _ publicwasm.Global = globalI32(0) +// compile-time check to ensure globalI32 is a api.Global +var _ api.Global = globalI32(0) -// Type implements wasm.Global Type -func (g globalI32) Type() publicwasm.ValueType { +// Type implements api.Global Type +func (g globalI32) Type() api.ValueType { return ValueTypeI32 } -// Get implements wasm.Global Get +// Get implements api.Global Get func (g globalI32) Get() uint64 { return uint64(g) } @@ -64,15 +64,15 @@ func (g globalI32) String() string { type globalI64 uint64 -// compile-time check to ensure globalI64 is a publicwasm.Global -var _ publicwasm.Global = globalI64(0) +// compile-time check to ensure globalI64 is a api.Global +var _ api.Global = globalI64(0) -// Type implements wasm.Global Type -func (g globalI64) Type() publicwasm.ValueType { +// Type implements api.Global Type +func (g globalI64) Type() api.ValueType { return ValueTypeI64 } -// Get implements wasm.Global Get +// Get implements api.Global Get func (g globalI64) Get() uint64 { return uint64(g) } @@ -84,40 +84,40 @@ func (g globalI64) String() string { type globalF32 uint64 -// compile-time check to ensure globalF32 is a publicwasm.Global -var _ publicwasm.Global = globalF32(0) +// compile-time check to ensure globalF32 is a api.Global +var _ api.Global = globalF32(0) -// Type implements wasm.Global Type -func (g globalF32) Type() publicwasm.ValueType { +// Type implements api.Global Type +func (g globalF32) Type() api.ValueType { return ValueTypeF32 } -// Get implements wasm.Global Get +// Get implements api.Global Get func (g globalF32) Get() uint64 { return uint64(g) } // String implements fmt.Stringer func (g globalF32) String() string { - return fmt.Sprintf("global(%f)", publicwasm.DecodeF32(g.Get())) + return fmt.Sprintf("global(%f)", api.DecodeF32(g.Get())) } type globalF64 uint64 -// compile-time check to ensure globalF64 is a publicwasm.Global -var _ publicwasm.Global = globalF64(0) +// compile-time check to ensure globalF64 is a api.Global +var _ api.Global = globalF64(0) -// Type implements wasm.Global Type -func (g globalF64) Type() publicwasm.ValueType { +// Type implements api.Global Type +func (g globalF64) Type() api.ValueType { return ValueTypeF64 } -// Get implements wasm.Global Get +// Get implements api.Global Get func (g globalF64) Get() uint64 { return uint64(g) } // String implements fmt.Stringer func (g globalF64) String() string { - return fmt.Sprintf("global(%f)", publicwasm.DecodeF64(g.Get())) + return fmt.Sprintf("global(%f)", api.DecodeF64(g.Get())) } diff --git a/internal/wasm/global_test.go b/internal/wasm/global_test.go index 2fc55e24..124ddeff 100644 --- a/internal/wasm/global_test.go +++ b/internal/wasm/global_test.go @@ -1,4 +1,4 @@ -package internalwasm +package wasm import ( "context" @@ -7,14 +7,14 @@ import ( "github.com/stretchr/testify/require" - publicwasm "github.com/tetratelabs/wazero/wasm" + "github.com/tetratelabs/wazero/api" ) func TestGlobalTypes(t *testing.T) { tests := []struct { name string - global publicwasm.Global - expectedType publicwasm.ValueType + global api.Global + expectedType api.ValueType expectedVal uint64 expectedString string expectedMutable bool @@ -35,16 +35,16 @@ func TestGlobalTypes(t *testing.T) { }, { name: "f32 - immutable", - global: globalF32(publicwasm.EncodeF32(1.0)), + global: globalF32(api.EncodeF32(1.0)), expectedType: ValueTypeF32, - expectedVal: publicwasm.EncodeF32(1.0), + expectedVal: api.EncodeF32(1.0), expectedString: "global(1.000000)", }, { name: "f64 - immutable", - global: globalF64(publicwasm.EncodeF64(1.0)), + global: globalF64(api.EncodeF64(1.0)), expectedType: ValueTypeF64, - expectedVal: publicwasm.EncodeF64(1.0), + expectedVal: api.EncodeF64(1.0), expectedString: "global(1.000000)", }, { @@ -73,10 +73,10 @@ func TestGlobalTypes(t *testing.T) { name: "f32 - mutable", global: &mutableGlobal{g: &GlobalInstance{ Type: &GlobalType{ValType: ValueTypeF32, Mutable: true}, - Val: publicwasm.EncodeF32(1.0), + Val: api.EncodeF32(1.0), }}, expectedType: ValueTypeF32, - expectedVal: publicwasm.EncodeF32(1.0), + expectedVal: api.EncodeF32(1.0), expectedString: "global(1.000000)", expectedMutable: true, }, @@ -84,10 +84,10 @@ func TestGlobalTypes(t *testing.T) { name: "f64 - mutable", global: &mutableGlobal{g: &GlobalInstance{ Type: &GlobalType{ValType: ValueTypeF64, Mutable: true}, - Val: publicwasm.EncodeF64(1.0), + Val: api.EncodeF64(1.0), }}, expectedType: ValueTypeF64, - expectedVal: publicwasm.EncodeF64(1.0), + expectedVal: api.EncodeF64(1.0), expectedString: "global(1.000000)", expectedMutable: true, }, @@ -101,7 +101,7 @@ func TestGlobalTypes(t *testing.T) { require.Equal(t, tc.expectedVal, tc.global.Get()) require.Equal(t, tc.expectedString, tc.global.String()) - mutable, ok := tc.global.(publicwasm.MutableGlobal) + mutable, ok := tc.global.(api.MutableGlobal) require.Equal(t, tc.expectedMutable, ok) if ok { mutable.Set(2) @@ -115,7 +115,7 @@ func TestPublicModule_Global(t *testing.T) { tests := []struct { name string module *Module // module as wat doesn't yet support globals - expected publicwasm.Global + expected api.Global }{ { name: "no global", @@ -165,13 +165,13 @@ func TestPublicModule_Global(t *testing.T) { { Type: &GlobalType{ValType: ValueTypeF32}, Init: &ConstantExpression{Opcode: OpcodeF32Const, - Data: uint64Le(publicwasm.EncodeF32(1.0)), + Data: uint64Le(api.EncodeF32(1.0)), }, }, }, ExportSection: map[string]*Export{"global": {Type: ExternTypeGlobal, Name: "global"}}, }, - expected: globalF32(publicwasm.EncodeF32(1.0)), + expected: globalF32(api.EncodeF32(1.0)), }, { name: "global exported - immutable F64", @@ -180,13 +180,13 @@ func TestPublicModule_Global(t *testing.T) { { Type: &GlobalType{ValType: ValueTypeF64}, Init: &ConstantExpression{Opcode: OpcodeF64Const, - Data: uint64Le(publicwasm.EncodeF64(1.0)), + Data: uint64Le(api.EncodeF64(1.0)), }, }, }, ExportSection: map[string]*Export{"global": {Type: ExternTypeGlobal, Name: "global"}}, }, - expected: globalF64(publicwasm.EncodeF64(1.0)), + expected: globalF64(api.EncodeF64(1.0)), }, { name: "global exported - mutable I32", @@ -225,14 +225,14 @@ func TestPublicModule_Global(t *testing.T) { { Type: &GlobalType{ValType: ValueTypeF32, Mutable: true}, Init: &ConstantExpression{Opcode: OpcodeF32Const, - Data: uint64Le(publicwasm.EncodeF32(1.0)), + Data: uint64Le(api.EncodeF32(1.0)), }, }, }, ExportSection: map[string]*Export{"global": {Type: ExternTypeGlobal, Name: "global"}}, }, expected: &mutableGlobal{ - g: &GlobalInstance{Type: &GlobalType{ValType: ValueTypeF32, Mutable: true}, Val: publicwasm.EncodeF32(1.0)}, + g: &GlobalInstance{Type: &GlobalType{ValType: ValueTypeF32, Mutable: true}, Val: api.EncodeF32(1.0)}, }, }, { @@ -242,14 +242,14 @@ func TestPublicModule_Global(t *testing.T) { { Type: &GlobalType{ValType: ValueTypeF64, Mutable: true}, Init: &ConstantExpression{Opcode: OpcodeF64Const, - Data: uint64Le(publicwasm.EncodeF64(1.0)), + Data: uint64Le(api.EncodeF64(1.0)), }, }, }, ExportSection: map[string]*Export{"global": {Type: ExternTypeGlobal, Name: "global"}}, }, expected: &mutableGlobal{ - g: &GlobalInstance{Type: &GlobalType{ValType: ValueTypeF64, Mutable: true}, Val: publicwasm.EncodeF64(1.0)}, + g: &GlobalInstance{Type: &GlobalType{ValType: ValueTypeF64, Mutable: true}, Val: api.EncodeF64(1.0)}, }, }, } diff --git a/internal/wasm/gofunc.go b/internal/wasm/gofunc.go index 7a31de07..83717419 100644 --- a/internal/wasm/gofunc.go +++ b/internal/wasm/gofunc.go @@ -1,4 +1,4 @@ -package internalwasm +package wasm import ( "context" @@ -6,7 +6,7 @@ import ( "fmt" "reflect" - publicwasm "github.com/tetratelabs/wazero/wasm" + "github.com/tetratelabs/wazero/api" ) // FunctionKind identifies the type of function that can be called. @@ -27,7 +27,7 @@ const ( // Below are reflection code to get the interface type used to parse functions and set values. -var moduleType = reflect.TypeOf((*publicwasm.Module)(nil)).Elem() +var moduleType = reflect.TypeOf((*api.Module)(nil)).Elem() var goContextType = reflect.TypeOf((*context.Context)(nil)).Elem() var errorType = reflect.TypeOf((*error)(nil)).Elem() diff --git a/internal/wasm/gofunc_test.go b/internal/wasm/gofunc_test.go index c59d23cc..e8357951 100644 --- a/internal/wasm/gofunc_test.go +++ b/internal/wasm/gofunc_test.go @@ -1,4 +1,4 @@ -package internalwasm +package wasm import ( "context" @@ -7,7 +7,7 @@ import ( "github.com/stretchr/testify/require" - publicwasm "github.com/tetratelabs/wazero/wasm" + "github.com/tetratelabs/wazero/api" ) type errno uint32 @@ -68,7 +68,7 @@ func TestGetFunctionType(t *testing.T) { }, { name: "wasm.Module void return", - inputFunc: func(publicwasm.Module) {}, + inputFunc: func(api.Module) {}, expectedKind: FunctionKindGoModule, expectedType: &FunctionType{Params: []ValueType{}, Results: []ValueType{}}, }, @@ -86,7 +86,7 @@ func TestGetFunctionType(t *testing.T) { }, { name: "all supported params and i32 result - wasm.Module", - inputFunc: func(publicwasm.Module, uint32, uint64, float32, float64) uint32 { return 0 }, + inputFunc: func(api.Module, uint32, uint64, float32, float64) uint32 { return 0 }, expectedKind: FunctionKindGoModule, expectedType: &FunctionType{Params: []ValueType{i32, i64, f32, f64}, Results: []ValueType{i32}}, }, @@ -146,7 +146,7 @@ func TestGetFunctionTypeErrors(t *testing.T) { }, { name: "multiple context types", - input: func(publicwasm.Module, context.Context) error { return nil }, + input: func(api.Module, context.Context) error { return nil }, expectedErr: "param[1] is a context.Context, which may be defined only once as param[0]", }, { @@ -156,8 +156,8 @@ func TestGetFunctionTypeErrors(t *testing.T) { }, { name: "multiple wasm.Module", - input: func(publicwasm.Module, uint64, publicwasm.Module) error { return nil }, - expectedErr: "param[2] is a wasm.Module, which may be defined only once as param[0]", + input: func(api.Module, uint64, api.Module) error { return nil }, + expectedErr: "param[2] is a api.Module, which may be defined only once as param[0]", }, } diff --git a/internal/wasm/host.go b/internal/wasm/host.go index 717d2c4b..ec6216ff 100644 --- a/internal/wasm/host.go +++ b/internal/wasm/host.go @@ -1,4 +1,4 @@ -package internalwasm +package wasm import ( "fmt" diff --git a/internal/wasm/host_test.go b/internal/wasm/host_test.go index 119b5edc..93ce5779 100644 --- a/internal/wasm/host_test.go +++ b/internal/wasm/host_test.go @@ -1,4 +1,4 @@ -package internalwasm +package wasm import ( "reflect" @@ -6,19 +6,18 @@ import ( "github.com/stretchr/testify/require" - "github.com/tetratelabs/wazero/wasi" - "github.com/tetratelabs/wazero/wasm" + "github.com/tetratelabs/wazero/api" ) // wasiAPI simulates the real WASI api type wasiAPI struct { } -func (a *wasiAPI) ArgsSizesGet(ctx wasm.Module, resultArgc, resultArgvBufSize uint32) wasi.Errno { +func (a *wasiAPI) ArgsSizesGet(ctx api.Module, resultArgc, resultArgvBufSize uint32) uint32 { return 0 } -func (a *wasiAPI) FdWrite(ctx wasm.Module, fd, iovs, iovsCount, resultSize uint32) wasi.Errno { +func (a *wasiAPI) FdWrite(ctx api.Module, fd, iovs, iovsCount, resultSize uint32) uint32 { return 0 } @@ -47,7 +46,7 @@ func TestNewHostModule(t *testing.T) { }, { name: "two struct funcs", - moduleName: wasi.ModuleSnapshotPreview1, + moduleName: "wasi_snapshot_preview1", goFuncs: map[string]interface{}{ functionArgsSizesGet: a.ArgsSizesGet, functionFdWrite: a.FdWrite, @@ -64,7 +63,7 @@ func TestNewHostModule(t *testing.T) { "fd_write": {Name: "fd_write", Type: ExternTypeFunc, Index: 1}, }, NameSection: &NameSection{ - ModuleName: wasi.ModuleSnapshotPreview1, + ModuleName: "wasi_snapshot_preview1", FunctionNames: NameMap{ {Index: 0, Name: "args_sizes_get"}, {Index: 1, Name: "fd_write"}, @@ -116,7 +115,7 @@ func TestNewHostModule_Errors(t *testing.T) { func TestModule_validateHostFunctions(t *testing.T) { notFn := reflect.ValueOf(t) - fn := reflect.ValueOf(func(wasm.Module) {}) + fn := reflect.ValueOf(func(api.Module) {}) t.Run("ok", func(t *testing.T) { m := Module{ diff --git a/internal/wasm/instruction.go b/internal/wasm/instruction.go index ebb81340..ee32eb36 100644 --- a/internal/wasm/instruction.go +++ b/internal/wasm/instruction.go @@ -1,4 +1,4 @@ -package internalwasm +package wasm // Opcode is the binary Opcode of an instruction. See also InstructionName type Opcode = byte diff --git a/internal/wasm/interpreter/interpreter.go b/internal/wasm/interpreter/interpreter.go index 8148bf3a..a39000b1 100644 --- a/internal/wasm/interpreter/interpreter.go +++ b/internal/wasm/interpreter/interpreter.go @@ -12,7 +12,7 @@ import ( "sync/atomic" "github.com/tetratelabs/wazero/internal/moremath" - wasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm" "github.com/tetratelabs/wazero/internal/wasm/buildoptions" "github.com/tetratelabs/wazero/internal/wazeroir" "github.com/tetratelabs/wazero/sys" @@ -20,7 +20,7 @@ import ( var callStackCeiling = buildoptions.CallStackCeiling -// engine is an interpreter implementation of internalwasm.Engine +// engine is an interpreter implementation of wasm.Engine type engine struct { compiledFunctions map[*wasm.FunctionInstance]*compiledFunction // guarded by mutex. mux sync.RWMutex @@ -51,7 +51,7 @@ func (e *engine) addCompiledFunction(f *wasm.FunctionInstance, cf *compiledFunct e.compiledFunctions[f] = cf } -// moduleEngine implements internalwasm.ModuleEngine +// moduleEngine implements wasm.ModuleEngine type moduleEngine struct { // name is the name the module was instantiated with used for error handling. name string @@ -160,7 +160,7 @@ type interpreterOp struct { rs []*wazeroir.InclusiveRange } -// NewModuleEngine implements the same method as documented on internalwasm.Engine. +// NewModuleEngine implements the same method as documented on wasm.Engine. func (e *engine) NewModuleEngine(name string, importedFunctions, moduleFunctions []*wasm.FunctionInstance, table *wasm.TableInstance, tableInit map[wasm.Index]wasm.Index) (wasm.ModuleEngine, error) { imported := uint32(len(importedFunctions)) me := &moduleEngine{ @@ -210,7 +210,7 @@ func (e *engine) NewModuleEngine(name string, importedFunctions, moduleFunctions return me, nil } -// Release implements internalwasm.Engine Release +// Release implements wasm.Engine Release func (me *moduleEngine) Release() error { // Release all the function instances declared in this module. for _, cf := range me.compiledFunctions[me.importedFunctionCount:] { @@ -493,12 +493,12 @@ func (e *engine) lowerIROps(f *wasm.FunctionInstance, return ret, nil } -// Name implements the same method as documented on internalwasm.ModuleEngine. +// Name implements the same method as documented on wasm.ModuleEngine. func (me *moduleEngine) Name() string { return me.name } -// Call implements the same method as documented on internalwasm.ModuleEngine. +// Call implements the same method as documented on wasm.ModuleEngine. func (me *moduleEngine) Call(ctx *wasm.ModuleContext, f *wasm.FunctionInstance, params ...uint64) (results []uint64, err error) { // Note: The input parameters are pre-validated, so a compiled function is only absent on close. Updates to // compiledFunctions on close aren't locked, neither is this read. @@ -1595,7 +1595,7 @@ func (ce *callEngine) callNativeFunc(ctx *wasm.ModuleContext, f *compiledFunctio ce.popFrame() } -// CloseWithExitCode implements the same method as documented on internalwasm.ModuleEngine. +// CloseWithExitCode implements the same method as documented on wasm.ModuleEngine. func (me *moduleEngine) CloseWithExitCode(exitCode uint32) (bool, error) { closed := uint64(1) + uint64(exitCode)<<32 // Store exitCode as high-order bits. if !atomic.CompareAndSwapUint64(&me.closed, 0, closed) { diff --git a/internal/wasm/interpreter/interpreter_test.go b/internal/wasm/interpreter/interpreter_test.go index a0fd7ad1..95bae339 100644 --- a/internal/wasm/interpreter/interpreter_test.go +++ b/internal/wasm/interpreter/interpreter_test.go @@ -9,7 +9,7 @@ import ( "github.com/stretchr/testify/require" "github.com/tetratelabs/wazero/internal/testing/enginetest" - wasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm" "github.com/tetratelabs/wazero/internal/wasm/buildoptions" "github.com/tetratelabs/wazero/internal/wazeroir" ) diff --git a/internal/wasm/jit/arch_amd64.go b/internal/wasm/jit/arch_amd64.go index dab9f42b..60298e7b 100644 --- a/internal/wasm/jit/arch_amd64.go +++ b/internal/wasm/jit/arch_amd64.go @@ -1,7 +1,7 @@ package jit import ( - wasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm" "github.com/tetratelabs/wazero/internal/wazeroir" ) diff --git a/internal/wasm/jit/arch_arm64.go b/internal/wasm/jit/arch_arm64.go index b617c445..15eb1024 100644 --- a/internal/wasm/jit/arch_arm64.go +++ b/internal/wasm/jit/arch_arm64.go @@ -3,7 +3,7 @@ package jit import ( "math" - wasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm" "github.com/tetratelabs/wazero/internal/wazeroir" ) diff --git a/internal/wasm/jit/arch_other.go b/internal/wasm/jit/arch_other.go index a0606653..ac63cd38 100644 --- a/internal/wasm/jit/arch_other.go +++ b/internal/wasm/jit/arch_other.go @@ -6,7 +6,7 @@ import ( "fmt" "runtime" - wasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm" "github.com/tetratelabs/wazero/internal/wazeroir" ) diff --git a/internal/wasm/jit/compiler.go b/internal/wasm/jit/compiler.go index 3f7bcd95..2ce6b972 100644 --- a/internal/wasm/jit/compiler.go +++ b/internal/wasm/jit/compiler.go @@ -24,7 +24,7 @@ type compiler interface { // See wazeroir.OperationLabel compileLabel(o *wazeroir.OperationLabel) (skipThisLabel bool) // compileUnreachable adds instructions to return to engine with jitCallStatusCodeUnreachable status. - // See internalwasm.OpcodeUnreachable + // See wasm.OpcodeUnreachable compileUnreachable() error // compileSwap adds instruction to swap the stack top value with the target in the Wasm value stack. // The values are might be on registers or memory-stack at runtime, so compiler implementations @@ -33,17 +33,17 @@ type compiler interface { compileSwap(o *wazeroir.OperationSwap) error // compileGlobalGet adds instructions to read the value of the given index in the ModuleInstance.Globals // and push the value onto the stack. - // See internalwasm.OpcodeGlobalGet + // See wasm.OpcodeGlobalGet compileGlobalGet(o *wazeroir.OperationGlobalGet) error // compileGlobalSet adds instructions to set the top value on the stack to the given index in the ModuleInstance.Globals. - // See internalwasm.OpcodeGlobalSet + // See wasm.OpcodeGlobalSet compileGlobalSet(o *wazeroir.OperationGlobalSet) error // compileBr adds instructions to branch into the given label. - // See internalwasm.OpcodeBr + // See wasm.OpcodeBr compileBr(o *wazeroir.OperationBr) error // compileBrIf adds instructions to pops a value and branch into ".then" label if the value equals 1. // Otherwise, the code branches into ".else" label. - // See internalwasm.OpcodeBrIf and wazeroir.OperationBrIf + // See wasm.OpcodeBrIf and wazeroir.OperationBrIf compileBrIf(o *wazeroir.OperationBrIf) error // compileBrTable adds instructions to do br_table operation. // A br_table operation has list of targets and default target, and @@ -53,10 +53,10 @@ type compiler interface { // For example, assume we have operations like {default: L_DEFAULT, targets: [L0, L1, L2]}. // If "index" >= len(defaults), then branch into the L_DEFAULT label. // Otherwise, we enter label of targets[index]. - // See internalwasm.OpcodeBrTable + // See wasm.OpcodeBrTable compileBrTable(o *wazeroir.OperationBrTable) error // compileCall adds instructions to call into a function of the given index. - // See internalwasm.OpcodeCall + // See wasm.OpcodeCall compileCall(o *wazeroir.OperationCall) error // compileCallIndirect adds instructions to perform call_indirect operation. // This consumes the one value from the top of stack (called "offset"), @@ -77,7 +77,7 @@ type compiler interface { compileDrop(o *wazeroir.OperationDrop) error // compileSelect uses top three values on the stack. For example, if we have stack as [..., x1, x2, c] // and the value "c" equals zero, then the stack results in [..., x1], otherwise, [..., x2]. - // See internalwasm.OpcodeSelect + // See wasm.OpcodeSelect compileSelect() error // compilePick adds instructions to copy a value on the given location in the Wasm value stack, // and push the copied value onto the top of the stack. @@ -85,118 +85,118 @@ type compiler interface { compilePick(o *wazeroir.OperationPick) error // compileAdd adds instructions to pop two values from the stack, add these two values, and push // back the result onto the stack. - // See internalwasm.OpcodeI32Add internalwasm.OpcodeI64Add internalwasm.OpcodeF32Add internalwasm.OpcodeF64Add + // See wasm.OpcodeI32Add wasm.OpcodeI64Add wasm.OpcodeF32Add wasm.OpcodeF64Add compileAdd(o *wazeroir.OperationAdd) error // compileSub adds instructions to pop two values from the stack, subtract the top from the second one, and push // back the result onto the stack. - // See internalwasm.OpcodeI32Sub internalwasm.OpcodeI64Sub internalwasm.OpcodeF32Sub internalwasm.OpcodeF64Sub + // See wasm.OpcodeI32Sub wasm.OpcodeI64Sub wasm.OpcodeF32Sub wasm.OpcodeF64Sub compileSub(o *wazeroir.OperationSub) error // compileMul adds instructions to pop two values from the stack, multiply these two values, and push // back the result onto the stack. - // See internalwasm.OpcodeI32Mul internalwasm.OpcodeI64Mul internalwasm.OpcodeF32Mul internalwasm.OpcodeF64Mul + // See wasm.OpcodeI32Mul wasm.OpcodeI64Mul wasm.OpcodeF32Mul wasm.OpcodeF64Mul compileMul(o *wazeroir.OperationMul) error // compileClz emits instructions to count up the leading zeros in the // current top of the stack, and push the count result. // For example, stack of [..., 0x00_ff_ff_ff] results in [..., 8]. - // See internalwasm.OpcodeI32Clz internalwasm.OpcodeI64Clz + // See wasm.OpcodeI32Clz wasm.OpcodeI64Clz compileClz(o *wazeroir.OperationClz) error // compileCtz emits instructions to count up the trailing zeros in the // current top of the stack, and push the count result. // For example, stack of [..., 0xff_ff_ff_00] results in [..., 8]. - // See internalwasm.OpcodeI32Ctz internalwasm.OpcodeI64Ctz + // See wasm.OpcodeI32Ctz wasm.OpcodeI64Ctz compileCtz(o *wazeroir.OperationCtz) error // compilePopcnt emits instructions to count up the number of set bits in the // current top of the stack, and push the count result. // For example, stack of [..., 0b00_00_00_11] results in [..., 2]. - // See internalwasm.OpcodeI32Popcnt internalwasm.OpcodeI64Popcnt + // See wasm.OpcodeI32Popcnt wasm.OpcodeI64Popcnt compilePopcnt(o *wazeroir.OperationPopcnt) error // compileDiv emits the instructions to perform division on the top two values on the stack. - // See internalwasm.OpcodeI32DivS internalwasm.OpcodeI32DivU internalwasm.OpcodeI64DivS internalwasm.OpcodeI64DivU internalwasm.OpcodeF32Div internalwasm.OpcodeF64Div + // See wasm.OpcodeI32DivS wasm.OpcodeI32DivU wasm.OpcodeI64DivS wasm.OpcodeI64DivU wasm.OpcodeF32Div wasm.OpcodeF64Div compileDiv(o *wazeroir.OperationDiv) error // compileRem emits the instructions to perform division on the top // two values of integer type on the stack and puts the remainder of the result // onto the stack. For example, stack [..., 10, 3] results in [..., 1] where // the quotient is discarded. - // See internalwasm.OpcodeI32RemS internalwasm.OpcodeI32RemU internalwasm.OpcodeI64RemS internalwasm.OpcodeI64RemU + // See wasm.OpcodeI32RemS wasm.OpcodeI32RemU wasm.OpcodeI64RemS wasm.OpcodeI64RemU compileRem(o *wazeroir.OperationRem) error // compileAnd emits instructions to perform logical "and" operation on // top two values on the stack, and push the result. - // See internalwasm.OpcodeI32And internalwasm.OpcodeI64And + // See wasm.OpcodeI32And wasm.OpcodeI64And compileAnd(o *wazeroir.OperationAnd) error // compileOr emits instructions to perform logical "or" operation on // top two values on the stack, and pushes the result. - // See internalwasm.OpcodeI32Or internalwasm.OpcodeI64Or + // See wasm.OpcodeI32Or wasm.OpcodeI64Or compileOr(o *wazeroir.OperationOr) error // compileXor emits instructions to perform logical "xor" operation on // top two values on the stack, and pushes the result. - // See internalwasm.OpcodeI32Xor internalwasm.OpcodeI64Xor + // See wasm.OpcodeI32Xor wasm.OpcodeI64Xor compileXor(o *wazeroir.OperationXor) error // compileShl emits instructions to perform a shift-left operation on // top two values on the stack, and pushes the result. - // See internalwasm.OpcodeI32Shl internalwasm.OpcodeI64Shl + // See wasm.OpcodeI32Shl wasm.OpcodeI64Shl compileShl(o *wazeroir.OperationShl) error // compileShr emits instructions to perform a shift-right operation on // top two values on the stack, and pushes the result. - // See internalwasm.OpcodeI32Shr internalwasm.OpcodeI64Shr + // See wasm.OpcodeI32Shr wasm.OpcodeI64Shr compileShr(o *wazeroir.OperationShr) error // compileRotl emits instructions to perform a rotate-left operation on // top two values on the stack, and pushes the result. - // See internalwasm.OpcodeI32Rotl internalwasm.OpcodeI64Rotl + // See wasm.OpcodeI32Rotl wasm.OpcodeI64Rotl compileRotl(o *wazeroir.OperationRotl) error // compileRotr emits instructions to perform a rotate-right operation on // top two values on the stack, and pushes the result. - // See internalwasm.OpcodeI32Rotr internalwasm.OpcodeI64Rotr + // See wasm.OpcodeI32Rotr wasm.OpcodeI64Rotr compileRotr(o *wazeroir.OperationRotr) error // compileAbs adds instructions to replace the top value of float type on the stack with its absolute value. // For example, stack [..., -1.123] results in [..., 1.123]. - // See internalwasm.OpcodeF32Abs internalwasm.OpcodeF64Abs + // See wasm.OpcodeF32Abs wasm.OpcodeF64Abs compileAbs(o *wazeroir.OperationAbs) error // compileNeg adds instructions to replace the top value of float type on the stack with its negated value. // For example, stack [..., -1.123] results in [..., 1.123]. - // See internalwasm.OpcodeF32Neg internalwasm.OpcodeF64Neg + // See wasm.OpcodeF32Neg wasm.OpcodeF64Neg compileNeg(o *wazeroir.OperationNeg) error // compileCeil adds instructions to replace the top value of float type on the stack with its ceiling value. // For example, stack [..., 1.123] results in [..., 2.0]. This is equivalent to math.Ceil. - // See internalwasm.OpcodeF32Ceil internalwasm.OpcodeF64Ceil + // See wasm.OpcodeF32Ceil wasm.OpcodeF64Ceil compileCeil(o *wazeroir.OperationCeil) error // compileFloor adds instructions to replace the top value of float type on the stack with its floor value. // For example, stack [..., 1.123] results in [..., 1.0]. This is equivalent to math.Floor. - // See internalwasm.OpcodeF32Floor internalwasm.OpcodeF64Floor + // See wasm.OpcodeF32Floor wasm.OpcodeF64Floor compileFloor(o *wazeroir.OperationFloor) error // compileTrunc adds instructions to replace the top value of float type on the stack with its truncated value. // For example, stack [..., 1.9] results in [..., 1.0]. This is equivalent to math.Trunc. - // See internalwasm.OpcodeF32Trunc internalwasm.OpcodeF64Trunc + // See wasm.OpcodeF32Trunc wasm.OpcodeF64Trunc compileTrunc(o *wazeroir.OperationTrunc) error // compileNearest adds instructions to replace the top value of float type on the stack with its nearest integer value. // For example, stack [..., 1.9] results in [..., 2.0]. This is *not* equivalent to math.Round and instead has the same // the semantics of LLVM's rint intrinsic. See https://llvm.org/docs/LangRef.html#llvm-rint-intrinsic. // For example, math.Round(-4.5) produces -5 while we want to produce -4. - // See internalwasm.OpcodeF32Nearest internalwasm.OpcodeF64Nearest + // See wasm.OpcodeF32Nearest wasm.OpcodeF64Nearest compileNearest(o *wazeroir.OperationNearest) error // compileSqrt adds instructions to replace the top value of float type on the stack with its square root. // For example, stack [..., 9.0] results in [..., 3.0]. This is equivalent to "math.Sqrt". - // See internalwasm.OpcodeF32Sqrt internalwasm.OpcodeF64Sqrt + // See wasm.OpcodeF32Sqrt wasm.OpcodeF64Sqrt compileSqrt(o *wazeroir.OperationSqrt) error // compileMin adds instructions to pop two values from the stack, and push back the maximum of // these two values onto the stack. For example, stack [..., 100.1, 1.9] results in [..., 1.9]. // Note: WebAssembly specifies that min/max must always return NaN if one of values is NaN, // which is a different behavior different from math.Min. - // See internalwasm.OpcodeF32Min internalwasm.OpcodeF64Min + // See wasm.OpcodeF32Min wasm.OpcodeF64Min compileMin(o *wazeroir.OperationMin) error // compileMax adds instructions to pop two values from the stack, and push back the maximum of // these two values onto the stack. For example, stack [..., 100.1, 1.9] results in [..., 100.1]. // Note: WebAssembly specifies that min/max must always return NaN if one of values is NaN, // which is a different behavior different from math.Max. - // See internalwasm.OpcodeF32Max internalwasm.OpcodeF64Max + // See wasm.OpcodeF32Max wasm.OpcodeF64Max compileMax(o *wazeroir.OperationMax) error // compileCopysign adds instructions to pop two float values from the stack, and copy the signbit of // the first-popped value to the last one. // For example, stack [..., 1.213, -5.0] results in [..., -1.213]. - // See internalwasm.OpcodeF32Copysign internalwasm.OpcodeF64Copysign + // See wasm.OpcodeF32Copysign wasm.OpcodeF64Copysign compileCopysign(o *wazeroir.OperationCopysign) error // compileI32WrapFromI64 adds instructions to replace the 64-bit int on top of the stack // with the corresponding 32-bit integer. This is equivalent to uint64(uint32(v)) in Go. - // See internalwasm.OpcodeI32WrapI64. + // See wasm.OpcodeI32WrapI64. compileI32WrapFromI64() error // compileITruncFromF adds instructions to replace the top value of float type on the stack with // the corresponding int value. This is equivalent to int32(math.Trunc(float32(x))), uint32(math.Trunc(float64(x))), etc in Go. @@ -217,124 +217,124 @@ type compiler interface { compileFConvertFromI(o *wazeroir.OperationFConvertFromI) error // compileF32DemoteFromF64 adds instructions to replace the 64-bit float on top of the stack // with the corresponding 32-bit float. This is equivalent to float32(float64(v)) in Go. - // See internalwasm.OpcodeF32DemoteF64 + // See wasm.OpcodeF32DemoteF64 compileF32DemoteFromF64() error // compileF64PromoteFromF32 adds instructions to replace the 32-bit float on top of the stack // with the corresponding 64-bit float. This is equivalent to float64(float32(v)) in Go. - // See internalwasm.OpcodeF64PromoteF32 + // See wasm.OpcodeF64PromoteF32 compileF64PromoteFromF32() error // compileI32ReinterpretFromF32 adds instructions to reinterpret the 32-bit float on top of the stack // as a 32-bit integer by preserving the bit representation. If the value is on the stack, // this is no-op as there is nothing to do for converting type. - // See internalwasm.OpcodeI32ReinterpretF32. + // See wasm.OpcodeI32ReinterpretF32. compileI32ReinterpretFromF32() error // compileI64ReinterpretFromF64 adds instructions to reinterpret the 64-bit float on top of the stack // as a 64-bit integer by preserving the bit representation. - // See internalwasm.OpcodeI64ReinterpretF64. + // See wasm.OpcodeI64ReinterpretF64. compileI64ReinterpretFromF64() error // compileF32ReinterpretFromI32 adds instructions to reinterpret the 32-bit int on top of the stack // as a 32-bit float by preserving the bit representation. - // See internalwasm.OpcodeF32ReinterpretI32. + // See wasm.OpcodeF32ReinterpretI32. compileF32ReinterpretFromI32() error // compileF64ReinterpretFromI64 adds instructions to reinterpret the 64-bit int on top of the stack // as a 64-bit float by preserving the bit representation. - // See internalwasm.OpcodeF64ReinterpretI64. + // See wasm.OpcodeF64ReinterpretI64. compileF64ReinterpretFromI64() error // compileExtend adds instructions to extend the 32-bit signed or unsigned int on top of the stack // as a 64-bit integer of corresponding signedness. For unsigned case, this is just reinterpreting the // underlying bit pattern as 64-bit integer. For signed case, this is sign-extension which preserves the // original integer's sign. - // See internalwasm.OpcodeI64ExtendI32S internalwasm.OpcodeI64ExtendI32U + // See wasm.OpcodeI64ExtendI32S wasm.OpcodeI64ExtendI32U compileExtend(o *wazeroir.OperationExtend) error // compileEq adds instructions to pop two values from the stack and push 1 if they equal otherwise 0. - // See internalwasm.OpcodeI32Eq internalwasm.OpcodeI64Eq + // See wasm.OpcodeI32Eq wasm.OpcodeI64Eq compileEq(o *wazeroir.OperationEq) error // compileEq adds instructions to pop two values from the stack and push 0 if they equal otherwise 1. - // See internalwasm.OpcodeI32Ne internalwasm.OpcodeI64Ne + // See wasm.OpcodeI32Ne wasm.OpcodeI64Ne compileNe(o *wazeroir.OperationNe) error // compileEq adds instructions to pop a value from the stack and push 1 if it equals zero, 0. - // See internalwasm.OpcodeI32Eqz internalwasm.OpcodeI64Eqz + // See wasm.OpcodeI32Eqz wasm.OpcodeI64Eqz compileEqz(o *wazeroir.OperationEqz) error // compileLt adds instructions to pop two values from the stack and push 1 if the second is less than the top one. Otherwise 0. - // See internalwasm.OpcodeI32Lt internalwasm.OpcodeI64Lt + // See wasm.OpcodeI32Lt wasm.OpcodeI64Lt compileLt(o *wazeroir.OperationLt) error // compileGt adds instructions to pop two values from the stack and push 1 if the second is greater than the top one. Otherwise 0. - // See internalwasm.OpcodeI32Gt internalwasm.OpcodeI64Gt + // See wasm.OpcodeI32Gt wasm.OpcodeI64Gt compileGt(o *wazeroir.OperationGt) error // compileLe adds instructions to pop two values from the stack and push 1 if the second is less than or equals the top one. Otherwise 0. - // See internalwasm.OpcodeI32Le internalwasm.OpcodeI64Le + // See wasm.OpcodeI32Le wasm.OpcodeI64Le compileLe(o *wazeroir.OperationLe) error // compileLe adds instructions to pop two values from the stack and push 1 if the second is greater than or equals the top one. Otherwise 0. - // See internalwasm.OpcodeI32Ge internalwasm.OpcodeI64Ge + // See wasm.OpcodeI32Ge wasm.OpcodeI64Ge compileGe(o *wazeroir.OperationGe) error // compileLoad adds instructions to perform load instruction in WebAssembly. - // See internalwasm.OpcodeI32Load internalwasm.OpcodeI64Load internalwasm.OpcodeF32Load internalwasm.OpcodeF64Load + // See wasm.OpcodeI32Load wasm.OpcodeI64Load wasm.OpcodeF32Load wasm.OpcodeF64Load compileLoad(o *wazeroir.OperationLoad) error // compileLoad8 adds instructions to perform load8 instruction in WebAssembly. // The resulting code checks the memory boundary at runtime, and exit the function with jitCallStatusCodeMemoryOutOfBounds if out-of-bounds access happens. - // See internalwasm.OpcodeI32Load8S internalwasm.OpcodeI32Load8U internalwasm.OpcodeI64Load8S internalwasm.OpcodeI64Load8U + // See wasm.OpcodeI32Load8S wasm.OpcodeI32Load8U wasm.OpcodeI64Load8S wasm.OpcodeI64Load8U compileLoad8(o *wazeroir.OperationLoad8) error // compileLoad16 adds instructions to perform load16 instruction in WebAssembly. // The resulting code checks the memory boundary at runtime, and exit the function with jitCallStatusCodeMemoryOutOfBounds if out-of-bounds access happens. - // See internalwasm.OpcodeI32Load16S internalwasm.OpcodeI32Load16U internalwasm.OpcodeI64Load16S internalwasm.OpcodeI64Load16U + // See wasm.OpcodeI32Load16S wasm.OpcodeI32Load16U wasm.OpcodeI64Load16S wasm.OpcodeI64Load16U compileLoad16(o *wazeroir.OperationLoad16) error // compileLoad32 adds instructions to perform load32 instruction in WebAssembly. // The resulting code checks the memory boundary at runtime, and exit the function with jitCallStatusCodeMemoryOutOfBounds // if out-of-bounds access happens. - // See internalwasm.OpcodeI64Load32S internalwasm.OpcodeI64Load32U + // See wasm.OpcodeI64Load32S wasm.OpcodeI64Load32U compileLoad32(o *wazeroir.OperationLoad32) error // compileStore adds instructions to perform store instruction in WebAssembly. // The resulting code checks the memory boundary at runtime, and exit the function with jitCallStatusCodeMemoryOutOfBounds // if out-of-bounds access happens. - // See internalwasm.OpcodeI32Store internalwasm.OpcodeI64Store internalwasm.OpcodeF32Store internalwasm.OpcodeF64Store + // See wasm.OpcodeI32Store wasm.OpcodeI64Store wasm.OpcodeF32Store wasm.OpcodeF64Store compileStore(o *wazeroir.OperationStore) error // compileStore8 adds instructions to perform store8 instruction in WebAssembly. // The resulting code checks the memory boundary at runtime, and exit the function with jitCallStatusCodeMemoryOutOfBounds // if out-of-bounds access happens. - // See internalwasm.OpcodeI32Store8S internalwasm.OpcodeI32Store8U internalwasm.OpcodeI64Store8S internalwasm.OpcodeI64Store8U + // See wasm.OpcodeI32Store8S wasm.OpcodeI32Store8U wasm.OpcodeI64Store8S wasm.OpcodeI64Store8U compileStore8(o *wazeroir.OperationStore8) error // compileStore16 adds instructions to perform store16 instruction in WebAssembly. // The resulting code checks the memory boundary at runtime, and exit the function with jitCallStatusCodeMemoryOutOfBounds // if out-of-bounds access happens. - // See internalwasm.OpcodeI32Store16S internalwasm.OpcodeI32Store16U internalwasm.OpcodeI64Store16S internalwasm.OpcodeI64Store16U + // See wasm.OpcodeI32Store16S wasm.OpcodeI32Store16U wasm.OpcodeI64Store16S wasm.OpcodeI64Store16U compileStore16(o *wazeroir.OperationStore16) error // compileStore32 adds instructions to perform store32 instruction in WebAssembly. // The resulting code checks the memory boundary at runtime, and exit the function with jitCallStatusCodeMemoryOutOfBounds // if out-of-bounds access happens. - // See internalwasm.OpcodeI64Store32S internalwasm.OpcodeI64Store32U + // See wasm.OpcodeI64Store32S wasm.OpcodeI64Store32U compileStore32(o *wazeroir.OperationStore32) error // compileMemorySize adds instruction to pop a value from the stack, grow the memory buffer according to the value, // and push the previous page size onto the stack. - // See internalwasm.OpcodeMemoryGrow + // See wasm.OpcodeMemoryGrow compileMemoryGrow() error // compileMemorySize adds instruction to read the current page size of memory instance and push it onto the stack. - // See internalwasm.OpcodeMemorySize + // See wasm.OpcodeMemorySize compileMemorySize() error // compileConstI32 adds instruction to push the given constant i32 value onto the stack. - // See internalwasm.OpcodeI32Const + // See wasm.OpcodeI32Const compileConstI32(o *wazeroir.OperationConstI32) error // compileConstI32 adds instruction to push the given constant i64 value onto the stack. - // See internalwasm.OpcodeI64Const + // See wasm.OpcodeI64Const compileConstI64(o *wazeroir.OperationConstI64) error // compileConstI32 adds instruction to push the given constant f32 value onto the stack. - // See internalwasm.OpcodeF32Const + // See wasm.OpcodeF32Const compileConstF32(o *wazeroir.OperationConstF32) error // compileConstI32 adds instruction to push the given constant f64 value onto the stack. - // See internalwasm.OpcodeF64Const + // See wasm.OpcodeF64Const compileConstF64(o *wazeroir.OperationConstF64) error // compileSignExtend32From8 adds instruction to sign-extends the first 8-bits of 32-bit in as signed 32-bit int. - // See internalwasm.OpcodeI32Extend8S + // See wasm.OpcodeI32Extend8S compileSignExtend32From8() error // compileSignExtend32From16 adds instruction to sign-extends the first 16-bits of 32-bit in as signed 32-bit int. - // See internalwasm.OpcodeI32Extend16S + // See wasm.OpcodeI32Extend16S compileSignExtend32From16() error // compileSignExtend64From8 adds instruction to sign-extends the first 8-bits of 64-bit in as signed 64-bit int. - // See internalwasm.OpcodeI64Extend8S + // See wasm.OpcodeI64Extend8S compileSignExtend64From8() error // compileSignExtend64From16 adds instruction to sign-extends the first 16-bits of 64-bit in as signed 64-bit int. - // See internalwasm.OpcodeI64Extend16S + // See wasm.OpcodeI64Extend16S compileSignExtend64From16() error // compileSignExtend64From32 adds instruction to sign-extends the first 32-bits of 64-bit in as signed 64-bit int. - // See internalwasm.OpcodeI64Extend32S + // See wasm.OpcodeI64Extend32S compileSignExtend64From32() error } diff --git a/internal/wasm/jit/engine.go b/internal/wasm/jit/engine.go index 392fd4cf..7a5058cf 100644 --- a/internal/wasm/jit/engine.go +++ b/internal/wasm/jit/engine.go @@ -11,14 +11,14 @@ import ( "sync/atomic" "unsafe" - wasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm" "github.com/tetratelabs/wazero/internal/wasm/buildoptions" "github.com/tetratelabs/wazero/internal/wazeroir" "github.com/tetratelabs/wazero/sys" ) type ( - // engine is an JIT implementation of internalwasm.Engine + // engine is an JIT implementation of wasm.Engine engine struct { compiledFunctions map[*wasm.FunctionInstance]*compiledFunction // guarded by mutex. mux sync.RWMutex @@ -26,7 +26,7 @@ type ( setFinalizer func(obj interface{}, finalizer interface{}) } - // moduleEngine implements internalwasm.ModuleEngine + // moduleEngine implements wasm.ModuleEngine moduleEngine struct { // name is the name the module was instantiated with used for error handling. name string @@ -242,24 +242,24 @@ const ( compiledFunctionStackPointerCeilOffset = 8 compiledFunctionSourceOffset = 16 - // Offsets for internalwasm.ModuleInstance. + // Offsets for wasm.ModuleInstance. moduleInstanceGlobalsOffset = 48 moduleInstanceMemoryOffset = 72 moduleInstanceTableOffset = 80 moduleInstanceEngineOffset = 120 - // Offsets for internalwasm.TableInstance. + // Offsets for wasm.TableInstance. tableInstanceTableOffset = 0 tableInstanceTableLenOffset = 8 - // Offsets for internalwasm.FunctionInstance. + // Offsets for wasm.FunctionInstance. functionInstanceTypeIDOffset = 96 - // Offsets for internalwasm.MemoryInstance. + // Offsets for wasm.MemoryInstance. memoryInstanceBufferOffset = 0 memoryInstanceBufferLenOffset = 8 - // Offsets for internalwasm.GlobalInstance. + // Offsets for wasm.GlobalInstance. globalInstanceValueOffset = 8 // Offsets for Go's interface. @@ -355,7 +355,7 @@ func releaseCompiledFunction(compiledFn *compiledFunction) { } } -// NewModuleEngine implements the same method as documented on internalwasm.Engine. +// NewModuleEngine implements the same method as documented on wasm.Engine. func (e *engine) NewModuleEngine(name string, importedFunctions, moduleFunctions []*wasm.FunctionInstance, table *wasm.TableInstance, tableInit map[wasm.Index]wasm.Index) (wasm.ModuleEngine, error) { imported := uint32(len(importedFunctions)) me := &moduleEngine{ @@ -453,12 +453,12 @@ func (e *engine) getCompiledFunction(f *wasm.FunctionInstance) (cf *compiledFunc return } -// Name implements the same method as documented on internalwasm.ModuleEngine. +// Name implements the same method as documented on wasm.ModuleEngine. func (me *moduleEngine) Name() string { return me.name } -// Call implements the same method as documented on internalwasm.ModuleEngine. +// Call implements the same method as documented on wasm.ModuleEngine. func (me *moduleEngine) Call(ctx *wasm.ModuleContext, f *wasm.FunctionInstance, params ...uint64) (results []uint64, err error) { // Note: The input parameters are pre-validated, so a compiled function is only absent on close. Updates to // compiledFunctions on close aren't locked, neither is this read. @@ -541,7 +541,7 @@ func failIfClosed(me *moduleEngine) error { return nil } -// CloseWithExitCode implements the same method as documented on internalwasm.ModuleEngine. +// CloseWithExitCode implements the same method as documented on wasm.ModuleEngine. func (me *moduleEngine) CloseWithExitCode(exitCode uint32) (bool, error) { closed := uint64(1) + uint64(exitCode)<<32 // Store exitCode as high-order bits. if !atomic.CompareAndSwapUint64(&me.closed, 0, closed) { diff --git a/internal/wasm/jit/engine_test.go b/internal/wasm/jit/engine_test.go index c5c6c4ae..350d32b7 100644 --- a/internal/wasm/jit/engine_test.go +++ b/internal/wasm/jit/engine_test.go @@ -12,7 +12,7 @@ import ( "github.com/stretchr/testify/require" "github.com/tetratelabs/wazero/internal/testing/enginetest" - wasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm" ) // Ensures that the offset consts do not drift when we manipulate the target structs. diff --git a/internal/wasm/jit/jit_controlflow_test.go b/internal/wasm/jit/jit_controlflow_test.go index 0920add8..31a5b31b 100644 --- a/internal/wasm/jit/jit_controlflow_test.go +++ b/internal/wasm/jit/jit_controlflow_test.go @@ -7,7 +7,7 @@ import ( "github.com/stretchr/testify/require" - wasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm" "github.com/tetratelabs/wazero/internal/wazeroir" ) diff --git a/internal/wasm/jit/jit_global_test.go b/internal/wasm/jit/jit_global_test.go index f701d6e3..19b2e6f8 100644 --- a/internal/wasm/jit/jit_global_test.go +++ b/internal/wasm/jit/jit_global_test.go @@ -5,7 +5,7 @@ import ( "github.com/stretchr/testify/require" - wasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm" "github.com/tetratelabs/wazero/internal/wazeroir" ) diff --git a/internal/wasm/jit/jit_impl_amd64.go b/internal/wasm/jit/jit_impl_amd64.go index 8f382688..f6558e9f 100644 --- a/internal/wasm/jit/jit_impl_amd64.go +++ b/internal/wasm/jit/jit_impl_amd64.go @@ -14,7 +14,7 @@ import ( "github.com/tetratelabs/wazero/internal/asm" amd64 "github.com/tetratelabs/wazero/internal/asm/amd64" - wasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm" "github.com/tetratelabs/wazero/internal/wasm/buildoptions" "github.com/tetratelabs/wazero/internal/wazeroir" ) diff --git a/internal/wasm/jit/jit_impl_amd64_test.go b/internal/wasm/jit/jit_impl_amd64_test.go index e50dc292..290c8b77 100644 --- a/internal/wasm/jit/jit_impl_amd64_test.go +++ b/internal/wasm/jit/jit_impl_amd64_test.go @@ -8,7 +8,7 @@ import ( "github.com/tetratelabs/wazero/internal/asm" amd64 "github.com/tetratelabs/wazero/internal/asm/amd64" "github.com/tetratelabs/wazero/internal/asm/amd64_debug" - wasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm" "github.com/tetratelabs/wazero/internal/wazeroir" ) diff --git a/internal/wasm/jit/jit_impl_arm64.go b/internal/wasm/jit/jit_impl_arm64.go index dd787639..7318dc21 100644 --- a/internal/wasm/jit/jit_impl_arm64.go +++ b/internal/wasm/jit/jit_impl_arm64.go @@ -16,7 +16,7 @@ import ( "github.com/tetratelabs/wazero/internal/asm" arm64 "github.com/tetratelabs/wazero/internal/asm/arm64" - wasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm" "github.com/tetratelabs/wazero/internal/wazeroir" ) diff --git a/internal/wasm/jit/jit_initialization_test.go b/internal/wasm/jit/jit_initialization_test.go index b47c6b89..37af4be9 100644 --- a/internal/wasm/jit/jit_initialization_test.go +++ b/internal/wasm/jit/jit_initialization_test.go @@ -8,7 +8,7 @@ import ( "github.com/stretchr/testify/require" - wasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm" "github.com/tetratelabs/wazero/internal/wazeroir" ) diff --git a/internal/wasm/jit/jit_memory_test.go b/internal/wasm/jit/jit_memory_test.go index 02f0ffa5..2a84404f 100644 --- a/internal/wasm/jit/jit_memory_test.go +++ b/internal/wasm/jit/jit_memory_test.go @@ -9,7 +9,7 @@ import ( "github.com/stretchr/testify/require" - wasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm" "github.com/tetratelabs/wazero/internal/wazeroir" ) diff --git a/internal/wasm/jit/jit_test.go b/internal/wasm/jit/jit_test.go index 1178b69f..113d5273 100644 --- a/internal/wasm/jit/jit_test.go +++ b/internal/wasm/jit/jit_test.go @@ -9,7 +9,7 @@ import ( "github.com/stretchr/testify/require" - wasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm" "github.com/tetratelabs/wazero/internal/wazeroir" ) diff --git a/internal/wasm/jit/jit_value_location.go b/internal/wasm/jit/jit_value_location.go index 6f98dc68..d7c2fe2f 100644 --- a/internal/wasm/jit/jit_value_location.go +++ b/internal/wasm/jit/jit_value_location.go @@ -113,15 +113,15 @@ func (v *valueLocationStack) String() string { return fmt.Sprintf("sp=%d, stack=[%s], used_registers=[%s]", v.sp, strings.Join(stackStr, ","), strings.Join(usedRegisters, ",")) } -func (s *valueLocationStack) clone() *valueLocationStack { +func (v *valueLocationStack) clone() *valueLocationStack { ret := &valueLocationStack{} - ret.sp = s.sp + ret.sp = v.sp ret.usedRegisters = make(map[asm.Register]struct{}, len(ret.usedRegisters)) - for r := range s.usedRegisters { + for r := range v.usedRegisters { ret.markRegisterUsed(r) } - ret.stack = make([]*valueLocation, len(s.stack)) - for i, v := range s.stack { + ret.stack = make([]*valueLocation, len(v.stack)) + for i, v := range v.stack { ret.stack[i] = &valueLocation{ regType: v.regType, conditionalRegister: v.conditionalRegister, @@ -129,13 +129,13 @@ func (s *valueLocationStack) clone() *valueLocationStack { register: v.register, } } - ret.stackPointerCeil = s.stackPointerCeil + ret.stackPointerCeil = v.stackPointerCeil return ret } // pushValueLocationOnRegister creates a new valueLocation with a given register and pushes onto // the location stack. -func (s *valueLocationStack) pushValueLocationOnRegister(reg asm.Register) (loc *valueLocation) { +func (v *valueLocationStack) pushValueLocationOnRegister(reg asm.Register) (loc *valueLocation) { loc = &valueLocation{register: reg, conditionalRegister: asm.ConditionalRegisterStateUnset} if isIntRegister(reg) { @@ -143,67 +143,67 @@ func (s *valueLocationStack) pushValueLocationOnRegister(reg asm.Register) (loc } else if isFloatRegister(reg) { loc.setRegisterType(generalPurposeRegisterTypeFloat) } - s.push(loc) + v.push(loc) return } // pushValueLocationOnRegister creates a new valueLocation and pushes onto the location stack. -func (s *valueLocationStack) pushValueLocationOnStack() (loc *valueLocation) { +func (v *valueLocationStack) pushValueLocationOnStack() (loc *valueLocation) { loc = &valueLocation{register: asm.NilRegister, conditionalRegister: asm.ConditionalRegisterStateUnset} - s.push(loc) + v.push(loc) return } // pushValueLocationOnRegister creates a new valueLocation with a given conditional register state // and pushes onto the location stack. -func (s *valueLocationStack) pushValueLocationOnConditionalRegister(state asm.ConditionalRegisterState) (loc *valueLocation) { +func (v *valueLocationStack) pushValueLocationOnConditionalRegister(state asm.ConditionalRegisterState) (loc *valueLocation) { loc = &valueLocation{register: asm.NilRegister, conditionalRegister: state} - s.push(loc) + v.push(loc) return } // push pushes to a given valueLocation onto the stack. -func (s *valueLocationStack) push(loc *valueLocation) { - loc.stackPointer = s.sp - if s.sp >= uint64(len(s.stack)) { +func (v *valueLocationStack) push(loc *valueLocation) { + loc.stackPointer = v.sp + if v.sp >= uint64(len(v.stack)) { // This case we need to grow the stack capacity by appending the item, // rather than indexing. - s.stack = append(s.stack, loc) + v.stack = append(v.stack, loc) } else { - s.stack[s.sp] = loc + v.stack[v.sp] = loc } - if s.sp > s.stackPointerCeil { - s.stackPointerCeil = s.sp + if v.sp > v.stackPointerCeil { + v.stackPointerCeil = v.sp } - s.sp++ + v.sp++ } -func (s *valueLocationStack) pop() (loc *valueLocation) { - s.sp-- - loc = s.stack[s.sp] +func (v *valueLocationStack) pop() (loc *valueLocation) { + v.sp-- + loc = v.stack[v.sp] return } -func (s *valueLocationStack) peek() (loc *valueLocation) { - loc = s.stack[s.sp-1] +func (v *valueLocationStack) peek() (loc *valueLocation) { + loc = v.stack[v.sp-1] return } -func (s *valueLocationStack) releaseRegister(loc *valueLocation) { - s.markRegisterUnused(loc.register) +func (v *valueLocationStack) releaseRegister(loc *valueLocation) { + v.markRegisterUnused(loc.register) loc.register = asm.NilRegister loc.conditionalRegister = asm.ConditionalRegisterStateUnset } -func (s *valueLocationStack) markRegisterUnused(regs ...asm.Register) { +func (v *valueLocationStack) markRegisterUnused(regs ...asm.Register) { for _, reg := range regs { - delete(s.usedRegisters, reg) + delete(v.usedRegisters, reg) } } -func (s *valueLocationStack) markRegisterUsed(regs ...asm.Register) { +func (v *valueLocationStack) markRegisterUsed(regs ...asm.Register) { for _, reg := range regs { - s.usedRegisters[reg] = struct{}{} + v.usedRegisters[reg] = struct{}{} } } @@ -225,7 +225,7 @@ func (tp generalPurposeRegisterType) String() (ret string) { } // takeFreeRegister searches for unused registers. Any found are marked used and returned. -func (s *valueLocationStack) takeFreeRegister(tp generalPurposeRegisterType) (reg asm.Register, found bool) { +func (v *valueLocationStack) takeFreeRegister(tp generalPurposeRegisterType) (reg asm.Register, found bool) { var targetRegs []asm.Register switch tp { case generalPurposeRegisterTypeFloat: @@ -234,7 +234,7 @@ func (s *valueLocationStack) takeFreeRegister(tp generalPurposeRegisterType) (re targetRegs = unreservedGeneralPurposeIntRegisters } for _, candidate := range targetRegs { - if _, ok := s.usedRegisters[candidate]; ok { + if _, ok := v.usedRegisters[candidate]; ok { continue } return candidate, true @@ -242,7 +242,7 @@ func (s *valueLocationStack) takeFreeRegister(tp generalPurposeRegisterType) (re return 0, false } -func (s *valueLocationStack) takeFreeRegisters(tp generalPurposeRegisterType, num int) (regs []asm.Register, found bool) { +func (v *valueLocationStack) takeFreeRegisters(tp generalPurposeRegisterType, num int) (regs []asm.Register, found bool) { var targetRegs []asm.Register switch tp { case generalPurposeRegisterTypeFloat: @@ -253,7 +253,7 @@ func (s *valueLocationStack) takeFreeRegisters(tp generalPurposeRegisterType, nu regs = make([]asm.Register, 0, num) for _, candidate := range targetRegs { - if _, ok := s.usedRegisters[candidate]; ok { + if _, ok := v.usedRegisters[candidate]; ok { continue } regs = append(regs, candidate) @@ -267,9 +267,9 @@ func (s *valueLocationStack) takeFreeRegisters(tp generalPurposeRegisterType, nu // Search through the stack, and steal the register from the last used // variable on the stack. -func (s *valueLocationStack) takeStealTargetFromUsedRegister(tp generalPurposeRegisterType) (*valueLocation, bool) { - for i := uint64(0); i < s.sp; i++ { - loc := s.stack[i] +func (v *valueLocationStack) takeStealTargetFromUsedRegister(tp generalPurposeRegisterType) (*valueLocation, bool) { + for i := uint64(0); i < v.sp; i++ { + loc := v.stack[i] if loc.onRegister() { switch tp { case generalPurposeRegisterTypeFloat: diff --git a/internal/wasm/memory.go b/internal/wasm/memory.go index b0fcc697..27e077ae 100644 --- a/internal/wasm/memory.go +++ b/internal/wasm/memory.go @@ -1,4 +1,4 @@ -package internalwasm +package wasm import ( "encoding/binary" @@ -18,7 +18,7 @@ const ( MemoryPageSizeInBits = 16 ) -// MemoryInstance represents a memory instance in a store, and implements wasm.Memory. +// MemoryInstance represents a memory instance in a store, and implements api.Memory. // // Note: In WebAssembly 1.0 (20191205), there may be up to one Memory per store, which means the precise memory is always // wasm.Store Memories index zero: `store.Memories[0]` @@ -28,7 +28,7 @@ type MemoryInstance struct { Min, Max uint32 } -// Size implements wasm.Memory Size +// Size implements api.Memory Size func (m *MemoryInstance) Size() uint32 { return uint32(len(m.Buffer)) } @@ -38,7 +38,7 @@ func (m *MemoryInstance) hasSize(offset uint32, sizeInBytes uint32) bool { return uint64(offset)+uint64(sizeInBytes) <= uint64(m.Size()) // uint64 prevents overflow on add } -// ReadByte implements wasm.Memory ReadByte +// ReadByte implements api.Memory ReadByte func (m *MemoryInstance) ReadByte(offset uint32) (byte, bool) { if offset >= m.Size() { return 0, false @@ -46,7 +46,7 @@ func (m *MemoryInstance) ReadByte(offset uint32) (byte, bool) { return m.Buffer[offset], true } -// ReadUint32Le implements wasm.Memory ReadUint32Le +// ReadUint32Le implements api.Memory ReadUint32Le func (m *MemoryInstance) ReadUint32Le(offset uint32) (uint32, bool) { if !m.hasSize(offset, 4) { return 0, false @@ -54,7 +54,7 @@ func (m *MemoryInstance) ReadUint32Le(offset uint32) (uint32, bool) { return binary.LittleEndian.Uint32(m.Buffer[offset : offset+4]), true } -// ReadFloat32Le implements wasm.Memory ReadFloat32Le +// ReadFloat32Le implements api.Memory ReadFloat32Le func (m *MemoryInstance) ReadFloat32Le(offset uint32) (float32, bool) { v, ok := m.ReadUint32Le(offset) if !ok { @@ -63,7 +63,7 @@ func (m *MemoryInstance) ReadFloat32Le(offset uint32) (float32, bool) { return math.Float32frombits(v), true } -// ReadUint64Le implements wasm.Memory ReadUint64Le +// ReadUint64Le implements api.Memory ReadUint64Le func (m *MemoryInstance) ReadUint64Le(offset uint32) (uint64, bool) { if !m.hasSize(offset, 8) { return 0, false @@ -71,7 +71,7 @@ func (m *MemoryInstance) ReadUint64Le(offset uint32) (uint64, bool) { return binary.LittleEndian.Uint64(m.Buffer[offset : offset+8]), true } -// ReadFloat64Le implements wasm.Memory ReadFloat64Le +// ReadFloat64Le implements api.Memory ReadFloat64Le func (m *MemoryInstance) ReadFloat64Le(offset uint32) (float64, bool) { v, ok := m.ReadUint64Le(offset) if !ok { @@ -80,7 +80,7 @@ func (m *MemoryInstance) ReadFloat64Le(offset uint32) (float64, bool) { return math.Float64frombits(v), true } -// Read implements wasm.Memory Read +// Read implements api.Memory Read func (m *MemoryInstance) Read(offset, byteCount uint32) ([]byte, bool) { if !m.hasSize(offset, byteCount) { return nil, false @@ -88,7 +88,7 @@ func (m *MemoryInstance) Read(offset, byteCount uint32) ([]byte, bool) { return m.Buffer[offset : offset+byteCount], true } -// WriteByte implements wasm.Memory WriteByte +// WriteByte implements api.Memory WriteByte func (m *MemoryInstance) WriteByte(offset uint32, v byte) bool { if offset >= m.Size() { return false @@ -97,7 +97,7 @@ func (m *MemoryInstance) WriteByte(offset uint32, v byte) bool { return true } -// WriteUint32Le implements wasm.Memory WriteUint32Le +// WriteUint32Le implements api.Memory WriteUint32Le func (m *MemoryInstance) WriteUint32Le(offset, v uint32) bool { if !m.hasSize(offset, 4) { return false @@ -106,12 +106,12 @@ func (m *MemoryInstance) WriteUint32Le(offset, v uint32) bool { return true } -// WriteFloat32Le implements wasm.Memory WriteFloat32Le +// WriteFloat32Le implements api.Memory WriteFloat32Le func (m *MemoryInstance) WriteFloat32Le(offset uint32, v float32) bool { return m.WriteUint32Le(offset, math.Float32bits(v)) } -// WriteUint64Le implements wasm.Memory WriteUint64Le +// WriteUint64Le implements api.Memory WriteUint64Le func (m *MemoryInstance) WriteUint64Le(offset uint32, v uint64) bool { if !m.hasSize(offset, 8) { return false @@ -120,12 +120,12 @@ func (m *MemoryInstance) WriteUint64Le(offset uint32, v uint64) bool { return true } -// WriteFloat64Le implements wasm.Memory WriteFloat64Le +// WriteFloat64Le implements api.Memory WriteFloat64Le func (m *MemoryInstance) WriteFloat64Le(offset uint32, v float64) bool { return m.WriteUint64Le(offset, math.Float64bits(v)) } -// Write implements wasm.Memory Write +// Write implements api.Memory Write func (m *MemoryInstance) Write(offset uint32, val []byte) bool { if !m.hasSize(offset, uint32(len(val))) { return false diff --git a/internal/wasm/memory_test.go b/internal/wasm/memory_test.go index 8036de26..13732ffa 100644 --- a/internal/wasm/memory_test.go +++ b/internal/wasm/memory_test.go @@ -1,4 +1,4 @@ -package internalwasm +package wasm import ( "math" diff --git a/internal/wasm/module.go b/internal/wasm/module.go index eda52198..b280c133 100644 --- a/internal/wasm/module.go +++ b/internal/wasm/module.go @@ -1,4 +1,4 @@ -package internalwasm +package wasm import ( "bytes" @@ -8,9 +8,9 @@ import ( "sort" "strings" + "github.com/tetratelabs/wazero/api" "github.com/tetratelabs/wazero/internal/ieee754" "github.com/tetratelabs/wazero/internal/leb128" - publicwasm "github.com/tetratelabs/wazero/wasm" ) // DecodeModule parses the configured source into a Module. This function returns when the source is exhausted or @@ -169,7 +169,7 @@ const ( MaximumFunctionIndex = uint32(1 << 27) ) -// TypeOfFunction returns the internalwasm.SectionIDType index for the given function namespace index or nil. +// TypeOfFunction returns the wasm.SectionIDType index for the given function namespace index or nil. // Note: The function index namespace is preceded by imported functions. // TODO: Returning nil should be impossible when decode results are validated. Validate decode before back-filling tests. func (m *Module) TypeOfFunction(funcIdx Index) *FunctionType { @@ -447,9 +447,9 @@ func (m *Module) buildGlobals(importedGlobals []*GlobalInstance) (globals []*Glo case int64: gv = uint64(v) case float32: - gv = publicwasm.EncodeF32(v) + gv = api.EncodeF32(v) case float64: - gv = publicwasm.EncodeF64(v) + gv = api.EncodeF64(v) } globals = append(globals, &GlobalInstance{Type: gs.Type, Val: gv}) } @@ -795,19 +795,19 @@ func SectionIDName(sectionID SectionID) string { return "unknown" } -// ValueType is an alias of wasm.ValueType defined to simplify imports. -type ValueType = publicwasm.ValueType +// ValueType is an alias of api.ValueType defined to simplify imports. +type ValueType = api.ValueType const ( - ValueTypeI32 = publicwasm.ValueTypeI32 - ValueTypeI64 = publicwasm.ValueTypeI64 - ValueTypeF32 = publicwasm.ValueTypeF32 - ValueTypeF64 = publicwasm.ValueTypeF64 + ValueTypeI32 = api.ValueTypeI32 + ValueTypeI64 = api.ValueTypeI64 + ValueTypeF32 = api.ValueTypeF32 + ValueTypeF64 = api.ValueTypeF64 ) -// ValueTypeName is an alias of wasm.ValueTypeName defined to simplify imports. +// ValueTypeName is an alias of api.ValueTypeName defined to simplify imports. func ValueTypeName(t ValueType) string { - return publicwasm.ValueTypeName(t) + return api.ValueTypeName(t) } // ElemType is fixed to ElemTypeFuncref until post 20191205 reference type is implemented. diff --git a/internal/wasm/module_context.go b/internal/wasm/module_context.go index abcb41b7..c511e707 100644 --- a/internal/wasm/module_context.go +++ b/internal/wasm/module_context.go @@ -1,34 +1,34 @@ -package internalwasm +package wasm import ( "context" "fmt" - publicwasm "github.com/tetratelabs/wazero/wasm" + "github.com/tetratelabs/wazero/api" ) -// compile time check to ensure ModuleContext implements wasm.Module -var _ publicwasm.Module = &ModuleContext{} +// compile time check to ensure ModuleContext implements api.Module +var _ api.Module = &ModuleContext{} func NewModuleContext(ctx context.Context, store *Store, instance *ModuleInstance, sys *SysContext) *ModuleContext { return &ModuleContext{ctx: ctx, memory: instance.Memory, module: instance, store: store, sys: sys} } -// ModuleContext implements wasm.Module +// ModuleContext implements api.Module type ModuleContext struct { // ctx is returned by Context and overridden WithContext ctx context.Context module *ModuleInstance // memory is returned by Memory and overridden WithMemory - memory publicwasm.Memory + memory api.Memory store *Store - // sys is not exposed publicly. This is currently only used by internalwasi. + // sys is not exposed publicly. This is currently only used by wasi. // Note: This is a part of ModuleContext so that scope is correct and Close is coherent. sys *SysContext } -// Name implements the same method as documented on wasm.Module +// Name implements the same method as documented on api.Module func (m *ModuleContext) Name() string { return m.module.Name } @@ -41,12 +41,12 @@ func (m *ModuleContext) WithMemory(memory *MemoryInstance) *ModuleContext { return m } -// String implements the same method as documented on wasm.Module +// String implements the same method as documented on api.Module func (m *ModuleContext) String() string { return fmt.Sprintf("Module[%s]", m.Name()) } -// Context implements the same method as documented on wasm.Module +// Context implements the same method as documented on api.Module func (m *ModuleContext) Context() context.Context { return m.ctx } @@ -56,20 +56,20 @@ func (m *ModuleContext) Sys() *SysContext { return m.sys } -// WithContext implements the same method as documented on wasm.Module -func (m *ModuleContext) WithContext(ctx context.Context) publicwasm.Module { +// WithContext implements the same method as documented on api.Module +func (m *ModuleContext) WithContext(ctx context.Context) api.Module { if ctx != nil && ctx != m.ctx { // only re-allocate if it will change the effective context return &ModuleContext{module: m.module, memory: m.memory, ctx: ctx, sys: m.sys} } return m } -// Close implements the same method as documented on wasm.Module. +// Close implements the same method as documented on api.Module. func (m *ModuleContext) Close() (err error) { return m.CloseWithExitCode(0) } -// CloseWithExitCode implements the same method as documented on wasm.Module. +// CloseWithExitCode implements the same method as documented on api.Module. func (m *ModuleContext) CloseWithExitCode(exitCode uint32) (err error) { if err = m.store.CloseModuleWithExitCode(m.module.Name, exitCode); err != nil { return err @@ -79,13 +79,13 @@ func (m *ModuleContext) CloseWithExitCode(exitCode uint32) (err error) { return } -// Memory implements wasm.Module Memory -func (m *ModuleContext) Memory() publicwasm.Memory { +// Memory implements api.Module Memory +func (m *ModuleContext) Memory() api.Memory { return m.module.Memory } -// ExportedMemory implements wasm.Module ExportedMemory -func (m *ModuleContext) ExportedMemory(name string) publicwasm.Memory { +// ExportedMemory implements api.Module ExportedMemory +func (m *ModuleContext) ExportedMemory(name string) api.Memory { exp, err := m.module.getExport(name, ExternTypeMemory) if err != nil { return nil @@ -93,8 +93,8 @@ func (m *ModuleContext) ExportedMemory(name string) publicwasm.Memory { return exp.Memory } -// ExportedFunction implements wasm.Module ExportedFunction -func (m *ModuleContext) ExportedFunction(name string) publicwasm.Function { +// ExportedFunction implements api.Module ExportedFunction +func (m *ModuleContext) ExportedFunction(name string) api.Function { exp, err := m.module.getExport(name, ExternTypeFunc) if err != nil { return nil @@ -102,18 +102,18 @@ func (m *ModuleContext) ExportedFunction(name string) publicwasm.Function { return exp.Function } -// ParamTypes implements wasm.Function ParamTypes -func (f *FunctionInstance) ParamTypes() []publicwasm.ValueType { +// ParamTypes implements api.Function ParamTypes +func (f *FunctionInstance) ParamTypes() []api.ValueType { return f.Type.Params } -// ResultTypes implements wasm.Function ResultTypes -func (f *FunctionInstance) ResultTypes() []publicwasm.ValueType { +// ResultTypes implements api.Function ResultTypes +func (f *FunctionInstance) ResultTypes() []api.ValueType { return f.Type.Results } -// Call implements wasm.Function Call -func (f *FunctionInstance) Call(m publicwasm.Module, params ...uint64) (ret []uint64, err error) { +// Call implements api.Function Call +func (f *FunctionInstance) Call(m api.Module, params ...uint64) (ret []uint64, err error) { mod := f.Module modCtx, ok := m.(*ModuleContext) if ok { @@ -124,8 +124,8 @@ func (f *FunctionInstance) Call(m publicwasm.Module, params ...uint64) (ret []ui return mod.Engine.Call(modCtx, f, params...) } -// ExportedGlobal implements wasm.Module ExportedGlobal -func (m *ModuleContext) ExportedGlobal(name string) publicwasm.Global { +// ExportedGlobal implements api.Module ExportedGlobal +func (m *ModuleContext) ExportedGlobal(name string) api.Global { exp, err := m.module.getExport(name, ExternTypeGlobal) if err != nil { return nil diff --git a/internal/wasm/module_context_test.go b/internal/wasm/module_context_test.go index e77386b9..6b416f66 100644 --- a/internal/wasm/module_context_test.go +++ b/internal/wasm/module_context_test.go @@ -1,4 +1,4 @@ -package internalwasm +package wasm import ( "context" diff --git a/internal/wasm/module_test.go b/internal/wasm/module_test.go index 7e2f0bf8..9b28e5a3 100644 --- a/internal/wasm/module_test.go +++ b/internal/wasm/module_test.go @@ -1,4 +1,4 @@ -package internalwasm +package wasm import ( "encoding/binary" @@ -9,7 +9,7 @@ import ( "github.com/stretchr/testify/require" - "github.com/tetratelabs/wazero/wasm" + "github.com/tetratelabs/wazero/api" ) func TestFunctionType_String(t *testing.T) { @@ -272,7 +272,7 @@ func TestValidateConstExpression(t *testing.T) { func TestModule_Validate_Errors(t *testing.T) { zero := Index(0) - fn := reflect.ValueOf(func(wasm.Module) {}) + fn := reflect.ValueOf(func(api.Module) {}) tests := []struct { name string diff --git a/internal/wasm/store.go b/internal/wasm/store.go index eac37cb7..323a5a6d 100644 --- a/internal/wasm/store.go +++ b/internal/wasm/store.go @@ -1,4 +1,4 @@ -package internalwasm +package wasm import ( "bytes" @@ -7,9 +7,9 @@ import ( "reflect" "sync" + "github.com/tetratelabs/wazero/api" "github.com/tetratelabs/wazero/internal/ieee754" "github.com/tetratelabs/wazero/internal/leb128" - publicwasm "github.com/tetratelabs/wazero/wasm" ) type ( @@ -372,7 +372,7 @@ func (s *Store) addModule(m *ModuleInstance) { } // Module implements wazero.Runtime Module -func (s *Store) Module(moduleName string) publicwasm.Module { +func (s *Store) Module(moduleName string) api.Module { if m := s.module(moduleName); m != nil { return m.Ctx } else { @@ -516,9 +516,9 @@ func executeConstExpression(globals []*GlobalInstance, expr *ConstantExpression) case ValueTypeI64: v = int64(g.Val) case ValueTypeF32: - v = publicwasm.DecodeF32(g.Val) + v = api.DecodeF32(g.Val) case ValueTypeF64: - v = publicwasm.DecodeF64(g.Val) + v = api.DecodeF64(g.Val) } } return diff --git a/internal/wasm/store_test.go b/internal/wasm/store_test.go index b0eaf01c..01644c5f 100644 --- a/internal/wasm/store_test.go +++ b/internal/wasm/store_test.go @@ -1,4 +1,4 @@ -package internalwasm +package wasm import ( "context" @@ -11,8 +11,8 @@ import ( "github.com/stretchr/testify/require" + "github.com/tetratelabs/wazero/api" "github.com/tetratelabs/wazero/internal/testing/hammer" - "github.com/tetratelabs/wazero/wasm" ) func TestModuleInstance_Memory(t *testing.T) { @@ -90,7 +90,7 @@ func TestModuleInstance_Memory(t *testing.T) { func TestStore_Instantiate(t *testing.T) { s := newStore() - m, err := NewHostModule("", map[string]interface{}{"fn": func(wasm.Module) {}}) + m, err := NewHostModule("", map[string]interface{}{"fn": func(api.Module) {}}) require.NoError(t, err) type key string @@ -120,7 +120,7 @@ func TestStore_CloseModule(t *testing.T) { { name: "Module imports HostModule", initializer: func(t *testing.T, s *Store) { - m, err := NewHostModule(importedModuleName, map[string]interface{}{"fn": func(wasm.Module) {}}) + m, err := NewHostModule(importedModuleName, map[string]interface{}{"fn": func(api.Module) {}}) require.NoError(t, err) _, err = s.Instantiate(context.Background(), m, importedModuleName, nil) require.NoError(t, err) @@ -177,7 +177,7 @@ func TestStore_CloseModule(t *testing.T) { func TestStore_hammer(t *testing.T) { const importedModuleName = "imported" - m, err := NewHostModule(importedModuleName, map[string]interface{}{"fn": func(wasm.Module) {}}) + m, err := NewHostModule(importedModuleName, map[string]interface{}{"fn": func(api.Module) {}}) require.NoError(t, err) s := newStore() @@ -227,7 +227,7 @@ func TestStore_Instantiate_Errors(t *testing.T) { const importedModuleName = "imported" const importingModuleName = "test" - m, err := NewHostModule(importedModuleName, map[string]interface{}{"fn": func(wasm.Module) {}}) + m, err := NewHostModule(importedModuleName, map[string]interface{}{"fn": func(api.Module) {}}) require.NoError(t, err) t.Run("Fails if module name already in use", func(t *testing.T) { @@ -312,7 +312,7 @@ func TestStore_Instantiate_Errors(t *testing.T) { } func TestStore_ExportImportedHostFunction(t *testing.T) { - m, err := NewHostModule("host", map[string]interface{}{"host_fn": func(wasm.Module) {}}) + m, err := NewHostModule("host", map[string]interface{}{"host_fn": func(api.Module) {}}) require.NoError(t, err) s := newStore() @@ -350,7 +350,7 @@ func TestFunctionInstance_Call(t *testing.T) { // Add the host module functionName := "fn" m, err := NewHostModule("host", - map[string]interface{}{functionName: func(wasm.Module) {}}, + map[string]interface{}{functionName: func(api.Module) {}}, ) require.NoError(t, err) @@ -424,7 +424,7 @@ func newStore() *Store { return NewStore(&mockEngine{shouldCompileFail: false, callFailIndex: -1}, Features20191205) } -// NewModuleEngine implements the same method as documented on internalwasm.Engine. +// NewModuleEngine implements the same method as documented on wasm.Engine. func (e *mockEngine) NewModuleEngine(_ string, _, _ []*FunctionInstance, _ *TableInstance, _ map[Index]Index) (ModuleEngine, error) { if e.shouldCompileFail { return nil, fmt.Errorf("some compilation error") @@ -432,12 +432,12 @@ func (e *mockEngine) NewModuleEngine(_ string, _, _ []*FunctionInstance, _ *Tabl return &mockModuleEngine{callFailIndex: e.callFailIndex}, nil } -// Name implements the same method as documented on internalwasm.ModuleEngine. +// Name implements the same method as documented on wasm.ModuleEngine. func (e *mockModuleEngine) Name() string { return e.name } -// Call implements the same method as documented on internalwasm.ModuleEngine. +// Call implements the same method as documented on wasm.ModuleEngine. func (e *mockModuleEngine) Call(ctx *ModuleContext, f *FunctionInstance, _ ...uint64) (results []uint64, err error) { if e.callFailIndex >= 0 && f.Index == Index(e.callFailIndex) { err = errors.New("call failed") @@ -447,8 +447,8 @@ func (e *mockModuleEngine) Call(ctx *ModuleContext, f *FunctionInstance, _ ...ui return } -// CloseWithExitCode implements the same method as documented on internalwasm.ModuleEngine. -func (me *mockModuleEngine) CloseWithExitCode(exitCode uint32) (bool, error) { +// CloseWithExitCode implements the same method as documented on wasm.ModuleEngine. +func (e *mockModuleEngine) CloseWithExitCode(exitCode uint32) (bool, error) { return true, nil } @@ -561,11 +561,11 @@ func TestExecuteConstExpression(t *testing.T) { case ValueTypeF32: actual, ok := val.(float32) require.True(t, ok) - require.Equal(t, wasm.DecodeF32(tc.val), actual) + require.Equal(t, api.DecodeF32(tc.val), actual) case ValueTypeF64: actual, ok := val.(float64) require.True(t, ok) - require.Equal(t, wasm.DecodeF64(tc.val), actual) + require.Equal(t, api.DecodeF64(tc.val), actual) } }) } diff --git a/internal/wasm/sys.go b/internal/wasm/sys.go index 62637b1c..5fd7b237 100644 --- a/internal/wasm/sys.go +++ b/internal/wasm/sys.go @@ -1,4 +1,4 @@ -package internalwasm +package wasm import ( "errors" diff --git a/internal/wasm/sys_test.go b/internal/wasm/sys_test.go index 2d72557d..47ad2764 100644 --- a/internal/wasm/sys_test.go +++ b/internal/wasm/sys_test.go @@ -1,4 +1,4 @@ -package internalwasm +package wasm import ( "bytes" diff --git a/internal/wasm/table.go b/internal/wasm/table.go index 85170e97..fbeb42cd 100644 --- a/internal/wasm/table.go +++ b/internal/wasm/table.go @@ -1,4 +1,4 @@ -package internalwasm +package wasm import ( "bytes" diff --git a/internal/wasm/table_test.go b/internal/wasm/table_test.go index 01e9430c..b250bf2f 100644 --- a/internal/wasm/table_test.go +++ b/internal/wasm/table_test.go @@ -1,4 +1,4 @@ -package internalwasm +package wasm import ( "math" diff --git a/internal/wasm/text/decoder.go b/internal/wasm/text/decoder.go index ee56f055..59d0dce2 100644 --- a/internal/wasm/text/decoder.go +++ b/internal/wasm/text/decoder.go @@ -4,7 +4,7 @@ import ( "errors" "fmt" - wasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm" ) // parserPosition holds the positional state of a parser. Values are also useful as they allow you to do a reference @@ -38,7 +38,7 @@ const ( callbackPositionEndField ) -// moduleParser parses a single wasm.Module from WebAssembly 1.0 (20191205) Text format. +// moduleParser parses a single api.Module from WebAssembly 1.0 (20191205) Text format. // // Note: The indexNamespace of wasm.SectionIDMemory and wasm.SectionIDTable allow up-to-one item. For example, you // cannot define both one import and one module-defined memory, rather one or the other (or none). Even if these rules @@ -72,8 +72,8 @@ type moduleParser struct { // functions. typeUseParser *typeUseParser - // funcNamespace represents the function index namespace, which begins with any internalwasm.ExternTypeFunc in the - // internalwasm.SectionIDImport followed by the internalwasm.SectionIDFunction. + // funcNamespace represents the function index namespace, which begins with any wasm.ExternTypeFunc in the + // wasm.SectionIDImport followed by the wasm.SectionIDFunction. // // Non-abbreviated imported and module-defined functions can declare symbolic IDs, such as "$main", which are // resolved here (without the '$' prefix). @@ -82,8 +82,8 @@ type moduleParser struct { // funcParser parses the CodeSection for a given module-defined function. funcParser *funcParser - // memoryNamespace represents the memory index namespace, which begins with any internalwasm.ExternTypeMemory in - // the internalwasm.SectionIDImport followed by the internalwasm.SectionIDMemory. + // memoryNamespace represents the memory index namespace, which begins with any wasm.ExternTypeMemory in + // the wasm.SectionIDImport followed by the wasm.SectionIDMemory. // // Non-abbreviated imported and module-defined memories can declare symbolic IDs, such as "$mem", which are resolved // here (without the '$' prefix). @@ -100,7 +100,7 @@ type moduleParser struct { fieldCountFunc uint32 } -// DecodeModule implements internalwasm.DecodeModule for the WebAssembly 1.0 (20191205) Text Format +// DecodeModule implements wasm.DecodeModule for the WebAssembly 1.0 (20191205) Text Format // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#text-format%E2%91%A0 func DecodeModule(source []byte, enabledFeatures wasm.Features, memoryMaxPages uint32) (result *wasm.Module, err error) { // TODO: when globals are supported, err on global vars if disabled diff --git a/internal/wasm/text/decoder_test.go b/internal/wasm/text/decoder_test.go index a9ef204e..278f56cd 100644 --- a/internal/wasm/text/decoder_test.go +++ b/internal/wasm/text/decoder_test.go @@ -6,8 +6,7 @@ import ( "github.com/stretchr/testify/require" - wasi "github.com/tetratelabs/wazero/internal/wasi" - wasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm" ) func TestDecodeModule(t *testing.T) { @@ -52,7 +51,7 @@ func TestDecodeModule(t *testing.T) { i32i32i32i32_i32, }, ImportSection: []*wasm.Import{{ - Module: "wasi_snapshot_preview1", Name: wasi.FunctionFdWrite, + Module: "wasi_snapshot_preview1", Name: "fd_write", Type: wasm.ExternTypeFunc, DescFunc: 1, }}, @@ -162,7 +161,7 @@ func TestDecodeModule(t *testing.T) { expected: &wasm.Module{ TypeSection: []*wasm.FunctionType{i32i32i32i32_i32}, ImportSection: []*wasm.Import{{ - Module: "wasi_snapshot_preview1", Name: wasi.FunctionFdWrite, + Module: "wasi_snapshot_preview1", Name: "fd_write", Type: wasm.ExternTypeFunc, DescFunc: 0, }}, @@ -179,7 +178,7 @@ func TestDecodeModule(t *testing.T) { expected: &wasm.Module{ TypeSection: []*wasm.FunctionType{i32i32i32i32_i32}, ImportSection: []*wasm.Import{{ - Module: "wasi_snapshot_preview1", Name: wasi.FunctionFdWrite, + Module: "wasi_snapshot_preview1", Name: "fd_write", Type: wasm.ExternTypeFunc, DescFunc: 0, }}, @@ -228,7 +227,7 @@ func TestDecodeModule(t *testing.T) { expected: &wasm.Module{ TypeSection: []*wasm.FunctionType{i32i32i32i32_i32}, ImportSection: []*wasm.Import{{ - Module: "wasi_snapshot_preview1", Name: wasi.FunctionFdWrite, + Module: "wasi_snapshot_preview1", Name: "fd_write", Type: wasm.ExternTypeFunc, DescFunc: 0, }}, @@ -245,7 +244,7 @@ func TestDecodeModule(t *testing.T) { expected: &wasm.Module{ TypeSection: []*wasm.FunctionType{i32_v}, ImportSection: []*wasm.Import{{ - Module: "wasi_snapshot_preview1", Name: wasi.FunctionProcExit, + Module: "wasi_snapshot_preview1", Name: "proc_exit", Type: wasm.ExternTypeFunc, DescFunc: 0, }}, @@ -270,7 +269,7 @@ func TestDecodeModule(t *testing.T) { expected: &wasm.Module{ TypeSection: []*wasm.FunctionType{i32i32i32i32i32i64i64i32i32_i32}, ImportSection: []*wasm.Import{{ - Module: "wasi_snapshot_preview1", Name: wasi.FunctionPathOpen, + Module: "wasi_snapshot_preview1", Name: "path_open", Type: wasm.ExternTypeFunc, DescFunc: 0, }}, @@ -287,7 +286,7 @@ func TestDecodeModule(t *testing.T) { expected: &wasm.Module{ TypeSection: []*wasm.FunctionType{i32i32i32i32i32i64i64i32i32_i32}, ImportSection: []*wasm.Import{{ - Module: "wasi_snapshot_preview1", Name: wasi.FunctionPathOpen, + Module: "wasi_snapshot_preview1", Name: "path_open", Type: wasm.ExternTypeFunc, DescFunc: 0, }}, @@ -305,11 +304,11 @@ func TestDecodeModule(t *testing.T) { expected: &wasm.Module{ TypeSection: []*wasm.FunctionType{i32i32_i32, i32i32i32i32_i32}, ImportSection: []*wasm.Import{{ - Module: "wasi_snapshot_preview1", Name: wasi.FunctionArgsSizesGet, + Module: "wasi_snapshot_preview1", Name: "args_sizes_get", Type: wasm.ExternTypeFunc, DescFunc: 0, }, { - Module: "wasi_snapshot_preview1", Name: wasi.FunctionFdWrite, + Module: "wasi_snapshot_preview1", Name: "fd_write", Type: wasm.ExternTypeFunc, DescFunc: 1, }}, @@ -338,11 +337,11 @@ func TestDecodeModule(t *testing.T) { }, ImportSection: []*wasm.Import{ { - Module: "wasi_snapshot_preview1", Name: wasi.FunctionArgsSizesGet, + Module: "wasi_snapshot_preview1", Name: "args_sizes_get", Type: wasm.ExternTypeFunc, DescFunc: 1, }, { - Module: "wasi_snapshot_preview1", Name: wasi.FunctionFdWrite, + Module: "wasi_snapshot_preview1", Name: "fd_write", Type: wasm.ExternTypeFunc, DescFunc: 2, }, @@ -368,11 +367,11 @@ func TestDecodeModule(t *testing.T) { TypeSection: []*wasm.FunctionType{v_v, i32i32_i32, i32i32i32i32_i32}, ImportSection: []*wasm.Import{ { - Module: "wasi_snapshot_preview1", Name: wasi.FunctionArgsSizesGet, + Module: "wasi_snapshot_preview1", Name: "args_sizes_get", Type: wasm.ExternTypeFunc, DescFunc: 1, }, { - Module: "wasi_snapshot_preview1", Name: wasi.FunctionFdWrite, + Module: "wasi_snapshot_preview1", Name: "fd_write", Type: wasm.ExternTypeFunc, DescFunc: 2, }, @@ -396,11 +395,11 @@ func TestDecodeModule(t *testing.T) { TypeSection: []*wasm.FunctionType{v_v, i32i32_i32}, ImportSection: []*wasm.Import{ { - Module: "wasi_snapshot_preview1", Name: wasi.FunctionEnvironGet, + Module: "wasi_snapshot_preview1", Name: "environ_get", Type: wasm.ExternTypeFunc, DescFunc: 1, }, { - Module: "wasi_snapshot_preview1", Name: wasi.FunctionArgsSizesGet, + Module: "wasi_snapshot_preview1", Name: "args_sizes_get", Type: wasm.ExternTypeFunc, DescFunc: 1, }, @@ -425,11 +424,11 @@ func TestDecodeModule(t *testing.T) { TypeSection: []*wasm.FunctionType{v_v, i32i32_i32}, ImportSection: []*wasm.Import{ { - Module: "wasi_snapshot_preview1", Name: wasi.FunctionEnvironGet, + Module: "wasi_snapshot_preview1", Name: "environ_get", Type: wasm.ExternTypeFunc, DescFunc: 1, }, { - Module: "wasi_snapshot_preview1", Name: wasi.FunctionArgsSizesGet, + Module: "wasi_snapshot_preview1", Name: "args_sizes_get", Type: wasm.ExternTypeFunc, DescFunc: 1, }, @@ -454,11 +453,11 @@ func TestDecodeModule(t *testing.T) { TypeSection: []*wasm.FunctionType{v_v, i32i32_i32}, ImportSection: []*wasm.Import{ { - Module: "wasi_snapshot_preview1", Name: wasi.FunctionEnvironGet, + Module: "wasi_snapshot_preview1", Name: "environ_get", Type: wasm.ExternTypeFunc, DescFunc: 1, }, { - Module: "wasi_snapshot_preview1", Name: wasi.FunctionArgsSizesGet, + Module: "wasi_snapshot_preview1", Name: "args_sizes_get", Type: wasm.ExternTypeFunc, DescFunc: 1, }, @@ -545,11 +544,11 @@ func TestDecodeModule(t *testing.T) { }, ImportSection: []*wasm.Import{ { - Module: "wasi_snapshot_preview1", Name: wasi.FunctionPathOpen, + Module: "wasi_snapshot_preview1", Name: "path_open", Type: wasm.ExternTypeFunc, DescFunc: 1, }, { - Module: "wasi_snapshot_preview1", Name: wasi.FunctionFdWrite, + Module: "wasi_snapshot_preview1", Name: "fd_write", Type: wasm.ExternTypeFunc, DescFunc: 2, }, @@ -930,7 +929,7 @@ func TestDecodeModule(t *testing.T) { TypeSection: []*wasm.FunctionType{v_v, i32i32_i32}, ImportSection: []*wasm.Import{ { - Module: "wasi_snapshot_preview1", Name: wasi.FunctionArgsGet, + Module: "wasi_snapshot_preview1", Name: "args_get", Type: wasm.ExternTypeFunc, DescFunc: 1, }, @@ -957,7 +956,7 @@ func TestDecodeModule(t *testing.T) { TypeSection: []*wasm.FunctionType{v_v, i32i32_i32}, ImportSection: []*wasm.Import{ { - Module: "wasi_snapshot_preview1", Name: wasi.FunctionArgsGet, + Module: "wasi_snapshot_preview1", Name: "args_get", Type: wasm.ExternTypeFunc, DescFunc: 1, }, @@ -984,7 +983,7 @@ func TestDecodeModule(t *testing.T) { TypeSection: []*wasm.FunctionType{v_v, i32i32_i32}, ImportSection: []*wasm.Import{ { - Module: "wasi_snapshot_preview1", Name: wasi.FunctionArgsGet, + Module: "wasi_snapshot_preview1", Name: "args_get", Type: wasm.ExternTypeFunc, DescFunc: 1, }, @@ -1011,7 +1010,7 @@ func TestDecodeModule(t *testing.T) { TypeSection: []*wasm.FunctionType{v_v, i32i32_i32}, ImportSection: []*wasm.Import{ { - Module: "wasi_snapshot_preview1", Name: wasi.FunctionArgsGet, + Module: "wasi_snapshot_preview1", Name: "args_get", Type: wasm.ExternTypeFunc, DescFunc: 1, }, @@ -1038,7 +1037,7 @@ func TestDecodeModule(t *testing.T) { TypeSection: []*wasm.FunctionType{v_v, i32i32_i32}, ImportSection: []*wasm.Import{ { - Module: "wasi_snapshot_preview1", Name: wasi.FunctionArgsGet, + Module: "wasi_snapshot_preview1", Name: "args_get", Type: wasm.ExternTypeFunc, DescFunc: 1, }, diff --git a/internal/wasm/text/errors.go b/internal/wasm/text/errors.go index 24972e39..555e21c9 100644 --- a/internal/wasm/text/errors.go +++ b/internal/wasm/text/errors.go @@ -3,7 +3,7 @@ package text import ( "fmt" - wasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm" ) // FormatError allows control over the format of errors parsing the WebAssembly Text Format. diff --git a/internal/wasm/text/errors_test.go b/internal/wasm/text/errors_test.go index 87d76c2a..3dc1c025 100644 --- a/internal/wasm/text/errors_test.go +++ b/internal/wasm/text/errors_test.go @@ -6,7 +6,7 @@ import ( "github.com/stretchr/testify/require" - wasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm" ) func TestFormatError_Error(t *testing.T) { diff --git a/internal/wasm/text/func_parser.go b/internal/wasm/text/func_parser.go index 93acd113..5503a3ff 100644 --- a/internal/wasm/text/func_parser.go +++ b/internal/wasm/text/func_parser.go @@ -5,7 +5,7 @@ import ( "fmt" "github.com/tetratelabs/wazero/internal/leb128" - wasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm" ) func newFuncParser(enabledFeatures wasm.Features, typeUseParser *typeUseParser, funcNamespace *indexNamespace, onFunc onFunc) *funcParser { @@ -47,7 +47,7 @@ type funcParser struct { var end = []byte{wasm.OpcodeEnd} var codeEnd = &wasm.Code{Body: end} -// begin should be called after reaching the internalwasm.ExternTypeFuncName keyword in a module field. Parsing +// begin should be called after reaching the wasm.ExternTypeFuncName keyword in a module field. Parsing // continues until onFunc or error. // // This stage records the ID of the current function, if present, and resumes with onFunc. diff --git a/internal/wasm/text/func_parser_test.go b/internal/wasm/text/func_parser_test.go index b3234de3..007b8883 100644 --- a/internal/wasm/text/func_parser_test.go +++ b/internal/wasm/text/func_parser_test.go @@ -6,7 +6,7 @@ import ( "github.com/stretchr/testify/require" - wasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm" ) func TestFuncParser(t *testing.T) { diff --git a/internal/wasm/text/index_namespace.go b/internal/wasm/text/index_namespace.go index a4b70fd7..913dadfd 100644 --- a/internal/wasm/text/index_namespace.go +++ b/internal/wasm/text/index_namespace.go @@ -4,10 +4,10 @@ import ( "errors" "fmt" - wasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm" ) -// newIndexNamespace sectionElementCount parameter should be internalwasm.Module SectionElementCount unless testing. +// newIndexNamespace sectionElementCount parameter should be wasm.Module SectionElementCount unless testing. func newIndexNamespace(sectionElementCount func(wasm.SectionID) uint32) *indexNamespace { return &indexNamespace{sectionElementCount: sectionElementCount, idToIdx: map[string]wasm.Index{}} } @@ -111,7 +111,7 @@ func (i *indexNamespace) recordOutOfRange(section wasm.SectionID, bodyOffset uin // // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#indices%E2%91%A4 type unresolvedIndex struct { - // section is the primary index of what's targeting this index (in the wasm.Module) + // section is the primary index of what's targeting this index (in the api.Module) section wasm.SectionID // idx is slice position in the section diff --git a/internal/wasm/text/index_namespace_test.go b/internal/wasm/text/index_namespace_test.go index 21ac5e88..ec8d8925 100644 --- a/internal/wasm/text/index_namespace_test.go +++ b/internal/wasm/text/index_namespace_test.go @@ -6,7 +6,7 @@ import ( "github.com/stretchr/testify/require" - wasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm" ) func TestIndexNamespace_SetId(t *testing.T) { diff --git a/internal/wasm/text/memory_parser.go b/internal/wasm/text/memory_parser.go index 08428ae1..c4cf6f22 100644 --- a/internal/wasm/text/memory_parser.go +++ b/internal/wasm/text/memory_parser.go @@ -4,7 +4,7 @@ import ( "errors" "fmt" - wasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm" ) func newMemoryParser(memoryMaxPages uint32, memoryNamespace *indexNamespace, onMemory onMemory) *memoryParser { @@ -13,7 +13,7 @@ func newMemoryParser(memoryMaxPages uint32, memoryNamespace *indexNamespace, onM type onMemory func(min, max uint32) tokenParser -// memoryParser parses a wasm.Memory from and dispatches to onMemory. +// memoryParser parses a api.Memory from and dispatches to onMemory. // // Ex. `(module (memory 0 1024))` // starts here --^ ^ @@ -22,7 +22,7 @@ type onMemory func(min, max uint32) tokenParser // Note: memoryParser is reusable. The caller resets via begin. // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#memories%E2%91%A7 type memoryParser struct { - // memoryMaxPages is the limit of pages (not bytes) for each internalwasm.Memory. + // memoryMaxPages is the limit of pages (not bytes) for each wasm.Memory. memoryMaxPages uint32 memoryNamespace *indexNamespace @@ -36,7 +36,7 @@ type memoryParser struct { currentMax uint32 } -// begin should be called after reaching the internalwasm.ExternTypeMemoryName keyword in a module field. Parsing +// begin should be called after reaching the wasm.ExternTypeMemoryName keyword in a module field. Parsing // continues until onMemory or error. // // This stage records the ID of the current memory, if present, and resumes with beginMin. diff --git a/internal/wasm/text/memory_parser_test.go b/internal/wasm/text/memory_parser_test.go index 2bdb7d9a..6eb24e8e 100644 --- a/internal/wasm/text/memory_parser_test.go +++ b/internal/wasm/text/memory_parser_test.go @@ -5,7 +5,7 @@ import ( "github.com/stretchr/testify/require" - wasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm" ) func TestMemoryParser(t *testing.T) { diff --git a/internal/wasm/text/type_parser.go b/internal/wasm/text/type_parser.go index 32b72b86..f6c3aabc 100644 --- a/internal/wasm/text/type_parser.go +++ b/internal/wasm/text/type_parser.go @@ -5,7 +5,7 @@ import ( "fmt" "github.com/tetratelabs/wazero/internal/leb128" - wasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm" ) func newTypeParser(typeNamespace *indexNamespace, onType onType) *typeParser { @@ -118,7 +118,7 @@ func (p *typeParser) parseFunc(tok tokenType, tokenBytes []byte, line, col uint3 } } -// parseFuncEnd completes the internalwasm.ExternTypeFuncName field and returns end +// parseFuncEnd completes the wasm.ExternTypeFuncName field and returns end func (p *typeParser) parseFuncEnd(tok tokenType, tokenBytes []byte, _, _ uint32) (tokenParser, error) { if tok != tokenRParen { return nil, unexpectedToken(tok, tokenBytes) @@ -222,7 +222,7 @@ func (p *typeParser) parseParam(tok tokenType, tokenBytes []byte, _, _ uint32) ( } } -// parseResult parses the wasm.ValueType in the "result" field and returns onType to finish the type. +// parseResult parses the api.ValueType in the "result" field and returns onType to finish the type. func (p *typeParser) parseResult(tok tokenType, tokenBytes []byte, _, _ uint32) (tokenParser, error) { switch tok { case tokenKeyword: // Ex. i32 diff --git a/internal/wasm/text/type_parser_test.go b/internal/wasm/text/type_parser_test.go index 00dd3146..1be69f8f 100644 --- a/internal/wasm/text/type_parser_test.go +++ b/internal/wasm/text/type_parser_test.go @@ -5,7 +5,7 @@ import ( "github.com/stretchr/testify/require" - wasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm" ) var ( diff --git a/internal/wasm/text/typeuse_parser.go b/internal/wasm/text/typeuse_parser.go index ae6cb62f..8b113960 100644 --- a/internal/wasm/text/typeuse_parser.go +++ b/internal/wasm/text/typeuse_parser.go @@ -4,7 +4,7 @@ import ( "errors" "fmt" - wasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm" ) func newTypeUseParser(module *wasm.Module, typeNamespace *indexNamespace) *typeUseParser { @@ -21,7 +21,7 @@ func newTypeUseParser(module *wasm.Module, typeNamespace *indexNamespace) *typeU // that is not a "result": pos clarifies this. type onTypeUse func(typeIdx wasm.Index, paramNames wasm.NameMap, pos callbackPosition, tok tokenType, tokenBytes []byte, line, col uint32) (tokenParser, error) -// typeUseParser parses an inlined type from a field such internalwasm.ExternTypeFuncName and calls onTypeUse. +// typeUseParser parses an inlined type from a field such wasm.ExternTypeFuncName and calls onTypeUse. // // Ex. `(import "Math" "PI" (func $math.pi (result f32)))` // starts here --^ ^ @@ -63,7 +63,7 @@ type typeUseParser struct { // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#type-uses%E2%91%A0 currentTypeIndex wasm.Index - // currentTypeIndexUnresolved is set when the currentTypeIndex was not in the wasm.Module TypeSection + // currentTypeIndexUnresolved is set when the currentTypeIndex was not in the api.Module TypeSection currentTypeIndexUnresolved *lineCol // currentInlinedType is reset on begin and complete onTypeUse @@ -308,7 +308,7 @@ func (p *typeUseParser) parseParam(tok tokenType, tokenBytes []byte, _, _ uint32 } } -// parseResult parses the wasm.ValueType in the "result" field and returns onType to finish the type. +// parseResult parses the api.ValueType in the "result" field and returns onType to finish the type. func (p *typeUseParser) parseResult(tok tokenType, tokenBytes []byte, _, _ uint32) (tokenParser, error) { switch tok { case tokenKeyword: // Ex. i32 diff --git a/internal/wasm/text/typeuse_parser_test.go b/internal/wasm/text/typeuse_parser_test.go index ad7b3c77..6f235f65 100644 --- a/internal/wasm/text/typeuse_parser_test.go +++ b/internal/wasm/text/typeuse_parser_test.go @@ -8,7 +8,7 @@ import ( "github.com/stretchr/testify/require" - wasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm" ) type typeUseParserTest struct { diff --git a/internal/wazeroir/compiler.go b/internal/wazeroir/compiler.go index b82d8f65..89c3ed44 100644 --- a/internal/wazeroir/compiler.go +++ b/internal/wazeroir/compiler.go @@ -9,7 +9,7 @@ import ( "strings" "github.com/tetratelabs/wazero/internal/leb128" - wasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm" "github.com/tetratelabs/wazero/internal/wasm/buildoptions" ) diff --git a/internal/wazeroir/signature.go b/internal/wazeroir/signature.go index d46e8cd3..78307072 100644 --- a/internal/wazeroir/signature.go +++ b/internal/wazeroir/signature.go @@ -3,7 +3,7 @@ package wazeroir import ( "fmt" - wasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm" ) // signature represents how a Wasm opcode diff --git a/internal/wazeroir/wazeroir.go b/internal/wazeroir/wazeroir.go index 8b32b9cd..fcd392e1 100644 --- a/internal/wazeroir/wazeroir.go +++ b/internal/wazeroir/wazeroir.go @@ -1,4 +1,4 @@ -// A pkg to compile down the standard Wasm binary to wazero's specific IR (wazeroir). +// Package wazeroir is a pkg to compile down the standard Wasm binary to wazero's specific IR (wazeroir). // The wazeroir is inspired by microwasm format (a.k.a. LightbeamIR), previously used // in the lightbeam JIT compiler in Wasmtime, though it is not specified and only exists // in the previous codebase of wasmtime diff --git a/sys/sys.go b/sys/sys.go index 25ed00a2..f0fd231b 100644 --- a/sys/sys.go +++ b/sys/sys.go @@ -5,7 +5,7 @@ import ( "fmt" ) -// ExitError is returned to a caller of wasm.Function still running when wasm.Module CloseWithExitCode was invoked. +// ExitError is returned to a caller of api.Function still running when api.Module CloseWithExitCode was invoked. // ExitCode zero value means success, while any other value is an error. // // Here's an example of how to get the exit code: @@ -16,7 +16,7 @@ import ( // } // --snip-- // -// Note: While possible the reason of this was "proc_exit" from wasi.ModuleSnapshotPreview1, it could be from other host +// Note: While possible the reason of this was "proc_exit" from "wasi_snapshot_preview1", it could be from other host // functions, for example an AssemblyScript's abort handler, or any arbitrary caller of CloseWithExitCode. // See https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md#proc_exit // See https://www.assemblyscript.org/concepts.html#special-imports @@ -29,7 +29,7 @@ func NewExitError(moduleName string, exitCode uint32) *ExitError { return &ExitError{moduleName: moduleName, exitCode: exitCode} } -// ModuleName is the wasm.Module that was closed. +// ModuleName is the api.Module that was closed. func (e *ExitError) ModuleName() string { return e.moduleName } diff --git a/tests/bench/bench_test.go b/tests/bench/bench_test.go index 8d767356..ad9f6ae4 100644 --- a/tests/bench/bench_test.go +++ b/tests/bench/bench_test.go @@ -8,7 +8,8 @@ import ( "testing" "github.com/tetratelabs/wazero" - "github.com/tetratelabs/wazero/wasm" + "github.com/tetratelabs/wazero/api" + "github.com/tetratelabs/wazero/wasi" ) // caseWasm was compiled from TinyGo testdata/case.go @@ -30,7 +31,7 @@ func BenchmarkEngines(b *testing.B) { } } -func runAllBenches(b *testing.B, m wasm.Module) { +func runAllBenches(b *testing.B, m api.Module) { runBase64Benches(b, m) runFibBenches(b, m) runStringManipulationBenches(b, m) @@ -38,7 +39,7 @@ func runAllBenches(b *testing.B, m wasm.Module) { runRandomMatMul(b, m) } -func runBase64Benches(b *testing.B, m wasm.Module) { +func runBase64Benches(b *testing.B, m api.Module) { base64 := m.ExportedFunction("base64") for _, numPerExec := range []int{5, 100, 10000} { @@ -52,7 +53,7 @@ func runBase64Benches(b *testing.B, m wasm.Module) { } } -func runFibBenches(b *testing.B, m wasm.Module) { +func runFibBenches(b *testing.B, m api.Module) { fibonacci := m.ExportedFunction("fibonacci") for _, num := range []int{5, 10, 20, 30} { @@ -68,7 +69,7 @@ func runFibBenches(b *testing.B, m wasm.Module) { } } -func runStringManipulationBenches(b *testing.B, m wasm.Module) { +func runStringManipulationBenches(b *testing.B, m api.Module) { stringManipulation := m.ExportedFunction("string_manipulation") for _, initialSize := range []int{50, 100, 1000} { @@ -84,7 +85,7 @@ func runStringManipulationBenches(b *testing.B, m wasm.Module) { } } -func runReverseArrayBenches(b *testing.B, m wasm.Module) { +func runReverseArrayBenches(b *testing.B, m api.Module) { reverseArray := m.ExportedFunction("reverse_array") for _, arraySize := range []int{500, 1000, 10000} { @@ -100,7 +101,7 @@ func runReverseArrayBenches(b *testing.B, m wasm.Module) { } } -func runRandomMatMul(b *testing.B, m wasm.Module) { +func runRandomMatMul(b *testing.B, m api.Module) { randomMatMul := m.ExportedFunction("random_mat_mul") for _, matrixSize := range []int{5, 10, 20} { @@ -116,8 +117,8 @@ func runRandomMatMul(b *testing.B, m wasm.Module) { } } -func instantiateHostFunctionModuleWithEngine(b *testing.B, engine *wazero.RuntimeConfig) wasm.Module { - getRandomString := func(ctx wasm.Module, retBufPtr uint32, retBufSize uint32) { +func instantiateHostFunctionModuleWithEngine(b *testing.B, engine *wazero.RuntimeConfig) api.Module { + getRandomString := func(ctx api.Module, retBufPtr uint32, retBufSize uint32) { results, err := ctx.ExportedFunction("allocate_buffer").Call(ctx, 10) if err != nil { b.Fatal(err) @@ -140,12 +141,13 @@ func instantiateHostFunctionModuleWithEngine(b *testing.B, engine *wazero.Runtim // Note: host_func.go doesn't directly use WASI, but TinyGo needs to be initialized as a WASI Command. // Add WASI to satisfy import tests - _, err = r.InstantiateModule(wazero.WASISnapshotPreview1()) + _, err = wasi.InstantiateSnapshotPreview1(r) if err != nil { b.Fatal(err) } - m, err := wazero.StartWASICommandFromSource(r, caseWasm) + // InstantiateModuleFromCode runs the "_start" function which is what TinyGo compiles "main" to. + m, err := r.InstantiateModuleFromCode(caseWasm) if err != nil { b.Fatal(err) } diff --git a/tests/bench/memory_bench_test.go b/tests/bench/memory_bench_test.go index 2069eee8..8691ab5d 100644 --- a/tests/bench/memory_bench_test.go +++ b/tests/bench/memory_bench_test.go @@ -3,7 +3,7 @@ package bench import ( "testing" - wasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm" ) func BenchmarkMemory(b *testing.B) { diff --git a/tests/engine/adhoc_test.go b/tests/engine/adhoc_test.go index c622607b..56790df8 100644 --- a/tests/engine/adhoc_test.go +++ b/tests/engine/adhoc_test.go @@ -10,9 +10,9 @@ import ( "github.com/stretchr/testify/require" "github.com/tetratelabs/wazero" - wasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/api" + "github.com/tetratelabs/wazero/internal/wasm" "github.com/tetratelabs/wazero/sys" - publicwasm "github.com/tetratelabs/wazero/wasm" ) var tests = map[string]func(t *testing.T, r wazero.Runtime){ @@ -61,7 +61,7 @@ var ( ) func testHugeStack(t *testing.T, r wazero.Runtime) { - module, err := r.InstantiateModuleFromSource(hugestackWasm) + module, err := r.InstantiateModuleFromCode(hugestackWasm) require.NoError(t, err) defer module.Close() @@ -73,14 +73,14 @@ func testHugeStack(t *testing.T, r wazero.Runtime) { } func testUnreachable(t *testing.T, r wazero.Runtime) { - callUnreachable := func(nil publicwasm.Module) { + callUnreachable := func(nil api.Module) { panic("panic in host function") } _, err := r.NewModuleBuilder("host").ExportFunction("cause_unreachable", callUnreachable).Instantiate() require.NoError(t, err) - module, err := r.InstantiateModuleFromSource(unreachableWasm) + module, err := r.InstantiateModuleFromCode(unreachableWasm) require.NoError(t, err) defer module.Close() @@ -95,7 +95,7 @@ wasm backtrace: } func testRecursiveEntry(t *testing.T, r wazero.Runtime) { - hostfunc := func(mod publicwasm.Module) { + hostfunc := func(mod api.Module) { _, err := mod.ExportedFunction("called_by_host_func").Call(nil) require.NoError(t, err) } @@ -103,7 +103,7 @@ func testRecursiveEntry(t *testing.T, r wazero.Runtime) { _, err := r.NewModuleBuilder("env").ExportFunction("host_func", hostfunc).Instantiate() require.NoError(t, err) - module, err := r.InstantiateModuleFromSource(recursiveWasm) + module, err := r.InstantiateModuleFromCode(recursiveWasm) require.NoError(t, err) defer module.Close() @@ -112,10 +112,10 @@ func testRecursiveEntry(t *testing.T, r wazero.Runtime) { } // testImportedAndExportedFunc fails if the engine cannot call an "imported-and-then-exported-back" function -// Notably, this uses memory, which ensures wasm.Module is valid in both interpreter and JIT engines. +// Notably, this uses memory, which ensures api.Module is valid in both interpreter and JIT engines. func testImportedAndExportedFunc(t *testing.T, r wazero.Runtime) { var memory *wasm.MemoryInstance - storeInt := func(nil publicwasm.Module, offset uint32, val uint64) uint32 { + storeInt := func(nil api.Module, offset uint32, val uint64) uint32 { if !nil.Memory().WriteUint64Le(offset, val) { return 1 } @@ -127,7 +127,7 @@ func testImportedAndExportedFunc(t *testing.T, r wazero.Runtime) { _, err := r.NewModuleBuilder("").ExportFunction("store_int", storeInt).Instantiate() require.NoError(t, err) - module, err := r.InstantiateModuleFromSource([]byte(`(module $test + module, err := r.InstantiateModuleFromCode([]byte(`(module $test (import "" "store_int" (func $store_int (param $offset i32) (param $val i64) (result (;errno;) i32))) (memory $memory 1 1) @@ -152,7 +152,7 @@ func testHostFunctionContextParameter(t *testing.T, r wazero.Runtime) { importedName := t.Name() + "-imported" importingName := t.Name() + "-importing" - var importing publicwasm.Module + var importing api.Module fns := map[string]interface{}{ "no_context": func(p uint32) uint32 { return p + 1 @@ -161,7 +161,7 @@ func testHostFunctionContextParameter(t *testing.T, r wazero.Runtime) { require.Equal(t, configContext, ctx) return p + 1 }, - "module_context": func(module publicwasm.Module, p uint32) uint32 { + "module_context": func(module api.Module, p uint32) uint32 { require.Equal(t, importing, module) return p + 1 }, @@ -174,7 +174,7 @@ func testHostFunctionContextParameter(t *testing.T, r wazero.Runtime) { for test := range fns { t.Run(test, func(t *testing.T) { // Instantiate a module that uses Wasm code to call the host function. - importing, err = r.InstantiateModuleFromSource([]byte(fmt.Sprintf(`(module $%[1]s + importing, err = r.InstantiateModuleFromCode([]byte(fmt.Sprintf(`(module $%[1]s (import "%[2]s" "%[3]s" (func $%[3]s (param i32) (result i32))) (func $call_%[3]s (param i32) (result i32) local.get 0 call $%[3]s) (export "call->%[3]s" (func $call_%[3]s)) @@ -229,18 +229,18 @@ func testHostFunctionNumericParameter(t *testing.T, r wazero.Runtime) { }, { name: "f32", - input: publicwasm.EncodeF32(math.MaxFloat32 - 1), - expected: publicwasm.EncodeF32(math.MaxFloat32), + input: api.EncodeF32(math.MaxFloat32 - 1), + expected: api.EncodeF32(math.MaxFloat32), }, { name: "f64", - input: publicwasm.EncodeF64(math.MaxFloat64 - 1), - expected: publicwasm.EncodeF64(math.MaxFloat64), + input: api.EncodeF64(math.MaxFloat64 - 1), + expected: api.EncodeF64(math.MaxFloat64), }, } { t.Run(test.name, func(t *testing.T) { // Instantiate a module that uses Wasm code to call the host function. - importing, err := r.InstantiateModuleFromSource([]byte(fmt.Sprintf(`(module $%[1]s + importing, err := r.InstantiateModuleFromCode([]byte(fmt.Sprintf(`(module $%[1]s (import "%[2]s" "%[3]s" (func $%[3]s (param %[3]s) (result %[3]s))) (func $call_%[3]s (param %[3]s) (result %[3]s) local.get 0 call $%[3]s) (export "call->%[3]s" (func $call_%[3]s)) @@ -289,7 +289,7 @@ func testCloseInFlight(t *testing.T, r wazero.Runtime) { tc := tt t.Run(tc.name, func(t *testing.T) { - var imported, importing publicwasm.Module + var imported, importing api.Module var err error closeAndReturn := func(x uint32) uint32 { if tc.closeImporting != 0 { @@ -309,7 +309,7 @@ func testCloseInFlight(t *testing.T, r wazero.Runtime) { // Import that module. source := callReturnImportSource(imported.Name(), t.Name()+"-importing") - importing, err = r.InstantiateModuleFromSource(source) + importing, err = r.InstantiateModuleFromCode(source) require.NoError(t, err) defer importing.Close() diff --git a/tests/engine/hammer_test.go b/tests/engine/hammer_test.go index 812987d9..30c7c6d9 100644 --- a/tests/engine/hammer_test.go +++ b/tests/engine/hammer_test.go @@ -7,9 +7,9 @@ import ( "github.com/stretchr/testify/require" "github.com/tetratelabs/wazero" + "github.com/tetratelabs/wazero/api" "github.com/tetratelabs/wazero/internal/testing/hammer" "github.com/tetratelabs/wazero/sys" - "github.com/tetratelabs/wazero/wasm" ) var hammers = map[string]func(t *testing.T, r wazero.Runtime){ @@ -30,20 +30,20 @@ func TestEngineInterpreter_hammer(t *testing.T) { } func closeImportingModuleWhileInUse(t *testing.T, r wazero.Runtime) { - closeModuleWhileInUse(t, r, func(imported, importing wasm.Module) (wasm.Module, wasm.Module) { + closeModuleWhileInUse(t, r, func(imported, importing api.Module) (api.Module, api.Module) { // Close the importing module, despite calls being in-flight. require.NoError(t, importing.Close()) // Prove a module can be redefined even with in-flight calls. source := callReturnImportSource(imported.Name(), importing.Name()) - importing, err := r.InstantiateModuleFromSource(source) + importing, err := r.InstantiateModuleFromCode(source) require.NoError(t, err) return imported, importing }) } func closeImportedModuleWhileInUse(t *testing.T, r wazero.Runtime) { - closeModuleWhileInUse(t, r, func(imported, importing wasm.Module) (wasm.Module, wasm.Module) { + closeModuleWhileInUse(t, r, func(imported, importing api.Module) (api.Module, api.Module) { // Close the importing and imported module, despite calls being in-flight. require.NoError(t, importing.Close()) require.NoError(t, imported.Close()) @@ -56,14 +56,14 @@ func closeImportedModuleWhileInUse(t *testing.T, r wazero.Runtime) { // Redefine the importing module, which should link to the redefined host module. source := callReturnImportSource(imported.Name(), importing.Name()) - importing, err = r.InstantiateModuleFromSource(source) + importing, err = r.InstantiateModuleFromCode(source) require.NoError(t, err) return imported, importing }) } -func closeModuleWhileInUse(t *testing.T, r wazero.Runtime, closeFn func(imported, importing wasm.Module) (wasm.Module, wasm.Module)) { +func closeModuleWhileInUse(t *testing.T, r wazero.Runtime, closeFn func(imported, importing api.Module) (api.Module, api.Module)) { P := 8 // max count of goroutines if testing.Short() { // Adjust down if `-test.short` P = 4 @@ -85,7 +85,7 @@ func closeModuleWhileInUse(t *testing.T, r wazero.Runtime, closeFn func(imported // Import that module. source := callReturnImportSource(imported.Name(), t.Name()+"-importing") - importing, err := r.InstantiateModuleFromSource(source) + importing, err := r.InstantiateModuleFromCode(source) require.NoError(t, err) defer importing.Close() @@ -110,13 +110,13 @@ func closeModuleWhileInUse(t *testing.T, r wazero.Runtime, closeFn func(imported requireFunctionCall(t, importing.ExportedFunction("call_return_import")) } -func requireFunctionCall(t *testing.T, fn wasm.Function) { +func requireFunctionCall(t *testing.T, fn api.Function) { res, err := fn.Call(nil, 3) require.NoError(t, err) require.Equal(t, uint64(3), res[0]) } -func requireFunctionCallExits(t *testing.T, moduleName string, fn wasm.Function) { +func requireFunctionCallExits(t *testing.T, moduleName string, fn api.Function) { _, err := fn.Call(nil, 3) require.Equal(t, sys.NewExitError(moduleName, 0), err) } diff --git a/tests/post1_0/post1_0_test.go b/tests/post1_0/post1_0_test.go index ea8fc547..87ad99e4 100644 --- a/tests/post1_0/post1_0_test.go +++ b/tests/post1_0/post1_0_test.go @@ -21,7 +21,7 @@ func TestInterpreter(t *testing.T) { runOptionalFeatureTests(t, wazero.NewRuntimeConfigInterpreter) } -// runOptionalFeatureTests tests features enabled by feature flags (internalwasm.Features) as they were unfinished when +// runOptionalFeatureTests tests features enabled by feature flags (wasm.Features) as they were unfinished when // WebAssembly 1.0 (20191205) was released. // // See https://github.com/WebAssembly/proposals/blob/main/finished-proposals.md @@ -56,12 +56,12 @@ func testSignExtensionOps(t *testing.T, newRuntimeConfig func() *wazero.RuntimeC t.Run("disabled", func(t *testing.T) { // Sign-extension is disabled by default. r := wazero.NewRuntimeWithConfig(newRuntimeConfig()) - _, err := r.InstantiateModuleFromSource(signExtend) + _, err := r.InstantiateModuleFromCode(signExtend) require.Error(t, err) }) t.Run("enabled", func(t *testing.T) { r := wazero.NewRuntimeWithConfig(newRuntimeConfig().WithFeatureSignExtensionOps(true)) - module, err := r.InstantiateModuleFromSource(signExtend) + module, err := r.InstantiateModuleFromCode(signExtend) require.NoError(t, err) signExtend32from8Name, signExtend32from16Name := "i32.extend8_s", "i32.extend16_s" diff --git a/tests/spectest/spec_test.go b/tests/spectest/spec_test.go index be4844c7..bb36738b 100644 --- a/tests/spectest/spec_test.go +++ b/tests/spectest/spec_test.go @@ -13,7 +13,7 @@ import ( "github.com/stretchr/testify/require" - wasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm" "github.com/tetratelabs/wazero/internal/wasm/binary" "github.com/tetratelabs/wazero/internal/wasm/interpreter" "github.com/tetratelabs/wazero/internal/wasm/jit" @@ -148,19 +148,19 @@ func (c command) getAssertReturnArgsExps() ([]uint64, []uint64) { return args, exps } -func (v commandActionVal) toUint64() uint64 { - if strings.Contains(v.Value, "nan") { - if v.ValType == "f32" { +func (c commandActionVal) toUint64() uint64 { + if strings.Contains(c.Value, "nan") { + if c.ValType == "f32" { return uint64(math.Float32bits(float32(math.NaN()))) } return math.Float64bits(math.NaN()) } - if strings.Contains(v.ValType, "32") { - ret, _ := strconv.ParseUint(v.Value, 10, 32) + if strings.Contains(c.ValType, "32") { + ret, _ := strconv.ParseUint(c.Value, 10, 32) return ret } else { - ret, _ := strconv.ParseUint(v.Value, 10, 64) + ret, _ := strconv.ParseUint(c.Value, 10, 64) return ret } } diff --git a/vs/bench_fac_iter_test.go b/vs/bench_fac_iter_test.go index 6730f58f..52b07cbc 100644 --- a/vs/bench_fac_iter_test.go +++ b/vs/bench_fac_iter_test.go @@ -5,7 +5,6 @@ package vs import ( - "context" _ "embed" "errors" "fmt" @@ -17,7 +16,7 @@ import ( "github.com/wasmerio/wasmer-go/wasmer" "github.com/tetratelabs/wazero" - "github.com/tetratelabs/wazero/wasm" + "github.com/tetratelabs/wazero/api" ) // ensureJITFastest is overridable via ldflags. Ex. @@ -156,7 +155,6 @@ func BenchmarkFacIter_Init(b *testing.B) { }) } -var ctx = context.Background() var facIterArgumentU64 = uint64(30) var facIterArgumentI64 = int64(facIterArgumentU64) @@ -298,10 +296,10 @@ func goWasm3FacIterInvoke(b *testing.B) { env.Destroy() } -func newWazeroFacIterBench(config *wazero.RuntimeConfig) (wasm.Module, wasm.Function, error) { +func newWazeroFacIterBench(config *wazero.RuntimeConfig) (api.Module, api.Function, error) { r := wazero.NewRuntimeWithConfig(config) - m, err := r.InstantiateModuleFromSource(facWasm) + m, err := r.InstantiateModuleFromCode(facWasm) if err != nil { return nil, nil, err } diff --git a/vs/codec_test.go b/vs/codec_test.go index dd66afa5..dae83434 100644 --- a/vs/codec_test.go +++ b/vs/codec_test.go @@ -13,10 +13,10 @@ import ( "github.com/wasmerio/wasmer-go/wasmer" "github.com/tetratelabs/wazero" - wasi "github.com/tetratelabs/wazero/internal/wasi" - wasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/internal/wasm" "github.com/tetratelabs/wazero/internal/wasm/binary" "github.com/tetratelabs/wazero/internal/wasm/text" + "github.com/tetratelabs/wazero/wasi" ) // example holds the latest supported features as described in the comments of exampleText @@ -43,11 +43,11 @@ func newExample() *wasm.Module { }, ImportSection: []*wasm.Import{ { - Module: "wasi_snapshot_preview1", Name: wasi.FunctionArgsSizesGet, + Module: "wasi_snapshot_preview1", Name: "args_sizes_get", Type: wasm.ExternTypeFunc, DescFunc: 0, }, { - Module: "wasi_snapshot_preview1", Name: wasi.FunctionFdWrite, + Module: "wasi_snapshot_preview1", Name: "fd_write", Type: wasm.ExternTypeFunc, DescFunc: 2, }, @@ -108,12 +108,14 @@ func TestExampleUpToDate(t *testing.T) { r := wazero.NewRuntimeWithConfig(wazero.NewRuntimeConfig().WithFeatureSignExtensionOps(true)) // Add WASI to satisfy import tests - _, err := r.InstantiateModule(wazero.WASISnapshotPreview1()) + wm, err := wasi.InstantiateSnapshotPreview1(r) require.NoError(t, err) + defer wm.Close() // Decode and instantiate the module - module, err := r.InstantiateModuleFromSource(exampleBinary) + module, err := r.InstantiateModuleFromCode(exampleBinary) require.NoError(t, err) + defer module.Close() // Call the add function as a smoke test results, err := module.ExportedFunction("AddInt").Call(nil, 1, 2) diff --git a/wasi.go b/wasi.go deleted file mode 100644 index bd4dae0d..00000000 --- a/wasi.go +++ /dev/null @@ -1,120 +0,0 @@ -package wazero - -import ( - "fmt" - - internalwasi "github.com/tetratelabs/wazero/internal/wasi" - internalwasm "github.com/tetratelabs/wazero/internal/wasm" - "github.com/tetratelabs/wazero/wasi" - "github.com/tetratelabs/wazero/wasm" -) - -// WASISnapshotPreview1 are functions importable as the module name wasi.ModuleSnapshotPreview1 -func WASISnapshotPreview1() *Module { - _, fns := internalwasi.SnapshotPreview1Functions() - m, err := internalwasm.NewHostModule(wasi.ModuleSnapshotPreview1, fns) - if err != nil { - panic(fmt.Errorf("BUG: %w", err)) - } - return &Module{name: wasi.ModuleSnapshotPreview1, module: m} -} - -// StartWASICommandFromSource instantiates a module from the WebAssembly 1.0 (20191205) text or binary source or errs if -// invalid. Once instantiated, this starts its WASI Command function ("_start"). -// -// Ex. -// r := wazero.NewRuntime() -// wasi, _ := r.NewHostModule(wazero.WASISnapshotPreview1()) -// defer wasi.Close() -// -// module, _ := StartWASICommandFromSource(r, source) -// defer module.Close() -// -// Note: This is a convenience utility that chains Runtime.CompileModule with StartWASICommand. -// See StartWASICommandWithConfig -func StartWASICommandFromSource(r Runtime, source []byte) (wasm.Module, error) { - if decoded, err := r.CompileModule(source); err != nil { - return nil, err - } else { - return StartWASICommand(r, decoded) - } -} - -// StartWASICommand instantiates the module and starts its WASI Command function ("_start") if present. The return value -// are all exported functions in the module. This errs if the module doesn't export a memory named "memory", or there -// are any instantiation or function call errors. On success, other modules can import wasi.ModuleSnapshotPreview1. -// -// Ex. -// r := wazero.NewRuntime() -// wasi, _ := r.NewHostModule(wazero.WASISnapshotPreview1()) -// defer wasi.Close() -// -// decoded, _ := r.CompileModule(source) -// module, _ := StartWASICommand(r, decoded) -// defer module.Close() -// -// ## "memory" export -// WASI snapshot-01 requires exporting a memory named "memory", and wazero enforces this as nearly all functions use -// memory to implement multiple returns. StartWASICommand errs if there is no memory exported as "memory". -// -// ## "_start" function export -// WASI snapshot-01 requires exporting a function named "_start" for WASI command, but wazero does not enforce this. If it is defined, -// it is called directly after any module-defined start function, in the runtime context (RuntimeConfig.WithContext). -// -// ## "__indirect_function_table" function export -// WASI snapshot-01 requires exporting a table named "__indirect_function_table", but wazero does not enforce this. -// -// Note: All TinyGo Wasm are WASI commands. They initialize memory on "_start" and import "fd_write" to implement panic. -// See StartWASICommandWithConfig -// See https://github.com/WebAssembly/WASI/blob/snapshot-01/design/application-abi.md#current-unstable-abi -func StartWASICommand(r Runtime, module *Module) (wasm.Module, error) { - return startWASICommandWithSysContext(r, module, internalwasm.DefaultSysContext()) -} - -// StartWASICommandWithConfig is like StartWASICommand, except you can override configuration based on the importing -// module. For example, you can use this to define different args depending on the importing module. -// -// r := wazero.NewRuntime() -// wasi, _ := r.NewHostModule(wazero.WASISnapshotPreview1()) -// mod, _ := r.CompileModule(source) -// -// // Initialize base configuration: -// sys := wazero.NewSysConfig().WithStdout(buf) -// -// // Assign different configuration on each instantiation -// module, _ := StartWASICommandWithConfig(r, mod.WithName("rotate"), sys.WithArgs("rotate", "angle=90", "dir=cw")) -// -// Note: Config is copied during instantiation: Later changes to config do not affect the instantiated result. -// See StartWASICommand -func StartWASICommandWithConfig(r Runtime, module *Module, config *SysConfig) (mod wasm.Module, err error) { - var sys *internalwasm.SysContext - if sys, err = config.toSysContext(); err != nil { - return - } - return startWASICommandWithSysContext(r, module, sys) -} - -func startWASICommandWithSysContext(r Runtime, module *Module, sys *internalwasm.SysContext) (mod wasm.Module, err error) { - if err = internalwasi.ValidateWASICommand(module.module, module.name); err != nil { - return - } - - internal, ok := r.(*runtime) - if !ok { - err = fmt.Errorf("unsupported Runtime implementation: %s", r) - return - } - - if mod, err = internal.store.Instantiate(internal.ctx, module.module, module.name, sys); err != nil { - return - } - - start := mod.ExportedFunction(internalwasi.FunctionStart) - if start == nil { - return - } - if _, err = start.Call(mod.WithContext(internal.ctx)); err != nil { - err = fmt.Errorf("module[%s] function[%s] failed: %w", module.name, internalwasi.FunctionStart, err) - } - return -} diff --git a/wasi/errno.go b/wasi/errno.go new file mode 100644 index 00000000..8a76ba2a --- /dev/null +++ b/wasi/errno.go @@ -0,0 +1,261 @@ +package wasi + +import ( + "fmt" +) + +// Errno are the error codes returned by WASI functions. +// +// Note: This is not always an error, as ErrnoSuccess is a valid code. +// Note: Codes are defined even when not relevant to WASI for use in higher-level libraries or alignment with POSIX. +// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-errno-enumu16 +// See https://linux.die.net/man/3/errno +type Errno = uint32 // alias for parity with wasm.ValueType + +// ErrnoName returns the POSIX error code name, except ErrnoSuccess, which is not an error. Ex. Errno2big -> "E2BIG" +func ErrnoName(errno Errno) string { + if int(errno) < len(errnoToString) { + return errnoToString[errno] + } + return fmt.Sprintf("errno(%d)", errno) +} + +// Note: Below prefers POSIX symbol names over WASI ones, even if the docs are from WASI. +// See https://linux.die.net/man/3/errno +// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#variants-1 +const ( + // ErrnoSuccess No error occurred. System call completed successfully. + ErrnoSuccess Errno = iota + // Errno2big Argument list too long. + Errno2big + // ErrnoAcces Permission denied. + ErrnoAcces + // ErrnoAddrinuse Address in use. + ErrnoAddrinuse + // ErrnoAddrnotavail Address not available. + ErrnoAddrnotavail + // ErrnoAfnosupport Address family not supported. + ErrnoAfnosupport + // ErrnoAgain Resource unavailable, or operation would block. + ErrnoAgain + // ErrnoAlready Connection already in progress. + ErrnoAlready + // ErrnoBadf Bad file descriptor. + ErrnoBadf + // ErrnoBadmsg Bad message. + ErrnoBadmsg + // ErrnoBusy Device or resource busy. + ErrnoBusy + // ErrnoCanceled Operation canceled. + ErrnoCanceled + // ErrnoChild No child processes. + ErrnoChild + // ErrnoConnaborted Connection aborted. + ErrnoConnaborted + // ErrnoConnrefused Connection refused. + ErrnoConnrefused + // ErrnoConnreset Connection reset. + ErrnoConnreset + // ErrnoDeadlk Resource deadlock would occur. + ErrnoDeadlk + // ErrnoDestaddrreq Destination address required. + ErrnoDestaddrreq + // ErrnoDom Mathematics argument out of domain of function. + ErrnoDom + // ErrnoDquot Reserved. + ErrnoDquot + // ErrnoExist File exists. + ErrnoExist + // ErrnoFault Bad address. + ErrnoFault + // ErrnoFbig File too large. + ErrnoFbig + // ErrnoHostunreach Host is unreachable. + ErrnoHostunreach + // ErrnoIdrm Identifier removed. + ErrnoIdrm + // ErrnoIlseq Illegal byte sequence. + ErrnoIlseq + // ErrnoInprogress Operation in progress. + ErrnoInprogress + // ErrnoIntr Interrupted function. + ErrnoIntr + // ErrnoInval Invalid argument. + ErrnoInval + // ErrnoIo I/O error. + ErrnoIo + // ErrnoIsconn Socket is connected. + ErrnoIsconn + // ErrnoIsdir Is a directory. + ErrnoIsdir + // ErrnoLoop Too many levels of symbolic links. + ErrnoLoop + // ErrnoMfile File descriptor value too large. + ErrnoMfile + // ErrnoMlink Too many links. + ErrnoMlink + // ErrnoMsgsize Message too large. + ErrnoMsgsize + // ErrnoMultihop Reserved. + ErrnoMultihop + // ErrnoNametoolong Filename too long. + ErrnoNametoolong + // ErrnoNetdown Network is down. + ErrnoNetdown + // ErrnoNetreset Connection aborted by network. + ErrnoNetreset + // ErrnoNetunreach Network unreachable. + ErrnoNetunreach + // ErrnoNfile Too many files open in system. + ErrnoNfile + // ErrnoNobufs No buffer space available. + ErrnoNobufs + // ErrnoNodev No such device. + ErrnoNodev + // ErrnoNoent No such file or directory. + ErrnoNoent + // ErrnoNoexec Executable file format error. + ErrnoNoexec + // ErrnoNolck No locks available. + ErrnoNolck + // ErrnoNolink Reserved. + ErrnoNolink + // ErrnoNomem Not enough space. + ErrnoNomem + // ErrnoNomsg No message of the desired type. + ErrnoNomsg + // ErrnoNoprotoopt No message of the desired type. + ErrnoNoprotoopt + // ErrnoNospc No space left on device. + ErrnoNospc + // ErrnoNosys function not supported. + ErrnoNosys + // ErrnoNotconn The socket is not connected. + ErrnoNotconn + // ErrnoNotdir Not a directory or a symbolic link to a directory. + ErrnoNotdir + // ErrnoNotempty Directory not empty. + ErrnoNotempty + // ErrnoNotrecoverable State not recoverable. + ErrnoNotrecoverable + // ErrnoNotsock Not a socket. + ErrnoNotsock + // ErrnoNotsup Not supported, or operation not supported on socket. + ErrnoNotsup + // ErrnoNotty Inappropriate I/O control operation. + ErrnoNotty + // ErrnoNxio No such device or address. + ErrnoNxio + // ErrnoOverflow Value too large to be stored in data type. + ErrnoOverflow + // ErrnoOwnerdead Previous owner died. + ErrnoOwnerdead + // ErrnoPerm Operation not permitted. + ErrnoPerm + // ErrnoPipe Broken pipe. + ErrnoPipe + // ErrnoProto Protocol error. + ErrnoProto + // ErrnoProtonosupport Protocol error. + ErrnoProtonosupport + // ErrnoPrototype Protocol wrong type for socket. + ErrnoPrototype + // ErrnoRange Result too large. + ErrnoRange + // ErrnoRofs Read-only file system. + ErrnoRofs + // ErrnoSpipe Invalid seek. + ErrnoSpipe + // ErrnoSrch No such process. + ErrnoSrch + // ErrnoStale Reserved. + ErrnoStale + // ErrnoTimedout Connection timed out. + ErrnoTimedout + // ErrnoTxtbsy Text file busy. + ErrnoTxtbsy + // ErrnoXdev Cross-device link. + ErrnoXdev + // ErrnoNotcapable Extension: Capabilities insufficient. + ErrnoNotcapable +) + +var errnoToString = [...]string{ + ErrnoSuccess: "ESUCCESS", + Errno2big: "E2BIG", + ErrnoAcces: "EACCES", + ErrnoAddrinuse: "EADDRINUSE", + ErrnoAddrnotavail: "EADDRNOTAVAIL", + ErrnoAfnosupport: "EAFNOSUPPORT", + ErrnoAgain: "EAGAIN", + ErrnoAlready: "EALREADY", + ErrnoBadf: "EBADF", + ErrnoBadmsg: "EBADMSG", + ErrnoBusy: "EBUSY", + ErrnoCanceled: "ECANCELED", + ErrnoChild: "ECHILD", + ErrnoConnaborted: "ECONNABORTED", + ErrnoConnrefused: "ECONNREFUSED", + ErrnoConnreset: "ECONNRESET", + ErrnoDeadlk: "EDEADLK", + ErrnoDestaddrreq: "EDESTADDRREQ", + ErrnoDom: "EDOM", + ErrnoDquot: "EDQUOT", + ErrnoExist: "EEXIST", + ErrnoFault: "EFAULT", + ErrnoFbig: "EFBIG", + ErrnoHostunreach: "EHOSTUNREACH", + ErrnoIdrm: "EIDRM", + ErrnoIlseq: "EILSEQ", + ErrnoInprogress: "EINPROGRESS", + ErrnoIntr: "EINTR", + ErrnoInval: "EINVAL", + ErrnoIo: "EIO", + ErrnoIsconn: "EISCONN", + ErrnoIsdir: "EISDIR", + ErrnoLoop: "ELOOP", + ErrnoMfile: "EMFILE", + ErrnoMlink: "EMLINK", + ErrnoMsgsize: "EMSGSIZE", + ErrnoMultihop: "EMULTIHOP", + ErrnoNametoolong: "ENAMETOOLONG", + ErrnoNetdown: "ENETDOWN", + ErrnoNetreset: "ENETRESET", + ErrnoNetunreach: "ENETUNREACH", + ErrnoNfile: "ENFILE", + ErrnoNobufs: "ENOBUFS", + ErrnoNodev: "ENODEV", + ErrnoNoent: "ENOENT", + ErrnoNoexec: "ENOEXEC", + ErrnoNolck: "ENOLCK", + ErrnoNolink: "ENOLINK", + ErrnoNomem: "ENOMEM", + ErrnoNomsg: "ENOMSG", + ErrnoNoprotoopt: "ENOPROTOOPT", + ErrnoNospc: "ENOSPC", + ErrnoNosys: "ENOSYS", + ErrnoNotconn: "ENOTCONN", + ErrnoNotdir: "ENOTDIR", + ErrnoNotempty: "ENOTEMPTY", + ErrnoNotrecoverable: "ENOTRECOVERABLE", + ErrnoNotsock: "ENOTSOCK", + ErrnoNotsup: "ENOTSUP", + ErrnoNotty: "ENOTTY", + ErrnoNxio: "ENXIO", + ErrnoOverflow: "EOVERFLOW", + ErrnoOwnerdead: "EOWNERDEAD", + ErrnoPerm: "EPERM", + ErrnoPipe: "EPIPE", + ErrnoProto: "EPROTO", + ErrnoProtonosupport: "EPROTONOSUPPORT", + ErrnoPrototype: "EPROTOTYPE", + ErrnoRange: "ERANGE", + ErrnoRofs: "EROFS", + ErrnoSpipe: "ESPIPE", + ErrnoSrch: "ESRCH", + ErrnoStale: "ESTALE", + ErrnoTimedout: "ETIMEDOUT", + ErrnoTxtbsy: "ETXTBSY", + ErrnoXdev: "EXDEV", + ErrnoNotcapable: "ENOTCAPABLE", +} diff --git a/examples/testdata/wasi_arg.wasm b/wasi/testdata/wasi_arg.wasm similarity index 100% rename from examples/testdata/wasi_arg.wasm rename to wasi/testdata/wasi_arg.wasm diff --git a/examples/testdata/wasi_arg.wat b/wasi/testdata/wasi_arg.wat similarity index 100% rename from examples/testdata/wasi_arg.wat rename to wasi/testdata/wasi_arg.wat diff --git a/wasi/usage_test.go b/wasi/usage_test.go new file mode 100644 index 00000000..983a6917 --- /dev/null +++ b/wasi/usage_test.go @@ -0,0 +1,42 @@ +package wasi + +import ( + "bytes" + _ "embed" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/tetratelabs/wazero" +) + +// wasiArg was compiled from testdata/wasi_arg.wat +//go:embed testdata/wasi_arg.wasm +var wasiArg []byte + +func TestInstantiateModuleWithConfig(t *testing.T) { + r := wazero.NewRuntime() + + stdout := bytes.NewBuffer(nil) + + // Configure WASI to write stdout to a buffer, so that we can verify it later. + sys := wazero.NewModuleConfig().WithStdout(stdout) + wm, err := InstantiateSnapshotPreview1(r) + require.NoError(t, err) + defer wm.Close() + + code, err := r.CompileModule(wasiArg) + require.NoError(t, err) + + // Re-use the same module many times. + for _, tc := range []string{"a", "b", "c"} { + mod, err := r.InstantiateModuleWithConfig(code, sys.WithArgs(tc).WithName(tc)) + require.NoError(t, err) + + // Ensure the scoped configuration applied. As the args are null-terminated, we append zero (NUL). + require.Equal(t, append([]byte(tc), 0), stdout.Bytes()) + + stdout.Reset() + require.NoError(t, mod.Close()) + } +} diff --git a/wasi/wasi.go b/wasi/wasi.go index 9a7b376f..8d6b8833 100644 --- a/wasi/wasi.go +++ b/wasi/wasi.go @@ -1,8 +1,17 @@ -// Package wasi includes constants and interfaces used by both public and internal APIs. package wasi import ( + crand "crypto/rand" + "errors" "fmt" + "io" + "io/fs" + "path" + "time" + + "github.com/tetratelabs/wazero" + "github.com/tetratelabs/wazero/api" + "github.com/tetratelabs/wazero/internal/wasm" ) const ( @@ -11,258 +20,1525 @@ const ( ModuleSnapshotPreview1 = "wasi_snapshot_preview1" ) -// Errno are the error codes returned by WASI functions. +// InstantiateSnapshotPreview1 instantiates ModuleSnapshotPreview1, so that other modules can import them. // -// Note: This is not always an error, as ErrnoSuccess is a valid code. -// Note: Codes are defined even when not relevant to WASI for use in higher-level libraries or alignment with POSIX. -// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-errno-enumu16 -// See https://linux.die.net/man/3/errno -type Errno = uint32 // alias for parity with internalwasm.ValueType - -// ErrnoName returns the POSIX error code name, except ErrnoSuccess, which is not an error. Ex. Errno2big -> "E2BIG" -func ErrnoName(errno Errno) string { - if int(errno) < len(errnoToString) { - return errnoToString[errno] - } - return fmt.Sprintf("errno(%d)", errno) +// Ex. After you configure like this, other modules can import functions like "wasi_snapshot_preview1" "fd_write". +// wm, _ := wasi.InstantiateSnapshotPreview1(r) +// defer wm.Close() +// +// Note: All WASI functions return a single Errno result, ErrnoSuccess on success. +func InstantiateSnapshotPreview1(r wazero.Runtime) (api.Module, error) { + _, fns := snapshotPreview1Functions() + return r.NewModuleBuilder(ModuleSnapshotPreview1).ExportFunctions(fns).Instantiate() } -// Note: Below prefers POSIX symbol names over WASI ones, even if the docs are from WASI. -// See https://linux.die.net/man/3/errno -// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#variants-1 const ( - // ErrnoSuccess No error occurred. System call completed successfully. - ErrnoSuccess Errno = iota - // Errno2big Argument list too long. - Errno2big - // ErrnoAcces Permission denied. - ErrnoAcces - // ErrnoAddrinuse Address in use. - ErrnoAddrinuse - // ErrnoAddrnotavail Address not available. - ErrnoAddrnotavail - // ErrnoAfnosupport Address family not supported. - ErrnoAfnosupport - // ErrnoAgain Resource unavailable, or operation would block. - ErrnoAgain - // ErrnoAlready Connection already in progress. - ErrnoAlready - // ErrnoBadf Bad file descriptor. - ErrnoBadf - // ErrnoBadmsg Bad message. - ErrnoBadmsg - // ErrnoBusy Device or resource busy. - ErrnoBusy - // ErrnoCanceled Operation canceled. - ErrnoCanceled - // ErrnoChild No child processes. - ErrnoChild - // ErrnoConnaborted Connection aborted. - ErrnoConnaborted - // ErrnoConnrefused Connection refused. - ErrnoConnrefused - // ErrnoConnreset Connection reset. - ErrnoConnreset - // ErrnoDeadlk Resource deadlock would occur. - ErrnoDeadlk - // ErrnoDestaddrreq Destination address required. - ErrnoDestaddrreq - // ErrnoDom Mathematics argument out of domain of function. - ErrnoDom - // ErrnoDquot Reserved. - ErrnoDquot - // ErrnoExist File exists. - ErrnoExist - // ErrnoFault Bad address. - ErrnoFault - // ErrnoFbig File too large. - ErrnoFbig - // ErrnoHostunreach Host is unreachable. - ErrnoHostunreach - // ErrnoIdrm Identifier removed. - ErrnoIdrm - // ErrnoIlseq Illegal byte sequence. - ErrnoIlseq - // ErrnoInprogress Operation in progress. - ErrnoInprogress - // ErrnoIntr Interrupted function. - ErrnoIntr - // ErrnoInval Invalid argument. - ErrnoInval - // ErrnoIo I/O error. - ErrnoIo - // ErrnoIsconn Socket is connected. - ErrnoIsconn - // ErrnoIsdir Is a directory. - ErrnoIsdir - // ErrnoLoop Too many levels of symbolic links. - ErrnoLoop - // ErrnoMfile File descriptor value too large. - ErrnoMfile - // ErrnoMlink Too many links. - ErrnoMlink - // ErrnoMsgsize Message too large. - ErrnoMsgsize - // ErrnoMultihop Reserved. - ErrnoMultihop - // ErrnoNametoolong Filename too long. - ErrnoNametoolong - // ErrnoNetdown Network is down. - ErrnoNetdown - // ErrnoNetreset Connection aborted by network. - ErrnoNetreset - // ErrnoNetunreach Network unreachable. - ErrnoNetunreach - // ErrnoNfile Too many files open in system. - ErrnoNfile - // ErrnoNobufs No buffer space available. - ErrnoNobufs - // ErrnoNodev No such device. - ErrnoNodev - // ErrnoNoent No such file or directory. - ErrnoNoent - // ErrnoNoexec Executable file format error. - ErrnoNoexec - // ErrnoNolck No locks available. - ErrnoNolck - // ErrnoNolink Reserved. - ErrnoNolink - // ErrnoNomem Not enough space. - ErrnoNomem - // ErrnoNomsg No message of the desired type. - ErrnoNomsg - // ErrnoNoprotoopt No message of the desired type. - ErrnoNoprotoopt - // ErrnoNospc No space left on device. - ErrnoNospc - // ErrnoNosys ExportedFunction not supported. - ErrnoNosys - // ErrnoNotconn The socket is not connected. - ErrnoNotconn - // ErrnoNotdir Not a directory or a symbolic link to a directory. - ErrnoNotdir - // ErrnoNotempty Directory not empty. - ErrnoNotempty - // ErrnoNotrecoverable State not recoverable. - ErrnoNotrecoverable - // ErrnoNotsock Not a socket. - ErrnoNotsock - // ErrnoNotsup Not supported, or operation not supported on socket. - ErrnoNotsup - // ErrnoNotty Inappropriate I/O control operation. - ErrnoNotty - // ErrnoNxio No such device or address. - ErrnoNxio - // ErrnoOverflow Value too large to be stored in data type. - ErrnoOverflow - // ErrnoOwnerdead Previous owner died. - ErrnoOwnerdead - // ErrnoPerm Operation not permitted. - ErrnoPerm - // ErrnoPipe Broken pipe. - ErrnoPipe - // ErrnoProto Protocol error. - ErrnoProto - // ErrnoProtonosupport Protocol error. - ErrnoProtonosupport - // ErrnoPrototype Protocol wrong type for socket. - ErrnoPrototype - // ErrnoRange Result too large. - ErrnoRange - // ErrnoRofs Read-only file system. - ErrnoRofs - // ErrnoSpipe Invalid seek. - ErrnoSpipe - // ErrnoSrch No such process. - ErrnoSrch - // ErrnoStale Reserved. - ErrnoStale - // ErrnoTimedout Connection timed out. - ErrnoTimedout - // ErrnoTxtbsy Text file busy. - ErrnoTxtbsy - // ErrnoXdev Cross-device link. - ErrnoXdev - // ErrnoNotcapable Extension: Capabilities insufficient. - ErrnoNotcapable + // functionStart is the name of the nullary function a module must export if it is a WASI Command Module. + // + // Note: When this is exported functionInitialize must not be. + // See https://github.com/WebAssembly/WASI/blob/snapshot-01/design/application-abi.md#current-unstable-abi + functionStart = "_start" // nolint + + // functionInitialize is the name of the nullary function a module must export if it is a WASI Reactor Module. + // + // Note: When this is exported functionStart must not be. + // See https://github.com/WebAssembly/WASI/blob/snapshot-01/design/application-abi.md#current-unstable-abi + functionInitialize = "_initialize" // nolint + + // functionArgsGet reads command-line argument data. + // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-args_getargv-pointerpointeru8-argv_buf-pointeru8---errno + functionArgsGet = "args_get" + + // importArgsGet is the WebAssembly 1.0 (20191205) Text format import of functionArgsGet. + importArgsGet = `(import "wasi_snapshot_preview1" "args_get" + (func $wasi.args_get (param $argv i32) (param $argv_buf i32) (result (;errno;) i32)))` + + // functionArgsSizesGet returns command-line argument data sizes. + // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-args_sizes_get---errno-size-size + functionArgsSizesGet = "args_sizes_get" + + // importArgsSizesGet is the WebAssembly 1.0 (20191205) Text format import of functionArgsSizesGet. + importArgsSizesGet = `(import "wasi_snapshot_preview1" "args_sizes_get" + (func $wasi.args_sizes_get (param $result.argc i32) (param $result.argv_buf_size i32) (result (;errno;) i32)))` + + // functionEnvironGet reads environment variable data. + // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-environ_getenviron-pointerpointeru8-environ_buf-pointeru8---errno + functionEnvironGet = "environ_get" + + // importEnvironGet is the WebAssembly 1.0 (20191205) Text format import of functionEnvironGet. + importEnvironGet = `(import "wasi_snapshot_preview1" "environ_get" + (func $wasi.environ_get (param $environ i32) (param $environ_buf i32) (result (;errno;) i32)))` + + // functionEnvironSizesGet returns environment variable data sizes. + // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-environ_sizes_get---errno-size-size + functionEnvironSizesGet = "environ_sizes_get" + + // importEnvironSizesGet is the WebAssembly 1.0 (20191205) Text format import of functionEnvironSizesGet. + importEnvironSizesGet = `(import "wasi_snapshot_preview1" "environ_sizes_get" + (func $wasi.environ_sizes_get (param $result.environc i32) (param $result.environBufSize i32) (result (;errno;) i32)))` + + // functionClockResGet returns the resolution of a clock. + // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-clock_res_getid-clockid---errno-timestamp + functionClockResGet = "clock_res_get" + + // importClockResGet is the WebAssembly 1.0 (20191205) Text format import of functionClockResGet. + importClockResGet = `(import "wasi_snapshot_preview1" "clock_res_get" + (func $wasi.clock_res_get (param $id i32) (param $result.resolution i32) (result (;errno;) i32)))` + + // functionClockTimeGet returns the time value of a clock. + // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-clock_time_getid-clockid-precision-timestamp---errno-timestamp + functionClockTimeGet = "clock_time_get" + + // importClockTimeGet is the WebAssembly 1.0 (20191205) Text format import of functionClockTimeGet. + importClockTimeGet = `(import "wasi_snapshot_preview1" "clock_time_get" + (func $wasi.clock_time_get (param $id i32) (param $precision i64) (param $result.timestamp i32) (result (;errno;) i32)))` + + // functionFdAdvise provides file advisory information on a file descriptor. + // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-fd_advisefd-fd-offset-filesize-len-filesize-advice-advice---errno + functionFdAdvise = "fd_advise" + + // importFdAdvise is the WebAssembly 1.0 (20191205) Text format import of functionFdAdvise. + importFdAdvise = `(import "wasi_snapshot_preview1" "fd_advise" + (func $wasi.fd_advise (param $fd i32) (param $offset i64) (param $len i64) (param $result.advice i32) (result (;errno;) i32)))` + + // functionFdAllocate forces the allocation of space in a file. + // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-fd_allocatefd-fd-offset-filesize-len-filesize---errno + functionFdAllocate = "fd_allocate" + + // importFdAllocate is the WebAssembly 1.0 (20191205) Text format import of functionFdAllocate. + importFdAllocate = `(import "wasi_snapshot_preview1" "fd_allocate" + (func $wasi.fd_allocate (param $fd i32) (param $offset i64) (param $len i64) (result (;errno;) i32)))` + + // functionFdClose closes a file descriptor. + // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#fd_close + functionFdClose = "fd_close" + + // importFdClose is the WebAssembly 1.0 (20191205) Text format import of functionFdClose. + importFdClose = `(import "wasi_snapshot_preview1" "fd_close" + (func $wasi.fd_close (param $fd i32) (result (;errno;) i32)))` + + // functionFdDatasync synchronizes the data of a file to disk. + // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#fd_close + functionFdDatasync = "fd_datasync" + + // importFdDatasync is the WebAssembly 1.0 (20191205) Text format import of functionFdDatasync. + importFdDatasync = `(import "wasi_snapshot_preview1" "fd_datasync" + (func $wasi.fd_datasync (param $fd i32) (result (;errno;) i32)))` + + // functionFdFdstatGet gets the attributes of a file descriptor. + // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-fd_fdstat_getfd-fd---errno-fdstat + functionFdFdstatGet = "fd_fdstat_get" + + // importFdFdstatGet is the WebAssembly 1.0 (20191205) Text format import of functionFdFdstatGet. + importFdFdstatGet = `(import "wasi_snapshot_preview1" "fd_fdstat_get" + (func $wasi.fd_fdstat_get (param $fd i32) (param $result.stat i32) (result (;errno;) i32)))` //nolint + + // functionFdFdstatSetFlags adjusts the flags associated with a file descriptor. + // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-fd_fdstat_set_flagsfd-fd-flags-fdflags---errno + functionFdFdstatSetFlags = "fd_fdstat_set_flags" + + // importFdFdstatSetFlags is the WebAssembly 1.0 (20191205) Text format import of functionFdFdstatSetFlags. + importFdFdstatSetFlags = `(import "wasi_snapshot_preview1" "fd_fdstat_set_flags" + (func $wasi.fd_fdstat_set_flags (param $fd i32) (param $flags i32) (result (;errno;) i32)))` + + // functionFdFdstatSetRights adjusts the rights associated with a file descriptor. + // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-fd_fdstat_set_rightsfd-fd-fs_rights_base-rights-fs_rights_inheriting-rights---errno + functionFdFdstatSetRights = "fd_fdstat_set_rights" + + // importFdFdstatSetRights is the WebAssembly 1.0 (20191205) Text format import of functionFdFdstatSetRights. + importFdFdstatSetRights = `(import "wasi_snapshot_preview1" "fd_fdstat_set_rights" + (func $wasi.fd_fdstat_set_rights (param $fd i32) (param $fs_rights_base i64) (param $fs_rights_inheriting i64) (result (;errno;) i32)))` + + // functionFdFilestatGet returns the attributes of an open file. + // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-fd_filestat_getfd-fd---errno-filestat + functionFdFilestatGet = "fd_filestat_get" + + // importFdFilestatGet is the WebAssembly 1.0 (20191205) Text format import of functionFdFilestatGet. + importFdFilestatGet = `(import "wasi_snapshot_preview1" "fd_filestat_get" + (func $wasi.fd_filestat_get (param $fd i32) (param $result.buf i32) (result (;errno;) i32)))` + + // functionFdFilestatSetSize adjusts the size of an open file. + // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-fd_filestat_set_sizefd-fd-size-filesize---errno + functionFdFilestatSetSize = "fd_filestat_set_size" + + // importFdFilestatSetSize is the WebAssembly 1.0 (20191205) Text format import of functionFdFilestatSetSize. + importFdFilestatSetSize = `(import "wasi_snapshot_preview1" "fd_filestat_set_size" + (func $wasi.fd_filestat_set_size (param $fd i32) (param $size i64) (result (;errno;) i32)))` + + // functionFdFilestatSetTimes adjusts the times of an open file. + // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-fd_filestat_set_timesfd-fd-atim-timestamp-mtim-timestamp-fst_flags-fstflags---errno + functionFdFilestatSetTimes = "fd_filestat_set_times" + + // importFdFilestatSetTimes is the WebAssembly 1.0 (20191205) Text format import of functionFdFilestatSetTimes. + importFdFilestatSetTimes = `(import "wasi_snapshot_preview1" "fd_filestat_set_times" + (func $wasi.fd_filestat_set_times (param $fd i32) (param $atim i64) (param $mtim i64) (param $fst_flags i32) (result (;errno;) i32)))` + + // functionFdPread reads from a file descriptor, without using and updating the file descriptor's offset. + // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-fd_preadfd-fd-iovs-iovec_array-offset-filesize---errno-size + functionFdPread = "fd_pread" + + // importFdPread is the WebAssembly 1.0 (20191205) Text format import of functionFdPread. + importFdPread = `(import "wasi_snapshot_preview1" "fd_pread" + (func $wasi.fd_pread (param $fd i32) (param $iovs i32) (param $iovs_len i32) (param $offset i64) (param $result.nread i32) (result (;errno;) i32)))` + + // functionFdPrestatGet returns the prestat data of a file descriptor. + // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#fd_prestat_get + functionFdPrestatGet = "fd_prestat_get" + + // importFdPrestatGet is the WebAssembly 1.0 (20191205) Text format import of functionFdPrestatGet. + importFdPrestatGet = `(import "wasi_snapshot_preview1" "fd_prestat_get" + (func $wasi.fd_prestat_get (param $fd i32) (param $result.prestat i32) (result (;errno;) i32)))` + + // functionFdPrestatDirName returns the path of the pre-opened directory of a file descriptor. + // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#fd_prestat_dir_name + functionFdPrestatDirName = "fd_prestat_dir_name" + + // importFdPrestatDirName is the WebAssembly 1.0 (20191205) Text format import of functionFdPrestatDirName. + importFdPrestatDirName = `(import "wasi_snapshot_preview1" "fd_prestat_dir_name" + (func $wasi.fd_prestat_dir_name (param $fd i32) (param $path i32) (param $path_len i32) (result (;errno;) i32)))` + + // functionFdPwrite writes to a file descriptor, without using and updating the file descriptor's offset. + // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-fd_pwritefd-fd-iovs-ciovec_array-offset-filesize---errno-size + functionFdPwrite = "fd_pwrite" + + // importFdPwrite is the WebAssembly 1.0 (20191205) Text format import of functionFdPwrite. + importFdPwrite = `(import "wasi_snapshot_preview1" "fd_pwrite" + (func $wasi.fd_pwrite (param $fd i32) (param $iovs i32) (param $iovs_len i32) (param $offset i64) (param $result.nwritten i32) (result (;errno;) i32)))` + + // functionFdRead read bytes from a file descriptor. + // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#fd_read + functionFdRead = "fd_read" + + // importFdRead is the WebAssembly 1.0 (20191205) Text format import of functionFdRead. + importFdRead = `(import "wasi_snapshot_preview1" "fd_read" + (func $wasi.fd_read (param $fd i32) (param $iovs i32) (param $iovs_len i32) (param $result.size i32) (result (;errno;) i32)))` + + // functionFdReaddir reads directory entries from a directory. + // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-fd_readdirfd-fd-buf-pointeru8-buf_len-size-cookie-dircookie---errno-size + functionFdReaddir = "fd_readdir" + + // importFdReaddir is the WebAssembly 1.0 (20191205) Text format import of functionFdReaddir. + importFdReaddir = `(import "wasi_snapshot_preview1" "fd_readdir" + (func $wasi.fd_readdir (param $fd i32) (param $buf i32) (param $buf_len i32) (param $cookie i64) (param $result.bufused i32) (result (;errno;) i32)))` + + // functionFdRenumber atomically replaces a file descriptor by renumbering another file descriptor. + // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-fd_renumberfd-fd-to-fd---errno + functionFdRenumber = "fd_renumber" + + // importFdRenumber is the WebAssembly 1.0 (20191205) Text format import of functionFdRenumber. + importFdRenumber = `(import "wasi_snapshot_preview1" "fd_renumber" + (func $wasi.fd_renumber (param $fd i32) (param $to i32) (result (;errno;) i32)))` + + // functionFdSeek moves the offset of a file descriptor. + // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-fd_seekfd-fd-offset-filedelta-whence-whence---errno-filesize + functionFdSeek = "fd_seek" + + // importFdSeek is the WebAssembly 1.0 (20191205) Text format import of functionFdSeek. + importFdSeek = `(import "wasi_snapshot_preview1" "fd_seek" + (func $wasi.fd_seek (param $fd i32) (param $offset i64) (param $whence i32) (param $result.newoffset i32) (result (;errno;) i32)))` + + // functionFdSync synchronizes the data and metadata of a file to disk. + // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-fd_syncfd-fd---errno + functionFdSync = "fd_sync" + + // importFdSync is the WebAssembly 1.0 (20191205) Text format import of functionFdSync. + importFdSync = `(import "wasi_snapshot_preview1" "fd_sync" + (func $wasi.fd_sync (param $fd i32) (result (;errno;) i32)))` + + // functionFdTell returns the current offset of a file descriptor. + // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-fd_tellfd-fd---errno-filesize + functionFdTell = "fd_tell" + + // importFdTell is the WebAssembly 1.0 (20191205) Text format import of functionFdTell. + importFdTell = `(import "wasi_snapshot_preview1" "fd_tell" + (func $wasi.fd_tell (param $fd i32) (param $result.offset i32) (result (;errno;) i32)))` + + // functionFdWrite write bytes to a file descriptor. + // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#fd_write + functionFdWrite = "fd_write" + + // importFdWrite is the WebAssembly 1.0 (20191205) Text format import of functionFdWrite. + importFdWrite = `(import "wasi_snapshot_preview1" "fd_write" + (func $wasi.fd_write (param $fd i32) (param $iovs i32) (param $iovs_len i32) (param $result.size i32) (result (;errno;) i32)))` + + // functionPathCreateDirectory creates a directory. + // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-path_create_directoryfd-fd-path-string---errno + functionPathCreateDirectory = "path_create_directory" + + // importPathCreateDirectory is the WebAssembly 1.0 (20191205) Text format import of functionPathCreateDirectory. + importPathCreateDirectory = `(import "wasi_snapshot_preview1" "path_create_directory" + (func $wasi.path_create_directory (param $fd i32) (param $path i32) (param $path_len i32) (result (;errno;) i32)))` + + // functionPathFilestatGet returns the attributes of a file or directory. + // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-path_filestat_getfd-fd-flags-lookupflags-path-string---errno-filestat + functionPathFilestatGet = "path_filestat_get" + + // importPathFilestatGet is the WebAssembly 1.0 (20191205) Text format import of functionPathFilestatGet. + importPathFilestatGet = `(import "wasi_snapshot_preview1" "path_filestat_get" + (func $wasi.path_filestat_get (param $fd i32) (param $flags i32) (param $path i32) (param $path_len i32) (param $result.buf i32) (result (;errno;) i32)))` + + // functionPathFilestatSetTimes adjusts the timestamps of a file or directory. + // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-path_filestat_set_timesfd-fd-flags-lookupflags-path-string-atim-timestamp-mtim-timestamp-fst_flags-fstflags---errno + functionPathFilestatSetTimes = "path_filestat_set_times" + + // importPathFilestatSetTimes is the WebAssembly 1.0 (20191205) Text format import of functionPathFilestatSetTimes. + importPathFilestatSetTimes = `(import "wasi_snapshot_preview1" "path_filestat_set_times" + (func $wasi.path_filestat_set_times (param $fd i32) (param $flags i32) (param $path i32) (param $path_len i32) (param $atim i64) (param $mtim i64) (param $fst_flags i32) (result (;errno;) i32)))` + + // functionPathLink adjusts the timestamps of a file or directory. + // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#path_link + functionPathLink = "path_link" + + // importPathLink is the WebAssembly 1.0 (20191205) Text format import of functionPathLink. + importPathLink = `(import "wasi_snapshot_preview1" "path_link" + (func $wasi.path_link (param $old_fd i32) (param $old_flags i32) (param $old_path i32) (param $old_path_len i32) (param $new_fd i32) (param $new_path i32) (param $new_path_len i32) (result (;errno;) i32)))` + + // functionPathOpen opens a file or directory. + // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-path_openfd-fd-dirflags-lookupflags-path-string-oflags-oflags-fs_rights_base-rights-fs_rights_inheriting-rights-fdflags-fdflags---errno-fd + functionPathOpen = "path_open" + + // importPathOpen is the WebAssembly 1.0 (20191205) Text format import of functionPathOpen. + importPathOpen = `(import "wasi_snapshot_preview1" "path_open" + (func $wasi.path_open (param $fd i32) (param $dirflags i32) (param $path i32) (param $path_len i32) (param $oflags i32) (param $fs_rights_base i64) (param $fs_rights_inheriting i64) (param $fdflags i32) (param $result.opened_fd i32) (result (;errno;) i32)))` + + // functionPathReadlink reads the contents of a symbolic link. + // See: https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-path_readlinkfd-fd-path-string-buf-pointeru8-buf_len-size---errno-size + functionPathReadlink = "path_readlink" + + // importPathReadlink is the WebAssembly 1.0 (20191205) Text format import of functionPathReadlink. + importPathReadlink = `(import "wasi_snapshot_preview1" "path_readlink" + (func $wasi.path_readlink (param $fd i32) (param $path i32) (param $path_len i32) (param $buf i32) (param $buf_len i32) (param $result.bufused i32) (result (;errno;) i32)))` + + // functionPathRemoveDirectory removes a directory. + // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-path_remove_directoryfd-fd-path-string---errno + functionPathRemoveDirectory = "path_remove_directory" + + // importPathRemoveDirectory is the WebAssembly 1.0 (20191205) Text format import of functionPathRemoveDirectory. + importPathRemoveDirectory = `(import "wasi_snapshot_preview1" "path_remove_directory" + (func $wasi.path_remove_directory (param $fd i32) (param $path i32) (param $path_len i32) (result (;errno;) i32)))` + + // functionPathRename renames a file or directory. + // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-path_renamefd-fd-old_path-string-new_fd-fd-new_path-string---errno + functionPathRename = "path_rename" + + // importPathRename is the WebAssembly 1.0 (20191205) Text format import of functionPathRename. + importPathRename = `(import "wasi_snapshot_preview1" "path_rename" + (func $wasi.path_rename (param $fd i32) (param $old_path i32) (param $old_path_len i32) (param $new_fd i32) (param $new_path i32) (param $new_path_len i32) (result (;errno;) i32)))` + + // functionPathSymlink creates a symbolic link. + // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#path_symlink + functionPathSymlink = "path_symlink" + + // importPathSymlink is the WebAssembly 1.0 (20191205) Text format import of functionPathSymlink. + importPathSymlink = `(import "wasi_snapshot_preview1" "path_symlink" + (func $wasi.path_symlink (param $old_path i32) (param $old_path_len i32) (param $fd i32) (param $new_path i32) (param $new_path_len i32) (result (;errno;) i32)))` + + // functionPathUnlinkFile unlinks a file. + // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-path_unlink_filefd-fd-path-string---errno + functionPathUnlinkFile = "path_unlink_file" + + // importPathUnlinkFile is the WebAssembly 1.0 (20191205) Text format import of functionPathUnlinkFile. + importPathUnlinkFile = `(import "wasi_snapshot_preview1" "path_unlink_file" + (func $wasi.path_unlink_file (param $fd i32) (param $path i32) (param $path_len i32) (result (;errno;) i32)))` + + // functionPollOneoff unlinks a file. + // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-poll_oneoffin-constpointersubscription-out-pointerevent-nsubscriptions-size---errno-size + functionPollOneoff = "poll_oneoff" + + // importPollOneoff is the WebAssembly 1.0 (20191205) Text format import of functionPollOneoff. + importPollOneoff = `(import "wasi_snapshot_preview1" "poll_oneoff" + (func $wasi.poll_oneoff (param $in i32) (param $out i32) (param $nsubscriptions i32) (param $result.nevents i32) (result (;errno;) i32)))` + + // functionProcExit terminates the execution of the module with an exit code. + // See https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md#proc_exit + functionProcExit = "proc_exit" + + // importProcExit is the WebAssembly 1.0 (20191205) Text format import of functionProcExit. + // + // See importProcExit + // See snapshotPreview1.ProcExit + // See functionProcExit + // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#proc_exit + importProcExit = `(import "wasi_snapshot_preview1" "proc_exit" + (func $wasi.proc_exit (param $rval i32)))` + + // functionProcRaise sends a signal to the process of the calling thread. + // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-proc_raisesig-signal---errno + functionProcRaise = "proc_raise" + + // importProcRaise is the WebAssembly 1.0 (20191205) Text format import of functionProcRaise. + importProcRaise = `(import "wasi_snapshot_preview1" "proc_raise" + (func $wasi.proc_raise (param $sig i32) (result (;errno;) i32)))` + + // functionSchedYield temporarily yields execution of the calling thread. + // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-sched_yield---errno + functionSchedYield = "sched_yield" + + // importSchedYield is the WebAssembly 1.0 (20191205) Text format import of functionSchedYield. + importSchedYield = `(import "wasi_snapshot_preview1" "sched_yield" + (func $wasi.sched_yield (result (;errno;) i32)))` + + // functionRandomGet writes random data in buffer. + // See: https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-random_getbuf-pointeru8-buf_len-size---errno + functionRandomGet = "random_get" + + // importRandomGet is the WebAssembly 1.0 (20191205) Text format import of functionRandomGet. + importRandomGet = `(import "wasi_snapshot_preview1" "random_get" + (func $wasi.random_get (param $buf i32) (param $buf_len i32) (result (;errno;) i32)))` + + // functionSockRecv receives a message from a socket. + // See: https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-sock_recvfd-fd-ri_data-iovec_array-ri_flags-riflags---errno-size-roflags + functionSockRecv = "sock_recv" + + // importSockRecv is the WebAssembly 1.0 (20191205) Text format import of functionSockRecv. + importSockRecv = `(import "wasi_snapshot_preview1" "sock_recv" + (func $wasi.sock_recv (param $fd i32) (param $ri_data i32) (param $ri_data_count i32) (param $ri_flags i32) (param $result.ro_datalen i32) (param $result.ro_flags i32) (result (;errno;) i32)))` + + // functionSockSend sends a message on a socket. + // See: https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-sock_sendfd-fd-si_data-ciovec_array-si_flags-siflags---errno-size + functionSockSend = "sock_send" + + // importSockSend is the WebAssembly 1.0 (20191205) Text format import of functionSockSend. + importSockSend = `(import "wasi_snapshot_preview1" "sock_send" + (func $wasi.sock_send (param $fd i32) (param $si_data i32) (param $si_data_count i32) (param $si_flags i32) (param $result.so_datalen i32) (result (;errno;) i32)))` + + // functionSockShutdown shuts down socket send and receive channels. + // See: https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-sock_shutdownfd-fd-how-sdflags---errno + functionSockShutdown = "sock_shutdown" + + // importSockShutdown is the WebAssembly 1.0 (20191205) Text format import of functionSockShutdown. + importSockShutdown = `(import "wasi_snapshot_preview1" "sock_shutdown" + (func $wasi.sock_shutdown (param $fd i32) (param $how i32) (result (;errno;) i32)))` ) -var errnoToString = [...]string{ - ErrnoSuccess: "ESUCCESS", - Errno2big: "E2BIG", - ErrnoAcces: "EACCES", - ErrnoAddrinuse: "EADDRINUSE", - ErrnoAddrnotavail: "EADDRNOTAVAIL", - ErrnoAfnosupport: "EAFNOSUPPORT", - ErrnoAgain: "EAGAIN", - ErrnoAlready: "EALREADY", - ErrnoBadf: "EBADF", - ErrnoBadmsg: "EBADMSG", - ErrnoBusy: "EBUSY", - ErrnoCanceled: "ECANCELED", - ErrnoChild: "ECHILD", - ErrnoConnaborted: "ECONNABORTED", - ErrnoConnrefused: "ECONNREFUSED", - ErrnoConnreset: "ECONNRESET", - ErrnoDeadlk: "EDEADLK", - ErrnoDestaddrreq: "EDESTADDRREQ", - ErrnoDom: "EDOM", - ErrnoDquot: "EDQUOT", - ErrnoExist: "EEXIST", - ErrnoFault: "EFAULT", - ErrnoFbig: "EFBIG", - ErrnoHostunreach: "EHOSTUNREACH", - ErrnoIdrm: "EIDRM", - ErrnoIlseq: "EILSEQ", - ErrnoInprogress: "EINPROGRESS", - ErrnoIntr: "EINTR", - ErrnoInval: "EINVAL", - ErrnoIo: "EIO", - ErrnoIsconn: "EISCONN", - ErrnoIsdir: "EISDIR", - ErrnoLoop: "ELOOP", - ErrnoMfile: "EMFILE", - ErrnoMlink: "EMLINK", - ErrnoMsgsize: "EMSGSIZE", - ErrnoMultihop: "EMULTIHOP", - ErrnoNametoolong: "ENAMETOOLONG", - ErrnoNetdown: "ENETDOWN", - ErrnoNetreset: "ENETRESET", - ErrnoNetunreach: "ENETUNREACH", - ErrnoNfile: "ENFILE", - ErrnoNobufs: "ENOBUFS", - ErrnoNodev: "ENODEV", - ErrnoNoent: "ENOENT", - ErrnoNoexec: "ENOEXEC", - ErrnoNolck: "ENOLCK", - ErrnoNolink: "ENOLINK", - ErrnoNomem: "ENOMEM", - ErrnoNomsg: "ENOMSG", - ErrnoNoprotoopt: "ENOPROTOOPT", - ErrnoNospc: "ENOSPC", - ErrnoNosys: "ENOSYS", - ErrnoNotconn: "ENOTCONN", - ErrnoNotdir: "ENOTDIR", - ErrnoNotempty: "ENOTEMPTY", - ErrnoNotrecoverable: "ENOTRECOVERABLE", - ErrnoNotsock: "ENOTSOCK", - ErrnoNotsup: "ENOTSUP", - ErrnoNotty: "ENOTTY", - ErrnoNxio: "ENXIO", - ErrnoOverflow: "EOVERFLOW", - ErrnoOwnerdead: "EOWNERDEAD", - ErrnoPerm: "EPERM", - ErrnoPipe: "EPIPE", - ErrnoProto: "EPROTO", - ErrnoProtonosupport: "EPROTONOSUPPORT", - ErrnoPrototype: "EPROTOTYPE", - ErrnoRange: "ERANGE", - ErrnoRofs: "EROFS", - ErrnoSpipe: "ESPIPE", - ErrnoSrch: "ESRCH", - ErrnoStale: "ESTALE", - ErrnoTimedout: "ETIMEDOUT", - ErrnoTxtbsy: "ETXTBSY", - ErrnoXdev: "EXDEV", - ErrnoNotcapable: "ENOTCAPABLE", +// snapshotPreview1 includes all host functions to export for WASI version "wasi_snapshot_preview1". +// +// ## Translation notes +// ### String +// WebAssembly 1.0 (20191205) has no string type, so any string input parameter expands to two uint32 parameters: offset +// and length. +// +// ### iovec_array +// `iovec_array` is encoded as two uin32le values (i32): offset and count. +// +// ### Result +// Each result besides wasi.Errno is always an uint32 parameter. WebAssembly 1.0 (20191205) can have up to one result, +// which is already used by wasi.Errno. This forces other results to be parameters. A result parameter is a memory +// offset to write the result to. As memory offsets are uint32, each parameter representing a result is uint32. +// +// ### Errno +// The WASI specification is sometimes ambiguous resulting in some runtimes interpreting the same function ways. +// wasi.Errno mappings are not defined in WASI, yet, so these mappings are best efforts by maintainers. When in doubt +// about portability, first look at internal/wasi/RATIONALE.md and if needed an issue on +// https://github.com/WebAssembly/WASI/issues +// +// ## Memory +// In WebAssembly 1.0 (20191205), there may be up to one Memory per store, which means api.Memory is always the +// wasm.Store Memories index zero: `store.Memories[0].Buffer` +// +// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md +// See https://github.com/WebAssembly/WASI/issues/215 +// See https://wwa.w3.org/TR/2019/REC-wasm-core-1-20191205/#memory-instances%E2%91%A0. +type snapshotPreview1 interface { + // ArgsGet is the WASI function that reads command-line argument data (WithArgs). + // + // There are two parameters. Both are offsets in api.Module Memory. If either are invalid due to + // memory constraints, this returns ErrnoFault. + // + // * argv - is the offset to begin writing argument offsets in uint32 little-endian encoding. + // * ArgsSizesGet result argc * 4 bytes are written to this offset + // * argvBuf - is the offset to write the null terminated arguments to m.Memory + // * ArgsSizesGet result argv_buf_size bytes are written to this offset + // + // For example, if ArgsSizesGet wrote argc=2 and argvBufSize=5 for arguments: "a" and "bc" + // parameters argv=7 and argvBuf=1, this function writes the below to `m.Memory`: + // + // argvBufSize uint32le uint32le + // +----------------+ +--------+ +--------+ + // | | | | | | + // []byte{?, 'a', 0, 'b', 'c', 0, ?, 1, 0, 0, 0, 3, 0, 0, 0, ?} + // argvBuf --^ ^ ^ + // argv --| | + // offset that begins "a" --+ | + // offset that begins "bc" --+ + // + // Note: importArgsGet shows this signature in the WebAssembly 1.0 (20191205) Text Format. + // See ArgsSizesGet + // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#args_get + // See https://en.wikipedia.org/wiki/Null-terminated_string + ArgsGet(m api.Module, argv, argvBuf uint32) Errno + + // ArgsSizesGet is the WASI function named functionArgsSizesGet that reads command-line argument data (WithArgs) + // sizes. + // + // There are two result parameters: these are offsets in the api.Module Memory to write + // corresponding sizes in uint32 little-endian encoding. If either are invalid due to memory constraints, this + // returns ErrnoFault. + // + // * resultArgc - is the offset to write the argument count to m.Memory + // * resultArgvBufSize - is the offset to write the null-terminated argument length to m.Memory + // + // For example, if WithArgs are []string{"a","bc"} and + // parameters resultArgc=1 and resultArgvBufSize=6, this function writes the below to `m.Memory`: + // + // uint32le uint32le + // +--------+ +--------+ + // | | | | + // []byte{?, 2, 0, 0, 0, ?, 5, 0, 0, 0, ?} + // resultArgc --^ ^ + // 2 args --+ | + // resultArgvBufSize --| + // len([]byte{'a',0,'b',c',0}) --+ + // + // Note: importArgsSizesGet shows this signature in the WebAssembly 1.0 (20191205) Text Format. + // See ArgsGet + // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#args_sizes_get + // See https://en.wikipedia.org/wiki/Null-terminated_string + ArgsSizesGet(m api.Module, resultArgc, resultArgvBufSize uint32) Errno + + // EnvironGet is the WASI function named functionEnvironGet that reads environment variables. (WithEnviron) + // + // There are two parameters. Both are offsets in api.Module Memory. If either are invalid due to + // memory constraints, this returns ErrnoFault. + // + // * environ - is the offset to begin writing environment variables offsets in uint32 little-endian encoding. + // * EnvironSizesGet result environc * 4 bytes are written to this offset + // * environBuf - is the offset to write the environment variables to m.Memory + // * the format is the same as os.Environ, null terminated "key=val" entries + // * EnvironSizesGet result environBufSize bytes are written to this offset + // + // For example, if EnvironSizesGet wrote environc=2 and environBufSize=9 for environment variables: "a=b", "b=cd" + // and parameters environ=11 and environBuf=1, this function writes the below to `m.Memory`: + // + // environBufSize uint32le uint32le + // +------------------------------------+ +--------+ +--------+ + // | | | | | | + // []byte{?, 'a', '=', 'b', 0, 'b', '=', 'c', 'd', 0, ?, 1, 0, 0, 0, 5, 0, 0, 0, ?} + // environBuf --^ ^ ^ + // environ offset for "a=b" --+ | + // environ offset for "b=cd" --+ + // + // Note: importEnvironGet shows this signature in the WebAssembly 1.0 (20191205) Text Format. + // See EnvironSizesGet + // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#environ_get + // See https://en.wikipedia.org/wiki/Null-terminated_string + EnvironGet(m api.Module, environ, environBuf uint32) Errno + + // EnvironSizesGet is the WASI function named functionEnvironSizesGet that reads environment variable + // (WithEnviron) sizes. + // + // There are two result parameters: these are offsets in the wasi.Module Memory to write + // corresponding sizes in uint32 little-endian encoding. If either are invalid due to memory constraints, this + // returns ErrnoFault. + // + // * resultEnvironc - is the offset to write the environment variable count to m.Memory + // * resultEnvironBufSize - is the offset to write the null-terminated environment variable length to m.Memory + // + // For example, if WithEnviron is []string{"a=b","b=cd"} and + // parameters resultEnvironc=1 and resultEnvironBufSize=6, this function writes the below to `m.Memory`: + // + // uint32le uint32le + // +--------+ +--------+ + // | | | | + // []byte{?, 2, 0, 0, 0, ?, 9, 0, 0, 0, ?} + // resultEnvironc --^ ^ + // 2 variables --+ | + // resultEnvironBufSize --| + // len([]byte{'a','=','b',0, | + // 'b','=','c','d',0}) --+ + // + // Note: importEnvironGet shows this signature in the WebAssembly 1.0 (20191205) Text Format. + // See EnvironGet + // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#environ_sizes_get + // See https://en.wikipedia.org/wiki/Null-terminated_string + EnvironSizesGet(m api.Module, resultEnvironc, resultEnvironBufSize uint32) Errno + + // ClockResGet is the WASI function named functionClockResGet and is stubbed for GrainLang per #271 + ClockResGet(m api.Module, id uint32, resultResolution uint32) Errno + + // ClockTimeGet is the WASI function named functionClockTimeGet that returns the time value of a clock (time.Now). + // + // * id - The clock id for which to return the time. + // * precision - The maximum lag (exclusive) that the returned time value may have, compared to its actual value. + // * resultTimestamp - the offset to write the timestamp to m.Memory + // * the timestamp is epoch nanoseconds encoded as a uint64 little-endian encoding. + // + // For example, if time.Now returned exactly midnight UTC 2022-01-01 (1640995200000000000), and + // parameters resultTimestamp=1, this function writes the below to `m.Memory`: + // + // uint64le + // +------------------------------------------+ + // | | + // []byte{?, 0x0, 0x0, 0x1f, 0xa6, 0x70, 0xfc, 0xc5, 0x16, ?} + // resultTimestamp --^ + // + // Note: importClockTimeGet shows this signature in the WebAssembly 1.0 (20191205) Text Format. + // Note: This is similar to `clock_gettime` in POSIX. + // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-clock_time_getid-clockid-precision-timestamp---errno-timestamp + // See https://linux.die.net/man/3/clock_gettime + ClockTimeGet(m api.Module, id uint32, precision uint64, resultTimestamp uint32) Errno + + // FdAdvise is the WASI function named functionFdAdvise and is stubbed for GrainLang per #271 + FdAdvise(m api.Module, fd uint32, offset, len uint64, resultAdvice uint32) Errno + + // FdAllocate is the WASI function named functionFdAllocate and is stubbed for GrainLang per #271 + FdAllocate(m api.Module, fd uint32, offset, len uint64) Errno + + // FdClose is the WASI function to close a file descriptor. This returns ErrnoBadf if the fd is invalid. + // + // * fd - the file descriptor to close + // + // Note: importFdClose shows this signature in the WebAssembly 1.0 (20191205) Text Format. + // Note: This is similar to `close` in POSIX. + // See https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md#fd_close + // See https://linux.die.net/man/3/close + FdClose(m api.Module, fd uint32) Errno + + // FdDatasync is the WASI function named functionFdDatasync and is stubbed for GrainLang per #271 + FdDatasync(m api.Module, fd uint32) Errno + + // FdFdstatGet is the WASI function to return the attributes of a file descriptor. + // + // * fd - the file descriptor to get the fdstat attributes data + // * resultFdstat - the offset to write the result fdstat data + // + // The wasi.Errno returned is wasi.ErrnoSuccess except the following error conditions: + // * wasi.ErrnoBadf - if `fd` is invalid + // * wasi.ErrnoFault - if `resultFdstat` contains an invalid offset due to the memory constraint + // + // fdstat byte layout is 24-byte size, which as the following elements in order + // * fs_filetype 1 byte, to indicate the file type + // * fs_flags 2 bytes, to indicate the file descriptor flag + // * 5 pad bytes + // * fs_right_base 8 bytes, to indicate the current rights of the fd + // * fs_right_inheriting 8 bytes, to indicate the maximum rights of the fd + // + // For example, with a file corresponding with `fd` was a directory (=3) opened with `fd_read` right (=1) and no fs_flags (=0), + // parameter resultFdstat=1, this function writes the below to `m.Memory`: + // + // uint16le padding uint64le uint64le + // uint8 --+ +--+ +-----------+ +--------------------+ +--------------------+ + // | | | | | | | | | + // []byte{?, 3, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0} + // resultFdstat --^ ^-- fs_flags ^-- fs_right_base ^-- fs_right_inheriting + // | + // +-- fs_filetype + // + // Note: importFdFdstatGet shows this signature in the WebAssembly 1.0 (20191205) Text Format. + // Note: FdFdstatGet returns similar flags to `fsync(fd, F_GETFL)` in POSIX, as well as additional fields. + // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#fdstat + // See https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md#fd_fdstat_get + // See https://linux.die.net/man/3/fsync + FdFdstatGet(m api.Module, fd, resultFdstat uint32) Errno + + // FdFdstatSetFlags is the WASI function named functionFdFdstatSetFlags and is stubbed for GrainLang per #271 + FdFdstatSetFlags(m api.Module, fd uint32, flags uint32) Errno + + // FdFdstatSetRights is the WASI function named functionFdFdstatSetRights and is stubbed for GrainLang per #271 + FdFdstatSetRights(m api.Module, fd uint32, fsRightsBase, fsRightsInheriting uint64) Errno + + // FdFilestatGet is the WASI function named functionFdFilestatGet + FdFilestatGet(m api.Module, fd uint32, resultBuf uint32) Errno + + // FdFilestatSetSize is the WASI function named functionFdFilestatSetSize + FdFilestatSetSize(m api.Module, fd uint32, size uint64) Errno + + // FdFilestatSetTimes is the WASI function named functionFdFilestatSetTimes + FdFilestatSetTimes(m api.Module, fd uint32, atim, mtim uint64, fstFlags uint32) Errno + + // FdPread is the WASI function named functionFdPread + FdPread(m api.Module, fd, iovs, iovsCount uint32, offset uint64, resultNread uint32) Errno + + // FdPrestatGet is the WASI function to return the prestat data of a file descriptor. + // + // * fd - the file descriptor to get the prestat + // * resultPrestat - the offset to write the result prestat data + // + // The wasi.Errno returned is wasi.ErrnoSuccess except the following error conditions: + // * wasi.ErrnoBadf - if `fd` is invalid or the `fd` is not a pre-opened directory. + // * wasi.ErrnoFault - if `resultPrestat` is an invalid offset due to the memory constraint + // + // prestat byte layout is 8 bytes, beginning with an 8-bit tag and 3 pad bytes. The only valid tag is `prestat_dir`, + // which is tag zero. This simplifies the byte layout to 4 empty bytes followed by the uint32le encoded path length. + // + // For example, the directory name corresponding with `fd` was "/tmp" and + // parameter resultPrestat=1, this function writes the below to `m.Memory`: + // + // padding uint32le + // uint8 --+ +-----+ +--------+ + // | | | | | + // []byte{?, 0, 0, 0, 0, 4, 0, 0, 0, ?} + // resultPrestat --^ ^ + // tag --+ | + // +-- size in bytes of the string "/tmp" + // + // Note: importFdPrestatGet shows this signature in the WebAssembly 1.0 (20191205) Text Format. + // See FdPrestatDirName + // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#prestat + // See https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md#fd_prestat_get + FdPrestatGet(m api.Module, fd uint32, resultPrestat uint32) Errno + + // FdPrestatDirName is the WASI function to return the path of the pre-opened directory of a file descriptor. + // + // * fd - the file descriptor to get the path of the pre-opened directory + // * path - the offset in `m.Memory` to write the result path + // * pathLen - the count of bytes to write to `path` + // * This should match the uint32le FdPrestatGet writes to offset `resultPrestat`+4 + // + // The wasi.Errno returned is wasi.ErrnoSuccess except the following error conditions: + // * wasi.ErrnoBadf - if `fd` is invalid + // * wasi.ErrnoFault - if `path` is an invalid offset due to the memory constraint + // * wasi.ErrnoNametoolong - if `pathLen` is longer than the actual length of the result path + // + // For example, the directory name corresponding with `fd` was "/tmp" and + // parameters path=1 pathLen=4 (correct), this function will write the below to `m.Memory`: + // + // pathLen + // +--------------+ + // | | + // []byte{?, '/', 't', 'm', 'p', ?} + // path --^ + // + // Note: importFdPrestatDirName shows this signature in the WebAssembly 1.0 (20191205) Text Format. + // See FdPrestatGet + // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#fd_prestat_dir_name + FdPrestatDirName(m api.Module, fd, path, pathLen uint32) Errno + // TODO: FdPrestatDirName may have to return ErrnoNotdir if the type of the prestat data of `fd` is not a PrestatDir. + + // FdPwrite is the WASI function named functionFdPwrite + FdPwrite(m api.Module, fd, iovs, iovsCount uint32, offset uint64, resultNwritten uint32) Errno + + // FdRead is the WASI function to read from a file descriptor. + // + // * fd - an opened file descriptor to read data from + // * iovs - the offset in `m.Memory` to read offset, size pairs representing where to write file data. + // * Both offset and length are encoded as uint32le. + // * iovsCount - the count of memory offset, size pairs to read sequentially starting at iovs. + // * resultSize - the offset in `m.Memory` to write the number of bytes read + // + // The wasi.Errno returned is wasi.ErrnoSuccess except the following error conditions: + // * wasi.ErrnoBadf - if `fd` is invalid + // * wasi.ErrnoFault - if `iovs` or `resultSize` contain an invalid offset due to the memory constraint + // * wasi.ErrnoIo - if an IO related error happens during the operation + // + // For example, this function needs to first read `iovs` to determine where to write contents. If + // parameters iovs=1 iovsCount=2, this function reads two offset/length pairs from `m.Memory`: + // + // iovs[0] iovs[1] + // +---------------------+ +--------------------+ + // | uint32le uint32le| |uint32le uint32le| + // +---------+ +--------+ +--------+ +--------+ + // | | | | | | | | + // []byte{?, 18, 0, 0, 0, 4, 0, 0, 0, 23, 0, 0, 0, 2, 0, 0, 0, ?... } + // iovs --^ ^ ^ ^ + // | | | | + // offset --+ length --+ offset --+ length --+ + // + // If the contents of the `fd` parameter was "wazero" (6 bytes) and + // parameter resultSize=26, this function writes the below to `m.Memory`: + // + // iovs[0].length iovs[1].length + // +--------------+ +----+ uint32le + // | | | | +--------+ + // []byte{ 0..16, ?, 'w', 'a', 'z', 'e', ?, 'r', 'o', ?, 6, 0, 0, 0 } + // iovs[0].offset --^ ^ ^ + // iovs[1].offset --+ | + // resultSize --+ + // + // Note: importFdRead shows this signature in the WebAssembly 1.0 (20191205) Text Format. + // Note: This is similar to `readv` in POSIX. + // See FdWrite + // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#fd_read + // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#iovec + // See https://linux.die.net/man/3/readv + FdRead(m api.Module, fd, iovs, iovsCount, resultSize uint32) Errno + + // FdReaddir is the WASI function named functionFdReaddir + FdReaddir(m api.Module, fd, buf, bufLen uint32, cookie uint64, resultBufused uint32) Errno + + // FdRenumber is the WASI function named functionFdRenumber + FdRenumber(m api.Module, fd, to uint32) Errno + + // FdSeek is the WASI function to move the offset of a file descriptor. + // + // * fd: the file descriptor to move the offset of + // * offset: the signed int64, which is encoded as uint64, input argument to `whence`, which results in a new offset + // * whence: the operator that creates the new offset, given `offset` bytes + // * If io.SeekStart, new offset == `offset`. + // * If io.SeekCurrent, new offset == existing offset + `offset`. + // * If io.SeekEnd, new offset == file size of `fd` + `offset`. + // * resultNewoffset: the offset in `m.Memory` to write the new offset to, relative to start of the file + // + // The wasi.Errno returned is wasi.ErrnoSuccess except the following error conditions: + // * wasi.ErrnoBadf - if `fd` is invalid + // * wasi.ErrnoFault - if `resultNewoffset` is an invalid offset in `m.Memory` due to the memory constraint + // * wasi.ErrnoInval - if `whence` is an invalid value + // * wasi.ErrnoIo - if other error happens during the operation of the underying file system + // + // For example, if fd 3 is a file with offset 0, and + // parameters fd=3, offset=4, whence=0 (=io.SeekStart), resultNewOffset=1, + // this function writes the below to `m.Memory`: + // + // uint64le + // +--------------------+ + // | | + // []byte{?, 4, 0, 0, 0, 0, 0, 0, 0, ? } + // resultNewoffset --^ + // + // See io.Seeker + // Note: importFdSeek shows this signature in the WebAssembly 1.0 (20191205) Text Format. + // Note: This is similar to `lseek` in POSIX. + // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#fd_seek + // See https://linux.die.net/man/3/lseek + FdSeek(m api.Module, fd uint32, offset uint64, whence uint32, resultNewoffset uint32) Errno + + // FdSync is the WASI function named functionFdSync + FdSync(m api.Module, fd uint32) Errno + + // FdTell is the WASI function named functionFdTell + FdTell(m api.Module, fd, resultOffset uint32) Errno + + // FdWrite is the WASI function to write to a file descriptor. + // + // * fd - an opened file descriptor to write data to + // * iovs - the offset in `m.Memory` to read offset, size pairs representing the data to write to `fd` + // * Both offset and length are encoded as uint32le. + // * iovsCount - the count of memory offset, size pairs to read sequentially starting at iovs. + // * resultSize - the offset in `m.Memory` to write the number of bytes written + // + // The wasi.Errno returned is wasi.ErrnoSuccess except the following error conditions: + // * wasi.ErrnoBadf - if `fd` is invalid + // * wasi.ErrnoFault - if `iovs` or `resultSize` contain an invalid offset due to the memory constraint + // * wasi.ErrnoIo - if an IO related error happens during the operation + // + // For example, this function needs to first read `iovs` to determine what to write to `fd`. If + // parameters iovs=1 iovsCount=2, this function reads two offset/length pairs from `m.Memory`: + // + // iovs[0] iovs[1] + // +---------------------+ +--------------------+ + // | uint32le uint32le| |uint32le uint32le| + // +---------+ +--------+ +--------+ +--------+ + // | | | | | | | | + // []byte{?, 18, 0, 0, 0, 4, 0, 0, 0, 23, 0, 0, 0, 2, 0, 0, 0, ?... } + // iovs --^ ^ ^ ^ + // | | | | + // offset --+ length --+ offset --+ length --+ + // + // This function reads those chunks `m.Memory` into the `fd` sequentially. + // + // iovs[0].length iovs[1].length + // +--------------+ +----+ + // | | | | + // []byte{ 0..16, ?, 'w', 'a', 'z', 'e', ?, 'r', 'o', ? } + // iovs[0].offset --^ ^ + // iovs[1].offset --+ + // + // Since "wazero" was written, if parameter resultSize=26, this function writes the below to `m.Memory`: + // + // uint32le + // +--------+ + // | | + // []byte{ 0..24, ?, 6, 0, 0, 0', ? } + // resultSize --^ + // + // Note: importFdWrite shows this signature in the WebAssembly 1.0 (20191205) Text Format. + // Note: This is similar to `writev` in POSIX. + // See FdRead + // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#ciovec + // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#fd_write + // See https://linux.die.net/man/3/writev + FdWrite(m api.Module, fd, iovs, iovsCount, resultSize uint32) Errno + + // PathCreateDirectory is the WASI function named functionPathCreateDirectory + PathCreateDirectory(m api.Module, fd, path, pathLen uint32) Errno + + // PathFilestatGet is the WASI function named functionPathFilestatGet + PathFilestatGet(m api.Module, fd, flags, path, pathLen, resultBuf uint32) Errno + + // PathFilestatSetTimes is the WASI function named functionPathFilestatSetTimes + PathFilestatSetTimes(m api.Module, fd, flags, path, pathLen uint32, atim, mtime uint64, fstFlags uint32) Errno + + // PathLink is the WASI function named functionPathLink + PathLink(m api.Module, oldFd, oldFlags, oldPath, oldPathLen, newFd, newPath, newPathLen uint32) Errno + + // PathOpen is the WASI function to open a file or directory. This returns ErrnoBadf if the fd is invalid. + // + // * fd - the file descriptor of a directory that `path` is relative to + // * dirflags - flags to indicate how to resolve `path` + // * path - the offset in `m.Memory` to read the path string from + // * pathLen - the length of `path` + // * oFlags - the open flags to indicate the method by which to open the file + // * fsRightsBase - the rights of the newly created file descriptor for `path` + // * fsRightsInheriting - the rights of the file descriptors derived from the newly created file descriptor for `path` + // * fdFlags - the file descriptor flags + // * resultOpenedFd - the offset in `m.Memory` to write the newly created file descriptor to. + // * The result FD value is guaranteed to be less than 2**31 + // + // The wasi.Errno returned is wasi.ErrnoSuccess except the following error conditions: + // * wasi.ErrnoBadf - if `fd` is invalid + // * wasi.ErrnoFault - if `resultOpenedFd` contains an invalid offset due to the memory constraint + // * wasi.ErrnoNoent - if `path` does not exist. + // * wasi.ErrnoExist - if `path` exists, while `oFlags` requires that it must not. + // * wasi.ErrnoNotdir - if `path` is not a directory, while `oFlags` requires that it must be. + // * wasi.ErrnoIo - if other error happens during the operation of the underying file system. + // + // For example, this function needs to first read `path` to determine the file to open. + // If parameters `path` = 1, `pathLen` = 6, and the path is "wazero", PathOpen reads the path from `m.Memory`: + // + // pathLen + // +------------------------+ + // | | + // []byte{ ?, 'w', 'a', 'z', 'e', 'r', 'o', ?... } + // path --^ + // + // Then, if parameters resultOpenedFd = 8, and this function opened a new file descriptor 5 with the given flags, + // this function writes the blow to `m.Memory`: + // + // uint32le + // +--------+ + // | | + // []byte{ 0..6, ?, 5, 0, 0, 0, ?} + // resultOpenedFd --^ + // + // Note: importPathOpen shows this signature in the WebAssembly 1.0 (20191205) Text Format. + // Note: This is similar to `openat` in POSIX. + // Note: The returned file descriptor is not guaranteed to be the lowest-numbered file + // See https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md#path_open + // See https://linux.die.net/man/3/openat + PathOpen(m api.Module, fd, dirflags, pathPtr, pathLen, oflags uint32, fsRightsBase, + fsRightsInheriting uint64, fdflags, resultOpenedFd uint32) Errno + + // PathReadlink is the WASI function named functionPathReadlink + PathReadlink(m api.Module, fd, path, pathLen, buf, bufLen, resultBufused uint32) Errno + + // PathRemoveDirectory is the WASI function named functionPathRemoveDirectory + PathRemoveDirectory(m api.Module, fd, path, pathLen uint32) Errno + + // PathRename is the WASI function named functionPathRename + PathRename(m api.Module, fd, oldPath, oldPathLen, newFd, newPath, newPathLen uint32) Errno + + // PathSymlink is the WASI function named functionPathSymlink + PathSymlink(m api.Module, oldPath, oldPathLen, fd, newPath, newPathLen uint32) Errno + + // PathUnlinkFile is the WASI function named functionPathUnlinkFile + PathUnlinkFile(m api.Module, fd, path, pathLen uint32) Errno + + // PollOneoff is the WASI function named functionPollOneoff + PollOneoff(m api.Module, in, out, nsubscriptions, resultNevents uint32) Errno + + // ProcExit is the WASI function that terminates the execution of the module with an exit code. + // An exit code of 0 indicates successful termination. The meanings of other values are not defined by WASI. + // + // * rval - The exit code. + // + // In wazero, this calls api.Module CloseWithExitCode. + // + // Note: importProcExit shows this signature in the WebAssembly 1.0 (20191205) Text Format. + // See https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md#proc_exit + ProcExit(m api.Module, rval uint32) + + // ProcRaise is the WASI function named functionProcRaise + ProcRaise(m api.Module, sig uint32) Errno + + // SchedYield is the WASI function named functionSchedYield + SchedYield(m api.Module) Errno + + // RandomGet is the WASI function named functionRandomGet that write random data in buffer (rand.Read()). + // + // * buf - is the m.Memory offset to write random values + // * bufLen - size of random data in bytes + // + // For example, if underlying random source was seeded like `rand.NewSource(42)`, we expect `m.Memory` to contain: + // + // bufLen (5) + // +--------------------------+ + // | | + // []byte{?, 0x53, 0x8c, 0x7f, 0x96, 0xb1, ?} + // buf --^ + // + // Note: importRandomGet shows this signature in the WebAssembly 1.0 (20191205) Text Format. + // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-random_getbuf-pointeru8-bufLen-size---errno + RandomGet(m api.Module, buf, bufLen uint32) Errno + + // SockRecv is the WASI function named functionSockRecv + SockRecv(m api.Module, fd, riData, riDataCount, riFlags, resultRoDataLen, resultRoFlags uint32) Errno + + // SockSend is the WASI function named functionSockSend + SockSend(m api.Module, fd, siData, siDataCount, siFlags, resultSoDataLen uint32) Errno + + // SockShutdown is the WASI function named functionSockShutdown + SockShutdown(m api.Module, fd, how uint32) Errno +} + +var _ snapshotPreview1 = &wasiAPI{} + +type wasiAPI struct { + // timeNowUnixNano is mutable for testing + timeNowUnixNano func() uint64 + randSource func([]byte) error +} + +// snapshotPreview1Functions returns all go functions that implement snapshotPreview1. +// These should be exported in the module named "wasi_snapshot_preview1". +// See wasm.NewHostModule +func snapshotPreview1Functions() (a *wasiAPI, nameToGoFunc map[string]interface{}) { + a = newAPI() + // Note: these are ordered per spec for consistency even if the resulting map can't guarantee that. + // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#functions + nameToGoFunc = map[string]interface{}{ + functionArgsGet: a.ArgsGet, + functionArgsSizesGet: a.ArgsSizesGet, + functionEnvironGet: a.EnvironGet, + functionEnvironSizesGet: a.EnvironSizesGet, + functionClockResGet: a.ClockResGet, + functionClockTimeGet: a.ClockTimeGet, + functionFdAdvise: a.FdAdvise, + functionFdAllocate: a.FdAllocate, + functionFdClose: a.FdClose, + functionFdDatasync: a.FdDatasync, + functionFdFdstatGet: a.FdFdstatGet, + functionFdFdstatSetFlags: a.FdFdstatSetFlags, + functionFdFdstatSetRights: a.FdFdstatSetRights, + functionFdFilestatGet: a.FdFilestatGet, + functionFdFilestatSetSize: a.FdFilestatSetSize, + functionFdFilestatSetTimes: a.FdFilestatSetTimes, + functionFdPread: a.FdPread, + functionFdPrestatGet: a.FdPrestatGet, + functionFdPrestatDirName: a.FdPrestatDirName, + functionFdPwrite: a.FdPwrite, + functionFdRead: a.FdRead, + functionFdReaddir: a.FdReaddir, + functionFdRenumber: a.FdRenumber, + functionFdSeek: a.FdSeek, + functionFdSync: a.FdSync, + functionFdTell: a.FdTell, + functionFdWrite: a.FdWrite, + functionPathCreateDirectory: a.PathCreateDirectory, + functionPathFilestatGet: a.PathFilestatGet, + functionPathFilestatSetTimes: a.PathFilestatSetTimes, + functionPathLink: a.PathLink, + functionPathOpen: a.PathOpen, + functionPathReadlink: a.PathReadlink, + functionPathRemoveDirectory: a.PathRemoveDirectory, + functionPathRename: a.PathRename, + functionPathSymlink: a.PathSymlink, + functionPathUnlinkFile: a.PathUnlinkFile, + functionPollOneoff: a.PollOneoff, + functionProcExit: a.ProcExit, + functionProcRaise: a.ProcRaise, + functionSchedYield: a.SchedYield, + functionRandomGet: a.RandomGet, + functionSockRecv: a.SockRecv, + functionSockSend: a.SockSend, + functionSockShutdown: a.SockShutdown, + } + return +} + +// ArgsGet implements snapshotPreview1.ArgsGet +func (a *wasiAPI) ArgsGet(m api.Module, argv, argvBuf uint32) Errno { + sys := sysCtx(m) + return writeOffsetsAndNullTerminatedValues(m.Memory(), sys.Args(), argv, argvBuf) +} + +// ArgsSizesGet implements snapshotPreview1.ArgsSizesGet +func (a *wasiAPI) ArgsSizesGet(m api.Module, resultArgc, resultArgvBufSize uint32) Errno { + sys := sysCtx(m) + mem := m.Memory() + + if !mem.WriteUint32Le(resultArgc, uint32(len(sys.Args()))) { + return ErrnoFault + } + if !mem.WriteUint32Le(resultArgvBufSize, sys.ArgsSize()) { + return ErrnoFault + } + return ErrnoSuccess +} + +// EnvironGet implements snapshotPreview1.EnvironGet +func (a *wasiAPI) EnvironGet(m api.Module, environ uint32, environBuf uint32) Errno { + sys := sysCtx(m) + return writeOffsetsAndNullTerminatedValues(m.Memory(), sys.Environ(), environ, environBuf) +} + +// EnvironSizesGet implements snapshotPreview1.EnvironSizesGet +func (a *wasiAPI) EnvironSizesGet(m api.Module, resultEnvironc uint32, resultEnvironBufSize uint32) Errno { + sys := sysCtx(m) + mem := m.Memory() + + if !mem.WriteUint32Le(resultEnvironc, uint32(len(sys.Environ()))) { + return ErrnoFault + } + if !mem.WriteUint32Le(resultEnvironBufSize, sys.EnvironSize()) { + return ErrnoFault + } + + return ErrnoSuccess +} + +// ClockResGet implements snapshotPreview1.ClockResGet +func (a *wasiAPI) ClockResGet(m api.Module, id uint32, resultResolution uint32) Errno { + return ErrnoNosys // stubbed for GrainLang per #271 +} + +// ClockTimeGet implements snapshotPreview1.ClockTimeGet +func (a *wasiAPI) ClockTimeGet(m api.Module, id uint32, precision uint64, resultTimestamp uint32) Errno { + // TODO: id and precision are currently ignored. + if !m.Memory().WriteUint64Le(resultTimestamp, a.timeNowUnixNano()) { + return ErrnoFault + } + return ErrnoSuccess +} + +// FdAdvise implements snapshotPreview1.FdAdvise +func (a *wasiAPI) FdAdvise(m api.Module, fd uint32, offset, len uint64, resultAdvice uint32) Errno { + return ErrnoNosys // stubbed for GrainLang per #271 +} + +// FdAllocate implements snapshotPreview1.FdAllocate +func (a *wasiAPI) FdAllocate(m api.Module, fd uint32, offset, len uint64) Errno { + return ErrnoNosys // stubbed for GrainLang per #271 +} + +// FdClose implements snapshotPreview1.FdClose +func (a *wasiAPI) FdClose(m api.Module, fd uint32) Errno { + sys := sysCtx(m) + + if ok, err := sys.CloseFile(fd); err != nil { + return ErrnoIo + } else if !ok { + return ErrnoBadf + } + + return ErrnoSuccess +} + +// FdDatasync implements snapshotPreview1.FdDatasync +func (a *wasiAPI) FdDatasync(m api.Module, fd uint32) Errno { + return ErrnoNosys // stubbed for GrainLang per #271 +} + +// FdFdstatGet implements snapshotPreview1.FdFdstatGet +func (a *wasiAPI) FdFdstatGet(m api.Module, fd uint32, resultStat uint32) Errno { + sys := sysCtx(m) + + if _, ok := sys.OpenedFile(fd); !ok { + return ErrnoBadf + } + return ErrnoSuccess +} + +// FdPrestatGet implements snapshotPreview1.FdPrestatGet +func (a *wasiAPI) FdPrestatGet(m api.Module, fd uint32, resultPrestat uint32) Errno { + sys := sysCtx(m) + + entry, ok := sys.OpenedFile(fd) + if !ok { + return ErrnoBadf + } + + // Zero-value 8-bit tag, and 3-byte zero-value paddings, which is uint32le(0) in short. + if !m.Memory().WriteUint32Le(resultPrestat, uint32(0)) { + return ErrnoFault + } + // Write the length of the directory name at offset 4. + if !m.Memory().WriteUint32Le(resultPrestat+4, uint32(len(entry.Path))) { + return ErrnoFault + } + + return ErrnoSuccess +} + +// FdFdstatSetFlags implements snapshotPreview1.FdFdstatSetFlags +func (a *wasiAPI) FdFdstatSetFlags(m api.Module, fd uint32, flags uint32) Errno { + return ErrnoNosys // stubbed for GrainLang per #271 +} + +// FdFdstatSetRights implements snapshotPreview1.FdFdstatSetRights +// Note: This will never be implemented per https://github.com/WebAssembly/WASI/issues/469#issuecomment-1045251844 +func (a *wasiAPI) FdFdstatSetRights(m api.Module, fd uint32, fsRightsBase, fsRightsInheriting uint64) Errno { + return ErrnoNosys // stubbed for GrainLang per #271 +} + +// FdFilestatGet implements snapshotPreview1.FdFilestatGet +func (a *wasiAPI) FdFilestatGet(m api.Module, fd uint32, resultBuf uint32) Errno { + return ErrnoNosys // stubbed for GrainLang per #271 +} + +// FdFilestatSetSize implements snapshotPreview1.FdFilestatSetSize +func (a *wasiAPI) FdFilestatSetSize(m api.Module, fd uint32, size uint64) Errno { + return ErrnoNosys // stubbed for GrainLang per #271 +} + +// FdFilestatSetTimes implements snapshotPreview1.FdFilestatSetTimes +func (a *wasiAPI) FdFilestatSetTimes(m api.Module, fd uint32, atim, mtim uint64, fstFlags uint32) Errno { + return ErrnoNosys // stubbed for GrainLang per #271 +} + +// FdPread implements snapshotPreview1.FdPread +func (a *wasiAPI) FdPread(m api.Module, fd, iovs, iovsCount uint32, offset uint64, resultNread uint32) Errno { + return ErrnoNosys // stubbed for GrainLang per #271 +} + +// FdPrestatDirName implements snapshotPreview1.FdPrestatDirName +func (a *wasiAPI) FdPrestatDirName(m api.Module, fd uint32, pathPtr uint32, pathLen uint32) Errno { + sys := sysCtx(m) + + f, ok := sys.OpenedFile(fd) + if !ok { + return ErrnoBadf + } + + // Some runtimes may have another semantics. See internal/wasi/RATIONALE.md + if uint32(len(f.Path)) < pathLen { + return ErrnoNametoolong + } + + // TODO: FdPrestatDirName may have to return ErrnoNotdir if the type of the prestat data of `fd` is not a PrestatDir. + if !m.Memory().Write(pathPtr, []byte(f.Path)[:pathLen]) { + return ErrnoFault + } + return ErrnoSuccess +} + +// FdPwrite implements snapshotPreview1.FdPwrite +func (a *wasiAPI) FdPwrite(m api.Module, fd, iovs, iovsCount uint32, offset uint64, resultNwritten uint32) Errno { + return ErrnoNosys // stubbed for GrainLang per #271 +} + +// FdRead implements snapshotPreview1.FdRead +func (a *wasiAPI) FdRead(m api.Module, fd, iovs, iovsCount, resultSize uint32) Errno { + sys := sysCtx(m) + + var reader io.Reader + + if fd == fdStdin { + reader = sys.Stdin() + } else if f, ok := sys.OpenedFile(fd); !ok || f.File == nil { + return ErrnoBadf + } else { + reader = f.File + } + + var nread uint32 + for i := uint32(0); i < iovsCount; i++ { + iovPtr := iovs + i*8 + offset, ok := m.Memory().ReadUint32Le(iovPtr) + if !ok { + return ErrnoFault + } + l, ok := m.Memory().ReadUint32Le(iovPtr + 4) + if !ok { + return ErrnoFault + } + b, ok := m.Memory().Read(offset, l) + if !ok { + return ErrnoFault + } + n, err := reader.Read(b) + nread += uint32(n) + if errors.Is(err, io.EOF) { + break + } else if err != nil { + return ErrnoIo + } + } + if !m.Memory().WriteUint32Le(resultSize, nread) { + return ErrnoFault + } + return ErrnoSuccess +} + +// FdReaddir implements snapshotPreview1.FdReaddir +func (a *wasiAPI) FdReaddir(m api.Module, fd, buf, bufLen uint32, cookie uint64, resultBufused uint32) Errno { + return ErrnoNosys // stubbed for GrainLang per #271 +} + +// FdRenumber implements snapshotPreview1.FdRenumber +func (a *wasiAPI) FdRenumber(m api.Module, fd, to uint32) Errno { + return ErrnoNosys // stubbed for GrainLang per #271 +} + +// FdSeek implements snapshotPreview1.FdSeek +func (a *wasiAPI) FdSeek(m api.Module, fd uint32, offset uint64, whence uint32, resultNewoffset uint32) Errno { + sys := sysCtx(m) + + var seeker io.Seeker + // Check to see if the file descriptor is available + if f, ok := sys.OpenedFile(fd); !ok || f.File == nil { + return ErrnoBadf + // fs.FS doesn't declare io.Seeker, but implementations such as os.File implement it. + } else if seeker, ok = f.File.(io.Seeker); !ok { + return ErrnoBadf + } + + if whence > io.SeekEnd /* exceeds the largest valid whence */ { + return ErrnoInval + } + newOffset, err := seeker.Seek(int64(offset), int(whence)) + if err != nil { + return ErrnoIo + } + + if !m.Memory().WriteUint32Le(resultNewoffset, uint32(newOffset)) { + return ErrnoFault + } + + return ErrnoSuccess +} + +// FdSync implements snapshotPreview1.FdSync +func (a *wasiAPI) FdSync(m api.Module, fd uint32) Errno { + return ErrnoNosys // stubbed for GrainLang per #271 +} + +// FdTell implements snapshotPreview1.FdTell +func (a *wasiAPI) FdTell(m api.Module, fd, resultOffset uint32) Errno { + return ErrnoNosys // stubbed for GrainLang per #271 +} + +// FdWrite implements snapshotPreview1.FdWrite +func (a *wasiAPI) FdWrite(m api.Module, fd, iovs, iovsCount, resultSize uint32) Errno { + sys := sysCtx(m) + + var writer io.Writer + + switch fd { + case fdStdout: + writer = sys.Stdout() + case fdStderr: + writer = sys.Stderr() + default: + // Check to see if the file descriptor is available + if f, ok := sys.OpenedFile(fd); !ok || f.File == nil { + return ErrnoBadf + // fs.FS doesn't declare io.Writer, but implementations such as os.File implement it. + } else if writer, ok = f.File.(io.Writer); !ok { + return ErrnoBadf + } + } + + var nwritten uint32 + for i := uint32(0); i < iovsCount; i++ { + iovPtr := iovs + i*8 + offset, ok := m.Memory().ReadUint32Le(iovPtr) + if !ok { + return ErrnoFault + } + l, ok := m.Memory().ReadUint32Le(iovPtr + 4) + if !ok { + return ErrnoFault + } + b, ok := m.Memory().Read(offset, l) + if !ok { + return ErrnoFault + } + n, err := writer.Write(b) + if err != nil { + return ErrnoIo + } + nwritten += uint32(n) + } + if !m.Memory().WriteUint32Le(resultSize, nwritten) { + return ErrnoFault + } + return ErrnoSuccess +} + +// PathCreateDirectory implements snapshotPreview1.PathCreateDirectory +func (a *wasiAPI) PathCreateDirectory(m api.Module, fd, path, pathLen uint32) Errno { + return ErrnoNosys // stubbed for GrainLang per #271 +} + +// PathFilestatGet implements snapshotPreview1.PathFilestatGet +func (a *wasiAPI) PathFilestatGet(m api.Module, fd, flags, path, pathLen, resultBuf uint32) Errno { + return ErrnoNosys // stubbed for GrainLang per #271 +} + +// PathFilestatSetTimes implements snapshotPreview1.PathFilestatSetTimes +func (a *wasiAPI) PathFilestatSetTimes(m api.Module, fd, flags, path, pathLen uint32, atim, mtime uint64, fstFlags uint32) Errno { + return ErrnoNosys // stubbed for GrainLang per #271 +} + +// PathLink implements snapshotPreview1.PathLink +func (a *wasiAPI) PathLink(m api.Module, oldFd, oldFlags, oldPath, oldPathLen, newFd, newPath, newPathLen uint32) Errno { + return ErrnoNosys // stubbed for GrainLang per #271 +} + +// PathOpen implements snapshotPreview1.PathOpen +// Note: Rights will never be implemented per https://github.com/WebAssembly/WASI/issues/469#issuecomment-1045251844 +func (a *wasiAPI) PathOpen(m api.Module, fd, dirflags, pathPtr, pathLen, oflags uint32, fsRightsBase, + fsRightsInheriting uint64, fdflags, resultOpenedFd uint32) (errno Errno) { + sys := sysCtx(m) + + dir, ok := sys.OpenedFile(fd) + if !ok || dir.FS == nil { + return ErrnoBadf + } + + b, ok := m.Memory().Read(pathPtr, pathLen) + if !ok { + return ErrnoFault + } + + // TODO: Consider dirflags and oflags. Also, allow non-read-only open based on config about the mount. + // Ex. allow os.O_RDONLY, os.O_WRONLY, or os.O_RDWR either by config flag or pattern on filename + // See #390 + entry, errno := openFileEntry(dir.FS, path.Join(dir.Path, string(b))) + if errno != ErrnoSuccess { + return errno + } + + if newFD, ok := sys.OpenFile(entry); !ok { + _ = entry.File.Close() + return ErrnoIo + } else if !m.Memory().WriteUint32Le(resultOpenedFd, newFD) { + _ = entry.File.Close() + return ErrnoFault + } + return ErrnoSuccess +} + +// PathReadlink implements snapshotPreview1.PathReadlink +func (a *wasiAPI) PathReadlink(m api.Module, fd, path, pathLen, buf, bufLen, resultBufused uint32) Errno { + return ErrnoNosys // stubbed for GrainLang per #271 +} + +// PathRemoveDirectory implements snapshotPreview1.PathRemoveDirectory +func (a *wasiAPI) PathRemoveDirectory(m api.Module, fd, path, pathLen uint32) Errno { + return ErrnoNosys // stubbed for GrainLang per #271 +} + +// PathRename implements snapshotPreview1.PathRename +func (a *wasiAPI) PathRename(m api.Module, fd, oldPath, oldPathLen, newFd, newPath, newPathLen uint32) Errno { + return ErrnoNosys // stubbed for GrainLang per #271 +} + +// PathSymlink implements snapshotPreview1.PathSymlink +func (a *wasiAPI) PathSymlink(m api.Module, oldPath, oldPathLen, fd, newPath, newPathLen uint32) Errno { + return ErrnoNosys // stubbed for GrainLang per #271 +} + +// PathUnlinkFile implements snapshotPreview1.PathUnlinkFile +func (a *wasiAPI) PathUnlinkFile(m api.Module, fd, path, pathLen uint32) Errno { + return ErrnoNosys // stubbed for GrainLang per #271 +} + +// PollOneoff implements snapshotPreview1.PollOneoff +func (a *wasiAPI) PollOneoff(m api.Module, in, out, nsubscriptions, resultNevents uint32) Errno { + return ErrnoNosys // stubbed for GrainLang per #271 +} + +// ProcExit implements snapshotPreview1.ProcExit +func (a *wasiAPI) ProcExit(m api.Module, exitCode uint32) { + _ = m.CloseWithExitCode(exitCode) +} + +// ProcRaise implements snapshotPreview1.ProcRaise +func (a *wasiAPI) ProcRaise(m api.Module, sig uint32) Errno { + return ErrnoNosys // stubbed for GrainLang per #271 +} + +// SchedYield implements snapshotPreview1.SchedYield +func (a *wasiAPI) SchedYield(m api.Module) Errno { + return ErrnoNosys // stubbed for GrainLang per #271 +} + +// RandomGet implements snapshotPreview1.RandomGet +func (a *wasiAPI) RandomGet(m api.Module, buf uint32, bufLen uint32) (errno Errno) { + randomBytes := make([]byte, bufLen) + err := a.randSource(randomBytes) + if err != nil { + // TODO: handle different errors that syscal to entropy source can return + return ErrnoIo + } + + if !m.Memory().Write(buf, randomBytes) { + return ErrnoFault + } + + return ErrnoSuccess +} + +// SockRecv implements snapshotPreview1.SockRecv +func (a *wasiAPI) SockRecv(m api.Module, fd, riData, riDataCount, riFlags, resultRoDataLen, resultRoFlags uint32) Errno { + return ErrnoNosys // stubbed for GrainLang per #271 +} + +// SockSend implements snapshotPreview1.SockSend +func (a *wasiAPI) SockSend(m api.Module, fd, siData, siDataCount, siFlags, resultSoDataLen uint32) Errno { + return ErrnoNosys // stubbed for GrainLang per #271 +} + +// SockShutdown implements snapshotPreview1.SockShutdown +func (a *wasiAPI) SockShutdown(m api.Module, fd, how uint32) Errno { + return ErrnoNosys // stubbed for GrainLang per #271 +} + +const ( + fdStdin = 0 + fdStdout = 1 + fdStderr = 2 +) + +// newAPI is exported for benchmarks +func newAPI() *wasiAPI { + return &wasiAPI{ + timeNowUnixNano: func() uint64 { + return uint64(time.Now().UnixNano()) + }, + randSource: func(p []byte) error { + _, err := crand.Read(p) + return err + }, + } +} + +func sysCtx(m api.Module) *wasm.SysContext { + if internal, ok := m.(*wasm.ModuleContext); !ok { + panic(fmt.Errorf("unsupported wasm.Module implementation: %v", m)) + } else { + return internal.Sys() + } +} + +func openFileEntry(rootFS fs.FS, pathName string) (*wasm.FileEntry, Errno) { + f, err := rootFS.Open(pathName) + if err != nil { + switch { + case errors.Is(err, fs.ErrNotExist): + return nil, ErrnoNoent + case errors.Is(err, fs.ErrExist): + return nil, ErrnoExist + default: + return nil, ErrnoIo + } + } + + // TODO: verify if oflags is a directory and fail with wasi.ErrnoNotdir if not + // See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-oflags-flagsu16 + + return &wasm.FileEntry{Path: pathName, FS: rootFS, File: f}, ErrnoSuccess +} + +func writeOffsetsAndNullTerminatedValues(mem api.Memory, values []string, offsets, bytes uint32) Errno { + for _, value := range values { + // Write current offset and advance it. + if !mem.WriteUint32Le(offsets, bytes) { + return ErrnoFault + } + offsets += 4 // size of uint32 + + // Write the next value to memory with a NUL terminator + if !mem.Write(bytes, []byte(value)) { + return ErrnoFault + } + bytes += uint32(len(value)) + if !mem.WriteByte(bytes, 0) { + return ErrnoFault + } + bytes++ + } + + return ErrnoSuccess } diff --git a/tests/bench/wasi_test.go b/wasi/wasi_bench_test.go similarity index 70% rename from tests/bench/wasi_test.go rename to wasi/wasi_bench_test.go index 8d14216b..c354768c 100644 --- a/tests/bench/wasi_test.go +++ b/wasi/wasi_bench_test.go @@ -1,16 +1,12 @@ -package bench +package wasi import ( - "bytes" "context" - "math" "testing" "github.com/stretchr/testify/require" - internalwasi "github.com/tetratelabs/wazero/internal/wasi" - wasm "github.com/tetratelabs/wazero/internal/wasm" - "github.com/tetratelabs/wazero/wasi" + "github.com/tetratelabs/wazero/internal/wasm" ) var testMem = &wasm.MemoryInstance{ @@ -31,9 +27,9 @@ func Test_EnvironGet(t *testing.T) { require.NoError(t, err) testCtx := newCtx(make([]byte, 20), sys) - environGet := internalwasi.NewAPI().EnvironGet + environGet := newAPI().EnvironGet - require.Equal(t, wasi.ErrnoSuccess, environGet(testCtx, 11, 1)) + require.Equal(t, ErrnoSuccess, environGet(testCtx, 11, 1)) require.Equal(t, testCtx.Memory(), testMem) } @@ -53,10 +49,10 @@ func Benchmark_EnvironGet(b *testing.B) { 0, }, sys) - environGet := internalwasi.NewAPI().EnvironGet + environGet := newAPI().EnvironGet b.Run("EnvironGet", func(b *testing.B) { for i := 0; i < b.N; i++ { - if environGet(testCtx, 0, 4) != wasi.ErrnoSuccess { + if environGet(testCtx, 0, 4) != ErrnoSuccess { b.Fatal() } } @@ -68,7 +64,3 @@ func newCtx(buf []byte, sys *wasm.SysContext) *wasm.ModuleContext { Memory: &wasm.MemoryInstance{Min: 1, Buffer: buf}, }, sys) } - -func newSysContext(args, environ []string, openedFiles map[uint32]*wasm.FileEntry) (sys *wasm.SysContext, err error) { - return wasm.NewSysContext(math.MaxUint32, args, environ, new(bytes.Buffer), nil, nil, openedFiles) -} diff --git a/internal/wasi/wasi_test.go b/wasi/wasi_test.go similarity index 71% rename from internal/wasi/wasi_test.go rename to wasi/wasi_test.go index 75b5fd14..228e0210 100644 --- a/internal/wasi/wasi_test.go +++ b/wasi/wasi_test.go @@ -1,4 +1,4 @@ -package internalwasi +package wasi import ( "bytes" @@ -17,12 +17,11 @@ import ( "github.com/stretchr/testify/require" - wasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/api" + "github.com/tetratelabs/wazero/internal/wasm" "github.com/tetratelabs/wazero/internal/wasm/interpreter" "github.com/tetratelabs/wazero/internal/wasm/text" "github.com/tetratelabs/wazero/sys" - "github.com/tetratelabs/wazero/wasi" - publicwasm "github.com/tetratelabs/wazero/wasm" ) const moduleName = "test" @@ -43,28 +42,28 @@ func TestSnapshotPreview1_ArgsGet(t *testing.T) { '?', // stopped after encoding } - a, mod, fn := instantiateModule(t, ctx, FunctionArgsGet, ImportArgsGet, moduleName, sysCtx) + a, mod, fn := instantiateModule(t, ctx, functionArgsGet, importArgsGet, moduleName, sysCtx) defer mod.Close() - t.Run("SnapshotPreview1.ArgsGet", func(t *testing.T) { + t.Run("snapshotPreview1.ArgsGet", func(t *testing.T) { maskMemory(t, mod, len(expectedMemory)) // Invoke ArgsGet directly and check the memory side effects. errno := a.ArgsGet(mod, argv, argvBuf) - require.Zero(t, errno, wasi.ErrnoName(errno)) + require.Zero(t, errno, ErrnoName(errno)) actual, ok := mod.Memory().Read(0, uint32(len(expectedMemory))) require.True(t, ok) require.Equal(t, expectedMemory, actual) }) - t.Run(FunctionArgsGet, func(t *testing.T) { + t.Run(functionArgsGet, func(t *testing.T) { maskMemory(t, mod, len(expectedMemory)) results, err := fn.Call(mod, uint64(argv), uint64(argvBuf)) require.NoError(t, err) - errno := wasi.Errno(results[0]) // results[0] is the errno - require.Zero(t, errno, wasi.ErrnoName(errno)) + errno := Errno(results[0]) // results[0] is the errno + require.Zero(t, errno, ErrnoName(errno)) actual, ok := mod.Memory().Read(0, uint32(len(expectedMemory))) require.True(t, ok) @@ -77,7 +76,7 @@ func TestSnapshotPreview1_ArgsGet_Errors(t *testing.T) { sysCtx, err := newSysContext([]string{"a", "bc"}, nil, nil) require.NoError(t, err) - a, mod, _ := instantiateModule(t, ctx, FunctionArgsGet, ImportArgsGet, moduleName, sysCtx) + a, mod, _ := instantiateModule(t, ctx, functionArgsGet, importArgsGet, moduleName, sysCtx) defer mod.Close() memorySize := mod.Memory().Size() @@ -118,7 +117,7 @@ func TestSnapshotPreview1_ArgsGet_Errors(t *testing.T) { t.Run(tc.name, func(t *testing.T) { errno := a.ArgsGet(mod, tc.argv, tc.argvBuf) require.NoError(t, err) - require.Equal(t, wasi.ErrnoFault, errno, wasi.ErrnoName(errno)) + require.Equal(t, ErrnoFault, errno, ErrnoName(errno)) }) } } @@ -138,28 +137,28 @@ func TestSnapshotPreview1_ArgsSizesGet(t *testing.T) { '?', // stopped after encoding } - a, mod, fn := instantiateModule(t, ctx, FunctionArgsSizesGet, ImportArgsSizesGet, moduleName, sysCtx) + a, mod, fn := instantiateModule(t, ctx, functionArgsSizesGet, importArgsSizesGet, moduleName, sysCtx) defer mod.Close() - t.Run("SnapshotPreview1.ArgsSizesGet", func(t *testing.T) { + t.Run("snapshotPreview1.ArgsSizesGet", func(t *testing.T) { maskMemory(t, mod, len(expectedMemory)) // Invoke ArgsSizesGet directly and check the memory side effects. errno := a.ArgsSizesGet(mod, resultArgc, resultArgvBufSize) - require.Zero(t, errno, wasi.ErrnoName(errno)) + require.Zero(t, errno, ErrnoName(errno)) actual, ok := mod.Memory().Read(0, uint32(len(expectedMemory))) require.True(t, ok) require.Equal(t, expectedMemory, actual) }) - t.Run(FunctionArgsSizesGet, func(t *testing.T) { + t.Run(functionArgsSizesGet, func(t *testing.T) { maskMemory(t, mod, len(expectedMemory)) results, err := fn.Call(mod, uint64(resultArgc), uint64(resultArgvBufSize)) require.NoError(t, err) - errno := wasi.Errno(results[0]) // results[0] is the errno - require.Zero(t, errno, wasi.ErrnoName(errno)) + errno := Errno(results[0]) // results[0] is the errno + require.Zero(t, errno, ErrnoName(errno)) actual, ok := mod.Memory().Read(0, uint32(len(expectedMemory))) require.True(t, ok) @@ -172,7 +171,7 @@ func TestSnapshotPreview1_ArgsSizesGet_Errors(t *testing.T) { sysCtx, err := newSysContext([]string{"a", "bc"}, nil, nil) require.NoError(t, err) - a, mod, _ := instantiateModule(t, ctx, FunctionArgsSizesGet, ImportArgsSizesGet, moduleName, sysCtx) + a, mod, _ := instantiateModule(t, ctx, functionArgsSizesGet, importArgsSizesGet, moduleName, sysCtx) defer mod.Close() memorySize := mod.Memory().Size() @@ -210,7 +209,7 @@ func TestSnapshotPreview1_ArgsSizesGet_Errors(t *testing.T) { t.Run(tc.name, func(t *testing.T) { errno := a.ArgsSizesGet(mod, tc.argc, tc.argvBufSize) - require.Equal(t, wasi.ErrnoFault, errno, wasi.ErrnoName(errno)) + require.Equal(t, ErrnoFault, errno, ErrnoName(errno)) }) } } @@ -232,28 +231,28 @@ func TestSnapshotPreview1_EnvironGet(t *testing.T) { '?', // stopped after encoding } - a, mod, fn := instantiateModule(t, ctx, FunctionEnvironGet, ImportEnvironGet, moduleName, sysCtx) + a, mod, fn := instantiateModule(t, ctx, functionEnvironGet, importEnvironGet, moduleName, sysCtx) defer mod.Close() - t.Run("SnapshotPreview1.EnvironGet", func(t *testing.T) { + t.Run("snapshotPreview1.EnvironGet", func(t *testing.T) { maskMemory(t, mod, len(expectedMemory)) // Invoke EnvironGet directly and check the memory side effects. errno := a.EnvironGet(mod, resultEnviron, resultEnvironBuf) - require.Zero(t, errno, wasi.ErrnoName(errno)) + require.Zero(t, errno, ErrnoName(errno)) actual, ok := mod.Memory().Read(0, uint32(len(expectedMemory))) require.True(t, ok) require.Equal(t, expectedMemory, actual) }) - t.Run(FunctionEnvironGet, func(t *testing.T) { + t.Run(functionEnvironGet, func(t *testing.T) { maskMemory(t, mod, len(expectedMemory)) results, err := fn.Call(mod, uint64(resultEnviron), uint64(resultEnvironBuf)) require.NoError(t, err) - errno := wasi.Errno(results[0]) // results[0] is the errno - require.Zero(t, errno, wasi.ErrnoName(errno)) + errno := Errno(results[0]) // results[0] is the errno + require.Zero(t, errno, ErrnoName(errno)) actual, ok := mod.Memory().Read(0, uint32(len(expectedMemory))) require.True(t, ok) @@ -266,7 +265,7 @@ func TestSnapshotPreview1_EnvironGet_Errors(t *testing.T) { sysCtx, err := newSysContext(nil, []string{"a=bc", "b=cd"}, nil) require.NoError(t, err) - a, mod, _ := instantiateModule(t, ctx, FunctionEnvironGet, ImportEnvironGet, moduleName, sysCtx) + a, mod, _ := instantiateModule(t, ctx, functionEnvironGet, importEnvironGet, moduleName, sysCtx) defer mod.Close() memorySize := mod.Memory().Size() @@ -306,7 +305,7 @@ func TestSnapshotPreview1_EnvironGet_Errors(t *testing.T) { t.Run(tc.name, func(t *testing.T) { errno := a.EnvironGet(mod, tc.environ, tc.environBuf) - require.Equal(t, wasi.ErrnoFault, errno, wasi.ErrnoName(errno)) + require.Equal(t, ErrnoFault, errno, ErrnoName(errno)) }) } } @@ -326,28 +325,28 @@ func TestSnapshotPreview1_EnvironSizesGet(t *testing.T) { '?', // stopped after encoding } - a, mod, fn := instantiateModule(t, ctx, FunctionEnvironSizesGet, ImportEnvironSizesGet, moduleName, sysCtx) + a, mod, fn := instantiateModule(t, ctx, functionEnvironSizesGet, importEnvironSizesGet, moduleName, sysCtx) defer mod.Close() - t.Run("SnapshotPreview1.EnvironSizesGet", func(t *testing.T) { + t.Run("snapshotPreview1.EnvironSizesGet", func(t *testing.T) { maskMemory(t, mod, len(expectedMemory)) // Invoke EnvironSizesGet directly and check the memory side effects. errno := a.EnvironSizesGet(mod, resultEnvironc, resultEnvironBufSize) - require.Zero(t, errno, wasi.ErrnoName(errno)) + require.Zero(t, errno, ErrnoName(errno)) actual, ok := mod.Memory().Read(0, uint32(len(expectedMemory))) require.True(t, ok) require.Equal(t, expectedMemory, actual) }) - t.Run(FunctionEnvironSizesGet, func(t *testing.T) { + t.Run(functionEnvironSizesGet, func(t *testing.T) { maskMemory(t, mod, len(expectedMemory)) results, err := fn.Call(mod, uint64(resultEnvironc), uint64(resultEnvironBufSize)) require.NoError(t, err) - errno := wasi.Errno(results[0]) // results[0] is the errno - require.Zero(t, errno, wasi.ErrnoName(errno)) + errno := Errno(results[0]) // results[0] is the errno + require.Zero(t, errno, ErrnoName(errno)) actual, ok := mod.Memory().Read(0, uint32(len(expectedMemory))) require.True(t, ok) @@ -360,7 +359,7 @@ func TestSnapshotPreview1_EnvironSizesGet_Errors(t *testing.T) { sysCtx, err := newSysContext(nil, []string{"a=b", "b=cd"}, nil) require.NoError(t, err) - a, mod, _ := instantiateModule(t, ctx, FunctionEnvironSizesGet, ImportEnvironSizesGet, moduleName, sysCtx) + a, mod, _ := instantiateModule(t, ctx, functionEnvironSizesGet, importEnvironSizesGet, moduleName, sysCtx) defer mod.Close() memorySize := mod.Memory().Size() @@ -398,7 +397,7 @@ func TestSnapshotPreview1_EnvironSizesGet_Errors(t *testing.T) { t.Run(tc.name, func(t *testing.T) { errno := a.EnvironSizesGet(mod, tc.environc, tc.environBufSize) - require.Equal(t, wasi.ErrnoFault, errno, wasi.ErrnoName(errno)) + require.Equal(t, ErrnoFault, errno, ErrnoName(errno)) }) } } @@ -409,18 +408,18 @@ func TestSnapshotPreview1_ClockResGet(t *testing.T) { sysCtx, err := newSysContext(nil, nil, nil) require.NoError(t, err) - a, mod, fn := instantiateModule(t, ctx, FunctionClockResGet, ImportClockResGet, moduleName, sysCtx) + a, mod, fn := instantiateModule(t, ctx, functionClockResGet, importClockResGet, moduleName, sysCtx) defer mod.Close() - t.Run("SnapshotPreview1.ClockResGet", func(t *testing.T) { - require.Equal(t, wasi.ErrnoNosys, a.ClockResGet(mod, 0, 0)) + t.Run("snapshotPreview1.ClockResGet", func(t *testing.T) { + require.Equal(t, ErrnoNosys, a.ClockResGet(mod, 0, 0)) }) - t.Run(FunctionClockResGet, func(t *testing.T) { + t.Run(functionClockResGet, func(t *testing.T) { results, err := fn.Call(mod, 0, 0) require.NoError(t, err) - errno := wasi.Errno(results[0]) // results[0] is the errno - require.Equal(t, wasi.ErrnoNosys, errno, wasi.ErrnoName(errno)) + errno := Errno(results[0]) // results[0] is the errno + require.Equal(t, ErrnoNosys, errno, ErrnoName(errno)) }) } @@ -437,30 +436,30 @@ func TestSnapshotPreview1_ClockTimeGet(t *testing.T) { sysCtx, err := newSysContext(nil, nil, nil) require.NoError(t, err) - a, mod, fn := instantiateModule(t, ctx, FunctionClockTimeGet, ImportClockTimeGet, moduleName, sysCtx) + a, mod, fn := instantiateModule(t, ctx, functionClockTimeGet, importClockTimeGet, moduleName, sysCtx) defer mod.Close() a.timeNowUnixNano = func() uint64 { return epochNanos } - t.Run("SnapshotPreview1.ClockTimeGet", func(t *testing.T) { + t.Run("snapshotPreview1.ClockTimeGet", func(t *testing.T) { maskMemory(t, mod, len(expectedMemory)) // invoke ClockTimeGet directly and check the memory side effects! errno := a.ClockTimeGet(mod, 0 /* TODO: id */, 0 /* TODO: precision */, resultTimestamp) - require.Zero(t, errno, wasi.ErrnoName(errno)) + require.Zero(t, errno, ErrnoName(errno)) actual, ok := mod.Memory().Read(0, uint32(len(expectedMemory))) require.True(t, ok) require.Equal(t, expectedMemory, actual) }) - t.Run(FunctionClockTimeGet, func(t *testing.T) { + t.Run(functionClockTimeGet, func(t *testing.T) { maskMemory(t, mod, len(expectedMemory)) results, err := fn.Call(mod, 0 /* TODO: id */, 0 /* TODO: precision */, uint64(resultTimestamp)) require.NoError(t, err) - errno := wasi.Errno(results[0]) // results[0] is the errno - require.Zero(t, errno, wasi.ErrnoName(errno)) + errno := Errno(results[0]) // results[0] is the errno + require.Zero(t, errno, ErrnoName(errno)) actual, ok := mod.Memory().Read(0, uint32(len(expectedMemory))) require.True(t, ok) @@ -475,7 +474,7 @@ func TestSnapshotPreview1_ClockTimeGet_Errors(t *testing.T) { sysCtx, err := newSysContext(nil, nil, nil) require.NoError(t, err) - a, mod, fn := instantiateModule(t, ctx, FunctionClockTimeGet, ImportClockTimeGet, moduleName, sysCtx) + a, mod, fn := instantiateModule(t, ctx, functionClockTimeGet, importClockTimeGet, moduleName, sysCtx) defer mod.Close() a.timeNowUnixNano = func() uint64 { return epochNanos } @@ -504,8 +503,8 @@ func TestSnapshotPreview1_ClockTimeGet_Errors(t *testing.T) { t.Run(tc.name, func(t *testing.T) { results, err := fn.Call(mod, 0 /* TODO: id */, 0 /* TODO: precision */, uint64(tc.resultTimestamp)) require.NoError(t, err) - errno := wasi.Errno(results[0]) // results[0] is the errno - require.Equal(t, wasi.ErrnoFault, errno, wasi.ErrnoName(errno)) + errno := Errno(results[0]) // results[0] is the errno + require.Equal(t, ErrnoFault, errno, ErrnoName(errno)) }) } } @@ -516,19 +515,19 @@ func TestSnapshotPreview1_FdAdvise(t *testing.T) { sysCtx, err := newSysContext(nil, nil, nil) require.NoError(t, err) - a, mod, fn := instantiateModule(t, ctx, FunctionFdAdvise, ImportFdAdvise, moduleName, sysCtx) + a, mod, fn := instantiateModule(t, ctx, functionFdAdvise, importFdAdvise, moduleName, sysCtx) defer mod.Close() - t.Run("SnapshotPreview1.FdAdvise", func(t *testing.T) { + t.Run("snapshotPreview1.FdAdvise", func(t *testing.T) { errno := a.FdAdvise(mod, 0, 0, 0, 0) - require.Equal(t, wasi.ErrnoNosys, errno, wasi.ErrnoName(errno)) + require.Equal(t, ErrnoNosys, errno, ErrnoName(errno)) }) - t.Run(FunctionFdAdvise, func(t *testing.T) { + t.Run(functionFdAdvise, func(t *testing.T) { results, err := fn.Call(mod, 0, 0, 0, 0) require.NoError(t, err) - errno := wasi.Errno(results[0]) // results[0] is the errno - require.Equal(t, wasi.ErrnoNosys, errno, wasi.ErrnoName(errno)) + errno := Errno(results[0]) // results[0] is the errno + require.Equal(t, ErrnoNosys, errno, ErrnoName(errno)) }) } @@ -538,19 +537,19 @@ func TestSnapshotPreview1_FdAllocate(t *testing.T) { sysCtx, err := newSysContext(nil, nil, nil) require.NoError(t, err) - a, mod, fn := instantiateModule(t, ctx, FunctionFdAllocate, ImportFdAllocate, moduleName, sysCtx) + a, mod, fn := instantiateModule(t, ctx, functionFdAllocate, importFdAllocate, moduleName, sysCtx) defer mod.Close() - t.Run("SnapshotPreview1.FdAllocate", func(t *testing.T) { + t.Run("snapshotPreview1.FdAllocate", func(t *testing.T) { errno := a.FdAllocate(mod, 0, 0, 0) - require.Equal(t, wasi.ErrnoNosys, errno, wasi.ErrnoName(errno)) + require.Equal(t, ErrnoNosys, errno, ErrnoName(errno)) }) - t.Run(FunctionFdAllocate, func(t *testing.T) { + t.Run(functionFdAllocate, func(t *testing.T) { results, err := fn.Call(mod, 0, 0, 0) require.NoError(t, err) - errno := wasi.Errno(results[0]) // results[0] is the errno - require.Equal(t, wasi.ErrnoNosys, errno, wasi.ErrnoName(errno)) + errno := Errno(results[0]) // results[0] is the errno + require.Equal(t, ErrnoNosys, errno, ErrnoName(errno)) }) } @@ -558,16 +557,16 @@ func TestSnapshotPreview1_FdClose(t *testing.T) { fdToClose := uint32(3) // arbitrary fd fdToKeep := uint32(4) // another arbitrary fd - setupFD := func() (publicwasm.Module, publicwasm.Function, *wasiAPI) { + setupFD := func() (api.Module, api.Function, *wasiAPI) { ctx := context.Background() // fd_close needs to close an open file descriptor. Open two files so that we can tell which is closed. path1, path2 := "a", "b" testFs := fstest.MapFS{path1: {Data: make([]byte, 0)}, path2: {Data: make([]byte, 0)}} entry1, errno := openFileEntry(testFs, path1) - require.Zero(t, errno, wasi.ErrnoName(errno)) + require.Zero(t, errno, ErrnoName(errno)) entry2, errno := openFileEntry(testFs, path2) - require.Zero(t, errno, wasi.ErrnoName(errno)) + require.Zero(t, errno, ErrnoName(errno)) sysCtx, err := newSysContext(nil, nil, map[uint32]*wasm.FileEntry{ fdToClose: entry1, @@ -575,11 +574,11 @@ func TestSnapshotPreview1_FdClose(t *testing.T) { }) require.NoError(t, err) - a, mod, fn := instantiateModule(t, ctx, FunctionFdClose, ImportFdClose, moduleName, sysCtx) + a, mod, fn := instantiateModule(t, ctx, functionFdClose, importFdClose, moduleName, sysCtx) return mod, fn, a } - verify := func(mod publicwasm.Module) { + verify := func(mod api.Module) { // Verify fdToClose is closed and removed from the opened FDs. _, ok := sysCtx(mod).OpenedFile(fdToClose) require.False(t, ok) @@ -589,23 +588,23 @@ func TestSnapshotPreview1_FdClose(t *testing.T) { require.True(t, ok) } - t.Run("SnapshotPreview1.FdClose", func(t *testing.T) { + t.Run("snapshotPreview1.FdClose", func(t *testing.T) { mod, _, api := setupFD() defer mod.Close() errno := api.FdClose(mod, fdToClose) - require.Zero(t, errno, wasi.ErrnoName(errno)) + require.Zero(t, errno, ErrnoName(errno)) verify(mod) }) - t.Run(FunctionFdClose, func(t *testing.T) { + t.Run(functionFdClose, func(t *testing.T) { mod, fn, _ := setupFD() defer mod.Close() results, err := fn.Call(mod, uint64(fdToClose)) require.NoError(t, err) - errno := wasi.Errno(results[0]) // results[0] is the errno - require.Zero(t, errno, wasi.ErrnoName(errno)) + errno := Errno(results[0]) // results[0] is the errno + require.Zero(t, errno, ErrnoName(errno)) verify(mod) }) @@ -614,7 +613,7 @@ func TestSnapshotPreview1_FdClose(t *testing.T) { defer mod.Close() errno := api.FdClose(mod, 42) // 42 is an arbitrary invalid FD - require.Equal(t, wasi.ErrnoBadf, errno) + require.Equal(t, ErrnoBadf, errno) }) } @@ -624,23 +623,27 @@ func TestSnapshotPreview1_FdDatasync(t *testing.T) { sysCtx, err := newSysContext(nil, nil, nil) require.NoError(t, err) - a, mod, fn := instantiateModule(t, ctx, FunctionFdDatasync, ImportFdDatasync, moduleName, sysCtx) + a, mod, fn := instantiateModule(t, ctx, functionFdDatasync, importFdDatasync, moduleName, sysCtx) defer mod.Close() - t.Run("SnapshotPreview1.FdDatasync", func(t *testing.T) { + t.Run("snapshotPreview1.FdDatasync", func(t *testing.T) { errno := a.FdDatasync(mod, 0) - require.Equal(t, wasi.ErrnoNosys, errno, wasi.ErrnoName(errno)) + require.Equal(t, ErrnoNosys, errno, ErrnoName(errno)) }) - t.Run(FunctionFdDatasync, func(t *testing.T) { + t.Run(functionFdDatasync, func(t *testing.T) { results, err := fn.Call(mod, 0) require.NoError(t, err) - errno := wasi.Errno(results[0]) // results[0] is the errno - require.Equal(t, wasi.ErrnoNosys, errno, wasi.ErrnoName(errno)) + errno := Errno(results[0]) // results[0] is the errno + require.Equal(t, ErrnoNosys, errno, ErrnoName(errno)) }) } // TODO: TestSnapshotPreview1_FdFdstatGet TestSnapshotPreview1_FdFdstatGet_Errors +func TestSnapshotPreview1_FdFdstatGet(t *testing.T) { + t.Skip("TODO") + _ = importFdFdstatGet // stop linter complaint until we implement this +} // TestSnapshotPreview1_FdFdstatSetFlags only tests it is stubbed for GrainLang per #271 func TestSnapshotPreview1_FdFdstatSetFlags(t *testing.T) { @@ -648,19 +651,19 @@ func TestSnapshotPreview1_FdFdstatSetFlags(t *testing.T) { sysCtx, err := newSysContext(nil, nil, nil) require.NoError(t, err) - a, mod, fn := instantiateModule(t, ctx, FunctionFdFdstatSetFlags, ImportFdFdstatSetFlags, moduleName, sysCtx) + a, mod, fn := instantiateModule(t, ctx, functionFdFdstatSetFlags, importFdFdstatSetFlags, moduleName, sysCtx) defer mod.Close() - t.Run("SnapshotPreview1.FdFdstatSetFlags", func(t *testing.T) { + t.Run("snapshotPreview1.FdFdstatSetFlags", func(t *testing.T) { errno := a.FdFdstatSetFlags(mod, 0, 0) - require.Equal(t, wasi.ErrnoNosys, errno, wasi.ErrnoName(errno)) + require.Equal(t, ErrnoNosys, errno, ErrnoName(errno)) }) - t.Run(FunctionFdFdstatSetFlags, func(t *testing.T) { + t.Run(functionFdFdstatSetFlags, func(t *testing.T) { results, err := fn.Call(mod, 0, 0) require.NoError(t, err) - errno := wasi.Errno(results[0]) // results[0] is the errno - require.Equal(t, wasi.ErrnoNosys, errno, wasi.ErrnoName(errno)) + errno := Errno(results[0]) // results[0] is the errno + require.Equal(t, ErrnoNosys, errno, ErrnoName(errno)) }) } @@ -670,19 +673,19 @@ func TestSnapshotPreview1_FdFdstatSetRights(t *testing.T) { sysCtx, err := newSysContext(nil, nil, nil) require.NoError(t, err) - a, mod, fn := instantiateModule(t, ctx, FunctionFdFdstatSetRights, ImportFdFdstatSetRights, moduleName, sysCtx) + a, mod, fn := instantiateModule(t, ctx, functionFdFdstatSetRights, importFdFdstatSetRights, moduleName, sysCtx) defer mod.Close() - t.Run("SnapshotPreview1.FdFdstatSetRights", func(t *testing.T) { + t.Run("snapshotPreview1.FdFdstatSetRights", func(t *testing.T) { errno := a.FdFdstatSetRights(mod, 0, 0, 0) - require.Equal(t, wasi.ErrnoNosys, errno, wasi.ErrnoName(errno)) + require.Equal(t, ErrnoNosys, errno, ErrnoName(errno)) }) - t.Run(FunctionFdFdstatSetRights, func(t *testing.T) { + t.Run(functionFdFdstatSetRights, func(t *testing.T) { results, err := fn.Call(mod, 0, 0, 0) require.NoError(t, err) - errno := wasi.Errno(results[0]) // results[0] is the errno - require.Equal(t, wasi.ErrnoNosys, errno, wasi.ErrnoName(errno)) + errno := Errno(results[0]) // results[0] is the errno + require.Equal(t, ErrnoNosys, errno, ErrnoName(errno)) }) } @@ -692,19 +695,19 @@ func TestSnapshotPreview1_FdFilestatGet(t *testing.T) { sysCtx, err := newSysContext(nil, nil, nil) require.NoError(t, err) - a, mod, fn := instantiateModule(t, ctx, FunctionFdFilestatGet, ImportFdFilestatGet, moduleName, sysCtx) + a, mod, fn := instantiateModule(t, ctx, functionFdFilestatGet, importFdFilestatGet, moduleName, sysCtx) defer mod.Close() - t.Run("SnapshotPreview1.FdFilestatGet", func(t *testing.T) { + t.Run("snapshotPreview1.FdFilestatGet", func(t *testing.T) { errno := a.FdFilestatGet(mod, 0, 0) - require.Equal(t, wasi.ErrnoNosys, errno, wasi.ErrnoName(errno)) + require.Equal(t, ErrnoNosys, errno, ErrnoName(errno)) }) - t.Run(FunctionFdFilestatGet, func(t *testing.T) { + t.Run(functionFdFilestatGet, func(t *testing.T) { results, err := fn.Call(mod, 0, 0) require.NoError(t, err) - errno := wasi.Errno(results[0]) // results[0] is the errno - require.Equal(t, wasi.ErrnoNosys, errno, wasi.ErrnoName(errno)) + errno := Errno(results[0]) // results[0] is the errno + require.Equal(t, ErrnoNosys, errno, ErrnoName(errno)) }) } @@ -714,19 +717,19 @@ func TestSnapshotPreview1_FdFilestatSetSize(t *testing.T) { sysCtx, err := newSysContext(nil, nil, nil) require.NoError(t, err) - a, mod, fn := instantiateModule(t, ctx, FunctionFdFilestatSetSize, ImportFdFilestatSetSize, moduleName, sysCtx) + a, mod, fn := instantiateModule(t, ctx, functionFdFilestatSetSize, importFdFilestatSetSize, moduleName, sysCtx) defer mod.Close() - t.Run("SnapshotPreview1.FdFilestatSetSize", func(t *testing.T) { + t.Run("snapshotPreview1.FdFilestatSetSize", func(t *testing.T) { errno := a.FdFilestatSetSize(mod, 0, 0) - require.Equal(t, wasi.ErrnoNosys, errno, wasi.ErrnoName(errno)) + require.Equal(t, ErrnoNosys, errno, ErrnoName(errno)) }) - t.Run(FunctionFdFilestatSetSize, func(t *testing.T) { + t.Run(functionFdFilestatSetSize, func(t *testing.T) { results, err := fn.Call(mod, 0, 0) require.NoError(t, err) - errno := wasi.Errno(results[0]) // results[0] is the errno - require.Equal(t, wasi.ErrnoNosys, errno, wasi.ErrnoName(errno)) + errno := Errno(results[0]) // results[0] is the errno + require.Equal(t, ErrnoNosys, errno, ErrnoName(errno)) }) } @@ -736,19 +739,19 @@ func TestSnapshotPreview1_FdFilestatSetTimes(t *testing.T) { sysCtx, err := newSysContext(nil, nil, nil) require.NoError(t, err) - a, mod, fn := instantiateModule(t, ctx, FunctionFdFilestatSetTimes, ImportFdFilestatSetTimes, moduleName, sysCtx) + a, mod, fn := instantiateModule(t, ctx, functionFdFilestatSetTimes, importFdFilestatSetTimes, moduleName, sysCtx) defer mod.Close() - t.Run("SnapshotPreview1.FdFilestatSetTimes", func(t *testing.T) { + t.Run("snapshotPreview1.FdFilestatSetTimes", func(t *testing.T) { errno := a.FdFilestatSetTimes(mod, 0, 0, 0, 0) - require.Equal(t, wasi.ErrnoNosys, errno, wasi.ErrnoName(errno)) + require.Equal(t, ErrnoNosys, errno, ErrnoName(errno)) }) - t.Run(FunctionFdFilestatSetTimes, func(t *testing.T) { + t.Run(functionFdFilestatSetTimes, func(t *testing.T) { results, err := fn.Call(mod, 0, 0, 0, 0) require.NoError(t, err) - errno := wasi.Errno(results[0]) // results[0] is the errno - require.Equal(t, wasi.ErrnoNosys, errno, wasi.ErrnoName(errno)) + errno := Errno(results[0]) // results[0] is the errno + require.Equal(t, ErrnoNosys, errno, ErrnoName(errno)) }) } @@ -758,19 +761,19 @@ func TestSnapshotPreview1_FdPread(t *testing.T) { sysCtx, err := newSysContext(nil, nil, nil) require.NoError(t, err) - a, mod, fn := instantiateModule(t, ctx, FunctionFdPread, ImportFdPread, moduleName, sysCtx) + a, mod, fn := instantiateModule(t, ctx, functionFdPread, importFdPread, moduleName, sysCtx) defer mod.Close() - t.Run("SnapshotPreview1.FdPread", func(t *testing.T) { + t.Run("snapshotPreview1.FdPread", func(t *testing.T) { errno := a.FdPread(mod, 0, 0, 0, 0, 0) - require.Equal(t, wasi.ErrnoNosys, errno, wasi.ErrnoName(errno)) + require.Equal(t, ErrnoNosys, errno, ErrnoName(errno)) }) - t.Run(FunctionFdPread, func(t *testing.T) { + t.Run(functionFdPread, func(t *testing.T) { results, err := fn.Call(mod, 0, 0, 0, 0, 0) require.NoError(t, err) - errno := wasi.Errno(results[0]) // results[0] is the errno - require.Equal(t, wasi.ErrnoNosys, errno, wasi.ErrnoName(errno)) + errno := Errno(results[0]) // results[0] is the errno + require.Equal(t, ErrnoNosys, errno, ErrnoName(errno)) }) } @@ -782,7 +785,7 @@ func TestSnapshotPreview1_FdPrestatGet(t *testing.T) { sysCtx, err := newSysContext(nil, nil, map[uint32]*wasm.FileEntry{fd: {Path: pathName}}) require.NoError(t, err) - a, mod, fn := instantiateModule(t, ctx, FunctionFdPrestatGet, ImportFdPrestatGet, moduleName, sysCtx) + a, mod, fn := instantiateModule(t, ctx, functionFdPrestatGet, importFdPrestatGet, moduleName, sysCtx) defer mod.Close() resultPrestat := uint32(1) // arbitrary offset @@ -795,24 +798,24 @@ func TestSnapshotPreview1_FdPrestatGet(t *testing.T) { '?', } - t.Run("SnapshotPreview1.FdPrestatGet", func(t *testing.T) { + t.Run("snapshotPreview1.FdPrestatGet", func(t *testing.T) { maskMemory(t, mod, len(expectedMemory)) errno := a.FdPrestatGet(mod, fd, resultPrestat) - require.Zero(t, errno, wasi.ErrnoName(errno)) + require.Zero(t, errno, ErrnoName(errno)) actual, ok := mod.Memory().Read(0, uint32(len(expectedMemory))) require.True(t, ok) require.Equal(t, expectedMemory, actual) }) - t.Run(FunctionFdPrestatDirName, func(t *testing.T) { + t.Run(functionFdPrestatDirName, func(t *testing.T) { maskMemory(t, mod, len(expectedMemory)) results, err := fn.Call(mod, uint64(fd), uint64(resultPrestat)) require.NoError(t, err) - errno := wasi.Errno(results[0]) // results[0] is the errno - require.Zero(t, errno, wasi.ErrnoName(errno)) + errno := Errno(results[0]) // results[0] is the errno + require.Zero(t, errno, ErrnoName(errno)) actual, ok := mod.Memory().Read(0, uint32(len(expectedMemory))) require.True(t, ok) @@ -828,7 +831,7 @@ func TestSnapshotPreview1_FdPrestatGet_Errors(t *testing.T) { sysCtx, err := newSysContext(nil, nil, map[uint32]*wasm.FileEntry{fd: {Path: "/tmp"}}) require.NoError(t, err) - a, mod, _ := instantiateModule(t, ctx, FunctionFdPrestatGet, ImportFdPrestatGet, moduleName, sysCtx) + a, mod, _ := instantiateModule(t, ctx, functionFdPrestatGet, importFdPrestatGet, moduleName, sysCtx) defer mod.Close() memorySize := mod.Memory().Size() @@ -837,21 +840,21 @@ func TestSnapshotPreview1_FdPrestatGet_Errors(t *testing.T) { name string fd uint32 resultPrestat uint32 - expectedErrno wasi.Errno + expectedErrno Errno }{ { name: "invalid FD", fd: 42, // arbitrary invalid FD resultPrestat: validAddress, - expectedErrno: wasi.ErrnoBadf, + expectedErrno: ErrnoBadf, }, { name: "out-of-memory resultPrestat", fd: fd, resultPrestat: memorySize, - expectedErrno: wasi.ErrnoFault, + expectedErrno: ErrnoFault, }, - // TODO: non pre-opened file == wasi.ErrnoBadf + // TODO: non pre-opened file == api.ErrnoBadf } for _, tt := range tests { @@ -859,7 +862,7 @@ func TestSnapshotPreview1_FdPrestatGet_Errors(t *testing.T) { t.Run(tc.name, func(t *testing.T) { errno := a.FdPrestatGet(mod, tc.fd, tc.resultPrestat) - require.Equal(t, tc.expectedErrno, errno, wasi.ErrnoName(errno)) + require.Equal(t, tc.expectedErrno, errno, ErrnoName(errno)) }) } } @@ -871,7 +874,7 @@ func TestSnapshotPreview1_FdPrestatDirName(t *testing.T) { sysCtx, err := newSysContext(nil, nil, map[uint32]*wasm.FileEntry{fd: {Path: "/tmp"}}) require.NoError(t, err) - a, mod, fn := instantiateModule(t, ctx, FunctionFdPrestatDirName, ImportFdPrestatDirName, moduleName, sysCtx) + a, mod, fn := instantiateModule(t, ctx, functionFdPrestatDirName, importFdPrestatDirName, moduleName, sysCtx) defer mod.Close() path := uint32(1) // arbitrary offset @@ -882,24 +885,24 @@ func TestSnapshotPreview1_FdPrestatDirName(t *testing.T) { '?', '?', '?', } - t.Run("SnapshotPreview1.FdPrestatDirName", func(t *testing.T) { + t.Run("snapshotPreview1.FdPrestatDirName", func(t *testing.T) { maskMemory(t, mod, len(expectedMemory)) errno := a.FdPrestatDirName(mod, fd, path, pathLen) - require.Zero(t, errno, wasi.ErrnoName(errno)) + require.Zero(t, errno, ErrnoName(errno)) actual, ok := mod.Memory().Read(0, uint32(len(expectedMemory))) require.True(t, ok) require.Equal(t, expectedMemory, actual) }) - t.Run(FunctionFdPrestatDirName, func(t *testing.T) { + t.Run(functionFdPrestatDirName, func(t *testing.T) { maskMemory(t, mod, len(expectedMemory)) results, err := fn.Call(mod, uint64(fd), uint64(path), uint64(pathLen)) require.NoError(t, err) - errno := wasi.Errno(results[0]) // results[0] is the errno - require.Zero(t, errno, wasi.ErrnoName(errno)) + errno := Errno(results[0]) // results[0] is the errno + require.Zero(t, errno, ErrnoName(errno)) actual, ok := mod.Memory().Read(0, uint32(len(expectedMemory))) require.True(t, ok) @@ -914,7 +917,7 @@ func TestSnapshotPreview1_FdPrestatDirName_Errors(t *testing.T) { sysCtx, err := newSysContext(nil, nil, map[uint32]*wasm.FileEntry{fd: {Path: "/tmp"}}) require.NoError(t, err) - a, mod, _ := instantiateModule(t, ctx, FunctionFdPrestatDirName, ImportFdPrestatDirName, moduleName, sysCtx) + a, mod, _ := instantiateModule(t, ctx, functionFdPrestatDirName, importFdPrestatDirName, moduleName, sysCtx) defer mod.Close() memorySize := mod.Memory().Size() @@ -926,35 +929,35 @@ func TestSnapshotPreview1_FdPrestatDirName_Errors(t *testing.T) { fd uint32 path uint32 pathLen uint32 - expectedErrno wasi.Errno + expectedErrno Errno }{ { name: "out-of-memory path", fd: fd, path: memorySize, pathLen: pathLen, - expectedErrno: wasi.ErrnoFault, + expectedErrno: ErrnoFault, }, { name: "path exceeds the maximum valid address by 1", fd: fd, path: memorySize - pathLen + 1, pathLen: pathLen, - expectedErrno: wasi.ErrnoFault, + expectedErrno: ErrnoFault, }, { name: "pathLen exceeds the length of the dir name", fd: fd, path: validAddress, pathLen: pathLen + 1, - expectedErrno: wasi.ErrnoNametoolong, + expectedErrno: ErrnoNametoolong, }, { name: "invalid fd", fd: 42, // arbitrary invalid fd path: validAddress, pathLen: pathLen, - expectedErrno: wasi.ErrnoBadf, + expectedErrno: ErrnoBadf, }, // TODO: non pre-opened file == wasi.ErrnoBadf } @@ -964,7 +967,7 @@ func TestSnapshotPreview1_FdPrestatDirName_Errors(t *testing.T) { t.Run(tc.name, func(t *testing.T) { errno := a.FdPrestatDirName(mod, tc.fd, tc.path, tc.pathLen) - require.Equal(t, tc.expectedErrno, errno, wasi.ErrnoName(errno)) + require.Equal(t, tc.expectedErrno, errno, ErrnoName(errno)) }) } } @@ -975,19 +978,19 @@ func TestSnapshotPreview1_FdPwrite(t *testing.T) { sysCtx, err := newSysContext(nil, nil, nil) require.NoError(t, err) - a, mod, fn := instantiateModule(t, ctx, FunctionFdPwrite, ImportFdPwrite, moduleName, sysCtx) + a, mod, fn := instantiateModule(t, ctx, functionFdPwrite, importFdPwrite, moduleName, sysCtx) defer mod.Close() - t.Run("SnapshotPreview1.FdPwrite", func(t *testing.T) { + t.Run("snapshotPreview1.FdPwrite", func(t *testing.T) { errno := a.FdPwrite(mod, 0, 0, 0, 0, 0) - require.Equal(t, wasi.ErrnoNosys, errno, wasi.ErrnoName(errno)) + require.Equal(t, ErrnoNosys, errno, ErrnoName(errno)) }) - t.Run(FunctionFdPwrite, func(t *testing.T) { + t.Run(functionFdPwrite, func(t *testing.T) { results, err := fn.Call(mod, 0, 0, 0, 0, 0) require.NoError(t, err) - errno := wasi.Errno(results[0]) // results[0] is the errno - require.Equal(t, wasi.ErrnoNosys, errno, wasi.ErrnoName(errno)) + errno := Errno(results[0]) // results[0] is the errno + require.Equal(t, ErrnoNosys, errno, ErrnoName(errno)) }) } @@ -1017,19 +1020,19 @@ func TestSnapshotPreview1_FdRead(t *testing.T) { ) // TestSnapshotPreview1_FdRead uses a matrix because setting up test files is complicated and has to be clean each time. - type fdReadFn func(ctx publicwasm.Module, fd, iovs, iovsCount, resultSize uint32) wasi.Errno + type fdReadFn func(ctx api.Module, fd, iovs, iovsCount, resultSize uint32) Errno tests := []struct { name string - fdRead func(*wasiAPI, *wasm.ModuleContext, publicwasm.Function) fdReadFn + fdRead func(*wasiAPI, *wasm.ModuleContext, api.Function) fdReadFn }{ - {"SnapshotPreview1.FdRead", func(a *wasiAPI, _ *wasm.ModuleContext, _ publicwasm.Function) fdReadFn { + {"snapshotPreview1.FdRead", func(a *wasiAPI, _ *wasm.ModuleContext, _ api.Function) fdReadFn { return a.FdRead }}, - {FunctionFdRead, func(_ *wasiAPI, mod *wasm.ModuleContext, fn publicwasm.Function) fdReadFn { - return func(ctx publicwasm.Module, fd, iovs, iovsCount, resultSize uint32) wasi.Errno { + {functionFdRead, func(_ *wasiAPI, mod *wasm.ModuleContext, fn api.Function) fdReadFn { + return func(ctx api.Module, fd, iovs, iovsCount, resultSize uint32) Errno { results, err := fn.Call(mod, uint64(fd), uint64(iovs), uint64(iovsCount), uint64(resultSize)) require.NoError(t, err) - return wasi.Errno(results[0]) + return Errno(results[0]) } }}, } @@ -1044,7 +1047,7 @@ func TestSnapshotPreview1_FdRead(t *testing.T) { }) require.NoError(t, err) - a, mod, fn := instantiateModule(t, ctx, FunctionFdRead, ImportFdRead, moduleName, sysCtx) + a, mod, fn := instantiateModule(t, ctx, functionFdRead, importFdRead, moduleName, sysCtx) defer mod.Close() maskMemory(t, mod, len(expectedMemory)) @@ -1053,7 +1056,7 @@ func TestSnapshotPreview1_FdRead(t *testing.T) { require.True(t, ok) errno := tc.fdRead(a, mod, fn)(mod, fd, iovs, iovsCount, resultSize) - require.Zero(t, errno, wasi.ErrnoName(errno)) + require.Zero(t, errno, ErrnoName(errno)) actual, ok := mod.Memory().Read(0, uint32(len(expectedMemory))) require.True(t, ok) @@ -1072,26 +1075,26 @@ func TestSnapshotPreview1_FdRead_Errors(t *testing.T) { }) require.NoError(t, err) - a, mod, _ := instantiateModule(t, ctx, FunctionFdRead, ImportFdRead, moduleName, sysCtx) + a, mod, _ := instantiateModule(t, ctx, functionFdRead, importFdRead, moduleName, sysCtx) defer mod.Close() tests := []struct { name string fd, iovs, iovsCount, resultSize uint32 memory []byte - expectedErrno wasi.Errno + expectedErrno Errno }{ { name: "invalid fd", fd: 42, // arbitrary invalid fd - expectedErrno: wasi.ErrnoBadf, + expectedErrno: ErrnoBadf, }, { name: "out-of-memory reading iovs[0].offset", fd: validFD, iovs: 1, memory: []byte{'?'}, - expectedErrno: wasi.ErrnoFault, + expectedErrno: ErrnoFault, }, { name: "out-of-memory reading iovs[0].length", @@ -1101,7 +1104,7 @@ func TestSnapshotPreview1_FdRead_Errors(t *testing.T) { '?', // `iovs` is after this 9, 0, 0, 0, // = iovs[0].offset }, - expectedErrno: wasi.ErrnoFault, + expectedErrno: ErrnoFault, }, { name: "iovs[0].offset is outside memory", @@ -1112,7 +1115,7 @@ func TestSnapshotPreview1_FdRead_Errors(t *testing.T) { 0, 0, 0x1, 0, // = iovs[0].offset on the second page 1, 0, 0, 0, // = iovs[0].length }, - expectedErrno: wasi.ErrnoFault, + expectedErrno: ErrnoFault, }, { name: "length to read exceeds memory by 1", @@ -1124,7 +1127,7 @@ func TestSnapshotPreview1_FdRead_Errors(t *testing.T) { 0, 0, 0x1, 0, // = iovs[0].length on the second page '?', }, - expectedErrno: wasi.ErrnoFault, + expectedErrno: ErrnoFault, }, { name: "resultSize offset is outside memory", @@ -1137,7 +1140,7 @@ func TestSnapshotPreview1_FdRead_Errors(t *testing.T) { 1, 0, 0, 0, // = iovs[0].length '?', }, - expectedErrno: wasi.ErrnoFault, + expectedErrno: ErrnoFault, }, } @@ -1150,7 +1153,7 @@ func TestSnapshotPreview1_FdRead_Errors(t *testing.T) { require.True(t, memoryWriteOK) errno := a.FdRead(mod, tc.fd, tc.iovs+offset, tc.iovsCount+offset, tc.resultSize+offset) - require.Equal(t, tc.expectedErrno, errno, wasi.ErrnoName(errno)) + require.Equal(t, tc.expectedErrno, errno, ErrnoName(errno)) }) } } @@ -1161,19 +1164,19 @@ func TestSnapshotPreview1_FdReaddir(t *testing.T) { sysCtx, err := newSysContext(nil, nil, nil) require.NoError(t, err) - a, mod, fn := instantiateModule(t, ctx, FunctionFdReaddir, ImportFdReaddir, moduleName, sysCtx) + a, mod, fn := instantiateModule(t, ctx, functionFdReaddir, importFdReaddir, moduleName, sysCtx) defer mod.Close() - t.Run("SnapshotPreview1.FdReaddir", func(t *testing.T) { + t.Run("snapshotPreview1.FdReaddir", func(t *testing.T) { errno := a.FdReaddir(mod, 0, 0, 0, 0, 0) - require.Equal(t, wasi.ErrnoNosys, errno, wasi.ErrnoName(errno)) + require.Equal(t, ErrnoNosys, errno, ErrnoName(errno)) }) - t.Run(FunctionFdReaddir, func(t *testing.T) { + t.Run(functionFdReaddir, func(t *testing.T) { results, err := fn.Call(mod, 0, 0, 0, 0, 0) require.NoError(t, err) - errno := wasi.Errno(results[0]) // results[0] is the errno - require.Equal(t, wasi.ErrnoNosys, errno, wasi.ErrnoName(errno)) + errno := Errno(results[0]) // results[0] is the errno + require.Equal(t, ErrnoNosys, errno, ErrnoName(errno)) }) } @@ -1183,19 +1186,19 @@ func TestSnapshotPreview1_FdRenumber(t *testing.T) { sysCtx, err := newSysContext(nil, nil, nil) require.NoError(t, err) - a, mod, fn := instantiateModule(t, ctx, FunctionFdRenumber, ImportFdRenumber, moduleName, sysCtx) + a, mod, fn := instantiateModule(t, ctx, functionFdRenumber, importFdRenumber, moduleName, sysCtx) defer mod.Close() - t.Run("SnapshotPreview1.FdRenumber", func(t *testing.T) { + t.Run("snapshotPreview1.FdRenumber", func(t *testing.T) { errno := a.FdRenumber(mod, 0, 0) - require.Equal(t, wasi.ErrnoNosys, errno, wasi.ErrnoName(errno)) + require.Equal(t, ErrnoNosys, errno, ErrnoName(errno)) }) - t.Run(FunctionFdRenumber, func(t *testing.T) { + t.Run(functionFdRenumber, func(t *testing.T) { results, err := fn.Call(mod, 0, 0) require.NoError(t, err) - errno := wasi.Errno(results[0]) // results[0] is the errno - require.Equal(t, wasi.ErrnoNosys, errno, wasi.ErrnoName(errno)) + errno := Errno(results[0]) // results[0] is the errno + require.Equal(t, ErrnoNosys, errno, ErrnoName(errno)) }) } @@ -1210,23 +1213,23 @@ func TestSnapshotPreview1_FdSeek(t *testing.T) { }) require.NoError(t, err) - a, mod, fn := instantiateModule(t, ctx, FunctionFdSeek, ImportFdSeek, moduleName, sysCtx) + a, mod, fn := instantiateModule(t, ctx, functionFdSeek, importFdSeek, moduleName, sysCtx) defer mod.Close() // TestSnapshotPreview1_FdSeek uses a matrix because setting up test files is complicated and has to be clean each time. - type fdSeekFn func(ctx publicwasm.Module, fd uint32, offset uint64, whence, resultNewOffset uint32) wasi.Errno + type fdSeekFn func(ctx api.Module, fd uint32, offset uint64, whence, resultNewOffset uint32) Errno seekFns := []struct { name string fdSeek func() fdSeekFn }{ - {"SnapshotPreview1.FdSeek", func() fdSeekFn { + {"snapshotPreview1.FdSeek", func() fdSeekFn { return a.FdSeek }}, - {FunctionFdSeek, func() fdSeekFn { - return func(ctx publicwasm.Module, fd uint32, offset uint64, whence, resultNewoffset uint32) wasi.Errno { + {functionFdSeek, func() fdSeekFn { + return func(ctx api.Module, fd uint32, offset uint64, whence, resultNewoffset uint32) Errno { results, err := fn.Call(mod, uint64(fd), offset, uint64(whence), uint64(resultNewoffset)) require.NoError(t, err) - return wasi.Errno(results[0]) + return Errno(results[0]) } }}, } @@ -1292,7 +1295,7 @@ func TestSnapshotPreview1_FdSeek(t *testing.T) { require.Equal(t, int64(1), offset) errno := sf.fdSeek()(mod, fd, uint64(tc.offset), uint32(tc.whence), resultNewoffset) - require.Zero(t, errno, wasi.ErrnoName(errno)) + require.Zero(t, errno, ErrnoName(errno)) actual, ok := mod.Memory().Read(0, uint32(len(tc.expectedMemory))) require.True(t, ok) @@ -1316,7 +1319,7 @@ func TestSnapshotPreview1_FdSeek_Errors(t *testing.T) { }) require.NoError(t, err) - a, mod, _ := instantiateModule(t, ctx, FunctionFdSeek, ImportFdSeek, moduleName, sysCtx) + a, mod, _ := instantiateModule(t, ctx, functionFdSeek, importFdSeek, moduleName, sysCtx) defer mod.Close() memorySize := mod.Memory().Size() @@ -1326,24 +1329,24 @@ func TestSnapshotPreview1_FdSeek_Errors(t *testing.T) { fd uint32 offset uint64 whence, resultNewoffset uint32 - expectedErrno wasi.Errno + expectedErrno Errno }{ { name: "invalid fd", fd: 42, // arbitrary invalid fd - expectedErrno: wasi.ErrnoBadf, + expectedErrno: ErrnoBadf, }, { name: "invalid whence", fd: validFD, whence: 3, // invalid whence, the largest whence io.SeekEnd(2) + 1 - expectedErrno: wasi.ErrnoInval, + expectedErrno: ErrnoInval, }, { name: "out-of-memory writing resultNewoffset", fd: validFD, resultNewoffset: memorySize, - expectedErrno: wasi.ErrnoFault, + expectedErrno: ErrnoFault, }, } @@ -1351,7 +1354,7 @@ func TestSnapshotPreview1_FdSeek_Errors(t *testing.T) { tc := tt t.Run(tc.name, func(t *testing.T) { errno := a.FdSeek(mod, tc.fd, tc.offset, tc.whence, tc.resultNewoffset) - require.Equal(t, tc.expectedErrno, errno, wasi.ErrnoName(errno)) + require.Equal(t, tc.expectedErrno, errno, ErrnoName(errno)) }) } @@ -1363,19 +1366,19 @@ func TestSnapshotPreview1_FdSync(t *testing.T) { sysCtx, err := newSysContext(nil, nil, nil) require.NoError(t, err) - a, mod, fn := instantiateModule(t, ctx, FunctionFdSync, ImportFdSync, moduleName, sysCtx) + a, mod, fn := instantiateModule(t, ctx, functionFdSync, importFdSync, moduleName, sysCtx) defer mod.Close() - t.Run("SnapshotPreview1.FdSync", func(t *testing.T) { + t.Run("snapshotPreview1.FdSync", func(t *testing.T) { errno := a.FdSync(mod, 0) - require.Equal(t, wasi.ErrnoNosys, errno, wasi.ErrnoName(errno)) + require.Equal(t, ErrnoNosys, errno, ErrnoName(errno)) }) - t.Run(FunctionFdSync, func(t *testing.T) { + t.Run(functionFdSync, func(t *testing.T) { results, err := fn.Call(mod, 0) require.NoError(t, err) - errno := wasi.Errno(results[0]) // results[0] is the errno - require.Equal(t, wasi.ErrnoNosys, errno, wasi.ErrnoName(errno)) + errno := Errno(results[0]) // results[0] is the errno + require.Equal(t, ErrnoNosys, errno, ErrnoName(errno)) }) } @@ -1385,19 +1388,19 @@ func TestSnapshotPreview1_FdTell(t *testing.T) { sysCtx, err := newSysContext(nil, nil, nil) require.NoError(t, err) - a, mod, fn := instantiateModule(t, ctx, FunctionFdTell, ImportFdTell, moduleName, sysCtx) + a, mod, fn := instantiateModule(t, ctx, functionFdTell, importFdTell, moduleName, sysCtx) defer mod.Close() - t.Run("SnapshotPreview1.FdTell", func(t *testing.T) { + t.Run("snapshotPreview1.FdTell", func(t *testing.T) { errno := a.FdTell(mod, 0, 0) - require.Equal(t, wasi.ErrnoNosys, errno, wasi.ErrnoName(errno)) + require.Equal(t, ErrnoNosys, errno, ErrnoName(errno)) }) - t.Run(FunctionFdTell, func(t *testing.T) { + t.Run(functionFdTell, func(t *testing.T) { results, err := fn.Call(mod, 0, 0) require.NoError(t, err) - errno := wasi.Errno(results[0]) // results[0] is the errno - require.Equal(t, wasi.ErrnoNosys, errno, wasi.ErrnoName(errno)) + errno := Errno(results[0]) // results[0] is the errno + require.Equal(t, ErrnoNosys, errno, ErrnoName(errno)) }) } @@ -1427,19 +1430,19 @@ func TestSnapshotPreview1_FdWrite(t *testing.T) { ) // TestSnapshotPreview1_FdWrite uses a matrix because setting up test files is complicated and has to be clean each time. - type fdWriteFn func(ctx publicwasm.Module, fd, iovs, iovsCount, resultSize uint32) wasi.Errno + type fdWriteFn func(ctx api.Module, fd, iovs, iovsCount, resultSize uint32) Errno tests := []struct { name string - fdWrite func(*wasiAPI, *wasm.ModuleContext, publicwasm.Function) fdWriteFn + fdWrite func(*wasiAPI, *wasm.ModuleContext, api.Function) fdWriteFn }{ - {"SnapshotPreview1.FdWrite", func(a *wasiAPI, _ *wasm.ModuleContext, _ publicwasm.Function) fdWriteFn { + {"snapshotPreview1.FdWrite", func(a *wasiAPI, _ *wasm.ModuleContext, _ api.Function) fdWriteFn { return a.FdWrite }}, - {FunctionFdWrite, func(_ *wasiAPI, mod *wasm.ModuleContext, fn publicwasm.Function) fdWriteFn { - return func(ctx publicwasm.Module, fd, iovs, iovsCount, resultSize uint32) wasi.Errno { + {functionFdWrite, func(_ *wasiAPI, mod *wasm.ModuleContext, fn api.Function) fdWriteFn { + return func(ctx api.Module, fd, iovs, iovsCount, resultSize uint32) Errno { results, err := fn.Call(mod, uint64(fd), uint64(iovs), uint64(iovsCount), uint64(resultSize)) require.NoError(t, err) - return wasi.Errno(results[0]) + return Errno(results[0]) } }}, } @@ -1457,7 +1460,7 @@ func TestSnapshotPreview1_FdWrite(t *testing.T) { }) require.NoError(t, err) - a, mod, fn := instantiateModule(t, ctx, FunctionFdWrite, ImportFdWrite, moduleName, sysCtx) + a, mod, fn := instantiateModule(t, ctx, functionFdWrite, importFdWrite, moduleName, sysCtx) defer mod.Close() maskMemory(t, mod, len(expectedMemory)) @@ -1465,7 +1468,7 @@ func TestSnapshotPreview1_FdWrite(t *testing.T) { require.True(t, ok) errno := tc.fdWrite(a, mod, fn)(mod, fd, iovs, iovsCount, resultSize) - require.Zero(t, errno, wasi.ErrnoName(errno)) + require.Zero(t, errno, ErrnoName(errno)) actual, ok := mod.Memory().Read(0, uint32(len(expectedMemory))) require.True(t, ok) @@ -1493,7 +1496,7 @@ func TestSnapshotPreview1_FdWrite_Errors(t *testing.T) { }) require.NoError(t, err) - a, mod, _ := instantiateModule(t, ctx, FunctionFdWrite, ImportFdWrite, moduleName, sysCtx) + a, mod, _ := instantiateModule(t, ctx, functionFdWrite, importFdWrite, moduleName, sysCtx) defer mod.Close() // Setup valid test memory @@ -1508,43 +1511,43 @@ func TestSnapshotPreview1_FdWrite_Errors(t *testing.T) { name string fd, resultSize uint32 memory []byte - expectedErrno wasi.Errno + expectedErrno Errno }{ { name: "invalid fd", fd: 42, // arbitrary invalid fd - expectedErrno: wasi.ErrnoBadf, + expectedErrno: ErrnoBadf, }, { name: "out-of-memory reading iovs[0].offset", fd: validFD, memory: []byte{}, - expectedErrno: wasi.ErrnoFault, + expectedErrno: ErrnoFault, }, { name: "out-of-memory reading iovs[0].length", fd: validFD, memory: memory[0:4], // iovs[0].offset was 4 bytes and iovs[0].length next, but not enough mod.Memory()! - expectedErrno: wasi.ErrnoFault, + expectedErrno: ErrnoFault, }, { name: "iovs[0].offset is outside memory", fd: validFD, memory: memory[0:8], // iovs[0].offset (where to read "hi") is outside memory. - expectedErrno: wasi.ErrnoFault, + expectedErrno: ErrnoFault, }, { name: "length to read exceeds memory by 1", fd: validFD, memory: memory[0:9], // iovs[0].offset (where to read "hi") is in memory, but truncated. - expectedErrno: wasi.ErrnoFault, + expectedErrno: ErrnoFault, }, { name: "resultSize offset is outside memory", fd: validFD, memory: memory, resultSize: uint32(len(memory)), // read was ok, but there wasn't enough memory to write the result. - expectedErrno: wasi.ErrnoFault, + expectedErrno: ErrnoFault, }, } @@ -1554,7 +1557,7 @@ func TestSnapshotPreview1_FdWrite_Errors(t *testing.T) { mod.Memory().(*wasm.MemoryInstance).Buffer = tc.memory errno := a.FdWrite(mod, tc.fd, iovs, iovsCount, tc.resultSize) - require.Equal(t, tc.expectedErrno, errno, wasi.ErrnoName(errno)) + require.Equal(t, tc.expectedErrno, errno, ErrnoName(errno)) }) } } @@ -1565,19 +1568,19 @@ func TestSnapshotPreview1_PathCreateDirectory(t *testing.T) { sysCtx, err := newSysContext(nil, nil, nil) require.NoError(t, err) - a, mod, fn := instantiateModule(t, ctx, FunctionPathCreateDirectory, ImportPathCreateDirectory, moduleName, sysCtx) + a, mod, fn := instantiateModule(t, ctx, functionPathCreateDirectory, importPathCreateDirectory, moduleName, sysCtx) defer mod.Close() - t.Run("SnapshotPreview1.PathCreateDirectory", func(t *testing.T) { + t.Run("snapshotPreview1.PathCreateDirectory", func(t *testing.T) { errno := a.PathCreateDirectory(mod, 0, 0, 0) - require.Equal(t, wasi.ErrnoNosys, errno, wasi.ErrnoName(errno)) + require.Equal(t, ErrnoNosys, errno, ErrnoName(errno)) }) - t.Run(FunctionPathCreateDirectory, func(t *testing.T) { + t.Run(functionPathCreateDirectory, func(t *testing.T) { results, err := fn.Call(mod, 0, 0, 0) require.NoError(t, err) - errno := wasi.Errno(results[0]) // results[0] is the errno - require.Equal(t, wasi.ErrnoNosys, errno, wasi.ErrnoName(errno)) + errno := Errno(results[0]) // results[0] is the errno + require.Equal(t, ErrnoNosys, errno, ErrnoName(errno)) }) } @@ -1587,19 +1590,19 @@ func TestSnapshotPreview1_PathFilestatGet(t *testing.T) { sysCtx, err := newSysContext(nil, nil, nil) require.NoError(t, err) - a, mod, fn := instantiateModule(t, ctx, FunctionPathFilestatGet, ImportPathFilestatGet, moduleName, sysCtx) + a, mod, fn := instantiateModule(t, ctx, functionPathFilestatGet, importPathFilestatGet, moduleName, sysCtx) defer mod.Close() - t.Run("SnapshotPreview1.PathFilestatGet", func(t *testing.T) { + t.Run("snapshotPreview1.PathFilestatGet", func(t *testing.T) { errno := a.PathFilestatGet(mod, 0, 0, 0, 0, 0) - require.Equal(t, wasi.ErrnoNosys, errno, wasi.ErrnoName(errno)) + require.Equal(t, ErrnoNosys, errno, ErrnoName(errno)) }) - t.Run(FunctionPathFilestatGet, func(t *testing.T) { + t.Run(functionPathFilestatGet, func(t *testing.T) { results, err := fn.Call(mod, 0, 0, 0, 0, 0) require.NoError(t, err) - errno := wasi.Errno(results[0]) // results[0] is the errno - require.Equal(t, wasi.ErrnoNosys, errno, wasi.ErrnoName(errno)) + errno := Errno(results[0]) // results[0] is the errno + require.Equal(t, ErrnoNosys, errno, ErrnoName(errno)) }) } @@ -1609,19 +1612,19 @@ func TestSnapshotPreview1_PathFilestatSetTimes(t *testing.T) { sysCtx, err := newSysContext(nil, nil, nil) require.NoError(t, err) - a, mod, fn := instantiateModule(t, ctx, FunctionPathFilestatSetTimes, ImportPathFilestatSetTimes, moduleName, sysCtx) + a, mod, fn := instantiateModule(t, ctx, functionPathFilestatSetTimes, importPathFilestatSetTimes, moduleName, sysCtx) defer mod.Close() - t.Run("SnapshotPreview1.PathFilestatSetTimes", func(t *testing.T) { + t.Run("snapshotPreview1.PathFilestatSetTimes", func(t *testing.T) { errno := a.PathFilestatSetTimes(mod, 0, 0, 0, 0, 0, 0, 0) - require.Equal(t, wasi.ErrnoNosys, errno, wasi.ErrnoName(errno)) + require.Equal(t, ErrnoNosys, errno, ErrnoName(errno)) }) - t.Run(FunctionPathFilestatSetTimes, func(t *testing.T) { + t.Run(functionPathFilestatSetTimes, func(t *testing.T) { results, err := fn.Call(mod, 0, 0, 0, 0, 0, 0, 0) require.NoError(t, err) - errno := wasi.Errno(results[0]) // results[0] is the errno - require.Equal(t, wasi.ErrnoNosys, errno, wasi.ErrnoName(errno)) + errno := Errno(results[0]) // results[0] is the errno + require.Equal(t, ErrnoNosys, errno, ErrnoName(errno)) }) } @@ -1631,19 +1634,19 @@ func TestSnapshotPreview1_PathLink(t *testing.T) { sysCtx, err := newSysContext(nil, nil, nil) require.NoError(t, err) - a, mod, fn := instantiateModule(t, ctx, FunctionPathLink, ImportPathLink, moduleName, sysCtx) + a, mod, fn := instantiateModule(t, ctx, functionPathLink, importPathLink, moduleName, sysCtx) defer mod.Close() - t.Run("SnapshotPreview1.PathLink", func(t *testing.T) { + t.Run("snapshotPreview1.PathLink", func(t *testing.T) { errno := a.PathLink(mod, 0, 0, 0, 0, 0, 0, 0) - require.Equal(t, wasi.ErrnoNosys, errno, wasi.ErrnoName(errno)) + require.Equal(t, ErrnoNosys, errno, ErrnoName(errno)) }) - t.Run(FunctionPathLink, func(t *testing.T) { + t.Run(functionPathLink, func(t *testing.T) { results, err := fn.Call(mod, 0, 0, 0, 0, 0, 0, 0) require.NoError(t, err) - errno := wasi.Errno(results[0]) // results[0] is the errno - require.Equal(t, wasi.ErrnoNosys, errno, wasi.ErrnoName(errno)) + errno := Errno(results[0]) // results[0] is the errno + require.Equal(t, ErrnoNosys, errno, ErrnoName(errno)) }) } @@ -1673,21 +1676,21 @@ func TestSnapshotPreview1_PathOpen(t *testing.T) { // rights are ignored per https://github.com/WebAssembly/WASI/issues/469#issuecomment-1045251844 fsRightsBase, fsRightsInheriting := uint64(1), uint64(2) - setup := func() (*wasiAPI, *wasm.ModuleContext, publicwasm.Function) { + setup := func() (*wasiAPI, *wasm.ModuleContext, api.Function) { testFS := fstest.MapFS{pathName: &fstest.MapFile{Mode: os.ModeDir}} sysCtx, err := newSysContext(nil, nil, map[uint32]*wasm.FileEntry{ workdirFD: {Path: ".", FS: testFS}, }) require.NoError(t, err) - a, mod, fn := instantiateModule(t, ctx, FunctionPathOpen, ImportPathOpen, moduleName, sysCtx) + a, mod, fn := instantiateModule(t, ctx, functionPathOpen, importPathOpen, moduleName, sysCtx) maskMemory(t, mod, len(expectedMemory)) ok := mod.Memory().Write(0, initialMemory) require.True(t, ok) return a, mod, fn } - verify := func(errno wasi.Errno, mod *wasm.ModuleContext) { - require.Zero(t, errno, wasi.ErrnoName(errno)) + verify := func(errno Errno, mod *wasm.ModuleContext) { + require.Zero(t, errno, ErrnoName(errno)) actual, ok := mod.Memory().Read(0, uint32(len(expectedMemory))) require.True(t, ok) @@ -1699,17 +1702,17 @@ func TestSnapshotPreview1_PathOpen(t *testing.T) { require.Equal(t, pathName, f.Path) } - t.Run("SnapshotPreview1.PathOpen", func(t *testing.T) { + t.Run("snapshotPreview1.PathOpen", func(t *testing.T) { a, mod, _ := setup() errno := a.PathOpen(mod, workdirFD, dirflags, path, pathLen, oflags, fsRightsBase, fsRightsInheriting, fdFlags, resultOpenedFd) verify(errno, mod) }) - t.Run(FunctionPathOpen, func(t *testing.T) { + t.Run(functionPathOpen, func(t *testing.T) { _, mod, fn := setup() results, err := fn.Call(mod, uint64(workdirFD), uint64(dirflags), uint64(path), uint64(pathLen), uint64(oflags), fsRightsBase, fsRightsInheriting, uint64(fdFlags), uint64(resultOpenedFd)) require.NoError(t, err) - errno := wasi.Errno(results[0]) + errno := Errno(results[0]) verify(errno, mod) }) } @@ -1725,7 +1728,7 @@ func TestSnapshotPreview1_PathOpen_Errors(t *testing.T) { }) require.NoError(t, err) - a, mod, _ := instantiateModule(t, ctx, FunctionPathOpen, ImportPathOpen, moduleName, sysCtx) + a, mod, _ := instantiateModule(t, ctx, functionPathOpen, importPathOpen, moduleName, sysCtx) defer mod.Close() validPath := uint32(0) // arbitrary offset @@ -1735,33 +1738,33 @@ func TestSnapshotPreview1_PathOpen_Errors(t *testing.T) { tests := []struct { name string fd, path, pathLen, oflags, resultOpenedFd uint32 - expectedErrno wasi.Errno + expectedErrno Errno }{ { name: "invalid fd", fd: 42, // arbitrary invalid fd - expectedErrno: wasi.ErrnoBadf, + expectedErrno: ErrnoBadf, }, { name: "out-of-memory reading path", fd: validFD, path: mod.Memory().Size(), pathLen: validPathLen, - expectedErrno: wasi.ErrnoFault, + expectedErrno: ErrnoFault, }, { name: "out-of-memory reading pathLen", fd: validFD, path: validPath, pathLen: mod.Memory().Size() + 1, // path is in the valid memory range, but pathLen is out-of-memory for path - expectedErrno: wasi.ErrnoFault, + expectedErrno: ErrnoFault, }, { name: "no such file exists", fd: validFD, path: validPath, pathLen: validPathLen - 1, // this make the path "wazer", which doesn't exit - expectedErrno: wasi.ErrnoNoent, + expectedErrno: ErrnoNoent, }, { name: "out-of-memory writing resultOpenedFd", @@ -1769,7 +1772,7 @@ func TestSnapshotPreview1_PathOpen_Errors(t *testing.T) { path: validPath, pathLen: validPathLen, resultOpenedFd: mod.Memory().Size(), // path and pathLen correctly point to the right path, but where to write the opened FD is outside memory. - expectedErrno: wasi.ErrnoFault, + expectedErrno: ErrnoFault, }, } @@ -1777,7 +1780,7 @@ func TestSnapshotPreview1_PathOpen_Errors(t *testing.T) { tc := tt t.Run(tc.name, func(t *testing.T) { errno := a.PathOpen(mod, tc.fd, 0, tc.path, tc.pathLen, tc.oflags, 0, 0, 0, tc.resultOpenedFd) - require.Equal(t, tc.expectedErrno, errno, wasi.ErrnoName(errno)) + require.Equal(t, tc.expectedErrno, errno, ErrnoName(errno)) }) } } @@ -1788,19 +1791,19 @@ func TestSnapshotPreview1_PathReadlink(t *testing.T) { sysCtx, err := newSysContext(nil, nil, nil) require.NoError(t, err) - a, mod, fn := instantiateModule(t, ctx, FunctionPathReadlink, ImportPathReadlink, moduleName, sysCtx) + a, mod, fn := instantiateModule(t, ctx, functionPathReadlink, importPathReadlink, moduleName, sysCtx) defer mod.Close() - t.Run("SnapshotPreview1.PathLink", func(t *testing.T) { + t.Run("snapshotPreview1.PathLink", func(t *testing.T) { errno := a.PathReadlink(mod, 0, 0, 0, 0, 0, 0) - require.Equal(t, wasi.ErrnoNosys, errno, wasi.ErrnoName(errno)) + require.Equal(t, ErrnoNosys, errno, ErrnoName(errno)) }) - t.Run(FunctionPathReadlink, func(t *testing.T) { + t.Run(functionPathReadlink, func(t *testing.T) { results, err := fn.Call(mod, 0, 0, 0, 0, 0, 0) require.NoError(t, err) - errno := wasi.Errno(results[0]) // results[0] is the errno - require.Equal(t, wasi.ErrnoNosys, errno, wasi.ErrnoName(errno)) + errno := Errno(results[0]) // results[0] is the errno + require.Equal(t, ErrnoNosys, errno, ErrnoName(errno)) }) } @@ -1810,19 +1813,19 @@ func TestSnapshotPreview1_PathRemoveDirectory(t *testing.T) { sysCtx, err := newSysContext(nil, nil, nil) require.NoError(t, err) - a, mod, fn := instantiateModule(t, ctx, FunctionPathRemoveDirectory, ImportPathRemoveDirectory, moduleName, sysCtx) + a, mod, fn := instantiateModule(t, ctx, functionPathRemoveDirectory, importPathRemoveDirectory, moduleName, sysCtx) defer mod.Close() - t.Run("SnapshotPreview1.PathRemoveDirectory", func(t *testing.T) { + t.Run("snapshotPreview1.PathRemoveDirectory", func(t *testing.T) { errno := a.PathRemoveDirectory(mod, 0, 0, 0) - require.Equal(t, wasi.ErrnoNosys, errno, wasi.ErrnoName(errno)) + require.Equal(t, ErrnoNosys, errno, ErrnoName(errno)) }) - t.Run(FunctionPathRemoveDirectory, func(t *testing.T) { + t.Run(functionPathRemoveDirectory, func(t *testing.T) { results, err := fn.Call(mod, 0, 0, 0) require.NoError(t, err) - errno := wasi.Errno(results[0]) // results[0] is the errno - require.Equal(t, wasi.ErrnoNosys, errno, wasi.ErrnoName(errno)) + errno := Errno(results[0]) // results[0] is the errno + require.Equal(t, ErrnoNosys, errno, ErrnoName(errno)) }) } @@ -1832,19 +1835,19 @@ func TestSnapshotPreview1_PathRename(t *testing.T) { sysCtx, err := newSysContext(nil, nil, nil) require.NoError(t, err) - a, mod, fn := instantiateModule(t, ctx, FunctionPathRename, ImportPathRename, moduleName, sysCtx) + a, mod, fn := instantiateModule(t, ctx, functionPathRename, importPathRename, moduleName, sysCtx) defer mod.Close() - t.Run("SnapshotPreview1.PathRename", func(t *testing.T) { + t.Run("snapshotPreview1.PathRename", func(t *testing.T) { errno := a.PathRename(mod, 0, 0, 0, 0, 0, 0) - require.Equal(t, wasi.ErrnoNosys, errno, wasi.ErrnoName(errno)) + require.Equal(t, ErrnoNosys, errno, ErrnoName(errno)) }) - t.Run(FunctionPathRename, func(t *testing.T) { + t.Run(functionPathRename, func(t *testing.T) { results, err := fn.Call(mod, 0, 0, 0, 0, 0, 0) require.NoError(t, err) - errno := wasi.Errno(results[0]) // results[0] is the errno - require.Equal(t, wasi.ErrnoNosys, errno, wasi.ErrnoName(errno)) + errno := Errno(results[0]) // results[0] is the errno + require.Equal(t, ErrnoNosys, errno, ErrnoName(errno)) }) } @@ -1854,19 +1857,19 @@ func TestSnapshotPreview1_PathSymlink(t *testing.T) { sysCtx, err := newSysContext(nil, nil, nil) require.NoError(t, err) - a, mod, fn := instantiateModule(t, ctx, FunctionPathSymlink, ImportPathSymlink, moduleName, sysCtx) + a, mod, fn := instantiateModule(t, ctx, functionPathSymlink, importPathSymlink, moduleName, sysCtx) defer mod.Close() - t.Run("SnapshotPreview1.PathSymlink", func(t *testing.T) { + t.Run("snapshotPreview1.PathSymlink", func(t *testing.T) { errno := a.PathSymlink(mod, 0, 0, 0, 0, 0) - require.Equal(t, wasi.ErrnoNosys, errno, wasi.ErrnoName(errno)) + require.Equal(t, ErrnoNosys, errno, ErrnoName(errno)) }) - t.Run(FunctionPathSymlink, func(t *testing.T) { + t.Run(functionPathSymlink, func(t *testing.T) { results, err := fn.Call(mod, 0, 0, 0, 0, 0) require.NoError(t, err) - errno := wasi.Errno(results[0]) // results[0] is the errno - require.Equal(t, wasi.ErrnoNosys, errno, wasi.ErrnoName(errno)) + errno := Errno(results[0]) // results[0] is the errno + require.Equal(t, ErrnoNosys, errno, ErrnoName(errno)) }) } @@ -1876,19 +1879,19 @@ func TestSnapshotPreview1_PathUnlinkFile(t *testing.T) { sysCtx, err := newSysContext(nil, nil, nil) require.NoError(t, err) - a, mod, fn := instantiateModule(t, ctx, FunctionPathUnlinkFile, ImportPathUnlinkFile, moduleName, sysCtx) + a, mod, fn := instantiateModule(t, ctx, functionPathUnlinkFile, importPathUnlinkFile, moduleName, sysCtx) defer mod.Close() - t.Run("SnapshotPreview1.PathUnlinkFile", func(t *testing.T) { + t.Run("snapshotPreview1.PathUnlinkFile", func(t *testing.T) { errno := a.PathUnlinkFile(mod, 0, 0, 0) - require.Equal(t, wasi.ErrnoNosys, errno, wasi.ErrnoName(errno)) + require.Equal(t, ErrnoNosys, errno, ErrnoName(errno)) }) - t.Run(FunctionPathUnlinkFile, func(t *testing.T) { + t.Run(functionPathUnlinkFile, func(t *testing.T) { results, err := fn.Call(mod, 0, 0, 0) require.NoError(t, err) - errno := wasi.Errno(results[0]) // results[0] is the errno - require.Equal(t, wasi.ErrnoNosys, errno, wasi.ErrnoName(errno)) + errno := Errno(results[0]) // results[0] is the errno + require.Equal(t, ErrnoNosys, errno, ErrnoName(errno)) }) } @@ -1898,19 +1901,19 @@ func TestSnapshotPreview1_PollOneoff(t *testing.T) { sysCtx, err := newSysContext(nil, nil, nil) require.NoError(t, err) - a, mod, fn := instantiateModule(t, ctx, FunctionPollOneoff, ImportPollOneoff, moduleName, sysCtx) + a, mod, fn := instantiateModule(t, ctx, functionPollOneoff, importPollOneoff, moduleName, sysCtx) defer mod.Close() - t.Run("SnapshotPreview1.PollOneoff", func(t *testing.T) { + t.Run("snapshotPreview1.PollOneoff", func(t *testing.T) { errno := a.PollOneoff(mod, 0, 0, 0, 0) - require.Equal(t, wasi.ErrnoNosys, errno, wasi.ErrnoName(errno)) + require.Equal(t, ErrnoNosys, errno, ErrnoName(errno)) }) - t.Run(FunctionPollOneoff, func(t *testing.T) { + t.Run(functionPollOneoff, func(t *testing.T) { results, err := fn.Call(mod, 0, 0, 0, 0) require.NoError(t, err) - errno := wasi.Errno(results[0]) // results[0] is the errno - require.Equal(t, wasi.ErrnoNosys, errno, wasi.ErrnoName(errno)) + errno := Errno(results[0]) // results[0] is the errno + require.Equal(t, ErrnoNosys, errno, ErrnoName(errno)) }) } @@ -1940,10 +1943,10 @@ func TestSnapshotPreview1_ProcExit(t *testing.T) { t.Run(tc.name, func(t *testing.T) { // Note: Unlike most tests, this uses fn, not the 'a' result parameter. This is because currently, this function // body panics, and we expect Call to unwrap the panic. - _, mod, fn := instantiateModule(t, ctx, FunctionProcExit, ImportProcExit, moduleName, sysCtx) + _, mod, fn := instantiateModule(t, ctx, functionProcExit, importProcExit, moduleName, sysCtx) defer mod.Close() - // When ProcExit is called, store.CallFunction returns immediately, returning the exit code as the error. + // When ProcExit is called, store.Callfunction returns immediately, returning the exit code as the error. _, err = fn.Call(mod, uint64(tc.exitCode)) require.Equal(t, tc.exitCode, err.(*sys.ExitError).ExitCode()) }) @@ -1956,19 +1959,19 @@ func TestSnapshotPreview1_ProcRaise(t *testing.T) { sysCtx, err := newSysContext(nil, nil, nil) require.NoError(t, err) - a, mod, fn := instantiateModule(t, ctx, FunctionProcRaise, ImportProcRaise, moduleName, sysCtx) + a, mod, fn := instantiateModule(t, ctx, functionProcRaise, importProcRaise, moduleName, sysCtx) defer mod.Close() - t.Run("SnapshotPreview1.ProcRaise", func(t *testing.T) { + t.Run("snapshotPreview1.ProcRaise", func(t *testing.T) { errno := a.ProcRaise(mod, 0) - require.Equal(t, wasi.ErrnoNosys, errno, wasi.ErrnoName(errno)) + require.Equal(t, ErrnoNosys, errno, ErrnoName(errno)) }) - t.Run(FunctionProcRaise, func(t *testing.T) { + t.Run(functionProcRaise, func(t *testing.T) { results, err := fn.Call(mod, 0) require.NoError(t, err) - errno := wasi.Errno(results[0]) // results[0] is the errno - require.Equal(t, wasi.ErrnoNosys, errno, wasi.ErrnoName(errno)) + errno := Errno(results[0]) // results[0] is the errno + require.Equal(t, ErrnoNosys, errno, ErrnoName(errno)) }) } @@ -1978,19 +1981,19 @@ func TestSnapshotPreview1_SchedYield(t *testing.T) { sysCtx, err := newSysContext(nil, nil, nil) require.NoError(t, err) - a, mod, fn := instantiateModule(t, ctx, FunctionSchedYield, ImportSchedYield, moduleName, sysCtx) + a, mod, fn := instantiateModule(t, ctx, functionSchedYield, importSchedYield, moduleName, sysCtx) defer mod.Close() - t.Run("SnapshotPreview1.SchedYield", func(t *testing.T) { + t.Run("snapshotPreview1.SchedYield", func(t *testing.T) { errno := a.SchedYield(mod) - require.Equal(t, wasi.ErrnoNosys, errno, wasi.ErrnoName(errno)) + require.Equal(t, ErrnoNosys, errno, ErrnoName(errno)) }) - t.Run(FunctionSchedYield, func(t *testing.T) { + t.Run(functionSchedYield, func(t *testing.T) { results, err := fn.Call(mod) require.NoError(t, err) - errno := wasi.Errno(results[0]) // results[0] is the errno - require.Equal(t, wasi.ErrnoNosys, errno, wasi.ErrnoName(errno)) + errno := Errno(results[0]) // results[0] is the errno + require.Equal(t, ErrnoNosys, errno, ErrnoName(errno)) }) } @@ -2008,7 +2011,7 @@ func TestSnapshotPreview1_RandomGet(t *testing.T) { sysCtx, err := newSysContext(nil, nil, nil) require.NoError(t, err) - a, mod, fn := instantiateModule(t, ctx, FunctionRandomGet, ImportRandomGet, moduleName, sysCtx) + a, mod, fn := instantiateModule(t, ctx, functionRandomGet, importRandomGet, moduleName, sysCtx) defer mod.Close() a.randSource = func(p []byte) error { @@ -2019,25 +2022,25 @@ func TestSnapshotPreview1_RandomGet(t *testing.T) { return err } - t.Run("SnapshotPreview1.RandomGet", func(t *testing.T) { + t.Run("snapshotPreview1.RandomGet", func(t *testing.T) { maskMemory(t, mod, len(expectedMemory)) // Invoke RandomGet directly and check the memory side effects! errno := a.RandomGet(mod, offset, length) - require.Zero(t, errno, wasi.ErrnoName(errno)) + require.Zero(t, errno, ErrnoName(errno)) actual, ok := mod.Memory().Read(0, offset+length+1) require.True(t, ok) require.Equal(t, expectedMemory, actual) }) - t.Run(FunctionRandomGet, func(t *testing.T) { + t.Run(functionRandomGet, func(t *testing.T) { maskMemory(t, mod, len(expectedMemory)) results, err := fn.Call(mod, uint64(offset), uint64(length)) require.NoError(t, err) - errno := wasi.Errno(results[0]) // results[0] is the errno - require.Zero(t, errno, wasi.ErrnoName(errno)) + errno := Errno(results[0]) // results[0] is the errno + require.Zero(t, errno, ErrnoName(errno)) actual, ok := mod.Memory().Read(0, offset+length+1) require.True(t, ok) @@ -2052,7 +2055,7 @@ func TestSnapshotPreview1_RandomGet_Errors(t *testing.T) { validAddress := uint32(0) // arbitrary valid address - a, mod, _ := instantiateModule(t, ctx, FunctionRandomGet, ImportRandomGet, moduleName, sysCtx) + a, mod, _ := instantiateModule(t, ctx, functionRandomGet, importRandomGet, moduleName, sysCtx) defer mod.Close() memorySize := mod.Memory().Size() @@ -2080,7 +2083,7 @@ func TestSnapshotPreview1_RandomGet_Errors(t *testing.T) { t.Run(tc.name, func(t *testing.T) { errno := a.RandomGet(mod, tc.offset, tc.length) - require.Equal(t, wasi.ErrnoFault, errno, wasi.ErrnoName(errno)) + require.Equal(t, ErrnoFault, errno, ErrnoName(errno)) }) } } @@ -2090,7 +2093,7 @@ func TestSnapshotPreview1_RandomGet_SourceError(t *testing.T) { sysCtx, err := newSysContext(nil, nil, nil) require.NoError(t, err) - a, mod, _ := instantiateModule(t, ctx, FunctionRandomGet, ImportRandomGet, moduleName, sysCtx) + a, mod, _ := instantiateModule(t, ctx, functionRandomGet, importRandomGet, moduleName, sysCtx) defer mod.Close() a.randSource = func(p []byte) error { @@ -2098,7 +2101,7 @@ func TestSnapshotPreview1_RandomGet_SourceError(t *testing.T) { } errno := a.RandomGet(mod, uint32(1), uint32(5)) // arbitrary offset and length - require.Equal(t, wasi.ErrnoIo, errno, wasi.ErrnoName(errno)) + require.Equal(t, ErrnoIo, errno, ErrnoName(errno)) } // TestSnapshotPreview1_SockRecv only tests it is stubbed for GrainLang per #271 @@ -2107,19 +2110,19 @@ func TestSnapshotPreview1_SockRecv(t *testing.T) { sysCtx, err := newSysContext(nil, nil, nil) require.NoError(t, err) - a, mod, fn := instantiateModule(t, ctx, FunctionSockRecv, ImportSockRecv, moduleName, sysCtx) + a, mod, fn := instantiateModule(t, ctx, functionSockRecv, importSockRecv, moduleName, sysCtx) defer mod.Close() - t.Run("SnapshotPreview1.SockRecv", func(t *testing.T) { + t.Run("snapshotPreview1.SockRecv", func(t *testing.T) { errno := a.SockRecv(mod, 0, 0, 0, 0, 0, 0) - require.Equal(t, wasi.ErrnoNosys, errno, wasi.ErrnoName(errno)) + require.Equal(t, ErrnoNosys, errno, ErrnoName(errno)) }) - t.Run(FunctionSockRecv, func(t *testing.T) { + t.Run(functionSockRecv, func(t *testing.T) { results, err := fn.Call(mod, 0, 0, 0, 0, 0, 0) require.NoError(t, err) - errno := wasi.Errno(results[0]) // results[0] is the errno - require.Equal(t, wasi.ErrnoNosys, errno, wasi.ErrnoName(errno)) + errno := Errno(results[0]) // results[0] is the errno + require.Equal(t, ErrnoNosys, errno, ErrnoName(errno)) }) } @@ -2129,19 +2132,19 @@ func TestSnapshotPreview1_SockSend(t *testing.T) { sysCtx, err := newSysContext(nil, nil, nil) require.NoError(t, err) - a, mod, fn := instantiateModule(t, ctx, FunctionSockSend, ImportSockSend, moduleName, sysCtx) + a, mod, fn := instantiateModule(t, ctx, functionSockSend, importSockSend, moduleName, sysCtx) defer mod.Close() - t.Run("SnapshotPreview1.SockSend", func(t *testing.T) { + t.Run("snapshotPreview1.SockSend", func(t *testing.T) { errno := a.SockSend(mod, 0, 0, 0, 0, 0) - require.Equal(t, wasi.ErrnoNosys, errno, wasi.ErrnoName(errno)) + require.Equal(t, ErrnoNosys, errno, ErrnoName(errno)) }) - t.Run(FunctionSockSend, func(t *testing.T) { + t.Run(functionSockSend, func(t *testing.T) { results, err := fn.Call(mod, 0, 0, 0, 0, 0) require.NoError(t, err) - errno := wasi.Errno(results[0]) // results[0] is the errno - require.Equal(t, wasi.ErrnoNosys, errno, wasi.ErrnoName(errno)) + errno := Errno(results[0]) // results[0] is the errno + require.Equal(t, ErrnoNosys, errno, ErrnoName(errno)) }) } @@ -2151,39 +2154,39 @@ func TestSnapshotPreview1_SockShutdown(t *testing.T) { sysCtx, err := newSysContext(nil, nil, nil) require.NoError(t, err) - a, mod, fn := instantiateModule(t, ctx, FunctionSockShutdown, ImportSockShutdown, moduleName, sysCtx) + a, mod, fn := instantiateModule(t, ctx, functionSockShutdown, importSockShutdown, moduleName, sysCtx) defer mod.Close() - t.Run("SnapshotPreview1.SockShutdown", func(t *testing.T) { + t.Run("snapshotPreview1.SockShutdown", func(t *testing.T) { errno := a.SockShutdown(mod, 0, 0) - require.Equal(t, wasi.ErrnoNosys, errno, wasi.ErrnoName(errno)) + require.Equal(t, ErrnoNosys, errno, ErrnoName(errno)) }) - t.Run(FunctionSockShutdown, func(t *testing.T) { + t.Run(functionSockShutdown, func(t *testing.T) { results, err := fn.Call(mod, 0, 0) require.NoError(t, err) - errno := wasi.Errno(results[0]) // results[0] is the errno - require.Equal(t, wasi.ErrnoNosys, errno, wasi.ErrnoName(errno)) + errno := Errno(results[0]) // results[0] is the errno + require.Equal(t, ErrnoNosys, errno, ErrnoName(errno)) }) } const testMemoryPageSize = 1 // maskMemory sets the first memory in the store to '?' * size, so tests can see what's written. -func maskMemory(t *testing.T, mod publicwasm.Module, size int) { +func maskMemory(t *testing.T, mod api.Module, size int) { for i := uint32(0); i < uint32(size); i++ { require.True(t, mod.Memory().WriteByte(i, '?')) } } -func instantiateModule(t *testing.T, ctx context.Context, wasiFunction, wasiImport, moduleName string, sysCtx *wasm.SysContext) (*wasiAPI, *wasm.ModuleContext, publicwasm.Function) { +func instantiateModule(t *testing.T, ctx context.Context, wasifunction, wasiimport, moduleName string, sysCtx *wasm.SysContext) (*wasiAPI, *wasm.ModuleContext, api.Function) { enabledFeatures := wasm.Features20191205 store := wasm.NewStore(interpreter.NewEngine(), enabledFeatures) // The package `wazero` has a simpler interface for adding host modules, but we can't use that as it would create an - // import cycle. Instead, we export internalwasm.NewHostModule and use it here. - a, fns := SnapshotPreview1Functions() - m, err := wasm.NewHostModule(wasi.ModuleSnapshotPreview1, fns) + // import cycle. Instead, we export wasm.NewHostModule and use it here. + a, fns := snapshotPreview1Functions() + m, err := wasm.NewHostModule("wasi_snapshot_preview1", fns) require.NoError(t, err) // Double-check what we created passes same validity as module-defined modules. @@ -2198,13 +2201,13 @@ func instantiateModule(t *testing.T, ctx context.Context, wasiFunction, wasiImpo (memory 1) ;; just an arbitrary size big enough for tests (export "memory" (memory 0)) (export "%[1]s" (func $wasi.%[1]s)) -)`, wasiFunction, wasiImport)), enabledFeatures, wasm.MemoryMaxPages) +)`, wasifunction, wasiimport)), enabledFeatures, wasm.MemoryMaxPages) require.NoError(t, err) mod, err := store.Instantiate(ctx, m, moduleName, sysCtx) require.NoError(t, err) - fn := mod.ExportedFunction(wasiFunction) + fn := mod.ExportedFunction(wasifunction) require.NotNil(t, fn) return a, mod, fn } diff --git a/wasi_test.go b/wasi_test.go deleted file mode 100644 index 28a8985f..00000000 --- a/wasi_test.go +++ /dev/null @@ -1,93 +0,0 @@ -package wazero - -import ( - "bytes" - "context" - _ "embed" - "testing" - - "github.com/stretchr/testify/require" - - "github.com/tetratelabs/wazero/wasm" -) - -// TestStartWASICommand_DoesntEnforce_Start ensures wapc-go work when modules import WASI, but don't export "_start". -func TestStartWASICommand_DoesntEnforce_Start(t *testing.T) { - r := NewRuntime() - - wasi, err := r.InstantiateModule(WASISnapshotPreview1()) - require.NoError(t, err) - defer wasi.Close() - - // Start the module as a WASI command. This will fail if the context wasn't as intended. - mod, err := StartWASICommandFromSource(r, []byte(`(module $wasi_test.go - (memory 1) - (export "memory" (memory 0)) -)`)) - require.NoError(t, err) - require.NoError(t, mod.Close()) -} - -func TestStartWASICommand_UsesRuntimeContext(t *testing.T) { - type key string - config := NewRuntimeConfig().WithContext(context.WithValue(context.Background(), key("wa"), "zero")) - r := NewRuntimeWithConfig(config) - - // Define a function that will be re-exported as the WASI function: _start - var calledStart bool - start := func(ctx wasm.Module) { - calledStart = true - require.Equal(t, config.ctx, ctx.Context()) - } - - host, err := r.NewModuleBuilder("").ExportFunction("start", start).Instantiate() - require.NoError(t, err) - defer host.Close() - - wasi, err := r.InstantiateModule(WASISnapshotPreview1()) - require.NoError(t, err) - defer wasi.Close() - - // Start the module as a WASI command. This will fail if the context wasn't as intended. - mod, err := StartWASICommandFromSource(r, []byte(`(module $wasi_test.go - (import "" "start" (func $start)) - (memory 1) - (export "_start" (func $start)) - (export "memory" (memory 0)) -)`)) - require.NoError(t, err) - defer mod.Close() - - require.True(t, calledStart) -} - -// wasiArg was compiled from examples/testdata/wasi_arg.wat -//go:embed examples/testdata/wasi_arg.wasm -var wasiArg []byte - -func TestStartWASICommandWithConfig(t *testing.T) { - r := NewRuntime() - - stdout := bytes.NewBuffer(nil) - - // Configure WASI to write stdout to a buffer, so that we can verify it later. - sys := NewSysConfig().WithStdout(stdout) - wasi, err := r.InstantiateModule(WASISnapshotPreview1()) - require.NoError(t, err) - defer wasi.Close() - - m, err := r.CompileModule(wasiArg) - require.NoError(t, err) - - // Re-use the same module many times. - for _, tc := range []string{"a", "b", "c"} { - mod, err := StartWASICommandWithConfig(r, m.WithName(tc), sys.WithArgs(tc)) - require.NoError(t, err) - - // Ensure the scoped configuration applied. As the args are null-terminated, we append zero (NUL). - require.Equal(t, append([]byte(tc), 0), stdout.Bytes()) - - stdout.Reset() - require.NoError(t, mod.Close()) - } -} diff --git a/wasm.go b/wasm.go index ece87f82..422e1dbf 100644 --- a/wasm.go +++ b/wasm.go @@ -6,18 +6,18 @@ import ( "errors" "fmt" - internalwasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/api" + "github.com/tetratelabs/wazero/internal/wasm" "github.com/tetratelabs/wazero/internal/wasm/binary" "github.com/tetratelabs/wazero/internal/wasm/text" - "github.com/tetratelabs/wazero/wasm" ) // Runtime allows embedding of WebAssembly 1.0 (20191205) modules. // // Ex. // r := wazero.NewRuntime() -// decoded, _ := r.CompileModule(source) -// module, _ := r.InstantiateModule(decoded) +// code, _ := r.CompileModule(source) +// module, _ := r.InstantiateModule(code) // defer module.Close() // // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/ @@ -33,45 +33,63 @@ type Runtime interface { NewModuleBuilder(moduleName string) ModuleBuilder // Module returns exports from an instantiated module or nil if there aren't any. - Module(moduleName string) wasm.Module + Module(moduleName string) api.Module // CompileModule decodes the WebAssembly 1.0 (20191205) text or binary source or errs if invalid. // Any pre-compilation done after decoding the source is dependent on the RuntimeConfig. // - // There are two main reasons to use CompileModule instead of InstantiateModuleFromSource: + // There are two main reasons to use CompileModule instead of InstantiateModuleFromCode: // * Improve performance when the same module is instantiated multiple times under different names // * Reduce the amount of errors that can occur during InstantiateModule. // - // Note: The resulting module name defaults to what was decoded from the custom name section. + // Note: The resulting module name defaults to what was binary from the custom name section. // See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#name-section%E2%91%A0 - CompileModule(source []byte) (*Module, error) + CompileModule(source []byte) (*CompiledCode, error) - // InstantiateModuleFromSource instantiates a module from the WebAssembly 1.0 (20191205) text or binary source or + // InstantiateModuleFromCode instantiates a module from the WebAssembly 1.0 (20191205) text or binary source or // errs if invalid. // // Ex. - // module, _ := wazero.NewRuntime().InstantiateModuleFromSource(source) + // module, _ := wazero.NewRuntime().InstantiateModuleFromCode(source) // defer module.Close() // // Note: This is a convenience utility that chains CompileModule with InstantiateModule. To instantiate the same // source multiple times, use CompileModule as InstantiateModule avoids redundant decoding and/or compilation. - InstantiateModuleFromSource(source []byte) (wasm.Module, error) + InstantiateModuleFromCode(source []byte) (api.Module, error) // InstantiateModule instantiates the module namespace or errs if the configuration was invalid. // // Ex. // r := wazero.NewRuntime() - // decoded, _ := r.CompileModule(source) - // module, _ := r.InstantiateModule(decoded) + // code, _ := r.CompileModule(source) + // module, _ := r.InstantiateModule(code) // defer module.Close() // - // While a Module is pre-validated, there are a few situations which can cause an error: - // * The Module name is already in use. - // * The Module has a table element initializer that resolves to an index outside the Table minimum size. - // * The Module has a start function, and it failed to execute. + // While CompiledCode is pre-validated, there are a few situations which can cause an error: + // * The module name is already in use. + // * The module has a table element initializer that resolves to an index outside the Table minimum size. + // * The module has a start function, and it failed to execute. // // Note: The last value of RuntimeConfig.WithContext is used for any start function. - InstantiateModule(module *Module) (wasm.Module, error) + InstantiateModule(code *CompiledCode) (api.Module, error) + + // InstantiateModuleWithConfig is like InstantiateModule, except you can override configuration such as the module + // name or ENV variables. + // + // For example, you can use this to define different args depending on the importing module. + // + // r := wazero.NewRuntime() + // wasi, _ := r.InstantiateModule(wazero.WASISnapshotPreview1()) + // code, _ := r.CompileModule(source) + // + // // Initialize base configuration: + // config := wazero.NewModuleConfig().WithStdout(buf) + // + // // Assign different configuration on each instantiation + // module, _ := r.InstantiateModuleWithConfig(code, config.WithName("rotate").WithArgs("rotate", "angle=90", "dir=cw")) + // + // Note: Config is copied during instantiation: Later changes to config do not affect the instantiated result. + InstantiateModuleWithConfig(code *CompiledCode, config *ModuleConfig) (mod api.Module, err error) } func NewRuntime() Runtime { @@ -82,7 +100,7 @@ func NewRuntime() Runtime { func NewRuntimeWithConfig(config *RuntimeConfig) Runtime { return &runtime{ ctx: config.ctx, - store: internalwasm.NewStore(config.newEngine(), config.enabledFeatures), + store: wasm.NewStore(config.newEngine(), config.enabledFeatures), enabledFeatures: config.enabledFeatures, memoryMaxPages: config.memoryMaxPages, } @@ -91,18 +109,18 @@ func NewRuntimeWithConfig(config *RuntimeConfig) Runtime { // runtime allows decoupling of public interfaces from internal representation. type runtime struct { ctx context.Context - store *internalwasm.Store - enabledFeatures internalwasm.Features + store *wasm.Store + enabledFeatures wasm.Features memoryMaxPages uint32 } // Module implements Runtime.Module -func (r *runtime) Module(moduleName string) wasm.Module { +func (r *runtime) Module(moduleName string) api.Module { return r.store.Module(moduleName) } // CompileModule implements Runtime.CompileModule -func (r *runtime) CompileModule(source []byte) (*Module, error) { +func (r *runtime) CompileModule(source []byte) (*CompiledCode, error) { if source == nil { return nil, errors.New("source == nil") } @@ -112,17 +130,17 @@ func (r *runtime) CompileModule(source []byte) (*Module, error) { } // Peek to see if this is a binary or text format - var decoder internalwasm.DecodeModule + var decoder wasm.DecodeModule if bytes.Equal(source[0:4], binary.Magic) { decoder = binary.DecodeModule } else { decoder = text.DecodeModule } - if r.memoryMaxPages > internalwasm.MemoryMaxPages { + if r.memoryMaxPages > wasm.MemoryMaxPages { return nil, fmt.Errorf("memoryMaxPages %d (%s) > specification max %d (%s)", - r.memoryMaxPages, internalwasm.PagesToUnitOfBytes(r.memoryMaxPages), - internalwasm.MemoryMaxPages, internalwasm.PagesToUnitOfBytes(internalwasm.MemoryMaxPages)) + r.memoryMaxPages, wasm.PagesToUnitOfBytes(r.memoryMaxPages), + wasm.MemoryMaxPages, wasm.PagesToUnitOfBytes(wasm.MemoryMaxPages)) } internal, err := decoder(source, r.enabledFeatures, r.memoryMaxPages) @@ -134,24 +152,49 @@ func (r *runtime) CompileModule(source []byte) (*Module, error) { return nil, err } - result := &Module{module: internal} - if internal.NameSection != nil { - result.name = internal.NameSection.ModuleName - } - - return result, nil + return &CompiledCode{module: internal}, nil } -// InstantiateModuleFromSource implements Runtime.InstantiateModuleFromSource -func (r *runtime) InstantiateModuleFromSource(source []byte) (wasm.Module, error) { - if decoded, err := r.CompileModule(source); err != nil { +// InstantiateModuleFromCode implements Runtime.InstantiateModuleFromCode +func (r *runtime) InstantiateModuleFromCode(source []byte) (api.Module, error) { + if code, err := r.CompileModule(source); err != nil { return nil, err } else { - return r.InstantiateModule(decoded) + return r.InstantiateModule(code) } } // InstantiateModule implements Runtime.InstantiateModule -func (r *runtime) InstantiateModule(module *Module) (wasm.Module, error) { - return r.store.Instantiate(r.ctx, module.module, module.name, internalwasm.DefaultSysContext()) +func (r *runtime) InstantiateModule(code *CompiledCode) (mod api.Module, err error) { + return r.InstantiateModuleWithConfig(code, NewModuleConfig()) +} + +// InstantiateModuleWithConfig implements Runtime.InstantiateModuleWithConfig +func (r *runtime) InstantiateModuleWithConfig(code *CompiledCode, config *ModuleConfig) (mod api.Module, err error) { + var sys *wasm.SysContext + if sys, err = config.toSysContext(); err != nil { + return + } + + name := config.name + if name == "" && code.module.NameSection != nil && code.module.NameSection.ModuleName != "" { + name = code.module.NameSection.ModuleName + } + + mod, err = r.store.Instantiate(r.ctx, code.module, name, sys) + if err != nil { + return + } + + for _, fn := range config.startFunctions { + start := mod.ExportedFunction(fn) + if start == nil { + continue + } + if _, err = start.Call(mod.WithContext(r.ctx)); err != nil { + err = fmt.Errorf("module[%s] function[%s] failed: %w", name, fn, err) + return + } + } + return } diff --git a/wasm_test.go b/wasm_test.go index 2e3d828e..fe30cad0 100644 --- a/wasm_test.go +++ b/wasm_test.go @@ -2,15 +2,16 @@ package wazero import ( "context" + _ "embed" "fmt" "math" "testing" "github.com/stretchr/testify/require" - internalwasm "github.com/tetratelabs/wazero/internal/wasm" + "github.com/tetratelabs/wazero/api" + "github.com/tetratelabs/wazero/internal/wasm" "github.com/tetratelabs/wazero/internal/wasm/binary" - "github.com/tetratelabs/wazero/wasm" ) func TestRuntime_DecodeModule(t *testing.T) { @@ -34,15 +35,15 @@ func TestRuntime_DecodeModule(t *testing.T) { }, { name: "binary - no name section", - source: binary.EncodeModule(&internalwasm.Module{}), + source: binary.EncodeModule(&wasm.Module{}), }, { name: "binary - empty NameSection.ModuleName", - source: binary.EncodeModule(&internalwasm.Module{NameSection: &internalwasm.NameSection{}}), + source: binary.EncodeModule(&wasm.Module{NameSection: &wasm.NameSection{}}), }, { name: "binary - NameSection.ModuleName", - source: binary.EncodeModule(&internalwasm.Module{NameSection: &internalwasm.NameSection{ModuleName: "test"}}), + source: binary.EncodeModule(&wasm.Module{NameSection: &wasm.NameSection{ModuleName: "test"}}), expectedName: "test", }, } @@ -52,9 +53,11 @@ func TestRuntime_DecodeModule(t *testing.T) { tc := tt t.Run(tc.name, func(t *testing.T) { - decoded, err := r.CompileModule(tc.source) + code, err := r.CompileModule(tc.source) require.NoError(t, err) - require.Equal(t, tc.expectedName, decoded.name) + if tc.expectedName != "" { + require.Equal(t, tc.expectedName, code.module.NameSection.ModuleName) + } }) } } @@ -95,7 +98,7 @@ func TestRuntime_DecodeModule_Errors(t *testing.T) { { name: "memory has too many pages - binary", runtime: NewRuntimeWithConfig(NewRuntimeConfig().WithMemoryMaxPages(2)), - source: binary.EncodeModule(&internalwasm.Module{MemorySection: &internalwasm.Memory{Min: 2, Max: 3}}), + source: binary.EncodeModule(&wasm.Module{MemorySection: &wasm.Memory{Min: 2, Max: 3}}), expectedErr: "section memory: max 3 pages (192 Ki) outside range of 2 pages (128 Ki)", }, } @@ -115,28 +118,6 @@ func TestRuntime_DecodeModule_Errors(t *testing.T) { } } -// TestDecodedModule_WithName tests that we can pre-validate (cache) a module and instantiate it under different -// names. This pattern is used in wapc-go. -func TestDecodedModule_WithName(t *testing.T) { - r := NewRuntime() - base, err := r.CompileModule([]byte(`(module $0 (memory 1))`)) - require.NoError(t, err) - - require.Equal(t, "0", base.name) - - // Use the same runtime to instantiate multiple modules - internal := r.(*runtime).store - m1, err := r.InstantiateModule(base.WithName("1")) - require.NoError(t, err) - require.Nil(t, internal.Module("0")) - require.Equal(t, internal.Module("1"), m1) - - m2, err := r.InstantiateModule(base.WithName("2")) - require.NoError(t, err) - require.Nil(t, internal.Module("0")) - require.Equal(t, internal.Module("2"), m2) -} - // TestModule_Memory only covers a couple cases to avoid duplication of internal/wasm/runtime_test.go func TestModule_Memory(t *testing.T) { tests := []struct { @@ -161,11 +142,11 @@ func TestModule_Memory(t *testing.T) { r := NewRuntime() t.Run(tc.name, func(t *testing.T) { - decoded, err := r.CompileModule([]byte(tc.wat)) + code, err := r.CompileModule([]byte(tc.wat)) require.NoError(t, err) // Instantiate the module and get the export of the above hostFn - module, err := r.InstantiateModule(decoded) + module, err := r.InstantiateModule(code) require.NoError(t, err) mem := module.ExportedMemory("memory") @@ -182,50 +163,50 @@ func TestModule_Memory(t *testing.T) { func TestModule_Global(t *testing.T) { tests := []struct { name string - module *internalwasm.Module // module as wat doesn't yet support globals + module *wasm.Module // module as wat doesn't yet support globals expected, expectedMutable bool }{ { name: "no global", - module: &internalwasm.Module{}, + module: &wasm.Module{}, }, { name: "global not exported", - module: &internalwasm.Module{ - GlobalSection: []*internalwasm.Global{ + module: &wasm.Module{ + GlobalSection: []*wasm.Global{ { - Type: &internalwasm.GlobalType{ValType: internalwasm.ValueTypeI64, Mutable: true}, - Init: &internalwasm.ConstantExpression{Opcode: internalwasm.OpcodeI64Const, Data: []byte{1}}, + Type: &wasm.GlobalType{ValType: wasm.ValueTypeI64, Mutable: true}, + Init: &wasm.ConstantExpression{Opcode: wasm.OpcodeI64Const, Data: []byte{1}}, }, }, }, }, { name: "global exported", - module: &internalwasm.Module{ - GlobalSection: []*internalwasm.Global{ + module: &wasm.Module{ + GlobalSection: []*wasm.Global{ { - Type: &internalwasm.GlobalType{ValType: internalwasm.ValueTypeI64}, - Init: &internalwasm.ConstantExpression{Opcode: internalwasm.OpcodeI64Const, Data: []byte{1}}, + Type: &wasm.GlobalType{ValType: wasm.ValueTypeI64}, + Init: &wasm.ConstantExpression{Opcode: wasm.OpcodeI64Const, Data: []byte{1}}, }, }, - ExportSection: map[string]*internalwasm.Export{ - "global": {Type: internalwasm.ExternTypeGlobal, Name: "global"}, + ExportSection: map[string]*wasm.Export{ + "global": {Type: wasm.ExternTypeGlobal, Name: "global"}, }, }, expected: true, }, { name: "global exported and mutable", - module: &internalwasm.Module{ - GlobalSection: []*internalwasm.Global{ + module: &wasm.Module{ + GlobalSection: []*wasm.Global{ { - Type: &internalwasm.GlobalType{ValType: internalwasm.ValueTypeI64, Mutable: true}, - Init: &internalwasm.ConstantExpression{Opcode: internalwasm.OpcodeI64Const, Data: []byte{1}}, + Type: &wasm.GlobalType{ValType: wasm.ValueTypeI64, Mutable: true}, + Init: &wasm.ConstantExpression{Opcode: wasm.OpcodeI64Const, Data: []byte{1}}, }, }, - ExportSection: map[string]*internalwasm.Export{ - "global": {Type: internalwasm.ExternTypeGlobal, Name: "global"}, + ExportSection: map[string]*wasm.Export{ + "global": {Type: wasm.ExternTypeGlobal, Name: "global"}, }, }, expected: true, @@ -239,7 +220,7 @@ func TestModule_Global(t *testing.T) { r := NewRuntime() t.Run(tc.name, func(t *testing.T) { // Instantiate the module and get the export of the above global - module, err := r.InstantiateModule(&Module{module: tc.module}) + module, err := r.InstantiateModule(&CompiledCode{module: tc.module}) require.NoError(t, err) global := module.ExportedGlobal("global") @@ -249,7 +230,7 @@ func TestModule_Global(t *testing.T) { } require.Equal(t, uint64(1), global.Get()) - mutable, ok := global.(wasm.MutableGlobal) + mutable, ok := global.(api.MutableGlobal) require.Equal(t, tc.expectedMutable, ok) if ok { mutable.Set(2) @@ -292,18 +273,20 @@ func TestFunction_Context(t *testing.T) { // Define a host function so that we can catch the context propagated from a module function call functionName := "fn" expectedResult := uint64(math.MaxUint64) - hostFn := func(ctx wasm.Module) uint64 { + hostFn := func(ctx api.Module) uint64 { require.Equal(t, tc.expected, ctx.Context()) return expectedResult } - source := requireImportAndExportFunction(t, r, hostFn, functionName) + source, closer := requireImportAndExportFunction(t, r, hostFn, functionName) + defer closer() // nolint // Instantiate the module and get the export of the above hostFn - decoded, err := r.CompileModule(source) + code, err := r.CompileModule(source) require.NoError(t, err) - module, err := r.InstantiateModule(decoded) + module, err := r.InstantiateModuleWithConfig(code, NewModuleConfig().WithName(t.Name())) require.NoError(t, err) + defer module.Close() // This fails if the function wasn't invoked, or had an unexpected context. results, err := module.ExportedFunction(functionName).Call(module.WithContext(tc.ctx)) @@ -321,7 +304,7 @@ func TestRuntime_NewModule_UsesStoreContext(t *testing.T) { // Define a function that will be set as the start function var calledStart bool - start := func(ctx wasm.Module) { + start := func(ctx api.Module) { calledStart = true require.Equal(t, runtimeCtx, ctx.Context()) } @@ -329,24 +312,87 @@ func TestRuntime_NewModule_UsesStoreContext(t *testing.T) { _, err := r.NewModuleBuilder("env").ExportFunction("start", start).Instantiate() require.NoError(t, err) - decoded, err := r.CompileModule([]byte(`(module $runtime_test.go + code, err := r.CompileModule([]byte(`(module $runtime_test.go (import "env" "start" (func $start)) (start $start) )`)) require.NoError(t, err) // Instantiate the module, which calls the start function. This will fail if the context wasn't as intended. - _, err = r.InstantiateModule(decoded) + _, err = r.InstantiateModule(code) require.NoError(t, err) require.True(t, calledStart) } +// TestInstantiateModuleFromCode_DoesntEnforce_Start ensures wapc-go work when modules import WASI, but don't export "_start". +func TestInstantiateModuleFromCode_DoesntEnforce_Start(t *testing.T) { + r := NewRuntime() + + mod, err := r.InstantiateModuleFromCode([]byte(`(module $wasi_test.go + (memory 1) + (export "memory" (memory 0)) +)`)) + require.NoError(t, err) + require.NoError(t, mod.Close()) +} + +func TestInstantiateModuleFromCode_UsesRuntimeContext(t *testing.T) { + type key string + config := NewRuntimeConfig().WithContext(context.WithValue(context.Background(), key("wa"), "zero")) + r := NewRuntimeWithConfig(config) + + // Define a function that will be re-exported as the WASI function: _start + var calledStart bool + start := func(ctx api.Module) { + calledStart = true + require.Equal(t, config.ctx, ctx.Context()) + } + + host, err := r.NewModuleBuilder("").ExportFunction("start", start).Instantiate() + require.NoError(t, err) + defer host.Close() + + // Start the module as a WASI command. This will fail if the context wasn't as intended. + mod, err := r.InstantiateModuleFromCode([]byte(`(module $start + (import "" "start" (func $start)) + (memory 1) + (export "_start" (func $start)) + (export "memory" (memory 0)) +)`)) + require.NoError(t, err) + defer mod.Close() + + require.True(t, calledStart) +} + +// TestInstantiateModuleWithConfig_WithName tests that we can pre-validate (cache) a module and instantiate it under +// different names. This pattern is used in wapc-go. +func TestInstantiateModuleWithConfig_WithName(t *testing.T) { + r := NewRuntime() + base, err := r.CompileModule([]byte(`(module $0 (memory 1))`)) + require.NoError(t, err) + + require.Equal(t, "0", base.module.NameSection.ModuleName) + + // Use the same runtime to instantiate multiple modules + internal := r.(*runtime).store + m1, err := r.InstantiateModuleWithConfig(base, NewModuleConfig().WithName("1")) + require.NoError(t, err) + require.Nil(t, internal.Module("0")) + require.Equal(t, internal.Module("1"), m1) + + m2, err := r.InstantiateModuleWithConfig(base, NewModuleConfig().WithName("2")) + require.NoError(t, err) + require.Nil(t, internal.Module("0")) + require.Equal(t, internal.Module("2"), m2) +} + // requireImportAndExportFunction re-exports a host function because only host functions can see the propagated context. -func requireImportAndExportFunction(t *testing.T, r Runtime, hostFn func(ctx wasm.Module) uint64, functionName string) []byte { - _, err := r.NewModuleBuilder("host").ExportFunction(functionName, hostFn).Instantiate() +func requireImportAndExportFunction(t *testing.T, r Runtime, hostFn func(ctx api.Module) uint64, functionName string) ([]byte, func() error) { + mod, err := r.NewModuleBuilder("host").ExportFunction(functionName, hostFn).Instantiate() require.NoError(t, err) return []byte(fmt.Sprintf( `(module (import "host" "%[1]s" (func (result i64))) (export "%[1]s" (func 0)))`, functionName, - )) + )), mod.Close }