fix: don't have Rc cycles in DioxusElement or Queries (#3618)
This commit is contained in:
1 parent
d42b1d5146
commit
d8850c7666
3 files changed
+26
-20
No files matched your search
@@ -88,8 +88,7 @@ pub(crate) struct DesktopEvaluator {
|
|||||||
impl DesktopEvaluator {
|
impl DesktopEvaluator {
|
||||||
/// Creates a new evaluator for desktop-based targets.
|
/// Creates a new evaluator for desktop-based targets.
|
||||||
pub fn create(desktop_ctx: DesktopContext, js: String) -> GenerationalBox<Box<dyn Evaluator>> {
|
pub fn create(desktop_ctx: DesktopContext, js: String) -> GenerationalBox<Box<dyn Evaluator>> {
|
||||||
let ctx = desktop_ctx.clone();
|
let query = desktop_ctx.query.new_query(&js, desktop_ctx.clone());
|
||||||
let query = desktop_ctx.query.new_query(&js, ctx);
|
|
||||||
|
|
||||||
// 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.
|
// 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();
|
let owner = UnsyncStorage::owner();
|
||||||
|
|||||||
@@ -1,21 +1,24 @@
|
|||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
use dioxus_core::ElementId;
|
use dioxus_core::ElementId;
|
||||||
use dioxus_html::{
|
use dioxus_html::{
|
||||||
geometry::{PixelsRect, PixelsSize, PixelsVector2D},
|
geometry::{PixelsRect, PixelsSize, PixelsVector2D},
|
||||||
MountedResult, RenderedElementBacking,
|
MountedResult, RenderedElementBacking,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{desktop_context::DesktopContext, query::QueryEngine};
|
use crate::{desktop_context::DesktopContext, query::QueryEngine, WeakDesktopContext};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
/// A mounted element passed to onmounted events
|
/// A mounted element passed to onmounted events
|
||||||
pub struct DesktopElement {
|
pub struct DesktopElement {
|
||||||
id: ElementId,
|
id: ElementId,
|
||||||
webview: DesktopContext,
|
webview: WeakDesktopContext,
|
||||||
query: QueryEngine,
|
query: QueryEngine,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DesktopElement {
|
impl DesktopElement {
|
||||||
pub(crate) fn new(id: ElementId, webview: DesktopContext, query: QueryEngine) -> Self {
|
pub(crate) fn new(id: ElementId, webview: DesktopContext, query: QueryEngine) -> Self {
|
||||||
|
let webview = Rc::downgrade(&webview);
|
||||||
Self { id, webview, query }
|
Self { id, webview, query }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -28,10 +31,13 @@ macro_rules! scripted_getter {
|
|||||||
Box<dyn futures_util::Future<Output = dioxus_html::MountedResult<$output_type>>>,
|
Box<dyn futures_util::Future<Output = dioxus_html::MountedResult<$output_type>>>,
|
||||||
> {
|
> {
|
||||||
let script = format!($script, id = self.id.0);
|
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
|
let fut = self
|
||||||
.query
|
.query
|
||||||
.new_query::<Option<$output_type>>(&script, self.webview.clone())
|
.new_query::<Option<$output_type>>(&script, webview)
|
||||||
.resolve();
|
.resolve();
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
match fut.await {
|
match fut.await {
|
||||||
@@ -80,11 +86,11 @@ impl RenderedElementBacking for DesktopElement {
|
|||||||
self.id.0,
|
self.id.0,
|
||||||
serde_json::to_string(&behavior).expect("Failed to serialize ScrollBehavior")
|
serde_json::to_string(&behavior).expect("Failed to serialize ScrollBehavior")
|
||||||
);
|
);
|
||||||
|
let webview = self
|
||||||
let fut = self
|
.webview
|
||||||
.query
|
.upgrade()
|
||||||
.new_query::<bool>(&script, self.webview.clone())
|
.expect("Webview should be alive if the element is being queried");
|
||||||
.resolve();
|
let fut = self.query.new_query::<bool>(&script, webview).resolve();
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
match fut.await {
|
match fut.await {
|
||||||
Ok(true) => Ok(()),
|
Ok(true) => Ok(()),
|
||||||
@@ -106,11 +112,11 @@ impl RenderedElementBacking for DesktopElement {
|
|||||||
"return window.interpreter.setFocus({}, {});",
|
"return window.interpreter.setFocus({}, {});",
|
||||||
self.id.0, focus
|
self.id.0, focus
|
||||||
);
|
);
|
||||||
|
let webview = self
|
||||||
let fut = self
|
.webview
|
||||||
.query
|
.upgrade()
|
||||||
.new_query::<bool>(&script, self.webview.clone())
|
.expect("Webview should be alive if the element is being queried");
|
||||||
.resolve();
|
let fut = self.query.new_query::<bool>(&script, webview).resolve();
|
||||||
|
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
match fut.await {
|
match fut.await {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use crate::DesktopContext;
|
use crate::{DesktopContext, WeakDesktopContext};
|
||||||
use futures_util::{FutureExt, StreamExt};
|
use futures_util::{FutureExt, StreamExt};
|
||||||
use generational_box::Owner;
|
use generational_box::Owner;
|
||||||
use serde::{de::DeserializeOwned, Deserialize};
|
use serde::{de::DeserializeOwned, Deserialize};
|
||||||
@@ -107,7 +107,7 @@ impl QueryEngine {
|
|||||||
id: request_id,
|
id: request_id,
|
||||||
receiver: rx,
|
receiver: rx,
|
||||||
return_receiver: Some(return_rx),
|
return_receiver: Some(return_rx),
|
||||||
desktop: context,
|
desktop: Rc::downgrade(&context),
|
||||||
phantom: std::marker::PhantomData,
|
phantom: std::marker::PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -140,7 +140,7 @@ impl QueryEngine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct Query<V: DeserializeOwned> {
|
pub(crate) struct Query<V: DeserializeOwned> {
|
||||||
desktop: DesktopContext,
|
desktop: WeakDesktopContext,
|
||||||
receiver: futures_channel::mpsc::UnboundedReceiver<Value>,
|
receiver: futures_channel::mpsc::UnboundedReceiver<Value>,
|
||||||
return_receiver: Option<futures_channel::oneshot::Receiver<Result<Value, String>>>,
|
return_receiver: Option<futures_channel::oneshot::Receiver<Result<Value, String>>>,
|
||||||
pub id: usize,
|
pub id: usize,
|
||||||
@@ -161,7 +161,8 @@ impl<V: DeserializeOwned> Query<V> {
|
|||||||
let data = message.to_string();
|
let data = message.to_string();
|
||||||
let script = format!(r#"window.getQuery({queue_id}).rustSend({data});"#);
|
let script = format!(r#"window.getQuery({queue_id}).rustSend({data});"#);
|
||||||
|
|
||||||
self.desktop
|
let desktop = self.desktop.upgrade().ok_or(QueryError::Finished)?;
|
||||||
|
desktop
|
||||||
.webview
|
.webview
|
||||||
.evaluate_script(&script)
|
.evaluate_script(&script)
|
||||||
.map_err(|e| QueryError::Send(e.to_string()))?;
|
.map_err(|e| QueryError::Send(e.to_string()))?;
|
||||||
|
|||||||
Reference in new issue
Block a user