Skip to content

Commit

Permalink
Merge pull request #2583 from wasmerio/js-wasi
Browse files Browse the repository at this point in the history
Improved wasmer-js api
  • Loading branch information
syrusakbary authored Oct 1, 2021
2 parents 6a0f692 + e2d1c36 commit f9ff574
Show file tree
Hide file tree
Showing 8 changed files with 78 additions and 30 deletions.
19 changes: 13 additions & 6 deletions lib/api/src/js/import_object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,25 +113,32 @@ impl ImportObject {
}
out
}
}

impl Into<js_sys::Object> 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<js_sys::Object> 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<Export> {
self.get_export(module, name)
Expand Down
38 changes: 29 additions & 9 deletions lib/api/src/js/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Self, InstantiationError> {
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()
Expand All @@ -110,16 +124,22 @@ impl Instance {
})
.collect::<Exports>();

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.
Expand Down
12 changes: 5 additions & 7 deletions lib/api/src/js/module.rs
Original file line number Diff line number Diff line change
@@ -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};
Expand Down Expand Up @@ -214,9 +214,9 @@ impl Module {
pub(crate) fn instantiate(
&self,
resolver: &dyn Resolver,
) -> Result<(WebAssembly::Instance, Vec<VMFunction>), RuntimeError> {
) -> Result<(WebAssembly::Instance, Vec<Export>), RuntimeError> {
let imports = js_sys::Object::new();
let mut functions: Vec<VMFunction> = vec![];
let mut import_externs: Vec<Export> = vec![];
for (i, import_type) in self.imports().enumerate() {
let resolved_import =
resolver.resolve(i as u32, import_type.module(), import_type.name());
Expand All @@ -239,17 +239,15 @@ 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
}
Ok((
WebAssembly::Instance::new(&self.module, &imports)
.map_err(|e: JsValue| -> RuntimeError { e.into() })?,
functions,
import_externs,
))
}

Expand Down
9 changes: 7 additions & 2 deletions lib/wasi-types/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
time = "0.1"

[features]
enable-serde = [
"serde",
]
4 changes: 3 additions & 1 deletion lib/wasi-types/src/file.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::*;
#[cfg(feature = "enable-serde")]
use serde::{Deserialize, Serialize};
use std::fmt;
use wasmer_types::ValueType;
Expand Down Expand Up @@ -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,
Expand Down
4 changes: 3 additions & 1 deletion lib/wasi-types/src/versions/snapshot0.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::*;
#[cfg(feature = "enable-serde")]
use serde::{Deserialize, Serialize};
use std::fmt;
use wasmer_types::ValueType;
Expand Down Expand Up @@ -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,
Expand Down
10 changes: 6 additions & 4 deletions lib/wasi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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" }
Expand Down Expand Up @@ -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"]
Expand All @@ -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",
]
12 changes: 12 additions & 0 deletions lib/wasi/src/syscalls/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>,
Expand Down Expand Up @@ -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<u32>,
) -> __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)));
Expand Down

0 comments on commit f9ff574

Please sign in to comment.