Skip to content

Commit

Permalink
Merge #2290
Browse files Browse the repository at this point in the history
2290: Handle Wasm modules with no imports in the CLI r=MarkMcCaskey a=MarkMcCaskey

Resolves #2282 

Co-authored-by: Mark McCaskey <[email protected]>
  • Loading branch information
bors[bot] and Mark McCaskey authored May 4, 2021
2 parents 240e5dc + 5d41f99 commit 46024fb
Show file tree
Hide file tree
Showing 7 changed files with 107 additions and 43 deletions.
62 changes: 33 additions & 29 deletions lib/cli/src/commands/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,37 +156,41 @@ impl Run {
use wasmer_wasi::WasiVersion;

let wasi_versions = Wasi::get_versions(&module);
if let Some(wasi_versions) = wasi_versions {
if wasi_versions.len() >= 2 {
let get_version_list = |versions: &BTreeSet<WasiVersion>| -> String {
versions
.iter()
.map(|v| format!("`{}`", v.get_namespace_str()))
.collect::<Vec<String>>()
.join(", ")
};
if self.wasi.deny_multiple_wasi_versions {
let version_list = get_version_list(&wasi_versions);
bail!("Found more than 1 WASI version in this module ({}) and `--deny-multiple-wasi-versions` is enabled.", version_list);
} else if !self.wasi.allow_multiple_wasi_versions {
let version_list = get_version_list(&wasi_versions);
warning!("Found more than 1 WASI version in this module ({}). If this is intentional, pass `--allow-multiple-wasi-versions` to suppress this warning.", version_list);
match wasi_versions {
Some(wasi_versions) if !wasi_versions.is_empty() => {
if wasi_versions.len() >= 2 {
let get_version_list = |versions: &BTreeSet<WasiVersion>| -> String {
versions
.iter()
.map(|v| format!("`{}`", v.get_namespace_str()))
.collect::<Vec<String>>()
.join(", ")
};
if self.wasi.deny_multiple_wasi_versions {
let version_list = get_version_list(&wasi_versions);
bail!("Found more than 1 WASI version in this module ({}) and `--deny-multiple-wasi-versions` is enabled.", version_list);
} else if !self.wasi.allow_multiple_wasi_versions {
let version_list = get_version_list(&wasi_versions);
warning!("Found more than 1 WASI version in this module ({}). If this is intentional, pass `--allow-multiple-wasi-versions` to suppress this warning.", version_list);
}
}
}

let program_name = self
.command_name
.clone()
.or_else(|| {
self.path
.file_name()
.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");
let program_name = self
.command_name
.clone()
.or_else(|| {
self.path
.file_name()
.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");
}
// not WASI
_ => (),
}
}

Expand Down
9 changes: 8 additions & 1 deletion lib/engine/src/resolver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,14 @@ impl NamedResolver for Box<dyn NamedResolver> {
}
}

/// `Resolver` implementation that always resolves to `None`.
impl NamedResolver for () {
/// Always returns `None`.
fn resolve_by_name(&self, _module: &str, _field: &str) -> Option<Export> {
None
}
}

/// `Resolver` implementation that always resolves to `None`. Equivalent to `()`.
pub struct NullResolver {}

impl Resolver for NullResolver {
Expand Down
13 changes: 3 additions & 10 deletions lib/wasi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,16 +88,9 @@ impl WasiEnv {
) -> Result<Box<dyn NamedResolver>, WasiError> {
let wasi_versions =
get_wasi_versions(module, false).ok_or(WasiError::UnknownWasiVersion)?;
let mut version_iter = wasi_versions.iter();
let mut resolver: Box<dyn NamedResolver> = {
let version = version_iter.next().ok_or(WasiError::UnknownWasiVersion)?;
Box::new(generate_import_object_from_env(
module.store(),
self.clone(),
*version,
))
};
for version in version_iter {

let mut resolver: Box<dyn NamedResolver> = { Box::new(()) };
for version in wasi_versions.iter() {
let new_import_object =
generate_import_object_from_env(module.store(), self.clone(), *version);
resolver = Box::new(new_import_object.chain_front(resolver));
Expand Down
3 changes: 2 additions & 1 deletion tests/integration/cli/src/assets.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use std::env;
use std::path::PathBuf;

pub const ASSET_PATH: &str = concat!(
pub const C_ASSET_PATH: &str = concat!(
env!("CARGO_MANIFEST_DIR"),
"/../../../lib/c-api/tests/assets"
);
pub const ASSET_PATH: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/../../../tests/examples");

pub const WASMER_INCLUDE_PATH: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/../../../lib/c-api");

Expand Down
2 changes: 1 addition & 1 deletion tests/integration/cli/tests/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const OBJECT_FILE_ENGINE_TEST_C_SOURCE: &[u8] =
include_bytes!("object_file_engine_test_c_source.c");

fn object_file_engine_test_wasm_path() -> String {
format!("{}/{}", ASSET_PATH, "qjs.wasm")
format!("{}/{}", C_ASSET_PATH, "qjs.wasm")
}

/// Data used to run the `wasmer compile` command.
Expand Down
2 changes: 1 addition & 1 deletion tests/integration/cli/tests/create_exe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use std::process::Command;
use wasmer_integration_tests_cli::*;

fn create_exe_test_wasm_path() -> String {
format!("{}/{}", ASSET_PATH, "qjs.wasm")
format!("{}/{}", C_ASSET_PATH, "qjs.wasm")
}
const JS_TEST_SRC_CODE: &[u8] =
b"function greet(name) { return JSON.stringify('Hello, ' + name); }; print(greet('World'));\n";
Expand Down
59 changes: 59 additions & 0 deletions tests/integration/cli/tests/run.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
//! Basic tests for the `run` subcommand
use anyhow::bail;
use std::process::Command;
use wasmer_integration_tests_cli::{ASSET_PATH, C_ASSET_PATH, WASMER_PATH};

fn wasi_test_wasm_path() -> String {
format!("{}/{}", C_ASSET_PATH, "qjs.wasm")
}

fn test_no_imports_wat_path() -> String {
format!("{}/{}", ASSET_PATH, "fib.wat")
}

#[test]
fn run_wasi_works() -> anyhow::Result<()> {
let output = Command::new(WASMER_PATH)
.arg("run")
.arg(wasi_test_wasm_path())
.arg("--")
.arg("-e")
.arg("print(3 * (4 + 5))")
.output()?;

if !output.status.success() {
bail!(
"linking failed with: stdout: {}\n\nstderr: {}",
std::str::from_utf8(&output.stdout)
.expect("stdout is not utf8! need to handle arbitrary bytes"),
std::str::from_utf8(&output.stderr)
.expect("stderr is not utf8! need to handle arbitrary bytes")
);
}

let stdout_output = std::str::from_utf8(&output.stdout).unwrap();
assert_eq!(stdout_output, "27\n");

Ok(())
}

#[test]
fn run_no_imports_wasm_works() -> anyhow::Result<()> {
let output = Command::new(WASMER_PATH)
.arg("run")
.arg(test_no_imports_wat_path())
.output()?;

if !output.status.success() {
bail!(
"linking failed with: stdout: {}\n\nstderr: {}",
std::str::from_utf8(&output.stdout)
.expect("stdout is not utf8! need to handle arbitrary bytes"),
std::str::from_utf8(&output.stderr)
.expect("stderr is not utf8! need to handle arbitrary bytes")
);
}

Ok(())
}

0 comments on commit 46024fb

Please sign in to comment.