Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion lib/api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ wasmer-types = { path = "../types", version = "=7.2.1", default-features = false
"std",
] }
wasm-bindgen.workspace = true
wasm-bindgen-futures = { workspace = true, optional = true }
js-sys.workspace = true
wasmer-derive = { path = "../derive", version = "=7.2.1" }
wasmer-compiler = { path = "../compiler", version = "=7.2.1" }
Expand All @@ -100,6 +101,7 @@ target-lexicon.workspace = true
[target.'cfg(target_arch = "wasm32")'.dev-dependencies]
wat.workspace = true
anyhow.workspace = true
futures.workspace = true
wasm-bindgen-test.workspace = true
macro-wasmer-engine-test = { version = "7.2.1", path = "./macro-wasmer-engine-test" }

Expand Down Expand Up @@ -162,7 +164,7 @@ v8-default = ["v8", "wat"]
wasm-c-api = ["wasm-types-polyfill"]

# Features for `js`.
js = ["wasm-bindgen", "js-sys"]
js = ["wasm-bindgen", "wasm-bindgen-futures", "js-sys"]
js-default = ["js", "std", "wasm-types-polyfill"]

wasm-types-polyfill = ["wasmparser"]
Expand Down
153 changes: 150 additions & 3 deletions lib/api/src/backend/js/entities/function/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ use crate::{
js::{store::StoreHandle, vm::VMFunctionEnvironment},
store::{AsStoreMut, AsStoreRef, StoreRef},
};
#[cfg(feature = "experimental-async")]
use crate::{
AsStoreAsync, StoreAsync, StoreAsyncReadLock, StoreAsyncWriteLock,
};
#[cfg(feature = "experimental-async")]
use wasmer_types::StoreId;

#[derive(Debug)]
#[repr(transparent)]
Expand Down Expand Up @@ -33,7 +39,7 @@ impl<T> FunctionEnv<T> {
/// Get the data as reference
pub fn as_ref<'a>(&self, store: &'a impl AsStoreRef) -> &'a T
where
T: Any + Send + 'static + Sized,
T: Any + 'static + Sized,
{
self.handle
.get(store.as_store_ref().objects().as_js())
Expand All @@ -52,7 +58,7 @@ impl<T> FunctionEnv<T> {
/// Get the data as mutable
pub fn as_mut<'a>(&self, store: &'a mut impl AsStoreMut) -> &'a mut T
where
T: Any + Send + 'static + Sized,
T: Any + 'static + Sized,
{
self.handle
.get_mut(store.objects_mut().as_js_mut())
Expand All @@ -64,7 +70,7 @@ impl<T> FunctionEnv<T> {
/// Convert it into a `FunctionEnvMut`
pub fn into_mut(self, store: &mut impl AsStoreMut) -> FunctionEnvMut<'_, T>
where
T: Any + Send + 'static + Sized,
T: Any + 'static + Sized,
{
FunctionEnvMut {
store_mut: store.as_store_mut(),
Expand Down Expand Up @@ -146,6 +152,11 @@ impl<T: Send + 'static> FunctionEnvMut<'_, T> {
let data = unsafe { &mut *data };
(data, self.store_mut.as_store_mut())
}

#[cfg(feature = "experimental-async")]
pub fn as_store_async(&self) -> Option<impl AsStoreAsync + 'static> {
self.store_mut.as_store_async()
}
}

impl<T> AsStoreRef for FunctionEnvMut<'_, T> {
Expand Down Expand Up @@ -205,3 +216,139 @@ impl<T> From<FunctionEnv<T>> for crate::FunctionEnv<T> {
Self(crate::BackendFunctionEnv::Js(value))
}
}

#[cfg(feature = "experimental-async")]
pub struct AsyncFunctionEnvMut<T> {
pub(crate) store: StoreAsync,
pub(crate) func_env: FunctionEnv<T>,
}

#[cfg(feature = "experimental-async")]
pub struct AsyncFunctionEnvHandle<T> {
read_lock: StoreAsyncReadLock,
pub(crate) func_env: FunctionEnv<T>,
}

#[cfg(feature = "experimental-async")]
pub struct AsyncFunctionEnvHandleMut<T> {
write_lock: StoreAsyncWriteLock,
pub(crate) func_env: FunctionEnv<T>,
}

#[cfg(feature = "experimental-async")]
impl<T> Clone for AsyncFunctionEnvMut<T> {
fn clone(&self) -> Self {
Self {
store: StoreAsync {
id: self.store.id,
inner: self.store.inner.clone(),
},
func_env: self.func_env.clone(),
}
}
}

#[cfg(feature = "experimental-async")]
impl<T> Debug for AsyncFunctionEnvMut<T>
where
T: Send + Debug + 'static,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self.store.inner.try_read() {
Some(read_lock) => self.func_env.as_ref(&read_lock).fmt(f),
None => write!(f, "AsyncFunctionEnvMut {{ <STORE LOCKED> }}"),
}
}
}

