Skip to main content

dioxus_js_bindgen/
watcher_guard.rs

1use std::fmt;
2
3/// Unified RAII lifecycle guard for active JavaScript/browser watchers.
4///
5/// Dropping this guard automatically cancels the asynchronous event receiver task
6/// and dispatches a browser-side teardown RPC to unregister the underlying observer
7/// (`disconnect()`, `removeEventListener()`, etc.).
8pub struct WatcherGuard {
9    name: &'static str,
10    sub_id: u64,
11    task: Option<::dioxus::core::Task>,
12    cleaned: bool,
13}
14
15impl WatcherGuard {
16    /// Creates a new `WatcherGuard` with the given diagnostic name, subscription ID, and optional background task.
17    pub fn new(name: &'static str, sub_id: u64, task: Option<::dioxus::core::Task>) -> Self {
18        Self {
19            name,
20            sub_id,
21            task,
22            cleaned: false,
23        }
24    }
25
26    /// Returns the static diagnostic name of the watcher (e.g. `"watch_resize"`).
27    pub fn name(&self) -> &'static str {
28        self.name
29    }
30
31    /// Returns the unique subscription ID assigned to this watcher.
32    pub fn subscription_id(&self) -> u64 {
33        self.sub_id
34    }
35
36    /// Manually consumes and stops the watcher, immediately running teardown.
37    pub fn stop(mut self) {
38        self.cleanup();
39    }
40
41    fn cleanup(&mut self) {
42        if self.cleaned {
43            return;
44        }
45        self.cleaned = true;
46
47        if let Some(task) = self.task.take() {
48            if ::dioxus::core::Runtime::try_current().is_some() {
49                let _ = ::std::panic::catch_unwind(::std::panic::AssertUnwindSafe(|| {
50                    task.cancel();
51                }));
52            }
53        }
54
55        crate::internal::dispatch_cleanup(self.sub_id);
56    }
57}
58
59impl Drop for WatcherGuard {
60    fn drop(&mut self) {
61        self.cleanup();
62    }
63}
64
65impl fmt::Debug for WatcherGuard {
66    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
67        f.debug_struct("WatcherGuard")
68            .field("name", &self.name)
69            .field("sub_id", &self.sub_id)
70            .finish()
71    }
72}