Commit 9fea063
committed
Add support for named imports to WASI implementations
This commit is at least an initial stab at making the `wasmtime-wasi`
and `wasmtime-wasi-http` crates compatible with "named imports" or the
`implements` field in the component model. This field enables importing
an interface under a kebab-name while annotating that it's additionally
to be considered an import of another interface's name. One example
use case for this feature is [dependency isolation][diso] when composing
two components together -- if they both import the filesystem the final
component will import the filesystem twice under two different kebab
names which means both components can have a different view of the
filesystem.
Wasmtime previously gained support for named imports and `implements` in
`bindgen!` as part of bytecodealliance#13513 where the `named_imports` option can be
specified at `bindgen!`-time which generates traits that take an extra
id-style parameter. This runtime parameter indicates which kebab-name is
being invoked through which the runtime can then dispatch on.
The goal here is to actually wire all this up in a way that's usable for
embedders. Specifically `named_imports` bindings generation is now
available for all WASIp2 and WASIp3 interfaces. Additionally all
implementations of these `id`-carrying traits are routed through the
previous implementations after locating the correct context to operate
over.
All implementations of WASI functionality are already modeled
more-or-less as methods on `Wasi*CtxView`-style types which internally
have a borrow to the actual state and the resource table to operate on.
This fits quite cleanly with named imports where conceptually what we
want is the ability to configure the context-per-kebab-name. This in
theory will keep the maintenance burden managable as there's still
largely one source of truth for the implementation. This neatly works
for all `Host`-style traits which are literally methods on
`Wasi*CtxView` types, meaning the `id`-carrying versions actually do
just acquire a `Wasi*CtxView` and then delegate the method. This
requires more finesse for `*WithStore` traits which work with `Access`
and `Accessor`, however. The `id` parameter cannot be threaded into the
`fn(..)` within the `Accessor`, so refactoring is performed where
appropriate to make the implementation of each interface a one-liner to
reduce duplication.
The end result of all of this is that this is a very large commit but
it's written in such a way that the Rust compiler in theory should catch
all mistakes. In other words we're heavily relying on the type system
and type checking here and don't ever rely on duplication of methods
that hopefully-won't-change. There's a lot of traits and a lot of
interfaces, hence the size of the commit, but conceptually everything is
intended to be pretty simple.
Some design decisions as part of this commit, in no particular order:
* IDs are represented by `wasmtime_wasi::NamedId` which is a
newtype-wrapper around `usize`. The goal here is to enable an
efficient implementation of dealing with ids. This notably forces the
embedder to derive some sort of string-to-id (and perhaps back) map
when adding items to a linker.
* All of this is opt-in and nothing is changed by default. For example
the `wasmtime` CLI does not support any of this yet -- in theory that
would require the ability to configure `-S` flags per-named-import as
opposed to all-at-once.
* Mapping a `NamedId` to a context is abstracted behind a trait rather
than dictating that a `Vec` or `HashMap` or similar is required. This
increases the cognitive load when reading code (more generics), but
avoids making this design decision within these crates and leaves
exact representations up to embedders.
* The `HasData` implementation can't reuse the preexisting `WasiCli`,
and this uses a new `WasiCliNamed<T>` instead. This enables threading
this trait-to-find-a-context to the right location for `*WithStore`
trait impls.
* Some miscellaneous `bindgen!` issues have been fixed during this
commit to ensure that this compiles and works correctly.
* An attempt has been made at documenting all the new
primitives/structs/etc here. These are sort of difficult to align
correctly unless you know what you're doing, so the documentation and
examples are intended to serve as a way of spreading this knowledge.
* One possible alternative I ended up deciding not to do was to put some
sort of map-to-context storage within each preexisting context type.
For example commit would be simpler for the `*WithStore` and
infrastructure if it reused the exact same `Self` type as all other
impls do. My thinking though is that this requires dictating the use
of a `HashMap` or something else which I was hoping to avoid.
Additionally the preexisting context structures are already minimal
enough that they're basically what you already want as the source for
each implementation, so I wanted to lean on them as much as possible.
* The main wrinkle in the new implementation is that `Accessor` carries
`fn(..)` to project out it's `D::Data<'_>` which means that it can't
close over any information. This feature needs to in theory close over
an `id: NamedId`, however, and there's no easy way to put this square
peg into a round hole. To work around this internal implementations
within `wasmtime-wasi{,-http}` now have a generic `F` parameter which
is a closure which projects data, but this closure is typically only
ever on the stack and doesn't make its way to the heap. This was one
of the more awkward things to work around in this commit.
* The design here is intentionally done to help ensure that this commit
is correct with minimal testing. It's not really feasible to duplicate
the entire test suite just for named imports but these are duplicate
trait impls which otherwise shouldn't be wrong. By ensuring that
there's either strict delegation or each-function-is-at-least-one-line
that the light amount of testing here is sufficient for keeping this
working over time.
[diso]: spinframework/spin#37081 parent 84dbb9f commit 9fea063
68 files changed
Lines changed: 7413 additions & 653 deletions
File tree
- crates
- component-macro/tests
- expanded
- test-programs/src/bin
- wasi-http
- src
- p2
- p3
- host
- tests/all
- p2
- p3
- wasi
- src
- p2
- host
- p3
- cli
- clocks
- filesystem
- random
- sockets
- host
- types
- sockets
- tests/all
- p2
- p3
- wit-bindgen/src
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1028 | 1028 | | |
1029 | 1029 | | |
1030 | 1030 | | |
| 1031 | + | |
| 1032 | + | |
| 1033 | + | |
| 1034 | + | |
| 1035 | + | |
| 1036 | + | |
| 1037 | + | |
| 1038 | + | |
| 1039 | + | |
| 1040 | + | |
| 1041 | + | |
| 1042 | + | |
| 1043 | + | |
| 1044 | + | |
| 1045 | + | |
| 1046 | + | |
| 1047 | + | |
| 1048 | + | |
| 1049 | + | |
| 1050 | + | |
| 1051 | + | |
| 1052 | + | |
| 1053 | + | |
| 1054 | + | |
| 1055 | + | |
| 1056 | + | |
| 1057 | + | |
| 1058 | + | |
| 1059 | + | |
| 1060 | + | |
| 1061 | + | |
| 1062 | + | |
| 1063 | + | |
| 1064 | + | |
| 1065 | + | |
| 1066 | + | |
| 1067 | + | |
| 1068 | + | |
| 1069 | + | |
| 1070 | + | |
| 1071 | + | |
| 1072 | + | |
| 1073 | + | |
| 1074 | + | |
| 1075 | + | |
| 1076 | + | |
| 1077 | + | |
| 1078 | + | |
| 1079 | + | |
| 1080 | + | |
| 1081 | + | |
| 1082 | + | |
| 1083 | + | |
| 1084 | + | |
| 1085 | + | |
| 1086 | + | |
| 1087 | + | |
| 1088 | + | |
1031 | 1089 | | |
1032 | 1090 | | |
1033 | 1091 | | |
| |||
Lines changed: 13 additions & 13 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 13 additions & 13 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 13 additions & 13 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 13 additions & 13 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 36 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
Lines changed: 45 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
0 commit comments