use crate::{
AsStoreMut, BackendInstance, Exports, Extern, Imports, InstantiationError, Module,
jsc::{utils::convert::AsJsc, vm::VMInstance},
};
use super::engine::IntoJSC;
#[derive(Clone, PartialEq, Eq)]
pub struct Instance {
pub(crate) _handle: VMInstance,
}
impl Instance {
#[allow(clippy::result_large_err)]
pub(crate) fn new(
mut store: &mut impl AsStoreMut,
module: &Module,
imports: &Imports,
) -> Result<(Self, Exports), InstantiationError> {
let instance = module
.as_jsc()
.instantiate(&mut store, imports)
.map_err(InstantiationError::Start)?;
Self::from_module_and_instance(store, module, instance)
}
#[allow(clippy::result_large_err)]
pub(crate) fn new_by_index(
store: &mut impl AsStoreMut,
module: &Module,
externs: &[Extern],
) -> Result<(Self, Exports), InstantiationError> {
let mut imports = Imports::new();
for (import_ty, extern_ty) in module.imports().zip(externs.iter()) {
imports.define(import_ty.module(), import_ty.name(), extern_ty.clone());
}
Self::new(store, module, &imports)
}
#[allow(clippy::result_large_err)]
pub(crate) fn from_module_and_instance(
mut store: &mut impl AsStoreMut,
module: &Module,
instance: VMInstance,
) -> Result<(Self, Exports), InstantiationError> {
let engine = store.as_store_mut();
let context = engine.jsc().context();
let mut instance_exports = instance
.get_property(context, "exports".to_string())
.to_object(context)
.unwrap();
let exports_ty = module.exports().collect::<Vec<_>>();
let exports = exports_ty
.iter()
.map(|export_type| {
let name = export_type.name();
let mut store = store.as_store_mut();
let context = store.jsc().context();
let extern_type = export_type.ty();
let js_export = instance_exports.get_property(context, name.to_string());
let extern_ = Extern::from_jsc_value(&mut store, extern_type, &js_export).unwrap();
Ok((name.to_string(), extern_))
})
.collect::<Result<Exports, InstantiationError>>()?;
Ok((Self { _handle: instance }, exports))
}
}
impl crate::Instance {
pub fn into_jsc(self) -> crate::backend::jsc::instance::Instance {
match self._inner {
BackendInstance::Jsc(s) => s,
_ => panic!("Not a `jsc` global!"),
}
}
pub fn as_jsc(&self) -> &crate::backend::jsc::instance::Instance {
match self._inner {
BackendInstance::Jsc(ref s) => s,
_ => panic!("Not a `jsc` global!"),
}
}
pub fn as_jsc_mut(&mut self) -> &mut crate::backend::jsc::instance::Instance {
match self._inner {
BackendInstance::Jsc(ref mut s) => s,
_ => panic!("Not a `jsc` global!"),
}
}
}