Skip to content

Commit

Permalink
WIP: Change Export to VMExtern, fix all remaining functions
Browse files Browse the repository at this point in the history
  • Loading branch information
fschutt committed Aug 25, 2022
1 parent 42cbe14 commit 678971c
Show file tree
Hide file tree
Showing 7 changed files with 130 additions and 172 deletions.
11 changes: 10 additions & 1 deletion lib/api/src/js/error.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::js::lib::std::string::String;
use crate::js::trap::RuntimeError;
use crate::js::trap::{RuntimeError, WasmerRuntimeError};
#[cfg(feature = "std")]
use std::borrow::Cow;
#[cfg(feature = "std")]
Expand Down Expand Up @@ -199,6 +199,15 @@ pub enum InstantiationError {
/// A generic error occured while invoking API functions
#[cfg_attr(feature = "std", error(transparent))]
Wasm(WasmError),

#[cfg_attr(feature = "std", error(transparent))]
Runtime(WasmerRuntimeError),
}

impl From<WasmerRuntimeError> for InstantiationError {
fn from(original: WasmerRuntimeError) -> Self {
Self::Runtime(original)
}
}

impl From<WasmError> for InstantiationError {
Expand Down
96 changes: 0 additions & 96 deletions lib/api/src/js/export.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,99 +86,3 @@ impl fmt::Debug for VMFunction {
.finish()
}
}

/// The value of an export passed from one instance to another.
#[derive(Debug, Clone)]
pub enum Export {
/// A function export value.
Function(InternalStoreHandle<VMFunction>),

/// A table export value.
Table(InternalStoreHandle<VMTable>),

/// A memory export value.
Memory(InternalStoreHandle<VMMemory>),

/// A global export value.
Global(InternalStoreHandle<VMGlobal>),
}

impl Export {
/// Return the export as a `JSValue`.
pub fn as_jsvalue<'context>(&self, store: &'context impl AsStoreRef) -> &'context JsValue {
match self {
Self::Memory(js_wasm_memory) => js_wasm_memory
.get(store.as_store_ref().objects())
.memory
.as_ref(),
Self::Function(js_func) => js_func
.get(store.as_store_ref().objects())
.function
.as_ref(),
Self::Table(js_wasm_table) => js_wasm_table
.get(store.as_store_ref().objects())
.table
.as_ref(),
Self::Global(js_wasm_global) => js_wasm_global
.get(store.as_store_ref().objects())
.global
.as_ref(),
}
}

/// Convert a `JsValue` into an `Export` within a given `Context`.
pub fn from_js_value(
val: JsValue,
store: &mut impl AsStoreMut,
extern_type: ExternType,
) -> Result<Self, WasmError> {
match extern_type {
ExternType::Memory(memory_type) => {
if val.is_instance_of::<Memory>() {
Ok(Self::Memory(InternalStoreHandle::new(
&mut store.objects_mut(),
VMMemory::new(val.unchecked_into::<Memory>(), memory_type),
)))
} else {
Err(WasmError::TypeMismatch(
val.js_typeof()
.as_string()
.map(Into::into)
.unwrap_or("unknown".into()),
"Memory".into(),
))
}
}
ExternType::Global(global_type) => {
if val.is_instance_of::<Global>() {
Ok(Self::Global(InternalStoreHandle::new(
&mut store.objects_mut(),
VMGlobal::new(val.unchecked_into::<Global>(), global_type),
)))
} else {
panic!("Extern type doesn't match js value type");
}
}
ExternType::Function(function_type) => {
if val.is_instance_of::<Function>() {
Ok(Self::Function(InternalStoreHandle::new(
&mut store.objects_mut(),
VMFunction::new(val.unchecked_into::<Function>(), function_type),
)))
} else {
panic!("Extern type doesn't match js value type");
}
}
ExternType::Table(table_type) => {
if val.is_instance_of::<Table>() {
Ok(Self::Table(InternalStoreHandle::new(
&mut store.objects_mut(),
VMTable::new(val.unchecked_into::<Table>(), table_type),
)))
} else {
panic!("Extern type doesn't match js value type");
}
}
}
}
}
112 changes: 94 additions & 18 deletions lib/api/src/js/externals/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,24 @@ pub(crate) mod memory;
pub(crate) mod memory_view;
mod table;

