mirror of
https://github.com/mii443/wasmer.git
synced 2025-12-10 22:58:18 +00:00
Make instance more uniform
This commit is contained in:
@@ -4,26 +4,27 @@
|
|||||||
use crate::imports::Imports;
|
use crate::imports::Imports;
|
||||||
use crate::js::externals::Extern;
|
use crate::js::externals::Extern;
|
||||||
use crate::js::vm::VMExtern;
|
use crate::js::vm::VMExtern;
|
||||||
|
use crate::js::Instance;
|
||||||
use crate::store::{AsStoreMut, AsStoreRef};
|
use crate::store::{AsStoreMut, AsStoreRef};
|
||||||
use crate::value::Value;
|
use crate::value::Value;
|
||||||
|
use crate::Exports;
|
||||||
use crate::ValType;
|
use crate::ValType;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use wasm_bindgen::JsValue;
|
use wasm_bindgen::{JsError, JsValue};
|
||||||
use wasmer_types::ExternType;
|
use wasmer_types::ExternType;
|
||||||
|
|
||||||
/// Convert the given type to a [`JsValue`].
|
/// Convert the given type to a [`JsValue`].
|
||||||
pub trait AsJs {
|
pub trait AsJs: Sized {
|
||||||
/// The inner definition type from this Javascript object
|
/// The inner definition type from this Javascript object
|
||||||
type DefinitionType;
|
type DefinitionType;
|
||||||
/// Convert the given type to a [`JsValue`].
|
/// Convert the given type to a [`JsValue`].
|
||||||
fn as_jsvalue(&self, store: &impl AsStoreRef) -> JsValue;
|
fn as_jsvalue(&self, store: &impl AsStoreRef) -> JsValue;
|
||||||
/// Convert the given type to a [`JsValue`].
|
/// Convert the given type to a [`JsValue`].
|
||||||
fn from_jsvalue(
|
fn from_jsvalue(
|
||||||
&self,
|
|
||||||
store: &mut impl AsStoreMut,
|
store: &mut impl AsStoreMut,
|
||||||
type_: &Self::DefinitionType,
|
type_: &Self::DefinitionType,
|
||||||
value: &JsValue,
|
value: &JsValue,
|
||||||
) -> Self;
|
) -> Result<Self, JsError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@@ -57,12 +58,11 @@ impl AsJs for Value {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn from_jsvalue(
|
fn from_jsvalue(
|
||||||
&self,
|
|
||||||
_store: &mut impl AsStoreMut,
|
_store: &mut impl AsStoreMut,
|
||||||
type_: &Self::DefinitionType,
|
type_: &Self::DefinitionType,
|
||||||
value: &JsValue,
|
value: &JsValue,
|
||||||
) -> Self {
|
) -> Result<Self, JsError> {
|
||||||
param_from_js(type_, value)
|
Ok(param_from_js(type_, value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,11 +74,10 @@ impl AsJs for wasmer_types::RawValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn from_jsvalue(
|
fn from_jsvalue(
|
||||||
&self,
|
|
||||||
_store: &mut impl AsStoreMut,
|
_store: &mut impl AsStoreMut,
|
||||||
type_: &Self::DefinitionType,
|
type_: &Self::DefinitionType,
|
||||||
value: &JsValue,
|
value: &JsValue,
|
||||||
) -> Self {
|
) -> Result<Self, JsError> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -162,11 +161,10 @@ impl AsJs for Imports {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn from_jsvalue(
|
fn from_jsvalue(
|
||||||
&self,
|
|
||||||
store: &mut impl AsStoreMut,
|
store: &mut impl AsStoreMut,
|
||||||
module: &Self::DefinitionType,
|
module: &Self::DefinitionType,
|
||||||
value: &JsValue,
|
value: &JsValue,
|
||||||
) -> Self {
|
) -> Result<Self, JsError> {
|
||||||
let module_imports: HashMap<(String, String), ExternType> = module
|
let module_imports: HashMap<(String, String), ExternType> = module
|
||||||
.imports()
|
.imports()
|
||||||
.map(|import| {
|
.map(|import| {
|
||||||
@@ -196,7 +194,7 @@ impl AsJs for Imports {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Self { map }
|
Ok(Self { map })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -213,11 +211,60 @@ impl AsJs for Extern {
|
|||||||
.clone()
|
.clone()
|
||||||
}
|
}
|
||||||
fn from_jsvalue(
|
fn from_jsvalue(
|
||||||
&self,
|
|
||||||
_store: &mut impl AsStoreMut,
|
_store: &mut impl AsStoreMut,
|
||||||
type_: &Self::DefinitionType,
|
type_: &Self::DefinitionType,
|
||||||
value: &JsValue,
|
value: &JsValue,
|
||||||
) -> Self {
|
) -> Result<Self, JsError> {
|
||||||
unimplemented!();
|
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}"))]
|
#[cfg_attr(feature = "std", error("Error while importing {0:?}.{1:?}: {2}"))]
|
||||||
Import(String, String, ImportError),
|
Import(String, String, ImportError),
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
|
||||||
/// A trap ocurred during linking.
|
/// A trap ocurred during linking.
|
||||||
#[cfg_attr(feature = "std", error("RuntimeError occurred during linking: {0}"))]
|
#[cfg_attr(feature = "std", error("RuntimeError occurred during linking: {0}"))]
|
||||||
Trap(#[source] RuntimeError),
|
Trap(#[source] RuntimeError),
|
||||||
@@ -146,20 +145,6 @@ pub enum InstantiationError {
|
|||||||
/// This error occurs when an import from a different store is used.
|
/// This error occurs when an import from a different store is used.
|
||||||
#[cfg_attr(feature = "std", error("cannot mix imports from different stores"))]
|
#[cfg_attr(feature = "std", error("cannot mix imports from different stores"))]
|
||||||
DifferentStores,
|
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")]
|
#[cfg(feature = "core")]
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
use crate::exports::Exports;
|
use crate::exports::Exports;
|
||||||
use crate::imports::Imports;
|
use crate::imports::Imports;
|
||||||
|
use crate::js::as_js::AsJs;
|
||||||
use crate::js::error::InstantiationError;
|
use crate::js::error::InstantiationError;
|
||||||
use crate::js::externals::Extern;
|
use crate::js::externals::Extern;
|
||||||
use crate::js::vm::{VMExtern, VMInstance};
|
use crate::js::vm::{VMExtern, VMInstance};
|
||||||
use crate::module::Module;
|
use crate::module::Module;
|
||||||
use crate::store::{AsStoreMut, AsStoreRef};
|
use crate::store::{AsStoreMut, AsStoreRef};
|
||||||
|
use crate::{LinkError, RuntimeError};
|
||||||
use js_sys::WebAssembly;
|
use js_sys::WebAssembly;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
@@ -18,8 +20,8 @@ use std::fmt;
|
|||||||
/// Spec: <https://webassembly.github.io/spec/core/exec/runtime.html#module-instances>
|
/// Spec: <https://webassembly.github.io/spec/core/exec/runtime.html#module-instances>
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Instance {
|
pub struct Instance {
|
||||||
handle: VMInstance,
|
pub(crate) handle: VMInstance,
|
||||||
module: Module,
|
pub(crate) module: Module,
|
||||||
/// The exports for an instance.
|
/// The exports for an instance.
|
||||||
pub exports: Exports,
|
pub exports: Exports,
|
||||||
}
|
}
|
||||||
@@ -68,7 +70,11 @@ impl Instance {
|
|||||||
.instantiate(&mut store, imports)
|
.instantiate(&mut store, imports)
|
||||||
.map_err(|e| InstantiationError::Start(e))?;
|
.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)
|
Ok(self_instance)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,60 +100,10 @@ impl Instance {
|
|||||||
Self::new(store, module, &imports)
|
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.
|
/// Gets the [`Module`] associated with this instance.
|
||||||
pub fn module(&self) -> &Module {
|
pub fn module(&self) -> &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 {
|
impl fmt::Debug for Instance {
|
||||||
|
|||||||
@@ -172,14 +172,6 @@ impl Instance {
|
|||||||
})
|
})
|
||||||
.collect::<Exports>();
|
.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 {
|
let instance = Self {
|
||||||
_handle: StoreHandle::new(store.objects_mut(), handle),
|
_handle: StoreHandle::new(store.objects_mut(), handle),
|
||||||
module: module.clone(),
|
module: module.clone(),
|
||||||
|
|||||||
Reference in New Issue
Block a user