mirror of
https://github.com/mii443/wasmer.git
synced 2025-12-10 14:48:27 +00:00
Merge branch 'master' into fix-sync-js-sys-api
This commit is contained in:
8
Cargo.lock
generated
8
Cargo.lock
generated
@@ -3220,11 +3220,7 @@ dependencies = [
|
||||
name = "wasmer-vbus"
|
||||
version = "3.0.0-beta"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"slab",
|
||||
"thiserror",
|
||||
"tracing",
|
||||
"typetag",
|
||||
"wasmer-vfs",
|
||||
]
|
||||
|
||||
@@ -3268,11 +3264,7 @@ name = "wasmer-vnet"
|
||||
version = "3.0.0-beta"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"libc",
|
||||
"slab",
|
||||
"thiserror",
|
||||
"tracing",
|
||||
"typetag",
|
||||
"wasmer-vfs",
|
||||
]
|
||||
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
//! The import module contains the implementation data structures and helper functions used to
|
||||
//! manipulate and access a wasm module's imports including memories, tables, globals, and
|
||||
//! functions.
|
||||
use crate::js::error::LinkError;
|
||||
use crate::js::error::{InstantiationError, LinkError, WasmError};
|
||||
use crate::js::export::Export;
|
||||
use crate::js::exports::Exports;
|
||||
use crate::js::module::Module;
|
||||
use crate::js::store::AsStoreRef;
|
||||
use crate::js::store::{AsStoreMut, AsStoreRef};
|
||||
use crate::js::types::AsJs;
|
||||
use crate::js::ExternType;
|
||||
use crate::Extern;
|
||||
use std::collections::HashMap;
|
||||
use std::fmt;
|
||||
@@ -179,6 +181,80 @@ impl Imports {
|
||||
pub fn iter<'a>(&'a self) -> ImportsIterator<'a> {
|
||||
ImportsIterator::new(self)
|
||||
}
|
||||
|
||||
/// Create a new `Imports` from a JS Object, it receives a reference to a `Module` to
|
||||
/// map and assign the types of each import and the JS Object
|
||||
/// that contains the values of imports.
|
||||
///
|
||||
/// # Usage
|
||||
/// ```ignore
|
||||
/// let import_object = Imports::new_from_js_object(&mut store, &module, js_object);
|
||||
/// ```
|
||||
pub fn new_from_js_object(
|
||||
store: &mut impl AsStoreMut,
|
||||
module: &Module,
|
||||
object: js_sys::Object,
|
||||
) -> Result<Self, WasmError> {
|
||||
let module_imports: HashMap<(String, String), ExternType> = module
|
||||
.imports()
|
||||
.map(|import| {
|
||||
(
|
||||
(import.module().to_string(), import.name().to_string()),
|
||||
import.ty().clone(),
|
||||
)
|
||||
})
|
||||
.collect::<HashMap<(String, String), ExternType>>();
|
||||
|
||||
let mut map: HashMap<(String, String), Extern> = HashMap::new();
|
||||
|
||||
for module_entry in js_sys::Object::entries(&object).iter() {
|
||||
let module_entry: js_sys::Array = module_entry.into();
|
||||
let module_name = module_entry.get(0).as_string().unwrap().to_string();
|
||||
let module_import_object: js_sys::Object = module_entry.get(1).into();
|
||||
for import_entry in js_sys::Object::entries(&module_import_object).iter() {
|
||||
let import_entry: js_sys::Array = import_entry.into();
|
||||
let import_name = import_entry.get(0).as_string().unwrap().to_string();
|
||||
let import_js: wasm_bindgen::JsValue = import_entry.get(1);
|
||||
let key = (module_name.clone(), import_name);
|
||||
let extern_type = module_imports.get(&key).unwrap();
|
||||
let export = Export::from_js_value(import_js, store, extern_type.clone())?;
|
||||
let extern_ = Extern::from_vm_extern(store, export);
|
||||
map.insert(key, extern_);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Self { map })
|
||||
}
|
||||
}
|
||||
|
||||
impl AsJs for Imports {
|
||||
fn as_jsvalue(&self, store: &impl AsStoreRef) -> wasm_bindgen::JsValue {
|
||||
let imports_object = js_sys::Object::new();
|
||||
for (namespace, name, extern_) in self.iter() {
|
||||
let val = js_sys::Reflect::get(&imports_object, &namespace.into()).unwrap();
|
||||
if !val.is_undefined() {
|
||||
// If the namespace is already set
|
||||
js_sys::Reflect::set(
|
||||
&val,
|
||||
&name.into(),
|
||||
&extern_.as_jsvalue(&store.as_store_ref()),
|
||||
)
|
||||
.unwrap();
|
||||
} else {
|
||||
// If the namespace doesn't exist
|
||||
let import_namespace = js_sys::Object::new();
|
||||
js_sys::Reflect::set(
|
||||
&import_namespace,
|
||||
&name.into(),
|
||||
&extern_.as_jsvalue(&store.as_store_ref()),
|
||||
)
|
||||
.unwrap();
|
||||
js_sys::Reflect::set(&imports_object, &namespace.into(), &import_namespace.into())
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
imports_object.into()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ImportsIterator<'a> {
|
||||
@@ -317,89 +393,18 @@ macro_rules! import_namespace {
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::js::exports::Exportable;
|
||||
use crate::js::Type;
|
||||
use crate::js::{Global, Store, Val};
|
||||
use crate::js::{Global, Store, Value};
|
||||
|
||||
use crate::js::export::Export;
|
||||
// use wasm_bindgen::*;
|
||||
use wasm_bindgen_test::*;
|
||||
fn namespace() {
|
||||
let mut store = Store::default();
|
||||
let g1 = Global::new(&store, Val::I32(0));
|
||||
let namespace = namespace! {
|
||||
"happy" => g1
|
||||
};
|
||||
let imports1 = imports! {
|
||||
"dog" => namespace
|
||||
};
|
||||
|
||||
let happy_dog_entry = imports1.get_export("dog", "happy").unwrap();
|
||||
|
||||
assert!(
|
||||
if let Export::Global(happy_dog_global) = happy_dog_entry.to_export() {
|
||||
happy_dog_global.ty.ty == Type::I32
|
||||
} else {
|
||||
false
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
fn imports_macro_allows_trailing_comma_and_none() {
|
||||
use crate::js::Function;
|
||||
|
||||
let mut store = Default::default();
|
||||
|
||||
fn func(arg: i32) -> i32 {
|
||||
arg + 1
|
||||
}
|
||||
|
||||
let _ = imports! {
|
||||
"env" => {
|
||||
"func" => Function::new_typed(&store, func),
|
||||
},
|
||||
};
|
||||
let _ = imports! {
|
||||
"env" => {
|
||||
"func" => Function::new_typed(&store, func),
|
||||
}
|
||||
};
|
||||
let _ = imports! {
|
||||
"env" => {
|
||||
"func" => Function::new_typed(&store, func),
|
||||
},
|
||||
"abc" => {
|
||||
"def" => Function::new_typed(&store, func),
|
||||
}
|
||||
};
|
||||
let _ = imports! {
|
||||
"env" => {
|
||||
"func" => Function::new_typed(&store, func)
|
||||
},
|
||||
};
|
||||
let _ = imports! {
|
||||
"env" => {
|
||||
"func" => Function::new_typed(&store, func)
|
||||
}
|
||||
};
|
||||
let _ = imports! {
|
||||
"env" => {
|
||||
"func1" => Function::new_typed(&store, func),
|
||||
"func2" => Function::new_typed(&store, func)
|
||||
}
|
||||
};
|
||||
let _ = imports! {
|
||||
"env" => {
|
||||
"func1" => Function::new_typed(&store, func),
|
||||
"func2" => Function::new_typed(&store, func),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[wasm_bindgen_test]
|
||||
fn chaining_works() {
|
||||
let mut store = Store::default();
|
||||
let g = Global::new(&store, Val::I32(0));
|
||||
|
||||
let g = Global::new(&mut store, Value::I32(0));
|
||||
|
||||
let mut imports1 = imports! {
|
||||
"dog" => {
|
||||
@@ -412,7 +417,7 @@ mod test {
|
||||
"small" => g.clone()
|
||||
},
|
||||
"cat" => {
|
||||
"small" => g.clone()
|
||||
"small" => g
|
||||
}
|
||||
};
|
||||
|
||||
@@ -426,62 +431,162 @@ mod test {
|
||||
assert!(happy.is_some());
|
||||
assert!(small.is_some());
|
||||
}
|
||||
// fn namespace() {
|
||||
// let mut store = Store::default();
|
||||
// let g1 = Global::new(&store, Val::I32(0));
|
||||
// let namespace = namespace! {
|
||||
// "happy" => g1
|
||||
// };
|
||||
// let imports1 = imports! {
|
||||
// "dog" => namespace
|
||||
// };
|
||||
|
||||
fn extending_conflict_overwrites() {
|
||||
let mut store = Store::default();
|
||||
let g1 = Global::new(&store, Val::I32(0));
|
||||
let g2 = Global::new(&store, Val::F32(0.));
|
||||
// let happy_dog_entry = imports1.get_export("dog", "happy").unwrap();
|
||||
|
||||
let mut imports1 = imports! {
|
||||
"dog" => {
|
||||
"happy" => g1,
|
||||
},
|
||||
};
|
||||
// assert!(
|
||||
// if let Export::Global(happy_dog_global) = happy_dog_entry.to_export() {
|
||||
// happy_dog_global.ty.ty == Type::I32
|
||||
// } else {
|
||||
// false
|
||||
// }
|
||||
// );
|
||||
// }
|
||||
|
||||
let imports2 = imports! {
|
||||
"dog" => {
|
||||
"happy" => g2,
|
||||
},
|
||||
};
|
||||
// fn imports_macro_allows_trailing_comma_and_none() {
|
||||
// use crate::js::Function;
|
||||
|
||||
imports1.extend(&imports2);
|
||||
let happy_dog_entry = imports1.get_export("dog", "happy").unwrap();
|
||||
// let mut store = Default::default();
|
||||
|
||||
assert!(
|
||||
if let Export::Global(happy_dog_global) = happy_dog_entry.to_export() {
|
||||
happy_dog_global.ty.ty == Type::F32
|
||||
} else {
|
||||
false
|
||||
}
|
||||
);
|
||||
// fn func(arg: i32) -> i32 {
|
||||
// arg + 1
|
||||
// }
|
||||
|
||||
// now test it in reverse
|
||||
let mut store = Store::default();
|
||||
let g1 = Global::new(&store, Val::I32(0));
|
||||
let g2 = Global::new(&store, Val::F32(0.));
|
||||
// let _ = imports! {
|
||||
// "env" => {
|
||||
// "func" => Function::new_typed(&store, func),
|
||||
// },
|
||||
// };
|
||||
// let _ = imports! {
|
||||
// "env" => {
|
||||
// "func" => Function::new_typed(&store, func),
|
||||
// }
|
||||
// };
|
||||
// let _ = imports! {
|
||||
// "env" => {
|
||||
// "func" => Function::new_typed(&store, func),
|
||||
// },
|
||||
// "abc" => {
|
||||
// "def" => Function::new_typed(&store, func),
|
||||
// }
|
||||
// };
|
||||
// let _ = imports! {
|
||||
// "env" => {
|
||||
// "func" => Function::new_typed(&store, func)
|
||||
// },
|
||||
// };
|
||||
// let _ = imports! {
|
||||
// "env" => {
|
||||
// "func" => Function::new_typed(&store, func)
|
||||
// }
|
||||
// };
|
||||
// let _ = imports! {
|
||||
// "env" => {
|
||||
// "func1" => Function::new_typed(&store, func),
|
||||
// "func2" => Function::new_typed(&store, func)
|
||||
// }
|
||||
// };
|
||||
// let _ = imports! {
|
||||
// "env" => {
|
||||
// "func1" => Function::new_typed(&store, func),
|
||||
// "func2" => Function::new_typed(&store, func),
|
||||
// }
|
||||
// };
|
||||
// }
|
||||
|
||||
let imports1 = imports! {
|
||||
"dog" => {
|
||||
"happy" => g1,
|
||||
},
|
||||
};
|
||||
// fn chaining_works() {
|
||||
// let mut store = Store::default();
|
||||
// let g = Global::new(&store, Val::I32(0));
|
||||
|
||||
let mut imports2 = imports! {
|
||||
"dog" => {
|
||||
"happy" => g2,
|
||||
},
|
||||
};
|
||||
// let mut imports1 = imports! {
|
||||
// "dog" => {
|
||||
// "happy" => g.clone()
|
||||
// }
|
||||
// };
|
||||
|
||||
imports2.extend(&imports1);
|
||||
let happy_dog_entry = imports2.get_export("dog", "happy").unwrap();
|
||||
// let imports2 = imports! {
|
||||
// "dog" => {
|
||||
// "small" => g.clone()
|
||||
// },
|
||||
// "cat" => {
|
||||
// "small" => g.clone()
|
||||
// }
|
||||
// };
|
||||
|
||||
assert!(
|
||||
if let Export::Global(happy_dog_global) = happy_dog_entry.to_export() {
|
||||
happy_dog_global.ty.ty == Type::I32
|
||||
} else {
|
||||
false
|
||||
}
|
||||
);
|
||||
}
|
||||
// imports1.extend(&imports2);
|
||||
|
||||
// let small_cat_export = imports1.get_export("cat", "small");
|
||||
// assert!(small_cat_export.is_some());
|
||||
|
||||
// let happy = imports1.get_export("dog", "happy");
|
||||
// let small = imports1.get_export("dog", "small");
|
||||
// assert!(happy.is_some());
|
||||
// assert!(small.is_some());
|
||||
// }
|
||||
|
||||
// fn extending_conflict_overwrites() {
|
||||
// let mut store = Store::default();
|
||||
// let g1 = Global::new(&store, Val::I32(0));
|
||||
// let g2 = Global::new(&store, Val::F32(0.));
|
||||
|
||||
// let mut imports1 = imports! {
|
||||
// "dog" => {
|
||||
// "happy" => g1,
|
||||
// },
|
||||
// };
|
||||
|
||||
// let imports2 = imports! {
|
||||
// "dog" => {
|
||||
// "happy" => g2,
|
||||
// },
|
||||
// };
|
||||
|
||||
// imports1.extend(&imports2);
|
||||
// let happy_dog_entry = imports1.get_export("dog", "happy").unwrap();
|
||||
|
||||
// assert!(
|
||||
// if let Export::Global(happy_dog_global) = happy_dog_entry.to_export() {
|
||||
// happy_dog_global.ty.ty == Type::F32
|
||||
// } else {
|
||||
// false
|
||||
// }
|
||||
// );
|
||||
|
||||
// // now test it in reverse
|
||||
// let mut store = Store::default();
|
||||
// let g1 = Global::new(&store, Val::I32(0));
|
||||
// let g2 = Global::new(&store, Val::F32(0.));
|
||||
|
||||
// let imports1 = imports! {
|
||||
// "dog" => {
|
||||
// "happy" => g1,
|
||||
// },
|
||||
// };
|
||||
|
||||
// let mut imports2 = imports! {
|
||||
// "dog" => {
|
||||
// "happy" => g2,
|
||||
// },
|
||||
// };
|
||||
|
||||
// imports2.extend(&imports1);
|
||||
// let happy_dog_entry = imports2.get_export("dog", "happy").unwrap();
|
||||
|
||||
// assert!(
|
||||
// if let Export::Global(happy_dog_global) = happy_dog_entry.to_export() {
|
||||
// happy_dog_global.ty.ty == Type::I32
|
||||
// } else {
|
||||
// false
|
||||
// }
|
||||
// );
|
||||
// }
|
||||
}
|
||||
*/
|
||||
|
||||
@@ -20,8 +20,6 @@ use std::fmt;
|
||||
pub struct Instance {
|
||||
_handle: StoreHandle<WebAssembly::Instance>,
|
||||
module: Module,
|
||||
#[allow(dead_code)]
|
||||
imports: Imports,
|
||||
/// The exports for an instance.
|
||||
pub exports: Exports,
|
||||
}
|
||||
@@ -65,12 +63,11 @@ impl Instance {
|
||||
module: &Module,
|
||||
imports: &Imports,
|
||||
) -> Result<Self, InstantiationError> {
|
||||
let import_copy = imports.clone();
|
||||
let (instance, _imports): (StoreHandle<WebAssembly::Instance>, Vec<Extern>) = module
|
||||
let instance: WebAssembly::Instance = module
|
||||
.instantiate(&mut store, imports)
|
||||
.map_err(|e| InstantiationError::Start(e))?;
|
||||
|
||||
let self_instance = Self::from_module_and_instance(store, module, instance, import_copy)?;
|
||||
let self_instance = Self::from_module_and_instance(store, module, instance)?;
|
||||
//self_instance.init_envs(&imports.iter().map(Extern::to_export).collect::<Vec<_>>())?;
|
||||
Ok(self_instance)
|
||||
}
|
||||
@@ -109,8 +106,7 @@ impl Instance {
|
||||
pub fn from_module_and_instance(
|
||||
mut store: &mut impl AsStoreMut,
|
||||
module: &Module,
|
||||
instance: StoreHandle<WebAssembly::Instance>,
|
||||
imports: Imports,
|
||||
instance: WebAssembly::Instance,
|
||||
) -> Result<Self, InstantiationError> {
|
||||
use crate::js::externals::VMExtern;
|
||||
let instance_exports = instance.get(store.as_store_ref().objects()).exports();
|
||||
@@ -127,11 +123,10 @@ impl Instance {
|
||||
Ok((name.to_string(), extern_))
|
||||
})
|
||||
.collect::<Result<Exports, InstantiationError>>()?;
|
||||
|
||||
let handle = StoreHandle::new(store.as_store_mut().objects_mut(), instance);
|
||||
Ok(Self {
|
||||
_handle: instance,
|
||||
_handle: handle,
|
||||
module: module.clone(),
|
||||
imports,
|
||||
exports,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
use crate::js::error::WasmError;
|
||||
use crate::js::store::AsStoreMut;
|
||||
use crate::js::{Export, ExternType, Module};
|
||||
use std::collections::HashMap;
|
||||
|
||||
/// This struct is used in case you want to create an `Instance`
|
||||
/// of a `Module` with imports that are provided directly from
|
||||
/// Javascript with a JS Object.
|
||||
#[derive(Clone, Default)]
|
||||
pub struct JsImportObject {
|
||||
module_imports: HashMap<(String, String), ExternType>,
|
||||
object: js_sys::Object,
|
||||
}
|
||||
|
||||
/// JS Objects with wasm-bindgen are not currently Send/Sync (although they
|
||||
/// are in Javascript, since we can use them safely between webworkers).
|
||||
unsafe impl Send for JsImportObject {}
|
||||
unsafe impl Sync for JsImportObject {}
|
||||
|
||||
impl JsImportObject {
|
||||
/// Create a new `JsImportObject`, it receives a reference to a `Module` to
|
||||
/// map and assign the types of each import and the JS Object
|
||||
/// that contains the values of imports.
|
||||
///
|
||||
/// # Usage
|
||||
/// ```ignore
|
||||
/// # use wasmer::JsImportObject;
|
||||
/// let import_object = JsImportObject::new(&module, js_object);
|
||||
/// ```
|
||||
pub fn new(module: &Module, object: js_sys::Object) -> Self {
|
||||
let module_imports = module
|
||||
.imports()
|
||||
.map(|import| {
|
||||
(
|
||||
(import.module().to_string(), import.name().to_string()),
|
||||
import.ty().clone(),
|
||||
)
|
||||
})
|
||||
.collect::<HashMap<(String, String), ExternType>>();
|
||||
Self {
|
||||
module_imports,
|
||||
object,
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets an export given a module and a name
|
||||
///
|
||||
/// # Usage
|
||||
/// ```ignore
|
||||
/// # use wasmer::JsImportObject;
|
||||
/// let import_object = JsImportObject::new(&module, js_object);
|
||||
/// import_object.get_export("module", "name");
|
||||
/// ```
|
||||
pub fn get_export(
|
||||
&self,
|
||||
store: &mut impl AsStoreMut,
|
||||
module: &str,
|
||||
name: &str,
|
||||
) -> Result<Export, WasmError> {
|
||||
let namespace = js_sys::Reflect::get(&self.object, &module.into())?;
|
||||
let js_export = js_sys::Reflect::get(&namespace, &name.into())?;
|
||||
match self
|
||||
.module_imports
|
||||
.get(&(module.to_string(), name.to_string()))
|
||||
{
|
||||
Some(extern_type) => Ok(Export::from_js_value(
|
||||
js_export,
|
||||
store,
|
||||
extern_type.clone(),
|
||||
)?),
|
||||
None => Err(WasmError::Generic(format!(
|
||||
"Name {} not found in module {}",
|
||||
name, module
|
||||
))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<js_sys::Object> for JsImportObject {
|
||||
fn into(self) -> js_sys::Object {
|
||||
self.object
|
||||
}
|
||||
}
|
||||
@@ -30,7 +30,6 @@ mod externals;
|
||||
mod function_env;
|
||||
mod imports;
|
||||
mod instance;
|
||||
mod js_import_object;
|
||||
mod mem_access;
|
||||
mod module;
|
||||
#[cfg(feature = "wasm-types-polyfill")]
|
||||
@@ -54,7 +53,6 @@ pub use crate::js::externals::{
|
||||
pub use crate::js::function_env::{FunctionEnv, FunctionEnvMut};
|
||||
pub use crate::js::imports::Imports;
|
||||
pub use crate::js::instance::Instance;
|
||||
pub use crate::js::js_import_object::JsImportObject;
|
||||
pub use crate::js::mem_access::{MemoryAccessError, WasmRef, WasmSlice, WasmSliceIter};
|
||||
pub use crate::js::module::{Module, ModuleTypeHints};
|
||||
pub use crate::js::native::TypedFunction;
|
||||
|
||||
@@ -3,9 +3,8 @@ use crate::js::error::WasmError;
|
||||
use crate::js::error::{CompileError, InstantiationError};
|
||||
#[cfg(feature = "js-serializable-module")]
|
||||
use crate::js::error::{DeserializeError, SerializeError};
|
||||
use crate::js::externals::Extern;
|
||||
use crate::js::imports::Imports;
|
||||
use crate::js::store::{AsStoreMut, StoreHandle};
|
||||
use crate::js::store::AsStoreMut;
|
||||
use crate::js::types::{AsJs, ExportType, ImportType};
|
||||
use crate::js::RuntimeError;
|
||||
use crate::AsStoreRef;
|
||||
@@ -222,7 +221,7 @@ impl Module {
|
||||
&self,
|
||||
store: &mut impl AsStoreMut,
|
||||
imports: &Imports,
|
||||
) -> Result<(StoreHandle<WebAssembly::Instance>, Vec<Extern>), RuntimeError> {
|
||||
) -> Result<WebAssembly::Instance, RuntimeError> {
|
||||
// Ensure all imports come from the same store.
|
||||
if imports
|
||||
.into_iter()
|
||||
@@ -232,46 +231,10 @@ impl Module {
|
||||
InstantiationError::DifferentStores,
|
||||
)));
|
||||
}
|
||||
let imports_object = js_sys::Object::new();
|
||||
let mut import_externs: Vec<Extern> = vec![];
|
||||
for import_type in self.imports() {
|
||||
let resolved_import = imports.get_export(import_type.module(), import_type.name());
|
||||
if let Some(import) = resolved_import {
|
||||
let val = js_sys::Reflect::get(&imports_object, &import_type.module().into())?;
|
||||
if !val.is_undefined() {
|
||||
// If the namespace is already set
|
||||
js_sys::Reflect::set(
|
||||
&val,
|
||||
&import_type.name().into(),
|
||||
&import.as_jsvalue(&store.as_store_ref()),
|
||||
)?;
|
||||
} else {
|
||||
// If the namespace doesn't exist
|
||||
let import_namespace = js_sys::Object::new();
|
||||
js_sys::Reflect::set(
|
||||
&import_namespace,
|
||||
&import_type.name().into(),
|
||||
&import.as_jsvalue(&store.as_store_ref()),
|
||||
)?;
|
||||
js_sys::Reflect::set(
|
||||
&imports_object,
|
||||
&import_type.module().into(),
|
||||
&import_namespace.into(),
|
||||
)?;
|
||||
}
|
||||
import_externs.push(import);
|
||||
}
|
||||
// in case the import is not found, the JS Wasm VM will handle
|
||||
// the error for us, so we don't need to handle it
|
||||
}
|
||||
Ok((
|
||||
StoreHandle::new(
|
||||
store.as_store_mut().objects_mut(),
|
||||
WebAssembly::Instance::new(&self.module, &imports_object)
|
||||
.map_err(|e: JsValue| -> RuntimeError { e.into() })?,
|
||||
),
|
||||
import_externs,
|
||||
))
|
||||
|
||||
let imports_js_obj = imports.as_jsvalue(store).into();
|
||||
Ok(WebAssembly::Instance::new(&self.module, &imports_js_obj)
|
||||
.map_err(|e: JsValue| -> RuntimeError { e.into() })?)
|
||||
}
|
||||
|
||||
/// Returns the name of the current module.
|
||||
|
||||
@@ -92,6 +92,61 @@ mod js {
|
||||
assert_eq!(get_magic.call(&mut store, &[]).unwrap(), expected);
|
||||
}
|
||||
|
||||
#[wasm_bindgen_test]
|
||||
fn test_imports_from_js_object() {
|
||||
let mut store = Store::default();
|
||||
let mut module = Module::new(
|
||||
&store,
|
||||
br#"
|
||||
(module
|
||||
(func $imported (import "env" "imported") (param i32) (result i32))
|
||||
(func (export "exported") (param i32) (result i32)
|
||||
(call $imported (local.get 0))
|
||||
)
|
||||
)
|
||||
"#,
|
||||
)
|
||||
.unwrap();
|
||||
module
|
||||
.set_type_hints(ModuleTypeHints {
|
||||
imports: vec![ExternType::Function(FunctionType::new(
|
||||
vec![Type::I32],
|
||||
vec![Type::I32],
|
||||
))],
|
||||
exports: vec![ExternType::Function(FunctionType::new(
|
||||
vec![Type::I32],
|
||||
vec![Type::I32],
|
||||
))],
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let obj: js_sys::Object = js_sys::Function::new_with_args(
|
||||
"",
|
||||
"return {
|
||||
\"env\": {
|
||||
\"imported\": function(num) {
|
||||
console.log(\"Calling `imported`...\");
|
||||
var result = num * 2;
|
||||
console.log(\"Result of `imported`: \", result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
};",
|
||||
)
|
||||
.call0(&wasm_bindgen::JsValue::UNDEFINED)
|
||||
.unwrap()
|
||||
.into();
|
||||
|
||||
let import_object = Imports::new_from_js_object(&mut store, &module, obj)
|
||||
.expect("Can't get imports from js object");
|
||||
let instance = Instance::new(&mut store, &module, &import_object).unwrap();
|
||||
|
||||
let exported = instance.exports.get_function("exported").unwrap();
|
||||
|
||||
let expected = vec![Val::I32(6)].into_boxed_slice();
|
||||
assert_eq!(exported.call(&mut store, &[Val::I32(3)]).unwrap(), expected);
|
||||
}
|
||||
|
||||
#[wasm_bindgen_test]
|
||||
fn test_imported_function_dynamic() {
|
||||
let mut store = Store::default();
|
||||
|
||||
@@ -7,11 +7,7 @@ license = "MIT"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
libc = { version = "^0.2", default-features = false, optional = true }
|
||||
thiserror = "1"
|
||||
tracing = { version = "0.1" }
|
||||
typetag = { version = "0.1", optional = true }
|
||||
slab = { version = "0.4", optional = true }
|
||||
wasmer-vfs = { path = "../vfs", version = "=3.0.0-beta", default-features = false }
|
||||
|
||||
[features]
|
||||
|
||||
@@ -7,11 +7,7 @@ license = "MIT"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
libc = { version = "^0.2", default-features = false, optional = true }
|
||||
thiserror = "1"
|
||||
tracing = { version = "0.1" }
|
||||
typetag = { version = "0.1", optional = true }
|
||||
slab = { version = "0.4", optional = true }
|
||||
wasmer-vfs = { path = "../vfs", version = "=3.0.0-beta", default-features = false }
|
||||
bytes = "1"
|
||||
|
||||
|
||||
@@ -44,8 +44,9 @@ tracing-wasm = "0.2"
|
||||
|
||||
[features]
|
||||
default = ["sys-default"]
|
||||
wasix = []
|
||||
|
||||
sys = ["wasmer/sys"]
|
||||
sys = ["wasmer/sys", "wasix"]
|
||||
sys-default = ["wasmer/wat", "wasmer/compiler", "sys", "logging", "host-fs", "sys-poll", "host-vnet" ]
|
||||
sys-poll = []
|
||||
|
||||
|
||||
@@ -47,9 +47,9 @@ pub use crate::state::{
|
||||
WasiStateCreationError, ALL_RIGHTS, VIRTUAL_ROOT_FD,
|
||||
};
|
||||
pub use crate::syscalls::types;
|
||||
pub use crate::utils::{
|
||||
get_wasi_version, get_wasi_versions, is_wasi_module, is_wasix_module, WasiVersion,
|
||||
};
|
||||
#[cfg(feature = "wasix")]
|
||||
pub use crate::utils::is_wasix_module;
|
||||
pub use crate::utils::{get_wasi_version, get_wasi_versions, is_wasi_module, WasiVersion};
|
||||
pub use wasmer_vbus::{UnsupportedVirtualBus, VirtualBus};
|
||||
#[deprecated(since = "2.1.0", note = "Please use `wasmer_vfs::FsError`")]
|
||||
pub use wasmer_vfs::FsError as WasiFsError;
|
||||
@@ -184,6 +184,7 @@ impl WasiFunctionEnv {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "wasix")]
|
||||
if is_wasix_module(module) {
|
||||
self.data_mut(store)
|
||||
.state
|
||||
@@ -394,8 +395,12 @@ pub fn generate_import_object_from_env(
|
||||
WasiVersion::Snapshot1 | WasiVersion::Latest => {
|
||||
generate_import_object_snapshot1(store, env)
|
||||
}
|
||||
#[cfg(feature = "wasix")]
|
||||
WasiVersion::Wasix32v1 => generate_import_object_wasix32_v1(store, env),
|
||||
#[cfg(feature = "wasix")]
|
||||
WasiVersion::Wasix64v1 => generate_import_object_wasix64_v1(store, env),
|
||||
#[cfg(not(feature = "wasix"))]
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -537,6 +542,7 @@ fn generate_import_object_snapshot1(
|
||||
}
|
||||
|
||||
/// Combines a state generating function with the import list for snapshot 1
|
||||
#[cfg(feature = "wasix")]
|
||||
fn generate_import_object_wasix32_v1(
|
||||
mut store: &mut impl AsStoreMut,
|
||||
env: &FunctionEnv<WasiEnv>,
|
||||
@@ -655,6 +661,7 @@ fn generate_import_object_wasix32_v1(
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "wasix")]
|
||||
fn generate_import_object_wasix64_v1(
|
||||
mut store: &mut impl AsStoreMut,
|
||||
env: &FunctionEnv<WasiEnv>,
|
||||
|
||||
@@ -18,7 +18,9 @@ pub mod windows;
|
||||
|
||||
pub mod legacy;
|
||||
//pub mod wasi;
|
||||
#[cfg(feature = "wasix")]
|
||||
pub mod wasix32;
|
||||
#[cfg(feature = "wasix")]
|
||||
pub mod wasix64;
|
||||
|
||||
use self::types::*;
|
||||
|
||||
@@ -10,6 +10,7 @@ pub fn is_wasi_module(module: &Module) -> bool {
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[cfg(feature = "wasix")]
|
||||
/// Returns if the module is WASIX or not
|
||||
pub fn is_wasix_module(module: &Module) -> bool {
|
||||
match get_wasi_versions(module, false).ok_or(false) {
|
||||
|
||||
Reference in New Issue
Block a user