Stops using "ex." to abbreviate "for example" (#827)
Signed-off-by: Adrian Cole <adrian@tetrate.io>
This commit is contained in:
2
.github/ISSUE_TEMPLATE/feature-request.md
vendored
2
.github/ISSUE_TEMPLATE/feature-request.md
vendored
@@ -8,7 +8,7 @@ assignees: ''
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
A clear and concise description of what the problem is. e.g. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
25
RATIONALE.md
25
RATIONALE.md
@@ -81,7 +81,7 @@ codebase productive.
|
||||
wazero shares constants and interfaces with internal code by a sharing pattern described below:
|
||||
* 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`.
|
||||
* e.g. `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`.
|
||||
|
||||
@@ -106,8 +106,9 @@ field.
|
||||
|
||||
In practice, this means shared functionality like memory mutation need to be implemented by interfaces.
|
||||
|
||||
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`
|
||||
Here are some examples:
|
||||
* `api.Memory` protects access by exposing functions like `WriteFloat64Le` instead of exporting a buffer (`[]byte`).
|
||||
* 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.
|
||||
|
||||
@@ -117,7 +118,7 @@ All exported types in public packages, regardless of configuration vs runtime, a
|
||||
internal flexibility and avoiding people accidentally mis-initializing by instantiating the types on their own vs using
|
||||
the `NewXxx` constructor functions. In other words, there's less support load when things can't be done incorrectly.
|
||||
|
||||
Ex.
|
||||
Here's an example:
|
||||
```go
|
||||
rt := &RuntimeConfig{} // not initialized properly (fields are nil which shouldn't be)
|
||||
rt := RuntimeConfig{} // not initialized properly (should be a pointer)
|
||||
@@ -131,9 +132,9 @@ There are a few drawbacks to this, notably some work for maintainers.
|
||||
|
||||
## Config
|
||||
|
||||
wazero configures scopes such as Runtime and Module using `XxxConfig` types. Ex. `RuntimeConfig` configures `Runtime`
|
||||
and `ModuleConfig` configures `Module` (instantiation). In all cases, config types begin defaults and can be customized
|
||||
by a user, for example, selecting features or a module name override.
|
||||
wazero configures scopes such as Runtime and Module using `XxxConfig` types. For example, `RuntimeConfig` configures
|
||||
`Runtime` and `ModuleConfig` configure `Module` (instantiation). In all cases, config types begin defaults and can be
|
||||
customized by a user, e.g., selecting features or a module name override.
|
||||
|
||||
### Why don't we make each configuration setting return an error?
|
||||
No config types create resources that would need to be closed, nor do they return errors on use. This helps reduce
|
||||
@@ -177,13 +178,13 @@ any goroutine.
|
||||
|
||||
Since config are immutable, changes apply via return val, similar to `append` in a slice.
|
||||
|
||||
Ex. Both of these are the same sort of error:
|
||||
For example, both of these are the same sort of error:
|
||||
```go
|
||||
append(slice, element) // bug as only the return value has the updated slice.
|
||||
cfg.WithName(next) // bug as only the return value has the updated name.
|
||||
```
|
||||
|
||||
This means the correct use is re-assigning explicitly or via chaining. Ex.
|
||||
Here's an example of correct use: re-assigning explicitly or via chaining.
|
||||
```go
|
||||
cfg = cfg.WithName(name) // explicit
|
||||
|
||||
@@ -279,9 +280,9 @@ space. It is accepted that the options pattern is common in Go, which is the mai
|
||||
### Why aren't config types deeply structured?
|
||||
wazero's configuration types cover the three main scopes of WebAssembly use:
|
||||
* `RuntimeConfig`: This is the broadest scope, so applies also to compilation
|
||||
and instantiation. Ex. This controls the WebAssembly Specification Version.
|
||||
and instantiation. e.g. This controls the WebAssembly Specification Version.
|
||||
* `ModuleConfig`: This affects modules instantiated after compilation and what
|
||||
resources are allowed. Ex. This defines how or if STDOUT is captured.
|
||||
resources are allowed. e.g. This defines how or if STDOUT is captured.
|
||||
|
||||
We could nest configuration, for example have `ModuleConfig.SysConfig` instead
|
||||
of a flat definition. However, a flat structure is easier to work with and is
|
||||
@@ -319,7 +320,7 @@ there to be an engine that has multiple stores which have multiple modules. More
|
||||
either 1 engine with 1 store and multiple modules, or 1 engine with many stores, each having 1 non-host module. In worst
|
||||
case, a user can use multiple runtimes until "multi-store" is better understood.
|
||||
|
||||
If later, we have demand for multiple stores, that can be accomplished by overload. Ex. `Runtime.InstantiateInStore` or
|
||||
If later, we have demand for multiple stores, that can be accomplished by overload. e.g. `Runtime.InstantiateInStore` or
|
||||
`Runtime.Store(name) Store`.
|
||||
|
||||
## wazeroir
|
||||
|
||||
4
Vagrantfile
vendored
4
Vagrantfile
vendored
@@ -1,6 +1,6 @@
|
||||
# Vagrant file for FreeBSD
|
||||
#
|
||||
# Ex.
|
||||
# Here's an example:
|
||||
# GOVERSION=$(go env GOVERSION) GOARCH=$(go env GOARCH) vagrant up
|
||||
# vagrant rsync
|
||||
# vagrant ssh -c "cd wazero; go test ./..."
|
||||
@@ -24,7 +24,7 @@ Vagrant.configure("2") do |config|
|
||||
v.cpus = 1
|
||||
end
|
||||
|
||||
# Ex. `GOVERSION=$(go env GOVERSION) GOARCH=$(go env GOARCH) vagrant provision`
|
||||
# Similar to `GOVERSION=$(go env GOVERSION) GOARCH=$(go env GOARCH) vagrant provision`
|
||||
config.vm.provision "install-golang", type: "shell", run: "once" do |sh|
|
||||
sh.env = {
|
||||
'GOVERSION': ENV['GOVERSION'],
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
//
|
||||
// Constants define individual features, such as CoreFeatureMultiValue, or
|
||||
// groups of "finished" features, assigned to a WebAssembly Core Specification
|
||||
// version, ex. CoreFeaturesV1 or CoreFeaturesV2.
|
||||
// version, e.g. CoreFeaturesV1 or CoreFeaturesV2.
|
||||
//
|
||||
// Note: Numeric values are not intended to be interpreted except as bit flags.
|
||||
type CoreFeatures uint64
|
||||
|
||||
14
api/wasm.go
14
api/wasm.go
@@ -60,12 +60,12 @@ func ExternTypeName(et ExternType) string {
|
||||
// - ValueTypeF64 - EncodeF64 DecodeF64 from float64
|
||||
// - ValueTypeExternref - unintptr(unsafe.Pointer(p)) where p is any pointer type in Go (e.g. *string)
|
||||
//
|
||||
// Ex. Given a Text Format type use (param i64) (result i64), no conversion is necessary.
|
||||
// e.g. Given a Text Format type use (param i64) (result i64), no conversion is necessary.
|
||||
//
|
||||
// results, _ := fn(ctx, input)
|
||||
// result := result[0]
|
||||
//
|
||||
// Ex. Given a Text Format type use (param f64) (result f64), conversion is necessary.
|
||||
// e.g. Given a Text Format type use (param f64) (result f64), conversion is necessary.
|
||||
//
|
||||
// results, _ := fn(ctx, api.EncodeF64(input))
|
||||
// result := api.DecodeF64(result[0])
|
||||
@@ -235,7 +235,7 @@ type FunctionDefinition interface {
|
||||
Name() string
|
||||
|
||||
// DebugName identifies this function based on its Index or Name in the
|
||||
// module. This is used for errors and stack traces. Ex. "env.abort".
|
||||
// module. This is used for errors and stack traces. e.g. "env.abort".
|
||||
//
|
||||
// When the function name is empty, a substitute name is generated by
|
||||
// prefixing '$' to its position in the index namespace. Ex ".$0" is the
|
||||
@@ -243,7 +243,7 @@ type FunctionDefinition interface {
|
||||
//
|
||||
// The format is dot-delimited module and function name, but there are no
|
||||
// restrictions on the module and function name. This means either can be
|
||||
// empty or include dots. Ex. "x.x.x" could mean module "x" and name "x.x",
|
||||
// empty or include dots. e.g. "x.x.x" could mean module "x" and name "x.x",
|
||||
// or it could mean module "x.x" and name "x".
|
||||
//
|
||||
// Note: This name is stable regardless of import or export. For example,
|
||||
@@ -303,12 +303,12 @@ type Function interface {
|
||||
|
||||
// Global is a WebAssembly 1.0 (20191205) global exported from an instantiated module (wazero.Runtime InstantiateModule).
|
||||
//
|
||||
// Ex. If the value is not mutable, you can read it once:
|
||||
// For example, if the value is not mutable, you can read it once:
|
||||
//
|
||||
// offset := module.ExportedGlobal("memory.offset").Get()
|
||||
//
|
||||
// Globals are allowed by specification to be mutable. However, this can be disabled by configuration. When in doubt,
|
||||
// safe cast to find out if the value can change. Ex.
|
||||
// safe cast to find out if the value can change. Here's an example:
|
||||
//
|
||||
// offset := module.ExportedGlobal("memory.offset")
|
||||
// if _, ok := offset.(api.MutableGlobal); ok {
|
||||
@@ -352,7 +352,7 @@ type Memory interface {
|
||||
// Definition is metadata about this memory from its defining module.
|
||||
Definition() MemoryDefinition
|
||||
|
||||
// Size returns the size in bytes available. Ex. If the underlying memory
|
||||
// Size returns the size in bytes available. e.g. If the underlying memory
|
||||
// has 1 page: 65536
|
||||
//
|
||||
// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#-hrefsyntax-instr-memorymathsfmemorysize%E2%91%A0
|
||||
|
||||
23
builder.go
23
builder.go
@@ -8,12 +8,13 @@ import (
|
||||
)
|
||||
|
||||
// HostModuleBuilder is a way to define host functions (in Go), so that a
|
||||
// WebAssembly binary (ex. %.wasm file) can import and use them.
|
||||
// WebAssembly binary (e.g. %.wasm file) can import and use them.
|
||||
//
|
||||
// Specifically, this implements the host side of an Application Binary
|
||||
// Interface (ABI) like WASI or AssemblyScript.
|
||||
//
|
||||
// Ex. Below defines and instantiates a module named "env" with one function:
|
||||
// For example, this defines and instantiates a module named "env" with one
|
||||
// function:
|
||||
//
|
||||
// ctx := context.Background()
|
||||
// r := wazero.NewRuntime(ctx)
|
||||
@@ -27,7 +28,7 @@ import (
|
||||
// Instantiate(ctx, r)
|
||||
//
|
||||
// If the same module may be instantiated multiple times, it is more efficient
|
||||
// to separate steps. Ex.
|
||||
// to separate steps. Here's an example:
|
||||
//
|
||||
// compiled, _ := r.NewHostModuleBuilder("env").
|
||||
// ExportFunction("get_random_string", getRandomString).
|
||||
@@ -75,7 +76,7 @@ type HostModuleBuilder interface {
|
||||
// - names - If present, the first is the api.FunctionDefinition name.
|
||||
// If any follow, they must match the count of goFunc's parameters.
|
||||
//
|
||||
// Ex.
|
||||
// Here's an example:
|
||||
// // Just export the function, and use "abort" in stack traces.
|
||||
// builder.ExportFunction("abort", env.abort)
|
||||
// // Ensure "~lib/builtins/abort" is used in stack traces.
|
||||
@@ -90,7 +91,7 @@ type HostModuleBuilder interface {
|
||||
// types must match WebAssembly 1.0 (20191205) value types. This means
|
||||
// uint32, uint64, float32 or float64. Up to one result can be returned.
|
||||
//
|
||||
// Ex. This is a valid host function:
|
||||
// For example, this is a valid host function:
|
||||
//
|
||||
// addInts := func(x, y uint32) uint32 {
|
||||
// return x + y
|
||||
@@ -99,16 +100,16 @@ type HostModuleBuilder interface {
|
||||
// Host functions may also have an initial parameter (param[0]) of type
|
||||
// context.Context or api.Module.
|
||||
//
|
||||
// Ex. This uses a Go Context:
|
||||
// For example, this uses a Go Context:
|
||||
//
|
||||
// addInts := func(ctx context.Context, x, y uint32) uint32 {
|
||||
// // add a little extra if we put some in the context!
|
||||
// return x + y + ctx.Value(extraKey).(uint32)
|
||||
// }
|
||||
//
|
||||
// Ex. This uses an api.Module to reads the parameters from 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.
|
||||
// The example below uses an api.Module to read parameters from 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.
|
||||
//
|
||||
// addInts := func(ctx context.Context, m api.Module, offset uint32) uint32 {
|
||||
// x, _ := m.Memory().ReadUint32Le(ctx, offset)
|
||||
@@ -118,7 +119,7 @@ type HostModuleBuilder interface {
|
||||
//
|
||||
// If both parameters exist, they must be in order at positions 0 and 1.
|
||||
//
|
||||
// Ex. This uses propagates context properly when calling other functions
|
||||
// This example propagates context properly when calling other functions
|
||||
// exported in the api.Module:
|
||||
// callRead := func(ctx context.Context, m api.Module, offset, byteCount uint32) uint32 {
|
||||
// fn = m.ExportedFunction("__read")
|
||||
@@ -139,7 +140,7 @@ type HostModuleBuilder interface {
|
||||
// Instantiate is a convenience that calls Compile, then Namespace.InstantiateModule.
|
||||
// This can fail for reasons documented on Namespace.InstantiateModule.
|
||||
//
|
||||
// Ex.
|
||||
// Here's an example:
|
||||
//
|
||||
// ctx := context.Background()
|
||||
// r := wazero.NewRuntime(ctx)
|
||||
|
||||
31
config.go
31
config.go
@@ -19,13 +19,16 @@ import (
|
||||
"github.com/tetratelabs/wazero/sys"
|
||||
)
|
||||
|
||||
// RuntimeConfig controls runtime behavior, with the default implementation as NewRuntimeConfig
|
||||
// RuntimeConfig controls runtime behavior, with the default implementation as
|
||||
// NewRuntimeConfig
|
||||
//
|
||||
// Ex. To explicitly limit to Wasm Core 1.0 features as opposed to relying on defaults:
|
||||
// The example below explicitly limits to Wasm Core 1.0 features as opposed to
|
||||
// relying on defaults:
|
||||
//
|
||||
// rConfig = wazero.NewRuntimeConfig().WithCoreFeatures(api.CoreFeaturesV1)
|
||||
//
|
||||
// Note: RuntimeConfig is immutable. Each WithXXX function returns a new instance including the corresponding change.
|
||||
// Note: RuntimeConfig is immutable. Each WithXXX function returns a new
|
||||
// instance including the corresponding change.
|
||||
type RuntimeConfig interface {
|
||||
// WithCoreFeatures sets the WebAssembly Core specification features this
|
||||
// runtime supports. Defaults to api.CoreFeaturesV2.
|
||||
@@ -47,7 +50,7 @@ type RuntimeConfig interface {
|
||||
// default is 65536, allowing 4GB total memory per instance. Setting a
|
||||
// value larger than default will panic.
|
||||
//
|
||||
// Ex. To reduce the largest possible memory size from 4GB to 128KB:
|
||||
// This example reduces the largest possible memory size from 4GB to 128KB:
|
||||
// rConfig = wazero.NewRuntimeConfig().WithMemoryLimitPages(2)
|
||||
//
|
||||
// Note: Wasm has 32-bit memory and each page is 65536 (2^16) bytes. This
|
||||
@@ -59,7 +62,7 @@ type RuntimeConfig interface {
|
||||
// not defined. The default is false, which means minimum memory is
|
||||
// allocated and any call to grow memory results in re-allocations.
|
||||
//
|
||||
// Ex. To ensure any memory.grow instruction will never re-allocate:
|
||||
// This example ensures any memory.grow instruction will never re-allocate:
|
||||
// rConfig = wazero.NewRuntimeConfig().WithMemoryCapacityFromMax(true)
|
||||
//
|
||||
// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#grow-mem
|
||||
@@ -243,7 +246,7 @@ func (c *compiledModule) ExportedMemories() map[string]api.MemoryDefinition {
|
||||
// system. Using this, resources such as STDIN can be isolated, so that the same module can be safely instantiated
|
||||
// multiple times.
|
||||
//
|
||||
// Ex.
|
||||
// Here's an example:
|
||||
//
|
||||
// // Initialize base configuration:
|
||||
// config := wazero.NewModuleConfig().WithStdout(buf).WithSysNanotime()
|
||||
@@ -291,7 +294,7 @@ type ModuleConfig interface {
|
||||
// WithFS assigns the file system to use for any paths beginning at "/".
|
||||
// Defaults return fs.ErrNotExist.
|
||||
//
|
||||
// Ex. This sets a read-only, embedded file-system:
|
||||
// This example sets a read-only, embedded file-system:
|
||||
//
|
||||
// //go:embed testdata/index.html
|
||||
// var testdataIndex embed.FS
|
||||
@@ -302,7 +305,7 @@ type ModuleConfig interface {
|
||||
// // "index.html" is accessible as "/index.html".
|
||||
// config := wazero.NewModuleConfig().WithFS(rooted)
|
||||
//
|
||||
// Ex. This sets a mutable file-system:
|
||||
// This example sets a mutable file-system:
|
||||
//
|
||||
// // Files relative to "/work/appA" are accessible as "/".
|
||||
// config := wazero.NewModuleConfig().WithFS(os.DirFS("/work/appA"))
|
||||
@@ -330,7 +333,7 @@ type ModuleConfig interface {
|
||||
// - If any function doesn't exist, it is skipped. However, all functions
|
||||
// that do exist are called in order.
|
||||
// - Some start functions may exit the module during instantiate with a
|
||||
// sys.ExitError (ex. emscripten), preventing use of exported functions.
|
||||
// sys.ExitError (e.g. emscripten), preventing use of exported functions.
|
||||
WithStartFunctions(...string) ModuleConfig
|
||||
|
||||
// WithStderr configures where standard error (file descriptor 2) is written. Defaults to io.Discard.
|
||||
@@ -376,7 +379,7 @@ type ModuleConfig interface {
|
||||
// real time clock. Defaults to a fake result that increases by 1ms on
|
||||
// each reading.
|
||||
//
|
||||
// Ex. To override with your own clock:
|
||||
// Here's an example that uses a custom clock:
|
||||
// moduleConfig = moduleConfig.
|
||||
// WithWalltime(func(context.Context) (sec int64, nsec int32) {
|
||||
// return clock.walltime()
|
||||
@@ -396,7 +399,7 @@ type ModuleConfig interface {
|
||||
// time in nanoseconds. Defaults to a fake result that increases by 1ms
|
||||
// on each reading.
|
||||
//
|
||||
// Ex. To override with your own clock:
|
||||
// Here's an example that uses a custom clock:
|
||||
// moduleConfig = moduleConfig.
|
||||
// WithNanotime(func(context.Context) int64 {
|
||||
// return clock.nanotime()
|
||||
@@ -404,7 +407,7 @@ type ModuleConfig interface {
|
||||
//
|
||||
// # Notes:
|
||||
// - This does not default to time.Since as that violates sandboxing.
|
||||
// - Some compilers implement sleep by looping on sys.Nanotime (ex. Go).
|
||||
// - Some compilers implement sleep by looping on sys.Nanotime (e.g. Go).
|
||||
// - If you set this, you should probably set WithNanosleep also.
|
||||
// - Use WithSysNanotime for a usable implementation.
|
||||
WithNanotime(sys.Nanotime, sys.ClockResolution) ModuleConfig
|
||||
@@ -417,7 +420,7 @@ type ModuleConfig interface {
|
||||
// WithNanosleep configures the how to pause the current goroutine for at
|
||||
// least the configured nanoseconds. Defaults to return immediately.
|
||||
//
|
||||
// Ex. To override with your own sleep function:
|
||||
// This example uses a custom sleep function:
|
||||
// moduleConfig = moduleConfig.
|
||||
// WithNanosleep(func(ctx context.Context, ns int64) {
|
||||
// rel := unix.NsecToTimespec(ns)
|
||||
@@ -429,7 +432,7 @@ type ModuleConfig interface {
|
||||
// # Notes:
|
||||
// - This primarily supports `poll_oneoff` for relative clock events.
|
||||
// - This does not default to time.Sleep as that violates sandboxing.
|
||||
// - Some compilers implement sleep by looping on sys.Nanotime (ex. Go).
|
||||
// - Some compilers implement sleep by looping on sys.Nanotime (e.g. Go).
|
||||
// - If you set this, you should probably set WithNanotime also.
|
||||
// - Use WithSysNanosleep for a usable implementation.
|
||||
WithNanosleep(sys.Nanosleep) ModuleConfig
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
This example shows how to pass strings in and out of a Wasm function defined
|
||||
in Rust, built with `cargo build --release --target wasm32-unknown-unknown`
|
||||
|
||||
Ex.
|
||||
```bash
|
||||
$ go run greet.go wazero
|
||||
Hello, wazero!
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
This example shows how to pass strings in and out of a Wasm function defined
|
||||
in TinyGo, built with `tinygo build -o greet.wasm -scheduler=none -target=wasi greet.go`
|
||||
|
||||
Ex.
|
||||
```bash
|
||||
$ go run greet.go wazero
|
||||
wasm >> Hello, wazero!
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
This example shows how to pass strings in and out of a Wasm function defined in
|
||||
Zig, built with `zig build`.
|
||||
|
||||
Ex.
|
||||
```bash
|
||||
$ go run greet.go wazero
|
||||
wasm >> Hello, wazero!
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
This example shows how to extend a Go application with an addition function
|
||||
defined in WebAssembly.
|
||||
|
||||
Ex.
|
||||
```bash
|
||||
$ go run add.go 7 9
|
||||
7 + 9 = 16
|
||||
|
||||
@@ -53,6 +53,6 @@ type FunctionListener interface {
|
||||
// TODO: Errors aren't handled, and the After hook should accept one along with the result values.
|
||||
|
||||
// TODO: The context parameter of the After hook is not the same as the Before hook. This means interceptor patterns
|
||||
// are awkward. Ex. something like timing is difficult as it requires propagating a stack. Otherwise, nested calls will
|
||||
// are awkward. e.g. something like timing is difficult as it requires propagating a stack. Otherwise, nested calls will
|
||||
// overwrite each other's "since" time. Propagating a stack is further awkward as the After hook needs to know the
|
||||
// position to read from which might be subtle.
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
Packages in this directory implement the *host* imports needed for specific
|
||||
languages or shared compiler toolchains.
|
||||
|
||||
* [AssemblyScript](assemblyscript) Ex. `asc X.ts --debug -b none -o X.wasm`
|
||||
* [Emscripten](emscripten) Ex. `em++ ... -s STANDALONE_WASM -o X.wasm X.cc`
|
||||
* [Go](go) Ex. `GOARCH=wasm GOOS=js go build -o X.wasm X.go`
|
||||
* [WASI](wasi_snapshot_preview1) Ex. `tinygo build -o X.wasm -target=wasi X.go`
|
||||
* [AssemblyScript](assemblyscript) e.g. `asc X.ts --debug -b none -o X.wasm`
|
||||
* [Emscripten](emscripten) e.g. `em++ ... -s STANDALONE_WASM -o X.wasm X.cc`
|
||||
* [Go](go) e.g. `GOARCH=wasm GOOS=js go build -o X.wasm X.go`
|
||||
* [WASI](wasi_snapshot_preview1) e.g. `tinygo build -o X.wasm -target=wasi X.go`
|
||||
|
||||
Note: You may not see a language listed here because it either works without
|
||||
host imports, or it uses WASI. Refer to https://wazero.io/languages/ for more.
|
||||
|
||||
@@ -195,7 +195,7 @@ var traceStderr = traceStdout.MustGoFunc(func(
|
||||
traceTo(ctx, mod, message, nArgs, arg0, arg1, arg2, arg3, arg4, mod.(*wasm.CallContext).Sys.Stderr())
|
||||
})
|
||||
|
||||
// traceTo implements the function "trace" in AssemblyScript. Ex.
|
||||
// traceTo implements the function "trace" in AssemblyScript. e.g.
|
||||
//
|
||||
// trace('Hello World!')
|
||||
//
|
||||
|
||||
@@ -9,7 +9,6 @@ AssemblyScript `abort` built-in function.
|
||||
|
||||
This demo configures AssemblyScript imports for errors and trace messages.
|
||||
|
||||
Ex.
|
||||
```bash
|
||||
$ go run assemblyscript.go 7
|
||||
hello_world returned: 10
|
||||
|
||||
@@ -16,7 +16,7 @@ import (
|
||||
// https://linux.die.net/man/3/errno
|
||||
type Errno = uint32 // neither uint16 nor an alias for parity with wasm.ValueType
|
||||
|
||||
// ErrnoName returns the POSIX error code name, except ErrnoSuccess, which is not an error. Ex. Errno2big -> "E2BIG"
|
||||
// ErrnoName returns the POSIX error code name, except ErrnoSuccess, which is not an error. e.g. Errno2big -> "E2BIG"
|
||||
func ErrnoName(errno Errno) string {
|
||||
return internalwasi.ErrnoName(errno)
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ to use Wasm built with "tinygo". Here are the included examples:
|
||||
* [tinygo](testdata/tinygo) - Built via `tinygo build -o cat.wasm -scheduler=none --no-debug -target=wasi cat.go`
|
||||
* [zig-cc](testdata/zig-cc) - Built via `zig cc cat.c -o cat.wasm --target=wasm32-wasi -O3`
|
||||
|
||||
Ex. To run the same example with zig-cc:
|
||||
To run the same example with zig-cc:
|
||||
```bash
|
||||
$ TOOLCHAIN=zig-cc go run cat.go /test.txt
|
||||
greet filesystem
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
// are accessible from WebAssembly-defined functions via importing ModuleName.
|
||||
// All WASI functions return a single Errno result: ErrnoSuccess on success.
|
||||
//
|
||||
// Ex. Call Instantiate before instantiating any wasm binary that imports
|
||||
// e.g. Call Instantiate before instantiating any wasm binary that imports
|
||||
// "wasi_snapshot_preview1", Otherwise, it will error due to missing imports.
|
||||
//
|
||||
// ctx := context.Background()
|
||||
|
||||
@@ -22,7 +22,7 @@ type arm64Compiler struct {
|
||||
// locationStack holds the state of wazeroir virtual stack.
|
||||
// and each item is either placed in register or the actual memory stack.
|
||||
locationStack *runtimeValueLocationStack
|
||||
// labels maps a label (Ex. ".L1_then") to *arm64LabelInfo.
|
||||
// labels maps a label (e.g. ".L1_then") to *arm64LabelInfo.
|
||||
labels map[string]*arm64LabelInfo
|
||||
// stackPointerCeil is the greatest stack pointer value (from runtimeValueLocationStack) seen during compilation.
|
||||
stackPointerCeil uint64
|
||||
|
||||
@@ -61,7 +61,7 @@ var StringVal = spfunc.MustCallFromSP(false, wasm.NewGoFunc(
|
||||
))
|
||||
|
||||
// ValueGet implements js.valueGet, which is used to load a js.Value property
|
||||
// by name, ex. `v.Get("address")`. Notably, this is used by js.handleEvent to
|
||||
// by name, e.g. `v.Get("address")`. Notably, this is used by js.handleEvent to
|
||||
// get the pending event.
|
||||
//
|
||||
// See https://github.com/golang/go/blob/go1.19/src/syscall/js/js.go#L295
|
||||
@@ -95,7 +95,7 @@ var ValueGet = spfunc.MustCallFromSP(false, wasm.NewGoFunc(
|
||||
))
|
||||
|
||||
// ValueSet implements js.valueSet, which is used to store a js.Value property
|
||||
// by name, ex. `v.Set("address", a)`. Notably, this is used by js.handleEvent
|
||||
// by name, e.g. `v.Set("address", a)`. Notably, this is used by js.handleEvent
|
||||
// set the event result.
|
||||
//
|
||||
// See https://github.com/golang/go/blob/go1.19/src/syscall/js/js.go#L309
|
||||
@@ -122,7 +122,7 @@ var ValueSet = spfunc.MustCallFromSP(false, wasm.NewGoFunc(
|
||||
return
|
||||
}
|
||||
} else if m, ok := v.(*object); ok {
|
||||
m.properties[p] = x // Ex. opt.Set("method", req.Method)
|
||||
m.properties[p] = x // e.g. opt.Set("method", req.Method)
|
||||
return
|
||||
}
|
||||
panic(fmt.Errorf("TODO: valueSet(v=%v, p=%s, x=%v)", v, p, x))
|
||||
@@ -135,7 +135,7 @@ var ValueSet = spfunc.MustCallFromSP(false, wasm.NewGoFunc(
|
||||
var ValueDelete = stubFunction(functionValueDelete)
|
||||
|
||||
// ValueIndex implements js.valueIndex, which is used to load a js.Value property
|
||||
// by index, ex. `v.Index(0)`. Notably, this is used by js.handleEvent to read
|
||||
// by index, e.g. `v.Index(0)`. Notably, this is used by js.handleEvent to read
|
||||
// event arguments
|
||||
//
|
||||
// See https://github.com/golang/go/blob/go1.19/src/syscall/js/js.go#L334
|
||||
@@ -158,7 +158,7 @@ var ValueIndex = spfunc.MustCallFromSP(false, wasm.NewGoFunc(
|
||||
var ValueSetIndex = stubFunction(functionValueSetIndex)
|
||||
|
||||
// ValueCall implements js.valueCall, which is used to call a js.Value function
|
||||
// by name, ex. `document.Call("createElement", "div")`.
|
||||
// by name, e.g. `document.Call("createElement", "div")`.
|
||||
//
|
||||
// See https://github.com/golang/go/blob/go1.19/src/syscall/js/js.go#L394
|
||||
//
|
||||
@@ -192,7 +192,7 @@ var ValueCall = spfunc.MustCallFromSP(true, wasm.NewGoFunc(
|
||||
// See https://github.com/golang/go/blob/go1.19/src/syscall/js/js.go#L413
|
||||
var ValueInvoke = stubFunction(functionValueInvoke)
|
||||
|
||||
// ValueNew implements js.valueNew, which is used to call a js.Value, ex.
|
||||
// ValueNew implements js.valueNew, which is used to call a js.Value, e.g.
|
||||
// `array.New(2)`.
|
||||
//
|
||||
// See https://github.com/golang/go/blob/go1.19/src/syscall/js/js.go#L432
|
||||
@@ -246,7 +246,7 @@ var ValueNew = spfunc.MustCallFromSP(true, wasm.NewGoFunc(
|
||||
))
|
||||
|
||||
// ValueLength implements js.valueLength, which is used to load the length
|
||||
// property of a value, ex. `array.length`.
|
||||
// property of a value, e.g. `array.length`.
|
||||
//
|
||||
// See https://github.com/golang/go/blob/go1.19/src/syscall/js/js.go#L372
|
||||
// and https://github.com/golang/go/blob/go1.19/misc/wasm/wasm_exec.js#L396-L397
|
||||
|
||||
@@ -453,25 +453,25 @@ func testCloseInFlight(t *testing.T, r wazero.Runtime) {
|
||||
closeImporting, closeImported uint32
|
||||
closeImportingCode, closeImportedCode bool
|
||||
}{
|
||||
{ // Ex. WASI proc_exit or AssemblyScript abort handler.
|
||||
{ // e.g. WASI proc_exit or AssemblyScript abort handler.
|
||||
name: "importing",
|
||||
function: "call_return_input",
|
||||
closeImporting: 1,
|
||||
},
|
||||
// TODO: A module that re-exports a function (ex "return_input") can call it after it is closed!
|
||||
{ // Ex. A function that stops the runtime.
|
||||
{ // e.g. A function that stops the runtime.
|
||||
name: "both",
|
||||
function: "call_return_input",
|
||||
closeImporting: 1,
|
||||
closeImported: 2,
|
||||
},
|
||||
{ // Ex. WASI proc_exit or AssemblyScript abort handler.
|
||||
{ // e.g. WASI proc_exit or AssemblyScript abort handler.
|
||||
name: "importing",
|
||||
function: "call_return_input",
|
||||
closeImporting: 1,
|
||||
closeImportedCode: true,
|
||||
},
|
||||
{ // Ex. WASI proc_exit or AssemblyScript abort handler.
|
||||
{ // e.g. WASI proc_exit or AssemblyScript abort handler.
|
||||
name: "importing",
|
||||
function: "call_return_input",
|
||||
closeImporting: 1,
|
||||
@@ -479,7 +479,7 @@ func testCloseInFlight(t *testing.T, r wazero.Runtime) {
|
||||
closeImportingCode: true,
|
||||
},
|
||||
// TODO: A module that re-exports a function (ex "return_input") can call it after it is closed!
|
||||
{ // Ex. A function that stops the runtime.
|
||||
{ // e.g. A function that stops the runtime.
|
||||
name: "both",
|
||||
function: "call_return_input",
|
||||
closeImporting: 1,
|
||||
|
||||
@@ -16,7 +16,7 @@ import (
|
||||
// testCtx is an arbitrary, non-default context. Non-nil also prevents linter errors.
|
||||
var testCtx = context.WithValue(context.Background(), struct{}{}, "arbitrary")
|
||||
|
||||
// ensureCompilerFastest is overridable via ldflags. Ex.
|
||||
// ensureCompilerFastest is overridable via ldflags. e.g.
|
||||
//
|
||||
// -ldflags '-X github.com/tetratelabs/wazero/internal/integration_test/vs.ensureCompilerFastest=true'
|
||||
var ensureCompilerFastest = "false"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//go:build amd64 && cgo && !windows && wasmedge
|
||||
|
||||
// Note: WasmEdge depends on manual installation of a shared library.
|
||||
// Ex. wget -qO- https://raw.githubusercontent.com/WasmEdge/WasmEdge/master/utils/install.sh | \
|
||||
// e.g. wget -qO- https://raw.githubusercontent.com/WasmEdge/WasmEdge/master/utils/install.sh | \
|
||||
// sudo bash -s -- -p /usr/local -e none -v ${WASMEDGE_VERSION}
|
||||
|
||||
package wasmedge
|
||||
|
||||
@@ -109,7 +109,7 @@ func WasmCompatMax32(x, y float32) float32 {
|
||||
// WasmCompatNearestF32 is the Wasm spec compatible variant of math.Round, used for Nearest instruction.
|
||||
// For example, this converts 1.9 to 2.0, and this has the semantics of LLVM's rint intrinsic.
|
||||
//
|
||||
// Ex. math.Round(-4.5) results in -5 while this results in -4.
|
||||
// e.g. math.Round(-4.5) results in -5 while this results in -4.
|
||||
//
|
||||
// See https://llvm.org/docs/LangRef.html#llvm-rint-intrinsic.
|
||||
func WasmCompatNearestF32(f float32) float32 {
|
||||
@@ -137,7 +137,7 @@ func WasmCompatNearestF32(f float32) float32 {
|
||||
// WasmCompatNearestF64 is the Wasm spec compatible variant of math.Round, used for Nearest instruction.
|
||||
// For example, this converts 1.9 to 2.0, and this has the semantics of LLVM's rint intrinsic.
|
||||
//
|
||||
// Ex. math.Round(-4.5) results in -5 while this results in -4.
|
||||
// e.g. math.Round(-4.5) results in -5 while this results in -4.
|
||||
//
|
||||
// See https://llvm.org/docs/LangRef.html#llvm-rint-intrinsic.
|
||||
func WasmCompatNearestF64(f float64) float64 {
|
||||
|
||||
@@ -111,7 +111,7 @@ func (c *FSContext) OpenedFile(_ context.Context, fd uint32) (*FileEntry, bool)
|
||||
// OpenFile is like syscall.Open and returns the file descriptor of the new file or an error.
|
||||
//
|
||||
// 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
|
||||
// e.g. allow os.O_RDONLY, os.O_WRONLY, or os.O_RDWR either by config flag or pattern on filename
|
||||
// See #390
|
||||
func (c *FSContext) OpenFile(_ context.Context, name string /* TODO: flags int, perm int */) (uint32, error) {
|
||||
// fs.ValidFile cannot be rooted (start with '/')
|
||||
@@ -119,7 +119,7 @@ func (c *FSContext) OpenFile(_ context.Context, name string /* TODO: flags int,
|
||||
if name[0] == '/' {
|
||||
fsOpenPath = name[1:]
|
||||
}
|
||||
fsOpenPath = path.Clean(fsOpenPath) // ex. "sub/." -> "sub"
|
||||
fsOpenPath = path.Clean(fsOpenPath) // e.g. "sub/." -> "sub"
|
||||
|
||||
f, err := c.fs.Open(fsOpenPath)
|
||||
if err != nil {
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
// 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:
|
||||
// In simplest case, dispatch:
|
||||
//
|
||||
// func TestModuleEngine_Call(t *testing.T) {
|
||||
// enginetest.RunTestModuleEngine_Call(t, NewEngine)
|
||||
// }
|
||||
//
|
||||
// Ex. Some tests using the Compiler Engine may need to guard as they use compiled features:
|
||||
// Some tests using the Compiler Engine may need to guard as they use compiled features:
|
||||
//
|
||||
// func TestModuleEngine_Call(t *testing.T) {
|
||||
// requireSupportedOSArch(t)
|
||||
@@ -907,7 +907,7 @@ func setupCallMemTests(t *testing.T, e wasm.Engine, readMem *wasm.Code, fnlf exp
|
||||
//
|
||||
// Note: This sets fields that are not needed in the interpreter, but are required by code compiled by Compiler. If a new
|
||||
// test here passes in the interpreter and segmentation faults in Compiler, check for a new field offset or a change in Compiler
|
||||
// (ex. compiler.TestVerifyOffsetValue). It is possible for all other tests to pass as that field is implicitly set by
|
||||
// (e.g. compiler.TestVerifyOffsetValue). It is possible for all other tests to pass as that field is implicitly set by
|
||||
// wasm.Store: store isn't used here for unit test precision.
|
||||
func linkModuleToEngine(module *wasm.ModuleInstance, me wasm.ModuleEngine) {
|
||||
module.Engine = me // for Compiler, links the module to the module-engine compiled from it (moduleInstanceEngineOffset).
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
|
||||
// Hammer invokes a test concurrently in P goroutines N times per goroutine.
|
||||
//
|
||||
// Ex.
|
||||
// Here's an example:
|
||||
//
|
||||
// P := 8 // max count of goroutines
|
||||
// N := 1000 // work per goroutine
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// ErrnoName returns the POSIX error code name, except ErrnoSuccess, which is not an error. Ex. Errno2big -> "E2BIG"
|
||||
// ErrnoName returns the POSIX error code name, except ErrnoSuccess, which is not an error. e.g. Errno2big -> "E2BIG"
|
||||
func ErrnoName(errno uint32) string {
|
||||
if int(errno) < len(errnoToString) {
|
||||
return errnoToString[errno]
|
||||
|
||||
@@ -18,7 +18,7 @@ func TestEncodeCode(t *testing.T) {
|
||||
}{
|
||||
{
|
||||
name: "smallest function body",
|
||||
input: &wasm.Code{ // Ex. (func)
|
||||
input: &wasm.Code{ // e.g. (func)
|
||||
Body: []byte{wasm.OpcodeEnd},
|
||||
},
|
||||
expected: []byte{
|
||||
@@ -29,7 +29,7 @@ func TestEncodeCode(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "params and instructions", // local.get index space is params, then locals
|
||||
input: &wasm.Code{ // Ex. (func (type 3) local.get 0 local.get 1 i32.add)
|
||||
input: &wasm.Code{ // e.g. (func (type 3) local.get 0 local.get 1 i32.add)
|
||||
Body: addLocalZeroLocalOne,
|
||||
},
|
||||
expected: append([]byte{
|
||||
@@ -41,7 +41,7 @@ func TestEncodeCode(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "locals and instructions",
|
||||
input: &wasm.Code{ // Ex. (func (result i32) (local i32, i32) local.get 0 local.get 1 i32.add)
|
||||
input: &wasm.Code{ // e.g. (func (result i32) (local i32, i32) local.get 0 local.get 1 i32.add)
|
||||
LocalTypes: []wasm.ValueType{wasm.ValueTypeI32, wasm.ValueTypeI32},
|
||||
Body: addLocalZeroLocalOne,
|
||||
},
|
||||
@@ -55,7 +55,7 @@ func TestEncodeCode(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "mixed locals and instructions",
|
||||
input: &wasm.Code{ // Ex. (func (result i32) (local i32) (local i64) (local i32) local.get 0 local.get 2 i32.add)
|
||||
input: &wasm.Code{ // e.g. (func (result i32) (local i32) (local i64) (local i32) local.get 0 local.get 2 i32.add)
|
||||
LocalTypes: []wasm.ValueType{wasm.ValueTypeI32, wasm.ValueTypeI64, wasm.ValueTypeI32},
|
||||
Body: addLocalZeroLocalTwo,
|
||||
},
|
||||
@@ -82,7 +82,7 @@ func TestEncodeCode(t *testing.T) {
|
||||
}
|
||||
|
||||
func BenchmarkEncodeCode(b *testing.B) {
|
||||
input := &wasm.Code{ // Ex. (func (result i32) (local i32) (local i64) (local i32) local.get 0 local.get 2 i32.add)
|
||||
input := &wasm.Code{ // e.g. (func (result i32) (local i32) (local i64) (local i32) local.get 0 local.get 2 i32.add)
|
||||
LocalTypes: []wasm.ValueType{wasm.ValueTypeI32, wasm.ValueTypeI64, wasm.ValueTypeI32},
|
||||
Body: addLocalZeroLocalTwo,
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ func TestEncodeExport(t *testing.T) {
|
||||
}{
|
||||
{
|
||||
name: "func no name, index 0",
|
||||
input: &wasm.Export{ // Ex. (export "" (func 0)))
|
||||
input: &wasm.Export{ // e.g. (export "" (func 0)))
|
||||
Type: wasm.ExternTypeFunc,
|
||||
Name: "",
|
||||
Index: 0,
|
||||
@@ -24,7 +24,7 @@ func TestEncodeExport(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "func name, func index 0",
|
||||
input: &wasm.Export{ // Ex. (export "pi" (func 0))
|
||||
input: &wasm.Export{ // e.g. (export "pi" (func 0))
|
||||
Type: wasm.ExternTypeFunc,
|
||||
Name: "pi",
|
||||
Index: 0,
|
||||
@@ -37,7 +37,7 @@ func TestEncodeExport(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "func name, index 10",
|
||||
input: &wasm.Export{ // Ex. (export "pi" (func 10))
|
||||
input: &wasm.Export{ // e.g. (export "pi" (func 10))
|
||||
Type: wasm.ExternTypeFunc,
|
||||
Name: "pi",
|
||||
Index: 10,
|
||||
@@ -50,7 +50,7 @@ func TestEncodeExport(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "global no name, index 0",
|
||||
input: &wasm.Export{ // Ex. (export "" (global 0)))
|
||||
input: &wasm.Export{ // e.g. (export "" (global 0)))
|
||||
Type: wasm.ExternTypeGlobal,
|
||||
Name: "",
|
||||
Index: 0,
|
||||
@@ -59,7 +59,7 @@ func TestEncodeExport(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "global name, global index 0",
|
||||
input: &wasm.Export{ // Ex. (export "pi" (global 0))
|
||||
input: &wasm.Export{ // e.g. (export "pi" (global 0))
|
||||
Type: wasm.ExternTypeGlobal,
|
||||
Name: "pi",
|
||||
Index: 0,
|
||||
@@ -72,7 +72,7 @@ func TestEncodeExport(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "global name, index 10",
|
||||
input: &wasm.Export{ // Ex. (export "pi" (global 10))
|
||||
input: &wasm.Export{ // e.g. (export "pi" (global 10))
|
||||
Type: wasm.ExternTypeGlobal,
|
||||
Name: "pi",
|
||||
Index: 10,
|
||||
@@ -85,7 +85,7 @@ func TestEncodeExport(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "memory no name, index 0",
|
||||
input: &wasm.Export{ // Ex. (export "" (memory 0)))
|
||||
input: &wasm.Export{ // e.g. (export "" (memory 0)))
|
||||
Type: wasm.ExternTypeMemory,
|
||||
Name: "",
|
||||
Index: 0,
|
||||
@@ -94,7 +94,7 @@ func TestEncodeExport(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "memory name, memory index 0",
|
||||
input: &wasm.Export{ // Ex. (export "mem" (memory 0))
|
||||
input: &wasm.Export{ // e.g. (export "mem" (memory 0))
|
||||
Type: wasm.ExternTypeMemory,
|
||||
Name: "mem",
|
||||
Index: 0,
|
||||
@@ -107,7 +107,7 @@ func TestEncodeExport(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "memory name, index 10",
|
||||
input: &wasm.Export{ // Ex. (export "mem" (memory 10))
|
||||
input: &wasm.Export{ // e.g. (export "mem" (memory 10))
|
||||
Type: wasm.ExternTypeMemory,
|
||||
Name: "mem",
|
||||
Index: 10,
|
||||
|
||||
@@ -19,7 +19,7 @@ func TestEncodeImport(t *testing.T) {
|
||||
}{
|
||||
{
|
||||
name: "func no module, no name, type index 0",
|
||||
input: &wasm.Import{ // Ex. (import "" "" (func (type 0)))
|
||||
input: &wasm.Import{ // e.g. (import "" "" (func (type 0)))
|
||||
Type: wasm.ExternTypeFunc,
|
||||
Module: "",
|
||||
Name: "",
|
||||
@@ -29,7 +29,7 @@ func TestEncodeImport(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "func module, no name, type index 0",
|
||||
input: &wasm.Import{ // Ex. (import "$test" "" (func (type 0)))
|
||||
input: &wasm.Import{ // e.g. (import "$test" "" (func (type 0)))
|
||||
Type: wasm.ExternTypeFunc,
|
||||
Module: "test",
|
||||
Name: "",
|
||||
@@ -44,7 +44,7 @@ func TestEncodeImport(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "func module, name, type index 0",
|
||||
input: &wasm.Import{ // Ex. (import "$math" "$pi" (func (type 0)))
|
||||
input: &wasm.Import{ // e.g. (import "$math" "$pi" (func (type 0)))
|
||||
Type: wasm.ExternTypeFunc,
|
||||
Module: "math",
|
||||
Name: "pi",
|
||||
@@ -59,7 +59,7 @@ func TestEncodeImport(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "func module, name, type index 10",
|
||||
input: &wasm.Import{ // Ex. (import "$math" "$pi" (func (type 10)))
|
||||
input: &wasm.Import{ // e.g. (import "$math" "$pi" (func (type 10)))
|
||||
Type: wasm.ExternTypeFunc,
|
||||
Module: "math",
|
||||
Name: "pi",
|
||||
|
||||
@@ -20,7 +20,7 @@ func TestEncodeNameSectionData(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "only module",
|
||||
// Ex. (module $simple )
|
||||
// e.g. (module $simple )
|
||||
input: &wasm.NameSection{ModuleName: "simple"},
|
||||
expected: []byte{
|
||||
subsectionIDModuleName, 0x07, // 7 bytes
|
||||
@@ -50,7 +50,7 @@ func TestEncodeNameSectionData(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "two function names", // Ex. TinyGo which at one point didn't set a module name
|
||||
name: "two function names", // e.g. TinyGo which at one point didn't set a module name
|
||||
// (module
|
||||
// (import "wasi_snapshot_preview1" "args_sizes_get" (func $wasi.args_sizes_get (param i32, i32) (result i32)))
|
||||
// (import "wasi_snapshot_preview1" "fd_write" (func $wasi.fd_write (param i32, i32, i32, i32) (result i32)))
|
||||
|
||||
@@ -67,6 +67,8 @@ func PopValues(count int, popper func() uint64) []uint64 {
|
||||
return params
|
||||
}
|
||||
|
||||
type HostFn func(ctx context.Context, mod api.Module, params ...uint64) ([]uint64, error)
|
||||
|
||||
// CallGoFunc executes the FunctionInstance.GoFunc by converting params to Go types. The results of the function call
|
||||
// are converted back to api.ValueType.
|
||||
//
|
||||
|
||||
@@ -207,7 +207,7 @@ func (m *MemoryInstance) PageSize(_ context.Context) (result uint32) {
|
||||
return memoryBytesNumToPages(uint64(len(m.Buffer)))
|
||||
}
|
||||
|
||||
// PagesToUnitOfBytes converts the pages to a human-readable form similar to what's specified. Ex. 1 -> "64Ki"
|
||||
// PagesToUnitOfBytes converts the pages to a human-readable form similar to what's specified. e.g. 1 -> "64Ki"
|
||||
//
|
||||
// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#memory-instances%E2%91%A0
|
||||
func PagesToUnitOfBytes(pages uint32) string {
|
||||
|
||||
@@ -66,7 +66,7 @@ type Module struct {
|
||||
// For example, if there are two imported functions and one defined in this module, the function Index 3 is defined
|
||||
// in this module at FunctionSection[0].
|
||||
//
|
||||
// Note: FunctionSection is index correlated with the CodeSection. If given the same position, ex. 2, a function
|
||||
// Note: FunctionSection is index correlated with the CodeSection. If given the same position, e.g. 2, a function
|
||||
// type is at TypeSection[FunctionSection[2]], while its locals and body are at CodeSection[2].
|
||||
//
|
||||
// Note: In the Binary Format, this is SectionIDFunction.
|
||||
@@ -700,7 +700,7 @@ func (f *FunctionType) EqualsSignature(params []ValueType, results []ValueType)
|
||||
return bytes.Equal(f.Params, params) && bytes.Equal(f.Results, results)
|
||||
}
|
||||
|
||||
// key gets or generates the key for Store.typeIDs. Ex. "i32_v" for one i32 parameter and no (void) result.
|
||||
// key gets or generates the key for Store.typeIDs. e.g. "i32_v" for one i32 parameter and no (void) result.
|
||||
func (f *FunctionType) key() string {
|
||||
if f.string != "" {
|
||||
return f.string
|
||||
@@ -800,7 +800,7 @@ type Export struct {
|
||||
Name string
|
||||
|
||||
// Index is the index of the definition to export, the index namespace is by Type
|
||||
// Ex. If ExternTypeFunc, this is a position in the function index namespace.
|
||||
// e.g. If ExternTypeFunc, this is a position in the function index namespace.
|
||||
Index Index
|
||||
}
|
||||
|
||||
@@ -855,17 +855,17 @@ func (d *DataSegment) IsPassive() bool {
|
||||
// Note: This can be nil if no names were decoded for any reason including configuration.
|
||||
// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#name-section%E2%91%A0
|
||||
type NameSection struct {
|
||||
// ModuleName is the symbolic identifier for a module. Ex. math
|
||||
// ModuleName is the symbolic identifier for a module. e.g. math
|
||||
//
|
||||
// Note: This can be empty for any reason including configuration.
|
||||
ModuleName string
|
||||
|
||||
// FunctionNames is an association of a function index to its symbolic identifier. Ex. add
|
||||
// FunctionNames is an association of a function index to its symbolic identifier. e.g. add
|
||||
//
|
||||
// * the key (idx) is in the function namespace, where module defined functions are preceded by imported ones.
|
||||
// See https://www.w3.org/TR/2019/REC-wasm-core-1-20191205/#functions%E2%91%A7
|
||||
//
|
||||
// Ex. Assuming the below text format is the second import, you would expect FunctionNames[1] = "mul"
|
||||
// For example, assuming the below text format is the second import, you would expect FunctionNames[1] = "mul"
|
||||
// (import "Math" "Mul" (func $mul (param $x f32) (param $y f32) (result f32)))
|
||||
//
|
||||
// Note: FunctionNames are only used for debugging. At runtime, functions are called based on raw numeric index.
|
||||
@@ -874,7 +874,8 @@ type NameSection struct {
|
||||
|
||||
// LocalNames contains symbolic names for function parameters or locals that have one.
|
||||
//
|
||||
// Note: In the Text Format, function local names can inherit parameter names from their type. Ex.
|
||||
// Note: In the Text Format, function local names can inherit parameter
|
||||
// names from their type. Here are some examples:
|
||||
// * (module (import (func (param $x i32) (param i32))) (func (type 0))) = [{0, {x,0}}]
|
||||
// * (module (import (func (param i32) (param $y i32))) (func (type 0) (local $z i32))) = [0, [{y,1},{z,2}]]
|
||||
// * (module (func (param $x i32) (local $y i32) (local $z i32))) = [{x,0},{y,1},{z,2}]
|
||||
|
||||
@@ -283,8 +283,8 @@ func (m *Module) buildTables(importedTables []*TableInstance, importedGlobals []
|
||||
// WebAssembly 1.0 (20191205) doesn't forbid growing to accommodate element segments, and spectests are inconsistent.
|
||||
// For example, the spectests enforce elements within Table limitsType.Min, but ignore Import.DescTable min. What this
|
||||
// means is we have to delay offset checks on imported tables until we link to them.
|
||||
// Ex. https://github.com/WebAssembly/spec/blob/wg-1.0/test/core/elem.wast#L117 wants pass on min=0 for import
|
||||
// Ex. https://github.com/WebAssembly/spec/blob/wg-1.0/test/core/elem.wast#L142 wants fail on min=0 module-defined
|
||||
// e.g. https://github.com/WebAssembly/spec/blob/wg-1.0/test/core/elem.wast#L117 wants pass on min=0 for import
|
||||
// e.g. https://github.com/WebAssembly/spec/blob/wg-1.0/test/core/elem.wast#L142 wants fail on min=0 module-defined
|
||||
func checkSegmentBounds(min uint32, requireMin uint64, idx Index) error { // uint64 in case offset was set to -1
|
||||
if requireMin > uint64(min) {
|
||||
return fmt.Errorf("%s[%d].init exceeds min table size", SectionIDName(SectionIDElement), idx)
|
||||
|
||||
@@ -135,9 +135,9 @@ func (s *stackTrace) FromRecovered(recovered interface{}) error {
|
||||
}
|
||||
|
||||
// At this point we expect the error was from a function defined by HostModuleBuilder that intentionally called panic.
|
||||
if runtimeErr, ok := recovered.(error); ok { // Ex. panic(errors.New("whoops"))
|
||||
if runtimeErr, ok := recovered.(error); ok { // e.g. panic(errors.New("whoops"))
|
||||
return fmt.Errorf("%w (recovered by wazero)\nwasm stack trace:\n\t%s", runtimeErr, stack)
|
||||
} else { // Ex. panic("whoops")
|
||||
} else { // e.g. panic("whoops")
|
||||
return fmt.Errorf("%v (recovered by wazero)\nwasm stack trace:\n\t%s", recovered, stack)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -218,7 +218,7 @@ type CompilationResult struct {
|
||||
// Here "callers" means that the call-sites which jumps to the label with br, br_if or br_table
|
||||
// instructions.
|
||||
//
|
||||
// Note: zero possible and allowed in wasm. Ex.
|
||||
// Note: zero possible and allowed in wasm. e.g.
|
||||
//
|
||||
// (block
|
||||
// (br 0)
|
||||
@@ -1767,13 +1767,13 @@ operatorSwitch:
|
||||
&OperationElemDrop{ElemIndex: elemIndex},
|
||||
)
|
||||
case wasm.OpcodeMiscTableCopy:
|
||||
// Read the source table index.
|
||||
// Read the source table inde.g.
|
||||
dst, num, err := leb128.DecodeUint32(bytes.NewReader(c.body[c.pc+1:]))
|
||||
if err != nil {
|
||||
return fmt.Errorf("reading i32.const value: %v", err)
|
||||
}
|
||||
c.pc += num
|
||||
// Read the destination table index.
|
||||
// Read the destination table inde.g.
|
||||
src, num, err := leb128.DecodeUint32(bytes.NewReader(c.body[c.pc+1:]))
|
||||
if err != nil {
|
||||
|
||||
@@ -1784,7 +1784,7 @@ operatorSwitch:
|
||||
&OperationTableCopy{SrcTableIndex: src, DstTableIndex: dst},
|
||||
)
|
||||
case wasm.OpcodeMiscTableGrow:
|
||||
// Read the source table index.
|
||||
// Read the source table inde.g.
|
||||
tableIndex, num, err := leb128.DecodeUint32(bytes.NewReader(c.body[c.pc+1:]))
|
||||
if err != nil {
|
||||
return fmt.Errorf("reading i32.const value: %v", err)
|
||||
@@ -1794,7 +1794,7 @@ operatorSwitch:
|
||||
&OperationTableGrow{TableIndex: tableIndex},
|
||||
)
|
||||
case wasm.OpcodeMiscTableSize:
|
||||
// Read the source table index.
|
||||
// Read the source table inde.g.
|
||||
tableIndex, num, err := leb128.DecodeUint32(bytes.NewReader(c.body[c.pc+1:]))
|
||||
if err != nil {
|
||||
return fmt.Errorf("reading i32.const value: %v", err)
|
||||
|
||||
@@ -17,7 +17,7 @@ type Namespace interface {
|
||||
|
||||
// InstantiateModule instantiates the module namespace or errs if the configuration was invalid.
|
||||
//
|
||||
// Ex.
|
||||
// Here's an example:
|
||||
// module, _ := n.InstantiateModule(ctx, compiled, wazero.NewModuleConfig().WithName("prod"))
|
||||
//
|
||||
// While CompiledModule is pre-validated, there are a few situations which can cause an error:
|
||||
@@ -29,7 +29,7 @@ type Namespace interface {
|
||||
// CloseWithExitCode closes all modules initialized in this Namespace with the provided exit code.
|
||||
// An error is returned if any module returns an error when closed.
|
||||
//
|
||||
// Ex.
|
||||
// Here's an example:
|
||||
// n := r.NewNamespace(ctx)
|
||||
// defer n.CloseWithExitCode(ctx, 2) // This closes all modules in this Namespace.
|
||||
//
|
||||
@@ -42,7 +42,7 @@ type Namespace interface {
|
||||
|
||||
// Closer closes modules initialized in this Namespace by delegating to CloseWithExitCode with an exit code of zero.
|
||||
//
|
||||
// Ex.
|
||||
// Here's an example:
|
||||
// n := r.NewNamespace(ctx)
|
||||
// defer n.Close(ctx) // This closes all modules in this Namespace.
|
||||
api.Closer
|
||||
|
||||
@@ -14,7 +14,7 @@ import (
|
||||
|
||||
// Runtime allows embedding of WebAssembly modules.
|
||||
//
|
||||
// Ex. The below is the basic initialization of wazero's WebAssembly Runtime.
|
||||
// The below is an example of basic initialization:
|
||||
//
|
||||
// ctx := context.Background()
|
||||
// r := wazero.NewRuntime(ctx)
|
||||
@@ -24,7 +24,7 @@ import (
|
||||
type Runtime interface {
|
||||
// NewHostModuleBuilder lets you create modules out of functions defined in Go.
|
||||
//
|
||||
// Ex. Below defines and instantiates a module named "env" with one function:
|
||||
// Below defines and instantiates a module named "env" with one function:
|
||||
//
|
||||
// ctx := context.Background()
|
||||
// hello := func() {
|
||||
@@ -50,7 +50,7 @@ type Runtime interface {
|
||||
|
||||
// InstantiateModuleFromBinary instantiates a module from the WebAssembly binary (%.wasm) or errs if invalid.
|
||||
//
|
||||
// Ex.
|
||||
// Here's an example:
|
||||
// ctx := context.Background()
|
||||
// r := wazero.NewRuntime(ctx)
|
||||
// defer r.Close(ctx) // This closes everything this Runtime created.
|
||||
@@ -103,7 +103,7 @@ type Runtime interface {
|
||||
// CloseWithExitCode closes all the modules that have been initialized in this Runtime with the provided exit code.
|
||||
// An error is returned if any module returns an error when closed.
|
||||
//
|
||||
// Ex.
|
||||
// Here's an example:
|
||||
// ctx := context.Background()
|
||||
// r := wazero.NewRuntime(ctx)
|
||||
// defer r.CloseWithExitCode(ctx, 2) // This closes everything this Runtime created.
|
||||
|
||||
@@ -8,7 +8,7 @@ process and the guest is a program compiled into the WebAssembly Binary Format,
|
||||
also known as Wasm. The first step is to take a source file and compile it into
|
||||
the Wasm bytecode.
|
||||
|
||||
Ex. If your source is in Go, you might compile it with TinyGo.
|
||||
e.g. If your source is in Go, you might compile it with TinyGo.
|
||||
```goat
|
||||
.-----------. .----------------------. .-----------.
|
||||
/ main.go /---->| tinygo -target=wasi +---->/ main.wasm /
|
||||
@@ -17,9 +17,9 @@ Ex. If your source is in Go, you might compile it with TinyGo.
|
||||
|
||||
Below are notes wazero contributed so far, in alphabetical order by language.
|
||||
|
||||
* [Go](go) Ex. `GOARCH=wasm GOOS=js go build -o X.wasm X.go`
|
||||
* [TinyGo](tinygo) Ex. `tinygo build -o X.wasm -target=wasi X.go`
|
||||
* [Rust](rust) Ex. `rustc -o X.wasm --target wasm32-wasi X.rs`
|
||||
* [Go](go) e.g. `GOARCH=wasm GOOS=js go build -o X.wasm X.go`
|
||||
* [TinyGo](tinygo) e.g. `tinygo build -o X.wasm -target=wasi X.go`
|
||||
* [Rust](rust) e.g. `rustc -o X.wasm --target wasm32-wasi X.rs`
|
||||
|
||||
wazero is a runtime that embeds in Go applications, not a web browser. As
|
||||
such, these notes bias towards backend use of WebAssembly, not browser use.
|
||||
|
||||
@@ -7,7 +7,7 @@ title = "Go"
|
||||
When `GOARCH=wasm GOOS=js`, Go's compiler targets WebAssembly Binary format
|
||||
(%.wasm).
|
||||
|
||||
Ex.
|
||||
Here's a typical compilation command:
|
||||
```bash
|
||||
$ GOOS=js GOARCH=wasm go build -o my.wasm .
|
||||
```
|
||||
@@ -62,12 +62,12 @@ values returned (such as the pid). When not supported, many functions return
|
||||
|
||||
Here are the more notable parts of Go which will not work when compiled via
|
||||
`GOARCH=wasm GOOS=js`, resulting in `syscall.ENOSYS` errors:
|
||||
* Raw network access. Ex. `net.Bind`
|
||||
* File descriptor control (`fnctl`). Ex. `syscall.Pipe`
|
||||
* Raw network access. e.g. `net.Bind`
|
||||
* File descriptor control (`fnctl`). e.g. `syscall.Pipe`
|
||||
* Arbitrary syscalls. Ex `syscall.Syscall`
|
||||
* Process control. Ex. `syscall.Kill`
|
||||
* Kernel parameters. Ex. `syscall.Sysctl`
|
||||
* Timezone-specific clock readings. Ex. `syscall.Gettimeofday`
|
||||
* Process control. e.g. `syscall.Kill`
|
||||
* Kernel parameters. e.g. `syscall.Sysctl`
|
||||
* Timezone-specific clock readings. e.g. `syscall.Gettimeofday`
|
||||
|
||||
## Memory
|
||||
|
||||
@@ -285,7 +285,6 @@ Tips:
|
||||
To test the Go you just built, you need to have `GOROOT` set to your workspace,
|
||||
and your PATH configured to find both `bin/go` and `misc/wasm/go_js_wasm_exec`.
|
||||
|
||||
Ex.
|
||||
```bash
|
||||
$ export GOROOT=$PWD
|
||||
$ export PATH=${GOROOT}/misc/wasm:${GOROOT}/bin:$PATH
|
||||
@@ -301,7 +300,7 @@ Now, you should be all set and can iterate similar to normal Go development.
|
||||
The main thing to keep in mind is where files are, and remember to set
|
||||
`GOOS=js GOARCH=wasm` when running go commands.
|
||||
|
||||
Ex. If you fixed something in the `syscall/js` package
|
||||
For example, if you fixed something in the `syscall/js` package
|
||||
(`${GOROOT}/src/syscall/js`), test it like so:
|
||||
```bash
|
||||
$ GOOS=js GOARCH=wasm go test syscall/js
|
||||
|
||||
@@ -54,7 +54,7 @@ functions you want to export to the WebAssembly host. You can read more about
|
||||
this in [The Embedded Rust Book][4].
|
||||
|
||||
Next, you'll notice the flag `--crate-type cdylib` passed to `rustc`. This
|
||||
compiles the source as a library, ex. without a `main` function.
|
||||
compiles the source as a library, e.g. without a `main` function.
|
||||
|
||||
## Disclaimer
|
||||
|
||||
|
||||
Reference in New Issue
Block a user