bitwarden_threading/
cancellation_token.rs

1pub use tokio_util::sync::CancellationToken;
2
3#[cfg(target_arch = "wasm32")]
4pub mod wasm {
5    use wasm_bindgen::prelude::*;
6
7    use super::*;
8
9    #[wasm_bindgen]
10    extern "C" {
11        #[wasm_bindgen]
12        #[derive(Clone)]
13        pub type AbortController;
14
15        #[wasm_bindgen(constructor)]
16        pub fn new() -> AbortController;
17
18        #[wasm_bindgen(method, getter)]
19        pub fn signal(this: &AbortController) -> AbortSignal;
20
21        #[wasm_bindgen(method, js_name = abort)]
22        pub fn abort(this: &AbortController, reason: JsValue);
23
24        #[wasm_bindgen]
25        pub type AbortSignal;
26
27        #[wasm_bindgen(method, getter)]
28        pub fn aborted(this: &AbortSignal) -> bool;
29
30        #[wasm_bindgen(method, js_name = addEventListener)]
31        pub fn add_event_listener(
32            this: &AbortSignal,
33            event_type: &str,
34            callback: &Closure<dyn FnMut()>,
35        );
36    }
37
38    pub trait AbortControllerExt {
39        /// Converts an `AbortController` to a `CancellationToken`.
40        /// The signal only travels in one direction: `AbortController` -> `CancellationToken`,
41        /// i.e. the `CancellationToken` will be cancelled when the `AbortController` is aborted
42        /// but not the other way around.
43        fn to_cancellation_token(&self) -> CancellationToken;
44    }
45
46    impl AbortControllerExt for AbortController {
47        fn to_cancellation_token(&self) -> CancellationToken {
48            self.signal().to_cancellation_token()
49        }
50    }
51
52    pub trait AbortSignalExt {
53        /// Converts an `AbortSignal` to a `CancellationToken`.
54        /// The signal only travels in one direction: `AbortSignal` -> `CancellationToken`,
55        /// i.e. the `CancellationToken` will be cancelled when the `AbortSignal` is aborted
56        /// but not the other way around.
57        fn to_cancellation_token(&self) -> CancellationToken;
58    }
59
60    impl AbortSignalExt for AbortSignal {
61        fn to_cancellation_token(&self) -> CancellationToken {
62            let token = CancellationToken::new();
63
64            let token_clone = token.clone();
65            let closure = Closure::new(move || {
66                token_clone.cancel();
67            });
68            self.add_event_listener("abort", &closure);
69            closure.forget(); // Transfer ownership to the JS runtime
70
71            token
72        }
73    }
74}