Commit Graph

22 Commits

Author SHA1 Message Date
Crypt Keeper
a1dc1f56a0 wasi: stops enforcing _start function export (#409)
Currently, we have custom code in wapc-go because our library forces a
failure when a module that uses WASI doesn't define a "_start" function.
Using the same pragmatism that resulted in us not enforcing the WASI
table, this makes the "_start" function optional. This doesn't add a
flag as the spec is not a proper version anyway (snapshot-01), so
there's no need to further complicate configuration.

If a "_start" function exists, we enforce it is of the proper signature
and succeeds. Otherwise, we allow it to be absent.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
Co-authored-by: Takeshi Yoneda <takeshi@tetrate.io>
2022-03-25 07:34:30 +08:00
Crypt Keeper
000cbdeb54 wasi: replaces existing filesystem apis with fs.FS (#394)
Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-03-24 15:35:17 +08:00
Crypt Keeper
59617a24c8 wasi: renames WASIConfig to SysConfig and makes stdio defaults safer (#396)
This introduces `SysConfig` to replace `WASIConfig` and formalize documentation around system calls.

The only incompatible change planned after this is to switch from wasi.FS to fs.FS

Implementation Notes:

Defaulting to os.Stdin os.Stdout and os.Stderr doesn't make sense for
the same reasons as why we don't propagate ENV or ARGV: it violates
sand-boxing. Moreover, these are worse as they prevent concurrency and
can also lead to console overload if accidentally not overridden.

This also changes default stdin to read EOF as that is safer than reading
from os.DevNull, which can run the host out of file descriptors.

Finally, this removes "WithPreopens" for "WithFS" and "WithWorkDirFS",
to focus on the intended result. Similar Docker, if the WorkDir isn't set, it
defaults to the same as root.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-03-23 12:58:55 +08:00
Crypt Keeper
9a0f7f6bc6 wasi: moves system resource management to the importing module (#401)
The prior design had a problem, where multiple imports of WASI would end
up having different file descriptors for the same file. Moreover, there
was no means to close any of these when a module importing WASI was
closed.

This moves all existing functionality to a new type SystemContext, which
is owned by the importing module, similar to how it owns its memory.
While this PR doesn't fix some problems such as unclosed files, the code
is now organized in a way it can be, and these issues will be resolved
by #394.

In order to fix scope, `WASISnapshotPreview1WithConfig` had to be
removed.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-03-22 07:58:31 +08:00
Crypt Keeper
8d6ed5651b wasi: moves test-only overrides out of config, simplifies error tests (#399)
This moves test-only overrides out of config in preparation of
normalized configuration. This also simplifies error tests by using the
API directly for all cases except exit.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-03-21 07:08:27 +08:00
Crypt Keeper
a8944f6098 Adds StartWASICommandWithConfig to defer configuration (#367)
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.

```go
// Initialize base configuration:
r := wazero.NewRuntime()
config := wazero.NewWASIConfig().WithStdout(buf)
wasi, _ := r.NewHostModule(wazero.WASISnapshotPreview1WithConfig(config))
decoded, _ := r.CompileModule(source)

// Assign configuration only when ready to instantiate.
module, _ := StartWASICommandWithConfig(r, decoded, config.WithArgs("rotate", "angle=90", "dir=cw"))
```

This also changes the config to be immutable since it may be reused many
times. Instead of assigning fields directly, use `WithXXX`.

Finally, this changes the examples to encourage using `.Close()`

Fixes #364

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-03-14 14:39:53 +08:00
Crypt Keeper
2114dfc492 Renames Runtime.DecodeModule to CompileModule (#351)
The best way to reduce performance impact of instantiating a module
multiple times is lowering it to wazero's IR or even generating
assembly. This renames `DecodeModule` to `CompileModule` to allow that
sort of side-effect to be obvious even if it isn't currently
implemented.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-03-09 13:59:19 +08:00
Crypt Keeper
50d9fa58a1 Runtime.NewModule -> InstantiateModule and adds ModuleBuilder (#349)
This reverts `Runtime.NewModule` back to `InstantiateModule` as it calls
more attention to the registration aspect of it, and also makes a chain
of `NewXX` more clear. This is particularly helpful as this change
introduces `ModuleBuilder` which is created by `NewModuleBuilder`.

`ModuleBuilder` is a way to define a WebAssembly 1.0 (20191205) in Go.
The first iteration allows setting the module name and exported
functions. The next PR will add globals.

Ex. Below defines and instantiates a module named "env" with one function:

```go
hello := func() {
	fmt.Fprintln(stdout, "hello!")
}
_, err := r.NewModuleBuilder("env").ExportFunction("hello", hello).InstantiateModule()
```

If the same module may be instantiated multiple times, it is more efficient to separate steps. Ex.

```go
env, err := r.NewModuleBuilder("env").ExportFunction("get_random_string", getRandomString).Build()

_, err := r.InstantiateModule(env.WithName("env.1"))
_, err := r.InstantiateModule(env.WithName("env.2"))
```

Note: Builder methods do not return errors, to allow chaining. Any validation errors are deferred until Build.
Note: Insertion order is not retained. Anything defined by this builder is sorted lexicographically on Build.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-03-09 10:39:13 +08:00
Crypt Keeper
1e4834612a Removes host-specific types (#347)
This converges host-defined modules with Wasm defined modules by
introducing a custom section for host-defined functions. The net result
are far less types and consistent initialization.

* HostModule is removed for Module
* HostFunction is removed for Function
* ModuleContext is removed for Module

Note: One impact of this is that the low-level API no longer accepts a
go context (context.Context), rather a `wasm.Module` which the function
is called in context of. This meant exposing `wasm.Module.WithContext`
to override the default.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-03-08 16:43:13 +08:00
Crypt Keeper
9d591b4ac5 untangles host module instantiation (#333)
Signed-off-by: Adrian Cole <adrian@tetrate.io>
Co-authored-by: Takeshi Yoneda <takeshi@tetrate.io>
2022-03-05 08:05:42 +08:00
Crypt Keeper
aa61087016 Reduces exports and prepares ReleaseModuleInstance for testing (#327)
This removes more exports and adds a toehold test for
`ReleaseModuleInstance` so that it can later be completed for both
wasm and host modules.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-03-04 08:55:49 +08:00
Takeshi Yoneda
759e820f77 Make store's fields private (#319)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2022-03-03 17:18:05 +09:00
Adrian Cole
76c0bfc33f Combines Store+Engine into Runtime
This simplifies state management and the amount of terminology end-users
need to learn by using one concept `Runtime` instead of two: `Engine`
and `Store`. This bridges the concepts to the specification by still
having `wazero.Runtime` implement `wasm.Store`.

The net result is that we can know for sure which "engine" is used when
decoding. This allows us a lot of flexibility especially pre-compilation
when JIT is possible.

This also changes the default to JIT based on compiler flags so that
downstream projects like wapc-go don't have to do this individually
(including tracking of which OS+Arch have JIT).

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-03-02 12:29:13 +08:00
Crypt Keeper
7c92cf4ca3 Exports wasm.ValueType and makes Functions interfaces for signature verification (#284)
This moves code for `ValueType` constants public, so that we can
centralize discussion on how values are encoded. We'll need this when
re-introducing a Globals API.

To keep complexity down in consideration that there are only 4 types, I
copied the constants into the internalwasm package. This reduces the
import complexity otherwise would have caused.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
Co-authored-by: Takaya Saeki <takaya@tetrate.io>
2022-02-24 10:04:15 +08:00
Crypt Keeper
80d0c348be Backfills integration tests of WithName to ensure bug is fixed (#283)
Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-02-23 18:29:00 +08:00
Crypt Keeper
0186e41b27 Consolidates API to config input types (#280)
This makes instantiating host or wasm-defined modules similar, by using
XXXConfig types. Doing so also allows configuration engines to seed
properties.

Since decoded modules are only usable during instantiation, this pushes
decoding inside those functions. By doing so, the API is easier to use
as it has less choices and less errors to catch. Detection is done
internally by peeking at the magic number.

See https://github.com/tetratelabs/wazero/issues/279

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-02-23 16:41:32 +08:00
Crypt Keeper
e31620a96b Adds ModuleExports.Memory and renames Memory.Len to Memory.Size (#275)
This adds a function to get an exported memory by name, allowing end
users to check ahead of time if memory writes might fail. This also
renames memory.len to size to as that's what the spec calls it.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-02-22 19:10:46 +08:00
Crypt Keeper
77813ef01b Makes API easier by returning nil when a function isn't available (#274)
Before, we emulated the map api by returning `fn, ok` to tell if a
function was there or not. This made a lot of cruft vs returning `nil`
instead, especially as many times configuration of functions is near
where they are called in the source (so they aren't likely to be nil).

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-02-22 12:31:24 +08:00
Crypt Keeper
6ff0c3cb7b wasi: ensure the context used for _start is consistent (#273)
This adds `StoreConfig.Context` to centralize assignment of the initial
context used implicitly by the WebAssembly 1.0 (MVP) start function and
also the WASI snapshot-01 "_start" exported function. This also
backfills tests and comments around propagation.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2022-02-22 10:59:26 +08:00
Crypt Keeper
3411795ac7 Adds wasm.Store API to get exported module and host functions (#266)
This adds this interface `wasm.Store` which gives access to functions in
a store without leaking an API to change the store. This is primarily to
support configuration use cases where post-initialization, there's no
need or desire to mutate the store. This also backfills codecs needed to
handle float results.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
2022-02-21 13:49:00 +08:00
Tim Bart
16f35f0d1e wasi: env initialization fix (#262)
Signed-off-by: tim <tim@pims.me>
Co-authored-by: Crypt Keeper <64215+codefromthecrypt@users.noreply.github.com>
2022-02-19 07:05:12 +08:00
Crypt Keeper
5180d2d9c3 Refactors out public API from internals (#238)
This moves to a new end-user API under the root package `wazero`. This
simplifies call sites while hardening function calls to their known
return value. Most importantly, this moves most logic internal, as
noted in the RATIONALE.md.

Ex.

```go
	// Read WebAssembly binary containing an exported "fac" function.
	source, _ := os.ReadFile("./tests/engine/testdata/fac.wasm")

	// Decode the binary as WebAssembly module.
	mod, _ := wazero.DecodeModuleBinary(source)

	// Initialize the execution environment called "store" with Interpreter-based engine.
	store := wazero.NewStore()

	// Instantiate the module, which returns its exported functions
	functions, _ := store.Instantiate(mod)

	// Get the factorial function
	fac, _ := functions.GetFunctionI64Return("fac")

	// Discover 7! is 5040
	fmt.Println(fac(context.Background(), 7))

```

PS I changed the README to factorial because the wat version of
fibonacci is not consistent with the TinyGo one!

Signed-off-by: Adrian Cole <adrian@tetrate.io>
Co-authored-by: Takaya Saeki <takaya@tetrate.io>
Co-authored-by: Takeshi Yoneda <takeshi@tetrate.io>
2022-02-17 17:39:28 +08:00