This adds a new type `internalapi.WazeroOnly` which should be embedded on types users are likely to accidentally implement despite docs saying otherwise.
Signed-off-by: Nuno Cruces <ncruces@users.noreply.github.com>
wazero uses interfaces even when they aren't intended to be implemented
by users. We relied on documentation, to suggest what is implementable,
and in some cases documented correctly types that weren't for
implementation.
However, we didn't add that boilerplate to all types, and we also forgot
to recently when it was discussed a week or two ago. This finishes the
job by boilerplating all types that aren't for implementation. This also
orders to the top when it already existed.
Later, we can choose to enforce by type as well, we didn't know how to
do that before. Basically before we just casted to our internal types,
which would stop accidental implementation for things except people
using the types for wrapping purposes.
Signed-off-by: Adrian Cole <adrian@tetrate.io>
This makes clock source configuration more clear about the timestamps
returned. Specifically, that realtime is UTC and the most common
consumers.
Signed-off-by: Adrian Cole <adrian@tetrate.io>
We currently allow clearing other config with nil, such as FSConfig.
However, we missed a spot as internally we couldn't differentiate
between name never set, or explicitly set to empty. Now, when someone
sets the module name to empty, the name in the binary section is
ignored.
Signed-off-by: Adrian Cole <adrian@tetrate.io>
In previous releases, passing a `nil` value as an FS config
did not cause any error. However, in 1.0.0-rc.1 this leads
to the creation of an invalid `adapter{fs: nil}`, which
eventually leads to a panic (nil):
(f *FileEntry) Stat(st *platform.Stat_t) =>
(r *lazyDir) file() =>
r.fs.OpenFile(".", os.O_RDONLY, 0)
with fs == nil
The backwards-compatible fix is to make Adapt()
return UnimplementedFS, and ensuring `nil` is a valid value
that config is able to handle.
However, we may want to consider returning an error somewhere,
because configuring a nil FS may be unintended.
Signed-off-by: Edoardo Vacchi <evacchi@users.noreply.github.com>
This implements WASI `sched_yield` with `sys.Osyield` that defaults to
return immediately. This is intentionally left without a built-in
alternative as common platforms such as darwin implement
`runtime.osyield` by sleeping for a microsecond. If we implemented that,
user code would be slowed down without a clear reason why.
Signed-off-by: Adrian Cole <adrian@tetrate.io>
This renames `InstantiateModuleFromBinary` to `Instantiate` to both make
first time use simpler to write and also de-complicate adding a
`WithConfig` variant as requested in #1105
End users in simple case need to change their signature like so.
```diff
- mod, err := r.InstantiateModuleFromBinary(ctx, addWasm)
+ mod, err := r.Instantiate(ctx, addWasm)
```
In practice, many will not need to change their signature because they
had to use the `InstantiateModule` function in order to assign
configuration such as the module name, filesystem or use a real clock.
Instead, they had to use the more complicated chain of `CompileModule`
and `InstantiateModule` even when only assigning config. Users in this
situation can opt into the more simplified syntax below:
```go
mod, err := r.InstantiateWithConfig(ctx, addWasm,
wazero.NewModuleConfig().WithName("adder"))
```
```diff
- mod, err := r.InstantiateModuleFromBinary(ctx, addWasm)
+ mod, err := r.Instantiate(ctx, addWasm)
```
Signed-off-by: Adrian Cole <adrian@tetrate.io>
This adds a new top-level type FSConfig, which is configured via
`ModuleConfig.WithFSConfig(fcfg)`. This implements read-only and
read-write directory mounts, something not formally supported before. It
also implements `WithFS` which adapts a normal `fs.FS`. For convenience,
we retain the old `ModuleConfig.WithFS` signature so as to not affect
existing users much. A new configuration for our emerging raw
filesystem, `FSConfig.WithSysfs()` will happen later without breaking
this API.
Here's an example:
```
moduleConfig = wazero.NewModuleConfig().
// Make the current directory read-only accessible to the guest.
WithReadOnlyDirMount(".", "/")
// Make "/tmp/wasm" accessible to the guest as "/tmp".
WithDirMount("/tmp/wasm", "/tmp")
```
Signed-off-by: Adrian Cole <adrian@tetrate.io>
This introduces the new API wazero.Cache interface which can be passed to wazero.RuntimeConfig.
Users can configure this to share the underlying compilation cache across multiple wazero.Runtime.
And along the way, this deletes the experimental file cache API as it's replaced by this new API.
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
Co-authored-by: Crypt Keeper <64215+codefromthecrypt@users.noreply.github.com>
This makes DWARF enabled by default, with an opt-out flag. This didn't
need to be experimental as the feature was requested for a long time and
there's no API impact to using it.
Signed-off-by: Adrian Cole <adrian@tetrate.io>
While most compilers will only read args/environ once, tools like WAGI
make heavy use of environment, possibly dozens of long variables. This
optimizes both args and environ for this reason and also to setup for
optimizing other functions.
Here are the notable changes:
* eagerly coerce to byte slices instead of strings
* re-use null terminated length for writing values
* avoid loops that call mem.WriteXXX internally
Signed-off-by: Adrian Cole <adrian@tetrate.io>
This switches to gofumpt and applies changes, as I've noticed working
in dapr (who uses this) that it finds some things that are annoying,
such as inconsistent block formatting in test tables.
Signed-off-by: Adrian Cole <adrian@tetrate.io>
This restores the ability to leave out the initial context parameter
when defining functions with reflection. This is important because some
projects are porting from a different library to wazero, and all the
alternatives are not contextualized.
For example, this project is porting envoy host functions, and the
original definitions (in mosn) don't have a context parameter. By being
lenient, they can migrate easier.
See 6b813482b6/pkg/proxywasm/wazero/imports_v1.go
Signed-off-by: Adrian Cole <adrian@tetrate.io>
It is more often the case that projects are enabling a freestanding
target, and that may or may not have an exporting memory depending on
how that's interpreted. This adds the ability to inspect memories
similar to how you can already inspect compiled code prior to
instantiation. For example, you can enforce an ABI constraint that
"memory" must be exported even if WASI is not in use.
Signed-off-by: Adrian Cole <adrian@tetrate.io>
We formerly introduced `MemorySizer` as a way to control capacity independently of size. This was the first and only feature in `CompileConfig`. While possibly used privately, `MemorySizer` has never been used in public GitHub code.
These APIs interfere with how we do caching of compiled modules. Notably, they can change the min or max defined in wasm, which invalidates some constants. This has also had a bad experience, forcing everyone to boilerplate`wazero.NewCompileConfig()` despite that API never being used in open source.
This addresses the use cases in a different way, by moving configuration to `RuntimeConfig` instead. This allows us to remove `MemorySizer` and `CompileConfig`, and the problems with them, yet still retaining functionality in case someone uses it.
* `RuntimeConfig.WithMemoryLimitPages(uint32)`: Prevents memory from growing to 4GB (spec limit) per instance.
* This works regardless of whether the wasm encodes max or not. If there is no max, it becomes effectively this value.
* `RuntimeConfig.WithMemoryCapacityFromMax(bool)`: Prevents reallocations (when growing).
* Wasm that never sets max will grow from min to the limit above.
Note: Those who want to change their wasm (ex insert a max where there was none), have to do that externally, ex via compiler settings or post-build transformations such as [wabin](https://github.com/tetratelabs/wabin)
Signed-off-by: Adrian Cole <adrian@tetrate.io>
We at one point considered making `ModuleBuilder` create complete
WebAssembly binaries. However, we recently spun out
[wabin](https://github.com/tetratelabs/wabin), which allows this.
Meanwhile, the features in `ModuleBuilder` were confusing and misused.
For example, the only two cases memory was exported on GitHub were done
by accident. This is because host functions act on the guest's memory,
not their own.
Hence, this removes memory and globals from host side definitions, and
renames the type to HostModuleBuilder to clarify this is not ever going
to be used to construct normal Wasm binaries.
Most importantly, this simplifies the API and reduces a lot of code. It
is important to make changes like this, particularly deleting any
experimental things that didn't end up useful.
Signed-off-by: Adrian Cole <adrian@tetrate.io>
Co-authored-by: Anuraag Agrawal <anuraaga@gmail.com>
While compilers should be conservative when targeting WebAssembly Core
features, runtimes should be lenient as otherwise people need to
constantly turn on all features. Currently, most examples have to turn
on 2.0 features because compilers such as AssemblyScript and TinyGo use
them by default. This matches the policy with the reality, and should
make first time use easier.
This top-levels an internal type as `api.CoreFeatures` and defaults to
2.0 as opposed to 1.0, our previous default. This is less cluttered than
the excess of `WithXXX` methods we had prior to implementing all
planned WebAssembly Core Specification 1.0 features.
Finally, this backfills rationale as flat config types were a distinct
decision even if feature set selection muddied the topic.
Signed-off-by: Adrian Cole <adrian@tetrate.io>
staticcheck linters broke until recent golangci-lint. Now, normal
behaviour of enforcing no nil context works again. Ex.
```
assemblyscript/assemblyscript_example_test.go:16:25: SA1012: do not pass a nil Context, even if a function permits it; pass context.TODO if you are unsure about which Context to use (staticcheck)
r := wazero.NewRuntime(nil)
```
Since default lint already checks for nil context, this removes our
permission of nil context args. The original reason we permitted nil is
no longer valid: we once allowed context to be stashed in config, and
removed that as it caused bugs. We forgot to undo allowing nil
explicitly.
Note: this doesn't particularly check in our code for nil context,
similar as we don't particularly check in our code for nil anything
else. End users should use linters as none of our parameters should be
nil anyway.
Signed-off-by: Adrian Cole <adrian@tetrate.io>
This changes the default random source to provide deterministic values
similar to how nanotime and walltime do. This also prevents any worries
about if wasm can deplete the host's underlying source of entropy.
Signed-off-by: Adrian Cole <adrian@tetrate.io>
This simplifies FunctionListener definition by making it possible to
implement both interfaces without intermediate state. Passing the
function definition to the before/after callbacks is the key.
This also continues efforts towards Go 1.19 doc formatting.
Signed-off-by: Adrian Cole <adrian@tetrate.io>
This improves the experimental logging listener to show parameter name
and values like so:
```
--> ._start.command_export()
--> .__wasm_call_ctors()
--> .__wasilibc_initialize_environ()
==> wasi_snapshot_preview1.environ_sizes_get(result.environc=1048572,result.environBufSize=1048568)
<== ESUCCESS
<-- ()
==> wasi_snapshot_preview1.fd_prestat_get(fd=3,result.prestat=1048568)
<== ESUCCESS
--> .dlmalloc(2)
--> .sbrk(0)
<-- (1114112)
<-- (1060080)
--snip--
```
The convention `==>` implies it was a host function call
(def.IsHostFunction). This also improves the lifecycle by creating
listeners during compile. Finally, this backfills param names for
assemblyscript and wasi.
Signed-off-by: Adrian Cole <adrian@tetrate.io>
This top-levels `api.FunctionDefinition` which was formerly
experimental, and also adds import metadata to it. Now, it holds all
metadata known at compile time.
Here are the public API visible changes:
* api.ExportedFunction - replaced with api.FunctionDefinition as it is
usable for all types of functions.
* api.Function - `.ParamTypes/ResultTypes()` are replaced with
`.Definition().
* api.FunctionDefinition - extracted from experimental and adds
`.Import()` to get the any imported module and function name.
* experimental.FunctionDefinition - replaced with
api.FunctionDefinition.
* experimental.FunctionListenerFactory - adds first arg of the
instantiated module name, as it can be different than compiled.
* wazero.CompiledModule - Adds `.ImportedFunctions()` and changes result
type of `.ExportedFunctions()` to api.FunctionDefinition.
Internally, logic to create function definition are consolidated between
host and wasm-defined functions, notably wasm.Module now includes
`.BuildFunctionDefinitions()` which reduces duplication in
wasm.ModuleInstance `.BuildFunctions()`,
This obviates #681 by deleting the `ExportedFunction` type which
overlaps with this information.
This fixes#637 as it includes more metadata including imports.
Signed-off-by: Adrian Cole <adrian@tetrate.io>
Co-authored-by: Takeshi Yoneda <takeshi@tetrate.io>
Before, we introduced a type `api.ImportRenamer` to resolve conflicts
where the "env" module was shared between AssemblyScript and
user-defined functions. This API was never used in GitHub, and is
complicated.
AssemblyScript also isn't the only ABI to share the "env" module, as
other web APIs like Emscripten do also. The less complicated approach is
to have packages that need to share "env" use
`ModuleBuilder.ExportFunctions` instead, and use namespaces as needed if
there is overlap.
Signed-off-by: Adrian Cole <adrian@tetrate.io>
This changes the AssemblyScript abort handler and WASI proc_exit
implementation to panic the caller which eventually invoked close.
This ensures no code executes afterwards, For example, LLVM inserts
unreachable instructions after calls to exit.
See https://github.com/emscripten-core/emscripten/issues/12322
See #601
Signed-off-by: Adrian Cole <adrian@tetrate.io>
This removes WithWorkDirFS and any other attempts to resolve the current directory (".") in host functions. This is a reaction to reality of compilers who track this inside wasm (not via host functions). One nice side effect is substantially simpler internal implementation of file-systems.
This also allows experimental.WithFS to block file access via passing nil.
Signed-off-by: Adrian Cole <adrian@tetrate.io>
This implements wasi_snapshot_preview1.poll_oneoff for relative clock events,
and in doing so stubs `Nanosleep` which defaults to noop, but can be configured
to `time.Sleep`.
Signed-off-by: Adrian Cole <adrian@tetrate.io>
This ensures fake clocks increment so that compilers that implement
sleep with them don't spin.
This also fixes a mutability bug in config where we weren't really doing
clone properly because map references are shared.
Signed-off-by: Adrian Cole <adrian@tetrate.io>
This adds two clock interfaces: sys.Walltime and sys.Nanotime to
allow implementations to override readings for purposes of security or
determinism.
The default values of both are a fake timestamp, to avoid the sandbox
break we formerly had by returning the real time. This is similar to how
we don't inherit OS Env values.
This drops the text format (%.wat) and renames
InstantiateModuleFromCode to InstantiateModuleFromBinary as it is no
longer ambiguous.
We decided to stop supporting the text format as it isn't typically used
in production, yet costs a lot of work to develop. Given the resources
available and the increased work added with WebAssembly 2.0 and soon
WASI 2, we can't afford to spend the time on it.
The old parser is used only internally and will eventually be moved to
its own repository named watzero, possibly towards archival.
See #59
Signed-off-by: Adrian Cole <adrian@tetrate.io>
I researched what is available for improving godoc. Notably, this does
the following on every non-internal go file (tests excluded).
* consolidates links where there's a better single one
* wraps See where there are multiple relevant links
* reduces use of Note: where possible
* Uses preformatting for bullets similar to gob
* Uses titles where appropriate
I looked into it and while there are many ways to re-render godoc into
markdown, there are limited options on what to do in godoc itself. There
are tricks implicitly used where preformatting (tab indent) is used to
avoid having to add extra lines everywhere. This is done in gob, for
example.
See https://go.dev/src/encoding/gob/doc.go
See https://github.com/fluhus/godoc-tricks/blob/master/doc.go
See #426
Signed-off-by: Adrian Cole <adrian@tetrate.io>
This consolidates the pattern used for context overrides, notably
replacing clock overrides via experimental.WithTimeNowUnixNano
and making all context keys internal.
This also makes sure experimental example tests are handled the same
way, notably backfilling one for WithFS