Browse Source

possible to run preview 1 modules through host adapter

pull/6391/head
Pat Hickey 2 years ago
parent
commit
66775e0591
  1. 99
      host/src/main.rs
  2. 36
      wasi-common/src/preview1/mod.rs

99
host/src/main.rs

@ -1,5 +1,6 @@
use anyhow::{Context, Result};
use wasi_cap_std_sync::WasiCtxBuilder;
use wasi_common::preview1::{self, WasiPreview1Adapter, WasiPreview1View};
use wasi_common::{wasi, Table, WasiCtx, WasiView};
use wasmtime::{
component::{Component, Linker},
@ -53,15 +54,8 @@ async fn main() -> Result<()> {
.init();
let args = Args::parse();
let input = args.component;
let mut config = Config::new();
config.wasm_backtrace_details(wasmtime::WasmBacktraceDetails::Enable);
config.wasm_component_model(true);
config.async_support(true);
let engine = Engine::new(&config)?;
let component = Component::from_file(&engine, &input)?;
let input =
std::fs::read(&args.component).with_context(|| format!("reading '{}'", args.component))?;
let mut argv: Vec<&str> = vec!["wasm"];
argv.extend(args.args.iter().map(String::as_str));
@ -77,6 +71,18 @@ async fn main() -> Result<()> {
let mut table = Table::new();
let wasi = builder.build(&mut table)?;
if input.get(0..8) != Some(&[0x00, 0x61, 0x73, 0x6d, 0x0a, 0x00, 0x01, 0x00]) {
return module_main(input, table, wasi).await;
}
let mut config = Config::new();
config.wasm_backtrace_details(wasmtime::WasmBacktraceDetails::Enable);
config.async_support(true);
config.wasm_component_model(true);
let engine = Engine::new(&config)?;
let component = Component::new(&engine, &input)?;
if args.world == "command" {
struct CommandCtx {
table: Table,
@ -178,3 +184,78 @@ async fn main() -> Result<()> {
anyhow::bail!("no such world {}", args.world)
}
}
async fn module_main(module_bytes: Vec<u8>, table: Table, wasi: WasiCtx) -> Result<()> {
struct Preview1CommandCtx {
table: Table,
wasi: WasiCtx,
sockets: WasiSocketsCtx,
adapter: WasiPreview1Adapter,
}
impl WasiView for Preview1CommandCtx {
fn table(&self) -> &Table {
&self.table
}
fn table_mut(&mut self) -> &mut Table {
&mut self.table
}
fn ctx(&self) -> &WasiCtx {
&self.wasi
}
fn ctx_mut(&mut self) -> &mut WasiCtx {
&mut self.wasi
}
}
impl WasiSocketsView for Preview1CommandCtx {
fn table(&self) -> &Table {
&self.table
}
fn table_mut(&mut self) -> &mut Table {
&mut self.table
}
fn ctx(&self) -> &WasiSocketsCtx {
&self.sockets
}
fn ctx_mut(&mut self) -> &mut WasiSocketsCtx {
&mut self.sockets
}
}
impl WasiPreview1View for Preview1CommandCtx {
fn adapter(&self) -> &WasiPreview1Adapter {
&self.adapter
}
fn adapter_mut(&mut self) -> &mut WasiPreview1Adapter {
&mut self.adapter
}
}
let sockets = WasiSocketsCtxBuilder::new()
.inherit_network(cap_std::ambient_authority())
.build();
let adapter = WasiPreview1Adapter::new();
let ctx = Preview1CommandCtx {
table,
wasi,
sockets,
adapter,
};
let mut config = Config::new();
config.wasm_backtrace_details(wasmtime::WasmBacktraceDetails::Enable);
config.async_support(true);
let engine = Engine::new(&config)?;
let module = wasmtime::Module::new(&engine, module_bytes)?;
let mut linker = wasmtime::Linker::new(&engine);
preview1::add_to_linker(&mut linker)?;
let mut store = Store::new(&engine, ctx);
let inst = linker.instantiate_async(&mut store, &module).await?;
let start: wasmtime::TypedFunc<(), ()> = inst.get_typed_func(&mut store, "_start")?;
start.call_async(&mut store, ()).await?;
Ok(())
}

36
wasi-common/src/preview1/mod.rs

@ -4,19 +4,46 @@
use crate::wasi;
use wiggle::GuestPtr;
pub struct WasiPreview1Adapter {/* all members private and only used inside this module */}
pub struct WasiPreview1Adapter {/* all members private and only used inside this module. also, this struct should be Send. */}
impl WasiPreview1Adapter {
// This should be the only public interface of this struct:
// This should be the only public interface of this struct. It should take
// no parameters: anything it needs from the preview 2 implementation
// should be retrieved lazily.
pub fn new() -> Self {
todo!()
}
}
// Any context that needs to support preview 1 will impl this trait. They can
// construct the needed member with WasiPreview1Adapter::new().
pub trait WasiPreview1View: Send {
fn adapter(&self) -> &WasiPreview1Adapter;
fn adapter_mut(&mut self) -> &mut WasiPreview1Adapter;
}
// This becomes the only way to add preview 1 support to a wasmtime (module)
// Linker:
pub fn add_to_linker<
T: WasiPreview1View
+ wasi::environment::Host
+ wasi::exit::Host
+ wasi::filesystem::Host
+ wasi::monotonic_clock::Host
+ wasi::poll::Host
+ wasi::preopens::Host
+ wasi::random::Host
+ wasi::streams::Host
+ wasi::wall_clock::Host,
>(
linker: &mut wasmtime::Linker<T>,
) -> anyhow::Result<()> {
wasi_snapshot_preview1::add_to_linker(linker, |t| t)
}
// Generate the wasi_snapshot_preview1::WasiSnapshotPreview1 trait,
// and the module types.
// None of the generated modules, traits, or types should be used externally
// to this module.
wiggle::from_witx!({
witx: ["$CARGO_MANIFEST_DIR/witx/wasi_snapshot_preview1.witx"],
errors: { errno => trappable Error },
@ -29,11 +56,12 @@ impl wiggle::GuestErrorType for types::Errno {
}
}
// Implement the WasiSnapshotPreview1 trait using only the traits that are
// required for T, i.e., in terms of the preview 2 wit interface, and state
// stored in the WasiPreview1Adapter struct.
#[wiggle::async_trait]
impl<
T: WasiPreview1View
// Use only the following set of traits, and the
// WasiPreview1Adapter state, to implement all of these functions:
+ wasi::environment::Host
+ wasi::exit::Host
+ wasi::filesystem::Host

Loading…
Cancel
Save