chore: remove pub field in Suspend so that Suspend::new() must be used

This commit is contained in:
Greg Johnston 2024-07-21 09:28:17 -04:00
parent a1ca8549a1
commit 4fe7fe725f
4 changed files with 69 additions and 28 deletions

View file

@ -710,7 +710,7 @@ where
}
fn to_html(self, style: &mut String) {
if let Some(inner) = self.0.now_or_never() {
if let Some(inner) = self.now_or_never() {
inner.to_html(style);
} else {
panic!("You cannot use Suspend on an attribute outside Suspense");
@ -727,7 +727,7 @@ where
let state = Rc::clone(&state);
async move {
*state.borrow_mut() =
Some(self.0.await.hydrate::<FROM_SERVER>(&el));
Some(self.await.hydrate::<FROM_SERVER>(&el));
}
});
state
@ -739,7 +739,7 @@ where
Executor::spawn_local({
let state = Rc::clone(&state);
async move {
*state.borrow_mut() = Some(self.0.await.build(&el));
*state.borrow_mut() = Some(self.await.build(&el));
}
});
state
@ -749,7 +749,7 @@ where
Executor::spawn_local({
let state = Rc::clone(state);
async move {
let value = self.0.await;
let value = self.await;
let mut state = state.borrow_mut();
if let Some(state) = state.as_mut() {
value.rebuild(state);
@ -769,6 +769,6 @@ where
fn dry_resolve(&mut self) {}
async fn resolve(self) -> Self::AsyncOutput {
self.0.await
self.await
}
}

View file

@ -388,7 +388,7 @@ where
let state = Rc::clone(&state);
async move {
*state.borrow_mut() =
Some(self.0.await.hydrate::<FROM_SERVER>(&key, &el));
Some(self.await.hydrate::<FROM_SERVER>(&key, &el));
}
});
state
@ -401,7 +401,7 @@ where
Executor::spawn_local({
let state = Rc::clone(&state);
async move {
*state.borrow_mut() = Some(self.0.await.build(&el, &key));
*state.borrow_mut() = Some(self.await.build(&el, &key));
}
});
state
@ -412,7 +412,7 @@ where
Executor::spawn_local({
let state = Rc::clone(state);
async move {
let value = self.0.await;
let value = self.await;
let mut state = state.borrow_mut();
if let Some(state) = state.as_mut() {
value.rebuild(&key, state);
@ -434,7 +434,7 @@ where
fn dry_resolve(&mut self) {}
async fn resolve(self) -> Self::AsyncOutput {
self.0.await
self.await
}
}

View file

@ -438,7 +438,7 @@ where
type CloneableOwned = Self;
fn to_html(self, style: &mut String) {
if let Some(inner) = self.0.now_or_never() {
if let Some(inner) = self.now_or_never() {
inner.to_html(style);
} else {
panic!("You cannot use Suspend on an attribute outside Suspense");
@ -455,7 +455,7 @@ where
let state = Rc::clone(&state);
async move {
*state.borrow_mut() =
Some(self.0.await.hydrate::<FROM_SERVER>(&el));
Some(self.await.hydrate::<FROM_SERVER>(&el));
}
});
state
@ -467,7 +467,7 @@ where
Executor::spawn_local({
let state = Rc::clone(&state);
async move {
*state.borrow_mut() = Some(self.0.await.build(&el));
*state.borrow_mut() = Some(self.await.build(&el));
}
});
state
@ -477,7 +477,7 @@ where
Executor::spawn_local({
let state = Rc::clone(state);
async move {
let value = self.0.await;
let value = self.await;
let mut state = state.borrow_mut();
if let Some(state) = state.as_mut() {
value.rebuild(state);
@ -497,6 +497,6 @@ where
fn dry_resolve(&mut self) {}
async fn resolve(self) -> Self::AsyncOutput {
self.0.await
self.await
}
}

View file

@ -10,6 +10,7 @@ use crate::{
};
use any_spawner::Executor;
use futures::{select, FutureExt};
use pin_project_lite::pin_project;
use reactive_graph::{
computed::{
suspense::{LocalResourceNotifier, SuspenseContext},
@ -17,16 +18,54 @@ use reactive_graph::{
},
owner::{provide_context, use_context},
};
use std::{cell::RefCell, fmt::Debug, future::Future, pin::Pin, rc::Rc};
use std::{
cell::RefCell,
fmt::Debug,
future::Future,
pin::Pin,
rc::Rc,
task::{Context, Poll},
};
/// A suspended `Future`, which can be used in the view.
#[derive(Clone)]
pub struct Suspend<Fut>(pub ScopedFuture<Fut>); // TODO probably shouldn't be pub
pin_project! {
/// A suspended `Future`, which can be used in the view.
#[derive(Clone)]
pub struct Suspend<Fut> {
#[pin]
inner: ScopedFuture<Fut>
}
}
impl<Fut> Suspend<Fut> {
/// Creates a new suspended view.
pub fn new(fut: Fut) -> Self {
Self(ScopedFuture::new(fut))
Self {
inner: ScopedFuture::new(fut),
}
}
}
impl<Fut> Future for Suspend<Fut>
where
Fut: Future,
{
type Output = Fut::Output;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let this = self.project();
this.inner.poll(cx)
}
}
impl<Fut> From<ScopedFuture<Fut>> for Suspend<Fut> {
fn from(inner: ScopedFuture<Fut>) -> Self {
Self { inner }
}
}
impl<Fut> From<Suspend<Fut>> for ScopedFuture<Fut> {
fn from(value: Suspend<Fut>) -> Self {
value.inner
}
}
@ -76,7 +115,7 @@ where
// poll the future once immediately
// if it's already available, start in the ready state
// otherwise, start with the fallback
let mut fut = Box::pin(self.0);
let mut fut = Box::pin(self);
let initial = fut.as_mut().now_or_never();
let initially_pending = initial.is_none();
let inner = Rc::new(RefCell::new(initial.build()));
@ -103,7 +142,7 @@ where
fn rebuild(self, state: &mut Self::State) {
// get a unique ID if there's a SuspenseContext
let fut = self.0;
let fut = self;
let id = use_context::<SuspenseContext>().map(|sc| sc.task_id());
// spawn the future, and rebuild the state when it resolves
@ -148,14 +187,16 @@ where
owner,
observer,
fut,
} = self.0;
Suspend(ScopedFuture {
} = self.into();
Suspend::from(ScopedFuture {
owner,
observer,
fut: Box::pin(async move {
let this = fut.await;
this.add_any_attr(attr)
}),
}) as Pin<Box<dyn Future<
Output = <<Fut as Future>::Output as AddAnyAttr<Rndr>>::Output<<NewAttr as Attribute<Rndr>>::CloneableOwned>> + Send + 'static
>>
})
}
}
@ -180,7 +221,7 @@ where
// TODO wrap this with a Suspense as needed
// currently this is just used for Routes, which creates a Suspend but never actually needs
// it (because we don't lazy-load routes on the server)
if let Some(inner) = self.0.now_or_never() {
if let Some(inner) = self.now_or_never() {
inner.to_html_with_buf(buf, position, escape, mark_branches);
}
}
@ -194,7 +235,7 @@ where
) where
Self: Sized,
{
let mut fut = Box::pin(self.0);
let mut fut = Box::pin(self);
match fut.as_mut().now_or_never() {
Some(inner) => inner.to_html_async_with_buf::<OUT_OF_ORDER>(
buf,
@ -262,7 +303,7 @@ where
// poll the future once immediately
// if it's already available, start in the ready state
// otherwise, start with the fallback
let mut fut = Box::pin(self.0);
let mut fut = Box::pin(self);
let initial = fut.as_mut().now_or_never();
let initially_pending = initial.is_none();
let inner = Rc::new(RefCell::new(
@ -290,7 +331,7 @@ where
}
async fn resolve(self) -> Self::AsyncOutput {
Some(self.0.await)
Some(self.await)
}
fn dry_resolve(&mut self) {}