Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
457 changes: 312 additions & 145 deletions Cargo.lock

Large diffs are not rendered by default.

16 changes: 8 additions & 8 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -169,16 +169,16 @@ tower-service = "0.3.3"
tracing = { version = "0.1.41", features = ["log"] }
url = "2"
walkdir = "2"
wasm-encoder = "0.235"
wasm-metadata = "0.235"
wasm-encoder = "0.236.1"
wasm-metadata = "0.236.1"
wasm-pkg-client = "0.11"
wasm-pkg-common = "0.11"
wasmparser = "0.235"
wasmtime = "35.0.0"
wasmtime-wasi = "35.0.0"
wasmtime-wasi-http = "35.0.0"
wit-component = "0.235"
wit-parser = "0.235"
wasmparser = "0.236.1"
wasmtime = "36.0.1"
wasmtime-wasi = "36.0.1"
wasmtime-wasi-http = "36.0.1"
wit-component = "0.236.1"
wit-parser = "0.236.1"

spin-componentize = { path = "crates/componentize" }

Expand Down
22 changes: 9 additions & 13 deletions crates/componentize/src/abi_conformance/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ use wasmtime::{
component::{Component, HasSelf, InstancePre, Linker},
Engine, Store,
};
use wasmtime_wasi::p2::{pipe::MemoryOutputPipe, IoView, WasiCtx, WasiCtxBuilder, WasiView};
use wasmtime_wasi::ResourceTable;
use wasmtime_wasi::p2::pipe::MemoryOutputPipe;
use wasmtime_wasi::{ResourceTable, WasiCtx, WasiCtxBuilder, WasiCtxView, WasiView};

pub use test_key_value::KeyValueReport;
pub use test_llm::LlmReport;
Expand All @@ -60,8 +60,7 @@ mod test_wasi;
wasmtime::component::bindgen!({
path: "../../wit",
world: "fermyon:spin/host",
async: true,
trappable_imports: true,
imports: { default: async | trappable },
});
pub use fermyon::spin::*;

Expand Down Expand Up @@ -264,15 +263,12 @@ impl Context {
}
}

impl IoView for Context {
fn table(&mut self) -> &mut ResourceTable {
&mut self.table
}
}

impl WasiView for Context {
fn ctx(&mut self) -> &mut WasiCtx {
&mut self.wasi
fn ctx(&mut self) -> WasiCtxView<'_> {
WasiCtxView {
ctx: &mut self.wasi,
table: &mut self.table,
}
}
}

Expand Down Expand Up @@ -321,7 +317,7 @@ async fn run_command(
// ownership once we return.
let table = ResourceTable::new();
store.data_mut().wasi = WasiCtxBuilder::new().build();
*store.data_mut().table() = table;
*store.data_mut().ctx().table = table;
let stderr =
std::mem::replace(&mut store.data_mut().stderr, MemoryOutputPipe::new(1024));

Expand Down
18 changes: 7 additions & 11 deletions crates/componentize/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -267,10 +267,8 @@ mod tests {
component::{Component, Linker},
Config, Engine, Store,
},
wasmtime_wasi::p2::{
bindings::Command, pipe::MemoryInputPipe, IoView, WasiCtx, WasiCtxBuilder, WasiView,
},
wasmtime_wasi::ResourceTable,
wasmtime_wasi::p2::{bindings::Command, pipe::MemoryInputPipe},
wasmtime_wasi::{ResourceTable, WasiCtx, WasiCtxBuilder, WasiCtxView, WasiView},
};

