浏览代码

fix(core): Send+Sync for Window, closes #3135 (#3140)

Lucas Fernandes Nogueira 3 年之前
父节点
当前提交
e784ebca9f
共有 4 个文件被更改,包括 49 次插入2 次删除
  1. 19 2
      core/tauri-runtime-wry/src/lib.rs
  2. 18 0
      core/tauri/src/app.rs
  3. 3 0
      core/tauri/src/lib.rs
  4. 9 0
      core/tauri/src/window.rs

+ 19 - 2
core/tauri-runtime-wry/src/lib.rs

@@ -175,7 +175,7 @@ struct DispatcherMainThreadContext {
   tray_context: TrayContext,
 }
 
-// the main thread context is only used on the main thread
+// SAFETY: we ensure this type is only used on the main thread.
 #[allow(clippy::non_send_fields_in_send_ty)]
 unsafe impl Send for DispatcherMainThreadContext {}
 
@@ -376,6 +376,7 @@ impl From<NativeImage> for NativeImageWrapper {
 #[derive(Debug, Clone)]
 pub struct GlobalShortcutWrapper(GlobalShortcut);
 
+// SAFETY: usage outside of main thread is guarded, we use the event loop on such cases.
 #[allow(clippy::non_send_fields_in_send_ty)]
 unsafe impl Send for GlobalShortcutWrapper {}
 
@@ -387,6 +388,10 @@ pub struct GlobalShortcutManagerHandle {
   listeners: GlobalShortcutListeners,
 }
 
+// SAFETY: this is safe since the `Context` usage is guarded on `send_user_message`.
+#[allow(clippy::non_send_fields_in_send_ty)]
+unsafe impl Sync for GlobalShortcutManagerHandle {}
+
 impl fmt::Debug for GlobalShortcutManagerHandle {
   fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     f.debug_struct("GlobalShortcutManagerHandle")
@@ -460,6 +465,10 @@ pub struct ClipboardManagerWrapper {
   context: Context,
 }
 
+// SAFETY: this is safe since the `Context` usage is guarded on `send_user_message`.
+#[allow(clippy::non_send_fields_in_send_ty)]
+unsafe impl Sync for ClipboardManagerWrapper {}
+
 impl ClipboardManager for ClipboardManagerWrapper {
   fn read_text(&self) -> Result<Option<String>> {
     let (tx, rx) = channel();
@@ -695,7 +704,7 @@ pub struct WindowBuilderWrapper {
   menu: Option<Menu>,
 }
 
-// safe since `menu_items` are read only here
+// SAFETY: this type is `Send` since `menu_items` are read only here
 #[allow(clippy::non_send_fields_in_send_ty)]
 unsafe impl Send for WindowBuilderWrapper {}
 
@@ -1053,6 +1062,10 @@ pub struct WryDispatcher {
   context: Context,
 }
 
+// SAFETY: this is safe since the `Context` usage is guarded on `send_user_message`.
+#[allow(clippy::non_send_fields_in_send_ty)]
+unsafe impl Sync for WryDispatcher {}
+
 impl Dispatch for WryDispatcher {
   type Runtime = Wry;
   type WindowBuilder = WindowBuilderWrapper;
@@ -1486,6 +1499,10 @@ pub struct WryHandle {
   context: Context,
 }
 
+// SAFETY: this is safe since the `Context` usage is guarded on `send_user_message`.
+#[allow(clippy::non_send_fields_in_send_ty)]
+unsafe impl Sync for WryHandle {}
+
 impl WryHandle {
   /// Creates a new tao window using a callback, and returns its window id.
   pub fn create_tao_window<F: FnOnce() -> (String, WryWindowBuilder) + Send + 'static>(

+ 18 - 0
core/tauri/src/app.rs

@@ -1147,3 +1147,21 @@ impl Default for Builder<crate::Wry> {
     Self::new()
   }
 }
+
+#[cfg(test)]
+mod tests {
+  #[test]
+  fn is_send_sync() {
+    crate::test::assert_send::<super::AppHandle>();
+    crate::test::assert_sync::<super::AppHandle>();
+
+    #[cfg(feature = "wry")]
+    {
+      crate::test::assert_send::<super::AssetResolver<crate::Wry>>();
+      crate::test::assert_sync::<super::AssetResolver<crate::Wry>>();
+    }
+
+    crate::test::assert_send::<super::PathResolver>();
+    crate::test::assert_sync::<super::PathResolver>();
+  }
+}

+ 3 - 0
core/tauri/src/lib.rs

@@ -392,6 +392,9 @@ pub(crate) mod sealed {
 mod test {
   use proptest::prelude::*;
 
+  pub fn assert_send<T: Send>() {}
+  pub fn assert_sync<T: Sync>() {}
+
   proptest! {
     #![proptest_config(ProptestConfig::with_cases(10000))]
     #[test]

+ 9 - 0
core/tauri/src/window.rs

@@ -713,3 +713,12 @@ impl<R: Runtime> Window<R> {
     self.window.dispatcher.start_dragging().map_err(Into::into)
   }
 }
+
+#[cfg(test)]
+mod tests {
+  #[test]
+  fn window_is_send_sync() {
+    crate::test::assert_send::<super::Window>();
+    crate::test::assert_sync::<super::Window>();
+  }
+}