The API breaking changes from future WASIX/Network/Threading addition

This commit is contained in:
ptitSeb
2022-08-26 10:46:56 +02:00
parent cfd49c2688
commit 1912373e1f
16 changed files with 197 additions and 62 deletions

1
Cargo.lock generated
View File

@@ -2923,6 +2923,7 @@ name = "wasmer"
version = "3.0.0-beta" version = "3.0.0-beta"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"bytes",
"cfg-if 1.0.0", "cfg-if 1.0.0",
"hashbrown 0.11.2", "hashbrown 0.11.2",
"indexmap", "indexmap",

View File

@@ -195,14 +195,13 @@ import_object.define("env", "host_function", host_function);
let instance = Instance::new(&mut store, &module, &import_object).expect("Could not instantiate module."); let instance = Instance::new(&mut store, &module, &import_object).expect("Could not instantiate module.");
``` ```
For WASI, don't forget to import memory to `WasiEnv` For WASI, don't forget to initialize the `WasiEnv` (it will import the memory)
```rust ```rust
let mut wasi_env = WasiState::new("hello").finalize()?; let mut wasi_env = WasiState::new("hello").finalize()?;
let import_object = wasi_env.import_object(&mut store, &module)?; let import_object = wasi_env.import_object(&mut store, &module)?;
let instance = Instance::new(&mut store, &module, &import_object).expect("Could not instantiate module."); let instance = Instance::new(&mut store, &module, &import_object).expect("Could not instantiate module.");
let memory = instance.exports.get_memory("memory")?; wasi_env.initialize(&mut store, &instance).unwrap();
wasi_env.data_mut(&mut store).set_memory(memory.clone());
``` ```
#### `ChainableNamedResolver` is removed #### `ChainableNamedResolver` is removed

View File

@@ -26,6 +26,7 @@ indexmap = { version = "1.6" }
cfg-if = "1.0" cfg-if = "1.0"
thiserror = "1.0" thiserror = "1.0"
more-asserts = "0.2" more-asserts = "0.2"
bytes = "1"
# - Optional shared dependencies. # - Optional shared dependencies.
wat = { version = "1.0", optional = true } wat = { version = "1.0", optional = true }
tracing = { version = "0.1", optional = true } tracing = { version = "0.1", optional = true }

View File

