Make instance more uniform

This commit is contained in:
Syrus Akbary
2023-02-10 18:53:18 -08:00
parent 4eaddb5ce4
commit b9d21187ed
4 changed files with 70 additions and 90 deletions

View File

@@ -4,26 +4,27 @@
use crate::imports::Imports;
use crate::js::externals::Extern;
use crate::js::vm::VMExtern;
use crate::js::Instance;
use crate::store::{AsStoreMut, AsStoreRef};
use crate::value::Value;
use crate::Exports;
use crate::ValType;
use std::collections::HashMap;
use wasm_bindgen::JsValue;
use wasm_bindgen::{JsError, JsValue};
use wasmer_types::ExternType;
/// Convert the given type to a [`JsValue`].
pub trait AsJs {
pub trait AsJs: Sized {
/// The inner definition type from this Javascript object
type DefinitionType;
/// Convert the given type to a [`JsValue`].
fn as_jsvalue(&self, store: &impl AsStoreRef) -> JsValue;
/// Convert the given type to a [`JsValue`].
fn from_jsvalue(
&self,
store: &mut impl AsStoreMut,
type_: &Self::DefinitionType,
value: &JsValue,
) -> Self;
) -> Result<Self, JsError>;
}
#[inline]
@@ -57,12 +58,11 @@ impl AsJs for Value {
}
fn from_jsvalue(
&self,
_store: &mut impl AsStoreMut,
type_: &Self::DefinitionType,
value: &JsValue,
) -> Self {
param_from_js(type_, value)
) -> Result<Self, JsError> {
Ok(param_from_js(type_, value))
}
}
@@ -74,11 +74,10 @@ impl AsJs for wasmer_types::RawValue {
}
fn from_jsvalue(
&self,
_store: &mut impl AsStoreMut,
type_: &Self::DefinitionType,
value: &JsValue,
) -> Self {
) -> Result<Self, JsError> {
unimplemented!();
}
}
@@ -162,11 +161,10 @@ impl AsJs for Imports {
}
fn from_jsvalue(
&self,
store: &mut impl AsStoreMut,
module: &Self::DefinitionType,
value: &JsValue,
) -> Self {
) -> Result<Self, JsError> {
let module_imports: HashMap<(String, String), ExternType> = module
.imports()
.map(|import| {
@@ -196,7 +194,7 @@ impl AsJs for Imports {
}
}
Self { map }
Ok(Self { map })
}
}
@@ -213,11 +211,60 @@ impl AsJs for Extern {
.clone()
}
fn from_jsvalue(
&self,
_store: &mut impl AsStoreMut,
type_: &Self::DefinitionType,
value: &JsValue,
) -> Self {
) -> Result<Self, JsError> {
unimplemented!();
}
}
impl AsJs for Instance {
type DefinitionType = crate::module::Module;
fn as_jsvalue(&self, store: &impl AsStoreRef) -> wasm_bindgen::JsValue {
self.handle.clone().into()
}
fn from_jsvalue(
mut store: &mut impl AsStoreMut,
module: &Self::DefinitionType,
value: &JsValue,
) -> Result<Self, JsError> {
let instance: js_sys::WebAssembly::Instance = value.clone().into();
let instance_exports = instance.exports();
let exports = module
.exports()
.map(|export_type| {
let name = export_type.name();
let extern_type = export_type.ty().clone();
// Annotation is here to prevent spurious IDE warnings.
#[allow(unused_unsafe)]
let js_export = unsafe {
js_sys::Reflect::get(&instance_exports, &name.into()).map_err(|_e| {
JsError::new(&format!(
"Can't get {0} from the instance exports",
name.to_string()
))
})?
};
let export: VMExtern = VMExtern::from_js_value(js_export, &mut store, extern_type)
.map_err(|_e| {
JsError::new(&format!(
"Can't get {0} from the instance exports",
name.to_string()
))
})?
.into();
let extern_ = Extern::from_vm_extern(&mut store, export);
Ok((name.to_string(), extern_))
})
.collect::<Result<Exports, JsError>>()?;
Ok(Self {
handle: instance,
module: module.clone(),
exports,
})
}
}

View File

