feat: allow manual signal disposal before the scope is disposed (#710)

This commit is contained in:
Greg Johnston 2023-03-19 21:40:16 -04:00 committed by GitHub
parent 2faddd85cb
commit 9d142758ec
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 42 additions and 2 deletions

View file

@ -1,8 +1,8 @@
#![forbid(unsafe_code)]
use crate::{
create_effect, node::NodeId, on_cleanup, with_runtime, AnyComputation,
RuntimeId, Scope, SignalGet, SignalGetUntracked, SignalStream, SignalWith,
SignalWithUntracked,
RuntimeId, Scope, SignalDispose, SignalGet, SignalGetUntracked,
SignalStream, SignalWith, SignalWithUntracked,
};
use std::{any::Any, cell::RefCell, fmt::Debug, marker::PhantomData, rc::Rc};
@ -412,6 +412,12 @@ impl<T: Clone> SignalStream<T> for Memo<T> {
}
}
impl<T> SignalDispose for Memo<T> {
fn dispose(self) {
_ = with_runtime(self.runtime, |runtime| runtime.dispose_node(self.id));
}
}
impl_get_fn_traits![Memo];
pub(crate) struct MemoState<T, F>

View file

@ -254,6 +254,12 @@ impl Runtime {
}
});
}
pub(crate) fn dispose_node(&self, node: NodeId) {
self.node_sources.borrow_mut().remove(node);
self.node_subscribers.borrow_mut().remove(node);
self.nodes.borrow_mut().remove(node);
}
}
impl Debug for Runtime {

View file

@ -274,6 +274,16 @@ pub trait SignalStream<T> {
fn to_stream(&self, cx: Scope) -> Pin<Box<dyn Stream<Item = T>>>;
}
/// This trait allows disposing a signal before its [Scope] has been disposed.
pub trait SignalDispose {
/// Disposes of the signal. This:
/// 1. Detaches the signal from the reactive graph, preventing it from triggering
/// further updates; and
/// 2. Drops the value contained in the signal.
#[track_caller]
fn dispose(self);
}
/// Creates a signal, the basic reactive primitive.
///
/// A signal is a piece of data that may change over time,
@ -725,6 +735,12 @@ impl<T: Clone> SignalStream<T> for ReadSignal<T> {
}
}
impl<T> SignalDispose for ReadSignal<T> {
fn dispose(self) {
_ = with_runtime(self.runtime, |runtime| runtime.dispose_node(self.id));
}
}
impl<T> ReadSignal<T>
where
T: 'static,
@ -1025,6 +1041,12 @@ impl<T> SignalSet<T> for WriteSignal<T> {
}
}
impl<T> SignalDispose for WriteSignal<T> {
fn dispose(self) {
_ = with_runtime(self.runtime, |runtime| runtime.dispose_node(self.id));
}
}
impl<T> Clone for WriteSignal<T> {
fn clone(&self) -> Self {
Self {
@ -1598,6 +1620,12 @@ impl<T: Clone> SignalStream<T> for RwSignal<T> {
}
}
impl<T> SignalDispose for RwSignal<T> {
fn dispose(self) {
_ = with_runtime(self.runtime, |runtime| runtime.dispose_node(self.id));
}
}
impl<T> RwSignal<T> {
/// Returns a read-only handle to the signal.
///