Added jsobjectresolver

This commit is contained in:
Syrus Akbary
2021-11-24 23:57:43 +01:00
parent 50e2bd2ed2
commit c0913fa913
4 changed files with 105 additions and 7 deletions

View File

@@ -118,6 +118,7 @@ pub enum Export {
}
impl Export {
/// Return the export as a `JSValue`.
pub fn as_jsvalue(&self) -> &JsValue {
match self {
Export::Memory(js_wasm_memory) => js_wasm_memory.memory.as_ref(),

View File

@@ -100,7 +100,7 @@ impl Instance {
.instantiate(resolver)
.map_err(|e| InstantiationError::Start(e))?;
let self_instance = Self::from_module_and_instance(module, instance);
let self_instance = Self::from_module_and_instance(module, instance)?;
self_instance.init_envs(&imports)?;
Ok(self_instance)
}
@@ -112,7 +112,11 @@ impl Instance {
/// 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 {
#[doc(hidden)]
pub fn from_module_and_instance(
module: &Module,
instance: WebAssembly::Instance,
) -> Result<Self, InstantiationError> {
let store = module.store();
let instance_exports = instance.exports();
let exports = module
@@ -120,21 +124,28 @@ impl Instance {
.map(|export_type| {
let name = export_type.name();
let extern_type = export_type.ty().clone();
let js_export = js_sys::Reflect::get(&instance_exports, &name.into()).unwrap();
let js_export =
js_sys::Reflect::get(&instance_exports, &name.into()).map_err(|_e| {
InstantiationError::Link(format!(
"Can't get {} from the instance exports",
&name
))
})?;
let export: Export = (js_export, extern_type).into();
let extern_ = Extern::from_vm_export(store, export);
(name.to_string(), extern_)
Ok((name.to_string(), extern_))
})
.collect::<Exports>();
.collect::<Result<Exports, InstantiationError>>()?;
Self {
Ok(Self {
instance,
module: module.clone(),
exports,
}
})
}
/// Initialize the given extern imports with the Instance
#[doc(hidden)]
pub fn init_envs(&self, imports: &[Export]) -> Result<(), InstantiationError> {
for import in imports {
if let Export::Function(func) = import {

View File

@@ -0,0 +1,83 @@
use crate::js::{Export, ExternType, Module, NamedResolver};
use std::collections::HashMap;
/// All of the import data used when instantiating.
///
/// It's suggested that you use the [`imports!`] macro
/// instead of creating an `ImportObject` by hand.
///
/// [`imports!`]: macro.imports.html
///
/// # Usage:
/// ```ignore
/// use wasmer::{Exports, ImportObject, Function};
///
/// let mut import_object = ImportObject::new();
/// let mut env = Exports::new();
///
/// env.insert("foo", Function::new_native(foo));
/// import_object.register("env", env);
///
/// fn foo(n: i32) -> i32 {
/// n
/// }
/// ```
#[derive(Clone, Default)]
pub struct JSObjectResolver {
module_imports: HashMap<(String, String), ExternType>,
object: js_sys::Object,
}
unsafe impl Send for JSObjectResolver {}
unsafe impl Sync for JSObjectResolver {}
impl JSObjectResolver {
/// Create a new `ImportObject`.
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::{ImportObject, Instance, Namespace};
/// let mut import_object = ImportObject::new();
/// import_object.get_export("module", "name");
/// ```
pub fn get_export(&self, module: &str, name: &str) -> Option<Export> {
let namespace = js_sys::Reflect::get(&self.object, &name.into()).ok()?;
let js_export = js_sys::Reflect::get(&namespace, &name.into()).ok()?;
match self
.module_imports
.get(&(module.to_string(), name.to_string()))
{
Some(extern_type) => Some((js_export, extern_type.clone()).into()),
None => None,
}
}
}
impl Into<js_sys::Object> for JSObjectResolver {
fn into(self) -> js_sys::Object {
self.object
}
}
impl NamedResolver for JSObjectResolver {
fn resolve_by_name(&self, module: &str, name: &str) -> Option<Export> {
self.get_export(module, name)
}
}

View File

@@ -31,6 +31,7 @@ mod exports;
mod externals;
mod import_object;
mod instance;
mod jsobjectresolver;
mod module;
#[cfg(feature = "wasm-types-polyfill")]
mod module_info_polyfill;
@@ -50,6 +51,7 @@ pub use wasmer_derive::WasmerEnv;
pub use crate::js::cell::WasmCell;
pub use crate::js::env::{HostEnvInitError, LazyInit, WasmerEnv};
pub use crate::js::export::Export;
pub use crate::js::exports::{ExportError, Exportable, Exports, ExportsIterator};
pub use crate::js::externals::{
Extern, FromToNativeWasmType, Function, Global, HostFunction, Memory, MemoryError, Table,
@@ -57,6 +59,7 @@ pub use crate::js::externals::{
};
pub use crate::js::import_object::{ImportObject, ImportObjectIterator, LikeNamespace};
pub use crate::js::instance::{Instance, InstantiationError};
pub use crate::js::jsobjectresolver::JSObjectResolver;
pub use crate::js::module::{Module, ModuleTypeHints};
pub use crate::js::native::NativeFunc;
pub use crate::js::ptr::{Array, Item, WasmPtr};