diff --git a/packages/desktop/src/document.rs b/packages/desktop/src/document.rs index b5c46ed67..813623de9 100644 --- a/packages/desktop/src/document.rs +++ b/packages/desktop/src/document.rs @@ -88,8 +88,7 @@ pub(crate) struct DesktopEvaluator { impl DesktopEvaluator { /// Creates a new evaluator for desktop-based targets. pub fn create(desktop_ctx: DesktopContext, js: String) -> GenerationalBox> { - let ctx = desktop_ctx.clone(); - let query = desktop_ctx.query.new_query(&js, ctx); + let query = desktop_ctx.query.new_query(&js, desktop_ctx.clone()); // We create a generational box that is owned by the query slot so that when we drop the query slot, the generational box is also dropped. let owner = UnsyncStorage::owner(); diff --git a/packages/desktop/src/element.rs b/packages/desktop/src/element.rs index 505b45c43..296f89bf7 100644 --- a/packages/desktop/src/element.rs +++ b/packages/desktop/src/element.rs @@ -1,21 +1,24 @@ +use std::rc::Rc; + use dioxus_core::ElementId; use dioxus_html::{ geometry::{PixelsRect, PixelsSize, PixelsVector2D}, MountedResult, RenderedElementBacking, }; -use crate::{desktop_context::DesktopContext, query::QueryEngine}; +use crate::{desktop_context::DesktopContext, query::QueryEngine, WeakDesktopContext}; #[derive(Clone)] /// A mounted element passed to onmounted events pub struct DesktopElement { id: ElementId, - webview: DesktopContext, + webview: WeakDesktopContext, query: QueryEngine, } impl DesktopElement { pub(crate) fn new(id: ElementId, webview: DesktopContext, query: QueryEngine) -> Self { + let webview = Rc::downgrade(&webview); Self { id, webview, query } } } @@ -28,10 +31,13 @@ macro_rules! scripted_getter { Box>>, > { let script = format!($script, id = self.id.0); - + let webview = self + .webview + .upgrade() + .expect("Webview should be alive if the element is being queried"); let fut = self .query - .new_query::>(&script, self.webview.clone()) + .new_query::>(&script, webview) .resolve(); Box::pin(async move { match fut.await { @@ -80,11 +86,11 @@ impl RenderedElementBacking for DesktopElement { self.id.0, serde_json::to_string(&behavior).expect("Failed to serialize ScrollBehavior") ); - - let fut = self - .query - .new_query::(&script, self.webview.clone()) - .resolve(); + let webview = self + .webview + .upgrade() + .expect("Webview should be alive if the element is being queried"); + let fut = self.query.new_query::(&script, webview).resolve(); Box::pin(async move { match fut.await { Ok(true) => Ok(()), @@ -106,11 +112,11 @@ impl RenderedElementBacking for DesktopElement { "return window.interpreter.setFocus({}, {});", self.id.0, focus ); - - let fut = self - .query - .new_query::(&script, self.webview.clone()) - .resolve(); + let webview = self + .webview + .upgrade() + .expect("Webview should be alive if the element is being queried"); + let fut = self.query.new_query::(&script, webview).resolve(); Box::pin(async move { match fut.await { diff --git a/packages/desktop/src/query.rs b/packages/desktop/src/query.rs index 15d625380..8f7267ae5 100644 --- a/packages/desktop/src/query.rs +++ b/packages/desktop/src/query.rs @@ -1,4 +1,4 @@ -use crate::DesktopContext; +use crate::{DesktopContext, WeakDesktopContext}; use futures_util::{FutureExt, StreamExt}; use generational_box::Owner; use serde::{de::DeserializeOwned, Deserialize}; @@ -107,7 +107,7 @@ impl QueryEngine { id: request_id, receiver: rx, return_receiver: Some(return_rx), - desktop: context, + desktop: Rc::downgrade(&context), phantom: std::marker::PhantomData, } } @@ -140,7 +140,7 @@ impl QueryEngine { } pub(crate) struct Query { - desktop: DesktopContext, + desktop: WeakDesktopContext, receiver: futures_channel::mpsc::UnboundedReceiver, return_receiver: Option>>, pub id: usize, @@ -161,7 +161,8 @@ impl Query { let data = message.to_string(); let script = format!(r#"window.getQuery({queue_id}).rustSend({data});"#); - self.desktop + let desktop = self.desktop.upgrade().ok_or(QueryError::Finished)?; + desktop .webview .evaluate_script(&script) .map_err(|e| QueryError::Send(e.to_string()))?;