mirror of
https://github.com/leptos-rs/leptos
synced 2024-11-10 06:44:17 +00:00
fix: do not panic in automatic Track implementation if source is disposed (#2964)
This commit is contained in:
parent
4fa6660a3f
commit
a083b57260
7 changed files with 61 additions and 8 deletions
|
@ -9,7 +9,7 @@ use reactive_graph::{
|
|||
},
|
||||
owner::use_context,
|
||||
signal::guards::{AsyncPlain, ReadGuard},
|
||||
traits::{DefinedAt, ReadUntracked},
|
||||
traits::{DefinedAt, IsDisposed, ReadUntracked},
|
||||
};
|
||||
use send_wrapper::SendWrapper;
|
||||
use std::{
|
||||
|
@ -121,6 +121,13 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: 'static> IsDisposed for ArcLocalResource<T> {
|
||||
#[inline(always)]
|
||||
fn is_disposed(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: 'static> ToAnySource for ArcLocalResource<T> {
|
||||
fn to_any_source(&self) -> AnySource {
|
||||
self.data.to_any_source()
|
||||
|
@ -292,6 +299,12 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: 'static> IsDisposed for LocalResource<T> {
|
||||
fn is_disposed(&self) -> bool {
|
||||
self.data.is_disposed()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: 'static> ToAnySource for LocalResource<T>
|
||||
where
|
||||
T: Send + Sync + 'static,
|
||||
|
|
|
@ -9,7 +9,7 @@ use crate::{
|
|||
guards::{Mapped, Plain, ReadGuard},
|
||||
ArcReadSignal, ArcRwSignal,
|
||||
},
|
||||
traits::{DefinedAt, Get, ReadUntracked},
|
||||
traits::{DefinedAt, Get, IsDisposed, ReadUntracked},
|
||||
};
|
||||
use core::fmt::Debug;
|
||||
use or_poisoned::OrPoisoned;
|
||||
|
@ -260,6 +260,16 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: 'static, S> IsDisposed for ArcMemo<T, S>
|
||||
where
|
||||
S: Storage<T>,
|
||||
{
|
||||
#[inline(always)]
|
||||
fn is_disposed(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: 'static, S> ToAnySource for ArcMemo<T, S>
|
||||
where
|
||||
S: Storage<T>,
|
||||
|
|
|
@ -18,7 +18,8 @@ use crate::{
|
|||
ArcTrigger,
|
||||
},
|
||||
traits::{
|
||||
DefinedAt, Notify, ReadUntracked, Track, UntrackableGuard, Writeable,
|
||||
DefinedAt, IsDisposed, Notify, ReadUntracked, Track, UntrackableGuard,
|
||||
Writeable,
|
||||
},
|
||||
transition::AsyncTransition,
|
||||
};
|
||||
|
@ -600,6 +601,13 @@ impl<T: 'static> Writeable for ArcAsyncDerived<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: 'static> IsDisposed for ArcAsyncDerived<T> {
|
||||
#[inline(always)]
|
||||
fn is_disposed(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: 'static> ToAnySource for ArcAsyncDerived<T> {
|
||||
fn to_any_source(&self) -> AnySource {
|
||||
AnySource(
|
||||
|
|
|
@ -7,7 +7,8 @@ use crate::{
|
|||
owner::{FromLocal, LocalStorage, Storage, StoredValue, SyncStorage},
|
||||
signal::guards::{AsyncPlain, ReadGuard, WriteGuard},
|
||||
traits::{
|
||||
DefinedAt, Dispose, Notify, ReadUntracked, UntrackableGuard, Writeable,
|
||||
DefinedAt, Dispose, IsDisposed, Notify, ReadUntracked,
|
||||
UntrackableGuard, Writeable,
|
||||
},
|
||||
unwrap_signal,
|
||||
};
|
||||
|
@ -322,6 +323,16 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<T, S> IsDisposed for AsyncDerived<T, S>
|
||||
where
|
||||
T: 'static,
|
||||
S: Storage<ArcAsyncDerived<T>>,
|
||||
{
|
||||
fn is_disposed(&self) -> bool {
|
||||
self.inner.is_disposed()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, S> ToAnySource for AsyncDerived<T, S>
|
||||
where
|
||||
T: 'static,
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
use super::{node::ReactiveNode, AnySubscriber};
|
||||
use crate::traits::DefinedAt;
|
||||
use crate::traits::{DefinedAt, IsDisposed};
|
||||
use core::{fmt::Debug, hash::Hash};
|
||||
use std::{panic::Location, sync::Weak};
|
||||
|
||||
/// Abstracts over the type of any reactive source.
|
||||
pub trait ToAnySource {
|
||||
pub trait ToAnySource: IsDisposed {
|
||||
/// Converts this type to its type-erased equivalent.
|
||||
fn to_any_source(&self) -> AnySource;
|
||||
}
|
||||
|
@ -62,6 +62,13 @@ impl PartialEq for AnySource {
|
|||
|
||||
impl Eq for AnySource {}
|
||||
|
||||
impl IsDisposed for AnySource {
|
||||
#[inline(always)]
|
||||
fn is_disposed(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
impl ToAnySource for AnySource {
|
||||
fn to_any_source(&self) -> AnySource {
|
||||
self.clone()
|
||||
|
|
|
@ -13,7 +13,7 @@ use crate::{
|
|||
AnySource, AnySubscriber, ReactiveNode, Source, SubscriberSet,
|
||||
ToAnySource,
|
||||
},
|
||||
traits::DefinedAt,
|
||||
traits::{DefinedAt, IsDisposed},
|
||||
unwrap_signal,
|
||||
};
|
||||
use or_poisoned::OrPoisoned;
|
||||
|
@ -93,7 +93,7 @@ impl<T: AsSubscriberSet + DefinedAt> Source for T {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: AsSubscriberSet + DefinedAt> ToAnySource for T
|
||||
impl<T: AsSubscriberSet + DefinedAt + IsDisposed> ToAnySource for T
|
||||
where
|
||||
T::Output: Borrow<Arc<RwLock<SubscriberSet>>>,
|
||||
{
|
||||
|
|
|
@ -107,6 +107,10 @@ pub trait Track {
|
|||
impl<T: Source + ToAnySource + DefinedAt> Track for T {
|
||||
#[track_caller]
|
||||
fn track(&self) {
|
||||
if self.is_disposed() {
|
||||
return;
|
||||
}
|
||||
|
||||
if let Some(subscriber) = Observer::get() {
|
||||
subscriber.add_source(self.to_any_source());
|
||||
self.add_subscriber(subscriber);
|
||||
|
|
Loading…
Reference in a new issue