diff --git a/lib/api/src/js/import_object.rs b/lib/api/src/js/import_object.rs index 4bd1f92fbe6..19b2ec64493 100644 --- a/lib/api/src/js/import_object.rs +++ b/lib/api/src/js/import_object.rs @@ -113,25 +113,32 @@ impl ImportObject { } out } -} -impl Into for ImportObject { - fn into(self) -> js_sys::Object { - let guard = self.map.lock().unwrap(); + /// Returns the `ImportObject` as a Javascript `Object` + pub fn as_jsobject(&self) -> js_sys::Object { + let guard = self.map.lock().expect("Can't get the map"); let map = guard.borrow(); let imports = js_sys::Object::new(); for (module, ns) in map.iter() { let import_namespace = js_sys::Object::new(); for (name, exp) in ns.get_namespace_exports() { - js_sys::Reflect::set(&import_namespace, &name.into(), exp.as_jsvalue()).unwrap(); + js_sys::Reflect::set(&import_namespace, &name.into(), exp.as_jsvalue()) + .expect("Error while setting into the js namespace object"); } - js_sys::Reflect::set(&imports, &module.into(), &import_namespace.into()).unwrap(); + js_sys::Reflect::set(&imports, &module.into(), &import_namespace.into()) + .expect("Error while setting into the js imports object"); } imports } } +impl Into for ImportObject { + fn into(self) -> js_sys::Object { + self.as_jsobject() + } +} + impl NamedResolver for ImportObject { fn resolve_by_name(&self, module: &str, name: &str) -> Option { self.get_export(module, name) diff --git a/lib/api/src/js/instance.rs b/lib/api/src/js/instance.rs index c7e155adc33..c7eb3f57341 100644 --- a/lib/api/src/js/instance.rs +++ b/lib/api/src/js/instance.rs @@ -93,10 +93,24 @@ impl Instance { /// * Link errors that happen when plugging the imports into the instance /// * Runtime errors that happen when running the module `start` function. pub fn new(module: &Module, resolver: &dyn Resolver) -> Result { - let store = module.store(); - let (instance, functions) = module + let (instance, imports) = module .instantiate(resolver) .map_err(|e| InstantiationError::Start(e))?; + + let self_instance = Self::from_module_and_instance(module, instance); + self_instance.init_envs(&imports)?; + Ok(self_instance) + } + + /// Creates a Wasmer `Instance` from a Wasmer `Module` and a WebAssembly Instance + /// + /// # Important + /// + /// Is expected that the function [`Instance::init_envs`] is run manually + /// by the user in case the instance has any Wasmer imports, so the function + /// environments are properly initiated. + pub fn from_module_and_instance(module: &Module, instance: WebAssembly::Instance) -> Self { + let store = module.store(); let instance_exports = instance.exports(); let exports = module .exports() @@ -110,16 +124,22 @@ impl Instance { }) .collect::(); - let self_instance = Self { - module: module.clone(), + Self { instance, + module: module.clone(), exports, - }; - for func in functions { - func.init_envs(&self_instance) - .map_err(|e| InstantiationError::HostEnvInitialization(e))?; } - Ok(self_instance) + } + + /// Initialize the given extern imports with the Instance + pub fn init_envs(&self, imports: &[Export]) -> Result<(), InstantiationError> { + for import in imports { + if let Export::Function(func) = import { + func.init_envs(&self) + .map_err(|e| InstantiationError::HostEnvInitialization(e))?; + } + } + Ok(()) } /// Gets the [`Module`] associated with this instance. diff --git a/lib/api/src/js/module.rs b/lib/api/src/js/module.rs index fb02c27b9a2..076c2f49892 100644 --- a/lib/api/src/js/module.rs +++ b/lib/api/src/js/module.rs @@ -1,4 +1,4 @@ -use crate::js::export::{Export, VMFunction}; +use crate::js::export::Export; use crate::js::resolver::Resolver; use crate::js::store::Store; use crate::js::types::{ExportType, ImportType}; @@ -214,9 +214,9 @@ impl Module { pub(crate) fn instantiate( &self, resolver: &dyn Resolver, - ) -> Result<(WebAssembly::Instance, Vec), RuntimeError> { + ) -> Result<(WebAssembly::Instance, Vec), RuntimeError> { let imports = js_sys::Object::new(); - let mut functions: Vec = vec![]; + let mut import_externs: Vec = vec![]; for (i, import_type) in self.imports().enumerate() { let resolved_import = resolver.resolve(i as u32, import_type.module(), import_type.name()); @@ -239,9 +239,7 @@ impl Module { &import_namespace.into(), )?; } - if let Export::Function(func) = import { - functions.push(func); - } + 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 @@ -249,7 +247,7 @@ impl Module { Ok(( WebAssembly::Instance::new(&self.module, &imports) .map_err(|e: JsValue| -> RuntimeError { e.into() })?, - functions, + import_externs, )) } diff --git a/lib/wasi-types/Cargo.toml b/lib/wasi-types/Cargo.toml index 1ef5f0e5886..d970e10a42e 100644 --- a/lib/wasi-types/Cargo.toml +++ b/lib/wasi-types/Cargo.toml @@ -12,6 +12,11 @@ edition = "2018" [dependencies] wasmer-types = { path = "../types", version = "2.0.0" } -serde = { version = "1.0", features = ["derive"] } +serde = { version = "1.0", features = ["derive"], optional=true } byteorder = "1.3" -time = "0.1" \ No newline at end of file +time = "0.1" + +[features] +enable-serde = [ + "serde", +] diff --git a/lib/wasi-types/src/file.rs b/lib/wasi-types/src/file.rs index e79ed46029a..58334d32097 100644 --- a/lib/wasi-types/src/file.rs +++ b/lib/wasi-types/src/file.rs @@ -1,4 +1,5 @@ use crate::*; +#[cfg(feature = "enable-serde")] use serde::{Deserialize, Serialize}; use std::fmt; use wasmer_types::ValueType; @@ -93,7 +94,8 @@ pub type __wasi_filedelta_t = i64; pub type __wasi_filesize_t = u64; -#[derive(Copy, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Copy, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] #[repr(C)] pub struct __wasi_filestat_t { pub st_dev: __wasi_device_t, diff --git a/lib/wasi-types/src/versions/snapshot0.rs b/lib/wasi-types/src/versions/snapshot0.rs index b5d6af3ee64..0ba103be541 100644 --- a/lib/wasi-types/src/versions/snapshot0.rs +++ b/lib/wasi-types/src/versions/snapshot0.rs @@ -1,4 +1,5 @@ use crate::*; +#[cfg(feature = "enable-serde")] use serde::{Deserialize, Serialize}; use std::fmt; use wasmer_types::ValueType; @@ -37,7 +38,8 @@ pub const __WASI_WHENCE_CUR: u8 = 0; pub const __WASI_WHENCE_END: u8 = 1; pub const __WASI_WHENCE_SET: u8 = 2; -#[derive(Copy, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Copy, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] #[repr(C)] pub struct __wasi_filestat_t { pub st_dev: __wasi_device_t, diff --git a/lib/wasi/Cargo.toml b/lib/wasi/Cargo.toml index df60143ecb5..24f6eee01e3 100644 --- a/lib/wasi/Cargo.toml +++ b/lib/wasi/Cargo.toml @@ -16,7 +16,7 @@ crate-type = ["cdylib", "rlib"] [dependencies] cfg-if = "1.0" thiserror = "1" -generational-arena = { version = "0.2", features = ["serde"] } +generational-arena = { version = "0.2" } tracing = "0.1" getrandom = "0.2" wasmer-wasi-types = { path = "../wasi-types", version = "2.0.0" } @@ -45,8 +45,8 @@ default = ["sys-default"] sys = ["wasmer/sys-default"] sys-default = ["sys", "logging", "host-fs"] -js = ["wasmer/js-default", "mem-fs", "wasmer-vfs/no-time", "getrandom/js"] -js-default = ["js"] +js = ["wasmer/js", "mem-fs", "wasmer-vfs/no-time", "getrandom/js"] +js-default = ["js", "wasmer/js-default"] test-js = ["js", "wasmer/js-default", "wasmer/wat"] host-fs = ["wasmer-vfs/host-fs"] @@ -61,5 +61,7 @@ enable-serde = [ "typetag", "serde", "bincode", - "wasmer-vfs/enable-serde" + "wasmer-vfs/enable-serde", + "generational-arena/serde", + "wasmer-wasi-types/enable-serde", ] diff --git a/lib/wasi/src/syscalls/mod.rs b/lib/wasi/src/syscalls/mod.rs index b428447fe70..ec3648f30cf 100644 --- a/lib/wasi/src/syscalls/mod.rs +++ b/lib/wasi/src/syscalls/mod.rs @@ -2322,6 +2322,7 @@ pub fn path_unlink_file( /// Output: /// - `u32 nevents` /// The number of events seen +#[cfg(not(feature = "js"))] pub fn poll_oneoff( env: &WasiEnv, in_: WasmPtr<__wasi_subscription_t, Array>, @@ -2509,6 +2510,17 @@ pub fn poll_oneoff( __WASI_ESUCCESS } +#[cfg(feature = "js")] +pub fn poll_oneoff( + env: &WasiEnv, + in_: WasmPtr<__wasi_subscription_t, Array>, + out_: WasmPtr<__wasi_event_t, Array>, + nsubscriptions: u32, + nevents: WasmPtr, +) -> __wasi_errno_t { + unimplemented!(); +} + pub fn proc_exit(env: &WasiEnv, code: __wasi_exitcode_t) { debug!("wasi::proc_exit, {}", code); RuntimeError::raise(Box::new(WasiError::Exit(code)));