mirror of
https://github.com/mii443/wasmer.git
synced 2025-12-10 06:38:22 +00:00
Unified Function into js/sys
This commit is contained in:
512
lib/api/src/externals/function.rs
vendored
512
lib/api/src/externals/function.rs
vendored
@@ -1,8 +1,510 @@
|
||||
#[cfg(feature = "js")]
|
||||
pub use crate::js::externals::function::{
|
||||
FromToNativeWasmType, Function, HostFunction, WasmTypeList,
|
||||
};
|
||||
use crate::js::externals::function as function_impl;
|
||||
#[cfg(feature = "sys")]
|
||||
pub use crate::sys::externals::function::{
|
||||
FromToNativeWasmType, Function, HostFunction, WasmTypeList,
|
||||
use crate::sys::externals::function as function_impl;
|
||||
|
||||
use crate::exports::{ExportError, Exportable};
|
||||
use crate::store::{AsStoreMut, AsStoreRef};
|
||||
use crate::vm::{VMExtern, VMExternFunction, VMFuncRef, VMFunctionBody, VMTrampoline};
|
||||
use crate::{
|
||||
Extern, FunctionEnv, FunctionEnvMut, FunctionType, RuntimeError, TypedFunction, Value,
|
||||
};
|
||||
use wasmer_types::RawValue;
|
||||
|
||||
use crate::native_type::WasmTypeList;
|
||||
|
||||
/// The `HostFunction` trait represents the set of functions that
|
||||
/// can be used as host function. To uphold this statement, it is
|
||||
/// necessary for a function to be transformed into a pointer to
|
||||
/// `VMFunctionBody`.
|
||||
pub trait HostFunction<T, Args, Rets, Kind>
|
||||
where
|
||||
Args: WasmTypeList,
|
||||
Rets: WasmTypeList,
|
||||
Kind: HostFunctionKind,
|
||||
{
|
||||
/// Get the pointer to the function body.
|
||||
fn function_body_ptr(&self) -> *const VMFunctionBody;
|
||||
|
||||
/// Get the pointer to the function call trampoline.
|
||||
fn call_trampoline_address() -> VMTrampoline {
|
||||
// This is not implemented in JS
|
||||
unimplemented!();
|
||||
}
|
||||
}
|
||||
|
||||
/// Empty trait to specify the kind of `HostFunction`: With or
|
||||
/// without an environment.
|
||||
///
|
||||
/// This trait is never aimed to be used by a user. It is used by
|
||||
/// the trait system to automatically generate the appropriate
|
||||
/// host functions.
|
||||
#[doc(hidden)]
|
||||
pub trait HostFunctionKind: private::HostFunctionKindSealed {}
|
||||
|
||||
/// An empty struct to help Rust typing to determine
|
||||
/// when a `HostFunction` does have an environment.
|
||||
pub struct WithEnv;
|
||||
|
||||
impl HostFunctionKind for WithEnv {}
|
||||
|
||||
/// An empty struct to help Rust typing to determine
|
||||
/// when a `HostFunction` does not have an environment.
|
||||
pub struct WithoutEnv;
|
||||
|
||||
impl HostFunctionKind for WithoutEnv {}
|
||||
|
||||
mod private {
|
||||
//! Sealing the HostFunctionKind because it shouldn't be implemented
|
||||
//! by any type outside.
|
||||
//! See:
|
||||
//! https://rust-lang.github.io/api-guidelines/future-proofing.html#c-sealed
|
||||
pub trait HostFunctionKindSealed {}
|
||||
impl HostFunctionKindSealed for super::WithEnv {}
|
||||
impl HostFunctionKindSealed for super::WithoutEnv {}
|
||||
}
|
||||
|
||||
/// A WebAssembly `function` instance.
|
||||
///
|
||||
/// A function instance is the runtime representation of a function.
|
||||
/// It effectively is a closure of the original function (defined in either
|
||||
/// the host or the WebAssembly module) over the runtime `Instance` of its
|
||||
/// originating `Module`.
|
||||
///
|
||||
/// The module instance is used to resolve references to other definitions
|
||||
/// during execution of the function.
|
||||
///
|
||||
/// Spec: <https://webassembly.github.io/spec/core/exec/runtime.html#function-instances>
|
||||
///
|
||||
/// # Panics
|
||||
/// - Closures (functions with captured environments) are not currently supported
|
||||
/// with native functions. Attempting to create a native `Function` with one will
|
||||
/// result in a panic.
|
||||
/// [Closures as host functions tracking issue](https://github.com/wasmerio/wasmer/issues/1840)
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Function(pub(crate) function_impl::Function);
|
||||
|
||||
impl Function {
|
||||
/// Creates a new host `Function` (dynamic) with the provided signature.
|
||||
///
|
||||
/// If you know the signature of the host function at compile time,
|
||||
/// consider using [`Function::new_typed`] for less runtime overhead.
|
||||
pub fn new<FT, F>(store: &mut impl AsStoreMut, ty: FT, func: F) -> Self
|
||||
where
|
||||
FT: Into<FunctionType>,
|
||||
F: Fn(&[Value]) -> Result<Vec<Value>, RuntimeError> + 'static + Send + Sync,
|
||||
{
|
||||
let env = FunctionEnv::new(&mut store.as_store_mut(), ());
|
||||
let wrapped_func = move |_env: FunctionEnvMut<()>,
|
||||
args: &[Value]|
|
||||
-> Result<Vec<Value>, RuntimeError> { func(args) };
|
||||
Self::new_with_env(store, &env, ty, wrapped_func)
|
||||
}
|
||||
|
||||
/// Creates a new host `Function` (dynamic) with the provided signature.
|
||||
///
|
||||
/// If you know the signature of the host function at compile time,
|
||||
/// consider using [`Function::new_typed_with_env`] for less runtime overhead.
|
||||
///
|
||||
/// Takes a [`FunctionEnv`] that is passed into func. If that is not required,
|
||||
/// [`Function::new`] might be an option as well.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # use wasmer::{Function, FunctionEnv, FunctionType, Type, Store, Value};
|
||||
/// # let mut store = Store::default();
|
||||
/// # let env = FunctionEnv::new(&mut store, ());
|
||||
/// #
|
||||
/// let signature = FunctionType::new(vec![Type::I32, Type::I32], vec![Type::I32]);
|
||||
///
|
||||
/// let f = Function::new_with_env(&mut store, &env, &signature, |_env, args| {
|
||||
/// let sum = args[0].unwrap_i32() + args[1].unwrap_i32();
|
||||
/// Ok(vec![Value::I32(sum)])
|
||||
/// });
|
||||
/// ```
|
||||
///
|
||||
/// With constant signature:
|
||||
///
|
||||
/// ```
|
||||
/// # use wasmer::{Function, FunctionEnv, FunctionType, Type, Store, Value};
|
||||
/// # let mut store = Store::default();
|
||||
/// # let env = FunctionEnv::new(&mut store, ());
|
||||
/// #
|
||||
/// const I32_I32_TO_I32: ([Type; 2], [Type; 1]) = ([Type::I32, Type::I32], [Type::I32]);
|
||||
///
|
||||
/// let f = Function::new_with_env(&mut store, &env, I32_I32_TO_I32, |_env, args| {
|
||||
/// let sum = args[0].unwrap_i32() + args[1].unwrap_i32();
|
||||
/// Ok(vec![Value::I32(sum)])
|
||||
/// });
|
||||
/// ```
|
||||
pub fn new_with_env<FT, F, T: Send + 'static>(
|
||||
store: &mut impl AsStoreMut,
|
||||
env: &FunctionEnv<T>,
|
||||
ty: FT,
|
||||
func: F,
|
||||
) -> Self
|
||||
where
|
||||
FT: Into<FunctionType>,
|
||||
F: Fn(FunctionEnvMut<T>, &[Value]) -> Result<Vec<Value>, RuntimeError>
|
||||
+ 'static
|
||||
+ Send
|
||||
+ Sync,
|
||||
{
|
||||
Function(function_impl::Function::new_with_env(store, env, ty, func))
|
||||
}
|
||||
|
||||
#[deprecated(
|
||||
since = "3.0.0",
|
||||
note = "new_native() has been renamed to new_typed()."
|
||||
)]
|
||||
/// Creates a new host `Function` from a native function.
|
||||
pub fn new_native<F, Args, Rets>(store: &mut impl AsStoreMut, func: F) -> Self
|
||||
where
|
||||
F: HostFunction<(), Args, Rets, WithoutEnv> + 'static + Send + Sync,
|
||||
Args: WasmTypeList,
|
||||
Rets: WasmTypeList,
|
||||
{
|
||||
Self::new_typed(store, func)
|
||||
}
|
||||
|
||||
/// Creates a new host `Function` from a native function.
|
||||
pub fn new_typed<F, Args, Rets>(store: &mut impl AsStoreMut, func: F) -> Self
|
||||
where
|
||||
F: HostFunction<(), Args, Rets, WithoutEnv> + 'static + Send + Sync,
|
||||
Args: WasmTypeList,
|
||||
Rets: WasmTypeList,
|
||||
{
|
||||
Function(function_impl::Function::new_typed(store, func))
|
||||
}
|
||||
|
||||
#[deprecated(
|
||||
since = "3.0.0",
|
||||
note = "new_native_with_env() has been renamed to new_typed_with_env()."
|
||||
)]
|
||||
/// Creates a new host `Function` with an environment from a native function.
|
||||
pub fn new_native_with_env<T: Send + 'static, F, Args, Rets>(
|
||||
store: &mut impl AsStoreMut,
|
||||
env: &FunctionEnv<T>,
|
||||
func: F,
|
||||
) -> Self
|
||||
where
|
||||
F: HostFunction<T, Args, Rets, WithEnv> + 'static + Send + Sync,
|
||||
Args: WasmTypeList,
|
||||
Rets: WasmTypeList,
|
||||
{
|
||||
Self::new_typed_with_env(store, env, func)
|
||||
}
|
||||
|
||||
/// Creates a new host `Function` with an environment from a typed function.
|
||||
///
|
||||
/// The function signature is automatically retrieved using the
|
||||
/// Rust typing system.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// # use wasmer::{Store, Function, FunctionEnv, FunctionEnvMut};
|
||||
/// # let mut store = Store::default();
|
||||
/// # let env = FunctionEnv::new(&mut store, ());
|
||||
/// #
|
||||
/// fn sum(_env: FunctionEnvMut<()>, a: i32, b: i32) -> i32 {
|
||||
/// a + b
|
||||
/// }
|
||||
///
|
||||
/// let f = Function::new_typed_with_env(&mut store, &env, sum);
|
||||
/// ```
|
||||
pub fn new_typed_with_env<T: Send + 'static, F, Args, Rets>(
|
||||
store: &mut impl AsStoreMut,
|
||||
env: &FunctionEnv<T>,
|
||||
func: F,
|
||||
) -> Self
|
||||
where
|
||||
F: HostFunction<T, Args, Rets, WithEnv> + 'static + Send + Sync,
|
||||
Args: WasmTypeList,
|
||||
Rets: WasmTypeList,
|
||||
{
|
||||
Function(function_impl::Function::new_typed_with_env(
|
||||
store, env, func,
|
||||
))
|
||||
}
|
||||
|
||||
/// Returns the [`FunctionType`] of the `Function`.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// # use wasmer::{Function, FunctionEnv, FunctionEnvMut, Store, Type};
|
||||
/// # let mut store = Store::default();
|
||||
/// # let env = FunctionEnv::new(&mut store, ());
|
||||
/// #
|
||||
/// fn sum(_env: FunctionEnvMut<()>, a: i32, b: i32) -> i32 {
|
||||
/// a + b
|
||||
/// }
|
||||
///
|
||||
/// let f = Function::new_typed_with_env(&mut store, &env, sum);
|
||||
///
|
||||
/// assert_eq!(f.ty(&mut store).params(), vec![Type::I32, Type::I32]);
|
||||
/// assert_eq!(f.ty(&mut store).results(), vec![Type::I32]);
|
||||
/// ```
|
||||
pub fn ty(&self, store: &impl AsStoreRef) -> FunctionType {
|
||||
self.0.ty(store)
|
||||
}
|
||||
|
||||
/// Returns the number of parameters that this function takes.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// # use wasmer::{Function, FunctionEnv, FunctionEnvMut, Store, Type};
|
||||
/// # let mut store = Store::default();
|
||||
/// # let env = FunctionEnv::new(&mut store, ());
|
||||
/// #
|
||||
/// fn sum(_env: FunctionEnvMut<()>, a: i32, b: i32) -> i32 {
|
||||
/// a + b
|
||||
/// }
|
||||
///
|
||||
/// let f = Function::new_typed_with_env(&mut store, &env, sum);
|
||||
///
|
||||
/// assert_eq!(f.param_arity(&mut store), 2);
|
||||
/// ```
|
||||
pub fn param_arity(&self, store: &impl AsStoreRef) -> usize {
|
||||
self.ty(store).params().len()
|
||||
}
|
||||
|
||||
/// Returns the number of results this function produces.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// # use wasmer::{Function, FunctionEnv, FunctionEnvMut, Store, Type};
|
||||
/// # let mut store = Store::default();
|
||||
/// # let env = FunctionEnv::new(&mut store, ());
|
||||
/// #
|
||||
/// fn sum(_env: FunctionEnvMut<()>, a: i32, b: i32) -> i32 {
|
||||
/// a + b
|
||||
/// }
|
||||
///
|
||||
/// let f = Function::new_typed_with_env(&mut store, &env, sum);
|
||||
///
|
||||
/// assert_eq!(f.result_arity(&mut store), 1);
|
||||
/// ```
|
||||
pub fn result_arity(&self, store: &impl AsStoreRef) -> usize {
|
||||
self.ty(store).results().len()
|
||||
}
|
||||
|
||||
/// Call the `Function` function.
|
||||
///
|
||||
/// Depending on where the Function is defined, it will call it.
|
||||
/// 1. If the function is defined inside a WebAssembly, it will call the trampoline
|
||||
/// for the function signature.
|
||||
/// 2. If the function is defined in the host (in a native way), it will
|
||||
/// call the trampoline.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # use wasmer::{imports, wat2wasm, Function, Instance, Module, Store, Type, Value};
|
||||
/// # use wasmer::FunctionEnv;
|
||||
/// # let mut store = Store::default();
|
||||
/// # let env = FunctionEnv::new(&mut store, ());
|
||||
/// # let wasm_bytes = wat2wasm(r#"
|
||||
/// # (module
|
||||
/// # (func (export "sum") (param $x i32) (param $y i32) (result i32)
|
||||
/// # local.get $x
|
||||
/// # local.get $y
|
||||
/// # i32.add
|
||||
/// # ))
|
||||
/// # "#.as_bytes()).unwrap();
|
||||
/// # let module = Module::new(&store, wasm_bytes).unwrap();
|
||||
/// # let import_object = imports! {};
|
||||
/// # let instance = Instance::new(&mut store, &module, &import_object).unwrap();
|
||||
/// #
|
||||
/// let sum = instance.exports.get_function("sum").unwrap();
|
||||
///
|
||||
/// assert_eq!(sum.call(&mut store, &[Value::I32(1), Value::I32(2)]).unwrap().to_vec(), vec![Value::I32(3)]);
|
||||
/// ```
|
||||
pub fn call(
|
||||
&self,
|
||||
store: &mut impl AsStoreMut,
|
||||
params: &[Value],
|
||||
) -> Result<Box<[Value]>, RuntimeError> {
|
||||
self.0.call(store, params)
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[allow(missing_docs)]
|
||||
pub fn call_raw(
|
||||
&self,
|
||||
store: &mut impl AsStoreMut,
|
||||
params: Vec<RawValue>,
|
||||
) -> Result<Box<[Value]>, RuntimeError> {
|
||||
self.0.call_raw(store, params)
|
||||
}
|
||||
|
||||
pub(crate) fn vm_funcref(&self, store: &impl AsStoreRef) -> VMFuncRef {
|
||||
self.0.vm_funcref(store)
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn from_vm_funcref(store: &mut impl AsStoreMut, funcref: VMFuncRef) -> Self {
|
||||
Function(function_impl::Function::from_vm_funcref(store, funcref))
|
||||
}
|
||||
|
||||
/// Transform this WebAssembly function into a native function.
|
||||
/// See [`TypedFunction`] to learn more.
|
||||
#[deprecated(since = "3.0.0", note = "native() has been renamed to typed().")]
|
||||
pub fn native<Args, Rets>(
|
||||
&self,
|
||||
store: &impl AsStoreRef,
|
||||
) -> Result<TypedFunction<Args, Rets>, RuntimeError>
|
||||
where
|
||||
Args: WasmTypeList,
|
||||
Rets: WasmTypeList,
|
||||
{
|
||||
self.typed(store)
|
||||
}
|
||||
|
||||
/// Transform this WebAssembly function into a typed function.
|
||||
/// See [`TypedFunction`] to learn more.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # use wasmer::{imports, wat2wasm, Function, Instance, Module, Store, Type, TypedFunction, Value};
|
||||
/// # use wasmer::FunctionEnv;
|
||||
/// # let mut store = Store::default();
|
||||
/// # let env = FunctionEnv::new(&mut store, ());
|
||||
/// # let wasm_bytes = wat2wasm(r#"
|
||||
/// # (module
|
||||
/// # (func (export "sum") (param $x i32) (param $y i32) (result i32)
|
||||
/// # local.get $x
|
||||
/// # local.get $y
|
||||
/// # i32.add
|
||||
/// # ))
|
||||
/// # "#.as_bytes()).unwrap();
|
||||
/// # let module = Module::new(&store, wasm_bytes).unwrap();
|
||||
/// # let import_object = imports! {};
|
||||
/// # let instance = Instance::new(&mut store, &module, &import_object).unwrap();
|
||||
/// #
|
||||
/// let sum = instance.exports.get_function("sum").unwrap();
|
||||
/// let sum_typed: TypedFunction<(i32, i32), i32> = sum.typed(&mut store).unwrap();
|
||||
///
|
||||
/// assert_eq!(sum_typed.call(&mut store, 1, 2).unwrap(), 3);
|
||||
/// ```
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// If the `Args` generic parameter does not match the exported function
|
||||
/// an error will be raised:
|
||||
///
|
||||
/// ```should_panic
|
||||
/// # use wasmer::{imports, wat2wasm, Function, Instance, Module, Store, Type, TypedFunction, Value};
|
||||
/// # use wasmer::FunctionEnv;
|
||||
/// # let mut store = Store::default();
|
||||
/// # let env = FunctionEnv::new(&mut store, ());
|
||||
/// # let wasm_bytes = wat2wasm(r#"
|
||||
/// # (module
|
||||
/// # (func (export "sum") (param $x i32) (param $y i32) (result i32)
|
||||
/// # local.get $x
|
||||
/// # local.get $y
|
||||
/// # i32.add
|
||||
/// # ))
|
||||
/// # "#.as_bytes()).unwrap();
|
||||
/// # let module = Module::new(&store, wasm_bytes).unwrap();
|
||||
/// # let import_object = imports! {};
|
||||
/// # let instance = Instance::new(&mut store, &module, &import_object).unwrap();
|
||||
/// #
|
||||
/// let sum = instance.exports.get_function("sum").unwrap();
|
||||
///
|
||||
/// // This results in an error: `RuntimeError`
|
||||
/// let sum_typed : TypedFunction<(i64, i64), i32> = sum.typed(&mut store).unwrap();
|
||||
/// ```
|
||||
///
|
||||
/// If the `Rets` generic parameter does not match the exported function
|
||||
/// an error will be raised:
|
||||
///
|
||||
/// ```should_panic
|
||||
/// # use wasmer::{imports, wat2wasm, Function, Instance, Module, Store, Type, TypedFunction, Value};
|
||||
/// # use wasmer::FunctionEnv;
|
||||
/// # let mut store = Store::default();
|
||||
/// # let env = FunctionEnv::new(&mut store, ());
|
||||
/// # let wasm_bytes = wat2wasm(r#"
|
||||
/// # (module
|
||||
/// # (func (export "sum") (param $x i32) (param $y i32) (result i32)
|
||||
/// # local.get $x
|
||||
/// # local.get $y
|
||||
/// # i32.add
|
||||
/// # ))
|
||||
/// # "#.as_bytes()).unwrap();
|
||||
/// # let module = Module::new(&store, wasm_bytes).unwrap();
|
||||
/// # let import_object = imports! {};
|
||||
/// # let instance = Instance::new(&mut store, &module, &import_object).unwrap();
|
||||
/// #
|
||||
/// let sum = instance.exports.get_function("sum").unwrap();
|
||||
///
|
||||
/// // This results in an error: `RuntimeError`
|
||||
/// let sum_typed: TypedFunction<(i32, i32), i64> = sum.typed(&mut store).unwrap();
|
||||
/// ```
|
||||
pub fn typed<Args, Rets>(
|
||||
&self,
|
||||
store: &impl AsStoreRef,
|
||||
) -> Result<TypedFunction<Args, Rets>, RuntimeError>
|
||||
where
|
||||
Args: WasmTypeList,
|
||||
Rets: WasmTypeList,
|
||||
{
|
||||
let ty = self.ty(store);
|
||||
|
||||
// type check
|
||||
{
|
||||
let expected = ty.params();
|
||||
let given = Args::wasm_types();
|
||||
|
||||
if expected != given {
|
||||
return Err(RuntimeError::new(format!(
|
||||
"given types (`{:?}`) for the function arguments don't match the actual types (`{:?}`)",
|
||||
given,
|
||||
expected,
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
let expected = ty.results();
|
||||
let given = Rets::wasm_types();
|
||||
|
||||
if expected != given {
|
||||
// todo: error result types don't match
|
||||
return Err(RuntimeError::new(format!(
|
||||
"given types (`{:?}`) for the function results don't match the actual types (`{:?}`)",
|
||||
given,
|
||||
expected,
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(TypedFunction::new(store, self.clone()))
|
||||
}
|
||||
|
||||
pub(crate) fn from_vm_extern(store: &mut impl AsStoreMut, vm_extern: VMExternFunction) -> Self {
|
||||
Function(function_impl::Function::from_vm_extern(store, vm_extern))
|
||||
}
|
||||
|
||||
/// Checks whether this `Function` can be used with the given store.
|
||||
pub fn is_from_store(&self, store: &impl AsStoreRef) -> bool {
|
||||
self.0.is_from_store(store)
|
||||
}
|
||||
|
||||
pub(crate) fn to_vm_extern(&self) -> VMExtern {
|
||||
self.0.to_vm_extern()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Exportable<'a> for Function {
|
||||
fn get_self_from_extern(_extern: &'a Extern) -> Result<&'a Self, ExportError> {
|
||||
match _extern {
|
||||
Extern::Function(func) => Ok(func),
|
||||
_ => Err(ExportError::IncompatibleType),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
4
lib/api/src/externals/mod.rs
vendored
4
lib/api/src/externals/mod.rs
vendored
@@ -1,10 +1,10 @@
|
||||
mod function;
|
||||
pub(crate) mod function;
|
||||
mod global;
|
||||
mod memory;
|
||||
mod memory_view;
|
||||
mod table;
|
||||
|
||||
pub use self::function::{FromToNativeWasmType, Function, HostFunction, WasmTypeList};
|
||||
pub use self::function::{Function, HostFunction};
|
||||
pub use self::global::Global;
|
||||
pub use self::memory::Memory;
|
||||
pub use self::memory_view::MemoryView;
|
||||
|
||||
@@ -56,7 +56,7 @@ impl AsJs for Value {
|
||||
Self::F32(f) => JsValue::from_f64(*f as f64),
|
||||
Self::F64(f) => JsValue::from_f64(*f),
|
||||
Self::V128(f) => JsValue::from_f64(*f as f64),
|
||||
Self::FuncRef(Some(func)) => func.handle.function.clone().into(),
|
||||
Self::FuncRef(Some(func)) => func.0.handle.function.clone().into(),
|
||||
Self::FuncRef(None) => JsValue::null(),
|
||||
Self::ExternRef(_) => unimplemented!(),
|
||||
}
|
||||
@@ -207,7 +207,7 @@ impl AsJs for Extern {
|
||||
fn as_jsvalue(&self, _store: &impl AsStoreRef) -> wasm_bindgen::JsValue {
|
||||
match self {
|
||||
Self::Memory(memory) => memory.0.handle.memory.clone().into(),
|
||||
Self::Function(function) => function.handle.function.clone().into(),
|
||||
Self::Function(function) => function.0.handle.function.clone().into(),
|
||||
Self::Table(table) => table.0.handle.table.clone().into(),
|
||||
Self::Global(global) => global.0.handle.global.clone().into(),
|
||||
}
|
||||
|
||||
1018
lib/api/src/js/externals/function.rs
vendored
1018
lib/api/src/js/externals/function.rs
vendored
File diff suppressed because it is too large
Load Diff
2
lib/api/src/js/externals/table.rs
vendored
2
lib/api/src/js/externals/table.rs
vendored
@@ -21,7 +21,7 @@ fn get_function(store: &mut impl AsStoreMut, val: Value) -> Result<Function, Run
|
||||
return Err(RuntimeError::new("cannot pass Value across contexts"));
|
||||
}
|
||||
match val {
|
||||
Value::FuncRef(Some(ref func)) => Ok(func.handle.function.clone().into()),
|
||||
Value::FuncRef(Some(ref func)) => Ok(func.0.handle.function.clone().into()),
|
||||
// Only funcrefs is supported by the spec atm
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ macro_rules! impl_native_traits {
|
||||
let mut r;
|
||||
// TODO: This loop is needed for asyncify. It will be refactored with https://github.com/wasmerio/wasmer/issues/3451
|
||||
loop {
|
||||
r = self.func.handle.function.apply(
|
||||
r = self.func.0.handle.function.apply(
|
||||
&JsValue::UNDEFINED,
|
||||
&Array::from_iter(params_list.iter())
|
||||
);
|
||||
|
||||
@@ -252,6 +252,8 @@ impl VMFuncRef {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct VMTrampoline;
|
||||
|
||||
pub(crate) type VMExternTable = VMTable;
|
||||
pub(crate) type VMExternMemory = VMMemory;
|
||||
pub(crate) type VMExternGlobal = VMGlobal;
|
||||
|
||||
@@ -459,10 +459,7 @@ mod js;
|
||||
#[cfg(feature = "js")]
|
||||
pub use js::*;
|
||||
|
||||
pub use crate::externals::{
|
||||
Extern, FromToNativeWasmType, Function, Global, HostFunction, Memory, MemoryView, Table,
|
||||
WasmTypeList,
|
||||
};
|
||||
pub use crate::externals::{Extern, Function, Global, HostFunction, Memory, MemoryView, Table};
|
||||
pub use engine::{AsEngineRef, Engine};
|
||||
pub use errors::InstantiationError;
|
||||
pub use exports::{ExportError, Exportable, Exports, ExportsIterator};
|
||||
@@ -473,7 +470,7 @@ pub use instance::Instance;
|
||||
pub use into_bytes::IntoBytes;
|
||||
pub use mem_access::{MemoryAccessError, WasmRef, WasmSlice, WasmSliceIter};
|
||||
pub use module::{IoCompileError, Module};
|
||||
pub use native_type::NativeWasmTypeInto;
|
||||
pub use native_type::{FromToNativeWasmType, NativeWasmTypeInto, WasmTypeList};
|
||||
pub use ptr::{Memory32, Memory64, MemorySize, WasmPtr, WasmPtr64};
|
||||
pub use store::{AsStoreMut, AsStoreRef, OnCalledHandler, Store, StoreId, StoreMut, StoreRef};
|
||||
#[cfg(feature = "sys")]
|
||||
|
||||
@@ -3,9 +3,13 @@
|
||||
|
||||
use wasmer_types::{NativeWasmType, RawValue, Type};
|
||||
|
||||
use crate::store::AsStoreRef;
|
||||
use crate::vm::{VMExternRef, VMFuncRef};
|
||||
|
||||
use crate::{ExternRef, Function, TypedFunction, WasmTypeList};
|
||||
use crate::{ExternRef, Function, TypedFunction};
|
||||
use std::array::TryFromSliceError;
|
||||
use std::convert::Infallible;
|
||||
use std::error::Error;
|
||||
|
||||
use crate::store::AsStoreMut;
|
||||
|
||||
@@ -205,6 +209,508 @@ impl NativeWasmTypeInto for Option<Function> {
|
||||
}
|
||||
}
|
||||
|
||||
/// A trait to convert a Rust value to a `WasmNativeType` value,
|
||||
/// or to convert `WasmNativeType` value to a Rust value.
|
||||
///
|
||||
/// This trait should ideally be split into two traits:
|
||||
/// `FromNativeWasmType` and `ToNativeWasmType` but it creates a
|
||||
/// non-negligible complexity in the `WasmTypeList`
|
||||
/// implementation.
|
||||
///
|
||||
/// # Safety
|
||||
/// This trait is unsafe given the nature of how values are written and read from the native
|
||||
/// stack
|
||||
pub unsafe trait FromToNativeWasmType
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
/// Native Wasm type.
|
||||
type Native: NativeWasmTypeInto;
|
||||
|
||||
/// Convert a value of kind `Self::Native` to `Self`.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This method panics if `native` cannot fit in the `Self`
|
||||
/// type`.
|
||||
fn from_native(native: Self::Native) -> Self;
|
||||
|
||||
/// Convert self to `Self::Native`.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This method panics if `self` cannot fit in the
|
||||
/// `Self::Native` type.
|
||||
fn to_native(self) -> Self::Native;
|
||||
|
||||
/// Returns whether the given value is from the given store.
|
||||
///
|
||||
/// This always returns true for primitive types that can be used with
|
||||
/// any context.
|
||||
fn is_from_store(&self, _store: &impl AsStoreRef) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! from_to_native_wasm_type {
|
||||
( $( $type:ty => $native_type:ty ),* ) => {
|
||||
$(
|
||||
#[allow(clippy::use_self)]
|
||||
unsafe impl FromToNativeWasmType for $type {
|
||||
type Native = $native_type;
|
||||
|
||||
#[inline]
|
||||
fn from_native(native: Self::Native) -> Self {
|
||||
native as Self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn to_native(self) -> Self::Native {
|
||||
self as Self::Native
|
||||
}
|
||||
}
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! from_to_native_wasm_type_same_size {
|
||||
( $( $type:ty => $native_type:ty ),* ) => {
|
||||
$(
|
||||
#[allow(clippy::use_self)]
|
||||
unsafe impl FromToNativeWasmType for $type {
|
||||
type Native = $native_type;
|
||||
|
||||
#[inline]
|
||||
fn from_native(native: Self::Native) -> Self {
|
||||
Self::from_ne_bytes(Self::Native::to_ne_bytes(native))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn to_native(self) -> Self::Native {
|
||||
Self::Native::from_ne_bytes(Self::to_ne_bytes(self))
|
||||
}
|
||||
}
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
from_to_native_wasm_type!(
|
||||
i8 => i32,
|
||||
u8 => i32,
|
||||
i16 => i32,
|
||||
u16 => i32
|
||||
);
|
||||
|
||||
from_to_native_wasm_type_same_size!(
|
||||
i32 => i32,
|
||||
u32 => i32,
|
||||
i64 => i64,
|
||||
u64 => i64,
|
||||
f32 => f32,
|
||||
f64 => f64
|
||||
);
|
||||
|
||||
unsafe impl FromToNativeWasmType for Option<ExternRef> {
|
||||
type Native = Self;
|
||||
|
||||
fn to_native(self) -> Self::Native {
|
||||
self
|
||||
}
|
||||
fn from_native(n: Self::Native) -> Self {
|
||||
n
|
||||
}
|
||||
fn is_from_store(&self, store: &impl AsStoreRef) -> bool {
|
||||
self.as_ref().map_or(true, |e| e.is_from_store(store))
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl FromToNativeWasmType for Option<Function> {
|
||||
type Native = Self;
|
||||
|
||||
fn to_native(self) -> Self::Native {
|
||||
self
|
||||
}
|
||||
fn from_native(n: Self::Native) -> Self {
|
||||
n
|
||||
}
|
||||
fn is_from_store(&self, store: &impl AsStoreRef) -> bool {
|
||||
self.as_ref().map_or(true, |f| f.is_from_store(store))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_from_to_native_wasm_type {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_to_native() {
|
||||
assert_eq!(7i8.to_native(), 7i32);
|
||||
assert_eq!(7u8.to_native(), 7i32);
|
||||
assert_eq!(7i16.to_native(), 7i32);
|
||||
assert_eq!(7u16.to_native(), 7i32);
|
||||
assert_eq!(u32::MAX.to_native(), -1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_to_native_same_size() {
|
||||
assert_eq!(7i32.to_native(), 7i32);
|
||||
assert_eq!(7u32.to_native(), 7i32);
|
||||
assert_eq!(7i64.to_native(), 7i64);
|
||||
assert_eq!(7u64.to_native(), 7i64);
|
||||
assert_eq!(7f32.to_native(), 7f32);
|
||||
assert_eq!(7f64.to_native(), 7f64);
|
||||
}
|
||||
}
|
||||
|
||||
/// The `WasmTypeList` trait represents a tuple (list) of Wasm
|
||||
/// typed values. It is used to get low-level representation of
|
||||
/// such a tuple.
|
||||
pub trait WasmTypeList
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
/// The C type (a struct) that can hold/represent all the
|
||||
/// represented values.
|
||||
type CStruct;
|
||||
|
||||
/// The array type that can hold all the represented values.
|
||||
///
|
||||
/// Note that all values are stored in their binary form.
|
||||
type Array: AsMut<[RawValue]>;
|
||||
|
||||
/// The size of the array
|
||||
fn size() -> u32;
|
||||
|
||||
/// Constructs `Self` based on an array of values.
|
||||
///
|
||||
/// # Safety
|
||||
unsafe fn from_array(store: &mut impl AsStoreMut, array: Self::Array) -> Self;
|
||||
|
||||
/// Constructs `Self` based on a slice of values.
|
||||
///
|
||||
/// `from_slice` returns a `Result` because it is possible
|
||||
/// that the slice doesn't have the same size than
|
||||
/// `Self::Array`, in which circumstance an error of kind
|
||||
/// `TryFromSliceError` will be returned.
|
||||
///
|
||||
/// # Safety
|
||||
unsafe fn from_slice(
|
||||
store: &mut impl AsStoreMut,
|
||||
slice: &[RawValue],
|
||||
) -> Result<Self, TryFromSliceError>;
|
||||
|
||||
/// Builds and returns an array of type `Array` from a tuple
|
||||
/// (list) of values.
|
||||
///
|
||||
/// # Safety
|
||||
unsafe fn into_array(self, store: &mut impl AsStoreMut) -> Self::Array;
|
||||
|
||||
/// Allocates and return an empty array of type `Array` that
|
||||
/// will hold a tuple (list) of values, usually to hold the
|
||||
/// returned values of a WebAssembly function call.
|
||||
fn empty_array() -> Self::Array;
|
||||
|
||||
/// Builds a tuple (list) of values from a C struct of type
|
||||
/// `CStruct`.
|
||||
///
|
||||
/// # Safety
|
||||
unsafe fn from_c_struct(store: &mut impl AsStoreMut, c_struct: Self::CStruct) -> Self;
|
||||
|
||||
/// Builds and returns a C struct of type `CStruct` from a
|
||||
/// tuple (list) of values.
|
||||
///
|
||||
/// # Safety
|
||||
unsafe fn into_c_struct(self, store: &mut impl AsStoreMut) -> Self::CStruct;
|
||||
|
||||
/// Writes the contents of a C struct to an array of `RawValue`.
|
||||
///
|
||||
/// # Safety
|
||||
unsafe fn write_c_struct_to_ptr(c_struct: Self::CStruct, ptr: *mut RawValue);
|
||||
|
||||
/// Get the Wasm types for the tuple (list) of currently
|
||||
/// represented values.
|
||||
fn wasm_types() -> &'static [Type];
|
||||
}
|
||||
|
||||
/// The `IntoResult` trait turns a `WasmTypeList` into a
|
||||
/// `Result<WasmTypeList, Self::Error>`.
|
||||
///
|
||||
/// It is mostly used to turn result values of a Wasm function
|
||||
/// call into a `Result`.
|
||||
pub trait IntoResult<T>
|
||||
where
|
||||
T: WasmTypeList,
|
||||
{
|
||||
/// The error type for this trait.
|
||||
type Error: Error + Sync + Send + 'static;
|
||||
|
||||
/// Transforms `Self` into a `Result`.
|
||||
fn into_result(self) -> Result<T, Self::Error>;
|
||||
}
|
||||
|
||||
impl<T> IntoResult<T> for T
|
||||
where
|
||||
T: WasmTypeList,
|
||||
{
|
||||
// `T` is not a `Result`, it's already a value, so no error
|
||||
// can be built.
|
||||
type Error = Infallible;
|
||||
|
||||
fn into_result(self) -> Result<Self, Infallible> {
|
||||
Ok(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, E> IntoResult<T> for Result<T, E>
|
||||
where
|
||||
T: WasmTypeList,
|
||||
E: Error + Sync + Send + 'static,
|
||||
{
|
||||
type Error = E;
|
||||
|
||||
fn into_result(self) -> Self {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_into_result {
|
||||
use super::*;
|
||||
use std::convert::Infallible;
|
||||
|
||||
#[test]
|
||||
fn test_into_result_over_t() {
|
||||
let x: i32 = 42;
|
||||
let result_of_x: Result<i32, Infallible> = x.into_result();
|
||||
|
||||
assert_eq!(result_of_x.unwrap(), x);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_into_result_over_result() {
|
||||
{
|
||||
let x: Result<i32, Infallible> = Ok(42);
|
||||
let result_of_x: Result<i32, Infallible> = x.into_result();
|
||||
|
||||
assert_eq!(result_of_x, x);
|
||||
}
|
||||
|
||||
{
|
||||
use std::{error, fmt};
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
struct E;
|
||||
|
||||
impl fmt::Display for E {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(formatter, "E")
|
||||
}
|
||||
}
|
||||
|
||||
impl error::Error for E {}
|
||||
|
||||
let x: Result<Infallible, E> = Err(E);
|
||||
let result_of_x: Result<Infallible, E> = x.into_result();
|
||||
|
||||
assert_eq!(result_of_x.unwrap_err(), E);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Implement `WasmTypeList` on `Infallible`, which means that
|
||||
// `Infallible` can be used as a returned type of a host function
|
||||
// to express that it doesn't return, or to express that it cannot
|
||||
// fail (with `Result<_, Infallible>`).
|
||||
impl WasmTypeList for Infallible {
|
||||
type CStruct = Self;
|
||||
type Array = [RawValue; 0];
|
||||
|
||||
fn size() -> u32 {
|
||||
0
|
||||
}
|
||||
|
||||
unsafe fn from_array(_: &mut impl AsStoreMut, _: Self::Array) -> Self {
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
unsafe fn from_slice(
|
||||
_: &mut impl AsStoreMut,
|
||||
_: &[RawValue],
|
||||
) -> Result<Self, TryFromSliceError> {
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
unsafe fn into_array(self, _: &mut impl AsStoreMut) -> Self::Array {
|
||||
[]
|
||||
}
|
||||
|
||||
fn empty_array() -> Self::Array {
|
||||
[]
|
||||
}
|
||||
|
||||
unsafe fn from_c_struct(_: &mut impl AsStoreMut, self_: Self::CStruct) -> Self {
|
||||
self_
|
||||
}
|
||||
|
||||
unsafe fn into_c_struct(self, _: &mut impl AsStoreMut) -> Self::CStruct {
|
||||
self
|
||||
}
|
||||
|
||||
unsafe fn write_c_struct_to_ptr(_: Self::CStruct, _: *mut RawValue) {}
|
||||
|
||||
fn wasm_types() -> &'static [Type] {
|
||||
&[]
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_wasm_type_list {
|
||||
use super::*;
|
||||
use wasmer_types::Type;
|
||||
/*
|
||||
#[test]
|
||||
fn test_from_array() {
|
||||
let mut store = Store::default();
|
||||
let env = FunctionEnv::new(&mut store, ());
|
||||
assert_eq!(<()>::from_array(&mut env, []), ());
|
||||
assert_eq!(<i32>::from_array(&mut env, [RawValue{i32: 1}]), (1i32));
|
||||
assert_eq!(<(i32, i64)>::from_array(&mut env, [RawValue{i32:1}, RawValue{i64:2}]), (1i32, 2i64));
|
||||
assert_eq!(
|
||||
<(i32, i64, f32, f64)>::from_array(&mut env, [
|
||||
RawValue{i32:1},
|
||||
RawValue{i64:2},
|
||||
RawValue{f32: 3.1f32},
|
||||
RawValue{f64: 4.2f64}
|
||||
]),
|
||||
(1, 2, 3.1f32, 4.2f64)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_into_array() {
|
||||
let mut store = Store::default();
|
||||
let env = FunctionEnv::new(&mut store, ());
|
||||
assert_eq!(().into_array(&mut store), [0i128; 0]);
|
||||
assert_eq!((1i32).into_array(&mut store), [1i32]);
|
||||
assert_eq!((1i32, 2i64).into_array(&mut store), [RawValue{i32: 1}, RawValue{i64: 2}]);
|
||||
assert_eq!(
|
||||
(1i32, 2i32, 3.1f32, 4.2f64).into_array(&mut store),
|
||||
[RawValue{i32: 1}, RawValue{i32: 2}, RawValue{ f32: 3.1f32}, RawValue{f64: 4.2f64}]
|
||||
);
|
||||
}
|
||||
*/
|
||||
#[test]
|
||||
fn test_empty_array() {
|
||||
assert_eq!(<()>::empty_array().len(), 0);
|
||||
assert_eq!(<i32>::empty_array().len(), 1);
|
||||
assert_eq!(<(i32, i64)>::empty_array().len(), 2);
|
||||
}
|
||||
/*
|
||||
#[test]
|
||||
fn test_from_c_struct() {
|
||||
let mut store = Store::default();
|
||||
let env = FunctionEnv::new(&mut store, ());
|
||||
assert_eq!(<()>::from_c_struct(&mut store, S0()), ());
|
||||
assert_eq!(<i32>::from_c_struct(&mut store, S1(1)), (1i32));
|
||||
assert_eq!(<(i32, i64)>::from_c_struct(&mut store, S2(1, 2)), (1i32, 2i64));
|
||||
assert_eq!(
|
||||
<(i32, i64, f32, f64)>::from_c_struct(&mut store, S4(1, 2, 3.1, 4.2)),
|
||||
(1i32, 2i64, 3.1f32, 4.2f64)
|
||||
);
|
||||
}
|
||||
*/
|
||||
#[test]
|
||||
fn test_wasm_types_for_uni_values() {
|
||||
assert_eq!(<i32>::wasm_types(), [Type::I32]);
|
||||
assert_eq!(<i64>::wasm_types(), [Type::I64]);
|
||||
assert_eq!(<f32>::wasm_types(), [Type::F32]);
|
||||
assert_eq!(<f64>::wasm_types(), [Type::F64]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_wasm_types_for_multi_values() {
|
||||
assert_eq!(<(i32, i32)>::wasm_types(), [Type::I32, Type::I32]);
|
||||
assert_eq!(<(i64, i64)>::wasm_types(), [Type::I64, Type::I64]);
|
||||
assert_eq!(<(f32, f32)>::wasm_types(), [Type::F32, Type::F32]);
|
||||
assert_eq!(<(f64, f64)>::wasm_types(), [Type::F64, Type::F64]);
|
||||
|
||||
assert_eq!(
|
||||
<(i32, i64, f32, f64)>::wasm_types(),
|
||||
[Type::I32, Type::I64, Type::F32, Type::F64]
|
||||
);
|
||||
}
|
||||
}
|
||||
/*
|
||||
#[allow(non_snake_case)]
|
||||
#[cfg(test)]
|
||||
mod test_function {
|
||||
use super::*;
|
||||
use crate::Store;
|
||||
use crate::FunctionEnv;
|
||||
use wasmer_types::Type;
|
||||
|
||||
fn func() {}
|
||||
fn func__i32() -> i32 {
|
||||
0
|
||||
}
|
||||
fn func_i32( _a: i32) {}
|
||||
fn func_i32__i32( a: i32) -> i32 {
|
||||
a * 2
|
||||
}
|
||||
fn func_i32_i32__i32( a: i32, b: i32) -> i32 {
|
||||
a + b
|
||||
}
|
||||
fn func_i32_i32__i32_i32( a: i32, b: i32) -> (i32, i32) {
|
||||
(a, b)
|
||||
}
|
||||
fn func_f32_i32__i32_f32( a: f32, b: i32) -> (i32, f32) {
|
||||
(b, a)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_function_types() {
|
||||
let mut store = Store::default();
|
||||
let env = FunctionEnv::new(&mut store, ());
|
||||
use wasmer_types::FunctionType;
|
||||
assert_eq!(
|
||||
StaticFunction::new(func).ty(&mut store),
|
||||
FunctionType::new(vec![], vec![])
|
||||
);
|
||||
assert_eq!(
|
||||
StaticFunction::new(func__i32).ty(&mut store),
|
||||
FunctionType::new(vec![], vec![Type::I32])
|
||||
);
|
||||
assert_eq!(
|
||||
StaticFunction::new(func_i32).ty(),
|
||||
FunctionType::new(vec![Type::I32], vec![])
|
||||
);
|
||||
assert_eq!(
|
||||
StaticFunction::new(func_i32__i32).ty(),
|
||||
FunctionType::new(vec![Type::I32], vec![Type::I32])
|
||||
);
|
||||
assert_eq!(
|
||||
StaticFunction::new(func_i32_i32__i32).ty(),
|
||||
FunctionType::new(vec![Type::I32, Type::I32], vec![Type::I32])
|
||||
);
|
||||
assert_eq!(
|
||||
StaticFunction::new(func_i32_i32__i32_i32).ty(),
|
||||
FunctionType::new(vec![Type::I32, Type::I32], vec![Type::I32, Type::I32])
|
||||
);
|
||||
assert_eq!(
|
||||
StaticFunction::new(func_f32_i32__i32_f32).ty(),
|
||||
FunctionType::new(vec![Type::F32, Type::I32], vec![Type::I32, Type::F32])
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_function_pointer() {
|
||||
let f = StaticFunction::new(func_i32__i32);
|
||||
let function = unsafe { std::mem::transmute::<_, fn(usize, i32) -> i32>(f.address) };
|
||||
assert_eq!(function(0, 3), 6);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_native_type {
|
||||
use super::*;
|
||||
|
||||
1044
lib/api/src/sys/externals/function.rs
vendored
1044
lib/api/src/sys/externals/function.rs
vendored
File diff suppressed because it is too large
Load Diff
@@ -20,8 +20,8 @@ pub(crate) mod vm {
|
||||
//! The `vm` module re-exports wasmer-vm types.
|
||||
use wasmer_vm::InternalStoreHandle;
|
||||
pub(crate) use wasmer_vm::{
|
||||
VMExtern, VMExternRef, VMFuncRef, VMFunction, VMFunctionEnvironment, VMGlobal, VMMemory,
|
||||
VMTable,
|
||||
VMExtern, VMExternRef, VMFuncRef, VMFunction, VMFunctionBody, VMFunctionEnvironment,
|
||||
VMGlobal, VMMemory, VMTable, VMTrampoline,
|
||||
};
|
||||
|
||||
pub(crate) type VMExternTable = InternalStoreHandle<VMTable>;
|
||||
|
||||
@@ -17,7 +17,7 @@ macro_rules! impl_native_traits {
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn call(&self, store: &mut impl AsStoreMut, $( $x: $x, )* ) -> Result<Rets, RuntimeError> {
|
||||
let anyfunc = unsafe {
|
||||
*self.func
|
||||
*self.func.0
|
||||
.handle
|
||||
.get(store.as_store_ref().objects())
|
||||
.anyfunc
|
||||
@@ -103,7 +103,7 @@ macro_rules! impl_native_traits {
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn call_raw(&self, store: &mut impl AsStoreMut, mut params_list: Vec<RawValue> ) -> Result<Rets, RuntimeError> {
|
||||
let anyfunc = unsafe {
|
||||
*self.func
|
||||
*self.func.0
|
||||
.handle
|
||||
.get(store.as_store_ref().objects())
|
||||
.anyfunc
|
||||
|
||||
@@ -3,13 +3,14 @@
|
||||
#[cfg(feature = "js")]
|
||||
pub(crate) use crate::js::vm::{
|
||||
VMExtern, VMExternFunction, VMExternGlobal, VMExternMemory, VMExternRef, VMExternTable,
|
||||
VMFuncRef, VMFunction, VMFunctionEnvironment, VMGlobal, VMMemory, VMTable,
|
||||
VMFuncRef, VMFunction, VMFunctionBody, VMFunctionEnvironment, VMGlobal, VMMemory, VMTable,
|
||||
VMTrampoline,
|
||||
};
|
||||
|
||||
#[cfg(feature = "sys")]
|
||||
pub(crate) use crate::sys::vm::{
|
||||
VMExtern, VMExternFunction, VMExternGlobal, VMExternMemory, VMExternRef, VMExternTable,
|
||||
VMFuncRef, VMFunctionEnvironment,
|
||||
VMFuncRef, VMFunctionBody, VMFunctionEnvironment, VMTrampoline,
|
||||
};
|
||||
|
||||
// Needed for tunables customization
|
||||
|
||||
Reference in New Issue
Block a user