From 60ad4bf5759fef234e9c5ef27da6361225b73795 Mon Sep 17 00:00:00 2001 From: Greg Johnston Date: Sun, 19 Mar 2023 16:44:43 -0400 Subject: [PATCH] feat: allow manual signal disposal before the scope is disposed --- leptos_reactive/src/memo.rs | 10 ++++++++-- leptos_reactive/src/runtime.rs | 6 ++++++ leptos_reactive/src/signal.rs | 28 ++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/leptos_reactive/src/memo.rs b/leptos_reactive/src/memo.rs index 6765ebd80..71aa12950 100644 --- a/leptos_reactive/src/memo.rs +++ b/leptos_reactive/src/memo.rs @@ -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 SignalStream for Memo { } } +impl SignalDispose for Memo { + fn dispose(self) { + _ = with_runtime(self.runtime, |runtime| runtime.dispose_node(self.id)); + } +} + impl_get_fn_traits![Memo]; pub(crate) struct MemoState diff --git a/leptos_reactive/src/runtime.rs b/leptos_reactive/src/runtime.rs index 78ef6f892..6e187dec1 100644 --- a/leptos_reactive/src/runtime.rs +++ b/leptos_reactive/src/runtime.rs @@ -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 { diff --git a/leptos_reactive/src/signal.rs b/leptos_reactive/src/signal.rs index b1248ece5..a179d6f5d 100644 --- a/leptos_reactive/src/signal.rs +++ b/leptos_reactive/src/signal.rs @@ -274,6 +274,16 @@ pub trait SignalStream { fn to_stream(&self, cx: Scope) -> Pin>>; } +/// 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 SignalStream for ReadSignal { } } +impl SignalDispose for ReadSignal { + fn dispose(self) { + _ = with_runtime(self.runtime, |runtime| runtime.dispose_node(self.id)); + } +} + impl ReadSignal where T: 'static, @@ -1025,6 +1041,12 @@ impl SignalSet for WriteSignal { } } +impl SignalDispose for WriteSignal { + fn dispose(self) { + _ = with_runtime(self.runtime, |runtime| runtime.dispose_node(self.id)); + } +} + impl Clone for WriteSignal { fn clone(&self) -> Self { Self { @@ -1598,6 +1620,12 @@ impl SignalStream for RwSignal { } } +impl SignalDispose for RwSignal { + fn dispose(self) { + _ = with_runtime(self.runtime, |runtime| runtime.dispose_node(self.id)); + } +} + impl RwSignal { /// Returns a read-only handle to the signal. ///