From 76b445bcb85796e4e7dc59f7482e3411947a6303 Mon Sep 17 00:00:00 2001 From: Michael-F-Bryan Date: Wed, 1 Mar 2023 02:21:10 +0800 Subject: [PATCH] Miscellaneous refactoring and tidy-ups --- Cargo.lock | 4 +- lib/c-api/Cargo.toml | 41 ++++------ lib/cli/Cargo.toml | 117 ++++++++++++++++------------ lib/cli/src/commands/run.rs | 2 +- lib/registry/Cargo.toml | 10 ++- lib/vfs/Cargo.toml | 13 +++- lib/wasi/src/runners/container.rs | 7 +- lib/wasi/src/runners/emscripten.rs | 21 ++--- lib/wasi/src/runners/wasi.rs | 35 ++++----- lib/wasi/src/runners/wcgi/runner.rs | 93 ++++++++++++++++------ 10 files changed, 202 insertions(+), 141 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6c9cca2d533..b6eea25f00e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5672,9 +5672,9 @@ dependencies = [ [[package]] name = "webc" -version = "5.0.0-rc.2" +version = "5.0.0-rc.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43ce94053d470a17f057637d2006615b102a5816ce5863e20f47b929bb887dd6" +checksum = "d8de39792e7afaf4d5c202eecfb8bfdee775fcbbb808bf45d7c85ae6bae07053" dependencies = [ "anyhow", "base64 0.21.0", diff --git a/lib/c-api/Cargo.toml b/lib/c-api/Cargo.toml index 5544743c708..1fb8191cec7 100644 --- a/lib/c-api/Cargo.toml +++ b/lib/c-api/Cargo.toml @@ -16,22 +16,27 @@ edition = "2018" # `libwasmer.so`, `libwasmer.dylib`, `wasmer.dll` etc. But it creates # a conflict with the existing `wasmer` crate, see below. name = "wasmer" # ##lib.name## - # ^ DO NOT REMOVE, it's used the `Makefile`, see `build-docs-capi`. +# ^ DO NOT REMOVE, it's used the `Makefile`, see `build-docs-capi`. crate-type = ["staticlib", "cdylib"] #"cdylib", "rlib", "staticlib"] [dependencies] # We rename `wasmer` to `wasmer-api` to avoid the conflict with this # library name (see `[lib]`). -wasmer-api = { version = "=3.2.0-alpha.1", path = "../api", default-features = false, features = ["sys"], package = "wasmer" } +wasmer-api = { version = "=3.2.0-alpha.1", path = "../api", default-features = false, features = [ + "sys", +], package = "wasmer" } wasmer-compiler-cranelift = { version = "=3.2.0-alpha.1", path = "../compiler-cranelift", optional = true } wasmer-compiler-singlepass = { version = "=3.2.0-alpha.1", path = "../compiler-singlepass", optional = true } wasmer-compiler-llvm = { version = "=3.2.0-alpha.1", path = "../compiler-llvm", optional = true } wasmer-emscripten = { version = "=3.2.0-alpha.1", path = "../emscripten", optional = true } wasmer-compiler = { version = "=3.2.0-alpha.1", path = "../compiler" } wasmer-middlewares = { version = "=3.2.0-alpha.1", path = "../middlewares", optional = true } -wasmer-wasi = { version = "=3.2.0-alpha.1", path = "../wasi", features = ["host-fs", "host-vnet"], optional = true } +wasmer-wasi = { version = "=3.2.0-alpha.1", path = "../wasi", features = [ + "host-fs", + "host-vnet", +], optional = true } wasmer-types = { version = "=3.2.0-alpha.1", path = "../types" } -webc = { version = "5.0.0-rc.2", optional = true } +webc = { version = "5.0.0-rc.3", optional = true } enumset = "1.0.2" cfg-if = "1.0" lazy_static = "1.4" @@ -50,19 +55,10 @@ wasmer-inline-c = "0.1.1" inline-c = "0.1.7" [features] -default = [ - "wat", - "cranelift", - "compiler", - "wasi", - "middlewares", -] +default = ["wat", "cranelift", "compiler", "wasi", "middlewares"] wat = ["wasmer-api/wat"] wasi = ["wasmer-wasi"] -middlewares = [ - "compiler", - "wasmer-middlewares", -] +middlewares = ["compiler", "wasmer-middlewares"] compiler = [ "wasmer-api/compiler", "wasmer-compiler/translator", @@ -75,18 +71,9 @@ compiler-headless = [ "wasmer-compiler/translator", "wasmer-compiler/compiler", ] -singlepass = [ - "wasmer-compiler-singlepass", - "compiler", -] -cranelift = [ - "wasmer-compiler-cranelift", - "compiler", -] -llvm = [ - "wasmer-compiler-llvm", - "compiler", -] +singlepass = ["wasmer-compiler-singlepass", "compiler"] +cranelift = ["wasmer-compiler-cranelift", "compiler"] +llvm = ["wasmer-compiler-llvm", "compiler"] wasmer-artifact-load = ["wasmer-compiler/wasmer-artifact-load"] wasmer-artifact-create = ["wasmer-compiler/wasmer-artifact-create"] static-artifact-load = ["wasmer-compiler/static-artifact-load"] diff --git a/lib/cli/Cargo.toml b/lib/cli/Cargo.toml index a574ceff99c..09faa67c56f 100644 --- a/lib/cli/Cargo.toml +++ b/lib/cli/Cargo.toml @@ -26,22 +26,30 @@ required-features = ["headless"] [dependencies] wasmer = { version = "=3.2.0-alpha.1", path = "../api", default-features = false } -wasmer-compiler = { version = "=3.2.0-alpha.1", path = "../compiler", features = ["compiler", ] } +wasmer-compiler = { version = "=3.2.0-alpha.1", path = "../compiler", features = [ + "compiler", +] } wasmer-compiler-cranelift = { version = "=3.2.0-alpha.1", path = "../compiler-cranelift", optional = true } wasmer-compiler-singlepass = { version = "=3.2.0-alpha.1", path = "../compiler-singlepass", optional = true } wasmer-compiler-llvm = { version = "=3.2.0-alpha.1", path = "../compiler-llvm", optional = true } wasmer-emscripten = { version = "=3.2.0-alpha.1", path = "../emscripten", optional = true } wasmer-vm = { version = "=3.2.0-alpha.1", path = "../vm" } wasmer-wasi = { version = "=3.2.0-alpha.1", path = "../wasi", optional = true } -wasmer-wasi-experimental-io-devices = { version = "=3.2.0-alpha.1", path = "../wasi-experimental-io-devices", optional = true, features = ["link_external_libs"] } +wasmer-wasi-experimental-io-devices = { version = "=3.2.0-alpha.1", path = "../wasi-experimental-io-devices", optional = true, features = [ + "link_external_libs", +] } wasmer-wasi-local-networking = { version = "=3.2.0-alpha.1", path = "../wasi-local-networking", optional = true } wasmer-wast = { version = "=3.2.0-alpha.1", path = "../../tests/lib/wast", optional = true } wasmer-cache = { version = "=3.2.0-alpha.1", path = "../cache", optional = true } -wasmer-types = { version = "=3.2.0-alpha.1", path = "../types", features = ["enable-serde"] } +wasmer-types = { version = "=3.2.0-alpha.1", path = "../types", features = [ + "enable-serde", +] } wasmer-registry = { version = "=4.0.0", path = "../registry" } wasmer-object = { version = "=3.2.0-alpha.1", path = "../object", optional = true } -wasmer-vfs = { version = "=3.2.0-alpha.1", path = "../vfs", default-features = false, features = ["host-fs"] } -wasmer-vnet = { version = "=3.2.0-alpha.1", path = "../vnet" } +wasmer-vfs = { version = "=3.2.0-alpha.1", path = "../vfs", default-features = false, features = [ + "host-fs", +] } +wasmer-vnet = { version = "=3.2.0-alpha.1", path = "../vnet" } wasmer-wasm-interface = { version = "3.2.0-alpha.1", path = "../wasm-interface" } wasmparser = "0.51.4" atty = "0.2" @@ -58,8 +66,14 @@ cfg-if = "1.0" fern = { version = "0.6", features = ["colored"], optional = true } tempfile = "3" tempdir = "0.3.7" -http_req = { version="^0.8", default-features = false, features = ["rust-tls"] } -reqwest = { version = "^0.11", default-features = false, features = ["rustls-tls", "json", "multipart"] } +http_req = { version = "^0.8", default-features = false, features = [ + "rust-tls", +] } +reqwest = { version = "^0.11", default-features = false, features = [ + "rustls-tls", + "json", + "multipart", +] } serde = { version = "1.0.147", features = ["derive"] } dirs = { version = "4.0" } serde_json = { version = "1.0" } @@ -73,7 +87,7 @@ toml = "0.5.9" url = "2.3.1" libc = { version = "^0.2", default-features = false } nuke-dir = { version = "0.1.0", optional = true } -webc = { version = "5.0.0-rc.2", optional = true } +webc = { version = "5.0.0-rc.3", optional = true } isatty = "0.1.9" dialoguer = "0.10.2" tldextract = "0.6.0" @@ -83,7 +97,11 @@ cargo_metadata = "0.15.2" rusqlite = { version = "0.28.0", features = ["bundled"] } tar = "0.4.38" thiserror = "1.0.37" -time = { version = "0.3.17", default-features = false, features = ["parsing", "std", "formatting"] } +time = { version = "0.3.17", default-features = false, features = [ + "parsing", + "std", + "formatting", +] } log = "0.4.17" minisign = "0.7.2" semver = "1.0.14" @@ -94,7 +112,10 @@ object = "0.30.0" wasm-coredump-builder = { version = "0.1.11" } [build-dependencies] -chrono = { version = "^0.4", default-features = false, features = [ "std", "clock" ] } +chrono = { version = "^0.4", default-features = false, features = [ + "std", + "clock", +] } [target.'cfg(target_os = "linux")'.dependencies] unix_mode = "0.1.3" @@ -119,51 +140,51 @@ wast = ["wasmer-wast"] wasi = ["wasmer-wasi", "wasmer-wasi-local-networking"] emscripten = ["wasmer-emscripten"] wat = ["wasmer/wat"] -webc_runner = ["wasi", "wasmer-wasi/webc_runner", "wasmer-wasi/webc_runner_rt_wasi", "wasmer-wasi/webc_runner_rt_emscripten", "wasmer-wasi/webc_runner_rt_wcgi", "nuke-dir", "webc"] +webc_runner = [ + "wasi", + "wasmer-wasi/webc_runner", + "wasmer-wasi/webc_runner_rt_wasi", + "wasmer-wasi/webc_runner_rt_emscripten", + "wasmer-wasi/webc_runner_rt_wcgi", + "nuke-dir", + "webc", +] compiler = [ "wasmer-compiler/translator", "wasmer-compiler/compiler", - "wasmer-wasi/compiler" + "wasmer-wasi/compiler", ] -wasmer-artifact-create = ["compiler", - "wasmer/wasmer-artifact-load", - "wasmer/wasmer-artifact-create", - "wasmer-compiler/wasmer-artifact-load", - "wasmer-compiler/wasmer-artifact-create", - "wasmer-object", - ] -static-artifact-create = ["compiler", - "wasmer/static-artifact-load", - "wasmer/static-artifact-create", - "wasmer-compiler/static-artifact-load", - "wasmer-compiler/static-artifact-create", - "wasmer-object", - ] -wasmer-artifact-load = ["compiler", - "wasmer/wasmer-artifact-load", - "wasmer-compiler/wasmer-artifact-load", - ] -static-artifact-load = ["compiler", - "wasmer/static-artifact-load", - "wasmer-compiler/static-artifact-load", - ] - -experimental-io-devices = [ - "wasmer-wasi-experimental-io-devices", - "wasi" +wasmer-artifact-create = [ + "compiler", + "wasmer/wasmer-artifact-load", + "wasmer/wasmer-artifact-create", + "wasmer-compiler/wasmer-artifact-load", + "wasmer-compiler/wasmer-artifact-create", + "wasmer-object", ] -singlepass = [ - "wasmer-compiler-singlepass", +static-artifact-create = [ "compiler", + "wasmer/static-artifact-load", + "wasmer/static-artifact-create", + "wasmer-compiler/static-artifact-load", + "wasmer-compiler/static-artifact-create", + "wasmer-object", ] -cranelift = [ - "wasmer-compiler-cranelift", +wasmer-artifact-load = [ "compiler", + "wasmer/wasmer-artifact-load", + "wasmer-compiler/wasmer-artifact-load", ] -llvm = [ - "wasmer-compiler-llvm", +static-artifact-load = [ "compiler", + "wasmer/static-artifact-load", + "wasmer-compiler/static-artifact-load", ] + +experimental-io-devices = ["wasmer-wasi-experimental-io-devices", "wasi"] +singlepass = ["wasmer-compiler-singlepass", "compiler"] +cranelift = ["wasmer-compiler-cranelift", "compiler"] +llvm = ["wasmer-compiler-llvm", "compiler"] debug = ["fern", "wasmer-wasi/logging"] disable-all-logging = ["wasmer-wasi/disable-all-logging"] headless = [] @@ -171,10 +192,10 @@ headless-minimal = ["headless", "disable-all-logging", "wasi"] # Optional enable-serde = [ - "wasmer/enable-serde", - "wasmer-vm/enable-serde", - "wasmer-compiler/enable-serde", - "wasmer-wasi/enable-serde", + "wasmer/enable-serde", + "wasmer-vm/enable-serde", + "wasmer-compiler/enable-serde", + "wasmer-wasi/enable-serde", ] [target.'cfg(target_os = "windows")'.dependencies] diff --git a/lib/cli/src/commands/run.rs b/lib/cli/src/commands/run.rs index f918663bde7..165cc5df546 100644 --- a/lib/cli/src/commands/run.rs +++ b/lib/cli/src/commands/run.rs @@ -408,7 +408,7 @@ impl RunWithPathBuf { if runner.can_run_command(id, command).unwrap_or(false) { runner .run_cmd(&container, id) - .context("Emscripten runner failed")?; + .context("WCGI runner failed")?; } anyhow::bail!("No runner"); diff --git a/lib/registry/Cargo.toml b/lib/registry/Cargo.toml index 047f9e3b2db..90bc6433796 100644 --- a/lib/registry/Cargo.toml +++ b/lib/registry/Cargo.toml @@ -13,7 +13,13 @@ dirs = "4.0.0" graphql_client = "0.11.0" serde = { version = "1.0.145", features = ["derive"] } anyhow = "1.0.65" -reqwest = { version = "0.11.12", default-features = false, features = ["rustls-tls", "blocking", "multipart", "json", "stream"] } +reqwest = { version = "0.11.12", default-features = false, features = [ + "rustls-tls", + "blocking", + "multipart", + "json", + "stream", +] } futures-util = "0.3.25" whoami = "1.2.3" serde_json = "1.0.85" @@ -25,7 +31,7 @@ tar = "0.4.38" flate2 = "1.0.24" semver = "1.0.14" lzma-rs = "0.2.0" -webc = { version = "5.0.0-rc.2", features = ["mmap"] } +webc = { version = "5.0.0-rc.3", features = ["mmap"] } hex = "0.4.3" tokio = "1.24.0" tempdir = "0.3.7" diff --git a/lib/vfs/Cargo.toml b/lib/vfs/Cargo.toml index 491db8e1faa..a486eea9680 100644 --- a/lib/vfs/Cargo.toml +++ b/lib/vfs/Cargo.toml @@ -11,7 +11,7 @@ libc = { version = "^0.2", default-features = false, optional = true } thiserror = "1" tracing = { version = "0.1" } typetag = { version = "0.1", optional = true } -webc = { version = "5.0.0-rc.2", optional = true } +webc = { version = "5.0.0-rc.3", optional = true } slab = { version = "0.4" } derivative = "2.2.0" anyhow = { version = "1.0.66", optional = true } @@ -20,12 +20,19 @@ lazy_static = "1.4" fs_extra = { version = "1.2.0", optional = true } filetime = { version = "0.2.18", optional = true } bytes = "1" -tokio = { version = "1", features = [ "io-util", "sync", "macros" ], default_features = false } +tokio = { version = "1", features = [ + "io-util", + "sync", + "macros", +], default_features = false } pin-project-lite = "0.2.9" indexmap = "1.9.2" [dev-dependencies] -tokio = { version = "1", features = [ "io-util", "rt" ], default_features = false } +tokio = { version = "1", features = [ + "io-util", + "rt", +], default_features = false } [features] default = ["host-fs", "webc-fs", "static-fs"] diff --git a/lib/wasi/src/runners/container.rs b/lib/wasi/src/runners/container.rs index a80a4351e24..b5ab831343f 100644 --- a/lib/wasi/src/runners/container.rs +++ b/lib/wasi/src/runners/container.rs @@ -8,7 +8,7 @@ use webc::{ Version, }; -/// Parsed WAPM file, memory-mapped to an on-disk path +/// A parsed WAPM package. #[derive(Debug, Clone)] pub struct WapmContainer { repr: Repr, @@ -89,8 +89,9 @@ impl WapmContainer { // HACK(Michael-F-Bryan): WapmContainer originally exposed its Arc // field, so every man and his dog accessed it directly instead of going // through the WapmContainer abstraction. This is an escape hatch to make - // that code w - pub fn v1(&self) -> &WebC<'_> { + // that code keep working for the time being. + // #[deprecated] + pub(crate) fn v1(&self) -> &WebC<'_> { match &self.repr { Repr::V1Mmap(mapped) => &*mapped, Repr::V1Owned(owned) => &*owned, diff --git a/lib/wasi/src/runners/emscripten.rs b/lib/wasi/src/runners/emscripten.rs index bd8a6e9777c..af2a5276656 100644 --- a/lib/wasi/src/runners/emscripten.rs +++ b/lib/wasi/src/runners/emscripten.rs @@ -1,14 +1,14 @@ //! WebC container support for running Emscripten modules use crate::runners::WapmContainer; -use anyhow::{anyhow, Error}; +use anyhow::{anyhow, Context, Error}; use serde::{Deserialize, Serialize}; use wasmer::{FunctionEnv, Instance, Module, Store}; use wasmer_emscripten::{ generate_emscripten_env, is_emscripten_module, run_emscripten_instance, EmEnv, EmscriptenGlobals, }; -use webc::metadata::Command; +use webc::metadata::{annotations::Emscripten, Command}; #[derive(Debug, PartialEq, Serialize, Deserialize)] pub struct EmscriptenRunner { @@ -56,17 +56,18 @@ impl crate::runners::Runner for EmscriptenRunner { fn run_command( &mut self, command_name: &str, - _command: &Command, + command: &Command, container: &WapmContainer, ) -> Result { - let container = container.v1(); - let atom_name = container - .get_atom_name_for_command("emscripten", command_name) - .map_err(Error::msg)?; - let main_args = container.get_main_args_for_command(command_name); + let Emscripten { + atom: atom_name, + main_args, + .. + } = command.get_annotation("emscripten")?.unwrap_or_default(); + let atom_name = atom_name.context("The atom name is required")?; let atom_bytes = container - .get_atom(&container.get_package_name(), &atom_name) - .map_err(Error::msg)?; + .get_atom(&atom_name) + .with_context(|| format!("Unable to read the \"{atom_name}\" atom"))?; let mut module = Module::new(&self.store, atom_bytes)?; module.set_name(&atom_name); diff --git a/lib/wasi/src/runners/wasi.rs b/lib/wasi/src/runners/wasi.rs index 66c3b99d7e5..d337fad09a9 100644 --- a/lib/wasi/src/runners/wasi.rs +++ b/lib/wasi/src/runners/wasi.rs @@ -4,10 +4,10 @@ use std::sync::Arc; use crate::{runners::WapmContainer, PluggableRuntimeImplementation, VirtualTaskManager}; use crate::{WasiEnv, WasiEnvBuilder}; -use anyhow::Error; +use anyhow::{Context, Error}; use serde::{Deserialize, Serialize}; use wasmer::{Module, Store}; -use webc::metadata::Command; +use webc::metadata::{annotations::Wasi, Command}; #[derive(Debug, Serialize, Deserialize)] pub struct WasiRunner { @@ -61,20 +61,22 @@ impl crate::runners::Runner for WasiRunner { Ok(command.runner.starts_with("https://webc.org/runner/wasi")) } - #[allow(unreachable_code, unused_variables)] fn run_command( &mut self, - command_name: &str, - _command: &Command, + _command_name: &str, + command: &Command, container: &WapmContainer, ) -> Result { - let webc = container.v1(); - let atom_name = webc - .get_atom_name_for_command("wasi", command_name) - .map_err(Error::msg)?; - let atom_bytes = webc.get_atom(&webc.get_package_name(), &atom_name)?; - - let mut module = Module::new(&self.store, atom_bytes)?; + let Wasi { + atom: atom_name, .. + } = command + .get_annotation("wasi")? + .context("The command doesn't have any WASI annotations")?; + let atom = container + .get_atom(&atom_name) + .with_context(|| format!("Unable to get the \"{atom_name}\" atom"))?; + + let mut module = Module::new(&self.store, atom)?; module.set_name(&atom_name); let mut builder = prepare_webc_env(container, &atom_name, &self.args)?; @@ -84,14 +86,7 @@ impl crate::runners::Runner for WasiRunner { builder.set_runtime(Arc::new(rt)); } - let init = builder.build_init()?; - - let (instance, env) = WasiEnv::instantiate(init, module, &mut self.store)?; - - let _result = instance - .exports - .get_function("_start")? - .call(&mut self.store, &[])?; + builder.run(module)?; Ok(()) } diff --git a/lib/wasi/src/runners/wcgi/runner.rs b/lib/wasi/src/runners/wcgi/runner.rs index b5da3c7cc66..0a6abc21695 100644 --- a/lib/wasi/src/runners/wcgi/runner.rs +++ b/lib/wasi/src/runners/wcgi/runner.rs @@ -5,7 +5,10 @@ use futures::future::AbortHandle; use wasmer::{Engine, Module, Store}; use wasmer_vfs::FileSystem; use wcgi_host::CgiDialect; -use webc::metadata::{annotations::Wcgi, Command, Manifest}; +use webc::metadata::{ + annotations::{Wasi, Wcgi}, + Command, Manifest, +}; use crate::{ runners::{ @@ -30,9 +33,17 @@ impl WcgiRunner { #[tracing::instrument(skip(self, ctx))] fn run_(&mut self, command_name: &str, ctx: &RunnerContext<'_>) -> Result<(), Error> { - let module = self.load_module(ctx).context("Couldn't load the module")?; + let wasi: Wasi = ctx + .command() + .get_annotation("wasi") + .context("Unable to retrieve the WASI metadata")? + .context("The command doesn't have any WASI annotations")?; + + let module = self + .load_module(&wasi, ctx) + .context("Couldn't load the module")?; - let handler = self.create_handler(module, ctx)?; + let handler = self.create_handler(module, &wasi, ctx)?; let task_manager = Arc::clone(&handler.task_manager); let make_service = hyper::service::make_service_fn(move |_| { @@ -56,6 +67,7 @@ impl WcgiRunner { .serve(make_service) .with_graceful_shutdown(async { let _ = shutdown.await; + tracing::info!("Shutting down gracefully"); }) .await }) @@ -77,15 +89,7 @@ impl WcgiRunner { &mut self.config } - fn load_module(&self, ctx: &RunnerContext<'_>) -> Result { - let wasi: webc::metadata::annotations::Wasi = ctx - .command() - .annotations - .get("wasi") - .cloned() - .and_then(|v| serde_cbor::value::from_value(v).ok()) - .context("Unable to retrieve the WASI metadata")?; - + fn load_module(&self, wasi: &Wasi, ctx: &RunnerContext<'_>) -> Result { let atom_name = &wasi.atom; let atom = ctx .get_atom(&atom_name) @@ -96,19 +100,16 @@ impl WcgiRunner { Ok(module) } - fn create_handler(&self, module: Module, ctx: &RunnerContext<'_>) -> Result { - let mut env = HashMap::new(); - - if self.config.forward_host_env { - env.extend(std::env::vars()); - } - - env.extend(self.config.env.clone()); + fn create_handler( + &self, + module: Module, + wasi: &Wasi, + ctx: &RunnerContext<'_>, + ) -> Result { + let env = construct_env(wasi, self.config.forward_host_env, &self.config.env); + let args = construct_args(wasi, &self.config.args); - let Wcgi { dialect, .. } = match ctx.command().annotations.get("wcgi") { - Some(v) => serde_cbor::value::from_value(v.clone())?, - None => Wcgi::default(), - }; + let Wcgi { dialect, .. } = ctx.command().get_annotation("wcgi")?.unwrap_or_default(); let dialect = match dialect { Some(d) => d.parse().context("Unable to parse the CGI dialect")?, @@ -118,7 +119,7 @@ impl WcgiRunner { let handler = Handler { program: Arc::clone(&self.program_name), env: Arc::new(env), - args: self.config.args.clone().into(), + args, mapped_dirs: self.config.mapped_dirs.clone().into(), task_manager: self .config @@ -134,6 +135,48 @@ impl WcgiRunner { } } +fn construct_args(wasi: &Wasi, extras: &[String]) -> Arc<[String]> { + let mut args = Vec::new(); + + if let Some(main_args) = &wasi.main_args { + args.extend(main_args.iter().cloned()); + } + + args.extend(extras.iter().cloned()); + + args.into() +} + +fn construct_env( + wasi: &Wasi, + forward_host_env: bool, + overrides: &HashMap, +) -> HashMap { + let mut env: HashMap = HashMap::new(); + + for item in wasi.env.as_deref().unwrap_or_default() { + // TODO(Michael-F-Bryan): Convert "wasi.env" in the webc crate from an + // Option> to a HashMap so we avoid this + // string.split() business + match item.split_once('=') { + Some((k, v)) => { + env.insert(k.to_string(), v.to_string()); + } + None => { + env.insert(item.to_string(), String::new()); + } + } + } + + if forward_host_env { + env.extend(std::env::vars()); + } + + env.extend(overrides.clone()); + + env +} + // TODO(Michael-F-Bryan): Pass this to Runner::run() as "&dyn RunnerContext" // when we rewrite the "Runner" trait. struct RunnerContext<'a> {