wasmer/entities/global/
inner.rs

1use crate::{
2    ExportError, Exportable, Extern,
3    error::RuntimeError,
4    macros::backend::{gen_rt_ty, match_rt},
5    store::{AsStoreMut, AsStoreRef, StoreMut, StoreRef},
6    value::Value,
7    vm::{VMExtern, VMExternGlobal},
8};
9use wasmer_types::{GlobalType, Mutability};
10
11/// A WebAssembly `global` instance.
12///
13/// A global instance is the runtime representation of a global variable.
14/// It consists of an individual value and a flag indicating whether it is mutable.
15///
16/// Spec: <https://webassembly.github.io/spec/core/exec/runtime.html#global-instances>
17gen_rt_ty! {
18    #[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
19    #[derive(Debug, Clone, PartialEq, Eq, derive_more::From)]
20    pub(crate) BackendGlobal(entities::global::Global);
21}
22
23impl BackendGlobal {
24    /// Create a new global with the initial [`Value`].
25    ///
26    /// # Example
27    ///
28    /// ```
29    /// # use wasmer::{Global, Mutability, Store, Value};
30    /// # let mut store = Store::default();
31    /// #
32    /// let g = Global::new(&mut store, Value::I32(1));
33    ///
34    /// assert_eq!(g.get(&mut store), Value::I32(1));
35    /// assert_eq!(g.ty(&mut store).mutability, Mutability::Const);
36    /// ```
37    #[inline]
38    pub fn new(store: &mut impl AsStoreMut, val: Value) -> Self {
39        Self::from_value(store, val, Mutability::Const).unwrap()
40    }
41
42    /// Create a mutable global with the initial [`Value`].
43    ///
44    /// # Example
45    ///
46    /// ```
47    /// # use wasmer::{Global, Mutability, Store, Value};
48    /// # let mut store = Store::default();
49    /// #
50    /// let g = Global::new_mut(&mut store, Value::I32(1));
51    ///
52    /// assert_eq!(g.get(&mut store), Value::I32(1));
53    /// assert_eq!(g.ty(&mut store).mutability, Mutability::Var);
54    /// ```
55    #[inline]
56    pub fn new_mut(store: &mut impl AsStoreMut, val: Value) -> Self {
57        Self::from_value(store, val, Mutability::Var).unwrap()
58    }
59
60    /// Create a global with the initial [`Value`] and the provided [`Mutability`].
61    #[inline]
62    pub(crate) fn from_value(
63        store: &mut impl AsStoreMut,
64        val: Value,
65        mutability: Mutability,
66    ) -> Result<Self, RuntimeError> {
67        match &store.as_store_mut().inner.store {
68            #[cfg(feature = "sys")]
69            crate::BackendStore::Sys(_) => Ok(Self::Sys(
70                crate::backend::sys::global::Global::from_value(store, val, mutability)?,
71            )),
72            #[cfg(feature = "v8")]
73            crate::BackendStore::V8(_) => Ok(Self::V8(
74                crate::backend::v8::global::Global::from_value(store, val, mutability)?,
75            )),
76            #[cfg(feature = "js")]
77            crate::BackendStore::Js(_) => Ok(Self::Js(
78                crate::backend::js::global::Global::from_value(store, val, mutability)?,
79            )),
80        }
81    }
82
83    /// Returns the [`GlobalType`] of the global.
84    ///
85    /// # Example
86    ///
87    /// ```
88    /// # use wasmer::{Global, Mutability, Store, Type, Value, GlobalType};
89    /// # let mut store = Store::default();
90    /// #
91    /// let c = Global::new(&mut store, Value::I32(1));
92    /// let v = Global::new_mut(&mut store, Value::I64(1));
93    ///
94    /// assert_eq!(c.ty(&mut store), GlobalType::new(Type::I32, Mutability::Const));
95    /// assert_eq!(v.ty(&mut store), GlobalType::new(Type::I64, Mutability::Var));
96    /// ```
97    #[inline]
98    pub fn ty(&self, store: &impl AsStoreRef) -> GlobalType {
99        match_rt!(on self => g {
100            g.ty(store)
101        })
102    }
103
104    /// Retrieves the current value [`Value`] that the global has.
105    ///
106    /// # Example
107    ///
108    /// ```
109    /// # use wasmer::{Global, Store, Value};
110    /// # let mut store = Store::default();
111    /// #
112    /// let g = Global::new(&mut store, Value::I32(1));
113    ///
114    /// assert_eq!(g.get(&mut store), Value::I32(1));
115    /// ```
116    #[inline]
117    pub fn get(&self, store: &mut impl AsStoreMut) -> Value {
118        match_rt!(on self => g {
119            g.get(store)
120        })
121    }
122
123    /// Sets a custom [`Value`] to the runtime global.
124    ///
125    /// # Example
126    ///
127    /// ```
128    /// # use wasmer::{Global, Store, Value};
129    /// # let mut store = Store::default();
130    /// #
131    /// let g = Global::new_mut(&mut store, Value::I32(1));
132    ///
133    /// assert_eq!(g.get(&mut store), Value::I32(1));
134    ///
135    /// g.set(&mut store, Value::I32(2));
136    ///
137    /// assert_eq!(g.get(&mut store), Value::I32(2));
138    /// ```
139    ///
140    /// # Errors
141    ///
142    /// Trying to mutate a immutable global will raise an error:
143    ///
144    /// ```should_panic
145    /// # use wasmer::{Global, Store, Value};
146    /// # let mut store = Store::default();
147    /// #
148    /// let g = Global::new(&mut store, Value::I32(1));
149    ///
150    /// g.set(&mut store, Value::I32(2)).unwrap();
151    /// ```
152    ///
153    /// Trying to set a value of a incompatible type will raise an error:
154    ///
155    /// ```should_panic
156    /// # use wasmer::{Global, Store, Value};
157    /// # let mut store = Store::default();
158    /// #
159    /// let g = Global::new(&mut store, Value::I32(1));
160    ///
161    /// // This results in an error: `RuntimeError`.
162    /// g.set(&mut store, Value::I64(2)).unwrap();
163    /// ```
164    #[inline]
165    pub fn set(&self, store: &mut impl AsStoreMut, val: Value) -> Result<(), RuntimeError> {
166        match_rt!(on self => s {
167            s.set(store, val)
168        })
169    }
170
171    #[inline]
172    pub(crate) fn from_vm_extern(store: &mut impl AsStoreMut, vm_extern: VMExternGlobal) -> Self {
173        match &store.as_store_mut().inner.store {
174            #[cfg(feature = "sys")]
175            crate::BackendStore::Sys(_) => Self::Sys(
176                crate::backend::sys::global::Global::from_vm_extern(store, vm_extern),
177            ),
178            #[cfg(feature = "v8")]
179            crate::BackendStore::V8(_) => Self::V8(
180                crate::backend::v8::global::Global::from_vm_extern(store, vm_extern),
181            ),
182            #[cfg(feature = "js")]
183            crate::BackendStore::Js(_) => Self::Js(
184                crate::backend::js::global::Global::from_vm_extern(store, vm_extern),
185            ),
186        }
187    }
188
189    /// Checks whether this global can be used with the given context.
190    #[inline]
191    pub fn is_from_store(&self, store: &impl AsStoreRef) -> bool {
192        match_rt!(on self => s {
193            s.is_from_store(store)
194        })
195    }
196
197    /// Create a [`VMExtern`] from self.
198    #[inline]
199    pub(crate) fn to_vm_extern(&self) -> VMExtern {
200        match_rt!(on self => s {
201            s.to_vm_extern()
202        })
203    }
204}