mirror of
https://github.com/mii443/wasmer.git
synced 2025-12-13 13:58:38 +00:00
Updated js-api to latest
This commit is contained in:
@@ -8,74 +8,36 @@ use std::marker::PhantomData;
|
||||
use js_sys::Uint8Array;
|
||||
use wasm_bindgen::JsValue;
|
||||
|
||||
/// A mutable memory location.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// In this example, you can see that `WasmCell<T>` enables mutation inside an
|
||||
/// immutable struct. In other words, it enables "interior mutability".
|
||||
///
|
||||
/// ```
|
||||
/// use wasmer::WasmCell;
|
||||
///
|
||||
/// struct SomeStruct {
|
||||
/// regular_field: u8,
|
||||
/// special_field: WasmCell<u8>,
|
||||
/// }
|
||||
///
|
||||
/// let my_struct = SomeStruct {
|
||||
/// regular_field: 0,
|
||||
/// special_field: WasmCell::new(1),
|
||||
/// };
|
||||
///
|
||||
/// let new_value = 100;
|
||||
///
|
||||
/// // ERROR: `my_struct` is immutable
|
||||
/// // my_struct.regular_field = new_value;
|
||||
///
|
||||
/// // WORKS: although `my_struct` is immutable, `special_field` is a `WasmCell`,
|
||||
/// // which can always be mutated
|
||||
/// my_struct.special_field.set(new_value);
|
||||
/// assert_eq!(my_struct.special_field.get(), new_value);
|
||||
/// ```
|
||||
///
|
||||
/// See the [module-level documentation](self) for more.
|
||||
#[derive(Clone)]
|
||||
pub struct WasmCell<T: ?Sized> {
|
||||
/// A mutable Wasm-memory location.
|
||||
pub struct WasmCell<'a, T: ?Sized> {
|
||||
pub(crate) memory: Uint8Array,
|
||||
phantom: PhantomData<T>,
|
||||
phantom: &'a PhantomData<T>,
|
||||
}
|
||||
|
||||
unsafe impl<T: ?Sized> Send for WasmCell<T> where T: Send {}
|
||||
unsafe impl<T: ?Sized> Send for WasmCell<'_, T> where T: Send {}
|
||||
|
||||
unsafe impl<T: ?Sized> Sync for WasmCell<T> {}
|
||||
unsafe impl<T: ?Sized> Sync for WasmCell<'_, T> {}
|
||||
|
||||
// impl<T: Copy> Clone for WasmCell<T> {
|
||||
// #[inline]
|
||||
// fn clone(&self) -> WasmCell<T> {
|
||||
// WasmCell::new(self.get())
|
||||
// }
|
||||
// }
|
||||
|
||||
impl<T: Default> Default for WasmCell<T> {
|
||||
/// Creates a `WasmCell<T>`, with the `Default` value for T.
|
||||
impl<'a, T: Copy> Clone for WasmCell<'a, T> {
|
||||
#[inline]
|
||||
fn default() -> WasmCell<T> {
|
||||
unimplemented!()
|
||||
// WasmCell::new(Default::default())
|
||||
fn clone(&self) -> WasmCell<'a, T> {
|
||||
WasmCell {
|
||||
memory: self.memory.clone(),
|
||||
phantom: &PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: PartialEq + Copy> PartialEq for WasmCell<T> {
|
||||
impl<T: PartialEq + Copy> PartialEq for WasmCell<'_, T> {
|
||||
#[inline]
|
||||
fn eq(&self, other: &WasmCell<T>) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Eq + Copy> Eq for WasmCell<T> {}
|
||||
impl<T: Eq + Copy> Eq for WasmCell<'_, T> {}
|
||||
|
||||
impl<T: PartialOrd + Copy> PartialOrd for WasmCell<T> {
|
||||
impl<T: PartialOrd + Copy> PartialOrd for WasmCell<'_, T> {
|
||||
#[inline]
|
||||
fn partial_cmp(&self, other: &WasmCell<T>) -> Option<Ordering> {
|
||||
self.get().partial_cmp(&other.get())
|
||||
@@ -102,118 +64,46 @@ impl<T: PartialOrd + Copy> PartialOrd for WasmCell<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Ord + Copy> Ord for WasmCell<T> {
|
||||
impl<T: Ord + Copy> Ord for WasmCell<'_, T> {
|
||||
#[inline]
|
||||
fn cmp(&self, other: &WasmCell<T>) -> Ordering {
|
||||
self.get().cmp(&other.get())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<T> for WasmCell<T> {
|
||||
fn from(t: T) -> WasmCell<T> {
|
||||
unimplemented!();
|
||||
// WasmCell::new(t)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> WasmCell<T> {
|
||||
impl<'a, T> WasmCell<'a, T> {
|
||||
/// Creates a new `WasmCell` containing the given value.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::cell::Cell;
|
||||
/// use wasmer::WasmCell;
|
||||
///
|
||||
/// let c = WasmCell::new(5);
|
||||
/// let cell = Cell::new(5);
|
||||
/// let wasm_cell = WasmCell::new(&cell);
|
||||
/// ```
|
||||
#[inline]
|
||||
pub const fn new(memory: Uint8Array) -> WasmCell<T> {
|
||||
// WasmCell { value: UnsafeWasmCell::new(value) }
|
||||
pub const fn new(memory: Uint8Array) -> WasmCell<'a, T> {
|
||||
WasmCell {
|
||||
memory,
|
||||
phantom: PhantomData,
|
||||
phantom: &PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/// Swaps the values of two WasmCells.
|
||||
/// Difference with `std::mem::swap` is that this function doesn't require `&mut` reference.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use wasmer::WasmCell;
|
||||
///
|
||||
/// let c1 = WasmCell::new(5i32);
|
||||
/// let c2 = WasmCell::new(10i32);
|
||||
/// c1.swap(&c2);
|
||||
/// assert_eq!(10, c1.get());
|
||||
/// assert_eq!(5, c2.get());
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn swap(&self, other: &Self) {
|
||||
unimplemented!();
|
||||
// if ptr::eq(self, other) {
|
||||
// return;
|
||||
// }
|
||||
// // SAFETY: This can be risky if called from separate threads, but `WasmCell`
|
||||
// // is `!Sync` so this won't happen. This also won't invalidate any
|
||||
// // pointers since `WasmCell` makes sure nothing else will be pointing into
|
||||
// // either of these `WasmCell`s.
|
||||
// unsafe {
|
||||
// ptr::swap(self.value.get(), other.value.get());
|
||||
// }
|
||||
}
|
||||
|
||||
/// Replaces the contained value with `val`, and returns the old contained value.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use wasmer::WasmCell;
|
||||
///
|
||||
/// let cell = WasmCell::new(5);
|
||||
/// assert_eq!(cell.get(), 5);
|
||||
/// assert_eq!(cell.replace(10), 5);
|
||||
/// assert_eq!(cell.get(), 10);
|
||||
/// ```
|
||||
pub fn replace(&self, val: T) -> T {
|
||||
unimplemented!();
|
||||
// SAFETY: This can cause data races if called from a separate thread,
|
||||
// but `WasmCell` is `!Sync` so this won't happen.
|
||||
// mem::replace(unsafe { &mut *self.value.get() }, val)
|
||||
}
|
||||
|
||||
// /// Unwraps the value.
|
||||
// ///
|
||||
// /// # Examples
|
||||
// ///
|
||||
// /// ```
|
||||
// /// use wasmer::WasmCell;
|
||||
// ///
|
||||
// /// let c = WasmCell::new(5);
|
||||
// /// let five = c.into_inner();
|
||||
// ///
|
||||
// /// assert_eq!(five, 5);
|
||||
// /// ```
|
||||
// pub const fn into_inner(self) -> T {
|
||||
// // This will get the item out of the MemoryView and into
|
||||
// // Rust memory allocator
|
||||
// unimplemented!()
|
||||
// // self.get()
|
||||
// }
|
||||
}
|
||||
|
||||
impl<T: Copy> WasmCell<T> {
|
||||
impl<'a, T: Copy> WasmCell<'a, T> {
|
||||
/// Returns a copy of the contained value.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::cell::Cell;
|
||||
/// use wasmer::WasmCell;
|
||||
///
|
||||
/// let c = WasmCell::new(5);
|
||||
///
|
||||
/// let five = c.get();
|
||||
/// let cell = Cell::new(5);
|
||||
/// let wasm_cell = WasmCell::new(&cell);
|
||||
/// let five = wasm_cell.get();
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn get(&self) -> T {
|
||||
@@ -222,44 +112,47 @@ impl<T: Copy> WasmCell<T> {
|
||||
// unimplemented!();
|
||||
}
|
||||
|
||||
/// Updates the contained value using a function and returns the new value.
|
||||
/// Get an unsafe mutable pointer to the inner item
|
||||
/// in the Cell.
|
||||
///
|
||||
/// # Examples
|
||||
/// # Safety
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(cell_update)]
|
||||
/// This method is highly discouraged to use. We have it for
|
||||
/// compatibility reasons with Emscripten.
|
||||
/// It is unsafe because changing an item inline will change
|
||||
/// the underlying memory.
|
||||
///
|
||||
/// use wasmer::WasmCell;
|
||||
///
|
||||
/// let c = WasmCell::new(5);
|
||||
/// let new = c.update(|x| x + 1);
|
||||
///
|
||||
/// assert_eq!(new, 6);
|
||||
/// assert_eq!(c.get(), 6);
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn update<F>(&self, f: F) -> T
|
||||
where
|
||||
F: FnOnce(T) -> T,
|
||||
{
|
||||
let old = self.get();
|
||||
let new = f(old);
|
||||
self.set(new);
|
||||
new
|
||||
/// It's highly encouraged to use the `set` method instead.
|
||||
#[deprecated(
|
||||
since = "2.0.0",
|
||||
note = "Please use the memory-safe set method instead"
|
||||
)]
|
||||
#[doc(hidden)]
|
||||
pub unsafe fn get_mut(&self) -> &'a mut T {
|
||||
&mut *self.inner.as_ptr()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Sized> WasmCell<T> {
|
||||
impl<T: Debug> Debug for WasmCell<'_, T> {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.get().fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Sized> WasmCell<'_, T> {
|
||||
/// Sets the contained value.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::cell::Cell;
|
||||
/// use wasmer::WasmCell;
|
||||
///
|
||||
/// let c = WasmCell::new(5);
|
||||
///
|
||||
/// c.set(10);
|
||||
/// let cell = Cell::new(5);
|
||||
/// let wasm_cell = WasmCell::new(&cell);
|
||||
/// wasm_cell.set(10);
|
||||
/// assert_eq!(cell.get(), 10);
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn set(&self, val: T) {
|
||||
@@ -269,98 +162,3 @@ impl<T: Sized> WasmCell<T> {
|
||||
self.memory.copy_from(slice);
|
||||
}
|
||||
}
|
||||
// /// Returns a raw pointer to the underlying data in this cell.
|
||||
// ///
|
||||
// /// # Examples
|
||||
// ///
|
||||
// /// ```
|
||||
// /// use wasmer::WasmCell;
|
||||
// ///
|
||||
// /// let c = WasmCell::new(5);
|
||||
// ///
|
||||
// /// let ptr = c.as_ptr();
|
||||
// /// ```
|
||||
// #[inline]
|
||||
// pub const fn as_ptr(&self) -> *mut T {
|
||||
// self.value.get()
|
||||
// }
|
||||
|
||||
// /// Returns a mutable reference to the underlying data.
|
||||
// ///
|
||||
// /// This call borrows `WasmCell` mutably (at compile-time) which guarantees
|
||||
// /// that we possess the only reference.
|
||||
// ///
|
||||
// /// # Examples
|
||||
// ///
|
||||
// /// ```
|
||||
// /// use wasmer::WasmCell;
|
||||
// ///
|
||||
// /// let mut c = WasmCell::new(5);
|
||||
// /// *c.get_mut() += 1;
|
||||
// ///
|
||||
// /// assert_eq!(c.get(), 6);
|
||||
// /// ```
|
||||
// #[inline]
|
||||
// pub fn get_mut(&mut self) -> &mut T {
|
||||
// self.value.get_mut()
|
||||
// }
|
||||
|
||||
// /// Returns a `&WasmCell<T>` from a `&mut T`
|
||||
// ///
|
||||
// /// # Examples
|
||||
// ///
|
||||
// /// ```
|
||||
// /// use wasmer::WasmCell;
|
||||
// ///
|
||||
// /// let slice: &mut [i32] = &mut [1, 2, 3];
|
||||
// /// let cell_slice: &WasmCell<[i32]> = WasmCell::from_mut(slice);
|
||||
// /// let slice_cell: &[WasmCell<i32>] = cell_slice.as_slice_of_cells();
|
||||
// ///
|
||||
// /// assert_eq!(slice_cell.len(), 3);
|
||||
// /// ```
|
||||
// #[inline]
|
||||
// pub fn from_mut(t: &mut T) -> &WasmCell<T> {
|
||||
// // SAFETY: `&mut` ensures unique access.
|
||||
// unsafe { &*(t as *mut T as *const WasmCell<T>) }
|
||||
// }
|
||||
// }
|
||||
|
||||
// impl<T: Default> WasmCell<T> {
|
||||
// /// Takes the value of the cell, leaving `Default::default()` in its place.
|
||||
// ///
|
||||
// /// # Examples
|
||||
// ///
|
||||
// /// ```
|
||||
// /// use wasmer::WasmCell;
|
||||
// ///
|
||||
// /// let c = WasmCell::new(5);
|
||||
// /// let five = c.take();
|
||||
// ///
|
||||
// /// assert_eq!(five, 5);
|
||||
// /// assert_eq!(c.into_inner(), 0);
|
||||
// /// ```
|
||||
// pub fn take(&self) -> T {
|
||||
// self.replace(Default::default())
|
||||
// }
|
||||
// }
|
||||
|
||||
impl<T> WasmCell<[T]> {
|
||||
/// Returns a `&[WasmCell<T>]` from a `&WasmCell<[T]>`
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use wasmer::WasmCell;
|
||||
///
|
||||
/// let slice: &mut [i32] = &mut [1, 2, 3];
|
||||
/// let cell_slice: &WasmCell<[i32]> = WasmCell::from_mut(slice);
|
||||
/// let slice_cell: &[WasmCell<i32>] = cell_slice.as_slice_of_cells();
|
||||
///
|
||||
/// assert_eq!(slice_cell.len(), 3);
|
||||
/// ```
|
||||
pub fn as_slice_of_cells(&self) -> &[WasmCell<T>] {
|
||||
unimplemented!();
|
||||
// SAFETY: `WasmCell<T>` has the same memory layout as `T`.
|
||||
// unsafe { &*(self as *const WasmCell<[T]> as *const [WasmCell<T>]) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,7 +82,11 @@ impl From<ExportError> for HostEnvInitError {
|
||||
/// When implementing the trait manually, it's important to get a "weak" export to
|
||||
/// prevent a cyclic reference leaking memory. You can access a "weak" export with
|
||||
/// a method like `get_with_generics_weak`.
|
||||
pub trait WasmerEnv: Clone + Send + Sync {
|
||||
|
||||
pub trait WasmerEnv {
|
||||
// TODO: Had to not use Clone here
|
||||
// pub trait WasmerEnv: Clone + Send + Sync {
|
||||
|
||||
/// The function that Wasmer will call on your type to let it finish
|
||||
/// setting up the environment with data from the `Instance`.
|
||||
///
|
||||
|
||||
@@ -1,10 +1,50 @@
|
||||
use crate::instance::Instance;
|
||||
use crate::WasmerEnv;
|
||||
use core::any::TypeId;
|
||||
use js_sys::Function;
|
||||
use js_sys::WebAssembly::Memory;
|
||||
use std::any::Any;
|
||||
use std::cell::RefCell;
|
||||
use std::fmt;
|
||||
use std::sync::Arc;
|
||||
use wasm_bindgen::JsCast;
|
||||
use wasm_bindgen::JsValue;
|
||||
|
||||
pub type VMMemory = Memory;
|
||||
pub type VMFunction = Function;
|
||||
#[derive(Clone)]
|
||||
pub struct VMFunction {
|
||||
pub(crate) function: Function,
|
||||
pub(crate) environment: Option<Arc<RefCell<Box<dyn WasmerEnv>>>>,
|
||||
}
|
||||
|
||||
impl VMFunction {
|
||||
pub(crate) fn new(function: Function, environment: Option<Box<dyn WasmerEnv>>) -> Self {
|
||||
Self {
|
||||
function,
|
||||
environment: environment.map(|env| Arc::new(RefCell::new(env))),
|
||||
}
|
||||
}
|
||||
pub(crate) fn init_envs(&self, instance: &Instance) {
|
||||
if let Some(env) = &self.environment {
|
||||
let mut borrowed_env = env.borrow_mut();
|
||||
borrowed_env.init_with_instance(instance);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for VMFunction {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.function == other.function
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for VMFunction {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("VMFunction")
|
||||
.field("function", &self.function)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
/// The value of an export passed from one instance to another.
|
||||
#[derive(Debug, Clone)]
|
||||
@@ -24,7 +64,7 @@ impl Export {
|
||||
pub fn as_jsvalue(&self) -> &JsValue {
|
||||
match self {
|
||||
Export::Memory(js_wasm_memory) => js_wasm_memory.as_ref(),
|
||||
Export::Function(js_func) => js_func.as_ref(),
|
||||
Export::Function(js_func) => js_func.function.as_ref(),
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
@@ -32,12 +72,12 @@ impl Export {
|
||||
|
||||
impl From<JsValue> for Export {
|
||||
fn from(val: JsValue) -> Export {
|
||||
if val.is_instance_of::<VMMemory>() {
|
||||
return Export::Memory(val.unchecked_into::<VMMemory>());
|
||||
if val.is_instance_of::<Memory>() {
|
||||
return Export::Memory(val.unchecked_into::<Memory>());
|
||||
}
|
||||
// Leave this last
|
||||
else if val.is_instance_of::<VMFunction>() {
|
||||
return Export::Function(val.unchecked_into::<VMFunction>());
|
||||
else if val.is_instance_of::<Function>() {
|
||||
return Export::Function(VMFunction::new(val.unchecked_into::<Function>(), None));
|
||||
}
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ use crate::export::Export;
|
||||
use crate::externals::{Extern, Function /* , Global, Table */, Memory};
|
||||
use crate::import_object::LikeNamespace;
|
||||
// use crate::native::NativeFunc;
|
||||
// use crate::WasmTypeList;
|
||||
use crate::WasmTypeList;
|
||||
use indexmap::IndexMap;
|
||||
use std::fmt;
|
||||
use std::iter::{ExactSizeIterator, FromIterator};
|
||||
@@ -153,31 +153,30 @@ impl Exports {
|
||||
// .map_err(|_| ExportError::IncompatibleType)
|
||||
// }
|
||||
|
||||
// /// Hack to get this working with nativefunc too
|
||||
// pub fn get_with_generics<'a, T, Args, Rets>(&'a self, name: &str) -> Result<T, ExportError>
|
||||
// where
|
||||
// Args: WasmTypeList,
|
||||
// Rets: WasmTypeList,
|
||||
// T: ExportableWithGenerics<'a, Args, Rets>,
|
||||
// {
|
||||
// match self.map.get(name) {
|
||||
// None => Err(ExportError::Missing(name.to_string())),
|
||||
// Some(extern_) => T::get_self_from_extern_with_generics(extern_),
|
||||
// }
|
||||
// }
|
||||
/// Hack to get this working with nativefunc too
|
||||
pub fn get_with_generics<'a, T, Args, Rets>(&'a self, name: &str) -> Result<T, ExportError>
|
||||
where
|
||||
Args: WasmTypeList,
|
||||
Rets: WasmTypeList,
|
||||
T: ExportableWithGenerics<'a, Args, Rets>,
|
||||
{
|
||||
match self.map.get(name) {
|
||||
None => Err(ExportError::Missing(name.to_string())),
|
||||
Some(extern_) => T::get_self_from_extern_with_generics(extern_),
|
||||
}
|
||||
}
|
||||
|
||||
// /// Like `get_with_generics` but with a WeakReference to the `InstanceRef` internally.
|
||||
// /// This is useful for passing data into `WasmerEnv`, for example.
|
||||
// pub fn get_with_generics_weak<'a, T, Args, Rets>(&'a self, name: &str) -> Result<T, ExportError>
|
||||
// where
|
||||
// Args: WasmTypeList,
|
||||
// Rets: WasmTypeList,
|
||||
// T: ExportableWithGenerics<'a, Args, Rets>,
|
||||
// {
|
||||
// let mut out: T = self.get_with_generics(name)?;
|
||||
// out.into_weak_instance_ref();
|
||||
// Ok(out)
|
||||
// }
|
||||
/// Like `get_with_generics` but with a WeakReference to the `InstanceRef` internally.
|
||||
/// This is useful for passing data into `WasmerEnv`, for example.
|
||||
pub fn get_with_generics_weak<'a, T, Args, Rets>(&'a self, name: &str) -> Result<T, ExportError>
|
||||
where
|
||||
Args: WasmTypeList,
|
||||
Rets: WasmTypeList,
|
||||
T: ExportableWithGenerics<'a, Args, Rets>,
|
||||
{
|
||||
let mut out: T = self.get_with_generics(name)?;
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
/// Get an export as an `Extern`.
|
||||
pub fn get_extern(&self, name: &str) -> Option<&Extern> {
|
||||
@@ -307,33 +306,20 @@ pub trait Exportable<'a>: Sized {
|
||||
///
|
||||
/// [`Instance`]: crate::Instance
|
||||
fn get_self_from_extern(_extern: &'a Extern) -> Result<&'a Self, ExportError>;
|
||||
|
||||
/// Convert the extern internally to hold a weak reference to the `InstanceRef`.
|
||||
/// This is useful for preventing cycles, for example for data stored in a
|
||||
/// type implementing `WasmerEnv`.
|
||||
fn into_weak_instance_ref(&mut self);
|
||||
}
|
||||
|
||||
// /// A trait for accessing exports (like [`Exportable`]) but it takes generic
|
||||
// /// `Args` and `Rets` parameters so that `NativeFunc` can be accessed directly
|
||||
// /// as well.
|
||||
// pub trait ExportableWithGenerics<'a, Args: WasmTypeList, Rets: WasmTypeList>: Sized {
|
||||
// /// Get an export with the given generics.
|
||||
// fn get_self_from_extern_with_generics(_extern: &'a Extern) -> Result<Self, ExportError>;
|
||||
// /// Convert the extern internally to hold a weak reference to the `InstanceRef`.
|
||||
// /// This is useful for preventing cycles, for example for data stored in a
|
||||
// /// type implementing `WasmerEnv`.
|
||||
// fn into_weak_instance_ref(&mut self);
|
||||
// }
|
||||
/// A trait for accessing exports (like [`Exportable`]) but it takes generic
|
||||
/// `Args` and `Rets` parameters so that `NativeFunc` can be accessed directly
|
||||
/// as well.
|
||||
pub trait ExportableWithGenerics<'a, Args: WasmTypeList, Rets: WasmTypeList>: Sized {
|
||||
/// Get an export with the given generics.
|
||||
fn get_self_from_extern_with_generics(_extern: &'a Extern) -> Result<Self, ExportError>;
|
||||
}
|
||||
|
||||
// /// We implement it for all concrete [`Exportable`] types (that are `Clone`)
|
||||
// /// with empty `Args` and `Rets`.
|
||||
// impl<'a, T: Exportable<'a> + Clone + 'static> ExportableWithGenerics<'a, (), ()> for T {
|
||||
// fn get_self_from_extern_with_generics(_extern: &'a Extern) -> Result<Self, ExportError> {
|
||||
// T::get_self_from_extern(_extern).map(|i| i.clone())
|
||||
// }
|
||||
|
||||
// fn into_weak_instance_ref(&mut self) {
|
||||
// <Self as Exportable>::into_weak_instance_ref(self);
|
||||
// }
|
||||
// }
|
||||
/// We implement it for all concrete [`Exportable`] types (that are `Clone`)
|
||||
/// with empty `Args` and `Rets`.
|
||||
impl<'a, T: Exportable<'a> + Clone + 'static> ExportableWithGenerics<'a, (), ()> for T {
|
||||
fn get_self_from_extern_with_generics(_extern: &'a Extern) -> Result<Self, ExportError> {
|
||||
T::get_self_from_extern(_extern).map(|i| i.clone())
|
||||
}
|
||||
}
|
||||
|
||||
47
lib/js-api/src/externals/function.rs
vendored
47
lib/js-api/src/externals/function.rs
vendored
@@ -45,8 +45,8 @@ pub struct VMFunctionBody(u8);
|
||||
// #[derive(PartialEq)]
|
||||
pub struct Function {
|
||||
pub(crate) store: Store,
|
||||
ty: FunctionType,
|
||||
pub(crate) exported: VMFunction,
|
||||
pub(crate) environment: Option<*const u8>, // environment: Option<WasmRefCell<Box<Any>>>,
|
||||
}
|
||||
|
||||
impl PartialEq for Function {
|
||||
@@ -172,11 +172,11 @@ impl Function {
|
||||
let ft = wasm_bindgen::function_table();
|
||||
let as_table = ft.unchecked_ref::<js_sys::WebAssembly::Table>();
|
||||
let func = as_table.get(call_func_dynamic as usize as u32).unwrap();
|
||||
let environment = None;
|
||||
// let environment: Option<Arc>
|
||||
Self {
|
||||
store: store.clone(),
|
||||
exported: func,
|
||||
environment,
|
||||
ty: ty.into(),
|
||||
exported: VMFunction::new(func, None),
|
||||
}
|
||||
// Function::new
|
||||
// let wrapped_func =
|
||||
@@ -311,11 +311,11 @@ impl Function {
|
||||
let as_table = ft.unchecked_ref::<js_sys::WebAssembly::Table>();
|
||||
let func = as_table.get(address).unwrap();
|
||||
let binded_func = func.bind1(&JsValue::UNDEFINED, &JsValue::UNDEFINED);
|
||||
let environment = None;
|
||||
let ty = FunctionType::new(Args::wasm_types(), Rets::wasm_types());
|
||||
Self {
|
||||
store: store.clone(),
|
||||
exported: binded_func,
|
||||
environment,
|
||||
ty,
|
||||
exported: VMFunction::new(binded_func, None),
|
||||
}
|
||||
|
||||
// let vmctx = VMFunctionEnvironment {
|
||||
@@ -341,6 +341,11 @@ impl Function {
|
||||
// }
|
||||
}
|
||||
|
||||
// /// Get a reference to the Function environment, if any
|
||||
// pub fn get_host_env(&self) -> Option<&Any> {
|
||||
// self.environment.as_ref().map(|e|&**e)
|
||||
// }
|
||||
|
||||
/// Creates a new host `Function` from a native function and a provided environment.
|
||||
///
|
||||
/// The function signature is automatically retrieved using the
|
||||
@@ -380,17 +385,19 @@ impl Function {
|
||||
let ft = wasm_bindgen::function_table();
|
||||
let as_table = ft.unchecked_ref::<js_sys::WebAssembly::Table>();
|
||||
let func = as_table.get(address).unwrap();
|
||||
let ty = FunctionType::new(Args::wasm_types(), Rets::wasm_types());
|
||||
// let b: Box<Any> = Box::new(env);
|
||||
// let environment = Some(WasmRefCell::new(b));
|
||||
let environment = Box::into_raw(Box::new(env)) as *mut u8;
|
||||
let environment = Box::new(env);
|
||||
let binded_func = func.bind1(
|
||||
&JsValue::UNDEFINED,
|
||||
&JsValue::from_f64(environment as usize as f64),
|
||||
&JsValue::from_f64(&*environment as *const Env as *const u8 as usize as f64),
|
||||
);
|
||||
// panic!("Function env {:?}", environment.type_id());
|
||||
Self {
|
||||
store: store.clone(),
|
||||
exported: binded_func,
|
||||
environment: Some(environment),
|
||||
ty,
|
||||
exported: VMFunction::new(binded_func, Some(environment)),
|
||||
}
|
||||
|
||||
// let function = inner::Function::<Args, Rets>::new(func);
|
||||
@@ -590,8 +597,10 @@ impl Function {
|
||||
let js_value = param.as_jsvalue();
|
||||
arr.set(i as u32, js_value);
|
||||
}
|
||||
let result = js_sys::Reflect::apply(&self.exported, &wasm_bindgen::JsValue::NULL, &arr);
|
||||
Ok(vec![Val::F64(result.unwrap().as_f64().unwrap())].into_boxed_slice())
|
||||
let result =
|
||||
js_sys::Reflect::apply(&self.exported.function, &wasm_bindgen::JsValue::NULL, &arr);
|
||||
// Ok(vec![Val::F64(result.unwrap().as_f64().unwrap())].into_boxed_slice())
|
||||
Ok(Box::new([]))
|
||||
// if let Some(trampoline) = self.exported.vm_function.call_trampoline {
|
||||
// let mut results = vec![Val::null(); self.result_arity()];
|
||||
// self.call_wasm(trampoline, params, &mut results)?;
|
||||
@@ -602,11 +611,10 @@ impl Function {
|
||||
}
|
||||
|
||||
pub(crate) fn from_vm_export(store: &Store, wasmer_export: VMFunction) -> Self {
|
||||
let environment = None;
|
||||
Self {
|
||||
store: store.clone(),
|
||||
ty: FunctionType::new(vec![], vec![]),
|
||||
exported: wasmer_export,
|
||||
environment,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -750,15 +758,6 @@ impl<'a> Exportable<'a> for Function {
|
||||
_ => Err(ExportError::IncompatibleType),
|
||||
}
|
||||
}
|
||||
|
||||
fn into_weak_instance_ref(&mut self) {
|
||||
unimplemented!();
|
||||
// self.exported
|
||||
// .vm_function
|
||||
// .instance_ref
|
||||
// .as_mut()
|
||||
// .map(|v| *v = v.downgrade());
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for Function {
|
||||
|
||||
7
lib/js-api/src/externals/global.rs
vendored
7
lib/js-api/src/externals/global.rs
vendored
@@ -239,11 +239,4 @@ impl<'a> Exportable<'a> for Global {
|
||||
_ => Err(ExportError::IncompatibleType),
|
||||
}
|
||||
}
|
||||
|
||||
fn into_weak_instance_ref(&mut self) {
|
||||
self.vm_global
|
||||
.instance_ref
|
||||
.as_mut()
|
||||
.map(|v| *v = v.downgrade());
|
||||
}
|
||||
}
|
||||
|
||||
32
lib/js-api/src/externals/memory.rs
vendored
32
lib/js-api/src/externals/memory.rs
vendored
@@ -46,7 +46,7 @@ extern "C" {
|
||||
/// mutable from both host and WebAssembly.
|
||||
///
|
||||
/// Spec: <https://webassembly.github.io/spec/core/exec/runtime.html#memory-instances>
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Memory {
|
||||
store: Store,
|
||||
ty: MemoryType,
|
||||
@@ -300,18 +300,18 @@ impl Memory {
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for Memory {
|
||||
fn clone(&self) -> Self {
|
||||
unimplemented!();
|
||||
// let mut vm_memory = self.vm_memory.clone();
|
||||
// vm_memory.upgrade_instance_ref().unwrap();
|
||||
// impl Clone for Memory {
|
||||
// fn clone(&self) -> Self {
|
||||
// unimplemented!();
|
||||
// // let mut vm_memory = self.vm_memory.clone();
|
||||
// // vm_memory.upgrade_instance_ref().unwrap();
|
||||
|
||||
// Self {
|
||||
// store: self.store.clone(),
|
||||
// vm_memory,
|
||||
// }
|
||||
}
|
||||
}
|
||||
// // Self {
|
||||
// // store: self.store.clone(),
|
||||
// // vm_memory,
|
||||
// // }
|
||||
// }
|
||||
// }
|
||||
|
||||
impl<'a> Exportable<'a> for Memory {
|
||||
fn to_export(&self) -> Export {
|
||||
@@ -325,12 +325,4 @@ impl<'a> Exportable<'a> for Memory {
|
||||
_ => Err(ExportError::IncompatibleType),
|
||||
}
|
||||
}
|
||||
|
||||
fn into_weak_instance_ref(&mut self) {
|
||||
unimplemented!();
|
||||
// self.vm_memory
|
||||
// .instance_ref
|
||||
// .as_mut()
|
||||
// .map(|v| *v = v.downgrade());
|
||||
}
|
||||
}
|
||||
|
||||
9
lib/js-api/src/externals/mod.rs
vendored
9
lib/js-api/src/externals/mod.rs
vendored
@@ -69,15 +69,6 @@ impl<'a> Exportable<'a> for Extern {
|
||||
// Since this is already an extern, we can just return it.
|
||||
Ok(_extern)
|
||||
}
|
||||
|
||||
fn into_weak_instance_ref(&mut self) {
|
||||
match self {
|
||||
Self::Function(f) => f.into_weak_instance_ref(),
|
||||
// Self::Global(g) => g.into_weak_instance_ref(),
|
||||
Self::Memory(m) => m.into_weak_instance_ref(),
|
||||
// Self::Table(t) => t.into_weak_instance_ref(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl StoreObject for Extern {}
|
||||
|
||||
6
lib/js-api/src/externals/table.rs
vendored
6
lib/js-api/src/externals/table.rs
vendored
@@ -184,10 +184,4 @@ impl<'a> Exportable<'a> for Table {
|
||||
}
|
||||
}
|
||||
|
||||
fn into_weak_instance_ref(&mut self) {
|
||||
self.vm_table
|
||||
.instance_ref
|
||||
.as_mut()
|
||||
.map(|v| *v = v.downgrade());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,9 +109,9 @@ impl Instance {
|
||||
/// Those are, as defined by the spec:
|
||||
/// * Link errors that happen when plugging the imports into the instance
|
||||
/// * Runtime errors that happen when running the module `start` function.
|
||||
pub fn new(module: &Module, resolver: &dyn NamedResolver) -> Result<Self, InstantiationError> {
|
||||
pub fn new(module: &Module, resolver: &dyn Resolver) -> Result<Self, InstantiationError> {
|
||||
let store = module.store();
|
||||
let instance = module.instantiate(resolver).unwrap();
|
||||
let (instance, functions) = module.instantiate(resolver).unwrap();
|
||||
let instance_exports = instance.exports();
|
||||
let exports = module
|
||||
.exports()
|
||||
@@ -123,11 +123,15 @@ impl Instance {
|
||||
})
|
||||
.collect::<Exports>();
|
||||
|
||||
Ok(Self {
|
||||
let self_instance = Self {
|
||||
module: module.clone(),
|
||||
instance: instance,
|
||||
exports,
|
||||
})
|
||||
};
|
||||
for mut func in functions {
|
||||
func.init_envs(&self_instance);
|
||||
}
|
||||
Ok(self_instance)
|
||||
}
|
||||
|
||||
/// Gets the [`Module`] associated with this instance.
|
||||
|
||||
@@ -287,11 +287,11 @@ mod error;
|
||||
mod export;
|
||||
mod exports;
|
||||
mod externals;
|
||||
mod resolver;
|
||||
mod import_object;
|
||||
mod instance;
|
||||
mod iterators;
|
||||
mod module;
|
||||
mod resolver;
|
||||
// mod native;
|
||||
mod ptr;
|
||||
mod store;
|
||||
@@ -303,6 +303,7 @@ mod utils;
|
||||
/// See the [`WasmerEnv`] trait for more information.
|
||||
pub use wasmer_derive::WasmerEnv;
|
||||
|
||||
pub use crate::cell::WasmCell;
|
||||
pub use crate::env::{HostEnvInitError, LazyInit, WasmerEnv};
|
||||
pub use crate::exports::{ExportError, Exportable, Exports, ExportsIterator};
|
||||
pub use crate::externals::{
|
||||
@@ -316,6 +317,8 @@ pub use crate::module::Module;
|
||||
pub use wasm_bindgen::JsValue as RuntimeError;
|
||||
// pub use crate::native::NativeFunc;
|
||||
pub use crate::ptr::{Array, Item, WasmPtr};
|
||||
pub use crate::resolver::{ChainableNamedResolver, NamedResolver, NamedResolverChain, Resolver};
|
||||
|
||||
pub use crate::store::{Store, StoreObject};
|
||||
pub use crate::types::{
|
||||
ExportType, ExternType, FunctionType, GlobalType, ImportType, MemoryType, Mutability,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use crate::export::{Export, VMFunction};
|
||||
use crate::iterators::{ExportsIterator, ImportsIterator};
|
||||
use crate::resolver::{NamedResolver, Resolver};
|
||||
use crate::resolver::Resolver;
|
||||
use crate::store::Store;
|
||||
use crate::types::{ExportType, ImportType};
|
||||
// use crate::InstantiationError;
|
||||
@@ -175,12 +176,13 @@ impl Module {
|
||||
|
||||
pub(crate) fn instantiate(
|
||||
&self,
|
||||
resolver: &dyn NamedResolver,
|
||||
) -> Result<WebAssembly::Instance, ()> {
|
||||
resolver: &dyn Resolver,
|
||||
) -> Result<(WebAssembly::Instance, Vec<VMFunction>), ()> {
|
||||
let imports = js_sys::Object::new();
|
||||
for import_type in self.imports() {
|
||||
let mut functions: Vec<VMFunction> = vec![];
|
||||
for (i, import_type) in self.imports().enumerate() {
|
||||
let resolved_import =
|
||||
resolver.resolve_by_name(import_type.module(), import_type.name());
|
||||
resolver.resolve(i as u32, import_type.module(), import_type.name());
|
||||
if let Some(import) = resolved_import {
|
||||
match js_sys::Reflect::get(&imports, &import_type.module().into()) {
|
||||
Ok(val) => {
|
||||
@@ -192,6 +194,7 @@ impl Module {
|
||||
import.as_jsvalue(),
|
||||
);
|
||||
} else {
|
||||
// If the namespace doesn't exist
|
||||
let import_namespace = js_sys::Object::new();
|
||||
js_sys::Reflect::set(
|
||||
&import_namespace,
|
||||
@@ -207,9 +210,17 @@ impl Module {
|
||||
}
|
||||
Err(_) => return Err(()),
|
||||
};
|
||||
if let Export::Function(func) = import {
|
||||
functions.push(func);
|
||||
}
|
||||
}
|
||||
// in case the import is not found, the JS Wasm VM will handle
|
||||
// the error for us, so we don't need to handle it
|
||||
}
|
||||
Ok(WebAssembly::Instance::new(&self.module, &imports).unwrap())
|
||||
Ok((
|
||||
WebAssembly::Instance::new(&self.module, &imports).unwrap(),
|
||||
functions,
|
||||
))
|
||||
}
|
||||
|
||||
/// Returns the name of the current module.
|
||||
|
||||
@@ -112,18 +112,6 @@ impl<T: Copy + ValueType> WasmPtr<T, Item> {
|
||||
let subarray = memory.uint8view().subarray(self.offset, total_len as u32);
|
||||
Some(WasmCell::new(subarray))
|
||||
}
|
||||
|
||||
/// Mutably dereference this `WasmPtr` getting a `&mut Cell<T>` allowing for
|
||||
/// direct access to a `&mut T`.
|
||||
///
|
||||
/// # Safety
|
||||
/// - This method does not do any aliasing checks: it's possible to create
|
||||
/// `&mut T` that point to the same memory. You should ensure that you have
|
||||
/// exclusive access to Wasm linear memory before calling this method.
|
||||
#[inline]
|
||||
pub unsafe fn deref_mut<'a>(self, memory: &'a Memory) -> Option<WasmCell<T>> {
|
||||
self.deref(memory)
|
||||
}
|
||||
}
|
||||
|
||||
/// Methods for `WasmPtr`s to arrays of data that can be dereferenced, namely to
|
||||
@@ -137,7 +125,7 @@ impl<T: Copy + ValueType> WasmPtr<T, Array> {
|
||||
/// If you're unsure what that means, it likely does not apply to you.
|
||||
/// This invariant will be enforced in the future.
|
||||
#[inline]
|
||||
pub fn deref(self, memory: &Memory, index: u32, length: u32) -> Option<Box<[WasmCell<T>]>> {
|
||||
pub fn deref(self, memory: &Memory, index: u32, length: u32) -> Option<Vec<WasmCell<T>>> {
|
||||
// gets the size of the item in the array with padding added such that
|
||||
// for any index, we will always result an aligned memory access
|
||||
let item_size = mem::size_of::<T>() as u32;
|
||||
@@ -160,28 +148,10 @@ impl<T: Copy + ValueType> WasmPtr<T, Array> {
|
||||
);
|
||||
WasmCell::new(subarray)
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.into_boxed_slice(),
|
||||
.collect::<Vec<_>>(),
|
||||
)
|
||||
}
|
||||
|
||||
/// Mutably dereference this `WasmPtr` getting a `&mut [Cell<T>]` allowing for
|
||||
/// direct access to a `&mut [T]`.
|
||||
///
|
||||
/// # Safety
|
||||
/// - This method does not do any aliasing checks: it's possible to create
|
||||
/// `&mut T` that point to the same memory. You should ensure that you have
|
||||
/// exclusive access to Wasm linear memory before calling this method.
|
||||
#[inline]
|
||||
pub unsafe fn deref_mut(
|
||||
self,
|
||||
memory: &Memory,
|
||||
index: u32,
|
||||
length: u32,
|
||||
) -> Option<Box<[WasmCell<T>]>> {
|
||||
self.deref(memory, index, length)
|
||||
}
|
||||
|
||||
/// Get a UTF-8 string from the `WasmPtr` with the given length.
|
||||
///
|
||||
/// Note that . The
|
||||
@@ -212,7 +182,9 @@ impl<T: Copy + ValueType> WasmPtr<T, Array> {
|
||||
return None;
|
||||
}
|
||||
let subarray_as_vec = memory.uint8view().subarray(self.offset, str_len).to_vec();
|
||||
String::from_utf8(subarray_as_vec).ok().map(std::borrow::Cow::from)
|
||||
String::from_utf8(subarray_as_vec)
|
||||
.ok()
|
||||
.map(std::borrow::Cow::from)
|
||||
}
|
||||
|
||||
/// Get a UTF-8 `String` from the `WasmPtr` with the given length.
|
||||
@@ -319,29 +291,23 @@ mod test {
|
||||
let start_wasm_ptr_array: WasmPtr<u8, Array> = WasmPtr::new(0);
|
||||
|
||||
assert!(start_wasm_ptr.deref(&memory).is_some());
|
||||
assert!(unsafe { start_wasm_ptr.deref_mut(&memory).is_some() });
|
||||
assert!(start_wasm_ptr_array.deref(&memory, 0, 0).is_some());
|
||||
assert!(unsafe { start_wasm_ptr_array.get_utf8_str(&memory, 0).is_some() });
|
||||
assert!(start_wasm_ptr_array.get_utf8_string(&memory, 0).is_some());
|
||||
assert!(unsafe { start_wasm_ptr_array.deref_mut(&memory, 0, 0).is_some() });
|
||||
assert!(start_wasm_ptr_array.deref(&memory, 0, 1).is_some());
|
||||
assert!(unsafe { start_wasm_ptr_array.deref_mut(&memory, 0, 1).is_some() });
|
||||
|
||||
// test that accessing the last valid memory address works correctly and OOB is caught
|
||||
let last_valid_address_for_u8 = (memory.size().bytes().0 - 1) as u32;
|
||||
let end_wasm_ptr: WasmPtr<u8> = WasmPtr::new(last_valid_address_for_u8);
|
||||
assert!(end_wasm_ptr.deref(&memory).is_some());
|
||||
assert!(unsafe { end_wasm_ptr.deref_mut(&memory).is_some() });
|
||||
|
||||
let end_wasm_ptr_array: WasmPtr<u8, Array> = WasmPtr::new(last_valid_address_for_u8);
|
||||
|
||||
assert!(end_wasm_ptr_array.deref(&memory, 0, 1).is_some());
|
||||
assert!(unsafe { end_wasm_ptr_array.deref_mut(&memory, 0, 1).is_some() });
|
||||
let invalid_idx_len_combos: [(u32, u32); 3] =
|
||||
[(last_valid_address_for_u8 + 1, 0), (0, 2), (1, 1)];
|
||||
for &(idx, len) in invalid_idx_len_combos.iter() {
|
||||
assert!(end_wasm_ptr_array.deref(&memory, idx, len).is_none());
|
||||
assert!(unsafe { end_wasm_ptr_array.deref_mut(&memory, idx, len).is_none() });
|
||||
}
|
||||
assert!(unsafe { end_wasm_ptr_array.get_utf8_str(&memory, 2).is_none() });
|
||||
assert!(end_wasm_ptr_array.get_utf8_string(&memory, 2).is_none());
|
||||
@@ -351,9 +317,7 @@ mod test {
|
||||
let last_valid_address_for_u32 = (memory.size().bytes().0 - 4) as u32;
|
||||
let end_wasm_ptr: WasmPtr<u32> = WasmPtr::new(last_valid_address_for_u32);
|
||||
assert!(end_wasm_ptr.deref(&memory).is_some());
|
||||
assert!(unsafe { end_wasm_ptr.deref_mut(&memory).is_some() });
|
||||
assert!(end_wasm_ptr.deref(&memory).is_some());
|
||||
assert!(unsafe { end_wasm_ptr.deref_mut(&memory).is_some() });
|
||||
|
||||
let end_wasm_ptr_oob_array: [WasmPtr<u32>; 4] = [
|
||||
WasmPtr::new(last_valid_address_for_u32 + 1),
|
||||
@@ -363,17 +327,14 @@ mod test {
|
||||
];
|
||||
for oob_end_ptr in end_wasm_ptr_oob_array.iter() {
|
||||
assert!(oob_end_ptr.deref(&memory).is_none());
|
||||
assert!(unsafe { oob_end_ptr.deref_mut(&memory).is_none() });
|
||||
}
|
||||
let end_wasm_ptr_array: WasmPtr<u32, Array> = WasmPtr::new(last_valid_address_for_u32);
|
||||
assert!(end_wasm_ptr_array.deref(&memory, 0, 1).is_some());
|
||||
assert!(unsafe { end_wasm_ptr_array.deref_mut(&memory, 0, 1).is_some() });
|
||||
|
||||
let invalid_idx_len_combos: [(u32, u32); 3] =
|
||||
[(last_valid_address_for_u32 + 1, 0), (0, 2), (1, 1)];
|
||||
for &(idx, len) in invalid_idx_len_combos.iter() {
|
||||
assert!(end_wasm_ptr_array.deref(&memory, idx, len).is_none());
|
||||
assert!(unsafe { end_wasm_ptr_array.deref_mut(&memory, idx, len).is_none() });
|
||||
}
|
||||
|
||||
let end_wasm_ptr_array_oob_array: [WasmPtr<u32, Array>; 4] = [
|
||||
@@ -385,9 +346,7 @@ mod test {
|
||||
|
||||
for oob_end_array_ptr in end_wasm_ptr_array_oob_array.iter() {
|
||||
assert!(oob_end_array_ptr.deref(&memory, 0, 1).is_none());
|
||||
assert!(unsafe { oob_end_array_ptr.deref_mut(&memory, 0, 1).is_none() });
|
||||
assert!(oob_end_array_ptr.deref(&memory, 1, 0).is_none());
|
||||
assert!(unsafe { oob_end_array_ptr.deref_mut(&memory, 1, 0).is_none() });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ use wasmer_types::entity::{BoxedSlice, EntityRef, PrimaryMap};
|
||||
use wasmer_types::{ExternType, FunctionIndex, ImportIndex, MemoryIndex, TableIndex};
|
||||
|
||||
/// Import resolver connects imports with available exported values.
|
||||
pub trait Resolver: Sized {
|
||||
pub trait Resolver {
|
||||
/// Resolves an import a WebAssembly module to an export it's hooked up to.
|
||||
///
|
||||
/// The `index` provided is the index of the import in the wasm module
|
||||
@@ -75,3 +75,93 @@ impl Resolver for NullResolver {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// A [`Resolver`] that links two resolvers together in a chain.
|
||||
pub struct NamedResolverChain<A: NamedResolver, B: NamedResolver> {
|
||||
a: A,
|
||||
b: B,
|
||||
}
|
||||
|
||||
/// A trait for chaining resolvers together.
|
||||
///
|
||||
/// ```
|
||||
/// # use wasmer_engine::{ChainableNamedResolver, NamedResolver};
|
||||
/// # fn chainable_test<A, B>(imports1: A, imports2: B)
|
||||
/// # where A: NamedResolver + Sized,
|
||||
/// # B: NamedResolver + Sized,
|
||||
/// # {
|
||||
/// // override duplicates with imports from `imports2`
|
||||
/// imports1.chain_front(imports2);
|
||||
/// # }
|
||||
/// ```
|
||||
pub trait ChainableNamedResolver: NamedResolver + Sized {
|
||||
/// Chain a resolver in front of the current resolver.
|
||||
///
|
||||
/// This will cause the second resolver to override the first.
|
||||
///
|
||||
/// ```
|
||||
/// # use wasmer_engine::{ChainableNamedResolver, NamedResolver};
|
||||
/// # fn chainable_test<A, B>(imports1: A, imports2: B)
|
||||
/// # where A: NamedResolver + Sized,
|
||||
/// # B: NamedResolver + Sized,
|
||||
/// # {
|
||||
/// // override duplicates with imports from `imports2`
|
||||
/// imports1.chain_front(imports2);
|
||||
/// # }
|
||||
/// ```
|
||||
fn chain_front<U>(self, other: U) -> NamedResolverChain<U, Self>
|
||||
where
|
||||
U: NamedResolver,
|
||||
{
|
||||
NamedResolverChain { a: other, b: self }
|
||||
}
|
||||
|
||||
/// Chain a resolver behind the current resolver.
|
||||
///
|
||||
/// This will cause the first resolver to override the second.
|
||||
///
|
||||
/// ```
|
||||
/// # use wasmer_engine::{ChainableNamedResolver, NamedResolver};
|
||||
/// # fn chainable_test<A, B>(imports1: A, imports2: B)
|
||||
/// # where A: NamedResolver + Sized,
|
||||
/// # B: NamedResolver + Sized,
|
||||
/// # {
|
||||
/// // override duplicates with imports from `imports1`
|
||||
/// imports1.chain_back(imports2);
|
||||
/// # }
|
||||
/// ```
|
||||
fn chain_back<U>(self, other: U) -> NamedResolverChain<Self, U>
|
||||
where
|
||||
U: NamedResolver,
|
||||
{
|
||||
NamedResolverChain { a: self, b: other }
|
||||
}
|
||||
}
|
||||
|
||||
// We give these chain methods to all types implementing NamedResolver
|
||||
impl<T: NamedResolver> ChainableNamedResolver for T {}
|
||||
|
||||
impl<A, B> NamedResolver for NamedResolverChain<A, B>
|
||||
where
|
||||
A: NamedResolver,
|
||||
B: NamedResolver,
|
||||
{
|
||||
fn resolve_by_name(&self, module: &str, field: &str) -> Option<Export> {
|
||||
self.a
|
||||
.resolve_by_name(module, field)
|
||||
.or_else(|| self.b.resolve_by_name(module, field))
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, B> Clone for NamedResolverChain<A, B>
|
||||
where
|
||||
A: NamedResolver + Clone,
|
||||
B: NamedResolver + Clone,
|
||||
{
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
a: self.a.clone(),
|
||||
b: self.b.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user