From 9bf5b22633afe4c1acc0c07f26459ccde8a08e29 Mon Sep 17 00:00:00 2001 From: Zak Stucke Date: Sun, 2 Nov 2025 15:24:26 +0200 Subject: [PATCH 1/2] Force cleanup even if there are other references to the root owner --- integrations/utils/src/lib.rs | 2 +- reactive_graph/src/owner.rs | 19 +++++++++++++++++++ router/src/static_routes.rs | 2 +- 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/integrations/utils/src/lib.rs b/integrations/utils/src/lib.rs index b4438eed9..880bacb4c 100644 --- a/integrations/utils/src/lib.rs +++ b/integrations/utils/src/lib.rs @@ -121,7 +121,7 @@ pub trait ExtendResponse: Sized { // drop the owner, cleaning up the reactive runtime, // once the stream is over .chain(once(async move { - owner.unset(); + owner.unset_with_forced_cleanup(); Default::default() })), )); diff --git a/reactive_graph/src/owner.rs b/reactive_graph/src/owner.rs index 8ad9a7d66..070af695e 100644 --- a/reactive_graph/src/owner.rs +++ b/reactive_graph/src/owner.rs @@ -340,6 +340,8 @@ impl Owner { } /// Removes this from its state as the thread-local owner and drops it. + /// If there are other holders of this owner, it may not cleanup, if always cleaning up is required, + /// see [`Owner::unset_with_forced_cleanup`]. pub fn unset(self) { OWNER.with_borrow_mut(|owner| { if owner.as_ref().and_then(|n| n.upgrade()) == Some(self) { @@ -348,6 +350,23 @@ impl Owner { }) } + /// Removes this from its state as the thread-local owner and drops it. + /// Unlike [`Owner::unset`], this will always run cleanup on this owner, + /// even if there are other holders of this owner. + pub fn unset_with_forced_cleanup(self) { + OWNER.with_borrow_mut(|owner| { + if owner + .as_ref() + .and_then(|n| n.upgrade()) + .map(|o| o == self) + .unwrap_or(false) + { + mem::take(owner); + } + }); + self.cleanup(); + } + /// Returns the current [`SharedContext`], if any. #[cfg(feature = "hydration")] pub fn current_shared_context( diff --git a/router/src/static_routes.rs b/router/src/static_routes.rs index ab6c60204..9d5bb51ec 100644 --- a/router/src/static_routes.rs +++ b/router/src/static_routes.rs @@ -369,7 +369,7 @@ impl ResolvedStaticPath { eprintln!("{e}"); } } - owner.unset(); + owner.unset_with_forced_cleanup(); } } }); From 4d01d951753199f6c7ee3377b57827a9ecfaed9c Mon Sep 17 00:00:00 2001 From: Zak Stucke Date: Sun, 2 Nov 2025 16:16:03 +0200 Subject: [PATCH 2/2] Clippy --- leptos_config/src/lib.rs | 22 ++++++++-------------- tachys/src/view/keyed.rs | 9 ++------- 2 files changed, 10 insertions(+), 21 deletions(-) diff --git a/leptos_config/src/lib.rs b/leptos_config/src/lib.rs index f4d560ec5..97b45b0eb 100644 --- a/leptos_config/src/lib.rs +++ b/leptos_config/src/lib.rs @@ -221,18 +221,15 @@ fn env_w_default( /// An enum that can be used to define the environment Leptos is running in. /// Setting this to the `PROD` variant will not include the WebSocket code for `cargo-leptos` watch mode. /// Defaults to `DEV`. -#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq, Eq)] +#[derive( + Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq, Eq, Default, +)] pub enum Env { PROD, + #[default] DEV, } -impl Default for Env { - fn default() -> Self { - Self::DEV - } -} - fn env_from_str(input: &str) -> Result { let sanitized = input.to_lowercase(); match sanitized.as_ref() { @@ -279,18 +276,15 @@ impl TryFrom for Env { /// An enum that can be used to define the websocket protocol Leptos uses for hotreloading /// Defaults to `ws`. -#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq, Eq)] +#[derive( + Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq, Eq, Default, +)] pub enum ReloadWSProtocol { + #[default] WS, WSS, } -impl Default for ReloadWSProtocol { - fn default() -> Self { - Self::WS - } -} - fn ws_from_str(input: &str) -> Result { let sanitized = input.to_lowercase(); match sanitized.as_ref() { diff --git a/tachys/src/view/keyed.rs b/tachys/src/view/keyed.rs index 2278bb281..acd499c25 100644 --- a/tachys/src/view/keyed.rs +++ b/tachys/src/view/keyed.rs @@ -642,18 +642,13 @@ struct DiffOpRemove { at: usize, } -#[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)] enum DiffOpAddMode { + #[default] Normal, Append, } -impl Default for DiffOpAddMode { - fn default() -> Self { - Self::Normal - } -} - fn apply_diff( parent: Option<&crate::renderer::types::Element>, marker: &crate::renderer::types::Placeholder,