@@ -109,7 +109,6 @@ pub enum LinkError {
#[cfg_attr(feature = "std", error("Error while importing {0:?}.{1:?}: {2}"))]
Import(String, String, ImportError),
#[cfg(not(target_arch = "wasm32"))]
/// A trap ocurred during linking.
#[cfg_attr(feature = "std", error("RuntimeError occurred during linking: {0}"))]
Trap(#[source] RuntimeError),
@@ -146,20 +145,6 @@ pub enum InstantiationError {
/// This error occurs when an import from a different store is used.
#[cfg_attr(feature = "std", error("cannot mix imports from different stores"))]
DifferentStores,
/// A generic error occured while invoking API functions
#[cfg_attr(feature = "std", error(transparent))]
Wasm(WasmError),
/// Insufficient resources available for execution.
#[cfg_attr(feature = "std", error("Can't get {0} from the instance exports"))]
NotInExports(String),
}
impl From<WasmError> for InstantiationError {
fn from(original: WasmError) -> Self {
Self::Wasm(original)
}
}
#[cfg(feature = "core")]

View File

@@ -1,10 +1,12 @@
use crate::exports::Exports;
use crate::imports::Imports;
use crate::js::as_js::AsJs;
use crate::js::error::InstantiationError;
use crate::js::externals::Extern;
use crate::js::vm::{VMExtern, VMInstance};
use crate::module::Module;
use crate::store::{AsStoreMut, AsStoreRef};
use crate::{LinkError, RuntimeError};
use js_sys::WebAssembly;
use std::fmt;
@@ -18,8 +20,8 @@ use std::fmt;
/// Spec: <https://webassembly.github.io/spec/core/exec/runtime.html#module-instances>
#[derive(Clone)]
pub struct Instance {
handle: VMInstance,
module: Module,
pub(crate) handle: VMInstance,
pub(crate) module: Module,
/// The exports for an instance.
pub exports: Exports,
}
@@ -68,7 +70,11 @@ impl Instance {
.instantiate(&mut store, imports)
.map_err(|e| InstantiationError::Start(e))?;
let self_instance = Self::from_module_and_instance(store, module, instance)?;
let self_instance = Self::from_jsvalue(store, &module, &instance).map_err(|e| {
let js_err: wasm_bindgen::JsValue = e.into();
let err: RuntimeError = js_err.into();
InstantiationError::Link(LinkError::Trap(err))
})?;
Ok(self_instance)
}
@@ -94,60 +100,10 @@ impl Instance {
Self::new(store, module, &imports)
}
/// 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.
///
/// *This method is only available when targeting JS environments*
pub fn from_module_and_instance(
mut store: &mut impl AsStoreMut,
module: &Module,
instance: WebAssembly::Instance,
) -> Result<Self, InstantiationError> {
let instance_exports = instance.exports();
let exports = module
.exports()
.map(|export_type| {
let name = export_type.name();
let extern_type = export_type.ty().clone();
// Annotation is here to prevent spurious IDE warnings.
#[allow(unused_unsafe)]
let js_export = unsafe {
js_sys::Reflect::get(&instance_exports, &name.into())
.map_err(|_e| InstantiationError::NotInExports(name.to_string()))?
};
let export: VMExtern =
VMExtern::from_js_value(js_export, &mut store, extern_type)?.into();
let extern_ = Extern::from_vm_extern(&mut store, export);
Ok((name.to_string(), extern_))
})
.collect::<Result<Exports, InstantiationError>>()?;
Ok(Self {
handle: instance,
module: module.clone(),
exports,
})
}
/// Gets the [`Module`] associated with this instance.
pub fn module(&self) -> &Module {
&self.module
}
/// Returns the inner WebAssembly Instance
#[doc(hidden)]
pub fn raw<'context>(
&'context self,
_store: &'context impl AsStoreRef,
) -> &'context WebAssembly::Instance {
&self.handle
}
}
impl fmt::Debug for Instance {

View File

@@ -172,14 +172,6 @@ impl Instance {
})
.collect::<Exports>();
// If the memory is imported then also export it for backwards compatibility reasons
// (many will assume the memory is always exported) - later we can remove this
if exports.get_memory("memory").is_err() {
if let Some(memory) = externs.iter().find(|a| a.ty(store).memory().is_some()) {
exports.insert("memory", memory.clone());
}
}
let instance = Self {
_handle: StoreHandle::new(store.objects_mut(), handle),
module: module.clone(),