From 65b48a0160103ecfc3f6c713c52c2da89a6c2dcd Mon Sep 17 00:00:00 2001 From: Pat Hickey Date: Thu, 30 Nov 2023 14:08:03 -0800 Subject: [PATCH 01/10] rename to ResourceTable, docs, and export --- crates/wasi/src/preview2/table.rs | 105 +++++++++++++++------------ crates/wasmtime/src/component/mod.rs | 2 + 2 files changed, 61 insertions(+), 46 deletions(-) diff --git a/crates/wasi/src/preview2/table.rs b/crates/wasi/src/preview2/table.rs index 9e60cd88d3c1..fe5244d36660 100644 --- a/crates/wasi/src/preview2/table.rs +++ b/crates/wasi/src/preview2/table.rs @@ -1,28 +1,36 @@ +use super::Resource; use std::any::Any; use std::collections::{BTreeSet, HashMap}; -use wasmtime::component::Resource; -#[derive(thiserror::Error, Debug)] -pub enum TableError { - #[error("table has no free keys")] +#[derive(Debug)] +/// Errors returned by operations on `ResourceTable` +pub enum ResourceTableError { + /// ResourceTable has no free keys Full, - #[error("value not present")] + /// Resource not present in table NotPresent, - #[error("value is of another type")] + /// Resource present in table, but with a different type WrongType, - #[error("entry still has children")] + /// Resource cannot be deleted because child resources exist in the table. Consult wit docs for + /// the particular resource to see which methods may return child resources. HasChildren, } -/// The `Table` type is designed to map u32 handles to resources. The table is now part of the -/// public interface to a `WasiCtx` - it is reference counted so that it can be shared beyond a -/// `WasiCtx` with other WASI proposals (e.g. `wasi-crypto` and `wasi-nn`) to manage their -/// resources. Elements in the `Table` are `Any` typed. -/// -/// The `Table` type is intended to model how the Interface Types concept of Resources is shaping -/// up. Right now it is just an approximation. +impl std::fmt::Display for ResourceTableError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Full => write!(f, "resource table has no free keys"), + Self::NotPresent => write!(f, "resource not present"), + Self::WrongType => write!(f, "resource is of another type"), + Self::HasChildren => write!(f, "resource has children"), + } + } +} +impl std::error::Error for ResourceTableError {} + +/// The `ResourceTable` type maps a `Resource` to its `T`. #[derive(Debug)] -pub struct Table { +pub struct ResourceTable { entries: Vec, free_head: Option, } @@ -86,10 +94,10 @@ impl TableEntry { } } -impl Table { +impl ResourceTable { /// Create an empty table pub fn new() -> Self { - Table { + ResourceTable { entries: Vec::new(), free_head: None, } @@ -97,7 +105,7 @@ impl Table { /// Create an empty table with at least the specified capacity. pub fn with_capacity(capacity: usize) -> Self { - Table { + ResourceTable { entries: Vec::with_capacity(capacity), free_head: None, } @@ -105,7 +113,7 @@ impl Table { /// Inserts a new value `T` into this table, returning a corresponding /// `Resource` which can be used to refer to it after it was inserted. - pub fn push(&mut self, entry: T) -> Result, TableError> + pub fn push(&mut self, entry: T) -> Result, ResourceTableError> where T: Send + Sync + 'static, { @@ -146,7 +154,7 @@ impl Table { /// Push a new entry into the table, returning its handle. This will prefer to use free entries /// if they exist, falling back on pushing new entries onto the end of the table. - fn push_(&mut self, e: TableEntry) -> Result { + fn push_(&mut self, e: TableEntry) -> Result { if let Some(free) = self.pop_free_list() { self.entries[free] = Entry::Occupied { entry: e }; Ok(free as u32) @@ -155,32 +163,33 @@ impl Table { .entries .len() .try_into() - .map_err(|_| TableError::Full)?; + .map_err(|_| ResourceTableError::Full)?; self.entries.push(Entry::Occupied { entry: e }); Ok(ix) } } - fn occupied(&self, key: u32) -> Result<&TableEntry, TableError> { + fn occupied(&self, key: u32) -> Result<&TableEntry, ResourceTableError> { self.entries .get(key as usize) .and_then(Entry::occupied) - .ok_or(TableError::NotPresent) + .ok_or(ResourceTableError::NotPresent) } - fn occupied_mut(&mut self, key: u32) -> Result<&mut TableEntry, TableError> { + fn occupied_mut(&mut self, key: u32) -> Result<&mut TableEntry, ResourceTableError> { self.entries .get_mut(key as usize) .and_then(Entry::occupied_mut) - .ok_or(TableError::NotPresent) + .ok_or(ResourceTableError::NotPresent) } /// Insert a resource at the next available index, and track that it has a /// parent resource. /// /// The parent must exist to create a child. All children resources must - /// be destroyed before a parent can be destroyed - otherwise [`Table::delete`] - /// will fail with [`TableError::HasChildren`]. + /// be destroyed before a parent can be destroyed - otherwise + /// [`ResourceTable::delete`] will fail with + /// [`ResourceTableError::HasChildren`]. /// /// Parent-child relationships are tracked inside the table to ensure that /// a parent resource is not deleted while it has live children. This @@ -191,13 +200,14 @@ impl Table { /// possibility for deadlocks. /// /// Parent-child relationships may not be modified once created. There - /// is no way to observe these relationships through the [`Table`] methods - /// except for erroring on deletion, or the [`std::fmt::Debug`] impl. + /// is no way to observe these relationships through the [`ResourceTable`] + /// methods except for erroring on deletion, or the [`std::fmt::Debug`] + /// impl. pub fn push_child( &mut self, entry: T, parent: &Resource, - ) -> Result, TableError> + ) -> Result, ResourceTableError> where T: Send + Sync + 'static, U: 'static, @@ -213,33 +223,36 @@ impl Table { /// index. /// /// Multiple shared references can be borrowed at any given time. - pub fn get(&self, key: &Resource) -> Result<&T, TableError> { + pub fn get(&self, key: &Resource) -> Result<&T, ResourceTableError> { self.get_(key.rep())? .downcast_ref() - .ok_or(TableError::WrongType) + .ok_or(ResourceTableError::WrongType) } - fn get_(&self, key: u32) -> Result<&dyn Any, TableError> { + fn get_(&self, key: u32) -> Result<&dyn Any, ResourceTableError> { let r = self.occupied(key)?; Ok(&*r.entry) } /// Get an mutable reference to a resource of a given type at a given /// index. - pub fn get_mut(&mut self, key: &Resource) -> Result<&mut T, TableError> { + pub fn get_mut( + &mut self, + key: &Resource, + ) -> Result<&mut T, ResourceTableError> { self.get_any_mut(key.rep())? .downcast_mut() - .ok_or(TableError::WrongType) + .ok_or(ResourceTableError::WrongType) } /// Returns the raw `Any` at the `key` index provided. - pub fn get_any_mut(&mut self, key: u32) -> Result<&mut dyn Any, TableError> { + pub fn get_any_mut(&mut self, key: u32) -> Result<&mut dyn Any, ResourceTableError> { let r = self.occupied_mut(key)?; Ok(&mut *r.entry) } /// Same as `delete`, but typed - pub fn delete(&mut self, resource: Resource) -> Result + pub fn delete(&mut self, resource: Resource) -> Result where T: Any, { @@ -247,13 +260,13 @@ impl Table { let entry = self.delete_entry(resource.rep())?; match entry.entry.downcast() { Ok(t) => Ok(*t), - Err(_e) => Err(TableError::WrongType), + Err(_e) => Err(ResourceTableError::WrongType), } } - fn delete_entry(&mut self, key: u32) -> Result { + fn delete_entry(&mut self, key: u32) -> Result { if !self.occupied(key)?.children.is_empty() { - return Err(TableError::HasChildren); + return Err(ResourceTableError::HasChildren); } let e = self.free_entry(key as usize); if let Some(parent) = e.parent { @@ -269,11 +282,11 @@ impl Table { /// Zip the values of the map with mutable references to table entries corresponding to each /// key. As the keys in the [HashMap] are unique, this iterator can give mutable references - /// with the same lifetime as the mutable reference to the [Table]. + /// with the same lifetime as the mutable reference to the [ResourceTable]. pub fn iter_entries<'a, T>( &'a mut self, map: HashMap, - ) -> impl Iterator, T)> { + ) -> impl Iterator, T)> { map.into_iter().map(move |(k, v)| { let item = self .occupied_mut(k) @@ -288,7 +301,7 @@ impl Table { pub fn iter_children( &self, parent: &Resource, - ) -> Result, TableError> + ) -> Result, ResourceTableError> where T: 'static, { @@ -300,15 +313,15 @@ impl Table { } } -impl Default for Table { +impl Default for ResourceTable { fn default() -> Self { - Table::new() + ResourceTable::new() } } #[test] pub fn test_free_list() { - let mut table = Table::new(); + let mut table = ResourceTable::new(); let x = table.push(()).unwrap(); assert_eq!(x.rep(), 0); diff --git a/crates/wasmtime/src/component/mod.rs b/crates/wasmtime/src/component/mod.rs index e2028a2bebb5..364942b53c06 100644 --- a/crates/wasmtime/src/component/mod.rs +++ b/crates/wasmtime/src/component/mod.rs @@ -10,6 +10,7 @@ mod func; mod instance; mod linker; mod matching; +mod resource_table; mod resources; mod storage; mod store; @@ -21,6 +22,7 @@ pub use self::func::{ }; pub use self::instance::{ExportInstance, Exports, Instance, InstancePre}; pub use self::linker::{Linker, LinkerInstance}; +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}; From 0442eeb0e773a27daf38b039af8614fea1b847a3 Mon Sep 17 00:00:00 2001 From: Pat Hickey Date: Thu, 30 Nov 2023 14:15:45 -0800 Subject: [PATCH 02/10] wasi: use the table from wasmtime::component --- crates/wasi/src/preview2/ctx.rs | 7 ++++--- crates/wasi/src/preview2/filesystem.rs | 7 +++---- crates/wasi/src/preview2/host/clocks.rs | 2 +- crates/wasi/src/preview2/host/filesystem.rs | 8 ++++---- crates/wasi/src/preview2/mod.rs | 3 +-- crates/wasi/src/preview2/network.rs | 6 +++--- crates/wasi/src/preview2/poll.rs | 8 ++++---- crates/wasi/src/preview2/preview1.rs | 8 ++++---- crates/wasi/src/preview2/stream.rs | 5 ++--- 9 files changed, 26 insertions(+), 28 deletions(-) diff --git a/crates/wasi/src/preview2/ctx.rs b/crates/wasi/src/preview2/ctx.rs index 73cd0e116e50..396852f6bbae 100644 --- a/crates/wasi/src/preview2/ctx.rs +++ b/crates/wasi/src/preview2/ctx.rs @@ -4,7 +4,7 @@ use crate::preview2::{ filesystem::Dir, pipe, random, stdio, stdio::{StdinStream, StdoutStream}, - DirPerms, FilePerms, Table, + DirPerms, FilePerms, }; use cap_rand::{Rng, RngCore, SeedableRng}; use cap_std::ipnet::{self, IpNet}; @@ -12,6 +12,7 @@ use cap_std::net::Pool; use cap_std::{ambient_authority, AmbientAuthority}; use std::mem; use std::net::{Ipv4Addr, Ipv6Addr}; +use wasmtime::component::ResourceTable; pub struct WasiCtxBuilder { stdin: Box, @@ -302,8 +303,8 @@ impl WasiCtxBuilder { } pub trait WasiView: Send { - fn table(&self) -> &Table; - fn table_mut(&mut self) -> &mut Table; + fn table(&self) -> &ResourceTable; + fn table_mut(&mut self) -> &mut ResourceTable; fn ctx(&self) -> &WasiCtx; fn ctx_mut(&mut self) -> &mut WasiCtx; } diff --git a/crates/wasi/src/preview2/filesystem.rs b/crates/wasi/src/preview2/filesystem.rs index d8dc2bc68ada..1f1d149dd93f 100644 --- a/crates/wasi/src/preview2/filesystem.rs +++ b/crates/wasi/src/preview2/filesystem.rs @@ -1,7 +1,6 @@ use crate::preview2::bindings::filesystem::types; use crate::preview2::{ - spawn_blocking, AbortOnDropJoinHandle, HostOutputStream, StreamError, Subscribe, TableError, - TrappableError, + spawn_blocking, AbortOnDropJoinHandle, HostOutputStream, StreamError, Subscribe, TrappableError, }; use anyhow::anyhow; use bytes::{Bytes, BytesMut}; @@ -13,8 +12,8 @@ pub type FsResult = Result; pub type FsError = TrappableError; -impl From for FsError { - fn from(error: TableError) -> Self { +impl From for FsError { + fn from(error: wasmtime::component::ResourceTableError) -> Self { Self::trap(error) } } diff --git a/crates/wasi/src/preview2/host/clocks.rs b/crates/wasi/src/preview2/host/clocks.rs index 4467b3681ec3..2f16b9e10490 100644 --- a/crates/wasi/src/preview2/host/clocks.rs +++ b/crates/wasi/src/preview2/host/clocks.rs @@ -43,7 +43,7 @@ impl wall_clock::Host for T { } fn subscribe_to_duration( - table: &mut crate::preview2::Table, + table: &mut wasmtime::component::ResourceTable, duration: tokio::time::Duration, ) -> anyhow::Result> { let sleep = if duration.is_zero() { diff --git a/crates/wasi/src/preview2/host/filesystem.rs b/crates/wasi/src/preview2/host/filesystem.rs index 39559ed43aec..4a70efee51e3 100644 --- a/crates/wasi/src/preview2/host/filesystem.rs +++ b/crates/wasi/src/preview2/host/filesystem.rs @@ -6,9 +6,9 @@ use crate::preview2::bindings::filesystem::types::{ use crate::preview2::bindings::io::streams::{InputStream, OutputStream}; use crate::preview2::filesystem::{Descriptor, Dir, File, ReaddirIterator}; use crate::preview2::filesystem::{FileInputStream, FileOutputStream}; -use crate::preview2::{DirPerms, FilePerms, FsError, FsResult, Table, WasiView}; +use crate::preview2::{DirPerms, FilePerms, FsError, FsResult, WasiView}; use anyhow::Context; -use wasmtime::component::Resource; +use wasmtime::component::{Resource, ResourceTable}; mod sync; @@ -840,7 +840,7 @@ impl HostDirectoryEntryStream for T { } async fn get_descriptor_metadata( - table: &Table, + table: &ResourceTable, fd: Resource, ) -> FsResult { match table.get(&fd)? { @@ -1059,7 +1059,7 @@ mod test { use super::*; #[test] fn table_readdir_works() { - let mut table = Table::new(); + let mut table = ResourceTable::new(); let ix = table .push(ReaddirIterator::new(std::iter::empty())) .unwrap(); diff --git a/crates/wasi/src/preview2/mod.rs b/crates/wasi/src/preview2/mod.rs index d4eb0e409cdf..f7fc9004e892 100644 --- a/crates/wasi/src/preview2/mod.rs +++ b/crates/wasi/src/preview2/mod.rs @@ -36,7 +36,6 @@ pub mod preview1; mod random; mod stdio; mod stream; -mod table; mod tcp; mod udp; mod write_stream; @@ -54,9 +53,9 @@ pub use self::stdio::{ pub use self::stream::{ HostInputStream, HostOutputStream, InputStream, OutputStream, StreamError, StreamResult, }; -pub use self::table::{Table, TableError}; pub use cap_fs_ext::SystemTimeSpec; pub use cap_rand::RngCore; +pub use wasmtime::component::{ResourceTable, ResourceTableError}; pub mod bindings { // Generate traits for synchronous bindings. diff --git a/crates/wasi/src/preview2/network.rs b/crates/wasi/src/preview2/network.rs index 65c380bd153c..13575202b72c 100644 --- a/crates/wasi/src/preview2/network.rs +++ b/crates/wasi/src/preview2/network.rs @@ -1,6 +1,6 @@ use crate::preview2::bindings::sockets::network::{Ipv4Address, Ipv6Address}; use crate::preview2::bindings::wasi::sockets::network::ErrorCode; -use crate::preview2::{TableError, TrappableError}; +use crate::preview2::TrappableError; use cap_std::net::Pool; pub struct Network { @@ -12,8 +12,8 @@ pub type SocketResult = Result; pub type SocketError = TrappableError; -impl From for SocketError { - fn from(error: TableError) -> Self { +impl From for SocketError { + fn from(error: wasmtime::component::ResourceTableError) -> Self { Self::trap(error) } } diff --git a/crates/wasi/src/preview2/poll.rs b/crates/wasi/src/preview2/poll.rs index 8e2b5385ffe1..4fba2a9940e0 100644 --- a/crates/wasi/src/preview2/poll.rs +++ b/crates/wasi/src/preview2/poll.rs @@ -1,11 +1,11 @@ -use crate::preview2::{bindings::io::poll, Table, WasiView}; +use crate::preview2::{bindings::io::poll, WasiView}; use anyhow::Result; use std::any::Any; use std::collections::HashMap; use std::future::Future; use std::pin::Pin; use std::task::{Context, Poll}; -use wasmtime::component::Resource; +use wasmtime::component::{Resource, ResourceTable}; pub type PollableFuture<'a> = Pin + Send + 'a>>; pub type MakeFuture = for<'a> fn(&'a mut dyn Any) -> PollableFuture<'a>; @@ -20,7 +20,7 @@ pub type ClosureFuture = Box PollableFuture<'static> + Send + Sync + pub struct Pollable { index: u32, make_future: MakeFuture, - remove_index_on_delete: Option Result<()>>, + remove_index_on_delete: Option Result<()>>, } #[async_trait::async_trait] @@ -35,7 +35,7 @@ pub trait Subscribe: Send + Sync + 'static { /// resource is deleted. Otherwise the returned resource is considered a "child" /// of the given `resource` which means that the given resource cannot be /// deleted while the `pollable` is still alive. -pub fn subscribe(table: &mut Table, resource: Resource) -> Result> +pub fn subscribe(table: &mut ResourceTable, resource: Resource) -> Result> where T: Subscribe, { diff --git a/crates/wasi/src/preview2/preview1.rs b/crates/wasi/src/preview2/preview1.rs index 967bceb0798c..8a0c64bd713c 100644 --- a/crates/wasi/src/preview2/preview1.rs +++ b/crates/wasi/src/preview2/preview1.rs @@ -8,7 +8,7 @@ use crate::preview2::bindings::{ filesystem::{preopens, types as filesystem}, io::{poll, streams}, }; -use crate::preview2::{FsError, IsATTY, StreamError, StreamResult, TableError, WasiView}; +use crate::preview2::{FsError, IsATTY, StreamError, StreamResult, WasiView}; use anyhow::{bail, Context}; use std::borrow::Borrow; use std::collections::{BTreeMap, HashSet}; @@ -325,7 +325,7 @@ pub trait WasiPreview1View: WasiView { // `&mut self` receivers and so this struct lets us extend the lifetime of the `&mut self` borrow // of the [`WasiPreview1View`] to provide means to return mutably and immutably borrowed [`Descriptors`] // without having to rely on something like `Arc>`, while also being able to -// call methods like [`TableFsExt::is_file`] and hiding complexity from preview1 method implementations. +// call methods like [`Descriptor::is_file`] and hiding complexity from preview1 method implementations. struct Transaction<'a, T: WasiPreview1View + ?Sized> { view: &'a mut T, descriptors: Descriptors, @@ -772,8 +772,8 @@ impl From for types::Error { } } -impl From for types::Error { - fn from(err: TableError) -> Self { +impl From for types::Error { + fn from(err: wasmtime::component::ResourceTableError) -> Self { types::Error::trap(err.into()) } } diff --git a/crates/wasi/src/preview2/stream.rs b/crates/wasi/src/preview2/stream.rs index ee13b6afa387..bf2ce502ba5c 100644 --- a/crates/wasi/src/preview2/stream.rs +++ b/crates/wasi/src/preview2/stream.rs @@ -1,6 +1,5 @@ use crate::preview2::filesystem::FileInputStream; use crate::preview2::poll::Subscribe; -use crate::preview2::TableError; use anyhow::Result; use bytes::Bytes; @@ -73,8 +72,8 @@ impl std::error::Error for StreamError { } } -impl From for StreamError { - fn from(error: TableError) -> Self { +impl From for StreamError { + fn from(error: wasmtime::component::ResourceTableError) -> Self { Self::Trap(error.into()) } } From b6b257d2102c876a553a10d350c78712aeb14d94 Mon Sep 17 00:00:00 2001 From: Pat Hickey Date: Thu, 30 Nov 2023 14:17:08 -0800 Subject: [PATCH 03/10] wasi-http: use wasmtime::component's resource table now --- crates/wasi-http/src/types.rs | 6 +++--- crates/wasi-http/src/types_impl.rs | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/crates/wasi-http/src/types.rs b/crates/wasi-http/src/types.rs index 1657d9a36650..2a9a92b98125 100644 --- a/crates/wasi-http/src/types.rs +++ b/crates/wasi-http/src/types.rs @@ -14,8 +14,8 @@ use std::sync::Arc; use std::time::Duration; use tokio::net::TcpStream; use tokio::time::timeout; -use wasmtime::component::Resource; -use wasmtime_wasi::preview2::{self, AbortOnDropJoinHandle, Subscribe, Table}; +use wasmtime::component::{Resource, ResourceTable}; +use wasmtime_wasi::preview2::{self, AbortOnDropJoinHandle, Subscribe}; /// Capture the state necessary for use in the wasi-http API implementation. pub struct WasiHttpCtx; @@ -31,7 +31,7 @@ pub struct OutgoingRequest { pub trait WasiHttpView: Send { fn ctx(&mut self) -> &mut WasiHttpCtx; - fn table(&mut self) -> &mut Table; + fn table(&mut self) -> &mut ResourceTable; fn new_incoming_request( &mut self, diff --git a/crates/wasi-http/src/types_impl.rs b/crates/wasi-http/src/types_impl.rs index 74ee18c2ff57..351f8f59d775 100644 --- a/crates/wasi-http/src/types_impl.rs +++ b/crates/wasi-http/src/types_impl.rs @@ -11,10 +11,10 @@ use crate::{ use anyhow::Context; use std::any::Any; use std::str::FromStr; -use wasmtime::component::Resource; +use wasmtime::component::{Resource, ResourceTable}; use wasmtime_wasi::preview2::{ bindings::io::streams::{InputStream, OutputStream}, - Pollable, Table, + Pollable, }; impl crate::bindings::http::types::Host for T { @@ -49,7 +49,7 @@ fn get_content_length(fields: &FieldMap) -> Result, ()> { /// Take ownership of the underlying [`FieldMap`] associated with this fields resource. If the /// fields resource references another fields, the returned [`FieldMap`] will be cloned. -fn move_fields(table: &mut Table, id: Resource) -> wasmtime::Result { +fn move_fields(table: &mut ResourceTable, id: Resource) -> wasmtime::Result { match table.delete(id)? { HostFields::Ref { parent, get_fields } => { let entry = table.get_any_mut(parent)?; @@ -61,7 +61,7 @@ fn move_fields(table: &mut Table, id: Resource) -> wasmtime::Result< } fn get_fields<'a>( - table: &'a mut Table, + table: &'a mut ResourceTable, id: &Resource, ) -> wasmtime::Result<&'a FieldMap> { let fields = table.get(&id)?; @@ -80,7 +80,7 @@ fn get_fields<'a>( } fn get_fields_mut<'a>( - table: &'a mut Table, + table: &'a mut ResourceTable, id: &Resource, ) -> wasmtime::Result> { match table.get_mut(&id)? { From d5f1299d5340630523956be3ad8b99a8cfeacf52 Mon Sep 17 00:00:00 2001 From: Pat Hickey Date: Thu, 7 Dec 2023 11:04:27 -0800 Subject: [PATCH 04/10] rename file (somehow got lost) --- .../table.rs => wasmtime/src/component/resource_table.rs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename crates/{wasi/src/preview2/table.rs => wasmtime/src/component/resource_table.rs} (100%) diff --git a/crates/wasi/src/preview2/table.rs b/crates/wasmtime/src/component/resource_table.rs similarity index 100% rename from crates/wasi/src/preview2/table.rs rename to crates/wasmtime/src/component/resource_table.rs From b6e19369d33046be6fac478cc7b38d59e1156ea6 Mon Sep 17 00:00:00 2001 From: Pat Hickey Date: Thu, 7 Dec 2023 11:52:02 -0800 Subject: [PATCH 05/10] wasmtime-cli: fixes for resourcetable --- src/commands/run.rs | 10 ++++++---- src/commands/serve.rs | 14 ++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/commands/run.rs b/src/commands/run.rs index 5f43c5a542bf..92b671626acf 100644 --- a/src/commands/run.rs +++ b/src/commands/run.rs @@ -791,7 +791,8 @@ struct Host { // Resource table for preview2 if the `preview2_ctx` is in use, otherwise // "just" an empty table. - preview2_table: Arc, + #[cfg(feature = "component-model")] + preview2_table: Arc, // State necessary for the preview1 implementation of WASI backed by the // preview2 host implementation. Only used with the `--preview2` flag right @@ -809,12 +810,13 @@ struct Host { guest_profiler: Option>, } +#[cfg(feature = "component-model")] impl preview2::WasiView for Host { - fn table(&self) -> &preview2::Table { + fn table(&self) -> &wasmtime::component::ResourceTable { &self.preview2_table } - fn table_mut(&mut self) -> &mut preview2::Table { + fn table_mut(&mut self) -> &mut wasmtime::component::ResourceTable { Arc::get_mut(&mut self.preview2_table).expect("preview2 is not compatible with threads") } @@ -845,7 +847,7 @@ impl wasmtime_wasi_http::types::WasiHttpView for Host { Arc::get_mut(ctx).expect("preview2 is not compatible with threads") } - fn table(&mut self) -> &mut preview2::Table { + fn table(&mut self) -> &mut wasmtime::component::ResourceTable { Arc::get_mut(&mut self.preview2_table).expect("preview2 is not compatible with threads") } } diff --git a/src/commands/serve.rs b/src/commands/serve.rs index 629ec8b57d6d..5601b3ddd940 100644 --- a/src/commands/serve.rs +++ b/src/commands/serve.rs @@ -11,9 +11,7 @@ use std::{ }; use wasmtime::component::{InstancePre, Linker}; use wasmtime::{Engine, Store, StoreLimits}; -use wasmtime_wasi::preview2::{ - self, StreamError, StreamResult, Table, WasiCtx, WasiCtxBuilder, WasiView, -}; +use wasmtime_wasi::preview2::{self, StreamError, StreamResult, WasiCtx, WasiCtxBuilder, WasiView}; use wasmtime_wasi_http::io::TokioIo; use wasmtime_wasi_http::{ bindings::http::types as http_types, body::HyperOutgoingBody, hyper_response_error, @@ -24,7 +22,7 @@ use wasmtime_wasi_http::{ use wasmtime_wasi_nn::WasiNnCtx; struct Host { - table: Table, + table: wasmtime::component::ResourceTable, ctx: WasiCtx, http: WasiHttpCtx, @@ -35,11 +33,11 @@ struct Host { } impl WasiView for Host { - fn table(&self) -> &Table { + fn table(&self) -> &wasmtime::component::ResourceTable { &self.table } - fn table_mut(&mut self) -> &mut Table { + fn table_mut(&mut self) -> &mut wasmtime::component::ResourceTable { &mut self.table } @@ -53,7 +51,7 @@ impl WasiView for Host { } impl WasiHttpView for Host { - fn table(&mut self) -> &mut Table { + fn table(&mut self) -> &mut wasmtime::component::ResourceTable { &mut self.table } @@ -157,7 +155,7 @@ impl ServeCommand { }); let mut host = Host { - table: Table::new(), + table: wasmtime::component::ResourceTable::new(), ctx: builder.build(), http: WasiHttpCtx, From a369c1079aeb7136a9deb73e3b98188e98ffb119 Mon Sep 17 00:00:00 2001 From: Pat Hickey Date: Thu, 7 Dec 2023 14:04:29 -0800 Subject: [PATCH 06/10] fix wasi-http tests --- crates/wasi-http/tests/all/main.rs | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/crates/wasi-http/tests/all/main.rs b/crates/wasi-http/tests/all/main.rs index 002e28b790e9..f078a30dece4 100644 --- a/crates/wasi-http/tests/all/main.rs +++ b/crates/wasi-http/tests/all/main.rs @@ -8,12 +8,10 @@ use sha2::{Digest, Sha256}; use std::{collections::HashMap, iter, net::Ipv4Addr, str, sync::Arc}; use tokio::task; use wasmtime::{ - component::{Component, Linker, Resource}, + component::{Component, Linker, Resource, ResourceTable}, Config, Engine, Store, }; -use wasmtime_wasi::preview2::{ - self, pipe::MemoryOutputPipe, Table, WasiCtx, WasiCtxBuilder, WasiView, -}; +use wasmtime_wasi::preview2::{self, pipe::MemoryOutputPipe, WasiCtx, WasiCtxBuilder, WasiView}; use wasmtime_wasi_http::{ bindings::http::types::ErrorCode, body::HyperIncomingBody, @@ -31,7 +29,7 @@ type RequestSender = Arc< >; struct Ctx { - table: Table, + table: ResourceTable, wasi: WasiCtx, http: WasiHttpCtx, stdout: MemoryOutputPipe, @@ -40,10 +38,10 @@ struct Ctx { } impl WasiView for Ctx { - fn table(&self) -> &Table { + fn table(&self) -> &ResourceTable { &self.table } - fn table_mut(&mut self) -> &mut Table { + fn table_mut(&mut self) -> &mut ResourceTable { &mut self.table } fn ctx(&self) -> &WasiCtx { @@ -59,7 +57,7 @@ impl WasiHttpView for Ctx { &mut self.http } - fn table(&mut self) -> &mut Table { + fn table(&mut self) -> &mut ResourceTable { &mut self.table } @@ -89,7 +87,7 @@ fn store(engine: &Engine, server: &Server) -> Store { builder.stderr(stderr.clone()); builder.env("HTTP_SERVER", server.addr().to_string()); let ctx = Ctx { - table: Table::new(), + table: ResourceTable::new(), wasi: builder.build(), http: WasiHttpCtx {}, stderr, @@ -132,7 +130,7 @@ async fn run_wasi_http( ) -> anyhow::Result>, ErrorCode>> { let stdout = MemoryOutputPipe::new(4096); let stderr = MemoryOutputPipe::new(4096); - let table = Table::new(); + let table = ResourceTable::new(); let mut config = Config::new(); config.wasm_backtrace_details(wasmtime::WasmBacktraceDetails::Enable); From dbc32036111f0cdc2a3131ecb7921b69dca89cf7 Mon Sep 17 00:00:00 2001 From: Pat Hickey Date: Thu, 7 Dec 2023 14:09:24 -0800 Subject: [PATCH 07/10] more test fixes --- crates/wasi/tests/all/api.rs | 17 ++++++++--------- crates/wasi/tests/all/main.rs | 12 ++++++------ 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/crates/wasi/tests/all/api.rs b/crates/wasi/tests/all/api.rs index 4abf8a11923c..413713aa1f65 100644 --- a/crates/wasi/tests/all/api.rs +++ b/crates/wasi/tests/all/api.rs @@ -4,26 +4,25 @@ use cap_std::fs::Dir; use std::io::Write; use std::sync::Mutex; use std::time::Duration; -use wasmtime::component::{Component, Linker}; +use wasmtime::component::{Component, Linker, ResourceTable}; use wasmtime::{Config, Engine, Store}; use wasmtime_wasi::preview2::bindings::wasi::clocks::wall_clock; use wasmtime_wasi::preview2::bindings::wasi::filesystem::types as filesystem; use wasmtime_wasi::preview2::command::{add_to_linker, Command}; use wasmtime_wasi::preview2::{ - self, DirPerms, FilePerms, HostMonotonicClock, HostWallClock, Table, WasiCtx, WasiCtxBuilder, - WasiView, + self, DirPerms, FilePerms, HostMonotonicClock, HostWallClock, WasiCtx, WasiCtxBuilder, WasiView, }; struct CommandCtx { - table: Table, + table: ResourceTable, wasi: WasiCtx, } impl WasiView for CommandCtx { - fn table(&self) -> &Table { + fn table(&self) -> &ResourceTable { &self.table } - fn table_mut(&mut self) -> &mut Table { + fn table_mut(&mut self) -> &mut ResourceTable { &mut self.table } fn ctx(&self) -> &WasiCtx { @@ -82,7 +81,7 @@ async fn api_time() -> Result<()> { } } - let table = Table::new(); + let table = ResourceTable::new(); let wasi = WasiCtxBuilder::new() .monotonic_clock(FakeMonotonicClock { now: Mutex::new(0) }) .wall_clock(FakeWallClock) @@ -104,7 +103,7 @@ async fn api_read_only() -> Result<()> { std::fs::File::create(dir.path().join("bar.txt"))?.write_all(b"And stood awhile in thought")?; std::fs::create_dir(dir.path().join("sub"))?; - let table = Table::new(); + let table = ResourceTable::new(); let open_dir = Dir::open_ambient_dir(dir.path(), ambient_authority())?; let wasi = WasiCtxBuilder::new() .preopened_dir(open_dir, DirPerms::READ, FilePerms::READ, "/") @@ -155,7 +154,7 @@ wasmtime::component::bindgen!({ #[test_log::test(tokio::test)] async fn api_reactor() -> Result<()> { - let table = Table::new(); + let table = ResourceTable::new(); let wasi = WasiCtxBuilder::new().env("GOOD_DOG", "gussie").build(); let mut config = Config::new(); diff --git a/crates/wasi/tests/all/main.rs b/crates/wasi/tests/all/main.rs index 1af5503f029d..03cf8031b157 100644 --- a/crates/wasi/tests/all/main.rs +++ b/crates/wasi/tests/all/main.rs @@ -2,17 +2,17 @@ use anyhow::Result; use cap_std::ambient_authority; use tempfile::TempDir; use wasmtime::{ - component::{Component, Linker}, + component::{Component, Linker, ResourceTable}, Config, Engine, Store, }; use wasmtime_wasi::preview2::{ pipe::MemoryOutputPipe, preview1::{WasiPreview1Adapter, WasiPreview1View}, - DirPerms, FilePerms, Table, WasiCtx, WasiCtxBuilder, WasiView, + DirPerms, FilePerms, WasiCtx, WasiCtxBuilder, WasiView, }; struct Ctx { - table: Table, + table: ResourceTable, wasi: WasiCtx, stdout: MemoryOutputPipe, stderr: MemoryOutputPipe, @@ -20,10 +20,10 @@ struct Ctx { } impl WasiView for Ctx { - fn table(&self) -> &Table { + fn table(&self) -> &ResourceTable { &self.table } - fn table_mut(&mut self) -> &mut Table { + fn table_mut(&mut self) -> &mut ResourceTable { &mut self.table } fn ctx(&self) -> &WasiCtx { @@ -75,7 +75,7 @@ fn store(engine: &Engine, name: &str, inherit_stdio: bool) -> Result<(Store } let ctx = Ctx { - table: Table::new(), + table: ResourceTable::new(), wasi: builder.build(), stderr, stdout, From 53b37d3c4ec8b482fd842d958d733a33ff7bc959 Mon Sep 17 00:00:00 2001 From: Pat Hickey Date: Thu, 7 Dec 2023 14:26:21 -0800 Subject: [PATCH 08/10] error messages --- crates/wasi/tests/all/async_.rs | 2 +- crates/wasi/tests/all/sync.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/wasi/tests/all/async_.rs b/crates/wasi/tests/all/async_.rs index be7359e92371..49ba0c52a96b 100644 --- a/crates/wasi/tests/all/async_.rs +++ b/crates/wasi/tests/all/async_.rs @@ -351,6 +351,6 @@ async fn preview2_stream_pollable_traps() { .unwrap_err(); assert_eq!( format!("{}", e.source().expect("trap source")), - "entry still has children" + "resource has children" ) } diff --git a/crates/wasi/tests/all/sync.rs b/crates/wasi/tests/all/sync.rs index 61d4cf69b130..c005ac35ea7f 100644 --- a/crates/wasi/tests/all/sync.rs +++ b/crates/wasi/tests/all/sync.rs @@ -290,6 +290,6 @@ fn preview2_stream_pollable_traps() { let e = run(PREVIEW2_STREAM_POLLABLE_TRAPS_COMPONENT, false).unwrap_err(); assert_eq!( format!("{}", e.source().expect("trap source")), - "entry still has children" + "resource has children" ) } From 5d4c83a4618e5bac4c465b8ab237e8a310b667f7 Mon Sep 17 00:00:00 2001 From: Pat Hickey Date: Thu, 7 Dec 2023 16:13:59 -0800 Subject: [PATCH 09/10] fix warning --- crates/wasi-common/src/error.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/wasi-common/src/error.rs b/crates/wasi-common/src/error.rs index b1a5135bb2b0..11b43ecd4952 100644 --- a/crates/wasi-common/src/error.rs +++ b/crates/wasi-common/src/error.rs @@ -7,7 +7,7 @@ //! can be provided with the [`Error::context`] method. This context is only observable with the //! `Display` and `Debug` impls of the error. -pub use crate::snapshots::preview_1::error::{Errno, Error, ErrorExt}; +pub use crate::snapshots::preview_1::error::{Error, ErrorExt}; use std::fmt; /// An error returned from the `proc_exit` host syscall. From fc920aa3ebfc759c9416f9fc8db8dbf553f83dfc Mon Sep 17 00:00:00 2001 From: Pat Hickey Date: Thu, 7 Dec 2023 16:17:01 -0800 Subject: [PATCH 10/10] cli: fix min build prtest:full --- src/commands/run.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/commands/run.rs b/src/commands/run.rs index 92b671626acf..e0155dcf7383 100644 --- a/src/commands/run.rs +++ b/src/commands/run.rs @@ -791,7 +791,6 @@ struct Host { // Resource table for preview2 if the `preview2_ctx` is in use, otherwise // "just" an empty table. - #[cfg(feature = "component-model")] preview2_table: Arc, // State necessary for the preview1 implementation of WASI backed by the @@ -810,7 +809,6 @@ struct Host { guest_profiler: Option>, } -#[cfg(feature = "component-model")] impl preview2::WasiView for Host { fn table(&self) -> &wasmtime::component::ResourceTable { &self.preview2_table