feat: standardize ScopedFuture::new_untracked like untrack() and untrack_with_diagnostics() (#4269)

This commit is contained in:
zakstucke
2025-08-31 19:30:16 +03:00
committed by GitHub
parent 06573cbca1
commit f3a053f99b
3 changed files with 55 additions and 11 deletions

View File

@@ -1,6 +1,7 @@
use crate::{
computed::{ArcMemo, Memo, ScopedFuture},
diagnostics::is_suppressing_resource_load,
graph::untrack,
owner::{ArcStoredValue, ArenaItem, Owner},
send_wrapper_ext::SendOption,
signal::{ArcMappedSignal, ArcRwSignal, MappedSignal, RwSignal},
@@ -207,10 +208,9 @@ where
version: Default::default(),
dispatched: Default::default(),
action_fn: Arc::new(move |input| {
Box::pin(
owner
.with(|| ScopedFuture::new_untracked(action_fn(input))),
)
Box::pin(owner.with(|| {
ScopedFuture::new_untracked(untrack(|| action_fn(input)))
}))
}),
#[cfg(any(debug_assertions, leptos_debuginfo))]
defined_at: Location::caller(),
@@ -385,10 +385,9 @@ where
version: Default::default(),
dispatched: Default::default(),
action_fn: Arc::new(move |input| {
Box::pin(SendWrapper::new(
owner
.with(|| ScopedFuture::new_untracked(action_fn(input))),
))
Box::pin(SendWrapper::new(owner.with(|| {
ScopedFuture::new_untracked(untrack(|| action_fn(input)))
})))
}),
#[cfg(any(debug_assertions, leptos_debuginfo))]
defined_at: Location::caller(),

View File

@@ -521,9 +521,10 @@ impl<T: 'static> ArcAsyncDerived<T> {
{
let fun = move || {
let fut = fun();
let fut = ScopedFuture::new_untracked(async move {
SendOption::new(Some(fut.await))
});
let fut =
ScopedFuture::new_untracked_with_diagnostics(async move {
SendOption::new(Some(fut.await))
});
#[cfg(feature = "sandboxed-arenas")]
let fut = Sandboxed::new(fut);
fut

View File

@@ -54,11 +54,55 @@ impl<Fut> ScopedFuture<Fut> {
fut,
}
}
#[doc(hidden)]
#[track_caller]
pub fn new_untracked_with_diagnostics(
fut: Fut,
) -> ScopedFutureUntrackedWithDiagnostics<Fut> {
let owner = Owner::current().unwrap_or_default();
ScopedFutureUntrackedWithDiagnostics {
owner,
observer: None,
fut,
}
}
}
impl<Fut: Future> Future for ScopedFuture<Fut> {
type Output = Fut::Output;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let this = self.project();
this.owner.with(|| {
#[cfg(debug_assertions)]
let _maybe_guard = if this.observer.is_none() {
Some(crate::diagnostics::SpecialNonReactiveZone::enter())
} else {
None
};
this.observer.with_observer(|| this.fut.poll(cx))
})
}
}
pin_project! {
/// A [`Future`] wrapper that sets the [`Owner`] and [`Observer`] before polling the inner
/// `Future`, output of [`ScopedFuture::new_untracked_with_diagnostics`].
///
/// In leptos 0.9 this will be replaced with `ScopedFuture` itself.
#[derive(Clone)]
pub struct ScopedFutureUntrackedWithDiagnostics<Fut> {
owner: Owner,
observer: Option<AnySubscriber>,
#[pin]
fut: Fut,
}
}
impl<Fut: Future> Future for ScopedFutureUntrackedWithDiagnostics<Fut> {
type Output = Fut::Output;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let this = self.project();
this.owner