devela::_dep::web_sys::js_sys::wasm_bindgen::closure

Struct Closure

Source
pub struct Closure<T>
where T: ?Sized,
{ /* private fields */ }
Available on crate feature dep_web_sys only.
Expand description

A handle to both a closure in Rust as well as JS closure which will invoke the Rust closure.

A Closure is the primary way that a 'static lifetime closure is transferred from Rust to JS. Closure currently requires that the closures it’s created with have the 'static lifetime in Rust for soundness reasons.

This type is a “handle” in the sense that whenever it is dropped it will invalidate the JS closure that it refers to. Any usage of the closure in JS after the Closure has been dropped will raise an exception. It’s then up to you to arrange for Closure to be properly deallocate at an appropriate location in your program.

The type parameter on Closure is the type of closure that this represents. Currently this can only be the Fn and FnMut traits with up to 7 arguments (and an optional return value).

§Examples

Here are a number of examples of using Closure.

§Using the setInterval API

Sample usage of Closure to invoke the setInterval API.

use wasm_bindgen::prelude::*;

#[wasm_bindgen]
extern "C" {
    fn setInterval(closure: &Closure<dyn FnMut()>, time: u32) -> i32;
    fn clearInterval(id: i32);

    #[wasm_bindgen(js_namespace = console)]
    fn log(s: &str);
}

#[wasm_bindgen]
pub struct IntervalHandle {
    interval_id: i32,
    _closure: Closure<dyn FnMut()>,
}

impl Drop for IntervalHandle {
    fn drop(&mut self) {
        clearInterval(self.interval_id);
    }
}

#[wasm_bindgen]
pub fn run() -> IntervalHandle {
    // First up we use `Closure::new` to wrap up a Rust closure and create
    // a JS closure.
    let cb = Closure::new(|| {
        log("interval elapsed!");
    });

    // Next we pass this via reference to the `setInterval` function, and
    // `setInterval` gets a handle to the corresponding JS closure.
    let interval_id = setInterval(&cb, 1_000);

    // If we were to drop `cb` here it would cause an exception to be raised
    // whenever the interval elapses. Instead we *return* our handle back to JS
    // so JS can decide when to cancel the interval and deallocate the closure.
    IntervalHandle {
        interval_id,
        _closure: cb,
    }
}

§Casting a Closure to a js_sys::Function

This is the same setInterval example as above, except it is using web_sys (which uses js_sys::Function for callbacks) instead of manually writing bindings to setInterval and other Web APIs.

use wasm_bindgen::JsCast;

#[wasm_bindgen]
pub struct IntervalHandle {
    interval_id: i32,
    _closure: Closure<dyn FnMut()>,
}

impl Drop for IntervalHandle {
    fn drop(&mut self) {
        let window = web_sys::window().unwrap();
        window.clear_interval_with_handle(self.interval_id);
    }
}

#[wasm_bindgen]
pub fn run() -> Result<IntervalHandle, JsValue> {
    let cb = Closure::new(|| {
        web_sys::console::log_1(&"interval elapsed!".into());
    });

    let window = web_sys::window().unwrap();
    let interval_id = window.set_interval_with_callback_and_timeout_and_arguments_0(
        // Note this method call, which uses `as_ref()` to get a `JsValue`
        // from our `Closure` which is then converted to a `&Function`
        // using the `JsCast::unchecked_ref` function.
        cb.as_ref().unchecked_ref(),
        1_000,
    )?;

    // Same as above.
    Ok(IntervalHandle {
        interval_id,
        _closure: cb,
    })
}

§Using FnOnce and Closure::once with requestAnimationFrame

Because requestAnimationFrame only calls its callback once, we can use FnOnce and Closure::once with it.

use wasm_bindgen::prelude::*;

#[wasm_bindgen]
extern "C" {
    fn requestAnimationFrame(closure: &Closure<dyn FnMut()>) -> u32;
    fn cancelAnimationFrame(id: u32);

    #[wasm_bindgen(js_namespace = console)]
    fn log(s: &str);
}

#[wasm_bindgen]
pub struct AnimationFrameHandle {
    animation_id: u32,
    _closure: Closure<dyn FnMut()>,
}

impl Drop for AnimationFrameHandle {
    fn drop(&mut self) {
        cancelAnimationFrame(self.animation_id);
    }
}

