feat: implement IntoClass for store fields (#3670)

* Implement `IntoClass` for store fields

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes (attempt 2/3)

* [autofix.ci] apply automated fixes (attempt 3/3)

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
mahdi739
2025-03-07 16:52:59 +03:30
committed by GitHub
parent bfe04593fd
commit 4ba9f67440
4 changed files with 268 additions and 186 deletions

View File

@@ -9,7 +9,7 @@ use std::{
error,
fmt::{self, Display},
future::Future,
mem, ops,
ops,
pin::Pin,
sync::Arc,
task::{Context, Poll},
@@ -103,9 +103,7 @@ pub fn get_error_hook() -> Option<Arc<dyn ErrorHook>> {
/// Sets the current thread-local error hook, which will be invoked when [`throw`] is called.
pub fn set_error_hook(hook: Arc<dyn ErrorHook>) -> ResetErrorHookOnDrop {
ResetErrorHookOnDrop(
ERROR_HOOK.with_borrow_mut(|this| mem::replace(this, Some(hook))),
)
ResetErrorHookOnDrop(ERROR_HOOK.with_borrow_mut(|this| this.replace(hook)))
}
/// Invokes the error hook set by [`set_error_hook`] with the given error.

View File

@@ -209,11 +209,8 @@ impl Owner {
pub fn with<T>(&self, fun: impl FnOnce() -> T) -> T {
// codegen optimisation:
fn inner_1(self_: &Owner) -> Option<Owner> {
let prev = {
OWNER.with(|o| {
mem::replace(&mut *o.borrow_mut(), Some(self_.clone()))
})
};
let prev =
{ OWNER.with(|o| (*o.borrow_mut()).replace(self_.clone())) };
#[cfg(feature = "sandboxed-arenas")]
Arena::set(&self_.inner.read().or_poisoned().arena);
prev

View File

@@ -37,10 +37,8 @@ impl AsyncTransition {
let (tx, rx) = mpsc::channel();
let global_transition = global_transition();
let inner = TransitionInner { tx };
let prev = std::mem::replace(
&mut *global_transition.write().or_poisoned(),
Some(inner.clone()),
);
let prev =
(*global_transition.write().or_poisoned()).replace(inner.clone());
let value = action().await;
_ = std::mem::replace(
&mut *global_transition.write().or_poisoned(),

View File

@@ -517,84 +517,13 @@ mod stable {
use super::RenderEffectWithClassName;
use crate::renderer::Rndr;
macro_rules! class_signal_arena {
($sig:ident) => {
macro_rules! tuple_class_reactive {
($name:ident, <$($impl_gen:ident),*>, <$($gen:ident),*> , $( $where_clause:tt )*) =>
{
#[allow(deprecated)]
impl<C, S> IntoClass for $sig<C, S>
impl<$($impl_gen),*> IntoClass for (&'static str, $name<$($gen),*>)
where
$sig<C, S>: Get<Value = C>,
S: Send + Sync + 'static,
S: Storage<C> + Storage<Option<C>>,
C: IntoClass + Send + Sync + Clone + 'static,
C::State: 'static,
{
type AsyncOutput = Self;
type State = RenderEffect<C::State>;
type Cloneable = Self;
type CloneableOwned = Self;
fn html_len(&self) -> usize {
0
}
fn to_html(self, class: &mut String) {
let value = self.get();
value.to_html(class);
}
fn hydrate<const FROM_SERVER: bool>(
self,
el: &crate::renderer::types::Element,
) -> Self::State {
(move || self.get()).hydrate::<FROM_SERVER>(el)
}
fn build(
self,
el: &crate::renderer::types::Element,
) -> Self::State {
(move || self.get()).build(el)
}
fn rebuild(self, state: &mut Self::State) {
(move || self.get()).rebuild(state)
}
fn into_cloneable(self) -> Self::Cloneable {
self
}
fn into_cloneable_owned(self) -> Self::CloneableOwned {
self
}
fn dry_resolve(&mut self) {}
async fn resolve(self) -> Self::AsyncOutput {
self
}
fn reset(state: &mut Self::State) {
*state = RenderEffect::new_with_value(
move |prev| {
if let Some(mut state) = prev {
C::reset(&mut state);
state
} else {
unreachable!()
}
},
state.take_value(),
);
}
}
#[allow(deprecated)]
impl<S> IntoClass for (&'static str, $sig<bool, S>)
where
$sig<bool, S>: Get<Value = bool>,
S: Send + 'static,
S: Storage<bool>,
$($where_clause)*
{
type AsyncOutput = Self;
type State = RenderEffectWithClassName<(
@@ -674,16 +603,18 @@ mod stable {
};
}
macro_rules! class_signal {
($sig:ident) => {
impl<C> IntoClass for $sig<C>
macro_rules! class_reactive {
($name:ident, <$($gen:ident),*>, $v:ty, $( $where_clause:tt )*) =>
{
#[allow(deprecated)]
impl<$($gen),*> IntoClass for $name<$($gen),*>
where
$sig<C>: Get<Value = C>,
C: IntoClass + Send + Sync + Clone + 'static,
C::State: 'static,
$v: IntoClass + Clone + Send + Sync + 'static,
<$v as IntoClass>::State: 'static,
$($where_clause)*
{
type AsyncOutput = Self;
type State = RenderEffect<C::State>;
type State = RenderEffect<<$v as IntoClass>::State>;
type Cloneable = Self;
type CloneableOwned = Self;
@@ -732,7 +663,7 @@ mod stable {
*state = RenderEffect::new_with_value(
move |prev| {
if let Some(mut state) = prev {
C::reset(&mut state);
<$v>::reset(&mut state);
state
} else {
unreachable!()
@@ -742,86 +673,6 @@ mod stable {
);
}
}
impl IntoClass for (&'static str, $sig<bool>)
where
$sig<bool>: Get<Value = bool>,
{
type AsyncOutput = Self;
type State = RenderEffectWithClassName<(
crate::renderer::types::ClassList,
bool,
)>;
type Cloneable = Self;
type CloneableOwned = Self;
fn html_len(&self) -> usize {
self.0.len()
}
fn to_html(self, class: &mut String) {
let (name, f) = self;
let include = f.get();
if include {
<&str as IntoClass>::to_html(name, class);
}
}
fn hydrate<const FROM_SERVER: bool>(
self,
el: &crate::renderer::types::Element,
) -> Self::State {
IntoClass::hydrate::<FROM_SERVER>(
(self.0, move || self.1.get()),
el,
)
}
fn build(
self,
el: &crate::renderer::types::Element,
) -> Self::State {
IntoClass::build((self.0, move || self.1.get()), el)
}
fn rebuild(self, state: &mut Self::State) {
IntoClass::rebuild((self.0, move || self.1.get()), state)
}
fn into_cloneable(self) -> Self::Cloneable {
self
}
fn into_cloneable_owned(self) -> Self::CloneableOwned {
self
}
fn dry_resolve(&mut self) {}
async fn resolve(self) -> Self::AsyncOutput {
self
}
fn reset(state: &mut Self::State) {
let name = state.name;
*state = RenderEffectWithClassName::new(
state.name,
RenderEffect::new_with_value(
move |prev| {
if let Some(mut state) = prev {
let (class_list, prev) = &mut state;
Rndr::remove_class(class_list, name);
*prev = false;
state
} else {
unreachable!()
}
},
state.effect.take_value(),
),
);
}
}
};
}
@@ -836,16 +687,254 @@ mod stable {
traits::Get,
wrappers::read::{ArcSignal, Signal},
};
class_reactive!(
RwSignal,
<V, S>,
V,
RwSignal<V, S>: Get<Value = V>,
S: Storage<V> + Storage<Option<V>>,
S: Send + Sync + 'static,
);
class_reactive!(
ReadSignal,
<V, S>,
V,
ReadSignal<V, S>: Get<Value = V>,
S: Storage<V> + Storage<Option<V>>,
S: Send + Sync + 'static,
);
class_reactive!(
Memo,
<V, S>,
V,
Memo<V, S>: Get<Value = V>,
S: Storage<V> + Storage<Option<V>>,
S: Send + Sync + 'static,
);
class_reactive!(
Signal,
<V, S>,
V,
Signal<V, S>: Get<Value = V>,
S: Storage<V> + Storage<Option<V>>,
S: Send + Sync + 'static,
);
class_reactive!(
MaybeSignal,
<V, S>,
V,
MaybeSignal<V, S>: Get<Value = V>,
S: Storage<V> + Storage<Option<V>>,
S: Send + Sync + 'static,
);
class_reactive!(ArcRwSignal, <V>, V, ArcRwSignal<V>: Get<Value = V>);
class_reactive!(ArcReadSignal, <V>, V, ArcReadSignal<V>: Get<Value = V>);
class_reactive!(ArcMemo, <V>, V, ArcMemo<V>: Get<Value = V>);
class_reactive!(ArcSignal, <V>, V, ArcSignal<V>: Get<Value = V>);
class_signal_arena!(RwSignal);
class_signal_arena!(ReadSignal);
class_signal_arena!(Memo);
class_signal_arena!(Signal);
class_signal_arena!(MaybeSignal);
class_signal!(ArcRwSignal);
class_signal!(ArcReadSignal);
class_signal!(ArcMemo);
class_signal!(ArcSignal);
tuple_class_reactive!(
RwSignal,
<S>,
<bool, S>,
RwSignal<bool, S>: Get<Value = bool>,
S: Storage<bool>,
S: Send + 'static,
);
tuple_class_reactive!(
ReadSignal,
<S>,
<bool, S>,
ReadSignal<bool, S>: Get<Value = bool>,
S: Storage<bool>,
S: Send + 'static,
);
tuple_class_reactive!(
Memo,
<S>,
<bool, S>,
Memo<bool, S>: Get<Value = bool>,
S: Storage<bool>,
S: Send + 'static,
);
tuple_class_reactive!(
Signal,
<S>,
<bool, S>,
Signal<bool, S>: Get<Value = bool>,
S: Storage<bool>,
S: Send + 'static,
);
tuple_class_reactive!(
MaybeSignal,
<S>,
<bool, S>,
MaybeSignal<bool, S>: Get<Value = bool>,
S: Storage<bool>,
S: Send + 'static,
);
tuple_class_reactive!(ArcRwSignal,<>, <bool>, ArcRwSignal<bool>: Get<Value = bool>);
tuple_class_reactive!(ArcReadSignal,<>, <bool>, ArcReadSignal<bool>: Get<Value = bool>);
tuple_class_reactive!(ArcMemo,<>, <bool>, ArcMemo<bool>: Get<Value = bool>);
tuple_class_reactive!(ArcSignal,<>, <bool>, ArcSignal<bool>: Get<Value = bool>);
#[cfg(feature = "reactive_stores")]
use {
reactive_stores::{
ArcField, ArcStore, AtIndex, AtKeyed, DerefedField, Field,
KeyedSubfield, Store, StoreField, Subfield,
},
std::ops::{Deref, DerefMut, Index, IndexMut},
};
#[cfg(feature = "reactive_stores")]
class_reactive!(
Subfield,
<Inner, Prev, V>,
V,
Subfield<Inner, Prev, V>: Get<Value = V>,
Prev: Send + Sync + 'static,
Inner: Send + Sync + Clone + 'static,
);
#[cfg(feature = "reactive_stores")]
class_reactive!(
AtKeyed,
<Inner, Prev, K, V>,
V,
AtKeyed<Inner, Prev, K, V>: Get<Value = V>,
Prev: Send + Sync + 'static,
Inner: Send + Sync + Clone + 'static,
K: Send + Sync + std::fmt::Debug + Clone + 'static,
for<'a> &'a V: IntoIterator,
);
#[cfg(feature = "reactive_stores")]
class_reactive!(
KeyedSubfield,
<Inner, Prev, K, V>,
V,
KeyedSubfield<Inner, Prev, K, V>: Get<Value = V>,
Prev: Send + Sync + 'static,
Inner: Send + Sync + Clone + 'static,
K: Send + Sync + std::fmt::Debug + Clone + 'static,
for<'a> &'a V: IntoIterator,
);
#[cfg(feature = "reactive_stores")]
class_reactive!(
DerefedField,
<S>,
<S::Value as Deref>::Target,
S: Clone + StoreField + Send + Sync + 'static,
<S as StoreField>::Value: Deref + DerefMut
);
#[cfg(feature = "reactive_stores")]
class_reactive!(
AtIndex,
<Inner, Prev>,
<Prev as Index<usize>>::Output,
AtIndex<Inner, Prev>: Get<Value = Prev::Output>,
Prev: Send + Sync + IndexMut<usize> + 'static,
Inner: Send + Sync + Clone + 'static,
);
#[cfg(feature = "reactive_stores")]
class_reactive!(
Store,
<V, S>,
V,
Store<V, S>: Get<Value = V>,
S: Storage<V> + Storage<Option<V>>,
S: Send + Sync + 'static,
);
#[cfg(feature = "reactive_stores")]
class_reactive!(
Field,
<V, S>,
V,
Field<V, S>: Get<Value = V>,
S: Storage<V> + Storage<Option<V>>,
S: Send + Sync + 'static,
);
#[cfg(feature = "reactive_stores")]
class_reactive!(ArcStore, <V>, V, ArcStore<V>: Get<Value = V>);
#[cfg(feature = "reactive_stores")]
class_reactive!(ArcField, <V>, V, ArcField<V>: Get<Value = V>);
#[cfg(feature = "reactive_stores")]
tuple_class_reactive!(
Subfield,
<Inner, Prev>,
<Inner, Prev, bool>,
Subfield<Inner, Prev, bool>: Get<Value = bool>,
Prev: Send + Sync + 'static,
Inner: Send + Sync + Clone + 'static,
);
#[cfg(feature = "reactive_stores")]
tuple_class_reactive!(
AtKeyed,
<Inner, Prev, K>,
<Inner, Prev, K, bool>,
AtKeyed<Inner, Prev, K, bool>: Get<Value = bool>,
Prev: Send + Sync + 'static,
Inner: Send + Sync + Clone + 'static,
K: Send + Sync + std::fmt::Debug + Clone + 'static,
for<'a> &'a bool: IntoIterator,
);
#[cfg(feature = "reactive_stores")]
tuple_class_reactive!(
KeyedSubfield,
<Inner, Prev, K>,
<Inner, Prev, K, bool>,
KeyedSubfield<Inner, Prev, K, bool>: Get<Value = bool>,
Prev: Send + Sync + 'static,
Inner: Send + Sync + Clone + 'static,
K: Send + Sync + std::fmt::Debug + Clone + 'static,
for<'a> &'a bool: IntoIterator,
);
#[cfg(feature = "reactive_stores")]
tuple_class_reactive!(
DerefedField,
<S>,
<S>,
S: Clone + StoreField + Send + Sync + 'static,
<S as StoreField>::Value: Deref<Target = bool> + DerefMut
);
#[cfg(feature = "reactive_stores")]
tuple_class_reactive!(
AtIndex,
<Inner, Prev>,
<Inner, Prev>,
AtIndex<Inner, Prev>: Get<Value = Prev::Output>,
Prev: Send + Sync + IndexMut<usize,Output = bool> + 'static,
Inner: Send + Sync + Clone + 'static,
);
#[cfg(feature = "reactive_stores")]
tuple_class_reactive!(
Store,
<S>,
<bool, S>,
Store<bool, S>: Get<Value = bool>,
S: Storage<bool>,
S: Send + 'static,
);
#[cfg(feature = "reactive_stores")]
tuple_class_reactive!(
Field,
<S>,
<bool, S>,
Field<bool, S>: Get<Value = bool>,
S: Storage<bool>,
S: Send + 'static,
);
#[cfg(feature = "reactive_stores")]
tuple_class_reactive!(ArcStore,<>, <bool>, ArcStore<bool>: Get<Value = bool>);
#[cfg(feature = "reactive_stores")]
tuple_class_reactive!(ArcField,<>, <bool>, ArcField<bool>: Get<Value = bool>);
}
/*