event.rs 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. // Copyright 2019-2021 Tauri Programme within The Commons Conservancy
  2. // SPDX-License-Identifier: Apache-2.0
  3. // SPDX-License-Identifier: MIT
  4. use std::{
  5. boxed::Box,
  6. collections::HashMap,
  7. fmt,
  8. hash::Hash,
  9. sync::{Arc, Mutex},
  10. };
  11. use uuid::Uuid;
  12. /// Represents an event handler.
  13. #[derive(Debug, Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)]
  14. pub struct EventHandler(Uuid);
  15. impl fmt::Display for EventHandler {
  16. fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  17. self.0.fmt(f)
  18. }
  19. }
  20. /// An event that was triggered.
  21. #[derive(Debug, Clone)]
  22. pub struct Event {
  23. id: EventHandler,
  24. data: Option<String>,
  25. }
  26. impl Event {
  27. /// The [`EventHandler`] that was triggered.
  28. pub fn id(&self) -> EventHandler {
  29. self.id
  30. }
  31. /// The event payload.
  32. pub fn payload(&self) -> Option<&str> {
  33. self.data.as_deref()
  34. }
  35. }
  36. /// What to do with the pending handler when resolving it?
  37. enum Pending {
  38. Unlisten(EventHandler),
  39. Listen(EventHandler, String, Handler),
  40. Trigger(String, Option<String>, Option<String>),
  41. }
  42. /// Stored in [`Listeners`] to be called upon when the event that stored it is triggered.
  43. struct Handler {
  44. window: Option<String>,
  45. callback: Box<dyn Fn(Event) + Send>,
  46. }
  47. /// Holds event handlers and pending event handlers, along with the salts associating them.
  48. struct InnerListeners {
  49. handlers: Mutex<HashMap<String, HashMap<EventHandler, Handler>>>,
  50. pending: Mutex<Vec<Pending>>,
  51. function_name: Uuid,
  52. listeners_object_name: Uuid,
  53. queue_object_name: Uuid,
  54. }
  55. /// A self-contained event manager.
  56. pub(crate) struct Listeners {
  57. inner: Arc<InnerListeners>,
  58. }
  59. impl Default for Listeners {
  60. fn default() -> Self {
  61. Self {
  62. inner: Arc::new(InnerListeners {
  63. handlers: Mutex::default(),
  64. pending: Mutex::default(),
  65. function_name: Uuid::new_v4(),
  66. listeners_object_name: Uuid::new_v4(),
  67. queue_object_name: Uuid::new_v4(),
  68. }),
  69. }
  70. }
  71. }
  72. impl Clone for Listeners {
  73. fn clone(&self) -> Self {
  74. Self {
  75. inner: self.inner.clone(),
  76. }
  77. }
  78. }
  79. impl Listeners {
  80. /// Randomly generated function name to represent the JavaScript event function.
  81. pub(crate) fn function_name(&self) -> String {
  82. self.inner.function_name.to_string()
  83. }
  84. /// Randomly generated listener object name to represent the JavaScript event listener object.
  85. pub(crate) fn listeners_object_name(&self) -> String {
  86. self.inner.listeners_object_name.to_string()
  87. }
  88. /// Randomly generated queue object name to represent the JavaScript event queue object.
  89. pub(crate) fn queue_object_name(&self) -> String {
  90. self.inner.queue_object_name.to_string()
  91. }
  92. /// Insert a pending event action to the queue.
  93. fn insert_pending(&self, action: Pending) {
  94. self
  95. .inner
  96. .pending
  97. .lock()
  98. .expect("poisoned pending event queue")
  99. .push(action)
  100. }
  101. /// Finish all pending event actions.
  102. fn flush_pending(&self) {
  103. let pending = {
  104. let mut lock = self
  105. .inner
  106. .pending
  107. .lock()
  108. .expect("poisoned pending event queue");
  109. std::mem::take(&mut *lock)
  110. };
  111. for action in pending {
  112. match action {
  113. Pending::Unlisten(id) => self.unlisten(id),
  114. Pending::Listen(id, event, handler) => self.listen_(id, event, handler),
  115. Pending::Trigger(ref event, window, payload) => self.trigger(event, window, payload),
  116. }
  117. }
  118. }
  119. fn listen_(&self, id: EventHandler, event: String, handler: Handler) {
  120. match self.inner.handlers.try_lock() {
  121. Err(_) => self.insert_pending(Pending::Listen(id, event, handler)),
  122. Ok(mut lock) => {
  123. lock.entry(event).or_default().insert(id, handler);
  124. }
  125. }
  126. }
  127. /// Adds an event listener for JS events.
  128. pub(crate) fn listen<F: Fn(Event) + Send + 'static>(
  129. &self,
  130. event: String,
  131. window: Option<String>,
  132. handler: F,
  133. ) -> EventHandler {
  134. let id = EventHandler(Uuid::new_v4());
  135. let handler = Handler {
  136. window,
  137. callback: Box::new(handler),
  138. };
  139. self.listen_(id, event, handler);
  140. id
  141. }
  142. /// Listen to a JS event and immediately unlisten.
  143. pub(crate) fn once<F: Fn(Event) + Send + 'static>(
  144. &self,
  145. event: String,
  146. window: Option<String>,
  147. handler: F,
  148. ) -> EventHandler {
  149. let self_ = self.clone();
  150. self.listen(event, window, move |event| {
  151. self_.unlisten(event.id);
  152. handler(event);
  153. })
  154. }
  155. /// Removes an event listener.
  156. pub(crate) fn unlisten(&self, handler_id: EventHandler) {
  157. match self.inner.handlers.try_lock() {
  158. Err(_) => self.insert_pending(Pending::Unlisten(handler_id)),
  159. Ok(mut lock) => lock.values_mut().for_each(|handler| {
  160. handler.remove(&handler_id);
  161. }),
  162. }
  163. }
  164. /// Triggers the given global event with its payload.
  165. pub(crate) fn trigger(&self, event: &str, window: Option<String>, payload: Option<String>) {
  166. let mut maybe_pending = false;
  167. match self.inner.handlers.try_lock() {
  168. Err(_) => self.insert_pending(Pending::Trigger(event.to_owned(), window, payload)),
  169. Ok(lock) => {
  170. if let Some(handlers) = lock.get(event) {
  171. for (&id, handler) in handlers {
  172. if handler.window.is_none() || window == handler.window {
  173. maybe_pending = true;
  174. (handler.callback)(self::Event {
  175. id,
  176. data: payload.clone(),
  177. })
  178. }
  179. }
  180. }
  181. }
  182. }
  183. if maybe_pending {
  184. self.flush_pending();
  185. }
  186. }
  187. }
  188. #[cfg(test)]
  189. mod test {
  190. use super::*;
  191. use proptest::prelude::*;
  192. // dummy event handler function
  193. fn event_fn(s: Event) {
  194. println!("{:?}", s);
  195. }
  196. proptest! {
  197. #![proptest_config(ProptestConfig::with_cases(10000))]
  198. // check to see if listen() is properly passing keys into the LISTENERS map
  199. #[test]
  200. fn listeners_check_key(e in "[a-z]+") {
  201. let listeners: Listeners = Default::default();
  202. // clone e as the key
  203. let key = e.clone();
  204. // pass e and an dummy func into listen
  205. listeners.listen(e, None, event_fn);
  206. // lock mutex
  207. let l = listeners.inner.handlers.lock().unwrap();
  208. // check if the generated key is in the map
  209. assert!(l.contains_key(&key));
  210. }
  211. // check to see if listen inputs a handler function properly into the LISTENERS map.
  212. #[test]
  213. fn listeners_check_fn(e in "[a-z]+") {
  214. let listeners: Listeners = Default::default();
  215. // clone e as the key
  216. let key = e.clone();
  217. // pass e and an dummy func into listen
  218. listeners.listen(e, None, event_fn);
  219. // lock mutex
  220. let mut l = listeners.inner.handlers.lock().unwrap();
  221. // check if l contains key
  222. if l.contains_key(&key) {
  223. // grab key if it exists
  224. let handler = l.get_mut(&key);
  225. // check to see if we get back a handler or not
  226. match handler {
  227. // pass on Some(handler)
  228. Some(_) => {},
  229. // Fail on None
  230. None => panic!("handler is None")
  231. }
  232. }
  233. }
  234. // check to see if on_event properly grabs the stored function from listen.
  235. #[test]
  236. fn check_on_event(e in "[a-z]+", d in "[a-z]+") {
  237. let listeners: Listeners = Default::default();
  238. // clone e as the key
  239. let key = e.clone();
  240. // call listen with e and the event_fn dummy func
  241. listeners.listen(e.clone(), None, event_fn);
  242. // call on event with e and d.
  243. listeners.trigger(&e, None, Some(d));
  244. // lock the mutex
  245. let l = listeners.inner.handlers.lock().unwrap();
  246. // assert that the key is contained in the listeners map
  247. assert!(l.contains_key(&key));
  248. }
  249. }
  250. }