async fn run_spin(module: &[u8]) -> Result<()> {
Expand Down Expand Up @@ -359,14 +357,12 @@ mod tests {
ctx: WasiCtx,
table: ResourceTable,
}
impl IoView for Wasi {
fn table(&mut self) -> &mut ResourceTable {
&mut self.table
}
}
impl WasiView for Wasi {
fn ctx(&mut self) -> &mut WasiCtx {
&mut self.ctx
fn ctx(&mut self) -> WasiCtxView<'_> {
WasiCtxView {
ctx: &mut self.ctx,
table: &mut self.table,
}
}
}

Expand Down
15 changes: 6 additions & 9 deletions crates/factor-outbound-http/src/wasi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ use tokio_rustls::client::TlsStream;
use tower_service::Service;
use tracing::{field::Empty, instrument, Instrument};
use wasmtime::component::HasData;
use wasmtime_wasi::p2::{IoImpl, IoView};
use wasmtime_wasi_http::{
bindings::http::types::ErrorCode,
body::HyperOutgoingBody,
Expand Down Expand Up @@ -60,7 +59,7 @@ where
C: spin_factors::InitContext<OutboundHttpFactor>,
{
let (state, table) = C::get_data_with_table(store);
WasiHttpImpl(IoImpl(WasiHttpImplInner { state, table }))
WasiHttpImpl(WasiHttpImplInner { state, table })
}
let get_http = get_http::<C> as fn(&mut C::StoreData) -> WasiHttpImpl<WasiHttpImplInner<'_>>;
let linker = ctx.linker();
Expand All @@ -84,7 +83,7 @@ impl OutboundHttpFactor {
runtime_instance_state: &mut impl RuntimeFactorsInstanceState,
) -> Option<WasiHttpImpl<impl WasiHttpView + '_>> {
let (state, table) = runtime_instance_state.get_with_table::<OutboundHttpFactor>()?;
Some(WasiHttpImpl(IoImpl(WasiHttpImplInner { state, table })))
Some(WasiHttpImpl(WasiHttpImplInner { state, table }))
}
}

Expand Down Expand Up @@ -123,17 +122,15 @@ pub(crate) struct WasiHttpImplInner<'a> {
table: &'a mut ResourceTable,
}

impl IoView for WasiHttpImplInner<'_> {
fn table(&mut self) -> &mut ResourceTable {
self.table
}
}

impl WasiHttpView for WasiHttpImplInner<'_> {
fn ctx(&mut self) -> &mut WasiHttpCtx {
&mut self.state.wasi_http_ctx
}

fn table(&mut self) -> &mut ResourceTable {
self.table
}

