mirror of
https://github.com/mii443/wasmer.git
synced 2025-12-09 22:28:21 +00:00
Merge branch 'master' into capi-wasi-overwrite-stdin-3
This commit is contained in:
@@ -14,6 +14,7 @@ Looking for changes that affect our C API? See the [C API Changelog](lib/c-api/C
|
|||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- #[3131](https://github.com/wasmerio/wasmer/pull/3131) Update migration docs for MemoryView changes
|
- #[3131](https://github.com/wasmerio/wasmer/pull/3131) Update migration docs for MemoryView changes
|
||||||
|
- #[3129](https://github.com/wasmerio/wasmer/pull/3129) Fix differences between -sys and -js API
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- #[3130](https://github.com/wasmerio/wasmer/pull/3130) Remove panics from Artifact::deserialize
|
- #[3130](https://github.com/wasmerio/wasmer/pull/3130) Remove panics from Artifact::deserialize
|
||||||
|
|||||||
9
Cargo.lock
generated
9
Cargo.lock
generated
@@ -2923,6 +2923,7 @@ name = "wasmer"
|
|||||||
version = "3.0.0-beta"
|
version = "3.0.0-beta"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
|
"bytes",
|
||||||
"cfg-if 1.0.0",
|
"cfg-if 1.0.0",
|
||||||
"hashbrown 0.11.2",
|
"hashbrown 0.11.2",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
@@ -3220,11 +3221,7 @@ dependencies = [
|
|||||||
name = "wasmer-vbus"
|
name = "wasmer-vbus"
|
||||||
version = "3.0.0-beta"
|
version = "3.0.0-beta"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
|
||||||
"slab",
|
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tracing",
|
|
||||||
"typetag",
|
|
||||||
"wasmer-vfs",
|
"wasmer-vfs",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -3268,11 +3265,7 @@ name = "wasmer-vnet"
|
|||||||
version = "3.0.0-beta"
|
version = "3.0.0-beta"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"libc",
|
|
||||||
"slab",
|
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tracing",
|
|
||||||
"typetag",
|
|
||||||
"wasmer-vfs",
|
"wasmer-vfs",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -195,14 +195,13 @@ import_object.define("env", "host_function", host_function);
|
|||||||
let instance = Instance::new(&mut store, &module, &import_object).expect("Could not instantiate module.");
|
let instance = Instance::new(&mut store, &module, &import_object).expect("Could not instantiate module.");
|
||||||
```
|
```
|
||||||
|
|
||||||
For WASI, don't forget to import memory to `WasiEnv`
|
For WASI, don't forget to initialize the `WasiEnv` (it will import the memory)
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
let mut wasi_env = WasiState::new("hello").finalize()?;
|
let mut wasi_env = WasiState::new("hello").finalize()?;
|
||||||
let import_object = wasi_env.import_object(&mut store, &module)?;
|
let import_object = wasi_env.import_object(&mut store, &module)?;
|
||||||
let instance = Instance::new(&mut store, &module, &import_object).expect("Could not instantiate module.");
|
let instance = Instance::new(&mut store, &module, &import_object).expect("Could not instantiate module.");
|
||||||
let memory = instance.exports.get_memory("memory")?;
|
wasi_env.initialize(&mut store, &instance).unwrap();
|
||||||
wasi_env.data_mut(&mut store).set_memory(memory.clone());
|
|
||||||
```
|
```
|
||||||
|
|
||||||
#### `ChainableNamedResolver` is removed
|
#### `ChainableNamedResolver` is removed
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ indexmap = { version = "1.6" }
|
|||||||
cfg-if = "1.0"
|
cfg-if = "1.0"
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
more-asserts = "0.2"
|
more-asserts = "0.2"
|
||||||
|
bytes = "1"
|
||||||
# - Optional shared dependencies.
|
# - Optional shared dependencies.
|
||||||
wat = { version = "1.0", optional = true }
|
wat = { version = "1.0", optional = true }
|
||||||
tracing = { version = "0.1", optional = true }
|
tracing = { version = "0.1", optional = true }
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ use crate::js::trap::RuntimeError;
|
|||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
use wasmer_types::ImportError;
|
||||||
|
|
||||||
// Compilation Errors
|
// Compilation Errors
|
||||||
//
|
//
|
||||||
@@ -144,6 +145,28 @@ pub enum DeserializeError {
|
|||||||
Compiler(CompileError),
|
Compiler(CompileError),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The WebAssembly.LinkError object indicates an error during
|
||||||
|
/// module instantiation (besides traps from the start function).
|
||||||
|
///
|
||||||
|
/// This is based on the [link error][link-error] API.
|
||||||
|
///
|
||||||
|
/// [link-error]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/LinkError
|
||||||
|
#[derive(Error, Debug)]
|
||||||
|
#[error("Link error: {0}")]
|
||||||
|
pub enum LinkError {
|
||||||
|
/// An error occurred when checking the import types.
|
||||||
|
#[error("Error while importing {0:?}.{1:?}: {2}")]
|
||||||
|
Import(String, String, ImportError),
|
||||||
|
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
/// A trap ocurred during linking.
|
||||||
|
#[error("RuntimeError occurred during linking: {0}")]
|
||||||
|
Trap(#[source] RuntimeError),
|
||||||
|
/// Insufficient resources available for linking.
|
||||||
|
#[error("Insufficient resources: {0}")]
|
||||||
|
Resource(String),
|
||||||
|
}
|
||||||
|
|
||||||
/// An error while instantiating a module.
|
/// An error while instantiating a module.
|
||||||
///
|
///
|
||||||
/// This is not a common WebAssembly error, however
|
/// This is not a common WebAssembly error, however
|
||||||
@@ -156,13 +179,18 @@ pub enum DeserializeError {
|
|||||||
#[cfg_attr(feature = "std", derive(Error))]
|
#[cfg_attr(feature = "std", derive(Error))]
|
||||||
pub enum InstantiationError {
|
pub enum InstantiationError {
|
||||||
/// A linking ocurred during instantiation.
|
/// A linking ocurred during instantiation.
|
||||||
#[cfg_attr(feature = "std", error("Link error: {0}"))]
|
#[cfg_attr(feature = "std", error(transparent))]
|
||||||
Link(String),
|
Link(LinkError),
|
||||||
|
|
||||||
/// A runtime error occured while invoking the start function
|
/// A runtime error occured while invoking the start function
|
||||||
#[cfg_attr(feature = "std", error(transparent))]
|
#[cfg_attr(feature = "std", error(transparent))]
|
||||||
Start(RuntimeError),
|
Start(RuntimeError),
|
||||||
|
|
||||||
|
/// The module was compiled with a CPU feature that is not available on
|
||||||
|
/// the current host.
|
||||||
|
#[cfg_attr(feature = "std", error("missing required CPU features: {0:?}"))]
|
||||||
|
CpuFeature(String),
|
||||||
|
|
||||||
/// Import from a different [`Store`].
|
/// Import from a different [`Store`].
|
||||||
/// This error occurs when an import from a different store is used.
|
/// This error occurs when an import from a different store is used.
|
||||||
#[cfg_attr(feature = "std", error("cannot mix imports from different stores"))]
|
#[cfg_attr(feature = "std", error("cannot mix imports from different stores"))]
|
||||||
@@ -171,6 +199,10 @@ pub enum InstantiationError {
|
|||||||
/// A generic error occured while invoking API functions
|
/// A generic error occured while invoking API functions
|
||||||
#[cfg_attr(feature = "std", error(transparent))]
|
#[cfg_attr(feature = "std", error(transparent))]
|
||||||
Wasm(WasmError),
|
Wasm(WasmError),
|
||||||
|
|
||||||
|
/// Insufficient resources available for execution.
|
||||||
|
#[cfg_attr(feature = "std", error("Can't get {0} from the instance exports"))]
|
||||||
|
NotInExports(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<WasmError> for InstantiationError {
|
impl From<WasmError> for InstantiationError {
|
||||||
|
|||||||
42
lib/api/src/js/externals/function.rs
vendored
42
lib/api/src/js/externals/function.rs
vendored
@@ -1,6 +1,6 @@
|
|||||||
pub use self::inner::{FromToNativeWasmType, HostFunction, WasmTypeList, WithEnv, WithoutEnv};
|
pub use self::inner::{FromToNativeWasmType, HostFunction, WasmTypeList, WithEnv, WithoutEnv};
|
||||||
use crate::js::exports::{ExportError, Exportable};
|
use crate::js::exports::{ExportError, Exportable};
|
||||||
use crate::js::externals::Extern;
|
use crate::js::externals::{Extern, VMExtern};
|
||||||
use crate::js::function_env::FunctionEnvMut;
|
use crate::js::function_env::FunctionEnvMut;
|
||||||
use crate::js::store::{AsStoreMut, AsStoreRef, InternalStoreHandle, StoreHandle, StoreMut};
|
use crate::js::store::{AsStoreMut, AsStoreRef, InternalStoreHandle, StoreHandle, StoreMut};
|
||||||
use crate::js::types::{param_from_js, AsJs}; /* ValFuncRef */
|
use crate::js::types::{param_from_js, AsJs}; /* ValFuncRef */
|
||||||
@@ -26,6 +26,7 @@ fn result_to_js(val: &Value) -> JsValue {
|
|||||||
Value::I64(i) => JsValue::from_f64(*i as _),
|
Value::I64(i) => JsValue::from_f64(*i as _),
|
||||||
Value::F32(f) => JsValue::from_f64(*f as _),
|
Value::F32(f) => JsValue::from_f64(*f as _),
|
||||||
Value::F64(f) => JsValue::from_f64(*f),
|
Value::F64(f) => JsValue::from_f64(*f),
|
||||||
|
Value::V128(f) => JsValue::from_f64(*f as _),
|
||||||
val => unimplemented!(
|
val => unimplemented!(
|
||||||
"The value `{:?}` is not yet supported in the JS Function API",
|
"The value `{:?}` is not yet supported in the JS Function API",
|
||||||
val
|
val
|
||||||
@@ -77,6 +78,11 @@ impl Function {
|
|||||||
Self::new_with_env(store, &env, ty, wrapped_func)
|
Self::new_with_env(store, &env, ty, wrapped_func)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// To `VMExtern`.
|
||||||
|
pub fn to_vm_extern(&self) -> VMExtern {
|
||||||
|
VMExtern::Function(self.handle.internal_handle())
|
||||||
|
}
|
||||||
|
|
||||||
/// Creates a new host `Function` (dynamic) with the provided signature.
|
/// Creates a new host `Function` (dynamic) with the provided signature.
|
||||||
///
|
///
|
||||||
/// If you know the signature of the host function at compile time,
|
/// If you know the signature of the host function at compile time,
|
||||||
@@ -229,13 +235,13 @@ impl Function {
|
|||||||
note = "new_native_with_env() has been renamed to new_typed_with_env()."
|
note = "new_native_with_env() has been renamed to new_typed_with_env()."
|
||||||
)]
|
)]
|
||||||
/// Creates a new host `Function` with an environment from a typed function.
|
/// Creates a new host `Function` with an environment from a typed function.
|
||||||
pub fn new_native_with_env<T, F, Args, Rets>(
|
pub fn new_native_with_env<T: Send + 'static, F, Args, Rets>(
|
||||||
store: &mut impl AsStoreMut,
|
store: &mut impl AsStoreMut,
|
||||||
env: &FunctionEnv<T>,
|
env: &FunctionEnv<T>,
|
||||||
func: F,
|
func: F,
|
||||||
) -> Self
|
) -> Self
|
||||||
where
|
where
|
||||||
F: HostFunction<T, Args, Rets, WithEnv>,
|
F: HostFunction<T, Args, Rets, WithEnv> + 'static + Send + Sync,
|
||||||
Args: WasmTypeList,
|
Args: WasmTypeList,
|
||||||
Rets: WasmTypeList,
|
Rets: WasmTypeList,
|
||||||
{
|
{
|
||||||
@@ -309,8 +315,8 @@ impl Function {
|
|||||||
/// assert_eq!(f.ty().params(), vec![Type::I32, Type::I32]);
|
/// assert_eq!(f.ty().params(), vec![Type::I32, Type::I32]);
|
||||||
/// assert_eq!(f.ty().results(), vec![Type::I32]);
|
/// assert_eq!(f.ty().results(), vec![Type::I32]);
|
||||||
/// ```
|
/// ```
|
||||||
pub fn ty<'context>(&self, store: &'context impl AsStoreRef) -> &'context FunctionType {
|
pub fn ty(&self, store: &impl AsStoreRef) -> FunctionType {
|
||||||
&self.handle.get(store.as_store_ref().objects()).ty
|
self.handle.get(store.as_store_ref().objects()).ty.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the number of parameters that this function takes.
|
/// Returns the number of parameters that this function takes.
|
||||||
@@ -598,7 +604,7 @@ mod inner {
|
|||||||
use super::RuntimeError;
|
use super::RuntimeError;
|
||||||
use super::VMFunctionBody;
|
use super::VMFunctionBody;
|
||||||
use crate::js::function_env::{FunctionEnvMut, VMFunctionEnvironment};
|
use crate::js::function_env::{FunctionEnvMut, VMFunctionEnvironment};
|
||||||
use crate::js::store::{AsStoreMut, InternalStoreHandle, StoreHandle, StoreMut};
|
use crate::js::store::{AsStoreMut, AsStoreRef, InternalStoreHandle, StoreHandle, StoreMut};
|
||||||
use crate::js::FunctionEnv;
|
use crate::js::FunctionEnv;
|
||||||
use crate::js::NativeWasmTypeInto;
|
use crate::js::NativeWasmTypeInto;
|
||||||
use std::array::TryFromSliceError;
|
use std::array::TryFromSliceError;
|
||||||
@@ -639,6 +645,9 @@ mod inner {
|
|||||||
/// This method panics if `self` cannot fit in the
|
/// This method panics if `self` cannot fit in the
|
||||||
/// `Self::Native` type.
|
/// `Self::Native` type.
|
||||||
fn to_native(self) -> Self::Native;
|
fn to_native(self) -> Self::Native;
|
||||||
|
|
||||||
|
/// Returns whether this native type belongs to the given store
|
||||||
|
fn is_from_store(&self, _store: &impl AsStoreRef) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! from_to_native_wasm_type {
|
macro_rules! from_to_native_wasm_type {
|
||||||
@@ -657,6 +666,11 @@ mod inner {
|
|||||||
fn to_native(self) -> Self::Native {
|
fn to_native(self) -> Self::Native {
|
||||||
self as Self::Native
|
self as Self::Native
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn is_from_store(&self, _store: &impl AsStoreRef) -> bool {
|
||||||
|
true // Javascript only has one store
|
||||||
|
}
|
||||||
}
|
}
|
||||||
)*
|
)*
|
||||||
};
|
};
|
||||||
@@ -678,6 +692,11 @@ mod inner {
|
|||||||
fn to_native(self) -> Self::Native {
|
fn to_native(self) -> Self::Native {
|
||||||
Self::Native::from_ne_bytes(Self::to_ne_bytes(self))
|
Self::Native::from_ne_bytes(Self::to_ne_bytes(self))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn is_from_store(&self, _store: &impl AsStoreRef) -> bool {
|
||||||
|
true // Javascript only has one store
|
||||||
|
}
|
||||||
}
|
}
|
||||||
)*
|
)*
|
||||||
};
|
};
|
||||||
@@ -887,11 +906,12 @@ mod inner {
|
|||||||
Args: WasmTypeList,
|
Args: WasmTypeList,
|
||||||
Rets: WasmTypeList,
|
Rets: WasmTypeList,
|
||||||
Kind: HostFunctionKind,
|
Kind: HostFunctionKind,
|
||||||
T: Sized,
|
|
||||||
Self: Sized,
|
|
||||||
{
|
{
|
||||||
/// Get the pointer to the function body.
|
/// Get the pointer to the function body.
|
||||||
fn function_body_ptr(self) -> *const VMFunctionBody;
|
fn function_body_ptr(&self) -> *const VMFunctionBody;
|
||||||
|
|
||||||
|
// /// Get the pointer to the function call trampoline.
|
||||||
|
// fn call_trampoline_address() -> VMTrampoline;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Empty trait to specify the kind of `HostFunction`: With or
|
/// Empty trait to specify the kind of `HostFunction`: With or
|
||||||
@@ -1102,7 +1122,7 @@ mod inner {
|
|||||||
Func: Fn(FunctionEnvMut<'_, T>, $( $x , )*) -> RetsAsResult + 'static,
|
Func: Fn(FunctionEnvMut<'_, T>, $( $x , )*) -> RetsAsResult + 'static,
|
||||||
{
|
{
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
fn function_body_ptr(self) -> *const VMFunctionBody {
|
fn function_body_ptr(&self) -> *const VMFunctionBody {
|
||||||
/// This is a function that wraps the real host
|
/// This is a function that wraps the real host
|
||||||
/// function. Its address will be used inside the
|
/// function. Its address will be used inside the
|
||||||
/// runtime.
|
/// runtime.
|
||||||
@@ -1150,7 +1170,7 @@ mod inner {
|
|||||||
Func: Fn($( $x , )*) -> RetsAsResult + 'static,
|
Func: Fn($( $x , )*) -> RetsAsResult + 'static,
|
||||||
{
|
{
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
fn function_body_ptr(self) -> *const VMFunctionBody {
|
fn function_body_ptr(&self) -> *const VMFunctionBody {
|
||||||
/// This is a function that wraps the real host
|
/// This is a function that wraps the real host
|
||||||
/// function. Its address will be used inside the
|
/// function. Its address will be used inside the
|
||||||
/// runtime.
|
/// runtime.
|
||||||
|
|||||||
16
lib/api/src/js/externals/global.rs
vendored
16
lib/api/src/js/externals/global.rs
vendored
@@ -1,6 +1,6 @@
|
|||||||
use crate::js::export::VMGlobal;
|
use crate::js::export::VMGlobal;
|
||||||
use crate::js::exports::{ExportError, Exportable};
|
use crate::js::exports::{ExportError, Exportable};
|
||||||
use crate::js::externals::Extern;
|
use crate::js::externals::{Extern, VMExtern};
|
||||||
use crate::js::store::{AsStoreMut, AsStoreRef, InternalStoreHandle, StoreHandle};
|
use crate::js::store::{AsStoreMut, AsStoreRef, InternalStoreHandle, StoreHandle};
|
||||||
use crate::js::value::Value;
|
use crate::js::value::Value;
|
||||||
use crate::js::wasm_bindgen_polyfill::Global as JSGlobal;
|
use crate::js::wasm_bindgen_polyfill::Global as JSGlobal;
|
||||||
@@ -55,6 +55,11 @@ impl Global {
|
|||||||
Self::from_value(store, val, Mutability::Var).unwrap()
|
Self::from_value(store, val, Mutability::Var).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// To `VMExtern`.
|
||||||
|
pub(crate) fn to_vm_extern(&self) -> VMExtern {
|
||||||
|
VMExtern::Global(self.handle.internal_handle())
|
||||||
|
}
|
||||||
|
|
||||||
/// Create a `Global` with the initial value [`Value`] and the provided [`Mutability`].
|
/// Create a `Global` with the initial value [`Value`] and the provided [`Mutability`].
|
||||||
fn from_value(
|
fn from_value(
|
||||||
store: &mut impl AsStoreMut,
|
store: &mut impl AsStoreMut,
|
||||||
@@ -135,15 +140,6 @@ impl Global {
|
|||||||
let ty = self.handle.get(store.as_store_ref().objects()).ty;
|
let ty = self.handle.get(store.as_store_ref().objects()).ty;
|
||||||
Value::from_raw(store, ty.ty, raw)
|
Value::from_raw(store, ty.ty, raw)
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
match self.vm_global.ty.ty {
|
|
||||||
ValType::I32 => Value::I32(self.vm_global.global.value().as_f64().unwrap() as _),
|
|
||||||
ValType::I64 => Value::I64(self.vm_global.global.value().as_f64().unwrap() as _),
|
|
||||||
ValType::F32 => Value::F32(self.vm_global.global.value().as_f64().unwrap() as _),
|
|
||||||
ValType::F64 => Value::F64(self.vm_global.global.value().as_f64().unwrap()),
|
|
||||||
_ => unimplemented!("The type is not yet supported in the JS Global API"),
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets a custom value [`Value`] to the runtime Global.
|
/// Sets a custom value [`Value`] to the runtime Global.
|
||||||
|
|||||||
13
lib/api/src/js/externals/memory.rs
vendored
13
lib/api/src/js/externals/memory.rs
vendored
@@ -1,6 +1,6 @@
|
|||||||
use crate::js::export::VMMemory;
|
use crate::js::export::VMMemory;
|
||||||
use crate::js::exports::{ExportError, Exportable};
|
use crate::js::exports::{ExportError, Exportable};
|
||||||
use crate::js::externals::Extern;
|
use crate::js::externals::{Extern, VMExtern};
|
||||||
use crate::js::store::{AsStoreMut, AsStoreRef, InternalStoreHandle, StoreHandle, StoreObjects};
|
use crate::js::store::{AsStoreMut, AsStoreRef, InternalStoreHandle, StoreHandle, StoreObjects};
|
||||||
use crate::js::{MemoryAccessError, MemoryType};
|
use crate::js::{MemoryAccessError, MemoryType};
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
@@ -118,6 +118,11 @@ impl Memory {
|
|||||||
Self::from_vm_extern(new_store, handle.internal_handle())
|
Self::from_vm_extern(new_store, handle.internal_handle())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// To `VMExtern`.
|
||||||
|
pub(crate) fn to_vm_extern(&self) -> VMExtern {
|
||||||
|
VMExtern::Memory(self.handle.internal_handle())
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the [`MemoryType`] of the `Memory`.
|
/// Returns the [`MemoryType`] of the `Memory`.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
@@ -218,6 +223,12 @@ impl Memory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl std::cmp::PartialEq for Memory {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
self.handle == other.handle
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> Exportable<'a> for Memory {
|
impl<'a> Exportable<'a> for Memory {
|
||||||
fn get_self_from_extern(_extern: &'a Extern) -> Result<&'a Self, ExportError> {
|
fn get_self_from_extern(_extern: &'a Extern) -> Result<&'a Self, ExportError> {
|
||||||
match _extern {
|
match _extern {
|
||||||
|
|||||||
137
lib/api/src/js/externals/mod.rs
vendored
137
lib/api/src/js/externals/mod.rs
vendored
@@ -10,13 +10,122 @@ pub use self::memory::{Memory, MemoryError};
|
|||||||
pub use self::memory_view::MemoryView;
|
pub use self::memory_view::MemoryView;
|
||||||
pub use self::table::Table;
|
pub use self::table::Table;
|
||||||
|
|
||||||
use crate::js::export::Export;
|
use crate::js::export::{Export, VMFunction, VMGlobal, VMMemory, VMTable};
|
||||||
use crate::js::exports::{ExportError, Exportable};
|
use crate::js::exports::{ExportError, Exportable};
|
||||||
use crate::js::store::StoreObject;
|
use crate::js::store::StoreObject;
|
||||||
use crate::js::store::{AsStoreMut, AsStoreRef};
|
|
||||||
use crate::js::types::AsJs;
|
use crate::js::types::AsJs;
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
|
||||||
|
use crate::js::store::InternalStoreHandle;
|
||||||
|
use crate::js::store::{AsStoreMut, AsStoreRef};
|
||||||
use crate::js::ExternType;
|
use crate::js::ExternType;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
*/
|
||||||
|
use crate::js::error::WasmError;
|
||||||
|
use crate::js::store::{AsStoreMut, AsStoreRef, InternalStoreHandle};
|
||||||
|
use crate::js::wasm_bindgen_polyfill::Global as JsGlobal;
|
||||||
|
use js_sys::Function as JsFunction;
|
||||||
|
use js_sys::WebAssembly::{Memory as JsMemory, Table as JsTable};
|
||||||
|
use std::fmt;
|
||||||
|
use wasm_bindgen::{JsCast, JsValue};
|
||||||
|
use wasmer_types::{ExternType, FunctionType, GlobalType, MemoryType, TableType};
|
||||||
|
|
||||||
|
/// The value of an export passed from one instance to another.
|
||||||
|
pub enum VMExtern {
|
||||||
|
/// 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 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::<JsMemory>() {
|
||||||
|
Ok(Self::Memory(InternalStoreHandle::new(
|
||||||
|
&mut store.objects_mut(),
|
||||||
|
VMMemory::new(val.unchecked_into::<JsMemory>(), 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::<JsGlobal>() {
|
||||||
|
Ok(Self::Global(InternalStoreHandle::new(
|
||||||
|
&mut store.objects_mut(),
|
||||||
|
VMGlobal::new(val.unchecked_into::<JsGlobal>(), global_type),
|
||||||
|
)))
|
||||||
|
} else {
|
||||||
|
panic!("Extern type doesn't match js value type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ExternType::Function(function_type) => {
|
||||||
|
if val.is_instance_of::<JsFunction>() {
|
||||||
|
Ok(Self::Function(InternalStoreHandle::new(
|
||||||
|
&mut store.objects_mut(),
|
||||||
|
VMFunction::new(val.unchecked_into::<JsFunction>(), function_type),
|
||||||
|
)))
|
||||||
|
} else {
|
||||||
|
panic!("Extern type doesn't match js value type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ExternType::Table(table_type) => {
|
||||||
|
if val.is_instance_of::<JsTable>() {
|
||||||
|
Ok(Self::Table(InternalStoreHandle::new(
|
||||||
|
&mut store.objects_mut(),
|
||||||
|
VMTable::new(val.unchecked_into::<JsTable>(), table_type),
|
||||||
|
)))
|
||||||
|
} else {
|
||||||
|
panic!("Extern type doesn't match js value type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// An `Extern` is the runtime representation of an entity that
|
/// An `Extern` is the runtime representation of an entity that
|
||||||
/// can be imported or exported.
|
/// can be imported or exported.
|
||||||
@@ -45,13 +154,23 @@ impl Extern {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create an `Extern` from an `wasmer_compiler::Export`.
|
/// Create an `Extern` from an `wasmer_engine::Export`.
|
||||||
pub fn from_vm_extern(store: &mut impl AsStoreMut, export: Export) -> Self {
|
pub fn from_vm_extern(store: &mut impl AsStoreMut, vm_extern: VMExtern) -> Self {
|
||||||
match export {
|
match vm_extern {
|
||||||
Export::Function(f) => Self::Function(Function::from_vm_extern(store, f)),
|
VMExtern::Function(f) => Self::Function(Function::from_vm_extern(store, f)),
|
||||||
Export::Memory(m) => Self::Memory(Memory::from_vm_extern(store, m)),
|
VMExtern::Memory(m) => Self::Memory(Memory::from_vm_extern(store, m)),
|
||||||
Export::Global(g) => Self::Global(Global::from_vm_extern(store, g)),
|
VMExtern::Global(g) => Self::Global(Global::from_vm_extern(store, g)),
|
||||||
Export::Table(t) => Self::Table(Table::from_vm_extern(store, t)),
|
VMExtern::Table(t) => Self::Table(Table::from_vm_extern(store, t)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// To `VMExtern`.
|
||||||
|
pub fn to_vm_extern(&self) -> VMExtern {
|
||||||
|
match self {
|
||||||
|
Self::Function(f) => f.to_vm_extern(),
|
||||||
|
Self::Global(g) => g.to_vm_extern(),
|
||||||
|
Self::Memory(m) => m.to_vm_extern(),
|
||||||
|
Self::Table(t) => t.to_vm_extern(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
8
lib/api/src/js/externals/table.rs
vendored
8
lib/api/src/js/externals/table.rs
vendored
@@ -1,6 +1,6 @@
|
|||||||
use crate::js::export::{VMFunction, VMTable};
|
use crate::js::export::{VMFunction, VMTable};
|
||||||
use crate::js::exports::{ExportError, Exportable};
|
use crate::js::exports::{ExportError, Exportable};
|
||||||
use crate::js::externals::Extern;
|
use crate::js::externals::{Extern, VMExtern};
|
||||||
use crate::js::store::{AsStoreMut, AsStoreRef, InternalStoreHandle, StoreHandle};
|
use crate::js::store::{AsStoreMut, AsStoreRef, InternalStoreHandle, StoreHandle};
|
||||||
use crate::js::value::Value;
|
use crate::js::value::Value;
|
||||||
use crate::js::RuntimeError;
|
use crate::js::RuntimeError;
|
||||||
@@ -75,6 +75,11 @@ impl Table {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// To `VMExtern`.
|
||||||
|
pub fn to_vm_extern(&self) -> VMExtern {
|
||||||
|
VMExtern::Table(self.handle.internal_handle())
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the [`TableType`] of the `Table`.
|
/// Returns the [`TableType`] of the `Table`.
|
||||||
pub fn ty(&self, store: &impl AsStoreRef) -> TableType {
|
pub fn ty(&self, store: &impl AsStoreRef) -> TableType {
|
||||||
self.handle.get(store.as_store_ref().objects()).ty
|
self.handle.get(store.as_store_ref().objects()).ty
|
||||||
@@ -143,6 +148,7 @@ impl Table {
|
|||||||
/// Returns an error if the range is out of bounds of either the source or
|
/// Returns an error if the range is out of bounds of either the source or
|
||||||
/// destination tables.
|
/// destination tables.
|
||||||
pub fn copy(
|
pub fn copy(
|
||||||
|
_store: &mut impl AsStoreMut,
|
||||||
_dst_table: &Self,
|
_dst_table: &Self,
|
||||||
_dst_index: u32,
|
_dst_index: u32,
|
||||||
_src_table: &Self,
|
_src_table: &Self,
|
||||||
|
|||||||
@@ -1,14 +1,17 @@
|
|||||||
//! The import module contains the implementation data structures and helper functions used to
|
//! The import module contains the implementation data structures and helper functions used to
|
||||||
//! manipulate and access a wasm module's imports including memories, tables, globals, and
|
//! manipulate and access a wasm module's imports including memories, tables, globals, and
|
||||||
//! functions.
|
//! functions.
|
||||||
use crate::js::error::InstantiationError;
|
use crate::js::error::{InstantiationError, LinkError, WasmError};
|
||||||
|
use crate::js::export::Export;
|
||||||
use crate::js::exports::Exports;
|
use crate::js::exports::Exports;
|
||||||
use crate::js::module::Module;
|
use crate::js::module::Module;
|
||||||
use crate::js::store::AsStoreRef;
|
use crate::js::store::{AsStoreMut, AsStoreRef};
|
||||||
use crate::js::types::AsJs;
|
use crate::js::types::AsJs;
|
||||||
|
use crate::js::ExternType;
|
||||||
use crate::Extern;
|
use crate::Extern;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
use wasmer_types::ImportError;
|
||||||
|
|
||||||
/// All of the import data used when instantiating.
|
/// All of the import data used when instantiating.
|
||||||
///
|
///
|
||||||
@@ -130,7 +133,7 @@ impl Imports {
|
|||||||
/// Resolve and return a vector of imports in the order they are defined in the `module`'s source code.
|
/// Resolve and return a vector of imports in the order they are defined in the `module`'s source code.
|
||||||
///
|
///
|
||||||
/// This means the returned `Vec<Extern>` might be a subset of the imports contained in `self`.
|
/// This means the returned `Vec<Extern>` might be a subset of the imports contained in `self`.
|
||||||
pub fn imports_for_module(&self, module: &Module) -> Result<Vec<Extern>, InstantiationError> {
|
pub fn imports_for_module(&self, module: &Module) -> Result<Vec<Extern>, LinkError> {
|
||||||
let mut ret = vec![];
|
let mut ret = vec![];
|
||||||
for import in module.imports() {
|
for import in module.imports() {
|
||||||
if let Some(imp) = self
|
if let Some(imp) = self
|
||||||
@@ -139,12 +142,11 @@ impl Imports {
|
|||||||
{
|
{
|
||||||
ret.push(imp.clone());
|
ret.push(imp.clone());
|
||||||
} else {
|
} else {
|
||||||
return Err(InstantiationError::Link(format!(
|
return Err(LinkError::Import(
|
||||||
"Error while importing {0:?}.{1:?}: unknown import. Expected {2:?}",
|
import.module().to_string(),
|
||||||
import.module(),
|
import.name().to_string(),
|
||||||
import.name(),
|
ImportError::UnknownImport(import.ty().clone()),
|
||||||
import.ty()
|
));
|
||||||
)));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(ret)
|
Ok(ret)
|
||||||
@@ -179,6 +181,81 @@ impl Imports {
|
|||||||
pub fn iter<'a>(&'a self) -> ImportsIterator<'a> {
|
pub fn iter<'a>(&'a self) -> ImportsIterator<'a> {
|
||||||
ImportsIterator::new(self)
|
ImportsIterator::new(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create a new `Imports` from a JS Object, it receives a reference to a `Module` to
|
||||||
|
/// map and assign the types of each import and the JS Object
|
||||||
|
/// that contains the values of imports.
|
||||||
|
///
|
||||||
|
/// # Usage
|
||||||
|
/// ```ignore
|
||||||
|
/// let import_object = Imports::new_from_js_object(&mut store, &module, js_object);
|
||||||
|
/// ```
|
||||||
|
pub fn new_from_js_object(
|
||||||
|
store: &mut impl AsStoreMut,
|
||||||
|
module: &Module,
|
||||||
|
object: js_sys::Object,
|
||||||
|
) -> Result<Self, WasmError> {
|
||||||
|
use crate::js::externals::VMExtern;
|
||||||
|
let module_imports: HashMap<(String, String), ExternType> = module
|
||||||
|
.imports()
|
||||||
|
.map(|import| {
|
||||||
|
(
|
||||||
|
(import.module().to_string(), import.name().to_string()),
|
||||||
|
import.ty().clone(),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect::<HashMap<(String, String), ExternType>>();
|
||||||
|
|
||||||
|
let mut map: HashMap<(String, String), Extern> = HashMap::new();
|
||||||
|
|
||||||
|
for module_entry in js_sys::Object::entries(&object).iter() {
|
||||||
|
let module_entry: js_sys::Array = module_entry.into();
|
||||||
|
let module_name = module_entry.get(0).as_string().unwrap().to_string();
|
||||||
|
let module_import_object: js_sys::Object = module_entry.get(1).into();
|
||||||
|
for import_entry in js_sys::Object::entries(&module_import_object).iter() {
|
||||||
|
let import_entry: js_sys::Array = import_entry.into();
|
||||||
|
let import_name = import_entry.get(0).as_string().unwrap().to_string();
|
||||||
|
let import_js: wasm_bindgen::JsValue = import_entry.get(1);
|
||||||
|
let key = (module_name.clone(), import_name);
|
||||||
|
let extern_type = module_imports.get(&key).unwrap();
|
||||||
|
let export = VMExtern::from_js_value(import_js, store, extern_type.clone())?;
|
||||||
|
let extern_ = Extern::from_vm_extern(store, export);
|
||||||
|
map.insert(key, extern_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Self { map })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsJs for Imports {
|
||||||
|
fn as_jsvalue(&self, store: &impl AsStoreRef) -> wasm_bindgen::JsValue {
|
||||||
|
let imports_object = js_sys::Object::new();
|
||||||
|
for (namespace, name, extern_) in self.iter() {
|
||||||
|
let val = js_sys::Reflect::get(&imports_object, &namespace.into()).unwrap();
|
||||||
|
if !val.is_undefined() {
|
||||||
|
// If the namespace is already set
|
||||||
|
js_sys::Reflect::set(
|
||||||
|
&val,
|
||||||
|
&name.into(),
|
||||||
|
&extern_.as_jsvalue(&store.as_store_ref()),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
} else {
|
||||||
|
// If the namespace doesn't exist
|
||||||
|
let import_namespace = js_sys::Object::new();
|
||||||
|
js_sys::Reflect::set(
|
||||||
|
&import_namespace,
|
||||||
|
&name.into(),
|
||||||
|
&extern_.as_jsvalue(&store.as_store_ref()),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
js_sys::Reflect::set(&imports_object, &namespace.into(), &import_namespace.into())
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
imports_object.into()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ImportsIterator<'a> {
|
pub struct ImportsIterator<'a> {
|
||||||
@@ -317,89 +394,18 @@ macro_rules! import_namespace {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use crate::js::exports::Exportable;
|
use crate::js::{Global, Store, Value};
|
||||||
use crate::js::Type;
|
|
||||||
use crate::js::{Global, Store, Val};
|
|
||||||
|
|
||||||
use crate::js::export::Export;
|
// use wasm_bindgen::*;
|
||||||
use wasm_bindgen_test::*;
|
use wasm_bindgen_test::*;
|
||||||
fn namespace() {
|
|
||||||
let mut store = Store::default();
|
|
||||||
let g1 = Global::new(&store, Val::I32(0));
|
|
||||||
let namespace = namespace! {
|
|
||||||
"happy" => g1
|
|
||||||
};
|
|
||||||
let imports1 = imports! {
|
|
||||||
"dog" => namespace
|
|
||||||
};
|
|
||||||
|
|
||||||
let happy_dog_entry = imports1.get_export("dog", "happy").unwrap();
|
|
||||||
|
|
||||||
assert!(
|
|
||||||
if let Export::Global(happy_dog_global) = happy_dog_entry.to_export() {
|
|
||||||
happy_dog_global.ty.ty == Type::I32
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn imports_macro_allows_trailing_comma_and_none() {
|
|
||||||
use crate::js::Function;
|
|
||||||
|
|
||||||
let mut store = Default::default();
|
|
||||||
|
|
||||||
fn func(arg: i32) -> i32 {
|
|
||||||
arg + 1
|
|
||||||
}
|
|
||||||
|
|
||||||
let _ = imports! {
|
|
||||||
"env" => {
|
|
||||||
"func" => Function::new_typed(&store, func),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
let _ = imports! {
|
|
||||||
"env" => {
|
|
||||||
"func" => Function::new_typed(&store, func),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let _ = imports! {
|
|
||||||
"env" => {
|
|
||||||
"func" => Function::new_typed(&store, func),
|
|
||||||
},
|
|
||||||
"abc" => {
|
|
||||||
"def" => Function::new_typed(&store, func),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let _ = imports! {
|
|
||||||
"env" => {
|
|
||||||
"func" => Function::new_typed(&store, func)
|
|
||||||
},
|
|
||||||
};
|
|
||||||
let _ = imports! {
|
|
||||||
"env" => {
|
|
||||||
"func" => Function::new_typed(&store, func)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let _ = imports! {
|
|
||||||
"env" => {
|
|
||||||
"func1" => Function::new_typed(&store, func),
|
|
||||||
"func2" => Function::new_typed(&store, func)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let _ = imports! {
|
|
||||||
"env" => {
|
|
||||||
"func1" => Function::new_typed(&store, func),
|
|
||||||
"func2" => Function::new_typed(&store, func),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
#[wasm_bindgen_test]
|
||||||
fn chaining_works() {
|
fn chaining_works() {
|
||||||
let mut store = Store::default();
|
let mut store = Store::default();
|
||||||
let g = Global::new(&store, Val::I32(0));
|
|
||||||
|
let g = Global::new(&mut store, Value::I32(0));
|
||||||
|
|
||||||
let mut imports1 = imports! {
|
let mut imports1 = imports! {
|
||||||
"dog" => {
|
"dog" => {
|
||||||
@@ -412,7 +418,7 @@ mod test {
|
|||||||
"small" => g.clone()
|
"small" => g.clone()
|
||||||
},
|
},
|
||||||
"cat" => {
|
"cat" => {
|
||||||
"small" => g.clone()
|
"small" => g
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -426,62 +432,162 @@ mod test {
|
|||||||
assert!(happy.is_some());
|
assert!(happy.is_some());
|
||||||
assert!(small.is_some());
|
assert!(small.is_some());
|
||||||
}
|
}
|
||||||
|
// fn namespace() {
|
||||||
|
// let mut store = Store::default();
|
||||||
|
// let g1 = Global::new(&store, Val::I32(0));
|
||||||
|
// let namespace = namespace! {
|
||||||
|
// "happy" => g1
|
||||||
|
// };
|
||||||
|
// let imports1 = imports! {
|
||||||
|
// "dog" => namespace
|
||||||
|
// };
|
||||||
|
|
||||||
fn extending_conflict_overwrites() {
|
// let happy_dog_entry = imports1.get_export("dog", "happy").unwrap();
|
||||||
let mut store = Store::default();
|
|
||||||
let g1 = Global::new(&store, Val::I32(0));
|
|
||||||
let g2 = Global::new(&store, Val::F32(0.));
|
|
||||||
|
|
||||||
let mut imports1 = imports! {
|
// assert!(
|
||||||
"dog" => {
|
// if let Export::Global(happy_dog_global) = happy_dog_entry.to_export() {
|
||||||
"happy" => g1,
|
// happy_dog_global.ty.ty == Type::I32
|
||||||
},
|
// } else {
|
||||||
};
|
// false
|
||||||
|
// }
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
||||||
let imports2 = imports! {
|
// fn imports_macro_allows_trailing_comma_and_none() {
|
||||||
"dog" => {
|
// use crate::js::Function;
|
||||||
"happy" => g2,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
imports1.extend(&imports2);
|
// let mut store = Default::default();
|
||||||
let happy_dog_entry = imports1.get_export("dog", "happy").unwrap();
|
|
||||||
|
|
||||||
assert!(
|
// fn func(arg: i32) -> i32 {
|
||||||
if let Export::Global(happy_dog_global) = happy_dog_entry.to_export() {
|
// arg + 1
|
||||||
happy_dog_global.ty.ty == Type::F32
|
// }
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// now test it in reverse
|
// let _ = imports! {
|
||||||
let mut store = Store::default();
|
// "env" => {
|
||||||
let g1 = Global::new(&store, Val::I32(0));
|
// "func" => Function::new_typed(&store, func),
|
||||||
let g2 = Global::new(&store, Val::F32(0.));
|
// },
|
||||||
|
// };
|
||||||
|
// let _ = imports! {
|
||||||
|
// "env" => {
|
||||||
|
// "func" => Function::new_typed(&store, func),
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
// let _ = imports! {
|
||||||
|
// "env" => {
|
||||||
|
// "func" => Function::new_typed(&store, func),
|
||||||
|
// },
|
||||||
|
// "abc" => {
|
||||||
|
// "def" => Function::new_typed(&store, func),
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
// let _ = imports! {
|
||||||
|
// "env" => {
|
||||||
|
// "func" => Function::new_typed(&store, func)
|
||||||
|
// },
|
||||||
|
// };
|
||||||
|
// let _ = imports! {
|
||||||
|
// "env" => {
|
||||||
|
// "func" => Function::new_typed(&store, func)
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
// let _ = imports! {
|
||||||
|
// "env" => {
|
||||||
|
// "func1" => Function::new_typed(&store, func),
|
||||||
|
// "func2" => Function::new_typed(&store, func)
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
// let _ = imports! {
|
||||||
|
// "env" => {
|
||||||
|
// "func1" => Function::new_typed(&store, func),
|
||||||
|
// "func2" => Function::new_typed(&store, func),
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
// }
|
||||||
|
|
||||||
let imports1 = imports! {
|
// fn chaining_works() {
|
||||||
"dog" => {
|
// let mut store = Store::default();
|
||||||
"happy" => g1,
|
// let g = Global::new(&store, Val::I32(0));
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut imports2 = imports! {
|
// let mut imports1 = imports! {
|
||||||
"dog" => {
|
// "dog" => {
|
||||||
"happy" => g2,
|
// "happy" => g.clone()
|
||||||
},
|
// }
|
||||||
};
|
// };
|
||||||
|
|
||||||
imports2.extend(&imports1);
|
// let imports2 = imports! {
|
||||||
let happy_dog_entry = imports2.get_export("dog", "happy").unwrap();
|
// "dog" => {
|
||||||
|
// "small" => g.clone()
|
||||||
|
// },
|
||||||
|
// "cat" => {
|
||||||
|
// "small" => g.clone()
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
assert!(
|
// imports1.extend(&imports2);
|
||||||
if let Export::Global(happy_dog_global) = happy_dog_entry.to_export() {
|
|
||||||
happy_dog_global.ty.ty == Type::I32
|
// let small_cat_export = imports1.get_export("cat", "small");
|
||||||
} else {
|
// assert!(small_cat_export.is_some());
|
||||||
false
|
|
||||||
}
|
// let happy = imports1.get_export("dog", "happy");
|
||||||
);
|
// let small = imports1.get_export("dog", "small");
|
||||||
}
|
// assert!(happy.is_some());
|
||||||
|
// assert!(small.is_some());
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fn extending_conflict_overwrites() {
|
||||||
|
// let mut store = Store::default();
|
||||||
|
// let g1 = Global::new(&store, Val::I32(0));
|
||||||
|
// let g2 = Global::new(&store, Val::F32(0.));
|
||||||
|
|
||||||
|
// let mut imports1 = imports! {
|
||||||
|
// "dog" => {
|
||||||
|
// "happy" => g1,
|
||||||
|
// },
|
||||||
|
// };
|
||||||
|
|
||||||
|
// let imports2 = imports! {
|
||||||
|
// "dog" => {
|
||||||
|
// "happy" => g2,
|
||||||
|
// },
|
||||||
|
// };
|
||||||
|
|
||||||
|
// imports1.extend(&imports2);
|
||||||
|
// let happy_dog_entry = imports1.get_export("dog", "happy").unwrap();
|
||||||
|
|
||||||
|
// assert!(
|
||||||
|
// if let Export::Global(happy_dog_global) = happy_dog_entry.to_export() {
|
||||||
|
// happy_dog_global.ty.ty == Type::F32
|
||||||
|
// } else {
|
||||||
|
// false
|
||||||
|
// }
|
||||||
|
// );
|
||||||
|
|
||||||
|
// // now test it in reverse
|
||||||
|
// let mut store = Store::default();
|
||||||
|
// let g1 = Global::new(&store, Val::I32(0));
|
||||||
|
// let g2 = Global::new(&store, Val::F32(0.));
|
||||||
|
|
||||||
|
// let imports1 = imports! {
|
||||||
|
// "dog" => {
|
||||||
|
// "happy" => g1,
|
||||||
|
// },
|
||||||
|
// };
|
||||||
|
|
||||||
|
// let mut imports2 = imports! {
|
||||||
|
// "dog" => {
|
||||||
|
// "happy" => g2,
|
||||||
|
// },
|
||||||
|
// };
|
||||||
|
|
||||||
|
// imports2.extend(&imports1);
|
||||||
|
// let happy_dog_entry = imports2.get_export("dog", "happy").unwrap();
|
||||||
|
|
||||||
|
// assert!(
|
||||||
|
// if let Export::Global(happy_dog_global) = happy_dog_entry.to_export() {
|
||||||
|
// happy_dog_global.ty.ty == Type::I32
|
||||||
|
// } else {
|
||||||
|
// false
|
||||||
|
// }
|
||||||
|
// );
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|||||||
@@ -20,8 +20,6 @@ use std::fmt;
|
|||||||
pub struct Instance {
|
pub struct Instance {
|
||||||
_handle: StoreHandle<WebAssembly::Instance>,
|
_handle: StoreHandle<WebAssembly::Instance>,
|
||||||
module: Module,
|
module: Module,
|
||||||
#[allow(dead_code)]
|
|
||||||
imports: Imports,
|
|
||||||
/// The exports for an instance.
|
/// The exports for an instance.
|
||||||
pub exports: Exports,
|
pub exports: Exports,
|
||||||
}
|
}
|
||||||
@@ -65,16 +63,37 @@ impl Instance {
|
|||||||
module: &Module,
|
module: &Module,
|
||||||
imports: &Imports,
|
imports: &Imports,
|
||||||
) -> Result<Self, InstantiationError> {
|
) -> Result<Self, InstantiationError> {
|
||||||
let import_copy = imports.clone();
|
let instance: WebAssembly::Instance = module
|
||||||
let (instance, _imports): (StoreHandle<WebAssembly::Instance>, Vec<Extern>) = module
|
|
||||||
.instantiate(&mut store, imports)
|
.instantiate(&mut store, imports)
|
||||||
.map_err(|e| InstantiationError::Start(e))?;
|
.map_err(|e| InstantiationError::Start(e))?;
|
||||||
|
|
||||||
let self_instance = Self::from_module_and_instance(store, module, instance, import_copy)?;
|
let self_instance = Self::from_module_and_instance(store, module, instance)?;
|
||||||
//self_instance.init_envs(&imports.iter().map(Extern::to_export).collect::<Vec<_>>())?;
|
//self_instance.init_envs(&imports.iter().map(Extern::to_export).collect::<Vec<_>>())?;
|
||||||
Ok(self_instance)
|
Ok(self_instance)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates a new `Instance` from a WebAssembly [`Module`] and a
|
||||||
|
/// vector of imports.
|
||||||
|
///
|
||||||
|
/// ## Errors
|
||||||
|
///
|
||||||
|
/// The function can return [`InstantiationError`]s.
|
||||||
|
///
|
||||||
|
/// 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_by_index(
|
||||||
|
store: &mut impl AsStoreMut,
|
||||||
|
module: &Module,
|
||||||
|
externs: &[Extern],
|
||||||
|
) -> Result<Self, InstantiationError> {
|
||||||
|
let mut imports = Imports::new();
|
||||||
|
for (import_ty, extern_ty) in module.imports().zip(externs.iter()) {
|
||||||
|
imports.define(import_ty.module(), import_ty.name(), extern_ty.clone());
|
||||||
|
}
|
||||||
|
Self::new(store, module, &imports)
|
||||||
|
}
|
||||||
|
|
||||||
/// Creates a Wasmer `Instance` from a Wasmer `Module` and a WebAssembly Instance
|
/// Creates a Wasmer `Instance` from a Wasmer `Module` and a WebAssembly Instance
|
||||||
///
|
///
|
||||||
/// # Important
|
/// # Important
|
||||||
@@ -87,33 +106,27 @@ impl Instance {
|
|||||||
pub fn from_module_and_instance(
|
pub fn from_module_and_instance(
|
||||||
mut store: &mut impl AsStoreMut,
|
mut store: &mut impl AsStoreMut,
|
||||||
module: &Module,
|
module: &Module,
|
||||||
instance: StoreHandle<WebAssembly::Instance>,
|
instance: WebAssembly::Instance,
|
||||||
imports: Imports,
|
|
||||||
) -> Result<Self, InstantiationError> {
|
) -> Result<Self, InstantiationError> {
|
||||||
let instance_exports = instance.get(store.as_store_ref().objects()).exports();
|
use crate::js::externals::VMExtern;
|
||||||
|
let instance_exports = instance.exports();
|
||||||
let exports = module
|
let exports = module
|
||||||
.exports()
|
.exports()
|
||||||
.map(|export_type| {
|
.map(|export_type| {
|
||||||
let name = export_type.name();
|
let name = export_type.name();
|
||||||
let extern_type = export_type.ty().clone();
|
let extern_type = export_type.ty().clone();
|
||||||
let js_export =
|
let js_export = js_sys::Reflect::get(&instance_exports, &name.into())
|
||||||
js_sys::Reflect::get(&instance_exports, &name.into()).map_err(|_e| {
|
.map_err(|_e| InstantiationError::NotInExports(name.to_string()))?;
|
||||||
InstantiationError::Link(format!(
|
let export: VMExtern =
|
||||||
"Can't get {} from the instance exports",
|
VMExtern::from_js_value(js_export, &mut store, extern_type)?.into();
|
||||||
&name
|
|
||||||
))
|
|
||||||
})?;
|
|
||||||
let export: Export =
|
|
||||||
Export::from_js_value(js_export, &mut store, extern_type)?.into();
|
|
||||||
let extern_ = Extern::from_vm_extern(&mut store, export);
|
let extern_ = Extern::from_vm_extern(&mut store, export);
|
||||||
Ok((name.to_string(), extern_))
|
Ok((name.to_string(), extern_))
|
||||||
})
|
})
|
||||||
.collect::<Result<Exports, InstantiationError>>()?;
|
.collect::<Result<Exports, InstantiationError>>()?;
|
||||||
|
let handle = StoreHandle::new(store.as_store_mut().objects_mut(), instance);
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
_handle: instance,
|
_handle: handle,
|
||||||
module: module.clone(),
|
module: module.clone(),
|
||||||
imports,
|
|
||||||
exports,
|
exports,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,83 +0,0 @@
|
|||||||
use crate::js::error::WasmError;
|
|
||||||
use crate::js::store::AsStoreMut;
|
|
||||||
use crate::js::{Export, ExternType, Module};
|
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
/// This struct is used in case you want to create an `Instance`
|
|
||||||
/// of a `Module` with imports that are provided directly from
|
|
||||||
/// Javascript with a JS Object.
|
|
||||||
#[derive(Clone, Default)]
|
|
||||||
pub struct JsImportObject {
|
|
||||||
module_imports: HashMap<(String, String), ExternType>,
|
|
||||||
object: js_sys::Object,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// JS Objects with wasm-bindgen are not currently Send/Sync (although they
|
|
||||||
/// are in Javascript, since we can use them safely between webworkers).
|
|
||||||
unsafe impl Send for JsImportObject {}
|
|
||||||
unsafe impl Sync for JsImportObject {}
|
|
||||||
|
|
||||||
impl JsImportObject {
|
|
||||||
/// Create a new `JsImportObject`, it receives a reference to a `Module` to
|
|
||||||
/// map and assign the types of each import and the JS Object
|
|
||||||
/// that contains the values of imports.
|
|
||||||
///
|
|
||||||
/// # Usage
|
|
||||||
/// ```ignore
|
|
||||||
/// # use wasmer::JsImportObject;
|
|
||||||
/// let import_object = JsImportObject::new(&module, js_object);
|
|
||||||
/// ```
|
|
||||||
pub fn new(module: &Module, object: js_sys::Object) -> Self {
|
|
||||||
let module_imports = module
|
|
||||||
.imports()
|
|
||||||
.map(|import| {
|
|
||||||
(
|
|
||||||
(import.module().to_string(), import.name().to_string()),
|
|
||||||
import.ty().clone(),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.collect::<HashMap<(String, String), ExternType>>();
|
|
||||||
Self {
|
|
||||||
module_imports,
|
|
||||||
object,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Gets an export given a module and a name
|
|
||||||
///
|
|
||||||
/// # Usage
|
|
||||||
/// ```ignore
|
|
||||||
/// # use wasmer::JsImportObject;
|
|
||||||
/// let import_object = JsImportObject::new(&module, js_object);
|
|
||||||
/// import_object.get_export("module", "name");
|
|
||||||
/// ```
|
|
||||||
pub fn get_export(
|
|
||||||
&self,
|
|
||||||
store: &mut impl AsStoreMut,
|
|
||||||
module: &str,
|
|
||||||
name: &str,
|
|
||||||
) -> Result<Export, WasmError> {
|
|
||||||
let namespace = js_sys::Reflect::get(&self.object, &module.into())?;
|
|
||||||
let js_export = js_sys::Reflect::get(&namespace, &name.into())?;
|
|
||||||
match self
|
|
||||||
.module_imports
|
|
||||||
.get(&(module.to_string(), name.to_string()))
|
|
||||||
{
|
|
||||||
Some(extern_type) => Ok(Export::from_js_value(
|
|
||||||
js_export,
|
|
||||||
store,
|
|
||||||
extern_type.clone(),
|
|
||||||
)?),
|
|
||||||
None => Err(WasmError::Generic(format!(
|
|
||||||
"Name {} not found in module {}",
|
|
||||||
name, module
|
|
||||||
))),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Into<js_sys::Object> for JsImportObject {
|
|
||||||
fn into(self) -> js_sys::Object {
|
|
||||||
self.object
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -197,6 +197,12 @@ impl<'a, T: ValueType> WasmSlice<'a, T> {
|
|||||||
self.len
|
self.len
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return if the slice is empty.
|
||||||
|
#[inline]
|
||||||
|
pub fn is_empty(&self) -> bool {
|
||||||
|
self.len == 0
|
||||||
|
}
|
||||||
|
|
||||||
/// Get a `WasmRef` to an element in the slice.
|
/// Get a `WasmRef` to an element in the slice.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn index(self, idx: u64) -> WasmRef<'a, T> {
|
pub fn index(self, idx: u64) -> WasmRef<'a, T> {
|
||||||
|
|||||||
@@ -30,7 +30,6 @@ mod externals;
|
|||||||
mod function_env;
|
mod function_env;
|
||||||
mod imports;
|
mod imports;
|
||||||
mod instance;
|
mod instance;
|
||||||
mod js_import_object;
|
|
||||||
mod mem_access;
|
mod mem_access;
|
||||||
mod module;
|
mod module;
|
||||||
#[cfg(feature = "wasm-types-polyfill")]
|
#[cfg(feature = "wasm-types-polyfill")]
|
||||||
@@ -54,7 +53,6 @@ pub use crate::js::externals::{
|
|||||||
pub use crate::js::function_env::{FunctionEnv, FunctionEnvMut};
|
pub use crate::js::function_env::{FunctionEnv, FunctionEnvMut};
|
||||||
pub use crate::js::imports::Imports;
|
pub use crate::js::imports::Imports;
|
||||||
pub use crate::js::instance::Instance;
|
pub use crate::js::instance::Instance;
|
||||||
pub use crate::js::js_import_object::JsImportObject;
|
|
||||||
pub use crate::js::mem_access::{MemoryAccessError, WasmRef, WasmSlice, WasmSliceIter};
|
pub use crate::js::mem_access::{MemoryAccessError, WasmRef, WasmSlice, WasmSliceIter};
|
||||||
pub use crate::js::module::{Module, ModuleTypeHints};
|
pub use crate::js::module::{Module, ModuleTypeHints};
|
||||||
pub use crate::js::native::TypedFunction;
|
pub use crate::js::native::TypedFunction;
|
||||||
@@ -88,6 +86,9 @@ pub use wasmer_types::{
|
|||||||
#[cfg(feature = "wat")]
|
#[cfg(feature = "wat")]
|
||||||
pub use wat::parse_bytes as wat2wasm;
|
pub use wat::parse_bytes as wat2wasm;
|
||||||
|
|
||||||
|
#[cfg(feature = "wasm-types-polyfill")]
|
||||||
|
pub use wasmparser;
|
||||||
|
|
||||||
/// Version number of this crate.
|
/// Version number of this crate.
|
||||||
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
|
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||||
|
|
||||||
|
|||||||
@@ -3,13 +3,14 @@ use crate::js::error::WasmError;
|
|||||||
use crate::js::error::{CompileError, InstantiationError};
|
use crate::js::error::{CompileError, InstantiationError};
|
||||||
#[cfg(feature = "js-serializable-module")]
|
#[cfg(feature = "js-serializable-module")]
|
||||||
use crate::js::error::{DeserializeError, SerializeError};
|
use crate::js::error::{DeserializeError, SerializeError};
|
||||||
use crate::js::externals::Extern;
|
|
||||||
use crate::js::imports::Imports;
|
use crate::js::imports::Imports;
|
||||||
use crate::js::store::{AsStoreMut, StoreHandle};
|
use crate::js::store::AsStoreMut;
|
||||||
use crate::js::types::{AsJs, ExportType, ImportType};
|
use crate::js::types::{AsJs, ExportType, ImportType};
|
||||||
use crate::js::RuntimeError;
|
use crate::js::RuntimeError;
|
||||||
use crate::AsStoreRef;
|
use crate::AsStoreRef;
|
||||||
|
use bytes::Bytes;
|
||||||
use js_sys::{Reflect, Uint8Array, WebAssembly};
|
use js_sys::{Reflect, Uint8Array, WebAssembly};
|
||||||
|
use std::borrow::Cow;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
@@ -49,6 +50,46 @@ pub struct ModuleTypeHints {
|
|||||||
pub exports: Vec<ExternType>,
|
pub exports: Vec<ExternType>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait IntoBytes {
|
||||||
|
fn into_bytes(self) -> Bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoBytes for Bytes {
|
||||||
|
fn into_bytes(self) -> Bytes {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoBytes for Vec<u8> {
|
||||||
|
fn into_bytes(self) -> Bytes {
|
||||||
|
Bytes::from(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoBytes for &[u8] {
|
||||||
|
fn into_bytes(self) -> Bytes {
|
||||||
|
Bytes::from(self.to_vec())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<const N: usize> IntoBytes for &[u8; N] {
|
||||||
|
fn into_bytes(self) -> Bytes {
|
||||||
|
Bytes::from(self.to_vec())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoBytes for &str {
|
||||||
|
fn into_bytes(self) -> Bytes {
|
||||||
|
Bytes::from(self.as_bytes().to_vec())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoBytes for Cow<'_, [u8]> {
|
||||||
|
fn into_bytes(self) -> Bytes {
|
||||||
|
Bytes::from(self.to_vec())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A WebAssembly Module contains stateless WebAssembly
|
/// A WebAssembly Module contains stateless WebAssembly
|
||||||
/// code that has already been compiled and can be instantiated
|
/// code that has already been compiled and can be instantiated
|
||||||
/// multiple times.
|
/// multiple times.
|
||||||
@@ -64,7 +105,7 @@ pub struct Module {
|
|||||||
// WebAssembly type hints
|
// WebAssembly type hints
|
||||||
type_hints: Option<ModuleTypeHints>,
|
type_hints: Option<ModuleTypeHints>,
|
||||||
#[cfg(feature = "js-serializable-module")]
|
#[cfg(feature = "js-serializable-module")]
|
||||||
raw_bytes: Option<Vec<u8>>,
|
raw_bytes: Option<Bytes>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Module {
|
impl Module {
|
||||||
@@ -200,7 +241,7 @@ impl Module {
|
|||||||
type_hints,
|
type_hints,
|
||||||
name,
|
name,
|
||||||
#[cfg(feature = "js-serializable-module")]
|
#[cfg(feature = "js-serializable-module")]
|
||||||
raw_bytes: Some(binary.to_vec()),
|
raw_bytes: Some(binary.into_bytes()),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -222,7 +263,7 @@ impl Module {
|
|||||||
&self,
|
&self,
|
||||||
store: &mut impl AsStoreMut,
|
store: &mut impl AsStoreMut,
|
||||||
imports: &Imports,
|
imports: &Imports,
|
||||||
) -> Result<(StoreHandle<WebAssembly::Instance>, Vec<Extern>), RuntimeError> {
|
) -> Result<WebAssembly::Instance, RuntimeError> {
|
||||||
// Ensure all imports come from the same store.
|
// Ensure all imports come from the same store.
|
||||||
if imports
|
if imports
|
||||||
.into_iter()
|
.into_iter()
|
||||||
@@ -232,46 +273,10 @@ impl Module {
|
|||||||
InstantiationError::DifferentStores,
|
InstantiationError::DifferentStores,
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
let imports_object = js_sys::Object::new();
|
|
||||||
let mut import_externs: Vec<Extern> = vec![];
|
let imports_js_obj = imports.as_jsvalue(store).into();
|
||||||
for import_type in self.imports() {
|
Ok(WebAssembly::Instance::new(&self.module, &imports_js_obj)
|
||||||
let resolved_import = imports.get_export(import_type.module(), import_type.name());
|
.map_err(|e: JsValue| -> RuntimeError { e.into() })?)
|
||||||
if let Some(import) = resolved_import {
|
|
||||||
let val = js_sys::Reflect::get(&imports_object, &import_type.module().into())?;
|
|
||||||
if !val.is_undefined() {
|
|
||||||
// If the namespace is already set
|
|
||||||
js_sys::Reflect::set(
|
|
||||||
&val,
|
|
||||||
&import_type.name().into(),
|
|
||||||
&import.as_jsvalue(&store.as_store_ref()),
|
|
||||||
)?;
|
|
||||||
} else {
|
|
||||||
// If the namespace doesn't exist
|
|
||||||
let import_namespace = js_sys::Object::new();
|
|
||||||
js_sys::Reflect::set(
|
|
||||||
&import_namespace,
|
|
||||||
&import_type.name().into(),
|
|
||||||
&import.as_jsvalue(&store.as_store_ref()),
|
|
||||||
)?;
|
|
||||||
js_sys::Reflect::set(
|
|
||||||
&imports_object,
|
|
||||||
&import_type.module().into(),
|
|
||||||
&import_namespace.into(),
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
import_externs.push(import);
|
|
||||||
}
|
|
||||||
// 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((
|
|
||||||
StoreHandle::new(
|
|
||||||
store.as_store_mut().objects_mut(),
|
|
||||||
WebAssembly::Instance::new(&self.module, &imports_object)
|
|
||||||
.map_err(|e: JsValue| -> RuntimeError { e.into() })?,
|
|
||||||
),
|
|
||||||
import_externs,
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the name of the current module.
|
/// Returns the name of the current module.
|
||||||
@@ -300,7 +305,7 @@ impl Module {
|
|||||||
/// can later process via [`Module::deserialize`].
|
/// can later process via [`Module::deserialize`].
|
||||||
///
|
///
|
||||||
#[cfg(feature = "js-serializable-module")]
|
#[cfg(feature = "js-serializable-module")]
|
||||||
pub fn serialize(&self) -> Result<Vec<u8>, SerializeError> {
|
pub fn serialize(&self) -> Result<Bytes, SerializeError> {
|
||||||
self.raw_bytes.clone().ok_or(SerializeError::Generic(
|
self.raw_bytes.clone().ok_or(SerializeError::Generic(
|
||||||
"Not able to serialize module".to_string(),
|
"Not able to serialize module".to_string(),
|
||||||
))
|
))
|
||||||
@@ -313,11 +318,38 @@ impl Module {
|
|||||||
#[cfg(feature = "js-serializable-module")]
|
#[cfg(feature = "js-serializable-module")]
|
||||||
pub unsafe fn deserialize(
|
pub unsafe fn deserialize(
|
||||||
_store: &impl AsStoreRef,
|
_store: &impl AsStoreRef,
|
||||||
bytes: &[u8],
|
bytes: impl IntoBytes,
|
||||||
) -> Result<Self, DeserializeError> {
|
) -> Result<Self, DeserializeError> {
|
||||||
|
let bytes = bytes.into_bytes();
|
||||||
Self::new(_store, bytes).map_err(|e| DeserializeError::Compiler(e))
|
Self::new(_store, bytes).map_err(|e| DeserializeError::Compiler(e))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "compiler")]
|
||||||
|
/// Deserializes a a serialized Module located in a `Path` into a `Module`.
|
||||||
|
/// > Note: the module has to be serialized before with the `serialize` method.
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// Please check [`Module::deserialize`].
|
||||||
|
///
|
||||||
|
/// # Usage
|
||||||
|
///
|
||||||
|
/// ```ignore
|
||||||
|
/// # use wasmer::*;
|
||||||
|
/// # let mut store = Store::default();
|
||||||
|
/// # fn main() -> anyhow::Result<()> {
|
||||||
|
/// let module = Module::deserialize_from_file(&store, path)?;
|
||||||
|
/// # Ok(())
|
||||||
|
/// # }
|
||||||
|
/// ```
|
||||||
|
pub unsafe fn deserialize_from_file(
|
||||||
|
store: &impl AsStoreRef,
|
||||||
|
path: impl AsRef<Path>,
|
||||||
|
) -> Result<Self, DeserializeError> {
|
||||||
|
let artifact = std::fs::read(path.as_ref())?;
|
||||||
|
Ok(Self::new(store, bytes).map_err(|e| DeserializeError::Compiler(e)))
|
||||||
|
}
|
||||||
|
|
||||||
/// Sets the name of the current module.
|
/// Sets the name of the current module.
|
||||||
/// This is normally useful for stacktraces and debugging.
|
/// This is normally useful for stacktraces and debugging.
|
||||||
///
|
///
|
||||||
@@ -525,16 +557,26 @@ impl Module {
|
|||||||
ExportsIterator::new(iter, exports.length() as usize)
|
ExportsIterator::new(iter, exports.length() as usize)
|
||||||
}
|
}
|
||||||
|
|
||||||
// /// Get the custom sections of the module given a `name`.
|
/// Get the custom sections of the module given a `name`.
|
||||||
// ///
|
///
|
||||||
// /// # Important
|
/// # Important
|
||||||
// ///
|
///
|
||||||
// /// Following the WebAssembly spec, one name can have multiple
|
/// Following the WebAssembly spec, one name can have multiple
|
||||||
// /// custom sections. That's why an iterator (rather than one element)
|
/// custom sections. That's why an iterator (rather than one element)
|
||||||
// /// is returned.
|
/// is returned.
|
||||||
// pub fn custom_sections<'a>(&'a self, name: &'a str) -> impl Iterator<Item = Arc<[u8]>> + 'a {
|
pub fn custom_sections<'a>(&'a self, name: &'a str) -> impl Iterator<Item = Box<[u8]>> + 'a {
|
||||||
// unimplemented!();
|
// TODO: implement on JavaScript
|
||||||
// }
|
DefaultCustomSectionsIterator {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct DefaultCustomSectionsIterator {}
|
||||||
|
|
||||||
|
impl Iterator for DefaultCustomSectionsIterator {
|
||||||
|
type Item = Box<[u8]>;
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for Module {
|
impl fmt::Debug for Module {
|
||||||
|
|||||||
@@ -114,6 +114,28 @@ impl NativeWasmTypeInto for f64 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl NativeWasmTypeInto for u128 {
|
||||||
|
#[inline]
|
||||||
|
unsafe fn from_abi(_store: &mut impl AsStoreMut, abi: Self::Abi) -> Self {
|
||||||
|
abi
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn into_abi(self, _store: &mut impl AsStoreMut) -> Self::Abi {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn into_raw(self, _store: &mut impl AsStoreMut) -> f64 {
|
||||||
|
self as _
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
unsafe fn from_raw(_store: &mut impl AsStoreMut, raw: f64) -> Self {
|
||||||
|
raw as _
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl NativeWasmType for Function {
|
impl NativeWasmType for Function {
|
||||||
const WASM_TYPE: Type = Type::FuncRef;
|
const WASM_TYPE: Type = Type::FuncRef;
|
||||||
type Abi = f64;
|
type Abi = f64;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use crate::js::NativeWasmTypeInto;
|
|
||||||
use crate::js::{externals::MemoryView, FromToNativeWasmType};
|
use crate::js::{externals::MemoryView, FromToNativeWasmType};
|
||||||
use crate::js::{MemoryAccessError, WasmRef, WasmSlice};
|
use crate::js::{MemoryAccessError, WasmRef, WasmSlice};
|
||||||
|
use crate::{js::NativeWasmTypeInto, AsStoreRef};
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::{fmt, marker::PhantomData, mem};
|
use std::{fmt, marker::PhantomData, mem};
|
||||||
pub use wasmer_types::Memory32;
|
pub use wasmer_types::Memory32;
|
||||||
@@ -71,7 +71,7 @@ impl<T, M: MemorySize> WasmPtr<T, M> {
|
|||||||
|
|
||||||
/// Get the offset into Wasm linear memory for this `WasmPtr`.
|
/// Get the offset into Wasm linear memory for this `WasmPtr`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn offset(self) -> M::Offset {
|
pub fn offset(&self) -> M::Offset {
|
||||||
self.offset
|
self.offset
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -234,6 +234,10 @@ where
|
|||||||
_phantom: PhantomData,
|
_phantom: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[inline]
|
||||||
|
fn is_from_store(&self, _store: &impl AsStoreRef) -> bool {
|
||||||
|
true // in Javascript there are no different stores
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl<T: ValueType, M: MemorySize> ValueType for WasmPtr<T, M> {
|
unsafe impl<T: ValueType, M: MemorySize> ValueType for WasmPtr<T, M> {
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ impl AsJs for Value {
|
|||||||
Self::I64(i) => JsValue::from_f64(*i as f64),
|
Self::I64(i) => JsValue::from_f64(*i as f64),
|
||||||
Self::F32(f) => JsValue::from_f64(*f as f64),
|
Self::F32(f) => JsValue::from_f64(*f as f64),
|
||||||
Self::F64(f) => JsValue::from_f64(*f),
|
Self::F64(f) => JsValue::from_f64(*f),
|
||||||
|
Self::V128(f) => JsValue::from_f64(*f as f64),
|
||||||
Self::FuncRef(Some(func)) => func
|
Self::FuncRef(Some(func)) => func
|
||||||
.handle
|
.handle
|
||||||
.get(store.as_store_ref().objects())
|
.get(store.as_store_ref().objects())
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use wasmer_types::Type;
|
|||||||
//use crate::ExternRef;
|
//use crate::ExternRef;
|
||||||
use crate::js::externals::function::Function;
|
use crate::js::externals::function::Function;
|
||||||
|
|
||||||
use super::store::AsStoreRef;
|
use super::store::{AsStoreMut, AsStoreRef};
|
||||||
|
|
||||||
/// WebAssembly computations manipulate values of basic value types:
|
/// WebAssembly computations manipulate values of basic value types:
|
||||||
/// * Integers (32 or 64 bit width)
|
/// * Integers (32 or 64 bit width)
|
||||||
@@ -37,6 +37,9 @@ pub enum Value {
|
|||||||
|
|
||||||
/// A first-class reference to a WebAssembly function.
|
/// A first-class reference to a WebAssembly function.
|
||||||
FuncRef(Option<Function>),
|
FuncRef(Option<Function>),
|
||||||
|
|
||||||
|
/// A 128-bit number
|
||||||
|
V128(u128),
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! accessors {
|
macro_rules! accessors {
|
||||||
@@ -76,6 +79,7 @@ impl Value {
|
|||||||
Self::I64(_) => Type::I64,
|
Self::I64(_) => Type::I64,
|
||||||
Self::F32(_) => Type::F32,
|
Self::F32(_) => Type::F32,
|
||||||
Self::F64(_) => Type::F64,
|
Self::F64(_) => Type::F64,
|
||||||
|
Self::V128(_) => Type::V128,
|
||||||
//Self::ExternRef(_) => Type::ExternRef,
|
//Self::ExternRef(_) => Type::ExternRef,
|
||||||
Self::FuncRef(_) => Type::FuncRef,
|
Self::FuncRef(_) => Type::FuncRef,
|
||||||
}
|
}
|
||||||
@@ -88,6 +92,7 @@ impl Value {
|
|||||||
Self::I64(v) => v as f64,
|
Self::I64(v) => v as f64,
|
||||||
Self::F32(v) => v as f64,
|
Self::F32(v) => v as f64,
|
||||||
Self::F64(v) => v,
|
Self::F64(v) => v,
|
||||||
|
Self::V128(v) => v as f64,
|
||||||
Self::FuncRef(Some(ref f)) => f
|
Self::FuncRef(Some(ref f)) => f
|
||||||
.handle
|
.handle
|
||||||
.get(store.as_store_ref().objects())
|
.get(store.as_store_ref().objects())
|
||||||
@@ -107,12 +112,12 @@ impl Value {
|
|||||||
///
|
///
|
||||||
pub unsafe fn from_raw(_store: &impl AsStoreRef, ty: Type, raw: f64) -> Self {
|
pub unsafe fn from_raw(_store: &impl AsStoreRef, ty: Type, raw: f64) -> Self {
|
||||||
match ty {
|
match ty {
|
||||||
Type::I32 => Self::I32(raw as i32),
|
Type::I32 => Self::I32(raw as _),
|
||||||
Type::I64 => Self::I64(raw as i64),
|
Type::I64 => Self::I64(raw as _),
|
||||||
Type::F32 => Self::F32(raw as f32),
|
Type::F32 => Self::F32(raw as _),
|
||||||
Type::F64 => Self::F64(raw),
|
Type::F64 => Self::F64(raw),
|
||||||
|
Type::V128 => Self::V128(raw as _),
|
||||||
Type::FuncRef => todo!(),
|
Type::FuncRef => todo!(),
|
||||||
Type::V128 => todo!(),
|
|
||||||
Type::ExternRef => todo!(),
|
Type::ExternRef => todo!(),
|
||||||
//Self::ExternRef(
|
//Self::ExternRef(
|
||||||
//{
|
//{
|
||||||
@@ -134,6 +139,7 @@ impl Value {
|
|||||||
| Self::I64(_)
|
| Self::I64(_)
|
||||||
| Self::F32(_)
|
| Self::F32(_)
|
||||||
| Self::F64(_)
|
| Self::F64(_)
|
||||||
|
| Self::V128(_)
|
||||||
//| Self::ExternRef(None)
|
//| Self::ExternRef(None)
|
||||||
| Self::FuncRef(None) => true,
|
| Self::FuncRef(None) => true,
|
||||||
//Self::ExternRef(Some(e)) => e.is_from_store(store),
|
//Self::ExternRef(Some(e)) => e.is_from_store(store),
|
||||||
@@ -147,6 +153,7 @@ impl Value {
|
|||||||
(I64(i64) i64 unwrap_i64 *e)
|
(I64(i64) i64 unwrap_i64 *e)
|
||||||
(F32(f32) f32 unwrap_f32 *e)
|
(F32(f32) f32 unwrap_f32 *e)
|
||||||
(F64(f64) f64 unwrap_f64 *e)
|
(F64(f64) f64 unwrap_f64 *e)
|
||||||
|
(V128(u128) v128 unwrap_v128 *e)
|
||||||
//(ExternRef(&Option<ExternRef>) externref unwrap_externref e)
|
//(ExternRef(&Option<ExternRef>) externref unwrap_externref e)
|
||||||
(FuncRef(&Option<Function>) funcref unwrap_funcref e)
|
(FuncRef(&Option<Function>) funcref unwrap_funcref e)
|
||||||
}
|
}
|
||||||
@@ -159,6 +166,7 @@ impl fmt::Debug for Value {
|
|||||||
Self::I64(v) => write!(f, "I64({:?})", v),
|
Self::I64(v) => write!(f, "I64({:?})", v),
|
||||||
Self::F32(v) => write!(f, "F32({:?})", v),
|
Self::F32(v) => write!(f, "F32({:?})", v),
|
||||||
Self::F64(v) => write!(f, "F64({:?})", v),
|
Self::F64(v) => write!(f, "F64({:?})", v),
|
||||||
|
Self::V128(v) => write!(f, "V128({:?})", v),
|
||||||
//Self::ExternRef(None) => write!(f, "Null ExternRef"),
|
//Self::ExternRef(None) => write!(f, "Null ExternRef"),
|
||||||
//Self::ExternRef(Some(v)) => write!(f, "ExternRef({:?})", v),
|
//Self::ExternRef(Some(v)) => write!(f, "ExternRef({:?})", v),
|
||||||
Self::FuncRef(None) => write!(f, "Null FuncRef"),
|
Self::FuncRef(None) => write!(f, "Null FuncRef"),
|
||||||
@@ -174,12 +182,19 @@ impl ToString for Value {
|
|||||||
Self::I64(v) => v.to_string(),
|
Self::I64(v) => v.to_string(),
|
||||||
Self::F32(v) => v.to_string(),
|
Self::F32(v) => v.to_string(),
|
||||||
Self::F64(v) => v.to_string(),
|
Self::F64(v) => v.to_string(),
|
||||||
|
Self::V128(v) => v.to_string(),
|
||||||
//Self::ExternRef(_) => "externref".to_string(),
|
//Self::ExternRef(_) => "externref".to_string(),
|
||||||
Self::FuncRef(_) => "funcref".to_string(),
|
Self::FuncRef(_) => "funcref".to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<u128> for Value {
|
||||||
|
fn from(val: u128) -> Self {
|
||||||
|
Self::V128(val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<i32> for Value {
|
impl From<i32> for Value {
|
||||||
fn from(val: i32) -> Self {
|
fn from(val: i32) -> Self {
|
||||||
Self::I32(val)
|
Self::I32(val)
|
||||||
@@ -246,9 +261,18 @@ const NOT_I32: &str = "Value is not of Wasm type i32";
|
|||||||
const NOT_I64: &str = "Value is not of Wasm type i64";
|
const NOT_I64: &str = "Value is not of Wasm type i64";
|
||||||
const NOT_F32: &str = "Value is not of Wasm type f32";
|
const NOT_F32: &str = "Value is not of Wasm type f32";
|
||||||
const NOT_F64: &str = "Value is not of Wasm type f64";
|
const NOT_F64: &str = "Value is not of Wasm type f64";
|
||||||
|
const NOT_V128: &str = "Value is not of Wasm type u128";
|
||||||
const NOT_FUNCREF: &str = "Value is not of Wasm type funcref";
|
const NOT_FUNCREF: &str = "Value is not of Wasm type funcref";
|
||||||
//const NOT_EXTERNREF: &str = "Value is not of Wasm type externref";
|
//const NOT_EXTERNREF: &str = "Value is not of Wasm type externref";
|
||||||
|
|
||||||
|
impl TryFrom<Value> for u128 {
|
||||||
|
type Error = &'static str;
|
||||||
|
|
||||||
|
fn try_from(value: Value) -> Result<Self, Self::Error> {
|
||||||
|
value.v128().ok_or(NOT_V128)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl TryFrom<Value> for i32 {
|
impl TryFrom<Value> for i32 {
|
||||||
type Error = &'static str;
|
type Error = &'static str;
|
||||||
|
|
||||||
|
|||||||
10
lib/api/src/sys/externals/function.rs
vendored
10
lib/api/src/sys/externals/function.rs
vendored
@@ -204,6 +204,7 @@ impl Function {
|
|||||||
Rets: WasmTypeList,
|
Rets: WasmTypeList,
|
||||||
{
|
{
|
||||||
let env = FunctionEnv::new(store, ());
|
let env = FunctionEnv::new(store, ());
|
||||||
|
let func_ptr = func.function_body_ptr();
|
||||||
let host_data = Box::new(StaticFunction {
|
let host_data = Box::new(StaticFunction {
|
||||||
raw_store: store.as_store_mut().as_raw() as *mut u8,
|
raw_store: store.as_store_mut().as_raw() as *mut u8,
|
||||||
env,
|
env,
|
||||||
@@ -211,7 +212,6 @@ impl Function {
|
|||||||
});
|
});
|
||||||
let function_type = FunctionType::new(Args::wasm_types(), Rets::wasm_types());
|
let function_type = FunctionType::new(Args::wasm_types(), Rets::wasm_types());
|
||||||
|
|
||||||
let func_ptr = <F as HostFunction<(), Args, Rets, WithoutEnv>>::function_body_ptr();
|
|
||||||
let type_index = store
|
let type_index = store
|
||||||
.as_store_mut()
|
.as_store_mut()
|
||||||
.engine()
|
.engine()
|
||||||
@@ -289,6 +289,7 @@ impl Function {
|
|||||||
{
|
{
|
||||||
// println!("new native {:p}", &new_env);
|
// println!("new native {:p}", &new_env);
|
||||||
|
|
||||||
|
let func_ptr = func.function_body_ptr();
|
||||||
let host_data = Box::new(StaticFunction {
|
let host_data = Box::new(StaticFunction {
|
||||||
raw_store: store.as_store_mut().as_raw() as *mut u8,
|
raw_store: store.as_store_mut().as_raw() as *mut u8,
|
||||||
env: env.clone(),
|
env: env.clone(),
|
||||||
@@ -296,7 +297,6 @@ impl Function {
|
|||||||
});
|
});
|
||||||
let function_type = FunctionType::new(Args::wasm_types(), Rets::wasm_types());
|
let function_type = FunctionType::new(Args::wasm_types(), Rets::wasm_types());
|
||||||
|
|
||||||
let func_ptr = <F as HostFunction<T, Args, Rets, WithEnv>>::function_body_ptr();
|
|
||||||
let type_index = store
|
let type_index = store
|
||||||
.as_store_mut()
|
.as_store_mut()
|
||||||
.engine()
|
.engine()
|
||||||
@@ -1092,7 +1092,7 @@ mod inner {
|
|||||||
Kind: HostFunctionKind,
|
Kind: HostFunctionKind,
|
||||||
{
|
{
|
||||||
/// Get the pointer to the function body.
|
/// Get the pointer to the function body.
|
||||||
fn function_body_ptr() -> *const VMFunctionBody;
|
fn function_body_ptr(&self) -> *const VMFunctionBody;
|
||||||
|
|
||||||
/// Get the pointer to the function call trampoline.
|
/// Get the pointer to the function call trampoline.
|
||||||
fn call_trampoline_address() -> VMTrampoline;
|
fn call_trampoline_address() -> VMTrampoline;
|
||||||
@@ -1268,7 +1268,7 @@ mod inner {
|
|||||||
Func: Fn(FunctionEnvMut<T>, $( $x , )*) -> RetsAsResult + 'static,
|
Func: Fn(FunctionEnvMut<T>, $( $x , )*) -> RetsAsResult + 'static,
|
||||||
{
|
{
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
fn function_body_ptr() -> *const VMFunctionBody {
|
fn function_body_ptr(&self) -> *const VMFunctionBody {
|
||||||
/// This is a function that wraps the real host
|
/// This is a function that wraps the real host
|
||||||
/// function. Its address will be used inside the
|
/// function. Its address will be used inside the
|
||||||
/// runtime.
|
/// runtime.
|
||||||
@@ -1352,7 +1352,7 @@ mod inner {
|
|||||||
Func: Fn($( $x , )*) -> RetsAsResult + 'static,
|
Func: Fn($( $x , )*) -> RetsAsResult + 'static,
|
||||||
{
|
{
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
fn function_body_ptr() -> *const VMFunctionBody {
|
fn function_body_ptr(&self) -> *const VMFunctionBody {
|
||||||
/// This is a function that wraps the real host
|
/// This is a function that wraps the real host
|
||||||
/// function. Its address will be used inside the
|
/// function. Its address will be used inside the
|
||||||
/// runtime.
|
/// runtime.
|
||||||
|
|||||||
1
lib/api/src/sys/externals/memory.rs
vendored
1
lib/api/src/sys/externals/memory.rs
vendored
@@ -154,6 +154,7 @@ impl Memory {
|
|||||||
mem.try_clone().map(|mem| mem.into())
|
mem.try_clone().map(|mem| mem.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// To `VMExtern`.
|
||||||
pub(crate) fn to_vm_extern(&self) -> VMExtern {
|
pub(crate) fn to_vm_extern(&self) -> VMExtern {
|
||||||
VMExtern::Memory(self.handle.internal_handle())
|
VMExtern::Memory(self.handle.internal_handle())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ impl<T> FunctionEnv<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get the data as reference
|
/// Get the data as reference
|
||||||
pub fn as_ref<'a>(&self, store: &'a impl AsStoreMut) -> &'a T
|
pub fn as_ref<'a>(&self, store: &'a impl AsStoreRef) -> &'a T
|
||||||
where
|
where
|
||||||
T: Any + Send + 'static + Sized,
|
T: Any + Send + 'static + Sized,
|
||||||
{
|
{
|
||||||
@@ -105,6 +105,11 @@ impl<T: Send + 'static> FunctionEnvMut<'_, T> {
|
|||||||
self.func_env.as_mut(&mut self.store_mut)
|
self.func_env.as_mut(&mut self.store_mut)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Borrows a new immmutable reference
|
||||||
|
pub fn as_ref(&self) -> FunctionEnv<T> {
|
||||||
|
self.func_env.clone()
|
||||||
|
}
|
||||||
|
|
||||||
/// Borrows a new mutable reference
|
/// Borrows a new mutable reference
|
||||||
pub fn as_mut(&mut self) -> FunctionEnvMut<'_, T> {
|
pub fn as_mut(&mut self) -> FunctionEnvMut<'_, T> {
|
||||||
FunctionEnvMut {
|
FunctionEnvMut {
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
use crate::sys::InstantiationError;
|
use crate::sys::InstantiationError;
|
||||||
use crate::AsStoreMut;
|
use crate::AsStoreMut;
|
||||||
use crate::AsStoreRef;
|
use crate::AsStoreRef;
|
||||||
|
use bytes::Bytes;
|
||||||
|
use std::borrow::Cow;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
@@ -54,6 +56,46 @@ pub struct Module {
|
|||||||
module_info: Arc<ModuleInfo>,
|
module_info: Arc<ModuleInfo>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait IntoBytes {
|
||||||
|
fn into_bytes(self) -> Bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoBytes for Bytes {
|
||||||
|
fn into_bytes(self) -> Bytes {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoBytes for Vec<u8> {
|
||||||
|
fn into_bytes(self) -> Bytes {
|
||||||
|
Bytes::from(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoBytes for &[u8] {
|
||||||
|
fn into_bytes(self) -> Bytes {
|
||||||
|
Bytes::from(self.to_vec())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<const N: usize> IntoBytes for &[u8; N] {
|
||||||
|
fn into_bytes(self) -> Bytes {
|
||||||
|
Bytes::from(self.to_vec())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoBytes for &str {
|
||||||
|
fn into_bytes(self) -> Bytes {
|
||||||
|
Bytes::from(self.as_bytes().to_vec())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoBytes for Cow<'_, [u8]> {
|
||||||
|
fn into_bytes(self) -> Bytes {
|
||||||
|
Bytes::from(self.to_vec())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Module {
|
impl Module {
|
||||||
#[cfg(feature = "compiler")]
|
#[cfg(feature = "compiler")]
|
||||||
/// Creates a new WebAssembly Module given the configuration
|
/// Creates a new WebAssembly Module given the configuration
|
||||||
@@ -124,7 +166,6 @@ impl Module {
|
|||||||
e
|
e
|
||||||
)))
|
)))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
Self::from_binary(store, bytes.as_ref())
|
Self::from_binary(store, bytes.as_ref())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,8 +247,8 @@ impl Module {
|
|||||||
/// # Ok(())
|
/// # Ok(())
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn serialize(&self) -> Result<Vec<u8>, SerializeError> {
|
pub fn serialize(&self) -> Result<Bytes, SerializeError> {
|
||||||
self.artifact.serialize()
|
self.artifact.serialize().map(|bytes| bytes.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Serializes a module into a file that the `Engine`
|
/// Serializes a module into a file that the `Engine`
|
||||||
@@ -254,9 +295,10 @@ impl Module {
|
|||||||
/// ```
|
/// ```
|
||||||
pub unsafe fn deserialize(
|
pub unsafe fn deserialize(
|
||||||
store: &impl AsStoreRef,
|
store: &impl AsStoreRef,
|
||||||
bytes: &[u8],
|
bytes: impl IntoBytes,
|
||||||
) -> Result<Self, DeserializeError> {
|
) -> Result<Self, DeserializeError> {
|
||||||
let artifact = store.as_store_ref().engine().deserialize(bytes)?;
|
let bytes = bytes.into_bytes();
|
||||||
|
let artifact = store.as_store_ref().engine().deserialize(&bytes)?;
|
||||||
Ok(Self::from_artifact(artifact))
|
Ok(Self::from_artifact(artifact))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ use wasmer_types::RawValue;
|
|||||||
/// A WebAssembly function that can be called natively
|
/// A WebAssembly function that can be called natively
|
||||||
/// (using the Native ABI).
|
/// (using the Native ABI).
|
||||||
pub struct TypedFunction<Args, Rets> {
|
pub struct TypedFunction<Args, Rets> {
|
||||||
func: Function,
|
pub(crate) func: Function,
|
||||||
_phantom: PhantomData<fn(Args) -> Rets>,
|
_phantom: PhantomData<fn(Args) -> Rets>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,16 +45,6 @@ impl<Args: WasmTypeList, Rets: WasmTypeList> Clone for TypedFunction<Args, Rets>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Args, Rets> From<TypedFunction<Args, Rets>> for Function
|
|
||||||
where
|
|
||||||
Args: WasmTypeList,
|
|
||||||
Rets: WasmTypeList,
|
|
||||||
{
|
|
||||||
fn from(other: TypedFunction<Args, Rets>) -> Self {
|
|
||||||
other.func
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! impl_native_traits {
|
macro_rules! impl_native_traits {
|
||||||
( $( $x:ident ),* ) => {
|
( $( $x:ident ),* ) => {
|
||||||
#[allow(unused_parens, non_snake_case)]
|
#[allow(unused_parens, non_snake_case)]
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
use wasmer_types::{NativeWasmType, RawValue, Type};
|
use wasmer_types::{NativeWasmType, RawValue, Type};
|
||||||
use wasmer_vm::{VMExternRef, VMFuncRef};
|
use wasmer_vm::{VMExternRef, VMFuncRef};
|
||||||
|
|
||||||
use crate::{ExternRef, Function};
|
use crate::{ExternRef, Function, TypedFunction, WasmTypeList};
|
||||||
|
|
||||||
use super::store::AsStoreMut;
|
use super::store::AsStoreMut;
|
||||||
|
|
||||||
@@ -165,6 +165,16 @@ impl NativeWasmTypeInto for Option<ExternRef> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<Args, Rets> From<TypedFunction<Args, Rets>> for Function
|
||||||
|
where
|
||||||
|
Args: WasmTypeList,
|
||||||
|
Rets: WasmTypeList,
|
||||||
|
{
|
||||||
|
fn from(other: TypedFunction<Args, Rets>) -> Self {
|
||||||
|
other.func
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl NativeWasmType for Function {
|
impl NativeWasmType for Function {
|
||||||
const WASM_TYPE: Type = Type::FuncRef;
|
const WASM_TYPE: Type = Type::FuncRef;
|
||||||
type Abi = usize;
|
type Abi = usize;
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ impl<T, M: MemorySize> WasmPtr<T, M> {
|
|||||||
|
|
||||||
/// Get the offset into Wasm linear memory for this `WasmPtr`.
|
/// Get the offset into Wasm linear memory for this `WasmPtr`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn offset(self) -> M::Offset {
|
pub fn offset(&self) -> M::Offset {
|
||||||
self.offset
|
self.offset
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ mod js {
|
|||||||
fn global_get() {
|
fn global_get() {
|
||||||
let mut store = Store::default();
|
let mut store = Store::default();
|
||||||
let global_i32 = Global::new(&mut store, Value::I32(10));
|
let global_i32 = Global::new(&mut store, Value::I32(10));
|
||||||
assert_eq!(global_i32.get(&store), Value::I32(10));
|
assert_eq!(global_i32.get(&mut store), Value::I32(10));
|
||||||
// 64-bit values are not yet fully supported in some versions of Node
|
// 64-bit values are not yet fully supported in some versions of Node
|
||||||
// Commenting this tests for now:
|
// Commenting this tests for now:
|
||||||
|
|
||||||
|
|||||||
@@ -92,6 +92,61 @@ mod js {
|
|||||||
assert_eq!(get_magic.call(&mut store, &[]).unwrap(), expected);
|
assert_eq!(get_magic.call(&mut store, &[]).unwrap(), expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen_test]
|
||||||
|
fn test_imports_from_js_object() {
|
||||||
|
let mut store = Store::default();
|
||||||
|
let mut module = Module::new(
|
||||||
|
&store,
|
||||||
|
br#"
|
||||||
|
(module
|
||||||
|
(func $imported (import "env" "imported") (param i32) (result i32))
|
||||||
|
(func (export "exported") (param i32) (result i32)
|
||||||
|
(call $imported (local.get 0))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
module
|
||||||
|
.set_type_hints(ModuleTypeHints {
|
||||||
|
imports: vec![ExternType::Function(FunctionType::new(
|
||||||
|
vec![Type::I32],
|
||||||
|
vec![Type::I32],
|
||||||
|
))],
|
||||||
|
exports: vec![ExternType::Function(FunctionType::new(
|
||||||
|
vec![Type::I32],
|
||||||
|
vec![Type::I32],
|
||||||
|
))],
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let obj: js_sys::Object = js_sys::Function::new_with_args(
|
||||||
|
"",
|
||||||
|
"return {
|
||||||
|
\"env\": {
|
||||||
|
\"imported\": function(num) {
|
||||||
|
console.log(\"Calling `imported`...\");
|
||||||
|
var result = num * 2;
|
||||||
|
console.log(\"Result of `imported`: \", result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};",
|
||||||
|
)
|
||||||
|
.call0(&wasm_bindgen::JsValue::UNDEFINED)
|
||||||
|
.unwrap()
|
||||||
|
.into();
|
||||||
|
|
||||||
|
let import_object = Imports::new_from_js_object(&mut store, &module, obj)
|
||||||
|
.expect("Can't get imports from js object");
|
||||||
|
let instance = Instance::new(&mut store, &module, &import_object).unwrap();
|
||||||
|
|
||||||
|
let exported = instance.exports.get_function("exported").unwrap();
|
||||||
|
|
||||||
|
let expected = vec![Val::I32(6)].into_boxed_slice();
|
||||||
|
assert_eq!(exported.call(&mut store, &[Val::I32(3)]).unwrap(), expected);
|
||||||
|
}
|
||||||
|
|
||||||
#[wasm_bindgen_test]
|
#[wasm_bindgen_test]
|
||||||
fn test_imported_function_dynamic() {
|
fn test_imported_function_dynamic() {
|
||||||
let mut store = Store::default();
|
let mut store = Store::default();
|
||||||
|
|||||||
@@ -475,7 +475,7 @@ pub unsafe extern "C" fn wasm_module_deserialize(
|
|||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn wasm_module_serialize(module: &wasm_module_t, out: &mut wasm_byte_vec_t) {
|
pub unsafe extern "C" fn wasm_module_serialize(module: &wasm_module_t, out: &mut wasm_byte_vec_t) {
|
||||||
let byte_vec = c_try!(module.inner.serialize(); otherwise ());
|
let byte_vec = c_try!(module.inner.serialize(); otherwise ());
|
||||||
out.set_buffer(byte_vec);
|
out.set_buffer(byte_vec.to_vec());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@@ -25,16 +25,11 @@ impl Inspect {
|
|||||||
fn inner_execute(&self) -> Result<()> {
|
fn inner_execute(&self) -> Result<()> {
|
||||||
let (store, _compiler_type) = self.store.get_store()?;
|
let (store, _compiler_type) = self.store.get_store()?;
|
||||||
let module_contents = std::fs::read(&self.path)?;
|
let module_contents = std::fs::read(&self.path)?;
|
||||||
let module = Module::new(&store, &module_contents)?;
|
let iswasm = is_wasm(&module_contents);
|
||||||
println!(
|
let module_len = module_contents.len();
|
||||||
"Type: {}",
|
let module = Module::new(&store, module_contents)?;
|
||||||
if !is_wasm(&module_contents) {
|
println!("Type: {}", if !iswasm { "wat" } else { "wasm" });
|
||||||
"wat"
|
println!("Size: {}", ByteSize(module_len as _));
|
||||||
} else {
|
|
||||||
"wasm"
|
|
||||||
}
|
|
||||||
);
|
|
||||||
println!("Size: {}", ByteSize(module_contents.len() as _));
|
|
||||||
println!("Imports:");
|
println!("Imports:");
|
||||||
println!(" Functions:");
|
println!(" Functions:");
|
||||||
for f in module.imports().functions() {
|
for f in module.imports().functions() {
|
||||||
|
|||||||
@@ -272,7 +272,7 @@ impl Run {
|
|||||||
let module_result: Result<Module> = if !self.disable_cache && contents.len() > 0x1000 {
|
let module_result: Result<Module> = if !self.disable_cache && contents.len() > 0x1000 {
|
||||||
self.get_module_from_cache(&store, &contents, &compiler_type)
|
self.get_module_from_cache(&store, &contents, &compiler_type)
|
||||||
} else {
|
} else {
|
||||||
Module::new(&store, &contents).map_err(|e| e.into())
|
Module::new(&store, contents).map_err(|e| e.into())
|
||||||
};
|
};
|
||||||
#[cfg(not(feature = "cache"))]
|
#[cfg(not(feature = "cache"))]
|
||||||
let module_result = Module::new(&store, &contents);
|
let module_result = Module::new(&store, &contents);
|
||||||
@@ -319,7 +319,7 @@ impl Run {
|
|||||||
warning!("cached module is corrupted: {}", err);
|
warning!("cached module is corrupted: {}", err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let module = Module::new(store, &contents)?;
|
let module = Module::new(store, contents)?;
|
||||||
// Store the compiled Module in cache
|
// Store the compiled Module in cache
|
||||||
cache.store(hash, &module)?;
|
cache.store(hash, &module)?;
|
||||||
Ok(module)
|
Ok(module)
|
||||||
|
|||||||
@@ -7,11 +7,7 @@ license = "MIT"
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libc = { version = "^0.2", default-features = false, optional = true }
|
|
||||||
thiserror = "1"
|
thiserror = "1"
|
||||||
tracing = { version = "0.1" }
|
|
||||||
typetag = { version = "0.1", optional = true }
|
|
||||||
slab = { version = "0.4", optional = true }
|
|
||||||
wasmer-vfs = { path = "../vfs", version = "=3.0.0-beta", default-features = false }
|
wasmer-vfs = { path = "../vfs", version = "=3.0.0-beta", default-features = false }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
|||||||
@@ -7,11 +7,7 @@ license = "MIT"
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libc = { version = "^0.2", default-features = false, optional = true }
|
|
||||||
thiserror = "1"
|
thiserror = "1"
|
||||||
tracing = { version = "0.1" }
|
|
||||||
typetag = { version = "0.1", optional = true }
|
|
||||||
slab = { version = "0.4", optional = true }
|
|
||||||
wasmer-vfs = { path = "../vfs", version = "=3.0.0-beta", default-features = false }
|
wasmer-vfs = { path = "../vfs", version = "=3.0.0-beta", default-features = false }
|
||||||
bytes = "1"
|
bytes = "1"
|
||||||
|
|
||||||
|
|||||||
@@ -44,8 +44,9 @@ tracing-wasm = "0.2"
|
|||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["sys-default"]
|
default = ["sys-default"]
|
||||||
|
wasix = []
|
||||||
|
|
||||||
sys = ["wasmer/sys"]
|
sys = ["wasmer/sys", "wasix"]
|
||||||
sys-default = ["wasmer/wat", "wasmer/compiler", "sys", "logging", "host-fs", "sys-poll", "host-vnet" ]
|
sys-default = ["wasmer/wat", "wasmer/compiler", "sys", "logging", "host-fs", "sys-poll", "host-vnet" ]
|
||||||
sys-poll = []
|
sys-poll = []
|
||||||
|
|
||||||
|
|||||||
@@ -47,9 +47,9 @@ pub use crate::state::{
|
|||||||
WasiStateCreationError, ALL_RIGHTS, VIRTUAL_ROOT_FD,
|
WasiStateCreationError, ALL_RIGHTS, VIRTUAL_ROOT_FD,
|
||||||
};
|
};
|
||||||
pub use crate::syscalls::types;
|
pub use crate::syscalls::types;
|
||||||
pub use crate::utils::{
|
#[cfg(feature = "wasix")]
|
||||||
get_wasi_version, get_wasi_versions, is_wasi_module, is_wasix_module, WasiVersion,
|
pub use crate::utils::is_wasix_module;
|
||||||
};
|
pub use crate::utils::{get_wasi_version, get_wasi_versions, is_wasi_module, WasiVersion};
|
||||||
pub use wasmer_vbus::{UnsupportedVirtualBus, VirtualBus};
|
pub use wasmer_vbus::{UnsupportedVirtualBus, VirtualBus};
|
||||||
#[deprecated(since = "2.1.0", note = "Please use `wasmer_vfs::FsError`")]
|
#[deprecated(since = "2.1.0", note = "Please use `wasmer_vfs::FsError`")]
|
||||||
pub use wasmer_vfs::FsError as WasiFsError;
|
pub use wasmer_vfs::FsError as WasiFsError;
|
||||||
@@ -62,9 +62,11 @@ use wasmer_wasi_types::__WASI_CLOCK_MONOTONIC;
|
|||||||
use derivative::*;
|
use derivative::*;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
use tracing::trace;
|
||||||
use wasmer::{
|
use wasmer::{
|
||||||
imports, namespace, AsStoreMut, AsStoreRef, Exports, Function, FunctionEnv, Imports, Memory,
|
imports, namespace, AsStoreMut, AsStoreRef, ExportError, Exports, Function, FunctionEnv,
|
||||||
Memory32, MemoryAccessError, MemorySize, MemoryView, Module, TypedFunction,
|
Imports, Instance, Memory, Memory32, MemoryAccessError, MemorySize, MemoryView, Module,
|
||||||
|
TypedFunction,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub use runtime::{
|
pub use runtime::{
|
||||||
@@ -166,6 +168,33 @@ impl WasiFunctionEnv {
|
|||||||
self.env.as_mut(store)
|
self.env.as_mut(store)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Initializes the WasiEnv using the instance exports
|
||||||
|
/// (this must be executed before attempting to use it)
|
||||||
|
/// (as the stores can not by themselves be passed between threads we can store the module
|
||||||
|
/// in a thread-local variables and use it later - for multithreading)
|
||||||
|
pub fn initialize(
|
||||||
|
&mut self,
|
||||||
|
store: &mut impl AsStoreMut,
|
||||||
|
instance: &Instance,
|
||||||
|
) -> Result<(), ExportError> {
|
||||||
|
// List all the exports and imports
|
||||||
|
for ns in instance.module().exports() {
|
||||||
|
//trace!("module::export - {} ({:?})", ns.name(), ns.ty());
|
||||||
|
trace!("module::export - {}", ns.name());
|
||||||
|
}
|
||||||
|
for ns in instance.module().imports() {
|
||||||
|
trace!("module::import - {}::{}", ns.module(), ns.name());
|
||||||
|
}
|
||||||
|
|
||||||
|
// First we get the malloc function which if it exists will be used to
|
||||||
|
// create the pthread_self structure
|
||||||
|
let memory = instance.exports.get_memory("memory")?.clone();
|
||||||
|
let env = self.data_mut(store);
|
||||||
|
env.set_memory(memory);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Like `import_object` but containing all the WASI versions detected in
|
/// Like `import_object` but containing all the WASI versions detected in
|
||||||
/// the module.
|
/// the module.
|
||||||
pub fn import_object_for_all_wasi_versions(
|
pub fn import_object_for_all_wasi_versions(
|
||||||
@@ -184,6 +213,7 @@ impl WasiFunctionEnv {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "wasix")]
|
||||||
if is_wasix_module(module) {
|
if is_wasix_module(module) {
|
||||||
self.data_mut(store)
|
self.data_mut(store)
|
||||||
.state
|
.state
|
||||||
@@ -394,8 +424,12 @@ pub fn generate_import_object_from_env(
|
|||||||
WasiVersion::Snapshot1 | WasiVersion::Latest => {
|
WasiVersion::Snapshot1 | WasiVersion::Latest => {
|
||||||
generate_import_object_snapshot1(store, env)
|
generate_import_object_snapshot1(store, env)
|
||||||
}
|
}
|
||||||
|
#[cfg(feature = "wasix")]
|
||||||
WasiVersion::Wasix32v1 => generate_import_object_wasix32_v1(store, env),
|
WasiVersion::Wasix32v1 => generate_import_object_wasix32_v1(store, env),
|
||||||
|
#[cfg(feature = "wasix")]
|
||||||
WasiVersion::Wasix64v1 => generate_import_object_wasix64_v1(store, env),
|
WasiVersion::Wasix64v1 => generate_import_object_wasix64_v1(store, env),
|
||||||
|
#[cfg(not(feature = "wasix"))]
|
||||||
|
_ => unimplemented!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -537,6 +571,7 @@ fn generate_import_object_snapshot1(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Combines a state generating function with the import list for snapshot 1
|
/// Combines a state generating function with the import list for snapshot 1
|
||||||
|
#[cfg(feature = "wasix")]
|
||||||
fn generate_import_object_wasix32_v1(
|
fn generate_import_object_wasix32_v1(
|
||||||
mut store: &mut impl AsStoreMut,
|
mut store: &mut impl AsStoreMut,
|
||||||
env: &FunctionEnv<WasiEnv>,
|
env: &FunctionEnv<WasiEnv>,
|
||||||
@@ -655,6 +690,7 @@ fn generate_import_object_wasix32_v1(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "wasix")]
|
||||||
fn generate_import_object_wasix64_v1(
|
fn generate_import_object_wasix64_v1(
|
||||||
mut store: &mut impl AsStoreMut,
|
mut store: &mut impl AsStoreMut,
|
||||||
env: &FunctionEnv<WasiEnv>,
|
env: &FunctionEnv<WasiEnv>,
|
||||||
|
|||||||
@@ -18,7 +18,9 @@ pub mod windows;
|
|||||||
|
|
||||||
pub mod legacy;
|
pub mod legacy;
|
||||||
//pub mod wasi;
|
//pub mod wasi;
|
||||||
|
#[cfg(feature = "wasix")]
|
||||||
pub mod wasix32;
|
pub mod wasix32;
|
||||||
|
#[cfg(feature = "wasix")]
|
||||||
pub mod wasix64;
|
pub mod wasix64;
|
||||||
|
|
||||||
use self::types::*;
|
use self::types::*;
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ pub fn is_wasi_module(module: &Module) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
#[cfg(feature = "wasix")]
|
||||||
/// Returns if the module is WASIX or not
|
/// Returns if the module is WASIX or not
|
||||||
pub fn is_wasix_module(module: &Module) -> bool {
|
pub fn is_wasix_module(module: &Module) -> bool {
|
||||||
match get_wasi_versions(module, false).ok_or(false) {
|
match get_wasi_versions(module, false).ok_or(false) {
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ fn test_deserialize(config: crate::Config) -> Result<()> {
|
|||||||
let serialized_bytes = module.serialize()?;
|
let serialized_bytes = module.serialize()?;
|
||||||
|
|
||||||
let headless_store = config.headless_store();
|
let headless_store = config.headless_store();
|
||||||
let deserialized_module = unsafe { Module::deserialize(&headless_store, &serialized_bytes)? };
|
let deserialized_module = unsafe { Module::deserialize(&headless_store, serialized_bytes)? };
|
||||||
assert_eq!(deserialized_module.name(), Some("name"));
|
assert_eq!(deserialized_module.name(), Some("name"));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
deserialized_module.exports().collect::<Vec<_>>(),
|
deserialized_module.exports().collect::<Vec<_>>(),
|
||||||
|
|||||||
Reference in New Issue
Block a user