Skip to content

Commit

Permalink
Provide WASI imports when invoking an explicit export from the CLI
Browse files Browse the repository at this point in the history
  • Loading branch information
Amanieu committed Nov 30, 2021
1 parent 277ab29 commit 57a8a09
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 34 deletions.
64 changes: 38 additions & 26 deletions lib/cli/src/commands/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,21 +94,6 @@ impl Run {

fn inner_execute(&self) -> Result<()> {
let module = self.get_module()?;
// Do we want to invoke a function?
if let Some(ref invoke) = self.invoke {
let imports = imports! {};
let instance = Instance::new(&module, &imports)?;
let result = self.invoke_function(&instance, &invoke, &self.args)?;
println!(
"{}",
result
.iter()
.map(|val| val.to_string())
.collect::<Vec<String>>()
.join(" ")
);
return Ok(());
}
#[cfg(feature = "emscripten")]
{
use wasmer_emscripten::{
Expand All @@ -117,6 +102,9 @@ impl Run {
};
// TODO: refactor this
if is_emscripten_module(&module) {
if self.invoke.is_some() {
bail!("--invoke is not supported with emscripten modules");
}
let mut emscripten_globals = EmscriptenGlobals::new(module.store(), &module)
.map_err(|e| anyhow!("{}", e))?;
let mut em_env = EmEnv::new(&emscripten_globals.data, Default::default());
Expand Down Expand Up @@ -154,7 +142,7 @@ impl Run {

// If WASI is enabled, try to execute it with it
#[cfg(feature = "wasi")]
{
let instance = {
use std::collections::BTreeSet;
use wasmer_wasi::WasiVersion;

Expand Down Expand Up @@ -187,21 +175,45 @@ impl Run {
.map(|f| f.to_string_lossy().to_string())
})
.unwrap_or_default();
return self
.wasi
.execute(module, program_name, self.args.clone())
.with_context(|| "WASI execution failed");
self.wasi
.instantiate(&module, program_name, self.args.clone())
.with_context(|| "failed to instantiate WASI module")?
}
// not WASI
_ => (),
_ => Instance::new(&module, &imports! {})?,
}
};
#[cfg(not(feature = "wasi"))]
let instance = Instance::new(&module, &imports! {})?;

// If this module exports an _initialize function, run that first.
if let Ok(initialize) = instance.exports.get_function("_initialize") {
initialize
.call(&[])
.with_context(|| "failed to run _initialize function")?;
}

// Try to instantiate the wasm file, with no provided imports
let imports = imports! {};
let instance = Instance::new(&module, &imports)?;
let start: Function = self.try_find_function(&instance, "_start", &[])?;
start.call(&[])?;
// Do we want to invoke a function?
if let Some(ref invoke) = self.invoke {
let imports = imports! {};
let instance = Instance::new(&module, &imports)?;
let result = self.invoke_function(&instance, &invoke, &self.args)?;
println!(
"{}",
result
.iter()
.map(|val| val.to_string())
.collect::<Vec<String>>()
.join(" ")
);
} else {
let start: Function = self.try_find_function(&instance, "_start", &[])?;
let result = start.call(&[]);
#[cfg(feature = "wasi")]
self.wasi.handle_result(result)?;
#[cfg(not(feature = "wasi"))]
result?;
}

Ok(())
}
Expand Down
21 changes: 13 additions & 8 deletions lib/cli/src/commands/run/wasi.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use crate::utils::{parse_envvar, parse_mapdir};
use anyhow::{Context, Result};
use anyhow::Result;
use std::collections::BTreeSet;
use std::path::PathBuf;
use wasmer::{Instance, Module};
use wasmer::{Instance, Module, RuntimeError, Val};
use wasmer_wasi::{get_wasi_versions, WasiError, WasiState, WasiVersion};

use structopt::StructOpt;
Expand Down Expand Up @@ -69,8 +69,13 @@ impl Wasi {
get_wasi_versions(&module, false).is_some()
}

/// Helper function for executing Wasi from the `Run` command.
pub fn execute(&self, module: Module, program_name: String, args: Vec<String>) -> Result<()> {
/// Helper function for instantiating a module with Wasi imports for the `Run` command.
pub fn instantiate(
&self,
module: &Module,
program_name: String,
args: Vec<String>,
) -> Result<Instance> {
let args = args.iter().cloned().map(|arg| arg.into_bytes());

let mut wasi_state_builder = WasiState::new(program_name);
Expand All @@ -91,10 +96,11 @@ impl Wasi {
let mut wasi_env = wasi_state_builder.finalize()?;
let resolver = wasi_env.import_object_for_all_wasi_versions(&module)?;
let instance = Instance::new(&module, &resolver)?;
Ok(instance)
}

let start = instance.exports.get_function("_start")?;
let result = start.call(&[]);

/// Helper function for handling the result of a Wasi _start function.
pub fn handle_result(&self, result: Result<Box<[Val]>, RuntimeError>) -> Result<()> {
match result {
Ok(_) => Ok(()),
Err(err) => {
Expand All @@ -109,7 +115,6 @@ impl Wasi {
Err(err)
}
}
.with_context(|| "failed to run WASI `_start` function")
}

pub fn for_binfmt_interpreter() -> Result<Self> {
Expand Down

0 comments on commit 57a8a09

Please sign in to comment.