// A type that will log a message when it is dropped.
struct LogOnDrop(&'static str);
impl Drop for LogOnDrop {
    fn drop(&mut self) {
        log(self.0);
    }
}

#[wasm_bindgen]
pub fn run() -> AnimationFrameHandle {
    // We are using `Closure::once` which takes a `FnOnce`, so the function
    // can drop and/or move things that it closes over.
    let fired = LogOnDrop("animation frame fired or canceled");
    let cb = Closure::once(move || drop(fired));

    // Schedule the animation frame!
    let animation_id = requestAnimationFrame(&cb);

    // Again, return a handle to JS, so that the closure is not dropped
    // immediately and JS can decide whether to cancel the animation frame.
    AnimationFrameHandle {
        animation_id,
        _closure: cb,
    }
}

§Converting FnOnces directly into JavaScript Functions with Closure::once_into_js

If we don’t want to allow a FnOnce to be eagerly dropped (maybe because we just want it to drop after it is called and don’t care about cancellation) then we can use the Closure::once_into_js function.

This is the same requestAnimationFrame example as above, but without supporting early cancellation.

use wasm_bindgen::prelude::*;

#[wasm_bindgen]
extern "C" {
    // We modify the binding to take an untyped `JsValue` since that is what
    // is returned by `Closure::once_into_js`.
    //
    // If we were using the `web_sys` binding for `requestAnimationFrame`,
    // then the call sites would cast the `JsValue` into a `&js_sys::Function`
    // using `f.unchecked_ref::<js_sys::Function>()`. See the `web_sys`
    // example above for details.
    fn requestAnimationFrame(callback: JsValue);

    #[wasm_bindgen(js_namespace = console)]
    fn log(s: &str);
}

// A type that will log a message when it is dropped.
struct LogOnDrop(&'static str);
impl Drop for LogOnDrop {
    fn drop(&mut self) {
        log(self.0);
    }
}

#[wasm_bindgen]
pub fn run() {
    // We are using `Closure::once_into_js` which takes a `FnOnce` and
    // converts it into a JavaScript function, which is returned as a
    // `JsValue`.
    let fired = LogOnDrop("animation frame fired");
    let cb = Closure::once_into_js(move || drop(fired));

    // Schedule the animation frame!
    requestAnimationFrame(cb);

    // No need to worry about whether or not we drop a `Closure`
    // here or return some sort of handle to JS!
}

Implementations§

Source§

impl<T> Closure<T>
where T: WasmClosure + ?Sized,

Source

pub fn new<F>(t: F) -> Closure<T>
where F: IntoWasmClosure<T> + 'static,

Available on crate feature dep_js_sys only.

Creates a new instance of Closure from the provided Rust function.

Note that the closure provided here, F, has a few requirements associated with it:

  • It must implement Fn or FnMut (for FnOnce functions see Closure::once and Closure::once_into_js).

  • It must be 'static, aka no stack references (use the move keyword).

  • It can have at most 7 arguments.

  • Its arguments and return values are all types that can be shared with JS (i.e. have #[wasm_bindgen] annotations or are simple numbers, etc.)

Source

pub fn wrap(data: Box<T>) -> Closure<T>

Available on crate feature dep_js_sys only.

A more direct version of Closure::new which creates a Closure from a Box<dyn Fn>/Box<dyn FnMut>, which is how it’s kept internally.

Source

pub fn into_js_value(self) -> JsValue

Available on crate feature dep_js_sys only.

Release memory management of this closure from Rust to the JS GC.

When a Closure is dropped it will release the Rust memory and invalidate the associated JS closure, but this isn’t always desired. Some callbacks are alive for the entire duration of the program or for a lifetime dynamically managed by the JS GC. This function can be used to drop this Closure while keeping the associated JS function still valid.

If the platform supports weak references, the Rust memory will be reclaimed when the JS closure is GC’d. If weak references is not supported, this can be dangerous if this function is called many times in an application because the memory leak will overwhelm the page quickly and crash the wasm.

Source

pub fn forget(self)

Available on crate feature dep_js_sys only.

Same as into_js_value, but doesn’t return a value.

Source§

impl Closure<dyn FnOnce()>

Source

pub fn once<F, A, R>( fn_once: F, ) -> Closure<<F as WasmClosureFnOnce<A, R>>::FnMut>
where F: 'static + WasmClosureFnOnce<A, R>,

Available on crate feature dep_js_sys only.

Create a Closure from a function that can only be called once.

Since we have no way of enforcing that JS cannot attempt to call this FnOne(A...) -> R more than once, this produces a Closure<dyn FnMut(A...) -> R> that will dynamically throw a JavaScript error if called more than once.

§Example
use wasm_bindgen::prelude::*;

// Create an non-`Copy`, owned `String`.
let mut s = String::from("Hello");

// Close over `s`. Since `f` returns `s`, it is `FnOnce` and can only be
// called once. If it was called a second time, it wouldn't have any `s`
// to work with anymore!
let f = move || {
    s += ", World!";
    s
};

// Create a `Closure` from `f`. Note that the `Closure`'s type parameter
// is `FnMut`, even though `f` is `FnOnce`.
let closure: Closure<dyn FnMut() -> String> = Closure::once(f);
Source

pub fn once_into_js<F, A, R>(fn_once: F) -> JsValue
where F: 'static + WasmClosureFnOnce<A, R>,

Available on crate feature dep_js_sys only.

Convert a FnOnce(A...) -> R into a JavaScript Function object.

If the JavaScript function is invoked more than once, it will throw an exception.

Unlike Closure::once, this does not return a Closure that can be dropped before the function is invoked to deallocate the closure. The only way the FnOnce is deallocated is by calling the JavaScript function. If the JavaScript function is never called then the FnOnce and everything it closes over will leak.

use wasm_bindgen::{prelude::*, JsCast};

let f = Closure::once_into_js(move || {
    // ...
});

assert!(f.is_instance_of::<js_sys::Function>());

Trait Implementations§

Source§

impl<T> AsRef<JsValue> for Closure<T>
where T: ?Sized,

Source§

fn as_ref(&self) -> &JsValue

Converts this type into a shared reference of the (usually inferred) input type.
Source§

impl<T> Debug for Closure<T>
where T: ?Sized,

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl<T> Drop for Closure<T>
where T: ?Sized,

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

impl<T> IntoWasmAbi for &Closure<T>
where T: WasmClosure + ?Sized,

Source§

type Abi = u32

The Wasm ABI type that this converts into when crossing the ABI boundary.
Source§

fn into_abi(self) -> u32

Convert self into Self::Abi so that it can be sent across the wasm ABI boundary.
Source§

impl<T> OptionIntoWasmAbi for &Closure<T>
where T: WasmClosure + ?Sized,

Source§

fn none() -> <&Closure<T> as IntoWasmAbi>::Abi

Returns an ABI instance indicating “none”, which JS will interpret as the None branch of this option. Read more

Auto Trait Implementations§

§

impl<T> Freeze for Closure<T>
where T: ?Sized,

§

impl<T> RefUnwindSafe for Closure<T>
where T: RefUnwindSafe + ?Sized,

§

impl<T> !Send for Closure<T>

§

impl<T> !Sync for Closure<T>

§

impl<T> Unpin for Closure<T>
where T: ?Sized,

§

impl<T> UnwindSafe for Closure<T>
where T: UnwindSafe + ?Sized,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
§

impl<T> ArchivePointee for T

§

type ArchivedMetadata = ()

The archived version of the pointer metadata for this type.
§

fn pointer_metadata( _: &<T as ArchivePointee>::ArchivedMetadata, ) -> <T as Pointee>::Metadata

Converts some archived metadata to the pointer metadata for itself.
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> ByteSized for T

Source§

const BYTE_ALIGN: usize = _

The alignment of this type in bytes.
Source§

const BYTE_SIZE: usize = _

The size of this type in bytes.
Source§

fn byte_align(&self) -> usize

Returns the alignment of this type in bytes.
Source§

fn byte_size(&self) -> usize

Returns the size of this type in bytes. Read more
Source§

fn ptr_size_ratio(&self) -> [usize; 2]

Returns the size ratio between Ptr::BYTES and BYTE_SIZE. Read more
Source§

impl<T, R> Chain<R> for T
where T: ?Sized,

Source§

fn chain<F>(self, f: F) -> R
where F: FnOnce(Self) -> R, Self: Sized,

Chain a function which takes the parameter by value.
Source§

fn chain_ref<F>(&self, f: F) -> R
where F: FnOnce(&Self) -> R,

Chain a function which takes the parameter by shared reference.
Source§

fn chain_mut<F>(&mut self, f: F) -> R
where F: FnOnce(&mut Self) -> R,

Chain a function which takes the parameter by exclusive reference.
Source§

impl<T> ExtAny for T
where T: Any + ?Sized,

Source§

fn type_id() -> TypeId

Returns the TypeId of Self. Read more
Source§

fn type_of(&self) -> TypeId

Returns the TypeId of self. Read more
Source§

fn type_name(&self) -> &'static str

Returns the type name of self. Read more
Source§

fn type_is<T: 'static>(&self) -> bool

Returns true if Self is of type T. Read more
Source§

fn as_any_ref(&self) -> &dyn Any
where Self: Sized,

Upcasts &self as &dyn Any. Read more
Source§

fn as_any_mut(&mut self) -> &mut dyn Any
where Self: Sized,

Upcasts &mut self as &mut dyn Any. Read more
Source§

fn as_any_box(self: Box<Self>) -> Box<dyn Any>
where Self: Sized,

Upcasts Box<self> as Box<dyn Any>. Read more
Source§

fn downcast_ref<T: 'static>(&self) -> Option<&T>

Available on crate feature unsafe_layout only.
Returns some shared reference to the inner value if it is of type T. Read more
Source§

fn downcast_mut<T: 'static>(&mut self) -> Option<&mut T>

Available on crate feature unsafe_layout only.
Returns some exclusive reference to the inner value if it is of type T. Read more
Source§

impl<T> ExtMem for T
where T: ?Sized,

Source§

const NEEDS_DROP: bool = _

Know whether dropping values of this type matters, in compile-time.
Source§

fn mem_align_of<T>() -> usize

Returns the minimum alignment of the type in bytes. Read more
Source§

fn mem_align_of_val(&self) -> usize

Returns the alignment of the pointed-to value in bytes. Read more
Source§

fn mem_size_of<T>() -> usize

Returns the size of a type in bytes. Read more
Source§

fn mem_size_of_val(&self) -> usize

Returns the size of the pointed-to value in bytes. Read more
Source§

fn mem_copy(&self) -> Self
where Self: Copy,

Bitwise-copies a value. Read more
Source§

fn mem_needs_drop(&self) -> bool

Returns true if dropping values of this type matters. Read more
Source§

fn mem_drop(self)
where Self: Sized,

Drops self by running its destructor. Read more
Source§

fn mem_forget(self)
where Self: Sized,

Forgets about self without running its destructor. Read more
Source§

fn mem_replace(&mut self, other: Self) -> Self
where Self: Sized,

Replaces self with other, returning the previous value of self. Read more
Source§

fn mem_take(&mut self) -> Self
where Self: Default,

Replaces self with its default value, returning the previous value of self. Read more
Source§

fn mem_swap(&mut self, other: &mut Self)
where Self: Sized,

Swaps the value of self and other without deinitializing either one. Read more
Source§

unsafe fn mem_zeroed<T>() -> T

Available on crate feature unsafe_layout only.
Returns the value of type T represented by the all-zero byte-pattern. Read more
Source§

unsafe fn mem_transmute_copy<Src, Dst>(src: &Src) -> Dst

Available on crate feature unsafe_layout only.
Returns the value of type T represented by the all-zero byte-pattern. Read more
Source§

fn mem_as_bytes(&self) -> &[u8]
where Self: Sync + Unpin,

Available on crate feature unsafe_slice only.
View a Sync + Unpin self as &[u8]. Read more
Source§

fn mem_as_bytes_mut(&mut self) -> &mut [u8]
where Self: Sync + Unpin,

Available on crate feature unsafe_slice only.
View a Sync + Unpin self as &mut [u8]. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<S> FromSample<S> for S

§

fn from_sample_(s: S) -> S

Source§

impl<T> Hook for T

Source§

fn hook_ref<F>(self, f: F) -> Self
where F: FnOnce(&Self),

Applies a function which takes the parameter by shared reference, and then returns the (possibly) modified owned value. Read more
Source§

fn hook_mut<F>(self, f: F) -> Self
where F: FnOnce(&mut Self),

Applies a function which takes the parameter by exclusive reference, and then returns the (possibly) modified owned value. Read more
§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
§

impl<F, T> IntoSample<T> for F
where T: FromSample<F>,

§

fn into_sample(self) -> T

§

impl<T> LayoutRaw for T

§

fn layout_raw(_: <T as Pointee>::Metadata) -> Result<Layout, LayoutError>

Returns the layout of the type.
§

impl<T, N1, N2> Niching<NichedOption<T, N1>> for N2
where T: SharedNiching<N1, N2>, N1: Niching<T>, N2: Niching<T>,

§

unsafe fn is_niched(niched: *const NichedOption<T, N1>) -> bool

Returns whether the given value has been niched. Read more
§

fn resolve_niched(out: Place<NichedOption<T, N1>>)

Writes data to out indicating that a T is niched.
§

impl<T> Pointable for T

§

const ALIGN: usize

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
§

impl<T> Pointee for T

§

type Metadata = ()

The metadata type for pointers and references to this type.
§

impl<T, U> ToSample<U> for T
where U: FromSample<T>,

§

fn to_sample_(self) -> U

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
§

impl<S, T> Duplex<S> for T
where T: FromSample<S> + ToSample<S>,