Add a wasmtime::component::bindgen! macro (#5317)

* Import Wasmtime support from the `wit-bindgen` repo

This commit imports the `wit-bindgen-gen-host-wasmtime-rust` crate from
the `wit-bindgen` repository into the upstream Wasmtime repository. I've
chosen to not import the full history here since the crate is relatively
small and doesn't have a ton of complexity. While the history of the
crate is quite long the current iteration of the crate's history is
relatively short so there's not a ton of import there anyway. The
thinking is that this can now continue to evolve in-tree.

* Refactor `wasmtime-component-macro` a bit

Make room for a `wit_bindgen` macro to slot in.

* Add initial support for a `bindgen` macro

* Add tests for `wasmtime::component::bindgen!`

* Improve error forgetting `async` feature

* Add end-to-end tests for bindgen

* Add an audit of `unicase`

* Add a license to the test-helpers crate

* Add vet entry for `pulldown-cmark`

* Update publish script with new crate

* Try to fix publish script

* Update audits

* Update lock file
This commit is contained in:
Alex Crichton
2022-12-06 13:06:00 -06:00
committed by GitHub
parent 293bb5b334
commit 2329ecc341
43 changed files with 4336 additions and 1212 deletions

View File

@@ -88,7 +88,12 @@ cache = ["dep:wasmtime-cache"]
# Enables support for "async stores" as well as defining host functions as
# `async fn` and calling functions asynchronously.
async = ["dep:wasmtime-fiber", "wasmtime-runtime/async", "dep:async-trait"]
async = [
"dep:wasmtime-fiber",
"wasmtime-runtime/async",
"dep:async-trait",
"wasmtime-component-macro?/async",
]
# Enables support for the pooling instance allocation strategy
pooling-allocator = ["wasmtime-runtime/pooling-allocator"]

View File

@@ -0,0 +1,126 @@
/// Type alias for the standard library [`Result`](std::result::Result) type
/// to specifie [`Error`] as the error payload.
pub type Result<A, E> = std::result::Result<A, Error<E>>;
/// Error type used by the [`bindgen!`](crate::component::bindgen) macro.
///
/// This error type represents either the typed error `T` specified here or a
/// trap, represented with [`anyhow::Error`].
pub struct Error<T> {
err: anyhow::Error,
ty: std::marker::PhantomData<T>,
}
impl<T> Error<T> {
/// Creates a new typed version of this error from the `T` specified.
///
/// This error, if it makes its way to the guest, will be returned to the
/// guest and the guest will be able to act upon it.
///
/// Alternatively errors can be created with [`Error::trap`] which will
/// cause the guest to trap and be unable to act upon it.
pub fn new(err: T) -> Error<T>
where
T: std::error::Error + Send + Sync + 'static,
{
Error {
err: err.into(),
ty: std::marker::PhantomData,
}
}
/// Creates a custom "trap" which will abort guest execution and have the
/// specified `err` as the payload context returned from the original
/// invocation.
///
/// Note that if `err` here actually has type `T` then the error will not be
/// considered a trap and will instead be dynamically detected as a normal
/// error to communicate to the original module.
pub fn trap(err: impl std::error::Error + Send + Sync + 'static) -> Error<T> {
Error {
err: anyhow::Error::from(err),
ty: std::marker::PhantomData,
}
}
/// Attempts to dynamically downcast this error internally to the `T`
/// representation.
///
/// If this error is internally represented as a `T` then `Ok(val)` will be
/// returned. If this error is instead represented as a trap then
/// `Err(trap)` will be returned instead.
pub fn downcast(self) -> anyhow::Result<T>
where
T: std::error::Error + Send + Sync + 'static,
{
self.err.downcast::<T>()
}
/// Attempts to dynamically downcast this error to peek at the inner
/// contents of `T` if present.
pub fn downcast_ref(&self) -> Option<&T>
where
T: std::error::Error + Send + Sync + 'static,
{
self.err.downcast_ref::<T>()
}
/// Attempts to dynamically downcast this error to peek at the inner
/// contents of `T` if present.
pub fn downcast_mut(&mut self) -> Option<&mut T>
where
T: std::error::Error + Send + Sync + 'static,
{
self.err.downcast_mut::<T>()
}
/// Converts this error into an `anyhow::Error` which loses the `T` type
/// information tagged to this error.
pub fn into_inner(self) -> anyhow::Error {
self.err
}
/// Same as [`anyhow::Error::context`], attaches a contextual message to
/// this error.
pub fn context<C>(self, context: C) -> Error<T>
where
C: std::fmt::Display + Send + Sync + 'static,
{
self.err.context(context).into()
}
}
impl<T> std::ops::Deref for Error<T> {
type Target = dyn std::error::Error + Send + Sync + 'static;
fn deref(&self) -> &Self::Target {
self.err.deref()
}
}
impl<T> std::ops::DerefMut for Error<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.err.deref_mut()
}
}
impl<T> std::fmt::Display for Error<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.err.fmt(f)
}
}
impl<T> std::fmt::Debug for Error<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.err.fmt(f)
}
}
impl<T> std::error::Error for Error<T> {}
impl<T> From<anyhow::Error> for Error<T> {
fn from(err: anyhow::Error) -> Error<T> {
Error {
err,
ty: std::marker::PhantomData,
}
}
}

View File

@@ -4,6 +4,7 @@
//! probably buggy implementation of the component model.
mod component;
mod error;
mod func;
mod instance;
mod linker;
@@ -13,6 +14,7 @@ mod store;
pub mod types;
mod values;
pub use self::component::Component;
pub use self::error::{Error, Result};
pub use self::func::{
ComponentNamedList, ComponentType, Func, Lift, Lower, TypedFunc, WasmList, WasmStr,
};
@@ -20,7 +22,7 @@ pub use self::instance::{ExportInstance, Exports, Instance, InstancePre};
pub use self::linker::{Linker, LinkerInstance};
pub use self::types::Type;
pub use self::values::Val;
pub use wasmtime_component_macro::{flags, ComponentType, Lift, Lower};
pub use wasmtime_component_macro::{bindgen, 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
@@ -35,6 +37,8 @@ pub mod __internal {
pub use crate::map_maybe_uninit;
pub use crate::store::StoreOpaque;
pub use anyhow;
#[cfg(feature = "async")]
pub use async_trait::async_trait;
pub use wasmtime_environ;
pub use wasmtime_environ::component::{CanonicalAbiInfo, ComponentTypes, InterfaceType};
}