pub use self::function::{FromToNativeWasmType, Function, HostFunction, WasmTypeList};
pub use self::global::Global;
pub use self::memory::{Memory, MemoryError};
pub use self::function::{FromToNativeWasmType, HostFunction, WasmTypeList};
pub use self::memory::MemoryError;
pub use self::memory_view::MemoryView;
pub use self::table::Table;
pub use self::memory::Memory as CrateMemory;
pub use self::global::Global as CrateGlobal;
pub use self::function::Function as CrateFunction;
pub use self::table::Table as CrateTable;

use crate::js::export::{Export, VMFunction, VMGlobal, VMMemory, VMTable};
use crate::js::export::{VMFunction, VMGlobal, VMMemory, VMTable};
use crate::js::exports::{ExportError, Exportable};
use crate::js::store::InternalStoreHandle;
use crate::js::store::StoreObject;
use crate::js::store::{AsStoreMut, AsStoreRef};
use crate::js::types::AsJs;
use crate::js::ExternType;
use crate::js::error::WasmError;
use js_sys::WebAssembly::Memory as JsSysMemory;
use wasm_bindgen::{JsValue, JsCast};
use std::fmt;

/// The value of an export passed from one instance to another.
Expand All @@ -34,6 +39,86 @@ pub enum VMExtern {
Global(InternalStoreHandle<VMGlobal>),
}

impl VMExtern {
/// Return the export as a `JSValue`.
pub fn as_jsvalue<'context>(&self, store: &'context impl AsStoreRef) -> &'context JsValue {
match self {
Self::Memory(js_wasm_memory) => js_wasm_memory
.get(store.as_store_ref().objects())
.memory
.as_ref(),
Self::Function(js_func) => js_func
.get(store.as_store_ref().objects())
.function
.as_ref(),
Self::Table(js_wasm_table) => js_wasm_table
.get(store.as_store_ref().objects())
.table
.as_ref(),
Self::Global(js_wasm_global) => js_wasm_global
.get(store.as_store_ref().objects())
.global
.as_ref(),
}
}

/// Convert a `JsValue` into an `Export` within a given `Context`.
pub fn from_js_value(
val: JsValue,
store: &mut impl AsStoreMut,
extern_type: ExternType,
) -> Result<Self, WasmError> {
match extern_type {
ExternType::Memory(memory_type) => {
if val.is_instance_of::<JsSysMemory>() {
Ok(Self::Memory(InternalStoreHandle::new(
&mut store.objects_mut(),
VMMemory::new(val.unchecked_into::<Memory>(), memory_type),
)))
} else {
Err(WasmError::TypeMismatch(
val.js_typeof()
.as_string()
.map(Into::into)
.unwrap_or("unknown".into()),
"Memory".into(),
))
}
}
ExternType::Global(global_type) => {
if val.is_instance_of::<Global>() {
Ok(Self::Global(InternalStoreHandle::new(
&mut store.objects_mut(),
VMGlobal::new(val.unchecked_into::<Global>(), global_type),
)))
} else {
panic!("Extern type doesn't match js value type");
}
}
ExternType::Function(function_type) => {
if val.is_instance_of::<Function>() {
Ok(Self::Function(InternalStoreHandle::new(
&mut store.objects_mut(),
VMFunction::new(val.unchecked_into::<Function>(), function_type),
)))
} else {
panic!("Extern type doesn't match js value type");
}
}
ExternType::Table(table_type) => {
if val.is_instance_of::<Table>() {
Ok(Self::Table(InternalStoreHandle::new(
&mut store.objects_mut(),
VMTable::new(val.unchecked_into::<Table>(), table_type),
)))
} else {
panic!("Extern type doesn't match js value type");
}
}
}
}
}

/// An `Extern` is the runtime representation of an entity that
/// can be imported or exported.
///
Expand Down Expand Up @@ -90,24 +175,15 @@ impl Extern {
Self::Table(val) => val.is_from_store(store),
}
}

