Skip to main content

wasm_bindgen/
closure.rs

1//! Support for closures in `wasm-bindgen`
2//!
3//! This module defines the [`ScopedClosure`] type which is used to pass Rust closures
4//! to JavaScript. All closures are unwind safe by default: panics are caught and converted to
5//! JavaScript exceptions when built with `panic=unwind`.
6//!
7//! # Immutable by Default
8//!
9//! The closure API defaults to **immutable** (`Fn`) closures because they are more
10//! likely to satisfy `UnwindSafe` automatically:
11//!
12//! - `&T` where `T: RefUnwindSafe` is `UnwindSafe`
13//! - `&mut T` is **never** `UnwindSafe` regardless of `T`
14//!
15//! This means:
16//! - [`ScopedClosure::borrow`] creates an immutable `Fn` closure
17//! - [`ScopedClosure::borrow_mut`] creates a mutable `FnMut` closure
18//! - [`ImmediateClosure::new`] creates an immutable `Fn` closure
19//! - [`ImmediateClosure::new_mut`] creates a mutable `FnMut` closure
20//!
21//! Immutable closures can be upcasted to mutable closures using [`upcast_ref`](crate::Upcast::upcast_ref).
22//!
23//! # Type Aliases
24//!
25//! - [`ScopedClosure<'a, T>`] — The unified closure type with a lifetime parameter
26//! - [`Closure<T>`] — Alias for `ScopedClosure<'static, T>` (for backwards compatibility)
27//! - [`ImmediateClosure<'a, T>`] — Lightweight wrapper for immediate callbacks with unwind safety
28//!
29//! # Unwind Safety
30//!
31//! For immediate/synchronous callbacks, you have two options:
32//!
33//! - **[`ImmediateClosure`]**: Recommended when you want panics to be caught and converted
34//!   to JavaScript exceptions. This is safer but has slight overhead.
35//!
36//! - **`&dyn FnMut` / `&dyn Fn`**: Use when you don't need unwind safety and prefer
37//!   panics to abort the process.
38//!
39//! For [`ScopedClosure`], the default constructors (`borrow`, `borrow_mut`, `own`) catch
40//! panics, while the `_aborting` variants (`borrow_aborting`, `borrow_mut_aborting`, etc.) do not.
41//!
42//! # Ownership Model
43//!
44//! `ScopedClosure` follows the same ownership model as other wasm-bindgen types:
45//! the JavaScript reference remains valid until the Rust value is dropped. When
46//! dropped, the closure is invalidated and any subsequent calls from JavaScript
47//! will throw an exception.
48//!
49//! For borrowed closures created with `borrow`/`borrow_mut`, Rust's borrow checker
50//! ensures the `ScopedClosure` cannot outlive the closure's captured data.
51//!
52//! See the [`ScopedClosure`] type documentation for detailed examples.
53
54#![allow(clippy::fn_to_numeric_cast)]
55use alloc::boxed::Box;
56use alloc::string::String;
57use core::fmt;
58use core::mem::{self, ManuallyDrop};
59
60use crate::__rt::marker::ErasableGeneric;
61use crate::__rt::marker::MaybeUnwindSafe;
62use crate::describe::*;
63use crate::JsValue;
64use crate::{convert::*, JsCast};
65use core::marker::PhantomData;
66use core::panic::AssertUnwindSafe;
67
68#[wasm_bindgen_macro::wasm_bindgen(wasm_bindgen = crate)]
69extern "C" {
70    type JsClosure;
71
72    #[wasm_bindgen(method)]
73    fn _wbg_cb_unref(js: &JsClosure);
74}
75
76/// A closure with a lifetime parameter that represents a Rust closure passed to JavaScript.
77///
78/// `ScopedClosure<'a, T>` is the unified closure type. The lifetime `'a` indicates
79/// how long the closure is valid:
80///
81/// - **`ScopedClosure<'static, T>`** - An owned closure with heap-allocated data. Requires
82///   `'static` captures. Use for long-lived closures like event listeners and timers.
83///   Created with [`Closure::new`] or [`ScopedClosure::own`]. May transfer ownership to the
84///   JS GC using finalizers.
85///
86/// - **`ScopedClosure<'a, T>`** (non-`'static`) - A borrowed closure referencing stack data.
87///   Allows non-`'static` captures. Use for immediate/synchronous callbacks. Created with
88///   [`ScopedClosure::borrow`] (for `FnMut`) or [`ScopedClosure::borrow_immutable`] (for `Fn`).
89///   Cannot transfer ownership to JS GC.
90///
91/// [`Closure<T>`] is currently a type alias for `ScopedClosure<'static, T>`. In
92/// a future release, a lifetime argument will be added to this alias.
93///
94/// # Ownership Model
95///
96/// `ScopedClosure` follows the same ownership model as other wasm-bindgen types:
97/// the JavaScript reference remains valid until the Rust value is dropped. When
98/// dropped, the closure is invalidated and any subsequent calls from JavaScript
99/// will throw: "closure invoked recursively or after being dropped".
100///
101/// For `'static` closures, you can also:
102/// - Pass by value to transfer ownership to JS (implements [`IntoWasmAbi`])
103/// - Call [`forget()`](Self::forget) to leak the closure (JS can use it indefinitely)
104/// - Call [`into_js_value()`](Self::into_js_value) to transfer to JS GC management
105///
106/// # Lifetime Safety
107///
108/// For borrowed closures, Rust's borrow checker ensures that `ScopedClosure` cannot
109/// be held longer than the closure's captured data:
110///
111/// ```ignore
112/// let mut sum = 0;
113/// let mut f = |x: u32| { sum += x; };  // f borrows sum
114/// let closure = ScopedClosure::borrow(&mut f);  // closure borrows f
115/// // closure cannot outlive f, and f cannot outlive sum
116/// ```
117///
118/// # Examples
119///
120/// ## Borrowed closures with `ScopedClosure::borrow`
121///
122/// Use for immediate/synchronous callbacks where JS calls the closure right away:
123///
124/// ```ignore
125/// use wasm_bindgen::prelude::*;
126///
127/// #[wasm_bindgen]
128/// extern "C" {
129///     fn call_immediately(cb: &ScopedClosure<dyn FnMut(u32)>);
130/// }
131///
132/// let mut sum = 0;
133/// {
134///     let mut f = |x: u32| { sum += x; };
135///     let closure = ScopedClosure::borrow(&mut f);
136///     call_immediately(&closure);
137/// }  // closure dropped here, JS function invalidated
138/// assert_eq!(sum, 42);
139/// ```
140///
141/// ## Owned closures with `Closure::new`
142///
143/// Use for long-lived callbacks like event listeners and timers:
144///
145/// ```ignore
146/// use wasm_bindgen::prelude::*;
147///
148/// #[wasm_bindgen]
149/// extern "C" {
150///     fn setInterval(closure: &Closure<dyn FnMut()>, time: u32) -> i32;
151/// }
152///
153/// // Closure::new requires 'static, so use `move` to capture by value
154/// let cb = Closure::new(move || {
155///     // ...
156/// });
157/// setInterval(&cb, 1000);
158/// // Must keep `cb` alive or call `cb.forget()` to transfer to JS
159/// ```
160///
161/// ## Transferring ownership to JS
162///
163/// Pass a `ScopedClosure<'static, T>` by value to transfer ownership:
164///
165/// ```ignore
166/// use wasm_bindgen::prelude::*;
167///
168/// #[wasm_bindgen]
169/// extern "C" {
170///     fn set_one_shot_callback(cb: ScopedClosure<dyn FnMut()>);
171/// }
172///
173/// let cb = ScopedClosure::own(|| { /* ... */ });
174/// set_one_shot_callback(cb);  // Ownership transferred, no need to store
175/// ```
176pub struct ScopedClosure<'a, T: ?Sized> {
177    js: JsClosure,
178    // careful: must be Box<T> not just T because unsized PhantomData
179    // seems to have weird interaction with Pin<>
180    _marker: PhantomData<Box<T>>,
181    _lifetime: PhantomData<&'a ()>,
182}
183
184/// Alias for [`ScopedClosure<'static, T>`] for backwards compatibility.
185///
186/// In a future major version, `Closure` will become `ScopedClosure<'a, T>` with a
187/// lifetime parameter.
188pub type Closure<T> = ScopedClosure<'static, T>;
189
190// ScopedClosure is Unpin because it only contains a JsValue (which is just a u32)
191// and PhantomData markers. The closure data is either on the heap (owned) or
192// referenced through a raw pointer (borrowed), neither of which is stored inline.
193impl<T: ?Sized> Unpin for ScopedClosure<'_, T> {}
194
195fn _assert_compiles<T>(pin: core::pin::Pin<&mut ScopedClosure<'static, T>>) {
196    let _ = &mut *pin.get_mut();
197}
198
199impl<T: ?Sized> Drop for ScopedClosure<'_, T> {
200    fn drop(&mut self) {
201        // Invalidate the closure on the JS side.
202        //
203        // The JS bindings distinguish owned vs borrowed closures via the `dtor_idx`
204        // encoded in `WasmDescribe`: owned closures pass a non-zero destructor
205        // function pointer, borrowed closures pass `0`.
206        //
207        // For owned closures (`Closure::new`/`ScopedClosure::own`), this decreases
208        // the refcount and frees the Rust heap data when the count reaches zero.
209        //
210        // For borrowed closures (`ScopedClosure::borrow`/`borrow_mut`), this sets
211        // state.a = state.b = 0 to prevent any further calls to the closure.
212        self.js._wbg_cb_unref();
213    }
214}
215
216impl<'a, T> ScopedClosure<'a, T>
217where
218    T: ?Sized + WasmClosure,
219{
220    /// Obtain a `&JsValue` reference for this closure
221    pub fn as_js_value(&self) -> &JsValue {
222        self.js.unchecked_ref()
223    }
224}
225
226/// Methods for creating and managing `'static` closures.
227///
228/// These methods are only available on `ScopedClosure<'static, T>`
229/// not on borrowed `ScopedClosure<'a, T>` where `'a` is not `'static`.
230impl<T> ScopedClosure<'static, T>
231where
232    T: ?Sized + WasmClosure,
233{
234    /// Alias for [`Closure::own`].
235    ///
236    /// Creates a new static owned `ScopedClosure<'static, T>` from the provided
237    /// Rust function, with panic unwind support.
238    ///
239    /// The type parameter `T` determines whether the closure is `Fn` or `FnMut`.
240    ///
241    /// Supports unwind via its UnwindSafe bound when building with panic=unwind.
242    /// Alternatively, pass `Closure::own(AssertUnwindSafe(...))` to assert unwind
243    /// safety, or use [`own_assert_unwind_safe`](Self::own_assert_unwind_safe) or
244    /// [`own_aborting`](Self::own_aborting).
245    ///
246    /// When provided to a JS function as an own value, to be managed by the JS GC.
247    ///
248    /// See [`borrow`](Self::borrow) for creating a borrowed `ScopedClosure` with
249    /// an associated lifetime (defaults to immutable `Fn`).
250    pub fn new<F>(t: F) -> Self
251    where
252        F: IntoWasmClosure<T> + MaybeUnwindSafe + 'static,
253    {
254        Self::_wrap(Box::new(t).unsize(), true)
255    }
256
257    /// Creates a new static owned `ScopedClosure<'static, T>` from the provided
258    /// Rust function, with panic unwind support.
259    ///
260    /// The type parameter `T` determines whether the closure is `Fn` or `FnMut`.
261    ///
262    /// Supports unwind via its UnwindSafe bound when building with panic=unwind.
263    /// Alternatively, pass `Closure::own(AssertUnwindSafe(...))` to assert unwind
264    /// safety, or use [`own_assert_unwind_safe`](Self::own_assert_unwind_safe) or
265    /// [`own_aborting`](Self::own_aborting).
266    ///
267    /// When provided to a JS function as an own value, to be managed by the JS GC.
268    ///
269    /// See [`borrow`](Self::borrow) for creating a borrowed `ScopedClosure` with
270    /// an associated lifetime (defaults to immutable `Fn`).
271    pub fn own<F>(t: F) -> Self
272    where
273        F: IntoWasmClosure<T> + MaybeUnwindSafe + 'static,
274    {
275        Self::_wrap(Box::new(t).unsize(), true)
276    }
277
278    /// Creates a new owned `'static` closure that aborts on panic.
279    ///
280    /// Unlike [`own`](Self::own), this version does NOT catch panics and does NOT
281    /// require `UnwindSafe`. If the closure panics, the process will abort.
282    ///
283    /// The type parameter `T` determines whether the closure is `Fn` or `FnMut`.
284    ///
285    /// When provided to a JS function as an own value, to be managed by the JS GC.
286    ///
287    /// See [`borrow_aborting`](Self::borrow_aborting) for creating a borrowed
288    /// `ScopedClosure` with an associated lifetime.
289    ///
290    /// **Note: Not unwind safe. Prefer [`own`](Self::own) or `own` with
291    /// [`AssertUnwindSafe`](core::panic::AssertUnwindSafe) when possible.**
292    pub fn own_aborting<F>(t: F) -> Self
293    where
294        F: IntoWasmClosure<T> + 'static,
295    {
296        Self::_wrap(Box::new(t).unsize(), false)
297    }
298
299    /// Creates a new static owned `ScopedClosure<'static, T>` from the provided
300    /// Rust function, with panic unwind support.
301    ///
302    /// The type parameter `T` determines whether the closure is `Fn` or `FnMut`.
303    ///
304    /// When provided to a JS function as an own value, to be managed by the JS GC.
305    ///
306    /// **Safety: Unwind safety is assumed when using this function, like using
307    /// `AssertUnwindSafe(...)`, this must be verified explicitly.**
308    ///
309    /// See [`borrow_aborting`](Self::borrow_aborting) for creating a borrowed
310    /// `ScopedClosure` with an associated lifetime.
311    pub fn own_assert_unwind_safe<F>(t: F) -> Self
312    where
313        F: IntoWasmClosure<T> + 'static,
314    {
315        Self::_wrap(Box::new(t).unsize(), true)
316    }
317
318    /// A more direct version of `Closure::new` which creates a `Closure` from
319    /// a `Box<dyn Fn>`/`Box<dyn FnMut>`, which is how it's kept internally.
320    ///
321    /// Supports unwind via its UnwindSafe bound when building with panic=unwind.
322    /// Alternatively, use [`wrap_assert_unwind_safe`](Self::wrap_assert_unwind_safe)
323    /// to assert unwind safety, or use [`wrap_aborting`](Self::wrap_aborting).
324    ///
325    pub fn wrap<F>(data: Box<F>) -> Self
326    where
327        F: IntoWasmClosure<T> + ?Sized + MaybeUnwindSafe,
328    {
329        Self::_wrap(data.unsize(), true)
330    }
331
332    /// A more direct version of `Closure::new` which creates a `Closure` from
333    /// a `Box<dyn Fn>`/`Box<dyn FnMut>`, which is how it's kept internally.
334    ///
335    /// This version aborts on panics.
336    pub fn wrap_aborting<F>(data: Box<F>) -> Self
337    where
338        F: IntoWasmClosure<T> + ?Sized,
339    {
340        Self::_wrap(data.unsize(), false)
341    }
342
343    /// A more direct version of `Closure::new` which creates a `Closure` from
344    /// a `Box<dyn Fn>`/`Box<dyn FnMut>`, which is how it's kept internally.
345    ///
346    /// **Safety: Unwind safety is assumed when using this function, like using
347    /// `AssertUnwindSafe(...)`, this must be verified explicitly.**
348    ///
349    /// This version catches panics when unwinding is available.
350    pub fn wrap_assert_unwind_safe<F>(data: Box<F>) -> Self
351    where
352        F: IntoWasmClosure<T> + ?Sized,
353    {
354        Self::_wrap(data.unsize(), true)
355    }
356
357    #[cfg(all(feature = "std", target_arch = "wasm32", panic = "unwind"))]
358    fn _wrap(data: Box<T>, unwind_safe: bool) -> Self {
359        Self {
360            js: crate::__rt::wbg_cast(OwnedClosureUnwind { data, unwind_safe }),
361            _marker: PhantomData,
362            _lifetime: PhantomData,
363        }
364    }
365
366    #[cfg(not(all(feature = "std", target_arch = "wasm32", panic = "unwind")))]
367    fn _wrap(data: Box<T>, _unwind_safe: bool) -> Self {
368        Self {
369            js: crate::__rt::wbg_cast(OwnedClosure(data)),
370            _marker: PhantomData,
371            _lifetime: PhantomData,
372        }
373    }
374
375    /// Creates a scoped closure by borrowing an immutable `Fn` closure with
376    /// panic unwind support.
377    ///
378    /// This is the recommended way to pass closures to JavaScript for immediate/
379    /// synchronous use. Unlike [`Closure::own`], this does not require the closure
380    /// to be `'static`, allowing you to capture references to local variables.
381    ///
382    /// Use [`borrow_mut`](Self::borrow_mut) when you need to mutate captured state.
383    ///
384    /// The returned `ScopedClosure<'a, _>` has lifetime `'a` from the closure
385    /// reference, which means it cannot outlive the closure or any data the
386    /// closure captures.
387    ///
388    /// Supports unwind via its UnwindSafe bound when building with panic=unwind.
389    /// Wrap with `AssertUnwindSafe` if necessary to achieve this bound, or
390    /// use [`borrow_assert_unwind_safe`](Self::borrow_assert_unwind_safe) or
391    /// [`borrow_aborting`](Self::borrow_aborting) for non-unwind-safe functions.
392    ///
393    /// The resulting closure can be upcasted to `FnMut` using [`upcast_ref`](crate::Upcast::upcast_ref).
394    ///
395    /// # When to use scoped closures
396    ///
397    /// Use `ScopedClosure::borrow` or `ScopedClosure::borrow_mut` when:
398    /// - JavaScript will call the closure immediately and not retain it
399    /// - You need to capture non-`'static` references
400    /// - You want automatic cleanup when the `ScopedClosure` is dropped
401    ///
402    /// # Closure lifetime
403    ///
404    /// The JavaScript function is only valid while the `ScopedClosure` exists.
405    /// Once dropped, the JavaScript function is invalidated. If JavaScript retains
406    /// a reference and calls it later, it will throw: "closure invoked recursively
407    /// or after being dropped".
408    ///
409    /// Rust's borrow checker ensures `ScopedClosure` cannot outlive the closure's
410    /// captured data, preventing use-after-free bugs.
411    ///
412    /// # Example
413    ///
414    /// ```ignore
415    /// use wasm_bindgen::prelude::*;
416    ///
417    /// #[wasm_bindgen]
418    /// extern "C" {
419    ///     fn call_with_value(cb: &ScopedClosure<dyn Fn(u32)>, value: u32);
420    ///     fn call_fnmut(cb: &ScopedClosure<dyn FnMut(u32)>, value: u32);
421    /// }
422    ///
423    /// let data = vec![1, 2, 3];
424    /// let f = |x| {
425    ///     println!("data len: {}, x: {}", data.len(), x);
426    /// };
427    /// let closure = ScopedClosure::borrow(&f);
428    /// call_with_value(&closure, 42);
429    /// // Can also upcast to FnMut
430    /// call_fnmut(closure.upcast_ref(), 42);
431    /// ```
432    pub fn borrow<'a, F>(t: &'a F) -> ScopedClosure<'a, F::Static>
433    where
434        F: IntoWasmClosureRef<'a, T> + MaybeUnwindSafe + ?Sized,
435    {
436        let t: &T = t.unsize_closure_ref();
437        let (ptr, len): (u32, u32) = unsafe { mem::transmute_copy(&t) };
438        ScopedClosure {
439            js: crate::__rt::wbg_cast(BorrowedClosure::<T> {
440                data: WasmSlice { ptr, len },
441                unwind_safe: true,
442                _marker: PhantomData,
443            }),
444            _marker: PhantomData,
445            _lifetime: PhantomData,
446        }
447    }
448
449    /// Like [`borrow`](Self::borrow), but does not catch panics.
450    ///
451    /// If the closure panics, the process will abort. This variant does not
452    /// require `UnwindSafe`.
453    ///
454    /// **Note: Not unwind safe. Prefer [`borrow`](Self::borrow) or
455    /// [`borrow_assert_unwind_safe`](Self::borrow_assert_unwind_safe) when possible.**
456    pub fn borrow_aborting<'a, F>(t: &'a F) -> ScopedClosure<'a, F::Static>
457    where
458        F: IntoWasmClosureRef<'a, T> + ?Sized,
459    {
460        let t: &T = t.unsize_closure_ref();
461        let (ptr, len): (u32, u32) = unsafe { mem::transmute_copy(&t) };
462        ScopedClosure {
463            js: crate::__rt::wbg_cast(BorrowedClosure::<T> {
464                data: WasmSlice { ptr, len },
465                unwind_safe: false,
466                _marker: PhantomData,
467            }),
468            _marker: PhantomData,
469            _lifetime: PhantomData,
470        }
471    }
472
473    /// Like [`borrow`](Self::borrow), but catches panics without requiring `MaybeUnwindSafe`.
474    ///
475    /// **Safety: Unwind safety is assumed when using this function, like using
476    /// `AssertUnwindSafe(...)`, this must be verified explicitly.**
477    pub fn borrow_assert_unwind_safe<'a, F>(t: &'a F) -> ScopedClosure<'a, F::Static>
478    where
479        F: IntoWasmClosureRef<'a, T> + ?Sized,
480    {
481        let t: &T = t.unsize_closure_ref();
482        let (ptr, len): (u32, u32) = unsafe { mem::transmute_copy(&t) };
483        ScopedClosure {
484            js: crate::__rt::wbg_cast(BorrowedClosure::<T> {
485                data: WasmSlice { ptr, len },
486                unwind_safe: true,
487                _marker: PhantomData,
488            }),
489            _marker: PhantomData,
490            _lifetime: PhantomData,
491        }
492    }
493
494    /// Creates a scoped closure by mutably borrowing a `FnMut` closure.
495    ///
496    /// Use this for closures that need to mutate captured state. For closures that
497    /// don't need mutation, prefer [`borrow`](Self::borrow) which creates an immutable
498    /// `Fn` closure that is more likely to satisfy `UnwindSafe` automatically.
499    ///
500    /// Supports unwind via its UnwindSafe bound when building with panic=unwind.
501    /// Wrap with `AssertUnwindSafe` if necessary to achieve this bound, or
502    /// use [`borrow_mut_assert_unwind_safe`](Self::borrow_mut_assert_unwind_safe) or
503    /// [`borrow_mut_aborting`](Self::borrow_mut_aborting) for non-unwind-safe functions.
504    ///
505    /// See [`borrow`](Self::borrow) for full documentation on scoped closures.
506    ///
507    /// # Example
508    ///
509    /// ```ignore
510    /// use wasm_bindgen::prelude::*;
511    ///
512    /// #[wasm_bindgen]
513    /// extern "C" {
514    ///     fn call_three_times(cb: &ScopedClosure<dyn FnMut(u32)>);
515    /// }
516    ///
517    /// let mut sum = 0;
518    /// let closure = ScopedClosure::borrow_mut(&mut |x: u32| {
519    ///     sum += x;
520    /// });
521    /// call_three_times(&closure);
522    /// // closure dropped, `sum` is accessible again
523    /// assert_eq!(sum, 6); // 1 + 2 + 3
524    /// ```
525    pub fn borrow_mut<'a, F>(t: &'a mut F) -> ScopedClosure<'a, F::Static>
526    where
527        F: IntoWasmClosureRefMut<'a, T> + MaybeUnwindSafe + ?Sized,
528    {
529        let t: &mut T = t.unsize_closure_ref();
530        let (ptr, len): (u32, u32) = unsafe { mem::transmute_copy(&t) };
531        ScopedClosure {
532            js: crate::__rt::wbg_cast(BorrowedClosure::<T> {
533                data: WasmSlice { ptr, len },
534                unwind_safe: true,
535                _marker: PhantomData,
536            }),
537            _marker: PhantomData,
538            _lifetime: PhantomData,
539        }
540    }
541
542    /// Like [`borrow_mut`](Self::borrow_mut), but does not catch panics.
543    ///
544    /// If the closure panics, the process will abort. This variant does not
545    /// require `UnwindSafe`.
546    ///
547    /// **Note: Not unwind safe. Prefer [`borrow_mut`](Self::borrow_mut) or
548    /// [`borrow_mut_assert_unwind_safe`](Self::borrow_mut_assert_unwind_safe) when possible.**
549    pub fn borrow_mut_aborting<'a, F>(t: &'a mut F) -> ScopedClosure<'a, F::Static>
550    where
551        F: IntoWasmClosureRefMut<'a, T> + ?Sized,
552    {
553        let t: &mut T = t.unsize_closure_ref();
554        let (ptr, len): (u32, u32) = unsafe { mem::transmute_copy(&t) };
555        ScopedClosure {
556            js: crate::__rt::wbg_cast(BorrowedClosure::<T> {
557                data: WasmSlice { ptr, len },
558                unwind_safe: false,
559                _marker: PhantomData,
560            }),
561            _marker: PhantomData,
562            _lifetime: PhantomData,
563        }
564    }
565
566    /// Like [`borrow_mut`](Self::borrow_mut), but catches panics without requiring `MaybeUnwindSafe`.
567    ///
568    /// **Safety: Unwind safety is assumed when using this function, like using
569    /// `AssertUnwindSafe(...)`, this must be verified explicitly.**
570    pub fn borrow_mut_assert_unwind_safe<'a, F>(t: &'a mut F) -> ScopedClosure<'a, F::Static>
571    where
572        F: IntoWasmClosureRefMut<'a, T> + ?Sized,
573    {
574        let t: &mut T = t.unsize_closure_ref();
575        let (ptr, len): (u32, u32) = unsafe { mem::transmute_copy(&t) };
576        ScopedClosure {
577            js: crate::__rt::wbg_cast(BorrowedClosure::<T> {
578                data: WasmSlice { ptr, len },
579                unwind_safe: true,
580                _marker: PhantomData,
581            }),
582            _marker: PhantomData,
583            _lifetime: PhantomData,
584        }
585    }
586
587    /// Release memory management of this closure from Rust to the JS GC.
588    ///
589    /// When a `Closure` is dropped it will release the Rust memory and
590    /// invalidate the associated JS closure, but this isn't always desired.
591    /// Some callbacks are alive for the entire duration of the program or for a
592    /// lifetime dynamically managed by the JS GC. This function can be used
593    /// to drop this `Closure` while keeping the associated JS function still
594    /// valid.
595    ///
596    /// If the platform supports weak references, the Rust memory will be
597    /// reclaimed when the JS closure is GC'd. If weak references is not
598    /// supported, this can be dangerous if this function is called many times
599    /// in an application because the memory leak will overwhelm the page
600    /// quickly and crash the wasm.
601    ///
602    /// # Safety Note
603    ///
604    /// This method is only available on `'static` closures. Calling it on a
605    /// borrowed `ScopedClosure` would be unsound because the closure data
606    /// would become invalid when the borrow ends.
607    pub fn into_js_value(self) -> JsValue {
608        let idx = self.js.idx;
609        mem::forget(self);
610        JsValue::_new(idx)
611    }
612
613    /// Same as `mem::forget(self)`.
614    ///
615    /// This can be used to fully relinquish closure ownership to the JS.
616    ///
617    /// # Safety Note
618    ///
619    /// This method is only available on `'static` closures. Calling it on a borrowed
620    /// `ScopedClosure` would be unsound because the closure data would become invalid
621    /// when the borrow ends.
622    pub fn forget(self) {
623        mem::forget(self);
624    }
625
626    /// Create a `Closure` from a function that can only be called once.
627    ///
628    /// Since we have no way of enforcing that JS cannot attempt to call this
629    /// `FnOne(A...) -> R` more than once, this produces a `Closure<dyn FnMut(A...)
630    /// -> R>` that will dynamically throw a JavaScript error if called more
631    /// than once.
632    ///
633    /// # Example
634    ///
635    /// ```rust,no_run
636    /// use wasm_bindgen::prelude::*;
637    ///
638    /// // Create an non-`Copy`, owned `String`.
639    /// let mut s = String::from("Hello");
640    ///
641    /// // Close over `s`. Since `f` returns `s`, it is `FnOnce` and can only be
642    /// // called once. If it was called a second time, it wouldn't have any `s`
643    /// // to work with anymore!
644    /// let f = move || {
645    ///     s += ", World!";
646    ///     s
647    /// };
648    ///
649    /// // Create a `Closure` from `f`. Note that the `Closure`'s type parameter
650    /// // is `FnMut`, even though `f` is `FnOnce`.
651    /// let closure: Closure<dyn FnMut() -> String> = Closure::once(f);
652    /// ```
653    ///
654    /// Note: the `A` and `R` type parameters are here just for backward compat
655    /// and will be removed in the future.
656    pub fn once<F, A, R>(fn_once: F) -> Self
657    where
658        F: WasmClosureFnOnce<T, A, R> + MaybeUnwindSafe,
659    {
660        Closure::_wrap(fn_once.into_fn_mut(), true)
661    }
662
663    /// Create a `Closure` from a function that can only be called once.
664    ///
665    /// Unlike `once`, this version does NOT catch panics and does NOT require `UnwindSafe`.
666    /// If the closure panics, the process will abort.
667    ///
668    /// Use this when:
669    /// - Your closure captures types that aren't `UnwindSafe` (like `Rc<Cell<T>>`)
670    /// - You don't need panic catching across the JS boundary
671    /// - You prefer abort-on-panic behavior
672    ///
673    /// Since we have no way of enforcing that JS cannot attempt to call this
674    /// `FnOnce(A...) -> R` more than once, this produces a `Closure<dyn FnMut(A...)
675    /// -> R>` that will dynamically throw a JavaScript error if called more
676    /// than once.
677    ///
678    /// **Note: Not unwind safe. Prefer [`once`](Self::once) or `once` with
679    /// [`AssertUnwindSafe`](core::panic::AssertUnwindSafe) when possible.**
680    ///
681    /// Note: the `A` and `R` type parameters are here just for backward compat
682    /// and will be removed in the future.
683    pub fn once_aborting<F, A, R>(fn_once: F) -> Self
684    where
685        F: WasmClosureFnOnceAbort<T, A, R>,
686    {
687        Closure::_wrap(fn_once.into_fn_mut(), false)
688    }
689
690    /// Create a `Closure` from a function that can only be called once,
691    /// with panic unwind support.
692    ///
693    /// **Safety: Unwind safety is assumed when using this function, like using
694    /// `AssertUnwindSafe(...)`, this must be verified explicitly.**
695    ///
696    /// Use this when:
697    /// - Your closure captures types that aren't `UnwindSafe` (like `Rc<Cell<T>>`)
698    /// - You still want panics to be caught and converted to JS exceptions
699    ///
700    /// Since we have no way of enforcing that JS cannot attempt to call this
701    /// `FnOnce(A...) -> R` more than once, this produces a `Closure<dyn FnMut(A...)
702    /// -> R>` that will dynamically throw a JavaScript error if called more
703    /// than once.
704    ///
705    /// Note: the `A` and `R` type parameters are here just for backward compat
706    /// and will be removed in the future.
707    pub fn once_assert_unwind_safe<F, A, R>(fn_once: F) -> Self
708    where
709        F: WasmClosureFnOnceAbort<T, A, R>,
710    {
711        Closure::_wrap(fn_once.into_fn_mut(), true)
712    }
713
714    // TODO: Update once closures to be generated on construction as once
715    // closures instead of using wrap(). Then we can share the same into_js()
716    // function between all closures, and deprecate this method.
717    /// Convert a `FnOnce(A...) -> R` into a JavaScript `Function` object.
718    ///
719    /// If the JavaScript function is invoked more than once, it will throw an
720    /// exception.
721    ///
722    /// Unlike `Closure::once`, this does *not* return a `Closure` that can be
723    /// dropped before the function is invoked to deallocate the closure. The
724    /// only way the `FnOnce` is deallocated is by calling the JavaScript
725    /// function. If the JavaScript function is never called then the `FnOnce`
726    /// and everything it closes over will leak.
727    ///
728    /// ```rust,ignore
729    /// use wasm_bindgen::{prelude::*, JsCast};
730    ///
731    /// let f = Closure::once_into_js(move || {
732    ///     // ...
733    /// });
734    ///
735    /// assert!(f.is_instance_of::<js_sys::Function>());
736    /// ```
737    ///
738    /// Note: the `A` and `R` type parameters are here just for backward compat
739    /// and will be removed in the future.
740    pub fn once_into_js<F, A, R>(fn_once: F) -> JsValue
741    where
742        F: WasmClosureFnOnce<T, A, R> + MaybeUnwindSafe,
743    {
744        fn_once.into_js_function()
745    }
746}
747
748/// A closure wrapper for immediate/synchronous callbacks with unwind safety.
749///
750/// `ImmediateClosure` wraps a borrowed closure for use in synchronous JS callbacks
751/// like `Array.forEach`, `Array.map`, etc. The JS side receives the closure,
752/// calls it immediately, and discards it - no GC tracking is needed.
753///
754/// Panics are caught and converted to JavaScript exceptions (when built with
755/// `panic=unwind`). No `UnwindSafe` bounds are required - the closure is wrapped
756/// internally.
757///
758/// # Unwind Safety
759///
760/// `ImmediateClosure` provides unwind safety by catching panics and converting them
761/// to JavaScript exceptions.
762///
763/// # Example
764///
765/// ```ignore
766/// use wasm_bindgen::prelude::*;
767///
768/// #[wasm_bindgen]
769/// extern "C" {
770///     fn forEach<'a>(cb: ImmediateClosure<'a, dyn FnMut(JsValue) + 'a>);
771/// }
772///
773/// let mut sum = 0;
774/// forEach(ImmediateClosure::new_mut(&mut |val: JsValue| {
775///     sum += val.as_f64().unwrap() as i32;
776/// }));
777/// // sum is now updated
778/// ```
779///
780/// **Note:** To ensure borrowed lifetimes are correctly inferred, make sure to pass
781/// the lifetime to both the ImmediateClosure lifetime parameter AND its dyn FnMut
782/// parameter, as in the example above.
783pub struct ImmediateClosure<'a, T: ?Sized> {
784    data: WasmSlice,
785    unwind_safe: bool,
786    _marker: PhantomData<&'a mut T>,
787}
788
789impl<'a, T: ?Sized + WasmClosure> ImmediateClosure<'a, T> {
790    /// Creates an immediate closure from an immutable borrow of a `Fn` closure.
791    ///
792    /// Immutable closures (`Fn`) are preferred because they are more likely to satisfy `UnwindSafe`
793    /// automatically. Use [`new_mut`](Self::new_mut) when you need to mutate captured state.
794    ///
795    /// Note that immutable closures can be `upcast()` to mutable closures on the JS boundary
796    /// when required by function signatures.
797    ///
798    /// Panics are caught as JS exceptions when building with panic=unwind.
799    /// The resulting closure can be upcasted to `FnMut` using [`upcast_ref`](crate::Upcast::upcast_ref).
800    ///
801    /// # Example
802    ///
803    /// ```ignore
804    /// let data = vec![1, 2, 3];
805    /// let closure = ImmediateClosure::new(&|| {
806    ///     println!("data len: {}", data.len());
807    /// });
808    /// call_closure(&closure);
809    /// ```
810    pub fn new<F>(f: &'a F) -> ImmediateClosure<'a, F::WithLifetime>
811    where
812        F: IntoWasmClosureRef<'a, T> + ?Sized + MaybeUnwindSafe,
813    {
814        let t: &T = f.unsize_closure_ref();
815        let (ptr, len): (u32, u32) = unsafe { mem::transmute_copy(&t) };
816        ImmediateClosure {
817            data: WasmSlice { ptr, len },
818            unwind_safe: true,
819            _marker: PhantomData,
820        }
821    }
822
823    /// Like [`new`](Self::new), but does not catch panics.
824    ///
825    /// This variant enables type inference from the expected type, since it
826    /// takes the dyn type directly.
827    ///
828    /// **Note: Not unwind safe. Prefer [`new`](Self::new) or
829    /// [`new_assert_unwind_safe`](Self::new_assert_unwind_safe) when possible.**
830    pub fn new_aborting(f: &'a T) -> Self {
831        ImmediateClosure {
832            data: T::to_wasm_slice(f),
833            unwind_safe: false,
834            _marker: PhantomData,
835        }
836    }
837
838    /// Like [`new_aborting`](Self::new_aborting), but catches panics and converts them to JS exceptions.
839    ///
840    /// **Safety: Unwind safety is assumed when using this function, like using
841    /// `AssertUnwindSafe(...)`, this must be verified explicitly.**
842    ///
843    /// # Example
844    ///
845    /// ```ignore
846    /// let data = vec![1, 2, 3];
847    /// // Type is inferred from context
848    /// let closure: ImmediateClosure<dyn Fn()> = ImmediateClosure::new_assert_unwind_safe(&|| {
849    ///     println!("data len: {}", data.len());
850    /// });
851    /// ```
852    pub fn new_assert_unwind_safe(f: &'a T) -> Self {
853        ImmediateClosure {
854            data: T::to_wasm_slice(f),
855            unwind_safe: true,
856            _marker: PhantomData,
857        }
858    }
859
860    /// Creates an immediate closure from a mutable borrow of a `FnMut` closure.
861    ///
862    /// Use this for closures that need to mutate captured state. For closures that
863    /// don't need mutation, [`new`](Self::new) creates an immutable `Fn` closure
864    /// that is more likely to satisfy `UnwindSafe` automatically.
865    ///
866    /// Panics are caught as JS exceptions when building with panic=unwind.
867    ///
868    /// # Example
869    ///
870    /// ```ignore
871    /// let mut count = 0;
872    /// let closure = ImmediateClosure::new_mut(&mut || { count += 1; });
873    /// call_closure(&closure);
874    /// assert_eq!(count, 1);
875    /// ```
876    pub fn new_mut<F>(f: &'a mut F) -> ImmediateClosure<'a, F::WithLifetime>
877    where
878        F: IntoWasmClosureRefMut<'a, T> + ?Sized + MaybeUnwindSafe,
879    {
880        let t: &mut T = f.unsize_closure_ref();
881        let (ptr, len): (u32, u32) = unsafe { mem::transmute_copy(&t) };
882        ImmediateClosure {
883            data: WasmSlice { ptr, len },
884            unwind_safe: true,
885            _marker: PhantomData,
886        }
887    }
888
889    /// Like [`new_mut`](Self::new_mut), but does not catch panics.
890    ///
891    /// This variant enables type inference from the expected type, since it
892    /// takes the dyn type directly.
893    ///
894    /// **Note: Not unwind safe. Prefer [`new_mut`](Self::new_mut) or
895    /// [`new_mut_assert_unwind_safe`](Self::new_mut_assert_unwind_safe) when possible.**
896    pub fn new_mut_aborting(f: &'a mut T) -> Self {
897        ImmediateClosure {
898            data: T::to_wasm_slice(f),
899            unwind_safe: false,
900            _marker: PhantomData,
901        }
902    }
903
904    /// Like [`new_mut_aborting`](Self::new_mut_aborting), but catches panics and converts them to JS exceptions.
905    ///
906    /// **Safety: Unwind safety is assumed when using this function, like using
907    /// `AssertUnwindSafe(...)`, this must be verified explicitly.**
908    ///
909    /// # Example
910    ///
911    /// ```ignore
912    /// let mut count = 0;
913    /// // Type of `x` is inferred from context
914    /// let closure: ImmediateClosure<dyn FnMut(u32)> = ImmediateClosure::new_mut_assert_unwind_safe(&mut |x| {
915    ///     count += x;
916    /// });
917    /// ```
918    pub fn new_mut_assert_unwind_safe(f: &'a mut T) -> Self {
919        ImmediateClosure {
920            data: T::to_wasm_slice(f),
921            unwind_safe: true,
922            _marker: PhantomData,
923        }
924    }
925
926    /// Converts this closure to a mutable `FnMut` closure.
927    ///
928    /// This is safe because every `Fn` can be called through a `FnMut` interface.
929    /// The fat pointer representation is compatible—`dyn Fn` can be safely
930    /// reinterpreted as `dyn FnMut`.
931    ///
932    /// Note: Unlike `ScopedClosure::as_mut`, this only supports the Fn→FnMut conversion
933    /// with the same argument and return types. `ImmediateClosure` stores a Rust fat
934    /// pointer directly, so argument/return type variance is not possible.
935    ///
936    /// # Example
937    ///
938    /// ```ignore
939    /// use wasm_bindgen::prelude::*;
940    ///
941    /// #[wasm_bindgen]
942    /// extern "C" {
943    ///     fn needs_fnmut(cb: ImmediateClosure<dyn FnMut(u32)>);
944    /// }
945    ///
946    /// let func: &dyn Fn(u32) = &|x| println!("{}", x);
947    /// let closure: ImmediateClosure<dyn Fn(u32)> = ImmediateClosure::new_assert_unwind_safe(func);
948    /// needs_fnmut(closure.as_mut());
949    /// ```
950    pub fn as_mut(self) -> ImmediateClosure<'a, T::AsMut> {
951        // SAFETY: ImmediateClosure stores a WasmSlice (fat pointer data) and metadata.
952        // The type parameter T is phantom data. A dyn Fn fat pointer can be safely
953        // reinterpreted as dyn FnMut since Fn is a supertrait of FnMut.
954        ImmediateClosure {
955            data: self.data,
956            unwind_safe: self.unwind_safe,
957            _marker: PhantomData,
958        }
959    }
960}
961
962impl<T: ?Sized> fmt::Debug for ImmediateClosure<'_, T> {
963    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
964        f.debug_struct("ImmediateClosure").finish_non_exhaustive()
965    }
966}
967
968/// A trait for converting an `FnOnce(A...) -> R` into a `FnMut(A...) -> R` that
969/// will throw if ever called more than once.
970#[doc(hidden)]
971pub trait WasmClosureFnOnce<FnMut: ?Sized, A, R>: 'static {
972    fn into_fn_mut(self) -> Box<FnMut>;
973
974    fn into_js_function(self) -> JsValue;
975}
976
977/// A trait for converting an `FnOnce(A...) -> R` into a `FnMut(A...) -> R` that
978/// will throw if ever called more than once. This variant does not require UnwindSafe.
979#[doc(hidden)]
980pub trait WasmClosureFnOnceAbort<FnMut: ?Sized, A, R>: 'static {
981    fn into_fn_mut(self) -> Box<FnMut>;
982
983    fn into_js_function(self) -> JsValue;
984}
985
986impl<T: ?Sized> AsRef<JsValue> for ScopedClosure<'_, T> {
987    fn as_ref(&self) -> &JsValue {
988        &self.js
989    }
990}
991
992/// Internal representation of an owned closure that we send to JS.
993/// This is used when panic=abort or when panic=unwind but without the unwind_safe flag.
994#[repr(transparent)]
995struct OwnedClosure<T: ?Sized>(Box<T>);
996
997/// Internal representation of an owned closure with unwind safety flag. Used
998/// when panic=unwind to pass both the closure and the unwind_safe flag to JS.
999#[cfg(all(feature = "std", target_arch = "wasm32", panic = "unwind"))]
1000struct OwnedClosureUnwind<T: ?Sized> {
1001    data: Box<T>,
1002    unwind_safe: bool,
1003}
1004
1005struct BorrowedClosure<T: ?Sized> {
1006    data: WasmSlice,
1007    unwind_safe: bool,
1008    _marker: PhantomData<T>,
1009}
1010
1011unsafe extern "C" fn destroy<T: ?Sized>(a: usize, mut b: usize) {
1012    if a == 0 {
1013        return;
1014    }
1015    // Mask out unwind_safe flag
1016    b &= !0x80000000;
1017    drop(mem::transmute_copy::<_, Box<T>>(&(a, b)));
1018}
1019
1020impl<T> WasmDescribe for OwnedClosure<T>
1021where
1022    T: WasmClosure + ?Sized,
1023{
1024    #[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
1025    fn describe() {
1026        inform(CLOSURE);
1027        inform(destroy::<T> as *const () as usize as u32);
1028        inform(T::IS_MUT as u32);
1029        T::describe();
1030    }
1031}
1032
1033impl<T> WasmDescribe for BorrowedClosure<T>
1034where
1035    T: WasmClosure + ?Sized,
1036{
1037    #[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
1038    fn describe() {
1039        inform(CLOSURE);
1040        inform(0);
1041        inform(T::IS_MUT as u32);
1042        T::describe();
1043    }
1044}
1045
1046impl<T> IntoWasmAbi for OwnedClosure<T>
1047where
1048    T: WasmClosure + ?Sized,
1049{
1050    type Abi = WasmSlice;
1051
1052    fn into_abi(self) -> WasmSlice {
1053        let (a, b): (usize, usize) = unsafe { mem::transmute_copy(&ManuallyDrop::new(self)) };
1054        WasmSlice {
1055            ptr: a as u32,
1056            len: b as u32,
1057        }
1058    }
1059}
1060
1061impl<T> IntoWasmAbi for BorrowedClosure<T>
1062where
1063    T: WasmClosure + ?Sized,
1064{
1065    type Abi = WasmSlice;
1066    fn into_abi(self) -> WasmSlice {
1067        let WasmSlice { ptr, mut len } = self.data;
1068        if self.unwind_safe {
1069            len |= 0x80000000;
1070        }
1071        WasmSlice { ptr, len }
1072    }
1073}
1074
1075#[cfg(all(feature = "std", target_arch = "wasm32", panic = "unwind"))]
1076impl<T> WasmDescribe for OwnedClosureUnwind<T>
1077where
1078    T: WasmClosure + ?Sized,
1079{
1080    #[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
1081    fn describe() {
1082        // Delegate to the inner closure's descriptor - type info is the same
1083        OwnedClosure::<T>::describe();
1084    }
1085}
1086
1087#[cfg(all(feature = "std", target_arch = "wasm32", panic = "unwind"))]
1088impl<T> IntoWasmAbi for OwnedClosureUnwind<T>
1089where
1090    T: WasmClosure + ?Sized,
1091{
1092    type Abi = WasmSlice;
1093
1094    fn into_abi(self) -> WasmSlice {
1095        let (a, b): (usize, usize) = unsafe { mem::transmute_copy(&ManuallyDrop::new(self.data)) };
1096        // Pack unwind_safe into most significant bit (bit 31) of vtable
1097        let b_with_flag = if self.unwind_safe {
1098            (b as u32) | 0x80000000
1099        } else {
1100            b as u32
1101        };
1102        WasmSlice {
1103            ptr: a as u32,
1104            len: b_with_flag,
1105        }
1106    }
1107}
1108
1109impl<T> WasmDescribe for ScopedClosure<'_, T>
1110where
1111    T: WasmClosure + ?Sized,
1112{
1113    #[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
1114    fn describe() {
1115        inform(EXTERNREF);
1116    }
1117}
1118
1119// `ScopedClosure` can be passed by reference to imports (for any lifetime).
1120impl<T> IntoWasmAbi for &ScopedClosure<'_, T>
1121where
1122    T: WasmClosure + ?Sized,
1123{
1124    type Abi = u32;
1125
1126    fn into_abi(self) -> u32 {
1127        (&self.js).into_abi()
1128    }
1129}
1130
1131impl<T> OptionIntoWasmAbi for &ScopedClosure<'_, T>
1132where
1133    T: WasmClosure + ?Sized,
1134{
1135    fn none() -> Self::Abi {
1136        0
1137    }
1138}
1139
1140/// `'static` closures can be passed by value to JS, transferring ownership.
1141///
1142/// This is useful for one-shot callbacks where you want JS to own the closure.
1143/// The closure will be cleaned up by JS GC (if weak references are supported)
1144/// or will leak (if weak references are not supported).
1145///
1146/// # Example
1147///
1148/// ```ignore
1149/// #[wasm_bindgen]
1150/// extern "C" {
1151///     fn set_one_shot_callback(cb: Closure<dyn FnMut()>);
1152/// }
1153///
1154/// let cb = Closure::new(|| { /* ... */ });
1155/// set_one_shot_callback(cb);  // Ownership transferred to JS
1156/// // No need to store or forget the closure
1157/// ```
1158impl<T> IntoWasmAbi for ScopedClosure<'static, T>
1159where
1160    T: WasmClosure + ?Sized,
1161{
1162    type Abi = u32;
1163
1164    fn into_abi(self) -> u32 {
1165        let idx = self.js.idx;
1166        mem::forget(self);
1167        idx
1168    }
1169}
1170
1171impl<T> OptionIntoWasmAbi for ScopedClosure<'static, T>
1172where
1173    T: WasmClosure + ?Sized,
1174{
1175    fn none() -> Self::Abi {
1176        0
1177    }
1178}
1179
1180impl<T> WasmDescribe for ImmediateClosure<'_, T>
1181where
1182    T: WasmClosure + ?Sized,
1183{
1184    #[cfg_attr(wasm_bindgen_unstable_test_coverage, coverage(off))]
1185    fn describe() {
1186        // For FnMut closures, wrap with REFMUT so the CLI generates
1187        // a reentrancy guard in JS. For Fn closures, emit bare FUNCTION.
1188        if T::IS_MUT {
1189            inform(REFMUT);
1190        }
1191        T::describe();
1192    }
1193}
1194
1195impl<T> IntoWasmAbi for ImmediateClosure<'_, T>
1196where
1197    T: WasmClosure + ?Sized,
1198{
1199    type Abi = WasmSlice;
1200
1201    fn into_abi(self) -> WasmSlice {
1202        let WasmSlice { ptr, len } = self.data;
1203        let len_with_flag = if self.unwind_safe {
1204            len | 0x80000000
1205        } else {
1206            len
1207        };
1208        WasmSlice {
1209            ptr,
1210            len: len_with_flag,
1211        }
1212    }
1213}
1214
1215impl<T> OptionIntoWasmAbi for ImmediateClosure<'_, T>
1216where
1217    T: WasmClosure + ?Sized,
1218{
1219    fn none() -> WasmSlice {
1220        WasmSlice { ptr: 0, len: 0 }
1221    }
1222}
1223
1224fn _check() {
1225    fn _assert<T: IntoWasmAbi>() {}
1226    // ScopedClosure by reference (any lifetime)
1227    _assert::<&ScopedClosure<dyn Fn()>>();
1228    _assert::<&ScopedClosure<dyn Fn(String)>>();
1229    _assert::<&ScopedClosure<dyn Fn() -> String>>();
1230    _assert::<&ScopedClosure<dyn FnMut()>>();
1231    _assert::<&ScopedClosure<dyn FnMut(String)>>();
1232    _assert::<&ScopedClosure<dyn FnMut() -> String>>();
1233    // ScopedClosure by value (only 'static)
1234    _assert::<ScopedClosure<'static, dyn Fn()>>();
1235    _assert::<ScopedClosure<'static, dyn FnMut()>>();
1236    _assert::<Closure<dyn Fn()>>();
1237    _assert::<Closure<dyn FnMut()>>();
1238    // ImmediateClosure by value
1239    _assert::<ImmediateClosure<dyn Fn()>>();
1240    _assert::<ImmediateClosure<dyn Fn(String)>>();
1241    _assert::<ImmediateClosure<dyn Fn() -> String>>();
1242    _assert::<ImmediateClosure<dyn FnMut()>>();
1243    _assert::<ImmediateClosure<dyn FnMut(String)>>();
1244    _assert::<ImmediateClosure<dyn FnMut() -> String>>();
1245}
1246
1247impl<T> fmt::Debug for ScopedClosure<'_, T>
1248where
1249    T: ?Sized,
1250{
1251    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1252        write!(f, "Closure {{ ... }}")
1253    }
1254}
1255
1256/// An internal trait for the `Closure` type.
1257///
1258/// This trait is not stable and it's not recommended to use this in bounds or
1259/// implement yourself.
1260#[doc(hidden)]
1261pub unsafe trait WasmClosure: WasmDescribe {
1262    const IS_MUT: bool;
1263    /// The mutable version of this closure type.
1264    /// For `dyn Fn(...) -> R` this is `dyn FnMut(...) -> R`.
1265    /// For `dyn FnMut(...) -> R` this is itself.
1266    type AsMut: ?Sized;
1267    fn to_wasm_slice(r: &Self) -> WasmSlice;
1268}
1269
1270unsafe impl<T: WasmClosure> WasmClosure for AssertUnwindSafe<T> {
1271    const IS_MUT: bool = T::IS_MUT;
1272    type AsMut = T::AsMut;
1273    fn to_wasm_slice(r: &Self) -> WasmSlice {
1274        let (ptr, len): (u32, u32) = unsafe { mem::transmute_copy(&r) };
1275        WasmSlice { ptr, len }
1276    }
1277}
1278
1279/// An internal trait for the `Closure` type.
1280///
1281/// This trait is not stable and it's not recommended to use this in bounds or
1282/// implement yourself.
1283#[doc(hidden)]
1284pub trait IntoWasmClosure<T: ?Sized> {
1285    fn unsize(self: Box<Self>) -> Box<T>;
1286}
1287
1288impl<T: ?Sized + WasmClosure> IntoWasmClosure<T> for T {
1289    fn unsize(self: Box<Self>) -> Box<T> {
1290        self
1291    }
1292}
1293
1294/// Trait for converting a reference to a closure into a trait object reference.
1295///
1296/// This trait is not stable and it's not recommended to use this in bounds or
1297/// implement yourself.
1298#[doc(hidden)]
1299pub trait IntoWasmClosureRef<'a, T: ?Sized> {
1300    /// The `'static` version of `T`. For example, if `T` is `dyn Fn() + 'a`,
1301    /// then `Static` is `dyn Fn()` (implicitly `'static`).
1302    type Static: ?Sized + WasmClosure;
1303    type WithLifetime: ?Sized + WasmClosure + 'a;
1304    fn unsize_closure_ref(&self) -> &T;
1305}
1306
1307/// Trait for converting a mutable reference to a closure into a trait object reference.
1308///
1309/// This trait is not stable and it's not recommended to use this in bounds or
1310/// implement yourself.
1311#[doc(hidden)]
1312pub trait IntoWasmClosureRefMut<'a, T: ?Sized> {
1313    /// The `'static` version of `T`. For example, if `T` is `dyn FnMut() + 'a`,
1314    /// then `Static` is `dyn FnMut()` (implicitly `'static`).
1315    type Static: ?Sized + WasmClosure;
1316    type WithLifetime: ?Sized + WasmClosure + 'a;
1317    fn unsize_closure_ref(&mut self) -> &mut T;
1318}
1319
1320// Blanket impl for AssertUnwindSafe - delegates to inner type
1321impl<'a, T: ?Sized, F> IntoWasmClosureRef<'a, T> for AssertUnwindSafe<F>
1322where
1323    F: IntoWasmClosureRef<'a, T>,
1324{
1325    type Static = F::Static;
1326    type WithLifetime = F::WithLifetime;
1327    fn unsize_closure_ref(&self) -> &T {
1328        self.0.unsize_closure_ref()
1329    }
1330}
1331
1332impl<'a, T: ?Sized, F> IntoWasmClosureRefMut<'a, T> for AssertUnwindSafe<F>
1333where
1334    F: IntoWasmClosureRefMut<'a, T>,
1335{
1336    type Static = F::Static;
1337    type WithLifetime = F::WithLifetime;
1338    fn unsize_closure_ref(&mut self) -> &mut T {
1339        self.0.unsize_closure_ref()
1340    }
1341}
1342
1343// In ScopedClosure, the Rust closure type is the phantom type that erases,
1344// unlike ImmedateClosure which is the reverse.
1345unsafe impl<T: ?Sized + WasmClosure> ErasableGeneric for ScopedClosure<'_, T> {
1346    type Repr = ScopedClosure<'static, dyn FnMut()>;
1347}