Revert "fix: constrain reactive rendering to Fn(), because using dry_resolve() for Suspense requires idempotent render functions so that they can be called once (to register resources) and called a second time to resolve"

This reverts commit 7ec5c77ba3e8f45bae04a7661a56741f95125adb.
This commit is contained in:
Greg Johnston 2024-06-14 15:16:42 -04:00
parent 96c956efdf
commit 36272a0b1b
30 changed files with 102 additions and 88 deletions

View File

@ -53,7 +53,7 @@ impl<T: IntoView> RenderHtml<Dom> for View<T> {
self.0.resolve().await
}
fn dry_resolve(&self) {
fn dry_resolve(&mut self) {
self.0.dry_resolve();
}

View File

@ -169,7 +169,7 @@ mod view_implementations {
R: Renderer,
{
type Output<SomeNewAttr: Attribute<R>> = Box<
dyn Fn() -> Suspend<
dyn FnMut() -> Suspend<
Pin<
Box<
dyn Future<
@ -203,7 +203,7 @@ mod view_implementations {
const MIN_LENGTH: usize = 0;
fn dry_resolve(&self) {
fn dry_resolve(&mut self) {
self.read();
}

View File

@ -126,7 +126,7 @@ impl RenderHtml<Dom> for BodyView {
const MIN_LENGTH: usize = 0;
fn dry_resolve(&self) {}
fn dry_resolve(&mut self) {}
async fn resolve(self) -> Self::AsyncOutput {
self

View File

@ -139,7 +139,7 @@ impl RenderHtml<Dom> for HtmlView {
const MIN_LENGTH: usize = 0;
fn dry_resolve(&self) {}
fn dry_resolve(&mut self) {}
async fn resolve(self) -> Self::AsyncOutput {
self

View File

@ -383,7 +383,7 @@ where
const MIN_LENGTH: usize = 0;
fn dry_resolve(&self) {
fn dry_resolve(&mut self) {
self.el.dry_resolve()
}
@ -488,7 +488,7 @@ impl RenderHtml<Dom> for MetaTagsView {
const MIN_LENGTH: usize = 0;
fn dry_resolve(&self) {}
fn dry_resolve(&mut self) {}
async fn resolve(self) -> Self::AsyncOutput {
self

View File

@ -239,7 +239,7 @@ impl RenderHtml<Dom> for TitleView {
const MIN_LENGTH: usize = 0;
fn dry_resolve(&self) {}
fn dry_resolve(&mut self) {}
async fn resolve(self) -> Self::AsyncOutput {
self

View File

@ -476,7 +476,7 @@ where
<Defs::Match as MatchInterface<R>>::View,
> as RenderHtml<R>>::MIN_LENGTH;
fn dry_resolve(&self) {}
fn dry_resolve(&mut self) {}
async fn resolve(self) -> Self::AsyncOutput {
self

View File

@ -230,7 +230,7 @@ where
const MIN_LENGTH: usize = 0; // TODO
fn dry_resolve(&self) {}
fn dry_resolve(&mut self) {}
async fn resolve(self) -> Self::AsyncOutput {
self

View File

@ -224,7 +224,7 @@ where
+ E::TAG.len()
};
fn dry_resolve(&self) {
fn dry_resolve(&mut self) {
self.children.dry_resolve()
}

View File

@ -100,7 +100,7 @@ where
+ "data-component".len()
+ View::MIN_LENGTH;
fn dry_resolve(&self) {
fn dry_resolve(&mut self) {
self.view.dry_resolve()
}
@ -219,7 +219,7 @@ where
+ "</>".len()
+ View::MIN_LENGTH;
fn dry_resolve(&self) {
fn dry_resolve(&mut self) {
self.view.dry_resolve()
}

View File

@ -44,7 +44,7 @@ where
const MIN_LENGTH: usize = "<!DOCTYPE html>".len();
fn dry_resolve(&self) {}
fn dry_resolve(&mut self) {}
async fn resolve(self) -> Self::AsyncOutput {
self

View File

@ -40,7 +40,7 @@ where
const MIN_LENGTH: usize = 0;
fn dry_resolve(&self) {}
fn dry_resolve(&mut self) {}
async fn resolve(self) -> Self::AsyncOutput {
self

View File

@ -22,12 +22,15 @@ where
0
}
fn to_html(self, class: &mut String) {
fn to_html(mut self, class: &mut String) {
let value = self.invoke();
value.to_html(class);
}
fn hydrate<const FROM_SERVER: bool>(self, el: &R::Element) -> Self::State {
fn hydrate<const FROM_SERVER: bool>(
mut self,
el: &R::Element,
) -> Self::State {
// TODO FROM_SERVER vs template
let el = el.clone();
RenderEffect::new(move |prev| {
@ -42,7 +45,7 @@ where
.into()
}
fn build(self, el: &R::Element) -> Self::State {
fn build(mut self, el: &R::Element) -> Self::State {
let el = el.to_owned();
RenderEffect::new(move |prev| {
let value = self.invoke();
@ -56,7 +59,7 @@ where
.into()
}
fn rebuild(self, state: &mut Self::State) {
fn rebuild(mut self, state: &mut Self::State) {
let prev_effect = std::mem::take(&mut state.0);
let prev_value = prev_effect.as_ref().and_then(|e| e.take_value());
drop(prev_effect);
@ -99,7 +102,7 @@ where
}
fn to_html(self, class: &mut String) {
let (name, f) = self;
let (name, mut f) = self;
let include = *f.invoke().borrow();
if include {
<&str as IntoClass<R>>::to_html(name, class);
@ -108,7 +111,7 @@ where
fn hydrate<const FROM_SERVER: bool>(self, el: &R::Element) -> Self::State {
// TODO FROM_SERVER vs template
let (name, f) = self;
let (name, mut f) = self;
let class_list = R::class_list(el);
let name = R::intern(name);
@ -129,7 +132,7 @@ where
}
fn build(self, el: &R::Element) -> Self::State {
let (name, f) = self;
let (name, mut f) = self;
let class_list = R::class_list(el);
let name = R::intern(name);
@ -184,7 +187,7 @@ where
}
fn to_html(self, class: &mut String) {
let (names, f) = self;
let (names, mut f) = self;
let include = *f.invoke().borrow();
if include {
for name in names {
@ -195,7 +198,7 @@ where
fn hydrate<const FROM_SERVER: bool>(self, el: &R::Element) -> Self::State {
// TODO FROM_SERVER vs template
let (names, f) = self;
let (names, mut f) = self;
let class_list = R::class_list(el);
RenderEffect::new(move |prev: Option<(R::ClassList, bool)>| {
@ -220,7 +223,7 @@ where
}
fn build(self, el: &R::Element) -> Self::State {
let (names, f) = self;
let (names, mut f) = self;
let class_list = R::class_list(el);
RenderEffect::new(move |prev: Option<(R::ClassList, bool)>| {

View File

@ -20,7 +20,7 @@ where
0
}
fn to_html(self, buf: &mut String) {
fn to_html(mut self, buf: &mut String) {
let value = self.invoke();
value.to_html(buf);
}
@ -28,7 +28,7 @@ where
fn to_template(_buf: &mut String) {}
fn hydrate<const FROM_SERVER: bool>(
self,
mut self,
el: &<R as Renderer>::Element,
) -> Self::State {
let el = el.to_owned();
@ -43,7 +43,7 @@ where
})
}
fn build(self, el: &<R as Renderer>::Element) -> Self::State {
fn build(mut self, el: &<R as Renderer>::Element) -> Self::State {
let el = el.to_owned();
RenderEffect::new(move |prev| {
let value = self.invoke();

View File

@ -51,7 +51,7 @@ where
type State = RenderEffectState<V::State>;
#[track_caller]
fn build(self) -> Self::State {
fn build(mut self) -> Self::State {
RenderEffect::new(move |prev| {
let value = self.invoke();
if let Some(mut state) = prev {
@ -157,11 +157,11 @@ where
const MIN_LENGTH: usize = 0;
fn dry_resolve(&self) {
fn dry_resolve(&mut self) {
self.invoke().dry_resolve();
}
async fn resolve(self) -> Self::AsyncOutput {
async fn resolve(mut self) -> Self::AsyncOutput {
self.invoke().resolve().await
}
@ -169,13 +169,13 @@ where
V::MIN_LENGTH
}
fn to_html_with_buf(self, buf: &mut String, position: &mut Position) {
fn to_html_with_buf(mut self, buf: &mut String, position: &mut Position) {
let value = self.invoke();
value.to_html_with_buf(buf, position)
}
fn to_html_async_with_buf<const OUT_OF_ORDER: bool>(
self,
mut self,
buf: &mut StreamBuilder,
position: &mut Position,
) where
@ -186,7 +186,7 @@ where
}
fn hydrate<const FROM_SERVER: bool>(
self,
mut self,
cursor: &Cursor<R>,
position: &PositionState,
) -> Self::State {
@ -212,10 +212,10 @@ where
R: Renderer + 'static,
{
type Output<SomeNewAttr: Attribute<R>> =
Box<dyn Fn() -> V::Output<SomeNewAttr::CloneableOwned> + Send>;
Box<dyn FnMut() -> V::Output<SomeNewAttr::CloneableOwned> + Send>;
fn add_any_attr<NewAttr: Attribute<R>>(
self,
mut self,
attr: NewAttr,
) -> Self::Output<NewAttr>
where
@ -305,7 +305,7 @@ where
0
}
fn to_html(self, key: &str, buf: &mut String) {
fn to_html(mut self, key: &str, buf: &mut String) {
let value = self.invoke();
value.to_html(key, buf);
}
@ -313,7 +313,7 @@ where
fn to_template(_key: &str, _buf: &mut String) {}
fn hydrate<const FROM_SERVER: bool>(
self,
mut self,
key: &str,
el: &<R as Renderer>::Element,
) -> Self::State {
@ -333,7 +333,11 @@ where
.into()
}
fn build(self, el: &<R as Renderer>::Element, key: &str) -> Self::State {
fn build(
mut self,
el: &<R as Renderer>::Element,
key: &str,
) -> Self::State {
let key = R::intern(key);
let key = key.to_owned();
let el = el.to_owned();
@ -363,40 +367,40 @@ where
}
}
pub type SharedReactiveFunction<T> = Arc<Mutex<dyn Fn() -> T + Send>>;
pub type SharedReactiveFunction<T> = Arc<Mutex<dyn FnMut() -> T + Send>>;
pub trait ReactiveFunction: Send + 'static {
type Output;
fn invoke(&self) -> Self::Output;
fn invoke(&mut self) -> Self::Output;
fn into_shared(self) -> Arc<Mutex<dyn Fn() -> Self::Output + Send>>;
fn into_shared(self) -> Arc<Mutex<dyn FnMut() -> Self::Output + Send>>;
}
impl<T: 'static> ReactiveFunction for Arc<Mutex<dyn Fn() -> T + Send>> {
impl<T: 'static> ReactiveFunction for Arc<Mutex<dyn FnMut() -> T + Send>> {
type Output = T;
fn invoke(&self) -> Self::Output {
let fun = self.lock().expect("lock poisoned");
fn invoke(&mut self) -> Self::Output {
let mut fun = self.lock().expect("lock poisoned");
fun()
}
fn into_shared(self) -> Arc<Mutex<dyn Fn() -> Self::Output + Send>> {
fn into_shared(self) -> Arc<Mutex<dyn FnMut() -> Self::Output + Send>> {
self
}
}
impl<F, T> ReactiveFunction for F
where
F: Fn() -> T + Send + 'static,
F: FnMut() -> T + Send + 'static,
{
type Output = T;
fn invoke(&self) -> Self::Output {
fn invoke(&mut self) -> Self::Output {
self()
}
fn into_shared(self) -> Arc<Mutex<dyn Fn() -> Self::Output + Send>> {
fn into_shared(self) -> Arc<Mutex<dyn FnMut() -> Self::Output + Send>> {
Arc::new(Mutex::new(self))
}
}
@ -472,7 +476,7 @@ mod stable {
const MIN_LENGTH: usize = 0;
fn dry_resolve(&self) {}
fn dry_resolve(&mut self) {}
async fn resolve(self) -> Self::AsyncOutput {
self
@ -616,7 +620,7 @@ mod stable {
const MIN_LENGTH: usize = 0;
fn dry_resolve(&self) {}
fn dry_resolve(&mut self) {}
async fn resolve(self) -> Self::AsyncOutput {
self

View File

@ -157,7 +157,7 @@ where
OwnedView { owner, view, rndr }
}
fn dry_resolve(&self) {
fn dry_resolve(&mut self) {
self.owner.with(|| self.view.dry_resolve());
}
}

View File

@ -18,7 +18,7 @@ where
type CloneableOwned = SharedReactiveFunction<V>;
fn hydrate<const FROM_SERVER: bool>(
self,
mut self,
el: &<R as Renderer>::Element,
key: &str,
) -> Self::State {
@ -37,7 +37,11 @@ where
})
}
fn build(self, el: &<R as Renderer>::Element, key: &str) -> Self::State {
fn build(
mut self,
el: &<R as Renderer>::Element,
key: &str,
) -> Self::State {
let key = R::intern(key);
let key = key.to_owned();
let el = el.to_owned();

View File

@ -14,7 +14,7 @@ where
type CloneableOwned = (&'static str, SharedReactiveFunction<S>);
fn to_html(self, style: &mut String) {
let (name, f) = self;
let (name, mut f) = self;
let value = f.invoke();
style.push_str(name);
style.push(':');
@ -23,7 +23,7 @@ where
}
fn hydrate<const FROM_SERVER: bool>(self, el: &R::Element) -> Self::State {
let (name, f) = self;
let (name, mut f) = self;
let name = R::intern(name);
// TODO FROM_SERVER vs template
let style = R::style(el);
@ -51,7 +51,7 @@ where
}
fn build(self, el: &R::Element) -> Self::State {
let (name, f) = self;
let (name, mut f) = self;
let name = R::intern(name);
let style = R::style(el);
RenderEffect::new(move |prev| {
@ -98,12 +98,15 @@ where
type Cloneable = SharedReactiveFunction<C>;
type CloneableOwned = SharedReactiveFunction<C>;
fn to_html(self, style: &mut String) {
fn to_html(mut self, style: &mut String) {
let value = self.invoke();
value.to_html(style);
}
fn hydrate<const FROM_SERVER: bool>(self, el: &R::Element) -> Self::State {
fn hydrate<const FROM_SERVER: bool>(
mut self,
el: &R::Element,
) -> Self::State {
// TODO FROM_SERVER vs template
let el = el.clone();
RenderEffect::new(move |prev| {
@ -117,7 +120,7 @@ where
})
}
fn build(self, el: &R::Element) -> Self::State {
fn build(mut self, el: &R::Element) -> Self::State {
let el = el.clone();
RenderEffect::new(move |prev| {
let value = self.invoke();

View File

@ -225,5 +225,5 @@ where
Some(self.0.await)
}
fn dry_resolve(&self) {}
fn dry_resolve(&mut self) {}
}

View File

@ -40,7 +40,7 @@ where
resolve:
fn(Box<dyn Any>) -> Pin<Box<dyn Future<Output = AnyView<R>> + Send>>,
#[cfg(feature = "ssr")]
dry_resolve: fn(&Box<dyn Any + Send>),
dry_resolve: fn(&mut Box<dyn Any + Send>),
#[cfg(feature = "hydrate")]
#[cfg(feature = "hydrate")]
#[allow(clippy::type_complexity)]
@ -144,10 +144,10 @@ where
let value = Box::new(self) as Box<dyn Any + Send>;
#[cfg(feature = "ssr")]
let dry_resolve = |value: &Box<dyn Any + Send>| {
let dry_resolve = |value: &mut Box<dyn Any + Send>| {
let value = value
.downcast_ref::<T>()
.expect("AnyView::dry_resolve could not be downcast");
.downcast_mut::<T>()
.expect("AnyView::resolve could not be downcast");
value.dry_resolve();
};
@ -304,10 +304,10 @@ where
{
type AsyncOutput = Self;
fn dry_resolve(&self) {
fn dry_resolve(&mut self) {
#[cfg(feature = "ssr")]
{
(self.dry_resolve)(&self.value)
(self.dry_resolve)(&mut self.value)
}
#[cfg(not(feature = "ssr"))]
panic!(

View File

@ -149,7 +149,7 @@ where
{
type AsyncOutput = Either<A::AsyncOutput, B::AsyncOutput>;
fn dry_resolve(&self) {
fn dry_resolve(&mut self) {
match self {
Either::Left(left) => left.dry_resolve(),
Either::Right(right) => right.dry_resolve(),
@ -337,7 +337,7 @@ where
const MIN_LENGTH: usize = 0;
fn dry_resolve(&self) {
fn dry_resolve(&mut self) {
todo!()
}
@ -551,7 +551,7 @@ macro_rules! tuples {
const MIN_LENGTH: usize = max_usize(&[$($ty ::MIN_LENGTH,)*]);
fn dry_resolve(&self) {
fn dry_resolve(&mut self) {
match self {
$([<EitherOf $num>]::$ty(this) => {
this.dry_resolve();

View File

@ -143,8 +143,8 @@ where
const MIN_LENGTH: usize = T::MIN_LENGTH;
fn dry_resolve(&self) {
if let Ok(inner) = self.as_ref() {
fn dry_resolve(&mut self) {
if let Ok(inner) = self.as_mut() {
inner.dry_resolve()
}
}

View File

@ -73,8 +73,8 @@ where
const MIN_LENGTH: usize = T::MIN_LENGTH;
fn dry_resolve(&self) {
if let Some(inner) = self.as_ref() {
fn dry_resolve(&mut self) {
if let Some(inner) = self.as_mut() {
inner.dry_resolve();
}
}
@ -313,8 +313,8 @@ where
const MIN_LENGTH: usize = 0;
fn dry_resolve(&self) {
for inner in self {
fn dry_resolve(&mut self) {
for inner in self.iter_mut() {
inner.dry_resolve();
}
}

View File

@ -199,7 +199,7 @@ where
const MIN_LENGTH: usize = 0;
fn dry_resolve(&self) {
fn dry_resolve(&mut self) {
// TODO...
}

View File

@ -67,7 +67,7 @@ where
const MIN_LENGTH: usize;
fn dry_resolve(&self);
fn dry_resolve(&mut self);
/// Waits for any asynchronous sections of the view to load and returns the output.
fn resolve(self) -> impl Future<Output = Self::AsyncOutput> + Send;

View File

@ -73,7 +73,7 @@ macro_rules! render_primitive {
const MIN_LENGTH: usize = 0;
fn dry_resolve(&self) {}
fn dry_resolve(&mut self) {}
async fn resolve(self) -> Self::AsyncOutput {
self

View File

@ -166,7 +166,7 @@ where
const MIN_LENGTH: usize = V.len();
fn dry_resolve(&self) {}
fn dry_resolve(&mut self) {}
// this won't actually compile because if a weird interaction because the const &'static str and
// the RPITIT, so we just refine it to a concrete future type; this will never change in any

View File

@ -43,7 +43,7 @@ where
const MIN_LENGTH: usize = 0;
fn dry_resolve(&self) {}
fn dry_resolve(&mut self) {}
async fn resolve(self) -> Self::AsyncOutput {
self
@ -168,7 +168,7 @@ where
const MIN_LENGTH: usize = 0;
type AsyncOutput = Self;
fn dry_resolve(&self) {}
fn dry_resolve(&mut self) {}
async fn resolve(self) -> Self::AsyncOutput {
self
@ -358,7 +358,7 @@ where
const MIN_LENGTH: usize = 0;
fn dry_resolve(&self) {}
fn dry_resolve(&mut self) {}
async fn resolve(self) -> Self::AsyncOutput {
self
@ -453,7 +453,7 @@ where
const MIN_LENGTH: usize = 0;
fn dry_resolve(&self) {}
fn dry_resolve(&mut self) {}
async fn resolve(self) -> Self::AsyncOutput {
self

View File

@ -92,7 +92,7 @@ where
self.view.hydrate::<FROM_SERVER>(cursor, position)
}
fn dry_resolve(&self) {
fn dry_resolve(&mut self) {
todo!()
}

View File

@ -38,7 +38,7 @@ where
async fn resolve(self) -> Self::AsyncOutput {}
fn dry_resolve(&self) {}
fn dry_resolve(&mut self) {}
}
impl<Rndr> AddAnyAttr<Rndr> for ()
@ -136,7 +136,7 @@ where
(self.0.resolve().await,)
}
fn dry_resolve(&self) {
fn dry_resolve(&mut self) {
self.0.dry_resolve();
}
}
@ -260,7 +260,7 @@ macro_rules! impl_view_for_tuples {
)
}
fn dry_resolve(&self) {
fn dry_resolve(&mut self) {
#[allow(non_snake_case)]
let ($first, $($ty,)*) = self;
$first.dry_resolve();