Skip to content

Commit d8850c7

Browse files
authored
fix: don't have Rc cycles in DioxusElement or Queries (#3618)
1 parent d42b1d5 commit d8850c7

File tree

3 files changed

+26
-20
lines changed

3 files changed

+26
-20
lines changed

packages/desktop/src/document.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,7 @@ pub(crate) struct DesktopEvaluator {
8888
impl DesktopEvaluator {
8989
/// Creates a new evaluator for desktop-based targets.
9090
pub fn create(desktop_ctx: DesktopContext, js: String) -> GenerationalBox<Box<dyn Evaluator>> {
91-
let ctx = desktop_ctx.clone();
92-
let query = desktop_ctx.query.new_query(&js, ctx);
91+
let query = desktop_ctx.query.new_query(&js, desktop_ctx.clone());
9392

9493
// 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.
9594
let owner = UnsyncStorage::owner();

packages/desktop/src/element.rs

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,24 @@
1+
use std::rc::Rc;
2+
13
use dioxus_core::ElementId;
24
use dioxus_html::{
35
geometry::{PixelsRect, PixelsSize, PixelsVector2D},
46
MountedResult, RenderedElementBacking,
57
};
68

7-
use crate::{desktop_context::DesktopContext, query::QueryEngine};
9+
use crate::{desktop_context::DesktopContext, query::QueryEngine, WeakDesktopContext};
810

911
#[derive(Clone)]
1012
/// A mounted element passed to onmounted events
1113
pub struct DesktopElement {
1214
id: ElementId,
13-
webview: DesktopContext,
15+
webview: WeakDesktopContext,
1416
query: QueryEngine,
1517
}
1618

1719
impl DesktopElement {
1820
pub(crate) fn new(id: ElementId, webview: DesktopContext, query: QueryEngine) -> Self {
21+
let webview = Rc::downgrade(&webview);
1922
Self { id, webview, query }
2023
}
2124
}
@@ -28,10 +31,13 @@ macro_rules! scripted_getter {
2831
Box<dyn futures_util::Future<Output = dioxus_html::MountedResult<$output_type>>>,
2932
> {
3033
let script = format!($script, id = self.id.0);
31-
34+
let webview = self
35+
.webview
36+
.upgrade()
37+
.expect("Webview should be alive if the element is being queried");
3238
let fut = self
3339
.query
34-
.new_query::<Option<$output_type>>(&script, self.webview.clone())
40+
.new_query::<Option<$output_type>>(&script, webview)
3541
.resolve();
3642
Box::pin(async move {
3743
match fut.await {
@@ -80,11 +86,11 @@ impl RenderedElementBacking for DesktopElement {
8086
self.id.0,
8187
serde_json::to_string(&behavior).expect("Failed to serialize ScrollBehavior")
8288
);
83-
84-
let fut = self
85-
.query
86-
.new_query::<bool>(&script, self.webview.clone())
87-
.resolve();
89+
let webview = self
90+
.webview
91+
.upgrade()
92+
.expect("Webview should be alive if the element is being queried");
93+
let fut = self.query.new_query::<bool>(&script, webview).resolve();
8894
Box::pin(async move {
8995
match fut.await {
9096
Ok(true) => Ok(()),
@@ -106,11 +112,11 @@ impl RenderedElementBacking for DesktopElement {
106112
"return window.interpreter.setFocus({}, {});",
107113
self.id.0, focus
108114
);
109-
110-
let fut = self
111-
.query
112-
.new_query::<bool>(&script, self.webview.clone())
113-
.resolve();
115+
let webview = self
116+
.webview
117+
.upgrade()
118+
.expect("Webview should be alive if the element is being queried");
119+
let fut = self.query.new_query::<bool>(&script, webview).resolve();
114120

115121
Box::pin(async move {
116122
match fut.await {

packages/desktop/src/query.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::DesktopContext;
1+
use crate::{DesktopContext, WeakDesktopContext};
22
use futures_util::{FutureExt, StreamExt};
33
use generational_box::Owner;
44
use serde::{de::DeserializeOwned, Deserialize};
@@ -107,7 +107,7 @@ impl QueryEngine {
107107
id: request_id,
108108
receiver: rx,
109109
return_receiver: Some(return_rx),
110-
desktop: context,
110+
desktop: Rc::downgrade(&context),
111111
phantom: std::marker::PhantomData,
112112
}
113113
}
@@ -140,7 +140,7 @@ impl QueryEngine {
140140
}
141141

142142
pub(crate) struct Query<V: DeserializeOwned> {
143-
desktop: DesktopContext,
143+
desktop: WeakDesktopContext,
144144
receiver: futures_channel::mpsc::UnboundedReceiver<Value>,
145145
return_receiver: Option<futures_channel::oneshot::Receiver<Result<Value, String>>>,
146146
pub id: usize,
@@ -161,7 +161,8 @@ impl<V: DeserializeOwned> Query<V> {
161161
let data = message.to_string();
162162
let script = format!(r#"window.getQuery({queue_id}).rustSend({data});"#);
163163

164-
self.desktop
164+
let desktop = self.desktop.upgrade().ok_or(QueryError::Finished)?;
165+
desktop
165166
.webview
166167
.evaluate_script(&script)
167168
.map_err(|e| QueryError::Send(e.to_string()))?;

0 commit comments

Comments
 (0)