#[instrument(
name = "spin_outbound_http.send_request",
skip_all,
Expand Down
7 changes: 2 additions & 5 deletions crates/factor-outbound-http/src/wasi_2023_10_18.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,8 @@ mod bindings {
wasmtime::component::bindgen!({
path: "../../wit",
world: "wasi:http/[email protected]",
async: {
// Only need async exports
only_imports: [],
},
imports: { default: trappable },
exports: { default: async },
with: {
"wasi:io/poll/pollable": latest::io::poll::Pollable,
"wasi:io/streams/input-stream": latest::io::streams::InputStream,
Expand All @@ -29,7 +27,6 @@ mod bindings {
"wasi:http/types/future-incoming-response": latest::http::types::FutureIncomingResponse,
"wasi:http/types/future-trailers": latest::http::types::FutureTrailers,
},
trappable_imports: true,
});
}

Expand Down
7 changes: 2 additions & 5 deletions crates/factor-outbound-http/src/wasi_2023_11_10.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,8 @@ mod bindings {
wasmtime::component::bindgen!({
path: "../../wit",
world: "wasi:http/[email protected]",
async: {
// Only need async exports
only_imports: [],
},
imports: { default: trappable },
exports: { default: async },
with: {
"wasi:io/poll/pollable": latest::io::poll::Pollable,
"wasi:io/streams/input-stream": latest::io::streams::InputStream,
Expand All @@ -33,7 +31,6 @@ mod bindings {
"wasi:http/types/future-trailers": latest::http::types::FutureTrailers,
"wasi:http/types/request-options": latest::http::types::RequestOptions,
},
trappable_imports: true,
});
}

Expand Down
4 changes: 2 additions & 2 deletions crates/factor-outbound-networking/tests/factor_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use spin_factor_variables::VariablesFactor;
use spin_factor_wasi::{DummyFilesMounter, WasiFactor};
use spin_factors::{anyhow, RuntimeFactors};
use spin_factors_test::{toml, TestEnvironment};
use wasmtime_wasi::p2::{bindings::sockets::instance_network::Host, IoView};
use wasmtime_wasi::p2::bindings::sockets::instance_network::Host;
use wasmtime_wasi::SocketAddrUse;

#[derive(RuntimeFactors)]
Expand Down Expand Up @@ -38,7 +38,7 @@ async fn configures_wasi_socket_addr_check() -> anyhow::Result<()> {
let mut wasi = WasiFactor::get_wasi_impl(&mut state).unwrap();

let network_resource = wasi.instance_network()?;
let network = wasi.table().get(&network_resource)?;
let network = wasi.table.get(&network_resource)?;

network
.check_socket_addr(
Expand Down
67 changes: 56 additions & 11 deletions crates/factor-wasi/src/io.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
use std::io::{Read, Write};
use std::io::{self, Read, Write};
use std::pin::Pin;
use std::sync::{Arc, Mutex};
use std::task::{Context, Poll};

use async_trait::async_trait;
use spin_factors::anyhow;
use wasmtime_wasi::p2::{
InputStream, OutputStream, Pollable, StdinStream, StdoutStream, StreamError,
};
use tokio::io::{AsyncRead, AsyncWrite};
use wasmtime_wasi::cli::{IsTerminal, StdinStream, StdoutStream};
use wasmtime_wasi::p2::{InputStream, OutputStream, Pollable, StreamError};

/// A [`OutputStream`] that writes to a `Write` type.
///
Expand Down Expand Up @@ -54,16 +56,37 @@ impl<T: Write + Send + Sync + 'static> OutputStream for PipedWriteStream<T> {
}
}

impl<T: Write + Send + Sync + 'static> StdoutStream for PipedWriteStream<T> {
fn stream(&self) -> Box<dyn OutputStream> {
Box::new(self.clone())
impl<T: Write + Send + Sync + 'static> AsyncWrite for PipedWriteStream<T> {
fn poll_write(
self: Pin<&mut Self>,
_cx: &mut Context<'_>,
buf: &[u8],
) -> Poll<io::Result<usize>> {
Poll::Ready(self.0.lock().unwrap().write(buf))
}
fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<io::Result<()>> {
Poll::Ready(self.0.lock().unwrap().flush())
}
fn poll_shutdown(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<io::Result<()>> {
Poll::Ready(Ok(()))
}
}

fn isatty(&self) -> bool {
impl<T> IsTerminal for PipedWriteStream<T> {
fn is_terminal(&self) -> bool {
false
}
}

impl<T: Write + Send + Sync + 'static> StdoutStream for PipedWriteStream<T> {
fn p2_stream(&self) -> Box<dyn OutputStream> {
Box::new(self.clone())
}
fn async_stream(&self) -> Box<dyn AsyncWrite + Send + Sync> {
Box::new(self.clone())
}
}

#[async_trait]
impl<T: Write + Send + Sync + 'static> Pollable for PipedWriteStream<T> {
async fn ready(&mut self) {}
Expand Down Expand Up @@ -95,6 +118,12 @@ impl<T> Clone for PipeReadStream<T> {
}
}

impl<T> IsTerminal for PipeReadStream<T> {
fn is_terminal(&self) -> bool {
false
}
}

impl<T: Read + Send + Sync + 'static> InputStream for PipeReadStream<T> {
fn read(&mut self, size: usize) -> wasmtime_wasi::p2::StreamResult<bytes::Bytes> {
let size = size.min(self.buffer.len());
Expand All @@ -113,17 +142,33 @@ impl<T: Read + Send + Sync + 'static> InputStream for PipeReadStream<T> {
}
}

impl<T: Read + Send + Sync + 'static> AsyncRead for PipeReadStream<T> {
fn poll_read(
self: Pin<&mut Self>,
_cx: &mut Context<'_>,
buf: &mut tokio::io::ReadBuf<'_>,
) -> Poll<io::Result<()>> {
let result = self
.inner
.lock()
.unwrap()
.read(buf.initialize_unfilled())
.map(|n| buf.advance(n));
Poll::Ready(result)
}
}

#[async_trait]
impl<T: Read + Send + Sync + 'static> Pollable for PipeReadStream<T> {
async fn ready(&mut self) {}
}

impl<T: Read + Send + Sync + 'static> StdinStream for PipeReadStream<T> {
fn stream(&self) -> Box<dyn InputStream> {
fn p2_stream(&self) -> Box<dyn InputStream> {
Box::new(self.clone())
}

fn isatty(&self) -> bool {
false
fn async_stream(&self) -> Box<dyn AsyncRead + Send + Sync> {
Box::new(self.clone())
}
}
Loading
Loading