mirror of
https://github.com/mii443/wasmer.git
synced 2025-12-10 06:38:22 +00:00
Make instance more uniform
This commit is contained in:
@@ -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,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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")]
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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(),
|
||||
|
||||
Reference in New Issue
Block a user