fn to_export(&self) -> Export {
match self {
Self::Function(val) => Export::Function(val.handle.internal_handle()),
Self::Memory(val) => Export::Memory(val.handle.internal_handle()),
Self::Global(val) => Export::Global(val.handle.internal_handle()),
Self::Table(val) => Export::Table(val.handle.internal_handle()),
}
}
}

impl AsJs for Extern {
fn as_jsvalue(&self, store: &impl AsStoreRef) -> wasm_bindgen::JsValue {
match self {
Self::Function(_) => self.to_export().as_jsvalue(store),
Self::Global(_) => self.to_export().as_jsvalue(store),
Self::Table(_) => self.to_export().as_jsvalue(store),
Self::Memory(_) => self.to_export().as_jsvalue(store),
Self::Function(_) => self.to_vm_extern().as_jsvalue(store),
Self::Global(_) => self.to_vm_extern().as_jsvalue(store),
Self::Table(_) => self.to_vm_extern().as_jsvalue(store),
Self::Memory(_) => self.to_vm_extern().as_jsvalue(store),
}
.clone()
}
Expand Down
35 changes: 9 additions & 26 deletions lib/api/src/js/instance.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use crate::js::error::InstantiationError;
use crate::js::export::Export;
use crate::js::exports::Exports;
use crate::js::externals::Extern;
use crate::js::externals::{Extern, VMExtern};
use crate::js::imports::Imports;
use crate::js::module::Module;
use crate::js::store::{AsStoreMut, AsStoreRef, StoreHandle};
Expand Down Expand Up @@ -90,25 +89,11 @@ impl Instance {
module: &Module,
externs: &[Extern],
) -> Result<Self, InstantiationError> {
let imports = externs.to_vec();
let mut handle = module.instantiate(store, &imports)?;
let exports = module
.exports()
.map(|export| {
let name = export.name().to_string();
let export = handle.lookup(&name).expect("export");
let extern_ = Extern::from_vm_extern(store, export);
(name, extern_)
})
.collect::<Exports>();

let instance = Self {
_handle: StoreHandle::new(store.objects_mut(), handle),
module: module.clone(),
exports,
};

Ok(instance)
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)
}

/// Creates a Wasmer `Instance` from a Wasmer `Module` and a WebAssembly Instance
Expand Down Expand Up @@ -139,12 +124,10 @@ impl Instance {
&name
))
})?;
let export: Export =
Export::from_js_value(js_export, &mut store, extern_type)?.into();
let extern_ = Extern::from_vm_extern(&mut store, export);
Ok((name.to_string(), extern_))

Ok((name.to_string(), ))
})
.collect::<Result<Exports, InstantiationError>>()?;
.collect::<Result<Vec<VMExtern>, InstantiationError>>()?;

Ok(Self {
_handle: instance,
Expand Down
5 changes: 4 additions & 1 deletion lib/api/src/js/js_import_object.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::js::error::WasmError;
use crate::js::store::AsStoreMut;
use crate::js::{Export, ExternType, Module};
use crate::js::{ExternType, Module};
use crate::js::externals::VMExtern;
use std::collections::HashMap;

/// This struct is used in case you want to create an `Instance`
Expand Down Expand Up @@ -43,6 +44,7 @@ impl JsImportObject {
}
}

/*
/// Gets an export given a module and a name
///
/// # Usage
Expand Down Expand Up @@ -74,6 +76,7 @@ impl JsImportObject {
))),
}
}
*/
}

impl Into<js_sys::Object> for JsImportObject {
Expand Down
3 changes: 1 addition & 2 deletions lib/api/src/js/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,10 @@ mod value;
mod wasm_bindgen_polyfill;

pub use crate::js::error::{DeserializeError, InstantiationError, SerializeError};
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, MemoryView,
Table, WasmTypeList,
Table, WasmTypeList, VMExtern,
};
pub use crate::js::function_env::{FunctionEnv, FunctionEnvMut};
pub use crate::js::imports::Imports;
Expand Down
Loading

0 comments on commit 678971c

Please sign in to comment.