summaryrefslogtreecommitdiffstats
path: root/vendor/wasm-bindgen/src/convert/closures.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/wasm-bindgen/src/convert/closures.rs')
-rw-r--r--vendor/wasm-bindgen/src/convert/closures.rs225
1 files changed, 225 insertions, 0 deletions
diff --git a/vendor/wasm-bindgen/src/convert/closures.rs b/vendor/wasm-bindgen/src/convert/closures.rs
new file mode 100644
index 000000000..97755b8ee
--- /dev/null
+++ b/vendor/wasm-bindgen/src/convert/closures.rs
@@ -0,0 +1,225 @@
+use core::mem;
+
+use crate::convert::slices::WasmSlice;
+use crate::convert::RefFromWasmAbi;
+use crate::convert::{FromWasmAbi, IntoWasmAbi, ReturnWasmAbi};
+use crate::describe::{inform, WasmDescribe, FUNCTION};
+use crate::throw_str;
+
+macro_rules! stack_closures {
+ ($( ($cnt:tt $invoke:ident $invoke_mut:ident $($var:ident)*) )*) => ($(
+ impl<'a, 'b, $($var,)* R> IntoWasmAbi for &'a (dyn Fn($($var),*) -> R + 'b)
+ where $($var: FromWasmAbi,)*
+ R: ReturnWasmAbi
+ {
+ type Abi = WasmSlice;
+
+ fn into_abi(self) -> WasmSlice {
+ unsafe {
+ let (a, b): (usize, usize) = mem::transmute(self);
+ WasmSlice { ptr: a as u32, len: b as u32 }
+ }
+ }
+ }
+
+ #[allow(non_snake_case)]
+ unsafe extern "C" fn $invoke<$($var: FromWasmAbi,)* R: ReturnWasmAbi>(
+ a: usize,
+ b: usize,
+ $($var: <$var as FromWasmAbi>::Abi),*
+ ) -> <R as ReturnWasmAbi>::Abi {
+ if a == 0 {
+ throw_str("closure invoked recursively or destroyed already");
+ }
+ // Scope all local variables before we call `return_abi` to
+ // ensure they're all destroyed as `return_abi` may throw
+ let ret = {
+ let f: &dyn Fn($($var),*) -> R = mem::transmute((a, b));
+ $(
+ let $var = <$var as FromWasmAbi>::from_abi($var);
+ )*
+ f($($var),*)
+ };
+ ret.return_abi()
+ }
+
+ impl<'a, $($var,)* R> WasmDescribe for dyn Fn($($var),*) -> R + 'a
+ where $($var: FromWasmAbi,)*
+ R: ReturnWasmAbi
+ {
+ fn describe() {
+ inform(FUNCTION);
+ inform($invoke::<$($var,)* R> as u32);
+ inform($cnt);
+ $(<$var as WasmDescribe>::describe();)*
+ <R as WasmDescribe>::describe();
+ <R as WasmDescribe>::describe();
+ }
+ }
+
+ impl<'a, 'b, $($var,)* R> IntoWasmAbi for &'a mut (dyn FnMut($($var),*) -> R + 'b)
+ where $($var: FromWasmAbi,)*
+ R: ReturnWasmAbi
+ {
+ type Abi = WasmSlice;
+
+ fn into_abi(self) -> WasmSlice {
+ unsafe {
+ let (a, b): (usize, usize) = mem::transmute(self);
+ WasmSlice { ptr: a as u32, len: b as u32 }
+ }
+ }
+ }
+
+ #[allow(non_snake_case)]
+ unsafe extern "C" fn $invoke_mut<$($var: FromWasmAbi,)* R: ReturnWasmAbi>(
+ a: usize,
+ b: usize,
+ $($var: <$var as FromWasmAbi>::Abi),*
+ ) -> <R as ReturnWasmAbi>::Abi {
+ if a == 0 {
+ throw_str("closure invoked recursively or destroyed already");
+ }
+ // Scope all local variables before we call `return_abi` to
+ // ensure they're all destroyed as `return_abi` may throw
+ let ret = {
+ let f: &mut dyn FnMut($($var),*) -> R = mem::transmute((a, b));
+ $(
+ let $var = <$var as FromWasmAbi>::from_abi($var);
+ )*
+ f($($var),*)
+ };
+ ret.return_abi()
+ }
+
+ impl<'a, $($var,)* R> WasmDescribe for dyn FnMut($($var),*) -> R + 'a
+ where $($var: FromWasmAbi,)*
+ R: ReturnWasmAbi
+ {
+ fn describe() {
+ inform(FUNCTION);
+ inform($invoke_mut::<$($var,)* R> as u32);
+ inform($cnt);
+ $(<$var as WasmDescribe>::describe();)*
+ <R as WasmDescribe>::describe();
+ <R as WasmDescribe>::describe();
+ }
+ }
+ )*)
+}
+
+stack_closures! {
+ (0 invoke0 invoke0_mut)
+ (1 invoke1 invoke1_mut A)
+ (2 invoke2 invoke2_mut A B)
+ (3 invoke3 invoke3_mut A B C)
+ (4 invoke4 invoke4_mut A B C D)
+ (5 invoke5 invoke5_mut A B C D E)
+ (6 invoke6 invoke6_mut A B C D E F)
+ (7 invoke7 invoke7_mut A B C D E F G)
+ (8 invoke8 invoke8_mut A B C D E F G H)
+}
+
+impl<'a, 'b, A, R> IntoWasmAbi for &'a (dyn Fn(&A) -> R + 'b)
+where
+ A: RefFromWasmAbi,
+ R: ReturnWasmAbi,
+{
+ type Abi = WasmSlice;
+
+ fn into_abi(self) -> WasmSlice {
+ unsafe {
+ let (a, b): (usize, usize) = mem::transmute(self);
+ WasmSlice {
+ ptr: a as u32,
+ len: b as u32,
+ }
+ }
+ }
+}
+
+#[allow(non_snake_case)]
+unsafe extern "C" fn invoke1_ref<A: RefFromWasmAbi, R: ReturnWasmAbi>(
+ a: usize,
+ b: usize,
+ arg: <A as RefFromWasmAbi>::Abi,
+) -> <R as ReturnWasmAbi>::Abi {
+ if a == 0 {
+ throw_str("closure invoked recursively or destroyed already");
+ }
+ // Scope all local variables before we call `return_abi` to
+ // ensure they're all destroyed as `return_abi` may throw
+ let ret = {
+ let f: &dyn Fn(&A) -> R = mem::transmute((a, b));
+ let arg = <A as RefFromWasmAbi>::ref_from_abi(arg);
+ f(&*arg)
+ };
+ ret.return_abi()
+}
+
+impl<'a, A, R> WasmDescribe for dyn Fn(&A) -> R + 'a
+where
+ A: RefFromWasmAbi,
+ R: ReturnWasmAbi,
+{
+ fn describe() {
+ inform(FUNCTION);
+ inform(invoke1_ref::<A, R> as u32);
+ inform(1);
+ <&A as WasmDescribe>::describe();
+ <R as WasmDescribe>::describe();
+ <R as WasmDescribe>::describe();
+ }
+}
+
+impl<'a, 'b, A, R> IntoWasmAbi for &'a mut (dyn FnMut(&A) -> R + 'b)
+where
+ A: RefFromWasmAbi,
+ R: ReturnWasmAbi,
+{
+ type Abi = WasmSlice;
+
+ fn into_abi(self) -> WasmSlice {
+ unsafe {
+ let (a, b): (usize, usize) = mem::transmute(self);
+ WasmSlice {
+ ptr: a as u32,
+ len: b as u32,
+ }
+ }
+ }
+}
+
+#[allow(non_snake_case)]
+unsafe extern "C" fn invoke1_mut_ref<A: RefFromWasmAbi, R: ReturnWasmAbi>(
+ a: usize,
+ b: usize,
+ arg: <A as RefFromWasmAbi>::Abi,
+) -> <R as ReturnWasmAbi>::Abi {
+ if a == 0 {
+ throw_str("closure invoked recursively or destroyed already");
+ }
+ // Scope all local variables before we call `return_abi` to
+ // ensure they're all destroyed as `return_abi` may throw
+ let ret = {
+ let f: &mut dyn FnMut(&A) -> R = mem::transmute((a, b));
+ let arg = <A as RefFromWasmAbi>::ref_from_abi(arg);
+ f(&*arg)
+ };
+ ret.return_abi()
+}
+
+impl<'a, A, R> WasmDescribe for dyn FnMut(&A) -> R + 'a
+where
+ A: RefFromWasmAbi,
+ R: ReturnWasmAbi,
+{
+ fn describe() {
+ inform(FUNCTION);
+ inform(invoke1_mut_ref::<A, R> as u32);
+ inform(1);
+ <&A as WasmDescribe>::describe();
+ <R as WasmDescribe>::describe();
+ <R as WasmDescribe>::describe();
+ }
+}