#[cfg(feature = "experimental-async")]
impl<T: 'static> AsyncFunctionEnvMut<T> {
pub(crate) fn store_id(&self) -> StoreId {
self.store.id
}

pub async fn read(&self) -> AsyncFunctionEnvHandle<T> {
AsyncFunctionEnvHandle {
read_lock: self.store.read_lock().await,
func_env: self.func_env.clone(),
}
}

pub async fn write(&self) -> AsyncFunctionEnvHandleMut<T> {
AsyncFunctionEnvHandleMut {
write_lock: self.store.write_lock().await,
func_env: self.func_env.clone(),
}
}

pub fn as_ref(&self) -> FunctionEnv<T> {
self.func_env.clone()
}

pub fn as_mut(&mut self) -> Self {
self.clone()
}

pub fn as_store_async(&self) -> impl AsStoreAsync + 'static {
StoreAsync {
id: self.store.id,
inner: self.store.inner.clone(),
}
}
}

#[cfg(feature = "experimental-async")]
impl<T: 'static> AsyncFunctionEnvHandle<T> {
pub fn data(&self) -> &T {
self.func_env.as_ref(&self.read_lock)
}

pub fn data_and_store(&self) -> (&T, &impl AsStoreRef) {
(self.data(), &self.read_lock)
}
}

#[cfg(feature = "experimental-async")]
impl<T: 'static> AsStoreRef for AsyncFunctionEnvHandle<T> {
fn as_store_ref(&self) -> StoreRef<'_> {
self.read_lock.as_store_ref()
}
}

#[cfg(feature = "experimental-async")]
impl<T: 'static> AsyncFunctionEnvHandleMut<T> {
pub fn data_mut(&mut self) -> &mut T {
self.func_env.as_mut(&mut self.write_lock)
}

pub fn data_and_store_mut(&mut self) -> (&mut T, &mut impl AsStoreMut) {
let data = self.data_mut() as *mut T;
let data = unsafe { &mut *data };
(data, &mut self.write_lock)
}

pub fn as_function_env_mut(&mut self) -> FunctionEnvMut<'_, T> {
FunctionEnvMut {
store_mut: self.write_lock.as_store_mut(),
func_env: self.func_env.clone(),
}
}
}

#[cfg(feature = "experimental-async")]
impl<T: 'static> AsStoreRef for AsyncFunctionEnvHandleMut<T> {
fn as_store_ref(&self) -> StoreRef<'_> {
self.write_lock.as_store_ref()
}
}

#[cfg(feature = "experimental-async")]
impl<T: 'static> AsStoreMut for AsyncFunctionEnvHandleMut<T> {
fn as_store_mut(&mut self) -> StoreMut<'_> {
self.write_lock.as_store_mut()
}

fn objects_mut(&mut self) -> &mut crate::StoreObjects {
self.write_lock.objects_mut()
}
}
Loading
Loading