Compare commits

...

3 Commits
4271 ... 3024

Author SHA1 Message Date
Greg Johnston
565a901c08 undo rename so I don't have to break all the rest 2024-09-26 16:56:48 -04:00
Greg Johnston
f626ac26e0 change: rename leptos::spawn to leptos::task and reexport scoped spawners 2024-09-26 16:25:59 -04:00
Greg Johnston
fb3159d093 fix: properly scope Suspend rebuilds within ownership tree (closes #3024) 2024-09-26 16:14:36 -04:00
6 changed files with 51 additions and 16 deletions

View File

@@ -293,6 +293,10 @@ pub mod spawn {
pub async fn tick() {
Executor::tick().await
}
pub use reactive_graph::{
spawn_local_scoped, spawn_local_scoped_with_cancellation,
};
}
// these reexports are used in islands

View File

@@ -87,6 +87,7 @@ pub mod traits;
pub mod transition;
pub mod wrappers;
use computed::ScopedFuture;
pub use graph::untrack;
#[cfg(feature = "nightly")]
@@ -130,3 +131,36 @@ pub(crate) fn spawn(task: impl Future<Output = ()> + Send + 'static) {
any_spawner::Executor::spawn(task);
}
/// Calls [`Executor::spawn_local`], but ensures that the task runs under the current reactive [`Owner`]
/// and [`Observed`]. Does not cancel the task if the owner is cleaned up.
pub fn spawn_local_scoped(task: impl Future<Output = ()> + 'static) {
let task = ScopedFuture::new(task);
#[cfg(feature = "sandboxed-arenas")]
let task = owner::Sandboxed::new(task);
any_spawner::Executor::spawn_local(task);
}
/// Calls [`Executor::spawn_local`], but ensures that the task runs under the current reactive [`Owner`]
/// and [`Observed`]. Cancels the task if the owner is cleaned up.
pub fn spawn_local_scoped_with_cancellation(
task: impl Future<Output = ()> + 'static,
) {
use crate::owner::on_cleanup;
use futures::future::{AbortHandle, Abortable};
let (abort_handle, abort_registration) = AbortHandle::new_pair();
on_cleanup(move || abort_handle.abort());
let task = Abortable::new(task, abort_registration);
let task = ScopedFuture::new(task);
#[cfg(feature = "sandboxed-arenas")]
let task = owner::Sandboxed::new(task);
any_spawner::Executor::spawn_local(async move {
_ = task.await;
});
}

View File

@@ -1,6 +1,5 @@
use super::{ReactiveFunction, SharedReactiveFunction, Suspend};
use crate::{html::class::IntoClass, renderer::Rndr};
use any_spawner::Executor;
use futures::FutureExt;
use reactive_graph::{effect::RenderEffect, signal::guards::ReadGuard};
use std::{
@@ -738,7 +737,7 @@ where
) -> Self::State {
let el = el.to_owned();
let state = Rc::new(RefCell::new(None));
Executor::spawn_local({
reactive_graph::spawn_local_scoped({
let state = Rc::clone(&state);
async move {
*state.borrow_mut() =
@@ -752,7 +751,7 @@ where
fn build(self, el: &crate::renderer::types::Element) -> Self::State {
let el = el.to_owned();
let state = Rc::new(RefCell::new(None));
Executor::spawn_local({
reactive_graph::spawn_local_scoped({
let state = Rc::clone(&state);
async move {
*state.borrow_mut() = Some(self.inner.await.build(&el));
@@ -763,7 +762,7 @@ where
}
fn rebuild(self, state: &mut Self::State) {
Executor::spawn_local({
reactive_graph::spawn_local_scoped({
let state = Rc::clone(state);
async move {
let value = self.inner.await;

View File

@@ -8,7 +8,6 @@ use crate::{
RenderHtml, ToTemplate,
},
};
use any_spawner::Executor;
use reactive_graph::effect::RenderEffect;
use std::{
cell::RefCell,
@@ -391,7 +390,7 @@ where
let key = key.to_owned();
let el = el.to_owned();
let state = Rc::new(RefCell::new(None));
Executor::spawn_local({
reactive_graph::spawn_local_scoped({
let state = Rc::clone(&state);
async move {
*state.borrow_mut() =
@@ -410,7 +409,7 @@ where
let key = key.to_owned();
let el = el.to_owned();
let state = Rc::new(RefCell::new(None));
Executor::spawn_local({
reactive_graph::spawn_local_scoped({
let state = Rc::clone(&state);
async move {
*state.borrow_mut() = Some(self.inner.await.build(&el, &key));
@@ -422,7 +421,7 @@ where
fn rebuild(self, key: &str, state: &mut Self::State) {
let key = key.to_owned();
Executor::spawn_local({
reactive_graph::spawn_local_scoped({
let state = Rc::clone(state);
async move {
let value = self.inner.await;

View File

@@ -1,6 +1,5 @@
use super::{ReactiveFunction, SharedReactiveFunction, Suspend};
use crate::{html::style::IntoStyle, renderer::Rndr};
use any_spawner::Executor;
use futures::FutureExt;
use reactive_graph::effect::RenderEffect;
use std::{borrow::Cow, cell::RefCell, future::Future, rc::Rc};
@@ -463,7 +462,7 @@ where
) -> Self::State {
let el = el.to_owned();
let state = Rc::new(RefCell::new(None));
Executor::spawn_local({
reactive_graph::spawn_local_scoped({
let state = Rc::clone(&state);
async move {
*state.borrow_mut() =
@@ -477,7 +476,7 @@ where
fn build(self, el: &crate::renderer::types::Element) -> Self::State {
let el = el.to_owned();
let state = Rc::new(RefCell::new(None));
Executor::spawn_local({
reactive_graph::spawn_local_scoped({
let state = Rc::clone(&state);
async move {
*state.borrow_mut() = Some(self.inner.await.build(&el));
@@ -488,7 +487,7 @@ where
}
fn rebuild(self, state: &mut Self::State) {
Executor::spawn_local({
reactive_graph::spawn_local_scoped({
let state = Rc::clone(state);
async move {
let value = self.inner.await;

View File

@@ -192,7 +192,7 @@ where
// spawning immediately means that our now_or_never poll result isn't lost
// if it wasn't pending at first, we don't need to poll the Future again
if initially_pending {
Executor::spawn_local({
reactive_graph::spawn_local_scoped({
let state = Rc::clone(&inner);
async move {
let _guard = error_hook.as_ref().map(|hook| {
@@ -231,7 +231,7 @@ where
let error_hook = use_context::<Arc<dyn ErrorHook>>();
// spawn the future, and rebuild the state when it resolves
Executor::spawn_local({
reactive_graph::spawn_local_scoped({
let state = Rc::clone(&state.inner);
async move {
let _guard = error_hook
@@ -244,7 +244,7 @@ where
// waiting a tick here allows Suspense to remount if necessary, which prevents some
// edge cases in which a rebuild can't happen while unmounted because the DOM node
// has no parent
any_spawner::Executor::tick().await;
Executor::tick().await;
if let Ok(value) = value {
Some(value).rebuild(&mut *state.borrow_mut());
}
@@ -411,7 +411,7 @@ where
// spawning immediately means that our now_or_never poll result isn't lost
// if it wasn't pending at first, we don't need to poll the Future again
if initially_pending {
Executor::spawn_local({
reactive_graph::spawn_local_scoped({
let state = Rc::clone(&inner);
async move {
let _guard = error_hook.as_ref().map(|hook| {