@@ -9,7 +9,9 @@ use crate::js::store::{AsStoreMut, StoreHandle};
use crate::js::types::{AsJs, ExportType, ImportType}; use crate::js::types::{AsJs, ExportType, ImportType};
use crate::js::RuntimeError; use crate::js::RuntimeError;
use crate::AsStoreRef; use crate::AsStoreRef;
use bytes::Bytes;
use js_sys::{Reflect, Uint8Array, WebAssembly}; use js_sys::{Reflect, Uint8Array, WebAssembly};
use std::borrow::Cow;
use std::fmt; use std::fmt;
use std::io; use std::io;
use std::path::Path; use std::path::Path;
@@ -49,6 +51,46 @@ pub struct ModuleTypeHints {
pub exports: Vec<ExternType>, pub exports: Vec<ExternType>,
} }
pub trait IntoBytes {
fn into_bytes(self) -> Bytes;
}
impl IntoBytes for Bytes {
fn into_bytes(self) -> Bytes {
self
}
}
impl IntoBytes for Vec<u8> {
fn into_bytes(self) -> Bytes {
Bytes::from(self)
}
}
impl IntoBytes for &[u8] {
fn into_bytes(self) -> Bytes {
Bytes::from(self.to_vec())
}
}
impl<const N: usize> IntoBytes for &[u8; N] {
fn into_bytes(self) -> Bytes {
Bytes::from(self.to_vec())
}
}
impl IntoBytes for &str {
fn into_bytes(self) -> Bytes {
Bytes::from(self.as_bytes().to_vec())
}
}
impl IntoBytes for Cow<'_, [u8]> {
fn into_bytes(self) -> Bytes {
Bytes::from(self.to_vec())
}
}
/// A WebAssembly Module contains stateless WebAssembly /// A WebAssembly Module contains stateless WebAssembly
/// code that has already been compiled and can be instantiated /// code that has already been compiled and can be instantiated
/// multiple times. /// multiple times.
@@ -128,15 +170,19 @@ impl Module {
/// # } /// # }
/// ``` /// ```
#[allow(unreachable_code)] #[allow(unreachable_code)]
pub fn new(_store: &impl AsStoreRef, bytes: impl AsRef<[u8]>) -> Result<Self, CompileError> { pub fn new(_store: &impl AsStoreRef, bytes: impl IntoBytes) -> Result<Self, CompileError> {
let mut bytes = bytes.into_bytes();
#[cfg(feature = "wat")] #[cfg(feature = "wat")]
let bytes = wat::parse_bytes(bytes.as_ref()).map_err(|e| { if bytes.starts_with(b"\0asm") == false {
CompileError::Wasm(WasmError::Generic(format!( let parsed_bytes = wat::parse_bytes(bytes.as_ref()).map_err(|e| {
"Error when converting wat: {}", CompileError::Wasm(WasmError::Generic(format!(
e "Error when converting wat: {}",
))) e
})?; )))
Self::from_binary(_store, bytes.as_ref()) })?;
bytes = Bytes::from(parsed_bytes.to_vec());
}
Self::from_binary(_store, bytes)
} }
/// Creates a new WebAssembly module from a file path. /// Creates a new WebAssembly module from a file path.
@@ -152,7 +198,11 @@ impl Module {
/// Opposed to [`Module::new`], this function is not compatible with /// Opposed to [`Module::new`], this function is not compatible with
/// the WebAssembly text format (if the "wat" feature is enabled for /// the WebAssembly text format (if the "wat" feature is enabled for
/// this crate). /// this crate).
pub fn from_binary(_store: &impl AsStoreRef, binary: &[u8]) -> Result<Self, CompileError> { pub fn from_binary(
_store: &impl AsStoreRef,
binary: impl IntoBytes,
) -> Result<Self, CompileError> {
let binary = binary.into_bytes();
// //
// Self::validate(store, binary)?; // Self::validate(store, binary)?;
unsafe { Self::from_binary_unchecked(_store, binary) } unsafe { Self::from_binary_unchecked(_store, binary) }
@@ -166,9 +216,10 @@ impl Module {
/// We maintain the `unsafe` to preserve the same API as Wasmer /// We maintain the `unsafe` to preserve the same API as Wasmer
pub unsafe fn from_binary_unchecked( pub unsafe fn from_binary_unchecked(
_store: &impl AsStoreRef, _store: &impl AsStoreRef,
binary: &[u8], binary: impl IntoBytes,
) -> Result<Self, CompileError> { ) -> Result<Self, CompileError> {
let js_bytes = Uint8Array::view(binary); let binary = binary.into_bytes();
let js_bytes = Uint8Array::view(&binary[..]);
let module = WebAssembly::Module::new(&js_bytes.into()).unwrap(); let module = WebAssembly::Module::new(&js_bytes.into()).unwrap();
// The module is now validated, so we can safely parse it's types // The module is now validated, so we can safely parse it's types
@@ -210,8 +261,9 @@ impl Module {
/// This validation is normally pretty fast and checks the enabled /// This validation is normally pretty fast and checks the enabled
/// WebAssembly features in the Store Engine to assure deterministic /// WebAssembly features in the Store Engine to assure deterministic
/// validation of the Module. /// validation of the Module.
pub fn validate(_store: &impl AsStoreRef, binary: &[u8]) -> Result<(), CompileError> { pub fn validate(_store: &impl AsStoreRef, binary: impl IntoBytes) -> Result<(), CompileError> {
let js_bytes = unsafe { Uint8Array::view(binary) }; let binary = binary.into_bytes();
let js_bytes = unsafe { Uint8Array::view(&binary[..]) };
match WebAssembly::validate(&js_bytes.into()) { match WebAssembly::validate(&js_bytes.into()) {
Ok(true) => Ok(()), Ok(true) => Ok(()),
_ => Err(CompileError::Validate("Invalid Wasm file".to_owned())), _ => Err(CompileError::Validate("Invalid Wasm file".to_owned())),
@@ -313,8 +365,9 @@ impl Module {
#[cfg(feature = "js-serializable-module")] #[cfg(feature = "js-serializable-module")]
pub unsafe fn deserialize( pub unsafe fn deserialize(
_store: &impl AsStoreRef, _store: &impl AsStoreRef,
bytes: &[u8], bytes: impl IntoBytes,
) -> Result<Self, DeserializeError> { ) -> Result<Self, DeserializeError> {
let bytes = bytes.into_bytes();
Self::new(_store, bytes).map_err(|e| DeserializeError::Compiler(e)) Self::new(_store, bytes).map_err(|e| DeserializeError::Compiler(e))
} }

View File

@@ -71,7 +71,7 @@ impl<T, M: MemorySize> WasmPtr<T, M> {
/// Get the offset into Wasm linear memory for this `WasmPtr`. /// Get the offset into Wasm linear memory for this `WasmPtr`.
#[inline] #[inline]
pub fn offset(self) -> M::Offset { pub fn offset(&self) -> M::Offset {
self.offset self.offset
} }

View File

@@ -55,7 +55,7 @@
//! "#; //! "#;
//! //!
//! let mut store = Store::default(); //! let mut store = Store::default();
//! let module = Module::new(&store, &module_wat)?; //! let module = Module::new(&store, module_wat)?;
//! // The module doesn't import anything, so we create an empty import object. //! // The module doesn't import anything, so we create an empty import object.
//! let import_object = imports! {}; //! let import_object = imports! {};
//! let instance = Instance::new(&mut store, &module, &import_object)?; //! let instance = Instance::new(&mut store, &module, &import_object)?;

View File

@@ -29,7 +29,7 @@ impl<T> FunctionEnv<T> {
} }
/// Get the data as reference /// Get the data as reference
pub fn as_ref<'a>(&self, store: &'a impl AsStoreMut) -> &'a T pub fn as_ref<'a>(&self, store: &'a impl AsStoreRef) -> &'a T
where where
T: Any + Send + 'static + Sized, T: Any + Send + 'static + Sized,
{ {
@@ -105,6 +105,11 @@ impl<T: Send + 'static> FunctionEnvMut<'_, T> {
self.func_env.as_mut(&mut self.store_mut) self.func_env.as_mut(&mut self.store_mut)
} }
/// Borrows a new immmutable reference
pub fn as_ref(&self) -> FunctionEnv<T> {
self.func_env.clone()
}
/// Borrows a new mutable reference /// Borrows a new mutable reference
pub fn as_mut(&mut self) -> FunctionEnvMut<'_, T> { pub fn as_mut(&mut self) -> FunctionEnvMut<'_, T> {
FunctionEnvMut { FunctionEnvMut {

View File

@@ -1,6 +1,8 @@
use crate::sys::InstantiationError; use crate::sys::InstantiationError;
use crate::AsStoreMut; use crate::AsStoreMut;
use crate::AsStoreRef; use crate::AsStoreRef;
use bytes::Bytes;
use std::borrow::Cow;
use std::fmt; use std::fmt;
use std::io; use std::io;
use std::path::Path; use std::path::Path;
@@ -54,6 +56,46 @@ pub struct Module {
module_info: Arc<ModuleInfo>, module_info: Arc<ModuleInfo>,
} }
pub trait IntoBytes {
fn into_bytes(self) -> Bytes;
}
impl IntoBytes for Bytes {
fn into_bytes(self) -> Bytes {
self
}
}
impl IntoBytes for Vec<u8> {
fn into_bytes(self) -> Bytes {
Bytes::from(self)
}
}
impl IntoBytes for &[u8] {
fn into_bytes(self) -> Bytes {
Bytes::from(self.to_vec())
}
}
impl<const N: usize> IntoBytes for &[u8; N] {
fn into_bytes(self) -> Bytes {
Bytes::from(self.to_vec())
}
}
impl IntoBytes for &str {
fn into_bytes(self) -> Bytes {
Bytes::from(self.as_bytes().to_vec())
}
}
impl IntoBytes for Cow<'_, [u8]> {
fn into_bytes(self) -> Bytes {
Bytes::from(self.to_vec())
}
}
impl Module { impl Module {
#[cfg(feature = "compiler")] #[cfg(feature = "compiler")]
/// Creates a new WebAssembly Module given the configuration /// Creates a new WebAssembly Module given the configuration
@@ -116,16 +158,19 @@ impl Module {
/// # } /// # }
/// ``` /// ```
#[allow(unreachable_code)] #[allow(unreachable_code)]
pub fn new(store: &impl AsStoreRef, bytes: impl AsRef<[u8]>) -> Result<Self, CompileError> { pub fn new(store: &impl AsStoreRef, bytes: impl IntoBytes) -> Result<Self, CompileError> {
let mut bytes = bytes.into_bytes();
#[cfg(feature = "wat")] #[cfg(feature = "wat")]
let bytes = wat::parse_bytes(bytes.as_ref()).map_err(|e| { if !bytes.starts_with(b"\0asm") {
CompileError::Wasm(WasmError::Generic(format!( let parsed_bytes = wat::parse_bytes(&bytes[..]).map_err(|e| {
"Error when converting wat: {}", CompileError::Wasm(WasmError::Generic(format!(
e "Error when converting wat: {}",
))) e
})?; )))
})?;
Self::from_binary(store, bytes.as_ref()) bytes = Bytes::from(parsed_bytes.to_vec());
}
Self::from_binary(store, bytes)
} }
#[cfg(feature = "compiler")] #[cfg(feature = "compiler")]
@@ -137,7 +182,7 @@ impl Module {
let file_ref = file.as_ref(); let file_ref = file.as_ref();
let canonical = file_ref.canonicalize()?; let canonical = file_ref.canonicalize()?;
let wasm_bytes = std::fs::read(file_ref)?; let wasm_bytes = std::fs::read(file_ref)?;
let mut module = Self::new(store, &wasm_bytes)?; let mut module = Self::new(store, wasm_bytes)?;
// Set the module name to the absolute path of the filename. // Set the module name to the absolute path of the filename.
// This is useful for debugging the stack traces. // This is useful for debugging the stack traces.
let filename = canonical.as_path().to_str().unwrap(); let filename = canonical.as_path().to_str().unwrap();
@@ -151,8 +196,12 @@ impl Module {
/// Opposed to [`Module::new`], this function is not compatible with /// Opposed to [`Module::new`], this function is not compatible with
/// the WebAssembly text format (if the "wat" feature is enabled for /// the WebAssembly text format (if the "wat" feature is enabled for
/// this crate). /// this crate).
pub fn from_binary(store: &impl AsStoreRef, binary: &[u8]) -> Result<Self, CompileError> { pub fn from_binary(
Self::validate(store, binary)?; store: &impl AsStoreRef,
binary: impl IntoBytes,
) -> Result<Self, CompileError> {
let binary = binary.into_bytes();
Self::validate(store, binary.clone())?;
unsafe { Self::from_binary_unchecked(store, binary) } unsafe { Self::from_binary_unchecked(store, binary) }
} }
@@ -166,8 +215,9 @@ impl Module {
/// beforehand. /// beforehand.
pub unsafe fn from_binary_unchecked( pub unsafe fn from_binary_unchecked(
store: &impl AsStoreRef, store: &impl AsStoreRef,
binary: &[u8], binary: impl IntoBytes,
) -> Result<Self, CompileError> { ) -> Result<Self, CompileError> {
let binary = binary.into_bytes();
let module = Self::compile(store, binary)?; let module = Self::compile(store, binary)?;
Ok(module) Ok(module)
} }
@@ -179,16 +229,18 @@ impl Module {
/// This validation is normally pretty fast and checks the enabled /// This validation is normally pretty fast and checks the enabled
/// WebAssembly features in the Store Engine to assure deterministic /// WebAssembly features in the Store Engine to assure deterministic
/// validation of the Module. /// validation of the Module.
pub fn validate(store: &impl AsStoreRef, binary: &[u8]) -> Result<(), CompileError> { pub fn validate(store: &impl AsStoreRef, binary: impl IntoBytes) -> Result<(), CompileError> {
store.as_store_ref().engine().validate(binary) let binary = binary.into_bytes();
store.as_store_ref().engine().validate(&binary[..])
} }
#[cfg(feature = "compiler")] #[cfg(feature = "compiler")]
fn compile(store: &impl AsStoreRef, binary: &[u8]) -> Result<Self, CompileError> { fn compile(store: &impl AsStoreRef, binary: impl IntoBytes) -> Result<Self, CompileError> {
let binary = binary.into_bytes();
let artifact = store let artifact = store
.as_store_ref() .as_store_ref()
.engine() .engine()
.compile(binary, store.as_store_ref().tunables())?; .compile(&binary[..], store.as_store_ref().tunables())?;
Ok(Self::from_artifact(artifact)) Ok(Self::from_artifact(artifact))
} }

View File

@@ -76,7 +76,7 @@ impl<T, M: MemorySize> WasmPtr<T, M> {
/// Get the offset into Wasm linear memory for this `WasmPtr`. /// Get the offset into Wasm linear memory for this `WasmPtr`.
#[inline] #[inline]
pub fn offset(self) -> M::Offset { pub fn offset(&self) -> M::Offset {
self.offset self.offset
} }

View File

@@ -25,16 +25,11 @@ impl Inspect {
fn inner_execute(&self) -> Result<()> { fn inner_execute(&self) -> Result<()> {
let (store, _compiler_type) = self.store.get_store()?; let (store, _compiler_type) = self.store.get_store()?;
let module_contents = std::fs::read(&self.path)?; let module_contents = std::fs::read(&self.path)?;
let module = Module::new(&store, &module_contents)?; let iswasm = is_wasm(&module_contents);
println!( let module_len = module_contents.len();
"Type: {}", let module = Module::new(&store, module_contents)?;
if !is_wasm(&module_contents) { println!("Type: {}", if !iswasm { "wat" } else { "wasm" });
"wat" println!("Size: {}", ByteSize(module_len as _));
} else {
"wasm"
}
);
println!("Size: {}", ByteSize(module_contents.len() as _));
println!("Imports:"); println!("Imports:");
println!(" Functions:"); println!(" Functions:");
for f in module.imports().functions() { for f in module.imports().functions() {

View File

@@ -272,7 +272,7 @@ impl Run {
let module_result: Result<Module> = if !self.disable_cache && contents.len() > 0x1000 { let module_result: Result<Module> = if !self.disable_cache && contents.len() > 0x1000 {
self.get_module_from_cache(&store, &contents, &compiler_type) self.get_module_from_cache(&store, &contents, &compiler_type)
} else { } else {
Module::new(&store, &contents).map_err(|e| e.into()) Module::new(&store, contents).map_err(|e| e.into())
}; };
#[cfg(not(feature = "cache"))] #[cfg(not(feature = "cache"))]
let module_result = Module::new(&store, &contents); let module_result = Module::new(&store, &contents);
@@ -319,7 +319,7 @@ impl Run {
warning!("cached module is corrupted: {}", err); warning!("cached module is corrupted: {}", err);
} }
} }
let module = Module::new(store, &contents)?; let module = Module::new(store, contents)?;
// Store the compiled Module in cache // Store the compiled Module in cache
cache.store(hash, &module)?; cache.store(hash, &module)?;
Ok(module) Ok(module)

View File

@@ -27,7 +27,7 @@ impl Validate {
if !is_wasm(&module_contents) { if !is_wasm(&module_contents) {
bail!("`wasmer validate` only validates WebAssembly files"); bail!("`wasmer validate` only validates WebAssembly files");
} }
Module::validate(&store, &module_contents)?; Module::validate(&store, module_contents)?;
eprintln!("Validation passed for `{}`.", self.path.display()); eprintln!("Validation passed for `{}`.", self.path.display());
Ok(()) Ok(())
} }

View File

@@ -62,9 +62,11 @@ use wasmer_wasi_types::__WASI_CLOCK_MONOTONIC;
use derivative::*; use derivative::*;
use std::ops::Deref; use std::ops::Deref;
use thiserror::Error; use thiserror::Error;
use tracing::trace;
use wasmer::{ use wasmer::{
imports, namespace, AsStoreMut, AsStoreRef, Exports, Function, FunctionEnv, Imports, Memory, imports, namespace, AsStoreMut, AsStoreRef, ExportError, Exports, Function, FunctionEnv,
Memory32, MemoryAccessError, MemorySize, MemoryView, Module, TypedFunction, Imports, Instance, Memory, Memory32, MemoryAccessError, MemorySize, MemoryView, Module,
TypedFunction,
}; };
pub use runtime::{ pub use runtime::{
@@ -166,6 +168,33 @@ impl WasiFunctionEnv {
self.env.as_mut(store) self.env.as_mut(store)
} }
/// Initializes the WasiEnv using the instance exports
/// (this must be executed before attempting to use it)
/// (as the stores can not by themselves be passed between threads we can store the module
/// in a thread-local variables and use it later - for multithreading)
pub fn initialize(
&mut self,
store: &mut impl AsStoreMut,
instance: &Instance,
) -> Result<(), ExportError> {
// List all the exports and imports
for ns in instance.module().exports() {
//trace!("module::export - {} ({:?})", ns.name(), ns.ty());
trace!("module::export - {}", ns.name());
}
for ns in instance.module().imports() {
trace!("module::import - {}::{}", ns.module(), ns.name());
}
// First we get the malloc function which if it exists will be used to
// create the pthread_self structure
let memory = instance.exports.get_memory("memory")?.clone();
let env = self.data_mut(store);
env.set_memory(memory);
Ok(())
}
/// Like `import_object` but containing all the WASI versions detected in /// Like `import_object` but containing all the WASI versions detected in
/// the module. /// the module.
pub fn import_object_for_all_wasi_versions( pub fn import_object_for_all_wasi_versions(

View File

@@ -40,7 +40,7 @@ fn get_module(store: &Store) -> Result<Module> {
(start $foo) (start $foo)
"#; "#;
let module = Module::new(store, &wat)?; let module = Module::new(store, wat)?;
Ok(module) Ok(module)
} }
@@ -339,7 +339,7 @@ fn static_function_that_fails(config: crate::Config) -> Result<()> {
(start $foo) (start $foo)
"#; "#;
let module = Module::new(&store, &wat)?; let module = Module::new(&store, wat)?;
let f0 = Function::new_typed(&mut store, || -> Result<Infallible, RuntimeError> { let f0 = Function::new_typed(&mut store, || -> Result<Infallible, RuntimeError> {
Err(RuntimeError::new("oops")) Err(RuntimeError::new("oops"))
}); });
@@ -375,7 +375,7 @@ fn get_module2(store: &Store) -> Result<Module> {
(call 0)) (call 0))
"#; "#;
let module = Module::new(store, &wat)?; let module = Module::new(store, wat)?;
Ok(module) Ok(module)
} }

View File

@@ -262,7 +262,7 @@ fn trap_start_function_import(config: crate::Config) -> Result<()> {
) )
"#; "#;
let module = Module::new(&store, &binary)?; let module = Module::new(&store, binary)?;
let sig = FunctionType::new(vec![], vec![]); let sig = FunctionType::new(vec![], vec![]);
let func = Function::new(&mut store, &sig, |_| Err(RuntimeError::new("user trap"))); let func = Function::new(&mut store, &sig, |_| Err(RuntimeError::new("user trap")));
let err = Instance::new( let err = Instance::new(
@@ -302,7 +302,7 @@ fn rust_panic_import(config: crate::Config) -> Result<()> {
) )
"#; "#;
let module = Module::new(&store, &binary)?; let module = Module::new(&store, binary)?;
let sig = FunctionType::new(vec![], vec![]); let sig = FunctionType::new(vec![], vec![]);
let func = Function::new(&mut store, &sig, |_| panic!("this is a panic")); let func = Function::new(&mut store, &sig, |_| panic!("this is a panic"));
let f0 = Function::new_typed(&mut store, || panic!("this is another panic")); let f0 = Function::new_typed(&mut store, || panic!("this is another panic"));
@@ -347,7 +347,7 @@ fn rust_panic_start_function(config: crate::Config) -> Result<()> {
) )
"#; "#;
let module = Module::new(&store, &binary)?; let module = Module::new(&store, binary)?;
let sig = FunctionType::new(vec![], vec![]); let sig = FunctionType::new(vec![], vec![]);
let func = Function::new(&mut store, &sig, |_| panic!("this is a panic")); let func = Function::new(&mut store, &sig, |_| panic!("this is a panic"));
let err = panic::catch_unwind(AssertUnwindSafe(|| { let err = panic::catch_unwind(AssertUnwindSafe(|| {
@@ -393,7 +393,7 @@ fn mismatched_arguments(config: crate::Config) -> Result<()> {
) )
"#; "#;
let module = Module::new(&store, &binary)?; let module = Module::new(&store, binary)?;
let instance = Instance::new(&mut store, &module, &imports! {})?; let instance = Instance::new(&mut store, &module, &imports! {})?;
let func: &Function = instance.exports.get("foo")?; let func: &Function = instance.exports.get("foo")?;
assert_eq!( assert_eq!(
@@ -432,7 +432,7 @@ fn call_signature_mismatch(config: crate::Config) -> Result<()> {
) )
"#; "#;
let module = Module::new(&store, &binary)?; let module = Module::new(&store, binary)?;
let err = Instance::new(&mut store, &module, &imports! {}) let err = Instance::new(&mut store, &module, &imports! {})
.err() .err()
.expect("expected error"); .expect("expected error");

View File

@@ -82,7 +82,7 @@ impl<'a> WasiTest<'a> {
wasm_module.read_to_end(&mut out)?; wasm_module.read_to_end(&mut out)?;
out out
}; };
let module = Module::new(store, &wasm_bytes)?; let module = Module::new(store, wasm_bytes)?;
let (env, _tempdirs, stdout_rx, stderr_rx) = let (env, _tempdirs, stdout_rx, stderr_rx) =
self.create_wasi_env(store, filesystem_kind)?; self.create_wasi_env(store, filesystem_kind)?;
let imports = self.get_imports(store, &env.env, &module)?; let imports = self.get_imports(store, &env.env, &module)?;