From 6d105f4d84fd6862ad3c3c0c2b4be01c18007705 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 5 Feb 2024 11:55:22 -0600 Subject: [PATCH] Update and add lots of docs, mostly for components (#7862) * Update and add lots of docs, mostly for components When I originally implemented the embedding API for the component model I left a lot of `// TODO: say more here` style comments assuming I'd come back around before stabilization. While I didn't quite make it in time for Wasmtime 17 this is my attempt to improve things for the future. This should add substantive documentation for all component-model related things and flesh out some more details here and there. Nowhere near comprehensive but, hey, Rome wasn't built in a day either. * Update crates/wasmtime/src/runtime/component/component.rs Co-authored-by: Jeff Parsons * Update crates/wasmtime/src/runtime/component/component.rs Co-authored-by: Jeff Parsons --------- Co-authored-by: Nick Fitzgerald Co-authored-by: Jeff Parsons --- crates/wasmtime/src/config.rs | 4 +- crates/wasmtime/src/lib.rs | 395 ++++++------------ .../src/runtime/component/component.rs | 129 +++++- crates/wasmtime/src/runtime/component/func.rs | 77 +++- .../src/runtime/component/func/typed.rs | 108 ++++- .../src/runtime/component/instance.rs | 17 +- crates/wasmtime/src/runtime/component/mod.rs | 377 +++++++++++++++-- .../wasmtime/src/runtime/component/values.rs | 150 ++++++- crates/wasmtime/src/runtime/func.rs | 17 +- crates/wasmtime/src/runtime/module.rs | 49 ++- crates/wasmtime/src/runtime/store.rs | 16 +- 11 files changed, 946 insertions(+), 393 deletions(-) diff --git a/crates/wasmtime/src/config.rs b/crates/wasmtime/src/config.rs index 944afd2558..ff98cc3c41 100644 --- a/crates/wasmtime/src/config.rs +++ b/crates/wasmtime/src/config.rs @@ -28,7 +28,9 @@ use wasmtime_fiber::RuntimeFiberStackCreator; pub use wasmtime_environ::CacheStore; #[cfg(feature = "pooling-allocator")] -pub use wasmtime_runtime::{mpk, MpkEnabled}; +use wasmtime_runtime::mpk; +#[cfg(feature = "pooling-allocator")] +pub use wasmtime_runtime::MpkEnabled; /// Represents the module instance allocation strategy to use. #[derive(Clone)] diff --git a/crates/wasmtime/src/lib.rs b/crates/wasmtime/src/lib.rs index e4278148c4..5f30104777 100644 --- a/crates/wasmtime/src/lib.rs +++ b/crates/wasmtime/src/lib.rs @@ -1,37 +1,52 @@ -//! Wasmtime's embedding API +//! # Wasmtime's embedding API //! //! Wasmtime is a WebAssembly engine for JIT-compiled or ahead-of-time compiled -//! WebAssembly modules. More information about the Wasmtime project as a whole -//! can be found [in the documentation book](https://docs.wasmtime.dev) whereas -//! this documentation mostly focuses on the API reference of the `wasmtime` -//! crate itself. -//! -//! This crate contains an API used to interact with WebAssembly modules. For -//! example you can compile modules, instantiate them, call them, etc. As an -//! embedder of WebAssembly you can also provide WebAssembly modules -//! functionality from the host by creating host-defined functions, memories, -//! globals, etc, which can do things that WebAssembly cannot (such as print to -//! the screen). -//! -//! The `wasmtime` crate has similar concepts to the -//! the [JS WebAssembly -//! API](https://developer.mozilla.org/en-US/docs/WebAssembly) as well as the -//! [proposed C API](https://github.com/webassembly/wasm-c-api), but the Rust -//! API is designed for efficiency, ergonomics, and expressivity in Rust. As -//! with all other Rust code you're guaranteed that programs will be safe (not -//! have undefined behavior or segfault) so long as you don't use `unsafe` in -//! your own program. With `wasmtime` you can easily and conveniently embed a -//! WebAssembly runtime with confidence that the WebAssembly is safely -//! sandboxed. -//! -//! An example of using Wasmtime looks like: +//! WebAssembly modules and components. More information about the Wasmtime +//! project as a whole can be found [in the documentation +//! book](https://docs.wasmtime.dev) whereas this documentation mostly focuses +//! on the API reference of the `wasmtime` crate itself. +//! +//! This crate contains an API used to interact with [WebAssembly modules] or +//! [WebAssembly components]. For example you can compile WebAssembly, create +//! instances, call functions, etc. As an embedder of WebAssembly you can also +//! provide guests functionality from the host by creating host-defined +//! functions, memories, globals, etc, which can do things that WebAssembly +//! cannot (such as print to the screen). +//! +//! [WebAssembly modules]: https://webassembly.github.io/spec +//! [WebAssembly components]: https://component-model.bytecodealliance.org +//! +//! The `wasmtime` crate is designed to be safe, efficient, and ergonomic. +//! This enables executing WebAssembly without the embedder needing to use +//! `unsafe` code, meaning that you're guaranteed there is no undefined behavior +//! or segfaults in either the WebAssembly guest or the host itself. +//! +//! The `wasmtime` crate can roughly be thought of as being split into two +//! halves: +//! +//! * One half of the crate is similar to the [JS WebAssembly +//! API](https://developer.mozilla.org/en-US/docs/WebAssembly) as well as the +//! [proposed C API](https://github.com/webassembly/wasm-c-api) and is +//! intended for working with [WebAssembly modules]. This API resides in the +//! root of the `wasmtime` crate's namespace, for example +//! [`wasmtime::Module`](`Module`). +//! +//! * The second half of the crate is for use with the [WebAssembly Component +//! Model]. The implementation of the component model is present in +//! [`wasmtime::component`](`component`) and roughly mirrors the structure for +//! core WebAssembly, for example [`component::Func`] mirrors [`Func`]. +//! +//! [WebAssembly Component Model]: https://component-model.bytecodealliance.org +//! +//! An example of using Wasmtime to run a core WebAssembly module looks like: //! //! ``` //! use wasmtime::*; //! //! fn main() -> wasmtime::Result<()> { -//! // Modules can be compiled through either the text or binary format //! let engine = Engine::default(); +//! +//! // Modules can be compiled through either the text or binary format //! let wat = r#" //! (module //! (import "host" "host_func" (func $host_hello (param i32))) @@ -43,19 +58,23 @@ //! "#; //! let module = Module::new(&engine, wat)?; //! +//! // Host functionality can be arbitrary Rust functions and is provided +//! // to guests through a `Linker`. +//! let mut linker = Linker::new(&engine); +//! linker.func_wrap("host", "host_func", |caller: Caller<'_, u32>, param: i32| { +//! println!("Got {} from WebAssembly", param); +//! println!("my host state is: {}", caller.data()); +//! })?; +//! //! // All wasm objects operate within the context of a "store". Each //! // `Store` has a type parameter to store host-specific data, which in //! // this case we're using `4` for. -//! let mut store = Store::new(&engine, 4); -//! let host_func = Func::wrap(&mut store, |caller: Caller<'_, u32>, param: i32| { -//! println!("Got {} from WebAssembly", param); -//! println!("my host state is: {}", caller.data()); -//! }); +//! let mut store: Store = Store::new(&engine, 4); //! //! // Instantiation of a module requires specifying its imports and then //! // afterwards we can fetch exports by name, as well as asserting the //! // type signature of the function with `get_typed_func`. -//! let instance = Instance::new(&mut store, &module, &[host_func.into()])?; +//! let instance = linker.instantiate(&mut store, &module)?; //! let hello = instance.get_typed_func::<(), ()>(&mut store, "hello")?; //! //! // And finally we can call the wasm! @@ -70,19 +89,13 @@ //! There are a number of core types and concepts that are important to be aware //! of when using the `wasmtime` crate: //! -//! * [`Engine`] - a global compilation environment for WebAssembly. An -//! [`Engine`] is an object that can be shared concurrently across threads and -//! is created with a [`Config`] to tweak various settings. Compilation of any -//! WebAssembly requires first configuring and creating an [`Engine`]. -//! -//! * [`Module`] - a compiled WebAssembly module. This structure represents -//! in-memory JIT code which is ready to execute after being instantiated. -//! It's often important to cache instances of a [`Module`] because creation -//! (compilation) can be expensive. Note that [`Module`] is safe to share -//! across threads, and can be created from a WebAssembly binary and an -//! [`Engine`] with [`Module::new`]. Caching can either happen with -//! [`Engine::precompile_module`] or [`Module::serialize`], feeding those -//! bytes back into [`Module::deserialize`]. +//! * [`Engine`] - a global compilation and runtime environment for WebAssembly. +//! An [`Engine`] is an object that can be shared concurrently across threads +//! and is created with a [`Config`] with many knobs for configuring +//! behavior. Compiling or executing any WebAssembly requires first +//! configuring and creating an [`Engine`]. All [`Module`]s and +//! [`Component`](component::Component)s belong to an [`Engine`], and +//! typically there's one [`Engine`] per process. //! //! * [`Store`] - container for all information related to WebAssembly objects //! such as functions, instances, memories, etc. A [`Store`][`Store`] @@ -92,19 +105,48 @@ //! required for all WebAssembly operations, such as calling a wasm function. //! The [`Store`] is passed in as a "context" to methods like [`Func::call`]. //! Dropping a [`Store`] will deallocate all memory associated with -//! WebAssembly objects within the [`Store`]. -//! -//! * [`Instance`] - an instantiated WebAssembly module. An instance is where -//! you can actually acquire a [`Func`] from, for example, to call. -//! -//! * [`Func`] - a WebAssembly (or host) function. This can be acquired as the -//! export of an [`Instance`] to call WebAssembly functions, or it can be -//! created via functions like [`Func::wrap`] to wrap host-defined -//! functionality and give it to WebAssembly. -//! -//! * [`Table`], [`Global`], [`Memory`] - other WebAssembly objects which can -//! either be defined on the host or in wasm itself (via instances). These all -//! have various ways of being interacted with like [`Func`]. +//! WebAssembly objects within the [`Store`]. A [`Store`] is cheap to create +//! and destroy and does not GC objects such as unused instances internally, +//! so it's intended to be short-lived (or no longer than the instances it +//! contains). +//! +//! * [`Linker`] (or [`component::Linker`]) - host functions are defined within +//! a linker to provide them a string-based name which can be looked up when +//! instantiating a WebAssembly module or component. Linkers are traditionally +//! populated at startup and then reused for all future instantiations of all +//! instances, assuming the set of host functions does not change over time. +//! Host functions are `Fn(..) + Send + Sync` and typically do not close over +//! mutable state. Instead it's recommended to store mutable state in the `T` +//! of [`Store`] which is accessed through [`Caller<'_, +//! T>`](crate::Caller) provided to host functions. +//! +//! * [`Module`] (or [`Component`](component::Component)) - a compiled +//! WebAssembly module or component. These structures contain compiled +//! executable code from a WebAssembly binary which is ready to execute after +//! being instantiated. These are expensive to create as they require +//! compilation of the input WebAssembly. Modules and components are safe to +//! share across threads, however. Modules and components can additionally be +//! [serialized into a list of bytes](crate::Module::serialize) to later be +//! [deserialized](crate::Module::deserialize) quickly. This enables JIT-style +//! compilation through constructors such as [`Module::new`] and AOT-style +//! compilation by having the compilation process use [`Module::serialize`] +//! and the execution process use [`Module::deserialize`]. +//! +//! * [`Instance`] (or [`component::Instance`]) - an instantiated WebAssembly +//! module or component. An instance is where you can actually acquire a +//! [`Func`] (or [`component::Func`]) from, for example, to call. +//! +//! * [`Func`] (or [`component::Func`]) - a WebAssembly function. This can be +//! acquired as the export of an [`Instance`] to call WebAssembly functions, +//! or it can be created via functions like [`Func::wrap`] to wrap +//! host-defined functionality and give it to WebAssembly. Functions also have +//! typed views as [`TypedFunc`] or [`component::TypedFunc`] for a more +//! efficient calling convention. +//! +//! * [`Table`], [`Global`], [`Memory`], [`component::Resource`] - other +//! WebAssembly objects which can either be defined on the host or in wasm +//! itself (via instances). These all have various ways of being interacted +//! with like [`Func`]. //! //! All "store-connected" types such as [`Func`], [`Memory`], etc, require the //! store to be passed in as a context to each method. Methods in wasmtime @@ -124,90 +166,6 @@ //! [`Func`] point within the [`Store`] and require the [`Store`] to be provided //! to actually access the internals of the WebAssembly function, for instance. //! -//! ## Linking -//! -//! WebAssembly modules almost always require functionality from the host to -//! perform I/O-like tasks. They might refer to quite a few pieces of host -//! functionality, WASI, or maybe even a number of other wasm modules. To assist -//! with managing this a [`Linker`] type is provided to instantiate modules. -//! -//! A [`Linker`] performs name-based resolution of the imports of a WebAssembly -//! module so the [`Linker::instantiate`] method does not take an `imports` -//! argument like [`Instance::new`] does. Methods like [`Linker::define`] or -//! [`Linker::func_wrap`] can be used to define names within a [`Linker`] to -//! later be used for instantiation. -//! -//! For example we can reimplement the above example with a `Linker`: -//! -//! ``` -//! use wasmtime::*; -//! -//! fn main() -> wasmtime::Result<()> { -//! let engine = Engine::default(); -//! let wat = r#" -//! (module -//! (import "host" "host_func" (func $host_hello (param i32))) -//! -//! (func (export "hello") -//! i32.const 3 -//! call $host_hello) -//! ) -//! "#; -//! let module = Module::new(&engine, wat)?; -//! -//! // Create a `Linker` and define our host function in it: -//! let mut linker = Linker::new(&engine); -//! linker.func_wrap("host", "host_func", |caller: Caller<'_, u32>, param: i32| { -//! println!("Got {} from WebAssembly", param); -//! println!("my host state is: {}", caller.data()); -//! })?; -//! -//! // Use the `linker` to instantiate the module, which will automatically -//! // resolve the imports of the module using name-based resolution. -//! let mut store = Store::new(&engine, 0); -//! let instance = linker.instantiate(&mut store, &module)?; -//! let hello = instance.get_typed_func::<(), ()>(&mut store, "hello")?; -//! hello.call(&mut store, ())?; -//! -//! Ok(()) -//! } -//! ``` -//! -//! The [`Linker`] type also transparently handles Commands and Reactors -//! as defined by WASI. -//! -//! ## Example Architecture -//! -//! To better understand how Wasmtime types interact with each other let's walk -//! through, at a high-level, an example of how you might use WebAssembly. In -//! our use case let's say we have a web server where we'd like to run some -//! custom WebAssembly on each request. To ensure requests are entirely isolated -//! from each other, though, we'll be creating a new [`Store`] for each -//! request. -//! -//! When the server starts, we'll start off by creating an [`Engine`] (and maybe -//! tweaking [`Config`] settings if necessary). This [`Engine`] will be the only -//! engine for the lifetime of the server itself. Next, we can compile our -//! WebAssembly. You'd create a [`Module`] through the [`Module::new`] API. -//! This will generate JIT code and perform expensive compilation tasks -//! up-front. Finally the last step of initialization would be to create a -//! [`Linker`] which will later be used to instantiate modules, adding -//! functionality like WASI to the linker too. -//! -//! After that setup, the server starts up as usual and is ready to receive -//! requests. Upon receiving a request you'd then create a [`Store`] with -//! [`Store::new`] referring to the original [`Engine`]. Using your [`Module`] -//! and [`Linker`] from before you'd then call [`Linker::instantiate`] to -//! instantiate our module for the request. Both of these operations are -//! designed to be as cheap as possible. -//! -//! With an [`Instance`] you can then invoke various exports and interact with -//! the WebAssembly module. Once the request is finished, the [`Store`] -//! is dropped and everything will be deallocated. Note that if the same -//! [`Store`] were used for every request then that would have all requests -//! sharing resources and nothing would ever get deallocated, causing memory -//! usage to baloon and would achive less isolation between requests. -//! //! ## WASI //! //! The `wasmtime` crate does not natively provide support for WASI, but you can @@ -218,36 +176,22 @@ //! //! [`wasmtime-wasi`]: https://crates.io/crates/wasmtime-wasi //! -//! ## Cross-store usage of items -//! -//! In `wasmtime` wasm items such as [`Global`] and [`Memory`] "belong" to a -//! [`Store`]. The store they belong to is the one they were created with -//! (passed in as a parameter) or instantiated with. This store is the only -//! store that can be used to interact with wasm items after they're created. -//! -//! The `wasmtime` crate will panic if the [`Store`] argument passed in to these -//! operations is incorrect. In other words it's considered a programmer error -//! rather than a recoverable error for the wrong [`Store`] to be used when -//! calling APIs. -//! //! ## Crate Features //! //! The `wasmtime` crate comes with a number of compile-time features that can //! be used to customize what features it supports. Some of these features are //! just internal details, but some affect the public API of the `wasmtime` -//! crate. Be sure to check the API you're using to see if any crate features -//! are enabled. +//! crate. Wasmtime APIs gated behind a Cargo feature should be indicated as +//! such in the documentation. //! //! * `runtime` - Enabled by default, this feature enables executing -//! WebAssembly modules. If modules are only compiled, however, this feature -//! can be disabled. +//! WebAssembly modules and components. If a compiler is not available (such +//! as `cranelift`) then [`Module::deserialize`] must be used, for example, to +//! provide an ahead-of-time compiled artifact to execute WebAssembly. //! //! * `cranelift` - Enabled by default, this features enables using Cranelift at //! runtime to compile a WebAssembly module to native code. This feature is -//! required to process and compile new WebAssembly modules. If this feature -//! is disabled then the only way to create a [`Module`] is to use the -//! [`Module::deserialize`] function with a precompiled artifact (typically -//! compiled with the same version of Wasmtime, just somewhere else). +//! required to process and compile new WebAssembly modules and components. //! //! * `cache` - Enabled by default, this feature adds support for wasmtime to //! perform internal caching of modules in a global location. This must still @@ -255,42 +199,31 @@ //! [`Config::cache_config_load_default`]. //! //! * `wat` - Enabled by default, this feature adds support for accepting the -//! text format of WebAssembly in [`Module::new`]. The text format will be +//! text format of WebAssembly in [`Module::new`] and +//! [`Component::new`](component::Component::new). The text format will be //! automatically recognized and translated to binary when compiling a //! module. //! //! * `parallel-compilation` - Enabled by default, this feature enables support -//! for compiling functions of a module in parallel with `rayon`. +//! for compiling functions in parallel with `rayon`. //! //! * `async` - Enabled by default, this feature enables APIs and runtime //! support for defining asynchronous host functions and calling WebAssembly -//! asynchronously. -//! -//! * `jitdump` - Enabled by default, this feature compiles in support for the -//! jitdump runtime profiling format. The profiler can be selected with -//! [`Config::profiler`]. +//! asynchronously. For more information see [`Config::async_support`]. //! -//! * `vtune` - Enabled by default, this feature compiles in support for VTune -//! profiling of JIT code. +//! * `profiling` - Enabled by default, this feature compiles in support for +//! profiling guest code via a number of possible strategies. See +//! [`Config::profiler`] for more information. //! //! * `all-arch` - Not enabled by default. This feature compiles in support for //! all architectures for both the JIT compiler and the `wasmtime compile` CLI -//! command. +//! command. This can be combined with [`Config::target`] to precompile +//! modules for a different platform than the host. //! //! * `pooling-allocator` - Enabled by default, this feature adds support for -//! the pooling allocation strategy enabled via -//! [`Config::allocation_strategy`]. The pooling allocator can enable more -//! efficient reuse of resources for high-concurrency and -//! high-instantiation-count scenarios. -//! -//! * `memory-init-cow` - Enabled by default, this feature builds in support -//! for, on supported platforms, initializing wasm linear memories with -//! copy-on-write heap mappings. This makes instantiation much faster by -//! `mmap`-ing the initial memory image into place instead of copying memory -//! into place, allowing sharing pages that end up only getting read. Note -//! that this is simply compile-time support and this must also be enabled at -//! run-time via [`Config::memory_init_cow`] (which is also enabled by -//! default). +//! [`PoolingAllocationConfig`] to pass to [`Config::allocation_strategy`]. +//! The pooling allocator can enable efficient reuse of resources for +//! high-concurrency and high-instantiation-count scenarios. //! //! * `demangle` - Enabled by default, this will affect how backtraces are //! printed and whether symbol names from WebAssembly are attempted to be @@ -310,98 +243,13 @@ //! will enable debugging guest code compiled to WebAssembly. This must also //! be enabled via [`Config::debug_info`] as well for guests. //! +//! * `component-model` - Enabled by default, this enables support for the +//! [`wasmtime::component`](component) API for working with components. +//! //! More crate features can be found in the [manifest] of Wasmtime itself for //! seeing what can be enabled and disabled. //! //! [manifest]: https://github.com/bytecodealliance/wasmtime/blob/main/crates/wasmtime/Cargo.toml -//! -//! ## Examples -//! -//! In addition to the examples below be sure to check out the [online embedding -//! documentation][rustdocs] as well as the [online list of examples][examples] -//! -//! [rustdocs]: https://bytecodealliance.github.io/wasmtime/lang-rust.html -//! [examples]: https://bytecodealliance.github.io/wasmtime/examples-rust-embed.html -//! -//! An example of using WASI looks like: -//! -//! ```no_run -//! # use wasmtime::*; -//! use wasmtime_wasi::sync::WasiCtxBuilder; -//! -//! # fn main() -> wasmtime::Result<()> { -//! // Compile our module and create a `Linker` which has WASI functions defined -//! // within it. -//! let engine = Engine::default(); -//! let module = Module::from_file(&engine, "foo.wasm")?; -//! let mut linker = Linker::new(&engine); -//! wasmtime_wasi::add_to_linker(&mut linker, |cx| cx)?; -//! -//! // Configure and create a `WasiCtx`, which WASI functions need access to -//! // through the host state of the store (which in this case is the host state -//! // of the store) -//! let wasi_ctx = WasiCtxBuilder::new().inherit_stdio().build(); -//! let mut store = Store::new(&engine, wasi_ctx); -//! -//! // Instantiate our module with the imports we've created, and run it. -//! let instance = linker.instantiate(&mut store, &module)?; -//! // ... -//! -//! # Ok(()) -//! # } -//! ``` -//! -//! An example of reading a string from a wasm module: -//! -//! ``` -//! use std::str; -//! -//! # use wasmtime::*; -//! # fn main() -> wasmtime::Result<()> { -//! let mut store = Store::default(); -//! let log_str = Func::wrap(&mut store, |mut caller: Caller<'_, ()>, ptr: i32, len: i32| { -//! // Use our `caller` context to learn about the memory export of the -//! // module which called this host function. -//! let mem = match caller.get_export("memory") { -//! Some(Extern::Memory(mem)) => mem, -//! _ => anyhow::bail!("failed to find host memory"), -//! }; -//! -//! // Use the `ptr` and `len` values to get a subslice of the wasm-memory -//! // which we'll attempt to interpret as utf-8. -//! let data = mem.data(&caller) -//! .get(ptr as u32 as usize..) -//! .and_then(|arr| arr.get(..len as u32 as usize)); -//! let string = match data { -//! Some(data) => match str::from_utf8(data) { -//! Ok(s) => s, -//! Err(_) => anyhow::bail!("invalid utf-8"), -//! }, -//! None => anyhow::bail!("pointer/length out of bounds"), -//! }; -//! assert_eq!(string, "Hello, world!"); -//! println!("{}", string); -//! Ok(()) -//! }); -//! let module = Module::new( -//! store.engine(), -//! r#" -//! (module -//! (import "" "" (func $log_str (param i32 i32))) -//! (func (export "foo") -//! i32.const 4 ;; ptr -//! i32.const 13 ;; len -//! call $log_str) -//! (memory (export "memory") 1) -//! (data (i32.const 4) "Hello, world!")) -//! "#, -//! )?; -//! let instance = Instance::new(&mut store, &module, &[log_str.into()])?; -//! let foo = instance.get_typed_func::<(), ()>(&mut store, "foo")?; -//! foo.call(&mut store, ())?; -//! # Ok(()) -//! # } -//! ``` #![deny(missing_docs)] #![doc(test(attr(deny(warnings))))] @@ -434,6 +282,7 @@ pub use crate::engine::*; /// This type can be used to interact with `wasmtimes`'s extensive use /// of `anyhow::Error` while still not directly depending on `anyhow`. /// This type alias is identical to `anyhow::Result`. +#[doc(no_inline)] pub use anyhow::{Error, Result}; fn _assert_send_and_sync() {} diff --git a/crates/wasmtime/src/runtime/component/component.rs b/crates/wasmtime/src/runtime/component/component.rs index 11280ef2c3..9b03c8cc2d 100644 --- a/crates/wasmtime/src/runtime/component/component.rs +++ b/crates/wasmtime/src/runtime/component/component.rs @@ -20,8 +20,36 @@ use wasmtime_runtime::{ }; /// A compiled WebAssembly Component. -// -// FIXME: need to write more docs here. +/// +/// This structure represents a compiled component that is ready to be +/// instantiated. This owns a region of virtual memory which contains executable +/// code compiled from a WebAssembly binary originally. This is the analog of +/// [`Module`](crate::Module) in the component embedding API. +/// +/// A [`Component`] can be turned into an +/// [`Instance`](crate::component::Instance) through a +/// [`Linker`](crate::component::Linker). [`Component`]s are safe to share +/// across threads. The compilation model of a component is the same as that of +/// [a module](crate::Module) which is to say: +/// +/// * Compilation happens synchronously during [`Component::new`]. +/// * The result of compilation can be saved into storage with +/// [`Component::serialize`]. +/// * A previously compiled artifact can be parsed with +/// [`Component::deserialize`]. +/// * No compilation happens at runtime for a component — everything is done +/// by the time [`Component::new`] returns. +/// +/// ## Components and `Clone` +/// +/// Using `clone` on a `Component` is a cheap operation. It will not create an +/// entirely new component, but rather just a new reference to the existing +/// component. In other words it's a shallow copy, not a deep copy. +/// +/// ## Examples +/// +/// For example usage see the documentation of [`Module`](crate::Module) as +/// [`Component`] has the same high-level API. #[derive(Clone)] pub struct Component { inner: Arc, @@ -53,10 +81,64 @@ pub(crate) struct AllCallFuncPointers { } impl Component { - /// Compiles a new WebAssembly component from the in-memory wasm image + /// Compiles a new WebAssembly component from the in-memory list of bytes /// provided. - // - // FIXME: need to write more docs here. + /// + /// The `bytes` provided can either be the binary or text format of a + /// [WebAssembly component]. Note that the text format requires the `wat` + /// feature of this crate to be enabled. This API does not support + /// streaming compilation. + /// + /// This function will synchronously validate the entire component, + /// including all core modules, and then compile all components, modules, + /// etc., found within the provided bytes. + /// + /// [WebAssembly component]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/Binary.md + /// + /// # Errors + /// + /// This function may fail and return an error. Errors may include + /// situations such as: + /// + /// * The binary provided could not be decoded because it's not a valid + /// WebAssembly binary + /// * The WebAssembly binary may not validate (e.g. contains type errors) + /// * Implementation-specific limits were exceeded with a valid binary (for + /// example too many locals) + /// * The wasm binary may use features that are not enabled in the + /// configuration of `engine` + /// * If the `wat` feature is enabled and the input is text, then it may be + /// rejected if it fails to parse. + /// + /// The error returned should contain full information about why compilation + /// failed. + /// + /// # Examples + /// + /// The `new` function can be invoked with a in-memory array of bytes: + /// + /// ```no_run + /// # use wasmtime::*; + /// # use wasmtime::component::Component; + /// # fn main() -> anyhow::Result<()> { + /// # let engine = Engine::default(); + /// # let wasm_bytes: Vec = Vec::new(); + /// let component = Component::new(&engine, &wasm_bytes)?; + /// # Ok(()) + /// # } + /// ``` + /// + /// Or you can also pass in a string to be parsed as the wasm text + /// format: + /// + /// ``` + /// # use wasmtime::*; + /// # use wasmtime::component::Component; + /// # fn main() -> anyhow::Result<()> { + /// # let engine = Engine::default(); + /// let component = Component::new(&engine, "(component (core module))")?; + /// # Ok(()) + /// # } #[cfg(any(feature = "cranelift", feature = "winch"))] #[cfg_attr(nightlydoc, doc(cfg(any(feature = "cranelift", feature = "winch"))))] pub fn new(engine: &Engine, bytes: impl AsRef<[u8]>) -> Result { @@ -66,10 +148,11 @@ impl Component { Component::from_binary(engine, &bytes) } - /// Compiles a new WebAssembly component from a wasm file on disk pointed to - /// by `file`. - // - // FIXME: need to write more docs here. + /// Compiles a new WebAssembly component from a wasm file on disk pointed + /// to by `file`. + /// + /// This is a convenience function for reading the contents of `file` on + /// disk and then calling [`Component::new`]. #[cfg(any(feature = "cranelift", feature = "winch"))] #[cfg_attr(nightlydoc, doc(cfg(any(feature = "cranelift", feature = "winch"))))] pub fn from_file(engine: &Engine, file: impl AsRef) -> Result { @@ -94,8 +177,13 @@ impl Component { /// Compiles a new WebAssembly component from the in-memory wasm image /// provided. - // - // FIXME: need to write more docs here. + /// + /// This function is the same as [`Component::new`] except that it does not + /// accept the text format of WebAssembly. Even if the `wat` feature + /// is enabled an error will be returned here if `binary` is the text + /// format. + /// + /// For more information on semantics and errors see [`Component::new`]. #[cfg(any(feature = "cranelift", feature = "winch"))] #[cfg_attr(nightlydoc, doc(cfg(any(feature = "cranelift", feature = "winch"))))] pub fn from_binary(engine: &Engine, binary: &[u8]) -> Result { @@ -153,12 +241,17 @@ impl Component { /// Same as [`Module::deserialize`], but for components. /// - /// Note that the file referenced here must contain contents previously + /// Note that the bytes referenced here must contain contents previously /// produced by [`Engine::precompile_component`] or /// [`Component::serialize`]. /// /// For more information see the [`Module::deserialize`] method. /// + /// # Unsafety + /// + /// The unsafety of this method is the same as that of the + /// [`Module::deserialize`] method. + /// /// [`Module::deserialize`]: crate::Module::deserialize pub unsafe fn deserialize(engine: &Engine, bytes: impl AsRef<[u8]>) -> Result { let code = engine.load_code_bytes(bytes.as_ref(), ObjectKind::Component)?; @@ -167,8 +260,16 @@ impl Component { /// Same as [`Module::deserialize_file`], but for components. /// - /// For more information see the [`Component::deserialize`] and - /// [`Module::deserialize_file`] methods. + /// Note that the file referenced here must contain contents previously + /// produced by [`Engine::precompile_component`] or + /// [`Component::serialize`]. + /// + /// For more information see the [`Module::deserialize_file`] method. + /// + /// # Unsafety + /// + /// The unsafety of this method is the same as that of the + /// [`Module::deserialize_file`] method. /// /// [`Module::deserialize_file`]: crate::Module::deserialize_file pub unsafe fn deserialize_file(engine: &Engine, path: impl AsRef) -> Result { diff --git a/crates/wasmtime/src/runtime/component/func.rs b/crates/wasmtime/src/runtime/component/func.rs index cf4f710f1b..3088dec872 100644 --- a/crates/wasmtime/src/runtime/component/func.rs +++ b/crates/wasmtime/src/runtime/component/func.rs @@ -85,9 +85,13 @@ union ParamsAndResults { ret: Return, } -/// A WebAssembly component function. -// -// FIXME: write more docs here +/// A WebAssembly component function which can be called. +/// +/// This type is the dual of [`wasmtime::Func`](crate::Func) for component +/// functions. An instance of [`Func`] represents a component function from a +/// component [`Instance`](crate::component::Instance). Like with +/// [`wasmtime::Func`](crate::Func) it's possible to call functions either +/// synchronously or asynchronously and either typed or untyped. #[derive(Copy, Clone, Debug)] pub struct Func(Stored); @@ -150,8 +154,8 @@ impl Func { /// The `Params` type parameter here is a tuple of the parameters to the /// function. A function which takes no arguments should use `()`, a /// function with one argument should use `(T,)`, etc. Note that all - /// `Params` must also implement the [`Lower`] trait since they're going tin - /// to wasm. + /// `Params` must also implement the [`Lower`] trait since they're going + /// into wasm. /// /// The `Return` type parameter is the return value of this function. A /// return value of `()` means that there's no return (similar to a Rust @@ -164,6 +168,9 @@ impl Func { /// primitives, floats, `Option`, `Result`, strings, `Vec`, and /// more. As parameters you'll be passing native Rust types. /// + /// See the documentation for [`ComponentType`] for more information about + /// supported types. + /// /// # Errors /// /// If the function does not actually take `Params` as its parameters or @@ -284,15 +291,39 @@ impl Func { /// Invokes this function with the `params` given and returns the result. /// - /// The `params` here must match the type signature of this `Func`, or this will return an error. If a trap - /// occurs while executing this function, then an error will also be returned. - // TODO: say more -- most of the docs for `TypedFunc::call` apply here, too - // - // # Panics - // - // Panics if this is called on a function in an asyncronous store. This only works - // with functions defined within a synchronous store. Also panics if `store` - // does not own this function. + /// The `params` provided must match the parameters that this function takes + /// in terms of their types and the number of parameters. Results will be + /// written to the `results` slice provided if the call completes + /// successfully. The initial types of the values in `results` are ignored + /// and values are overwritten to write the result. It's required that the + /// size of `results` exactly matches the number of results that this + /// function produces. + /// + /// Note that after a function is invoked the embedder needs to invoke + /// [`Func::post_return`] to execute any final cleanup required by the + /// guest. This function call is required to either call the function again + /// or to call another function. + /// + /// For more detailed information see the documentation of + /// [`TypedFunc::call`]. + /// + /// # Errors + /// + /// Returns an error in situations including but not limited to: + /// + /// * `params` is not the right size or if the values have the wrong type + /// * `results` is not the right size + /// * A trap occurs while executing the function + /// * The function calls a host function which returns an error + /// + /// See [`TypedFunc::call`] for more information in addition to + /// [`wasmtime::Func::call`](crate::Func::call). + /// + /// # Panics + /// + /// Panics if this is called on a function in an asyncronous store. This + /// only works with functions defined within a synchronous store. Also + /// panics if `store` does not own this function. pub fn call( &self, mut store: impl AsContextMut, @@ -309,11 +340,14 @@ impl Func { /// Exactly like [`Self::call`] except for use on async stores. /// + /// Note that after this [`Func::post_return_async`] will be used instead of + /// the synchronous version at [`Func::post_return`]. + /// /// # Panics /// - /// Panics if this is called on a function in a synchronous store. This only works - /// with functions defined within an asynchronous store. Also panics if `store` - /// does not own this function. + /// Panics if this is called on a function in a synchronous store. This + /// only works with functions defined within an asynchronous store. Also + /// panics if `store` does not own this function. #[cfg(feature = "async")] #[cfg_attr(nightlydoc, doc(cfg(feature = "async")))] pub async fn call_async( @@ -539,11 +573,9 @@ impl Func { /// Invokes the `post-return` canonical ABI option, if specified, after a /// [`Func::call`] has finished. /// - /// For some more information on when to use this function see the - /// documentation for post-return in the [`Func::call`] method. - /// Otherwise though this function is a required method call after a - /// [`Func::call`] completes successfully. After the embedder has - /// finished processing the return value then this function must be invoked. + /// This function is a required method call after a [`Func::call`] completes + /// successfully. After the embedder has finished processing the return + /// value then this function must be invoked. /// /// # Errors /// @@ -598,7 +630,6 @@ impl Func { store.on_fiber(|store| self.post_return_impl(store)).await? } - #[inline] fn post_return_impl(&self, mut store: impl AsContextMut) -> Result<()> { let mut store = store.as_context_mut(); let data = &mut store.0[self.0]; diff --git a/crates/wasmtime/src/runtime/component/func/typed.rs b/crates/wasmtime/src/runtime/component/func/typed.rs index a524418990..ba728f685a 100644 --- a/crates/wasmtime/src/runtime/component/func/typed.rs +++ b/crates/wasmtime/src/runtime/component/func/typed.rs @@ -29,6 +29,8 @@ use wasmtime_runtime::SendSyncPtr; /// and usage will panic if used with the wrong store. /// /// This type is primarily created with the [`Func::typed`] API. +/// +/// See [`ComponentType`] for more information about supported types. pub struct TypedFunc { func: Func, @@ -365,11 +367,47 @@ pub unsafe trait ComponentNamedList: ComponentType {} /// with the canonical ABI. /// /// This trait is implemented for Rust types which can be communicated to -/// components. This is implemented for Rust types which correspond to -/// interface types in the component model of WebAssembly. The [`Func::typed`] -/// and [`TypedFunc`] Rust items are the main consumers of this trait. +/// components. The [`Func::typed`] and [`TypedFunc`] Rust items are the main +/// consumers of this trait. +/// +/// Supported Rust types include: +/// +/// | Component Model Type | Rust Type | +/// |-----------------------------------|--------------------------------------| +/// | `{s,u}{8,16,32,64}` | `{i,u}{8,16,32,64}` | +/// | `f{32,64}` | `f{32,64}` | +/// | `bool` | `bool` | +/// | `char` | `char` | +/// | `tuple` | `(A, B)` | +/// | `option` | `Option` | +/// | `result` | `Result<(), ()>` | +/// | `result` | `Result` | +/// | `result<_, E>` | `Result<(), E>` | +/// | `result` | `Result` | +/// | `string` | `String`, `&str`, or [`WasmStr`] | +/// | `list` | `Vec`, `&[T]`, or [`WasmList`] | +/// | `own`, `borrow` | [`Resource`] or [`ResourceAny`] | +/// | `record` | [`#[derive(ComponentType)]`][d-cm] | +/// | `variant` | [`#[derive(ComponentType)]`][d-cm] | +/// | `enum` | [`#[derive(ComponentType)]`][d-cm] | +/// | `flags` | [`flags!`][f-m] | /// -/// For more information on this trait see the examples in [`Func::typed`]. +/// [`Resource`]: crate::component::Resource +/// [`ResourceAny`]: crate::component::ResourceAny +/// [d-cm]: macro@crate::component::ComponentType +/// [f-m]: crate::component::flags +/// +/// Rust standard library pointers such as `&T`, `Box`, `Rc`, and `Arc` +/// additionally represent whatever type `T` represents in the component model. +/// Note that types such as `record`, `variant`, `enum`, and `flags` are +/// generated by the embedder at compile time. These macros derive +/// implementation of this trait for custom types to map to custom types in the +/// component model. Note that for `record`, `variant`, `enum`, and `flags` +/// those types are often generated by the +/// [`bindgen!`](crate::component::bindgen) macro from WIT definitions. +/// +/// Types that implement [`ComponentType`] are used for `Params` and `Return` +/// in [`TypedFunc`] and [`Func::typed`]. /// /// The contents of this trait are hidden as it's intended to be an /// implementation detail of Wasmtime. The contents of this trait are not @@ -454,9 +492,18 @@ pub unsafe trait ComponentVariant: ComponentType { /// either as parameters of component exports or returns of component imports. /// This trait represents the ability to convert from the native host /// representation to the canonical ABI. -// -// TODO: #[derive(Lower)] -// TODO: more docs here +/// +/// Built-in types to Rust such as `Option` implement this trait as +/// appropriate. For a mapping of component model to Rust types see +/// [`ComponentType`]. +/// +/// For user-defined types, for example `record` types mapped to Rust `struct`s, +/// this crate additionally has +/// [`#[derive(Lower)]`](macro@crate::component::Lower). +/// +/// Note that like [`ComponentType`] the definition of this trait is intended to +/// be an internal implementation detail of Wasmtime at this time. It's +/// recommended to use the `#[derive(Lower)]` implementation instead. pub unsafe trait Lower: ComponentType { /// Performs the "lower" function in the canonical ABI. /// @@ -535,9 +582,21 @@ pub unsafe trait Lower: ComponentType { } /// Host types which can be created from the canonical ABI. -// -// TODO: #[derive(Lower)] -// TODO: more docs here +/// +/// This is the mirror of the [`Lower`] trait where it represents the capability +/// of acquiring items from WebAssembly and passing them to the host. +/// +/// Built-in types to Rust such as `Option` implement this trait as +/// appropriate. For a mapping of component model to Rust types see +/// [`ComponentType`]. +/// +/// For user-defined types, for example `record` types mapped to Rust `struct`s, +/// this crate additionally has +/// [`#[derive(Lift)]`](macro@crate::component::Lift). +/// +/// Note that like [`ComponentType`] the definition of this trait is intended to +/// be an internal implementation detail of Wasmtime at this time. It's +/// recommended to use the `#[derive(Lift)]` implementation instead. pub unsafe trait Lift: Sized + ComponentType { /// Performs the "lift" operation in the canonical ABI. /// @@ -1178,6 +1237,23 @@ fn lower_string(cx: &mut LowerContext<'_, T>, string: &str) -> Result<(usize, /// Representation of a string located in linear memory in a WebAssembly /// instance. /// +/// This type can be used in place of `String` and `str` for string-taking APIs +/// in some situations. The purpose of this type is to represent a range of +/// validated bytes within a component but does not actually copy the bytes. The +/// primary method, [`WasmStr::to_str`], attempts to return a reference to the +/// string directly located in the component's memory, avoiding a copy into the +/// host if possible. +/// +/// The downside of this type, however, is that accessing a string requires a +/// [`Store`](crate::Store) pointer (via [`StoreContext`]). Bindings generated +/// by [`bindgen!`](crate::component::bindgen), for example, do not have access +/// to [`StoreContext`] and thus can't use this type. +/// +/// This is intended for more advanced use cases such as defining functions +/// directly in a [`Linker`](crate::component::Linker). It's expected that in +/// the future [`bindgen!`](crate::component::bindgen) will also have a way to +/// use this type. +/// /// This type is used with [`TypedFunc`], for example, when WebAssembly returns /// a string. This type cannot be used to give a string to WebAssembly, instead /// `&str` should be used for that (since it's coming from the host). @@ -1185,8 +1261,9 @@ fn lower_string(cx: &mut LowerContext<'_, T>, string: &str) -> Result<(usize, /// Note that this type represents an in-bounds string in linear memory, but it /// does not represent a valid string (e.g. valid utf-8). Validation happens /// when [`WasmStr::to_str`] is called. -// -// TODO: should probably expand this with examples +/// +/// Also note that this type does not implement [`Lower`], it only implements +/// [`Lift`]. pub struct WasmStr { ptr: usize, len: usize, @@ -1414,6 +1491,11 @@ where /// Representation of a list of values that are owned by a WebAssembly instance. /// +/// For some more commentary about the rationale for this type see the +/// documentation of [`WasmStr`]. In summary this type can avoid a copy when +/// passing data to the host in some situations but is additionally more +/// cumbersome to use by requiring a [`Store`](crate::Store) to be provided. +/// /// This type is used whenever a `(list T)` is returned from a [`TypedFunc`], /// for example. This type represents a list of values that are stored in linear /// memory which are waiting to be read. @@ -1421,6 +1503,8 @@ where /// Note that this type represents only a valid range of bytes for the list /// itself, it does not represent validity of the elements themselves and that's /// performed when they're iterated. +/// +/// Note that this type does not implement the [`Lower`] trait, only [`Lift`]. pub struct WasmList { ptr: usize, len: usize, diff --git a/crates/wasmtime/src/runtime/component/instance.rs b/crates/wasmtime/src/runtime/component/instance.rs index a3f2a20254..b90aee0bb6 100644 --- a/crates/wasmtime/src/runtime/component/instance.rs +++ b/crates/wasmtime/src/runtime/component/instance.rs @@ -19,11 +19,18 @@ use wasmtime_runtime::VMFuncRef; /// An instantiated component. /// -/// This is similar to [`crate::Instance`] except that it represents an -/// instantiated component instead of an instantiated module. Otherwise though -/// the two behave similarly. -// -// FIXME: need to write more docs here. +/// This type represents an instantiated [`Component`](super::Component). +/// Instances have exports which can be accessed through functions such as +/// [`Instance::get_func`] or [`Instance::exports`]. Instances are owned by a +/// [`Store`](crate::Store) and all methods require a handle to the store. +/// +/// Component instances are created through +/// [`Linker::instantiate`](super::Linker::instantiate) and its family of +/// methods. +/// +/// This type is similar to the core wasm version +/// [`wasmtime::Instance`](crate::Instance) except that it represents an +/// instantiated component instead of an instantiated module. #[derive(Copy, Clone)] pub struct Instance(pub(crate) Stored>>); diff --git a/crates/wasmtime/src/runtime/component/mod.rs b/crates/wasmtime/src/runtime/component/mod.rs index e820525e26..821ef62590 100644 --- a/crates/wasmtime/src/runtime/component/mod.rs +++ b/crates/wasmtime/src/runtime/component/mod.rs @@ -1,7 +1,43 @@ -//! In-progress implementation of the WebAssembly component model +//! # Embedding API for the Component Model //! -//! This module is a work-in-progress and currently represents an incomplete and -//! probably buggy implementation of the component model. +//! This module contains the embedding API for the [Component Model] in +//! Wasmtime. This module requires the `component-model` feature to be enabled, +//! which is enabled by default. The embedding API here is mirrored after the +//! core wasm embedding API at the crate root and is intended to have the same +//! look-and-feel while handling concepts of the component model. +//! +//! [Component Model]: https://component-model.bytecodealliance.org +//! +//! The component model is a broad topic which can't be explained here fully, so +//! it's recommended to read over individual items' documentation to see more +//! about the capabilities of the embedding API. At a high-level, however, +//! perhaps the most interesting items in this module are: +//! +//! * [`Component`] - a compiled component ready to be instantiated. Similar to +//! a [`Module`](crate::Module) for core wasm. +//! +//! * [`Linker`] - a component-style location for defining host functions. This +//! is not the same as [`wasmtime::Linker`](crate::Linker) for core wasm +//! modules. +//! +//! * [`bindgen!`] - a macro to generate Rust bindings for a [WIT] [world]. This +//! maps all WIT types into Rust automatically and generates traits for +//! embedders to implement. +//! +//! [WIT]: https://component-model.bytecodealliance.org/design/wit.html +//! [world]: https://component-model.bytecodealliance.org/design/worlds.html +//! +//! Embedders of the component model will typically start by defining their API +//! in [WIT]. This describes what will be available to guests and what needs to +//! be provided to the embedder by the guest. This [`world`][world] that was +//! created is then fed into [`bindgen!`] to generate types and traits for the +//! embedder to use. The embedder then implements these traits, adds +//! functionality via the generated `add_to_linker` method (see [`bindgen!`] for +//! more info), and then instantiates/executes a component. +//! +//! It's recommended to read over the [documentation for the Component +//! Model][Component Model] to get an overview about how to build components +//! from various languages. #![cfg_attr(nightlydoc, doc(cfg(feature = "component-model")))] @@ -26,7 +62,6 @@ pub use self::resource_table::{ResourceTable, ResourceTableError}; pub use self::resources::{Resource, ResourceAny}; pub use self::types::{ResourceType, Type}; pub use self::values::{Enum, Flags, List, OptionVal, Record, ResultVal, Tuple, Val, Variant}; -pub use wasmtime_component_macro::{flags, ComponentType, Lift, Lower}; // These items are expected to be used by an eventual // `#[derive(ComponentType)]`, they are not part of Wasmtime's API stability @@ -50,26 +85,26 @@ pub mod __internal { pub(crate) use self::store::ComponentStoreData; -/// Generate bindings for a WIT package. +/// Generate bindings for a [WIT world]. +/// +/// [WIT world]: https://component-model.bytecodealliance.org/design/worlds.html +/// [WIT package]: https://component-model.bytecodealliance.org/design/packages.html /// -/// This macro ingests a [WIT package] and will generate all the necessary -/// bindings for instantiating and invoking a particular `world` in the -/// package. A `world` in a WIT package is a description of imports and exports -/// for a component. This provides a higher-level representation of working with -/// a component than the raw [`Instance`] type which must be manually-type-check -/// and manually have its imports provided via the [`Linker`] type. +/// This macro ingests a [WIT world] and will generate all the necessary +/// bindings for instantiating components that ascribe to the `world`. This +/// provides a higher-level representation of working with a component than the +/// raw [`Instance`] type which must be manually-type-checked and manually have +/// its imports provided via the [`Linker`] type. /// /// The most basic usage of this macro is: /// /// ```rust,ignore -/// wasmtime::component::bindgen!("my-component"); +/// wasmtime::component::bindgen!(); /// ``` /// -/// This will parse your projects WIT package in a `wit` directory adjacent to +/// This will parse your projects [WIT package] in a `wit` directory adjacent to /// your crate's `Cargo.toml`. All of the `*.wit` files in that directory are -/// parsed and then the `default world` will be looked up within -/// `my-component.wit`. This world is then used as the basis for generating -/// bindings. +/// parsed and then the single `world` found will be used for bindings. /// /// For example if your project contained: /// @@ -86,18 +121,29 @@ pub(crate) use self::store::ComponentStoreData; /// /// Then you can interact with the generated bindings like so: /// -/// ```rust,ignore +/// ```rust /// use wasmtime::component::*; /// use wasmtime::{Config, Engine, Store}; /// +/// # const _: () = { macro_rules! bindgen { () => () } /// bindgen!(); +/// # }; +/// # bindgen!({ +/// # inline: r#" +/// # package my:project; +/// # world hello-world { +/// # import name: func() -> string; +/// # export greet: func(); +/// # } +/// # "#, +/// # }); /// /// struct MyState { /// name: String, /// } /// -/// // Imports into the world, like the `name` import for this world, are satisfied -/// // through traits. +/// // Imports into the world, like the `name` import for this world, are +/// // satisfied through traits. /// impl HelloWorldImports for MyState { /// // Note the `Result` return value here where `Ok` is returned back to /// // the component and `Err` will raise a trap. @@ -107,6 +153,7 @@ pub(crate) use self::store::ComponentStoreData; /// } /// /// fn main() -> wasmtime::Result<()> { +/// # if true { return Ok(()) } /// // Configure an `Engine` and compile the `Component` that is being run for /// // the application. /// let mut config = Config::new(); @@ -162,7 +209,7 @@ pub(crate) use self::store::ComponentStoreData; /// sha256: func(bytes: list) -> string; /// } /// -/// default world hello-world { +/// world hello-world { /// import host; /// /// export demo: interface { @@ -173,12 +220,32 @@ pub(crate) use self::store::ComponentStoreData; /// /// Then you can interact with the generated bindings like so: /// -/// ```rust,ignore +/// ```rust /// use wasmtime::component::*; /// use wasmtime::{Config, Engine, Store}; /// use my::project::host::Host; /// +/// # const _: () = { macro_rules! bindgen { () => () } /// bindgen!(); +/// # }; +/// # bindgen!({ +/// # inline: r#" +/// # package my:project; +/// # +/// # interface host { +/// # gen-random-integer: func() -> u32; +/// # sha256: func(bytes: list) -> string; +/// # } +/// # +/// # world hello-world { +/// # import host; +/// # +/// # export demo: interface { +/// # run: func(); +/// # } +/// # } +/// # "#, +/// # }); /// /// struct MyState { /// // ... @@ -187,15 +254,19 @@ pub(crate) use self::store::ComponentStoreData; /// // Note that the trait here is per-interface and within a submodule now. /// impl Host for MyState { /// fn gen_random_integer(&mut self) -> wasmtime::Result { +/// # panic!(); +/// # #[cfg(FALSE)] /// Ok(rand::thread_rng().gen()) /// } /// /// fn sha256(&mut self, bytes: Vec) -> wasmtime::Result { /// // ... +/// # panic!() /// } /// } /// /// fn main() -> wasmtime::Result<()> { +/// # if true { return Ok(()) } /// let mut config = Config::new(); /// config.wasm_component_model(true); /// let engine = Engine::new(&config)?; @@ -227,12 +298,12 @@ pub(crate) use self::store::ComponentStoreData; /// `world` from the parsed package. There are then codegen-specific options to /// the bindings themselves which can additionally be specified. /// -/// Basic usage of this macro looks like: +/// Usage of this macro looks like: /// /// ```rust,ignore /// // Parse the `wit/` folder adjacent to this crate's `Cargo.toml` and look -/// // for a `default world` in its documents. There must be exactly one -/// // `default world` for this to succeed. +/// // for a single `world` in it. There must be exactly one for this to +/// // succeed. /// bindgen!(); /// /// // Parse the `wit/` folder adjacent to this crate's `Cargo.toml` and look @@ -346,6 +417,260 @@ pub(crate) use self::store::ComponentStoreData; /// }, /// }); /// ``` -/// -/// [WIT package]: https://github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md pub use wasmtime_component_macro::bindgen; + +/// Derive macro to generate implementations of the [`ComponentType`] trait. +/// +/// This derive macro can be applied to `struct` and `enum` definitions and is +/// used to bind either a `record`, `enum`, or `variant` in the component model. +/// +/// Note you might be looking for [`bindgen!`] rather than this macro as that +/// will generate the entire type for you rather than just a trait +/// implementation. +/// +/// This macro supports a `#[component]` attribute which is used to customize +/// how the type is bound to the component model. A top-level `#[component]` +/// attribute is required to specify either `record`, `enum`, or `variant`. +/// +/// ## Records +/// +/// `record`s in the component model correspond to `struct`s in Rust. An example +/// is: +/// +/// ```rust +/// use wasmtime::component::ComponentType; +/// +/// #[derive(ComponentType)] +/// #[component(record)] +/// struct Color { +/// r: u8, +/// g: u8, +/// b: u8, +/// } +/// ``` +/// +/// which corresponds to the WIT type: +/// +/// ```wit +/// record color { +/// r: u8, +/// g: u8, +/// b: u8, +/// } +/// ``` +/// +/// Note that the name `Color` here does not need to match the name in WIT. +/// That's purely used as a name in Rust of what to refer to. The field names +/// must match that in WIT, however. Field names can be customized with the +/// `#[component]` attribute though. +/// +/// ```rust +/// use wasmtime::component::ComponentType; +/// +/// #[derive(ComponentType)] +/// #[component(record)] +/// struct VerboseColor { +/// #[component(name = "r")] +/// red: u8, +/// #[component(name = "g")] +/// green: u8, +/// #[component(name = "b")] +/// blue: u8, +/// } +/// ``` +/// +/// Also note that field ordering is significant at this time and must match +/// WIT. +/// +/// ## Variants +/// +/// `variant`s in the component model correspond to a subset of shapes of a Rust +/// `enum`. Variants in the component model have a single optional payload type +/// which means that not all Rust `enum`s correspond to component model +/// `variant`s. An example variant is: +/// +/// ```rust +/// use wasmtime::component::ComponentType; +/// +/// #[derive(ComponentType)] +/// #[component(variant)] +/// enum Filter { +/// #[component(name = "none")] +/// None, +/// #[component(name = "all")] +/// All, +/// #[component(name = "some")] +/// Some(Vec), +/// } +/// ``` +/// +/// which corresponds to the WIT type: +/// +/// ```wit +/// variant filter { +/// none, +/// all, +/// some(list), +/// } +/// ``` +/// +/// The `variant` style of derive allows an optional payload on Rust `enum` +/// variants but it must be a single unnamed field. Variants of the form `Foo(T, +/// U)` or `Foo { name: T }` are not supported at this time. +/// +/// Note that the order of variants in Rust must match the order of variants in +/// WIT. Additionally it's likely that `#[component(name = "...")]` is required +/// on all Rust `enum` variants because the name currently defaults to the Rust +/// name which is typically UpperCamelCase whereas WIT uses kebab-case. +/// +/// ## Enums +/// +/// `enum`s in the component model correspond to C-like `enum`s in Rust. Note +/// that a component model `enum` does not allow any payloads so the Rust `enum` +/// must additionally have no payloads. +/// +/// ```rust +/// use wasmtime::component::ComponentType; +/// +/// #[derive(ComponentType)] +/// #[component(enum)] +/// enum Setting { +/// #[component(name = "yes")] +/// Yes, +/// #[component(name = "no")] +/// No, +/// #[component(name = "auto")] +/// Auto, +/// } +/// ``` +/// +/// which corresponds to the WIT type: +/// +/// ```wit +/// enum setting { +/// yes, +/// no, +/// auto, +/// } +/// ``` +/// +/// Note that the order of variants in Rust must match the order of variants in +/// WIT. Additionally it's likely that `#[component(name = "...")]` is required +/// on all Rust `enum` variants because the name currently defaults to the Rust +/// name which is typically UpperCamelCase whereas WIT uses kebab-case. +pub use wasmtime_component_macro::ComponentType; + +/// A derive macro for generating implementations of the [`Lift`] trait. +/// +/// This macro will likely be applied in conjunction with the +/// [`#[derive(ComponentType)]`](macro@ComponentType) macro along the lines +/// of `#[derive(ComponentType, Lift)]`. This trait enables reading values from +/// WebAssembly. +/// +/// Note you might be looking for [`bindgen!`] rather than this macro as that +/// will generate the entire type for you rather than just a trait +/// implementation. +/// +/// At this time this derive macro has no configuration. +/// +/// ## Examples +/// +/// ```rust +/// use wasmtime::component::{ComponentType, Lift}; +/// +/// #[derive(ComponentType, Lift)] +/// #[component(record)] +/// struct Color { +/// r: u8, +/// g: u8, +/// b: u8, +/// } +/// ``` +pub use wasmtime_component_macro::Lift; + +/// A derive macro for generating implementations of the [`Lower`] trait. +/// +/// This macro will likely be applied in conjunction with the +/// [`#[derive(ComponentType)]`](macro@ComponentType) macro along the lines +/// of `#[derive(ComponentType, Lower)]`. This trait enables passing values to +/// WebAssembly. +/// +/// Note you might be looking for [`bindgen!`] rather than this macro as that +/// will generate the entire type for you rather than just a trait +/// implementation. +/// +/// At this time this derive macro has no configuration. +/// +/// ## Examples +/// +/// ```rust +/// use wasmtime::component::{ComponentType, Lower}; +/// +/// #[derive(ComponentType, Lower)] +/// #[component(record)] +/// struct Color { +/// r: u8, +/// g: u8, +/// b: u8, +/// } +/// ``` +pub use wasmtime_component_macro::Lower; + +/// A macro to generate a Rust type corresponding to WIT `flags` +/// +/// This macro generates a type that implements the [`ComponentType`], [`Lift`], +/// and [`Lower`] traits. The generated Rust type corresponds to the `flags` +/// type in WIT. +/// +/// Example usage of this looks like: +/// +/// ```rust +/// use wasmtime::component::flags; +/// +/// flags! { +/// Permissions { +/// #[component(name = "read")] +/// const READ; +/// #[component(name = "write")] +/// const WRITE; +/// #[component(name = "execute")] +/// const EXECUTE; +/// } +/// } +/// +/// fn validate_permissions(permissions: &mut Permissions) { +/// if permissions.contains(Permissions::EXECUTE | Permissions::WRITE) { +/// panic!("cannot enable both writable and executable at the same time"); +/// } +/// +/// if permissions.contains(Permissions::READ) { +/// panic!("permissions must at least contain read"); +/// } +/// } +/// ``` +/// +/// which corresponds to the WIT type: +/// +/// ```wit +/// flags permissions { +/// read, +/// write, +/// execute, +/// } +/// ``` +/// +/// This generates a structure which is similar to/inspired by the [`bitflags` +/// crate](https://crates.io/crates/bitflags). The `Permissions` structure +/// generated implements the [`PartialEq`], [`Eq`], [`Debug`], [`BitOr`], +/// [`BitOrAssign`], [`BitAnd`], [`BitAndAssign`], [`BitXor`], [`BitXorAssign`], +/// and [`Not`] traits - in addition to the Wasmtime-specific component ones +/// [`ComponentType`], [`Lift`], and [`Lower`]. +/// +/// [`BitOr`]: std::ops::BitOr +/// [`BitOrAssign`]: std::ops::BitOrAssign +/// [`BitAnd`]: std::ops::BitAnd +/// [`BitAndAssign`]: std::ops::BitAndAssign +/// [`BitXor`]: std::ops::BitXor +/// [`BitXorAssign`]: std::ops::BitXorAssign +/// [`Not`]: std::ops::Not +pub use wasmtime_component_macro::flags; diff --git a/crates/wasmtime/src/runtime/component/values.rs b/crates/wasmtime/src/runtime/component/values.rs index 0775dcf7b2..52d08d120b 100644 --- a/crates/wasmtime/src/runtime/component/values.rs +++ b/crates/wasmtime/src/runtime/component/values.rs @@ -13,7 +13,14 @@ use wasmtime_environ::component::{ CanonicalAbiInfo, ComponentTypes, InterfaceType, TypeListIndex, VariantInfo, }; -/// Represents runtime list values +/// Dynamic representation of `list` in the component model. +/// +/// This structure is part of the dynamically-typed [`Val`] which represents +/// all possible values in the component model. This is often used in +/// conjunction with [`Func::call`](crate::component::Func::call). +/// +/// Note that `Vec` is also supported for component model lists when +/// using [`TypedFunc`](crate::component::TypedFunc). #[derive(PartialEq, Eq, Clone)] pub struct List { ty: types::List, @@ -21,7 +28,12 @@ pub struct List { } impl List { - /// Instantiate the specified type with the specified `values`. + /// Creates a new list with the specified type with the specified `values`. + /// + /// # Errors + /// + /// Returns an error if any value in `values` does not have the element + /// type of `ty` specified. pub fn new(ty: &types::List, values: Box<[Val]>) -> Result { let element_type = ty.ty(); for (index, value) in values.iter().enumerate() { @@ -60,7 +72,15 @@ impl fmt::Debug for List { } } -/// Represents runtime record values +/// Dynamic representation of `record` in the component model. +/// +/// This structure is part of the dynamically-typed [`Val`] which represents +/// all possible values in the component model. This is often used in +/// conjunction with [`Func::call`](crate::component::Func::call). +/// +/// Note that records can also be mapped to Rust `struct`s through the +/// [`#[derive(ComponentType)]`](macro@crate::component::ComponentType) macro +/// and using [`TypedFunc`](crate::component::TypedFunc). #[derive(PartialEq, Eq, Clone)] pub struct Record { ty: types::Record, @@ -68,7 +88,15 @@ pub struct Record { } impl Record { - /// Instantiate the specified type with the specified `values`. + /// Creates a new record with the specified `ty` and the `values` for fields. + /// + /// Note that the `values` specified for fields must list fields in the + /// same order that the `ty` lists them in. + /// + /// # Errors + /// + /// Returns an error if any of the `values` specified are in the wrong order + /// field-wise or have the wrong type relative to what's specified in `ty`. pub fn new<'a>( ty: &types::Record, values: impl IntoIterator, @@ -111,8 +139,9 @@ impl Record { &self.ty } - /// Gets the value of the specified field `name` from this record. - pub fn fields(&self) -> impl Iterator { + /// Returns the list of fields that this struct contains with their name + /// and value. + pub fn fields(&self) -> impl ExactSizeIterator { assert_eq!(self.values.len(), self.ty.fields().len()); self.ty .fields() @@ -131,7 +160,14 @@ impl fmt::Debug for Record { } } -/// Represents runtime tuple values +/// Dynamic representation of `tuple<...>` in the component model. +/// +/// This structure is part of the dynamically-typed [`Val`] which represents +/// all possible values in the component model. This is often used in +/// conjunction with [`Func::call`](crate::component::Func::call). +/// +/// Note that tuples are also mapped to Rust tuples when using +/// [`TypedFunc`](crate::component::TypedFunc). #[derive(PartialEq, Eq, Clone)] pub struct Tuple { ty: types::Tuple, @@ -139,7 +175,13 @@ pub struct Tuple { } impl Tuple { - /// Instantiate the specified type ith the specified `values`. + /// Creates a new tuple with the `ty` specified and `values` for each + /// entry. + /// + /// # Errors + /// + /// Returns an error if `values` does not match the `ty` specified, such as + /// if it has the wrong length or if any field has the wrong type. pub fn new(ty: &types::Tuple, values: Box<[Val]>) -> Result { if values.len() != ty.types().len() { bail!( @@ -181,7 +223,15 @@ impl fmt::Debug for Tuple { } } -/// Represents runtime variant values +/// Dynamic representation of `variant` in the component model. +/// +/// This structure is part of the dynamically-typed [`Val`] which represents +/// all possible values in the component model. This is often used in +/// conjunction with [`Func::call`](crate::component::Func::call). +/// +/// Note that variants can also be mapped to Rust `enum`s through the +/// [`#[derive(ComponentType)]`](macro@crate::component::ComponentType) macro +/// and using [`TypedFunc`](crate::component::TypedFunc). #[derive(PartialEq, Eq, Clone)] pub struct Variant { ty: types::Variant, @@ -190,7 +240,18 @@ pub struct Variant { } impl Variant { - /// Instantiate the specified type with the specified case `name` and `value`. + /// Creates a new variant with the specified `ty` and the case `name` and + /// `value` provided. + /// + /// This will create a instance of a variant with the case `name` which has + /// the optional payload of `value`. + /// + /// # Errors + /// + /// Returns an error if `name` doesn't match any case of `ty` or if + /// `value` is of the wrong type. Note that `ty` must match the payload + /// type exactly, in that if the case for `name` doesn't have a type then + /// `value` must be `None`. pub fn new(ty: &types::Variant, name: &str, value: Option) -> Result { let (discriminant, case_type) = ty .cases() @@ -272,7 +333,15 @@ impl fmt::Debug for Variant { } } -/// Represents runtime enum values +/// Dynamic representation of `enum` in the component model. +/// +/// This structure is part of the dynamically-typed [`Val`] which represents +/// all possible values in the component model. This is often used in +/// conjunction with [`Func::call`](crate::component::Func::call). +/// +/// Note that enums can also be mapped to Rust `enum`s through the +/// [`#[derive(ComponentType)]`](macro@crate::component::ComponentType) macro +/// and using [`TypedFunc`](crate::component::TypedFunc). #[derive(PartialEq, Eq, Clone)] pub struct Enum { ty: types::Enum, @@ -280,7 +349,12 @@ pub struct Enum { } impl Enum { - /// Instantiate the specified type with the specified case `name`. + /// Creates a new enum value with the `ty` specified selecting the + /// specified variant called `name`. + /// + /// # Errors + /// + /// Returns an error if `name` isn't listed within `ty`. pub fn new(ty: &types::Enum, name: &str) -> Result { let discriminant = u32::try_from( ty.names() @@ -328,7 +402,14 @@ impl fmt::Debug for Enum { } } -/// Represents runtime option values +/// Dynamic representation of `option` in the component model. +/// +/// This structure is part of the dynamically-typed [`Val`] which represents +/// all possible values in the component model. This is often used in +/// conjunction with [`Func::call`](crate::component::Func::call). +/// +/// Note that options are also mapped to Rust `Option` when using +/// [`TypedFunc`](crate::component::TypedFunc). #[derive(PartialEq, Eq, Clone)] pub struct OptionVal { ty: types::OptionType, @@ -337,7 +418,12 @@ pub struct OptionVal { } impl OptionVal { - /// Instantiate the specified type with the specified `value`. + /// Creates a new value with the `ty` specified holding the payload `value`. + /// + /// # Errors + /// + /// Returns an error if `value` is `Some` and the payload has the wrong + /// type for `ty`. pub fn new(ty: &types::OptionType, value: Option) -> Result { let value = value .map(|value| { @@ -390,7 +476,14 @@ impl fmt::Debug for OptionVal { } } -/// Represents runtime result values +/// Dynamic representation of `result` in the component model. +/// +/// This structure is part of the dynamically-typed [`Val`] which represents +/// all possible values in the component model. This is often used in +/// conjunction with [`Func::call`](crate::component::Func::call). +/// +/// Note that tuples are also mapped to Rust's `Result` when using +/// [`TypedFunc`](crate::component::TypedFunc). #[derive(PartialEq, Eq, Clone)] pub struct ResultVal { ty: types::ResultType, @@ -399,7 +492,14 @@ pub struct ResultVal { } impl ResultVal { - /// Instantiate the specified type with the specified `value`. + /// Creates a new `Result` from the specified `ty` and `value`. + /// + /// Note that the `value` uses `Option` for payloads to map to the + /// optional payload value of the component model within each variant. + /// + /// # Errors + /// + /// Returns an error if the `value` payload has the wrong type for `ty`. pub fn new(ty: &types::ResultType, value: Result, Option>) -> Result { Ok(Self { ty: ty.clone(), @@ -459,7 +559,15 @@ impl fmt::Debug for ResultVal { } } -/// Represents runtime flag values +/// Dynamic representation of `flags` in the component model. +/// +/// This structure is part of the dynamically-typed [`Val`] which represents +/// all possible values in the component model. This is often used in +/// conjunction with [`Func::call`](crate::component::Func::call). +/// +/// Note that flags can also be mapped to Rust structures through the +/// [`flags!`](crate::component::flags) macro and using +/// [`TypedFunc`](crate::component::TypedFunc). #[derive(PartialEq, Eq, Clone)] pub struct Flags { ty: types::Flags, @@ -468,7 +576,13 @@ pub struct Flags { } impl Flags { - /// Instantiate the specified type with the specified flag `names`. + /// Creates a new set of flags with the `ty` specified and the `names` as + /// members of the flags. + /// + /// # Errors + /// + /// An error is returned if any of `names` aren't present within the `ty` + /// specified. pub fn new(ty: &types::Flags, names: &[&str]) -> Result { let map = ty .names() diff --git a/crates/wasmtime/src/runtime/func.rs b/crates/wasmtime/src/runtime/func.rs index b7e9d66177..6a19734cdd 100644 --- a/crates/wasmtime/src/runtime/func.rs +++ b/crates/wasmtime/src/runtime/func.rs @@ -18,16 +18,15 @@ use wasmtime_runtime::{ /// A WebAssembly function which can be called. /// -/// This type can represent either an exported function from a WebAssembly -/// module or a host-defined function which can be used to satisfy an import of -/// a module. [`Func`] and can be used to both instantiate an [`Instance`] as -/// well as be extracted from an [`Instance`]. +/// This type typically represents an exported function from a WebAssembly +/// module instance. In this case a [`Func`] belongs to an [`Instance`] and is +/// loaded from there. A [`Func`] may also represent a host function as well in +/// some cases, too. /// -/// [`Instance`]: crate::Instance -/// -/// A [`Func`] "belongs" to the store that it was originally created within. -/// Operations on a [`Func`] only work with the store it belongs to, and if -/// another store is passed in by accident then methods will panic. +/// Functions can be called in a few different ways, either synchronous or async +/// and either typed or untyped (more on this below). Note that host functions +/// are normally inserted directly into a [`Linker`](crate::Linker) rather than +/// using this directly, but both options are available. /// /// # `Func` and `async` /// diff --git a/crates/wasmtime/src/runtime/module.rs b/crates/wasmtime/src/runtime/module.rs index 94c9470b63..56bd904b03 100644 --- a/crates/wasmtime/src/runtime/module.rs +++ b/crates/wasmtime/src/runtime/module.rs @@ -40,14 +40,25 @@ pub use registry::{ /// representation. Instead you'll need to create an /// [`Instance`](crate::Instance) to interact with the wasm module. /// -/// Creating a `Module` currently involves compiling code, meaning that it can -/// be an expensive operation. All `Module` instances are compiled according to -/// the configuration in [`Config`], but typically they're JIT-compiled. If -/// you'd like to instantiate a module multiple times you can do so with -/// compiling the original wasm module only once with a single [`Module`] -/// instance. +/// A `Module` can be created by compiling WebAssembly code through APIs such as +/// [`Module::new`]. This would be a JIT-style use case where code is compiled +/// just before it's used. Alternatively a `Module` can be compiled in one +/// process and [`Module::serialize`] can be used to save it to storage. A later +/// call to [`Module::deserialize`] will quickly load the module to execute and +/// does not need to compile any code, representing a more AOT-style use case. /// -/// The `Module` is thread-safe and safe to share across threads. +/// Currently a `Module` does not implement any form of tiering or dynamic +/// optimization of compiled code. Creation of a `Module` via [`Module::new`] or +/// related APIs will perform the entire compilation step synchronously. When +/// finished no further compilation will happen at runtime or later during +/// execution of WebAssembly instances for example. +/// +/// Compilation of WebAssembly by default goes through Cranelift and is +/// recommended to be done once-per-module. The same WebAssembly binary need not +/// be compiled multiple times and can instead used an embedder-cached result of +/// the first call. +/// +/// `Module` is thread-safe and safe to share across threads. /// /// ## Modules and `Clone` /// @@ -98,6 +109,25 @@ pub use registry::{ /// # } /// ``` /// +/// Serializing and deserializing a module looks like: +/// +/// ```no_run +/// # use wasmtime::*; +/// # fn main() -> anyhow::Result<()> { +/// let engine = Engine::default(); +/// # let wasm_bytes: Vec = Vec::new(); +/// let module = Module::new(&engine, &wasm_bytes)?; +/// let module_bytes = module.serialize()?; +/// +/// // ... can save `module_bytes` to disk or other storage ... +/// +/// // recreate the module from the serialized bytes. For the `unsafe` bits +/// // see the documentation of `deserialize`. +/// let module = unsafe { Module::deserialize(&engine, &module_bytes)? }; +/// # Ok(()) +/// # } +/// ``` +/// /// [`Config`]: crate::Config #[derive(Clone)] pub struct Module { @@ -157,9 +187,8 @@ impl Module { /// loaded into memory all at once, this API does not support streaming /// compilation of a module. /// - /// If the module has not been already been compiled, the WebAssembly binary will - /// be decoded and validated. It will also be compiled according to the - /// configuration of the provided `engine`. + /// The WebAssembly binary will be decoded and validated. It will also be + /// compiled according to the configuration of the provided `engine`. /// /// # Errors /// diff --git a/crates/wasmtime/src/runtime/store.rs b/crates/wasmtime/src/runtime/store.rs index 631f49b3bd..513474f8b0 100644 --- a/crates/wasmtime/src/runtime/store.rs +++ b/crates/wasmtime/src/runtime/store.rs @@ -120,8 +120,8 @@ use func_refs::FuncRefs; /// [`Store`] it will not be deallocated until the [`Store`] itself is dropped. /// This makes [`Store`] unsuitable for creating an unbounded number of /// instances in it because [`Store`] will never release this memory. It's -/// recommended to have a [`Store`] correspond roughly to the lifetime of a "main -/// instance" that an embedding is interested in executing. +/// recommended to have a [`Store`] correspond roughly to the lifetime of a +/// "main instance" that an embedding is interested in executing. /// /// ## Type parameter `T` /// @@ -158,6 +158,18 @@ use func_refs::FuncRefs; /// You can create a store with default configuration settings using /// `Store::default()`. This will create a brand new [`Engine`] with default /// configuration (see [`Config`](crate::Config) for more information). +/// +/// ## Cross-store usage of items +/// +/// In `wasmtime` wasm items such as [`Global`] and [`Memory`] "belong" to a +/// [`Store`]. The store they belong to is the one they were created with +/// (passed in as a parameter) or instantiated with. This store is the only +/// store that can be used to interact with wasm items after they're created. +/// +/// The `wasmtime` crate will panic if the [`Store`] argument passed in to these +/// operations is incorrect. In other words it's considered a programmer error +/// rather than a recoverable error for the wrong [`Store`] to be used when +/// calling APIs. pub struct Store { // for comments about `ManuallyDrop`, see `Store::into_data` inner: ManuallyDrop>>,