mirror of
https://github.com/mii443/wasmer.git
synced 2025-12-10 22:58:18 +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"
|
name = "wasmer-vbus"
|
||||||
version = "3.0.0-beta"
|
version = "3.0.0-beta"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
|
||||||
"slab",
|
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tracing",
|
|
||||||
"typetag",
|
|
||||||
"wasmer-vfs",
|
"wasmer-vfs",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -3268,11 +3264,7 @@ name = "wasmer-vnet"
|
|||||||
version = "3.0.0-beta"
|
version = "3.0.0-beta"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"libc",
|
|
||||||
"slab",
|
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tracing",
|
|
||||||
"typetag",
|
|
||||||
"wasmer-vfs",
|
"wasmer-vfs",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
//! The import module contains the implementation data structures and helper functions used to
|
//! 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
|
//! manipulate and access a wasm module's imports including memories, tables, globals, and
|
||||||
//! functions.
|
//! 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::exports::Exports;
|
||||||
use crate::js::module::Module;
|
use crate::js::module::Module;
|
||||||
use crate::js::store::AsStoreRef;
|
use crate::js::store::{AsStoreMut, AsStoreRef};
|
||||||
use crate::js::types::AsJs;
|
use crate::js::types::AsJs;
|
||||||
|
use crate::js::ExternType;
|
||||||
use crate::Extern;
|
use crate::Extern;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
@@ -179,6 +181,80 @@ impl Imports {
|
|||||||
pub fn iter<'a>(&'a self) -> ImportsIterator<'a> {
|
pub fn iter<'a>(&'a self) -> ImportsIterator<'a> {
|
||||||
ImportsIterator::new(self)
|
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> {
|
pub struct ImportsIterator<'a> {
|
||||||
@@ -317,89 +393,18 @@ macro_rules! import_namespace {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use crate::js::exports::Exportable;
|
use crate::js::{Global, Store, Value};
|
||||||
use crate::js::Type;
|
|
||||||
use crate::js::{Global, Store, Val};
|
|
||||||
|
|
||||||
use crate::js::export::Export;
|
// use wasm_bindgen::*;
|
||||||
use wasm_bindgen_test::*;
|
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() {
|
fn chaining_works() {
|
||||||
let mut store = Store::default();
|
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! {
|
let mut imports1 = imports! {
|
||||||
"dog" => {
|
"dog" => {
|
||||||
@@ -412,7 +417,7 @@ mod test {
|
|||||||
"small" => g.clone()
|
"small" => g.clone()
|
||||||
},
|
},
|
||||||
"cat" => {
|
"cat" => {
|
||||||
"small" => g.clone()
|
"small" => g
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -426,62 +431,162 @@ mod test {
|
|||||||
assert!(happy.is_some());
|
assert!(happy.is_some());
|
||||||
assert!(small.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 happy_dog_entry = imports1.get_export("dog", "happy").unwrap();
|
||||||
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! {
|
// assert!(
|
||||||
"dog" => {
|
// if let Export::Global(happy_dog_global) = happy_dog_entry.to_export() {
|
||||||
"happy" => g1,
|
// happy_dog_global.ty.ty == Type::I32
|
||||||
},
|
// } else {
|
||||||
};
|
// false
|
||||||
|
// }
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
||||||
let imports2 = imports! {
|
// fn imports_macro_allows_trailing_comma_and_none() {
|
||||||
"dog" => {
|
// use crate::js::Function;
|
||||||
"happy" => g2,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
imports1.extend(&imports2);
|
// let mut store = Default::default();
|
||||||
let happy_dog_entry = imports1.get_export("dog", "happy").unwrap();
|
|
||||||
|
|
||||||
assert!(
|
// fn func(arg: i32) -> i32 {
|
||||||
if let Export::Global(happy_dog_global) = happy_dog_entry.to_export() {
|
// arg + 1
|
||||||
happy_dog_global.ty.ty == Type::F32
|
// }
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// now test it in reverse
|
// let _ = imports! {
|
||||||
let mut store = Store::default();
|
// "env" => {
|
||||||
let g1 = Global::new(&store, Val::I32(0));
|
// "func" => Function::new_typed(&store, func),
|
||||||
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),
|
||||||
|
// },
|
||||||
|
// "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! {
|
// fn chaining_works() {
|
||||||
"dog" => {
|
// let mut store = Store::default();
|
||||||
"happy" => g1,
|
// let g = Global::new(&store, Val::I32(0));
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut imports2 = imports! {
|
// let mut imports1 = imports! {
|
||||||
"dog" => {
|
// "dog" => {
|
||||||
"happy" => g2,
|
// "happy" => g.clone()
|
||||||
},
|
// }
|
||||||
};
|
// };
|
||||||
|
|
||||||
imports2.extend(&imports1);
|
// let imports2 = imports! {
|
||||||
let happy_dog_entry = imports2.get_export("dog", "happy").unwrap();
|
// "dog" => {
|
||||||
|
// "small" => g.clone()
|
||||||
|
// },
|
||||||
|
// "cat" => {
|
||||||
|
// "small" => g.clone()
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
assert!(
|
// imports1.extend(&imports2);
|
||||||
if let Export::Global(happy_dog_global) = happy_dog_entry.to_export() {
|
|
||||||
happy_dog_global.ty.ty == Type::I32
|
// let small_cat_export = imports1.get_export("cat", "small");
|
||||||
} else {
|
// assert!(small_cat_export.is_some());
|
||||||
false
|
|
||||||
}
|
// 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 {
|
pub struct Instance {
|
||||||
_handle: StoreHandle<WebAssembly::Instance>,
|
_handle: StoreHandle<WebAssembly::Instance>,
|
||||||
module: Module,
|
module: Module,
|
||||||
#[allow(dead_code)]
|
|
||||||
imports: Imports,
|
|
||||||
/// The exports for an instance.
|
/// The exports for an instance.
|
||||||
pub exports: Exports,
|
pub exports: Exports,
|
||||||
}
|
}
|
||||||
@@ -65,12 +63,11 @@ impl Instance {
|
|||||||
module: &Module,
|
module: &Module,
|
||||||
imports: &Imports,
|
imports: &Imports,
|
||||||
) -> Result<Self, InstantiationError> {
|
) -> Result<Self, InstantiationError> {
|
||||||
let import_copy = imports.clone();
|
let instance: WebAssembly::Instance = module
|
||||||
let (instance, _imports): (StoreHandle<WebAssembly::Instance>, Vec<Extern>) = module
|
|
||||||
.instantiate(&mut store, imports)
|
.instantiate(&mut store, imports)
|
||||||
.map_err(|e| InstantiationError::Start(e))?;
|
.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<_>>())?;
|
//self_instance.init_envs(&imports.iter().map(Extern::to_export).collect::<Vec<_>>())?;
|
||||||
Ok(self_instance)
|
Ok(self_instance)
|
||||||
}
|
}
|
||||||
@@ -109,8 +106,7 @@ impl Instance {
|
|||||||
pub fn from_module_and_instance(
|
pub fn from_module_and_instance(
|
||||||
mut store: &mut impl AsStoreMut,
|
mut store: &mut impl AsStoreMut,
|
||||||
module: &Module,
|
module: &Module,
|
||||||
instance: StoreHandle<WebAssembly::Instance>,
|
instance: WebAssembly::Instance,
|
||||||
imports: Imports,
|
|
||||||
) -> Result<Self, InstantiationError> {
|
) -> Result<Self, InstantiationError> {
|
||||||
use crate::js::externals::VMExtern;
|
use crate::js::externals::VMExtern;
|
||||||
let instance_exports = instance.get(store.as_store_ref().objects()).exports();
|
let instance_exports = instance.get(store.as_store_ref().objects()).exports();
|
||||||
@@ -127,11 +123,10 @@ impl Instance {
|
|||||||
Ok((name.to_string(), extern_))
|
Ok((name.to_string(), extern_))
|
||||||
})
|
})
|
||||||
.collect::<Result<Exports, InstantiationError>>()?;
|
.collect::<Result<Exports, InstantiationError>>()?;
|
||||||
|
let handle = StoreHandle::new(store.as_store_mut().objects_mut(), instance);
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
_handle: instance,
|
_handle: handle,
|
||||||
module: module.clone(),
|
module: module.clone(),
|
||||||
imports,
|
|
||||||
exports,
|
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 function_env;
|
||||||
mod imports;
|
mod imports;
|
||||||
mod instance;
|
mod instance;
|
||||||
mod js_import_object;
|
|
||||||
mod mem_access;
|
mod mem_access;
|
||||||
mod module;
|
mod module;
|
||||||
#[cfg(feature = "wasm-types-polyfill")]
|
#[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::function_env::{FunctionEnv, FunctionEnvMut};
|
||||||
pub use crate::js::imports::Imports;
|
pub use crate::js::imports::Imports;
|
||||||
pub use crate::js::instance::Instance;
|
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::mem_access::{MemoryAccessError, WasmRef, WasmSlice, WasmSliceIter};
|
||||||
pub use crate::js::module::{Module, ModuleTypeHints};
|
pub use crate::js::module::{Module, ModuleTypeHints};
|
||||||
pub use crate::js::native::TypedFunction;
|
pub use crate::js::native::TypedFunction;
|
||||||
|
|||||||
@@ -3,9 +3,8 @@ use crate::js::error::WasmError;
|
|||||||
use crate::js::error::{CompileError, InstantiationError};
|
use crate::js::error::{CompileError, InstantiationError};
|
||||||
#[cfg(feature = "js-serializable-module")]
|
#[cfg(feature = "js-serializable-module")]
|
||||||
use crate::js::error::{DeserializeError, SerializeError};
|
use crate::js::error::{DeserializeError, SerializeError};
|
||||||
use crate::js::externals::Extern;
|
|
||||||
use crate::js::imports::Imports;
|
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::types::{AsJs, ExportType, ImportType};
|
||||||
use crate::js::RuntimeError;
|
use crate::js::RuntimeError;
|
||||||
use crate::AsStoreRef;
|
use crate::AsStoreRef;
|
||||||
@@ -222,7 +221,7 @@ impl Module {
|
|||||||
&self,
|
&self,
|
||||||
store: &mut impl AsStoreMut,
|
store: &mut impl AsStoreMut,
|
||||||
imports: &Imports,
|
imports: &Imports,
|
||||||
) -> Result<(StoreHandle<WebAssembly::Instance>, Vec<Extern>), RuntimeError> {
|
) -> Result<WebAssembly::Instance, RuntimeError> {
|
||||||
// Ensure all imports come from the same store.
|
// Ensure all imports come from the same store.
|
||||||
if imports
|
if imports
|
||||||
.into_iter()
|
.into_iter()
|
||||||
@@ -232,46 +231,10 @@ impl Module {
|
|||||||
InstantiationError::DifferentStores,
|
InstantiationError::DifferentStores,
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
let imports_object = js_sys::Object::new();
|
|
||||||
let mut import_externs: Vec<Extern> = vec![];
|
let imports_js_obj = imports.as_jsvalue(store).into();
|
||||||
for import_type in self.imports() {
|
Ok(WebAssembly::Instance::new(&self.module, &imports_js_obj)
|
||||||
let resolved_import = imports.get_export(import_type.module(), import_type.name());
|
.map_err(|e: JsValue| -> RuntimeError { e.into() })?)
|
||||||
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,
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the name of the current module.
|
/// Returns the name of the current module.
|
||||||
|
|||||||
@@ -92,6 +92,61 @@ mod js {
|
|||||||
assert_eq!(get_magic.call(&mut store, &[]).unwrap(), expected);
|
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]
|
#[wasm_bindgen_test]
|
||||||
fn test_imported_function_dynamic() {
|
fn test_imported_function_dynamic() {
|
||||||
let mut store = Store::default();
|
let mut store = Store::default();
|
||||||
|
|||||||
@@ -7,11 +7,7 @@ license = "MIT"
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libc = { version = "^0.2", default-features = false, optional = true }
|
|
||||||
thiserror = "1"
|
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 }
|
wasmer-vfs = { path = "../vfs", version = "=3.0.0-beta", default-features = false }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
|||||||
@@ -7,11 +7,7 @@ license = "MIT"
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libc = { version = "^0.2", default-features = false, optional = true }
|
|
||||||
thiserror = "1"
|
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 }
|
wasmer-vfs = { path = "../vfs", version = "=3.0.0-beta", default-features = false }
|
||||||
bytes = "1"
|
bytes = "1"
|
||||||
|
|
||||||
|
|||||||
@@ -44,8 +44,9 @@ tracing-wasm = "0.2"
|
|||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["sys-default"]
|
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-default = ["wasmer/wat", "wasmer/compiler", "sys", "logging", "host-fs", "sys-poll", "host-vnet" ]
|
||||||
sys-poll = []
|
sys-poll = []
|
||||||
|
|
||||||
|
|||||||
@@ -47,9 +47,9 @@ pub use crate::state::{
|
|||||||
WasiStateCreationError, ALL_RIGHTS, VIRTUAL_ROOT_FD,
|
WasiStateCreationError, ALL_RIGHTS, VIRTUAL_ROOT_FD,
|
||||||
};
|
};
|
||||||
pub use crate::syscalls::types;
|
pub use crate::syscalls::types;
|
||||||
pub use crate::utils::{
|
#[cfg(feature = "wasix")]
|
||||||
get_wasi_version, get_wasi_versions, is_wasi_module, is_wasix_module, WasiVersion,
|
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};
|
pub use wasmer_vbus::{UnsupportedVirtualBus, VirtualBus};
|
||||||
#[deprecated(since = "2.1.0", note = "Please use `wasmer_vfs::FsError`")]
|
#[deprecated(since = "2.1.0", note = "Please use `wasmer_vfs::FsError`")]
|
||||||
pub use wasmer_vfs::FsError as WasiFsError;
|
pub use wasmer_vfs::FsError as WasiFsError;
|
||||||
@@ -184,6 +184,7 @@ impl WasiFunctionEnv {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "wasix")]
|
||||||
if is_wasix_module(module) {
|
if is_wasix_module(module) {
|
||||||
self.data_mut(store)
|
self.data_mut(store)
|
||||||
.state
|
.state
|
||||||
@@ -394,8 +395,12 @@ pub fn generate_import_object_from_env(
|
|||||||
WasiVersion::Snapshot1 | WasiVersion::Latest => {
|
WasiVersion::Snapshot1 | WasiVersion::Latest => {
|
||||||
generate_import_object_snapshot1(store, env)
|
generate_import_object_snapshot1(store, env)
|
||||||
}
|
}
|
||||||
|
#[cfg(feature = "wasix")]
|
||||||
WasiVersion::Wasix32v1 => generate_import_object_wasix32_v1(store, env),
|
WasiVersion::Wasix32v1 => generate_import_object_wasix32_v1(store, env),
|
||||||
|
#[cfg(feature = "wasix")]
|
||||||
WasiVersion::Wasix64v1 => generate_import_object_wasix64_v1(store, env),
|
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
|
/// Combines a state generating function with the import list for snapshot 1
|
||||||
|
#[cfg(feature = "wasix")]
|
||||||
fn generate_import_object_wasix32_v1(
|
fn generate_import_object_wasix32_v1(
|
||||||
mut store: &mut impl AsStoreMut,
|
mut store: &mut impl AsStoreMut,
|
||||||
env: &FunctionEnv<WasiEnv>,
|
env: &FunctionEnv<WasiEnv>,
|
||||||
@@ -655,6 +661,7 @@ fn generate_import_object_wasix32_v1(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "wasix")]
|
||||||
fn generate_import_object_wasix64_v1(
|
fn generate_import_object_wasix64_v1(
|
||||||
mut store: &mut impl AsStoreMut,
|
mut store: &mut impl AsStoreMut,
|
||||||
env: &FunctionEnv<WasiEnv>,
|
env: &FunctionEnv<WasiEnv>,
|
||||||
|
|||||||
@@ -18,7 +18,9 @@ pub mod windows;
|
|||||||
|
|
||||||
pub mod legacy;
|
pub mod legacy;
|
||||||
//pub mod wasi;
|
//pub mod wasi;
|
||||||
|
#[cfg(feature = "wasix")]
|
||||||
pub mod wasix32;
|
pub mod wasix32;
|
||||||
|
#[cfg(feature = "wasix")]
|
||||||
pub mod wasix64;
|
pub mod wasix64;
|
||||||
|
|
||||||
use self::types::*;
|
use self::types::*;
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ pub fn is_wasi_module(module: &Module) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
#[cfg(feature = "wasix")]
|
||||||
/// Returns if the module is WASIX or not
|
/// Returns if the module is WASIX or not
|
||||||
pub fn is_wasix_module(module: &Module) -> bool {
|
pub fn is_wasix_module(module: &Module) -> bool {
|
||||||
match get_wasi_versions(module, false).ok_or(false) {
|
match get_wasi_versions(module, false).ok_or(false) {
|
||||||
|
|||||||
Reference in New Issue
Block a user