From f930da1a67618ce8fa2a277fd712b11d96a92e97 Mon Sep 17 00:00:00 2001 From: zhom <2717306+zhom@users.noreply.github.com> Date: Sat, 26 Sep 2026 10:46:29 +0400 Subject: [PATCH] refactor: use std LazyLock --- src-tauri/Cargo.lock | 2 - src-tauri/Cargo.toml | 2 - src-tauri/src/api_client.rs | 4 +- src-tauri/src/api_server.rs | 6 +-- src-tauri/src/app_auto_updater.rs | 12 ++--- src-tauri/src/auto_updater.rs | 8 ++-- src-tauri/src/browser.rs | 9 ++-- src-tauri/src/browser_runner.rs | 9 ++-- src-tauri/src/browser_version_manager.rs | 5 +-- src-tauri/src/cloud_auth.rs | 6 +-- src-tauri/src/commercial_license.rs | 4 +- src-tauri/src/default_browser.rs | 5 +-- src-tauri/src/dns_blocklist.rs | 12 +++-- src-tauri/src/downloaded_browsers_registry.rs | 7 ++- src-tauri/src/downloader.rs | 20 ++++----- src-tauri/src/ephemeral_dirs.rs | 5 +-- src-tauri/src/extension_manager.rs | 5 +-- src-tauri/src/extraction.rs | 8 ++-- src-tauri/src/fingerprint_consistency.rs | 5 +-- src-tauri/src/geoip_downloader.rs | 5 +-- src-tauri/src/group_manager.rs | 5 +-- src-tauri/src/launch_gate.rs | 5 +-- src-tauri/src/launch_gate_prefs.rs | 8 ++-- src-tauri/src/mcp_server.rs | 4 +- src-tauri/src/profile/encryption.rs | 9 ++-- src-tauri/src/profile/manager.rs | 5 +-- src-tauri/src/profile/password.rs | 44 +++++++++---------- src-tauri/src/profile_importer.rs | 5 +-- src-tauri/src/proxy_manager.rs | 5 +-- src-tauri/src/proxy_runner.rs | 7 ++- src-tauri/src/recorder.rs | 5 +-- src-tauri/src/settings_manager.rs | 5 +-- src-tauri/src/sync/engine.rs | 6 +-- src-tauri/src/tag_manager.rs | 5 +-- src-tauri/src/team_lock.rs | 6 +-- src-tauri/src/vpn/mod.rs | 5 ++- src-tauri/src/wayfern_manager.rs | 5 +-- src-tauri/src/wayfern_terms.rs | 5 +-- src-tauri/src/window_decorations.rs | 5 +-- src/generated/licenses.json | 4 -- 40 files changed, 116 insertions(+), 171 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 38ee99fc..71db0e8d 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -1773,7 +1773,6 @@ dependencies = [ "hyper-util", "image", "jsonc-parser", - "lazy_static", "libc", "log", "lzma-rs", @@ -1784,7 +1783,6 @@ dependencies = [ "nix", "objc2", "objc2-app-kit", - "once_cell", "quick-xml 0.42.0", "rand 0.10.3", "regex-lite", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index b997d0cf..50526361 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -62,7 +62,6 @@ tokio-native-tls = "0.3" tokio = { version = "1", features = ["full", "sync"] } tokio-util = "0.7" sysinfo = "0.39" -lazy_static = "1.5" # 0.23 turns on `simd-unsafe` by default, decoding via hand-written unsafe # AVX2/NEON. This crate decodes attacker-influenced input (proxy CONNECT auth, # extension payloads, os_crypt key blobs), and none of those paths are hot @@ -83,7 +82,6 @@ url = "2.5" blake3 = "1" globset = "0.4" mime_guess = "2" -once_cell = "1" urlencoding = "2.1" chrono = { version = "0.4", features = ["serde"] } chrono-tz = "0.10" diff --git a/src-tauri/src/api_client.rs b/src-tauri/src/api_client.rs index 3107b534..91b9b62a 100644 --- a/src-tauri/src/api_client.rs +++ b/src-tauri/src/api_client.rs @@ -378,9 +378,7 @@ impl ApiClient { } } -lazy_static::lazy_static! { - static ref API_CLIENT: ApiClient = ApiClient::new(); -} +static API_CLIENT: std::sync::LazyLock = std::sync::LazyLock::new(ApiClient::new); #[cfg(test)] mod tests { diff --git a/src-tauri/src/api_server.rs b/src-tauri/src/api_server.rs index fbdad44d..32bc68b1 100644 --- a/src-tauri/src/api_server.rs +++ b/src-tauri/src/api_server.rs @@ -16,7 +16,6 @@ use axum::{ routing::get, Router, }; -use lazy_static::lazy_static; use serde::{Deserialize, Serialize}; use std::sync::Arc; use tokio::net::TcpListener; @@ -1211,9 +1210,8 @@ async fn rate_limit_middleware(request: axum::extract::Request, next: Next) -> R } // Global API server instance -lazy_static! { - pub static ref API_SERVER: Arc> = Arc::new(Mutex::new(ApiServer::new())); -} +pub static API_SERVER: std::sync::LazyLock>> = + std::sync::LazyLock::new(|| Arc::new(Mutex::new(ApiServer::new()))); // Tauri commands #[tauri::command] diff --git a/src-tauri/src/app_auto_updater.rs b/src-tauri/src/app_auto_updater.rs index eefaf3a5..37f986eb 100644 --- a/src-tauri/src/app_auto_updater.rs +++ b/src-tauri/src/app_auto_updater.rs @@ -2082,6 +2082,12 @@ pub async fn check_for_app_updates_manual() -> Result, Str .map_err(|e| format!("Failed to check for app updates: {e}")) } +// Global singleton instance +static APP_AUTO_UPDATER: std::sync::LazyLock = + std::sync::LazyLock::new(AppAutoUpdater::new); +static PENDING_INSTALLER_PATH: std::sync::LazyLock>> = + std::sync::LazyLock::new(|| std::sync::Mutex::new(None)); + #[cfg(test)] mod tests { use super::*; @@ -2518,9 +2524,3 @@ mod tests { let _rpm = AppAutoUpdater::is_rpm_repo_configured(); } } - -// Global singleton instance -lazy_static::lazy_static! { - static ref APP_AUTO_UPDATER: AppAutoUpdater = AppAutoUpdater::new(); - static ref PENDING_INSTALLER_PATH: std::sync::Mutex> = std::sync::Mutex::new(None); -} diff --git a/src-tauri/src/auto_updater.rs b/src-tauri/src/auto_updater.rs index f76885ce..96a6915d 100644 --- a/src-tauri/src/auto_updater.rs +++ b/src-tauri/src/auto_updater.rs @@ -649,6 +649,9 @@ pub async fn check_for_updates_with_progress(app_handle: tauri::AppHandle) { updater.check_for_updates_with_progress(&app_handle).await; } +// Global singleton instance +static AUTO_UPDATER: std::sync::LazyLock = std::sync::LazyLock::new(AutoUpdater::new); + #[cfg(test)] mod tests { use super::*; @@ -1000,8 +1003,3 @@ mod tests { ); } } - -// Global singleton instance -lazy_static::lazy_static! { - static ref AUTO_UPDATER: AutoUpdater = AutoUpdater::new(); -} diff --git a/src-tauri/src/browser.rs b/src-tauri/src/browser.rs index b09d7b2f..00187281 100644 --- a/src-tauri/src/browser.rs +++ b/src-tauri/src/browser.rs @@ -494,6 +494,10 @@ pub struct GithubAsset { pub updated_at: Option, } +// Global singleton instance +static BROWSER_FACTORY: std::sync::LazyLock = + std::sync::LazyLock::new(BrowserFactory::new); + #[cfg(test)] mod tests { use super::*; @@ -748,8 +752,3 @@ mod tests { ); } } - -// Global singleton instance -lazy_static::lazy_static! { - static ref BROWSER_FACTORY: BrowserFactory = BrowserFactory::new(); -} diff --git a/src-tauri/src/browser_runner.rs b/src-tauri/src/browser_runner.rs index d4dd6af4..ff8250d4 100644 --- a/src-tauri/src/browser_runner.rs +++ b/src-tauri/src/browser_runner.rs @@ -2004,6 +2004,10 @@ pub async fn open_url_with_profile( .await } +// Global singleton instance +static BROWSER_RUNNER: std::sync::LazyLock = + std::sync::LazyLock::new(BrowserRunner::new); + #[cfg(test)] mod tests { use super::*; @@ -2034,8 +2038,3 @@ mod tests { ); } } - -// Global singleton instance -lazy_static::lazy_static! { - static ref BROWSER_RUNNER: BrowserRunner = BrowserRunner::new(); -} diff --git a/src-tauri/src/browser_version_manager.rs b/src-tauri/src/browser_version_manager.rs index 4fbb76ba..3cd21113 100644 --- a/src-tauri/src/browser_version_manager.rs +++ b/src-tauri/src/browser_version_manager.rs @@ -554,6 +554,5 @@ pub async fn fetch_browser_versions_with_count( } // Global singleton instance -lazy_static::lazy_static! { - static ref BROWSER_VERSION_SERVICE: BrowserVersionManager = BrowserVersionManager::new(); -} +static BROWSER_VERSION_SERVICE: std::sync::LazyLock = + std::sync::LazyLock::new(BrowserVersionManager::new); diff --git a/src-tauri/src/cloud_auth.rs b/src-tauri/src/cloud_auth.rs index 9bda3eaf..b6ec6a32 100644 --- a/src-tauri/src/cloud_auth.rs +++ b/src-tauri/src/cloud_auth.rs @@ -1,5 +1,4 @@ use chrono::Utc; -use lazy_static::lazy_static; use reqwest::Client; use serde::{Deserialize, Serialize}; use sha2::{Digest, Sha256}; @@ -349,9 +348,8 @@ pub struct CloudAuthManager { wayfern_device_refusal: std::sync::Mutex>, } -lazy_static! { - pub static ref CLOUD_AUTH: CloudAuthManager = CloudAuthManager::new(); -} +pub static CLOUD_AUTH: std::sync::LazyLock = + std::sync::LazyLock::new(CloudAuthManager::new); impl CloudAuthManager { fn new() -> Self { diff --git a/src-tauri/src/commercial_license.rs b/src-tauri/src/commercial_license.rs index f0e08fa5..19a641b0 100644 --- a/src-tauri/src/commercial_license.rs +++ b/src-tauri/src/commercial_license.rs @@ -113,9 +113,7 @@ impl CommercialLicenseManager { } } -lazy_static::lazy_static! { - static ref COMMERCIAL_LICENSE_MANAGER: CommercialLicenseManager = CommercialLicenseManager; -} +static COMMERCIAL_LICENSE_MANAGER: CommercialLicenseManager = CommercialLicenseManager; #[cfg(test)] mod tests { diff --git a/src-tauri/src/default_browser.rs b/src-tauri/src/default_browser.rs index 9296c349..2b140af2 100644 --- a/src-tauri/src/default_browser.rs +++ b/src-tauri/src/default_browser.rs @@ -1054,9 +1054,8 @@ mod linux { } // Global singleton instance -lazy_static::lazy_static! { - static ref DEFAULT_BROWSER: DefaultBrowser = DefaultBrowser::new(); -} +static DEFAULT_BROWSER: std::sync::LazyLock = + std::sync::LazyLock::new(DefaultBrowser::new); #[command] pub async fn is_default_browser() -> Result { diff --git a/src-tauri/src/dns_blocklist.rs b/src-tauri/src/dns_blocklist.rs index 4be4d266..5c954510 100644 --- a/src-tauri/src/dns_blocklist.rs +++ b/src-tauri/src/dns_blocklist.rs @@ -281,12 +281,12 @@ pub struct BlocklistCacheStatus { pub struct BlocklistManager; -lazy_static::lazy_static! { - static ref HTTP_CLIENT: reqwest::Client = reqwest::Client::builder() +static HTTP_CLIENT: std::sync::LazyLock = std::sync::LazyLock::new(|| { + reqwest::Client::builder() .timeout(Duration::from_secs(60)) .build() - .expect("Failed to create HTTP client"); -} + .expect("Failed to create HTTP client") +}); impl BlocklistManager { pub fn instance() -> &'static BlocklistManager { @@ -628,9 +628,7 @@ impl BlocklistManager { } } -lazy_static::lazy_static! { - static ref BLOCKLIST_MANAGER: BlocklistManager = BlocklistManager; -} +static BLOCKLIST_MANAGER: BlocklistManager = BlocklistManager; // Tauri commands diff --git a/src-tauri/src/downloaded_browsers_registry.rs b/src-tauri/src/downloaded_browsers_registry.rs index 8c2d80cf..86b70972 100644 --- a/src-tauri/src/downloaded_browsers_registry.rs +++ b/src-tauri/src/downloaded_browsers_registry.rs @@ -1091,15 +1091,14 @@ impl DownloadedBrowsersRegistry { } // Global singleton instance -lazy_static::lazy_static! { - static ref DOWNLOADED_BROWSERS_REGISTRY: DownloadedBrowsersRegistry = { +static DOWNLOADED_BROWSERS_REGISTRY: std::sync::LazyLock = + std::sync::LazyLock::new(|| { let registry = DownloadedBrowsersRegistry::new(); if let Err(e) = registry.load() { log::warn!("Warning: Failed to load downloaded browsers registry: {e}"); } registry - }; -} + }); #[cfg(test)] mod tests { diff --git a/src-tauri/src/downloader.rs b/src-tauri/src/downloader.rs index 51cbd0e4..a6a29efb 100644 --- a/src-tauri/src/downloader.rs +++ b/src-tauri/src/downloader.rs @@ -21,12 +21,12 @@ const STREAM_IDLE_TIMEOUT: std::time::Duration = std::time::Duration::from_secs( const DOWNLOAD_USER_AGENT: &str = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36"; // Global state to track currently downloading browser-version pairs -lazy_static::lazy_static! { - static ref DOWNLOADING_BROWSERS: std::sync::Arc>> = - std::sync::Arc::new(Mutex::new(std::collections::HashSet::new())); - static ref DOWNLOAD_CANCELLATION_TOKENS: std::sync::Arc>> = - std::sync::Arc::new(Mutex::new(std::collections::HashMap::new())); -} +static DOWNLOADING_BROWSERS: std::sync::LazyLock< + std::sync::Arc>>, +> = std::sync::LazyLock::new(|| std::sync::Arc::new(Mutex::new(std::collections::HashSet::new()))); +static DOWNLOAD_CANCELLATION_TOKENS: std::sync::LazyLock< + std::sync::Arc>>, +> = std::sync::LazyLock::new(|| std::sync::Arc::new(Mutex::new(std::collections::HashMap::new()))); /// Clears a browser-version pair from the in-flight download maps on every /// exit path of `download_browser_full`. A leaked key would permanently report @@ -1191,6 +1191,9 @@ pub async fn cancel_download(browser_str: String, version: String) -> Result<(), } } +// Global singleton instance +static DOWNLOADER: std::sync::LazyLock = std::sync::LazyLock::new(Downloader::new); + #[cfg(test)] mod tests { use super::*; @@ -1513,8 +1516,3 @@ mod tests { clear_download_state_for_browser("chromium"); } } - -// Global singleton instance -lazy_static::lazy_static! { - static ref DOWNLOADER: Downloader = Downloader::new(); -} diff --git a/src-tauri/src/ephemeral_dirs.rs b/src-tauri/src/ephemeral_dirs.rs index ab717710..f5b55c30 100644 --- a/src-tauri/src/ephemeral_dirs.rs +++ b/src-tauri/src/ephemeral_dirs.rs @@ -29,9 +29,8 @@ struct EphemeralEntry { backing: EphemeralBacking, } -lazy_static::lazy_static! { - static ref EPHEMERAL_DIRS: Mutex> = Mutex::new(HashMap::new()); -} +static EPHEMERAL_DIRS: std::sync::LazyLock>> = + std::sync::LazyLock::new(|| Mutex::new(HashMap::new())); /// Test-only redirect for the ephemeral base. /// diff --git a/src-tauri/src/extension_manager.rs b/src-tauri/src/extension_manager.rs index e8cfa424..e77baec9 100644 --- a/src-tauri/src/extension_manager.rs +++ b/src-tauri/src/extension_manager.rs @@ -1776,9 +1776,8 @@ impl ExtensionManager { } // Global instance -lazy_static::lazy_static! { - pub static ref EXTENSION_MANAGER: Mutex = Mutex::new(ExtensionManager::new()); -} +pub static EXTENSION_MANAGER: std::sync::LazyLock> = + std::sync::LazyLock::new(|| Mutex::new(ExtensionManager::new())); // Tauri commands diff --git a/src-tauri/src/extraction.rs b/src-tauri/src/extraction.rs index b02e8991..07350d0c 100644 --- a/src-tauri/src/extraction.rs +++ b/src-tauri/src/extraction.rs @@ -1535,6 +1535,9 @@ impl Extractor { } } +// Global singleton instance +static EXTRACTOR: std::sync::LazyLock = std::sync::LazyLock::new(Extractor::new); + #[cfg(test)] mod tests { use super::*; @@ -2081,8 +2084,3 @@ mod tests { } } } - -// Global singleton instance -lazy_static::lazy_static! { - static ref EXTRACTOR: Extractor = Extractor::new(); -} diff --git a/src-tauri/src/fingerprint_consistency.rs b/src-tauri/src/fingerprint_consistency.rs index 85ddd85a..154c92b6 100644 --- a/src-tauri/src/fingerprint_consistency.rs +++ b/src-tauri/src/fingerprint_consistency.rs @@ -91,9 +91,8 @@ pub fn exit_cache_key(profile: &BrowserProfile) -> Option { None } -lazy_static::lazy_static! { - static ref EXIT_CACHE: Mutex> = Mutex::new(HashMap::new()); -} +static EXIT_CACHE: std::sync::LazyLock>> = + std::sync::LazyLock::new(|| Mutex::new(HashMap::new())); /// The dimensions an exit is compared on, in report order. pub const CHECKED_DIMENSIONS: [&str; 2] = ["timezone", "language"]; diff --git a/src-tauri/src/geoip_downloader.rs b/src-tauri/src/geoip_downloader.rs index 5ad15c18..382e5270 100644 --- a/src-tauri/src/geoip_downloader.rs +++ b/src-tauri/src/geoip_downloader.rs @@ -357,9 +357,8 @@ pub fn check_missing_geoip_database() -> Result { } // Global singleton instance -lazy_static::lazy_static! { - static ref GEOIP_DOWNLOADER: GeoIPDownloader = GeoIPDownloader::new(); -} +static GEOIP_DOWNLOADER: std::sync::LazyLock = + std::sync::LazyLock::new(GeoIPDownloader::new); #[cfg(test)] mod tests { diff --git a/src-tauri/src/group_manager.rs b/src-tauri/src/group_manager.rs index 21c889b6..1ca224f2 100644 --- a/src-tauri/src/group_manager.rs +++ b/src-tauri/src/group_manager.rs @@ -380,9 +380,8 @@ impl GroupManager { } // Global instance -lazy_static::lazy_static! { - pub static ref GROUP_MANAGER: Mutex = Mutex::new(GroupManager::new()); -} +pub static GROUP_MANAGER: std::sync::LazyLock> = + std::sync::LazyLock::new(|| Mutex::new(GroupManager::new())); // Helper function to get groups with counts pub fn get_groups_with_counts(profiles: &[crate::profile::BrowserProfile]) -> Vec { diff --git a/src-tauri/src/launch_gate.rs b/src-tauri/src/launch_gate.rs index e3ee9b63..4795ef41 100644 --- a/src-tauri/src/launch_gate.rs +++ b/src-tauri/src/launch_gate.rs @@ -56,9 +56,8 @@ struct PendingConsent { issued_at: u64, } -lazy_static::lazy_static! { - static ref CONSENTS: Mutex> = Mutex::new(HashMap::new()); -} +static CONSENTS: std::sync::LazyLock>> = + std::sync::LazyLock::new(|| Mutex::new(HashMap::new())); fn consents() -> std::sync::MutexGuard<'static, HashMap> { CONSENTS.lock().unwrap_or_else(|e| e.into_inner()) diff --git a/src-tauri/src/launch_gate_prefs.rs b/src-tauri/src/launch_gate_prefs.rs index 2c0fcb18..551c4e25 100644 --- a/src-tauri/src/launch_gate_prefs.rs +++ b/src-tauri/src/launch_gate_prefs.rs @@ -31,11 +31,9 @@ pub struct LaunchGatePrefs { pub vpn_extension_acks: HashMap>, } -lazy_static::lazy_static! { - /// Serializes read-modify-write so two concurrent acknowledgements in a bulk - /// run cannot clobber each other. - static ref PREFS_LOCK: Mutex<()> = Mutex::new(()); -} +/// Serializes read-modify-write so two concurrent acknowledgements in a bulk +/// run cannot clobber each other. +static PREFS_LOCK: std::sync::LazyLock> = std::sync::LazyLock::new(|| Mutex::new(())); fn prefs_file() -> PathBuf { crate::app_dirs::data_subdir().join("launch_gate_prefs.json") diff --git a/src-tauri/src/mcp_server.rs b/src-tauri/src/mcp_server.rs index a2704849..96a2606a 100644 --- a/src-tauri/src/mcp_server.rs +++ b/src-tauri/src/mcp_server.rs @@ -9739,9 +9739,7 @@ impl McpServer { } } -lazy_static::lazy_static! { - static ref MCP_SERVER: McpServer = McpServer::new(); -} +static MCP_SERVER: std::sync::LazyLock = std::sync::LazyLock::new(McpServer::new); #[cfg(test)] mod tests { diff --git a/src-tauri/src/profile/encryption.rs b/src-tauri/src/profile/encryption.rs index 4a39f172..1cff966e 100644 --- a/src-tauri/src/profile/encryption.rs +++ b/src-tauri/src/profile/encryption.rs @@ -30,11 +30,10 @@ const HMAC_FILENAME_LEN: usize = 32; const VERIFY_FILE_NAME: &str = ".donut-pw-verify"; const VERIFY_FILE_PATH: &str = "__donut_pw_verify__"; -lazy_static::lazy_static! { - /// In-memory cache of derived per-profile encryption keys, keyed by profile UUID. - /// Only populated while a profile is unlocked / running. Never persisted. - static ref KEY_CACHE: Mutex> = Mutex::new(HashMap::new()); -} +/// In-memory cache of derived per-profile encryption keys, keyed by profile UUID. +/// Only populated while a profile is unlocked / running. Never persisted. +static KEY_CACHE: std::sync::LazyLock>> = + std::sync::LazyLock::new(|| Mutex::new(HashMap::new())); #[derive(Debug, thiserror::Error)] pub enum PasswordError { diff --git a/src-tauri/src/profile/manager.rs b/src-tauri/src/profile/manager.rs index 317bb2b8..e44ae0d9 100644 --- a/src-tauri/src/profile/manager.rs +++ b/src-tauri/src/profile/manager.rs @@ -2599,6 +2599,5 @@ pub fn delete_profile( }) } -lazy_static::lazy_static! { - static ref PROFILE_MANAGER: ProfileManager = ProfileManager::new(); -} +static PROFILE_MANAGER: std::sync::LazyLock = + std::sync::LazyLock::new(ProfileManager::new); diff --git a/src-tauri/src/profile/password.rs b/src-tauri/src/profile/password.rs index 8f02ee00..520a13ba 100644 --- a/src-tauri/src/profile/password.rs +++ b/src-tauri/src/profile/password.rs @@ -40,29 +40,27 @@ fn err_internal(detail: impl std::fmt::Display) -> String { err_with("INTERNAL_ERROR", &[("detail", detail.to_string())]) } -lazy_static::lazy_static! { - /// Per-profile snapshot of plaintext file mtimes captured at launch time. - /// Used by `complete_after_quit` to skip re-encrypting unchanged files. - static ref LAUNCH_SNAPSHOTS: Mutex>> = - Mutex::new(HashMap::new()); - - /// Profile IDs whose ephemeral dir is currently populated and matches the - /// on-disk encrypted state, so we can skip re-decrypting on the next launch - /// when `keep_decrypted_profiles_in_ram` is enabled. - static ref POPULATED_EPHEMERAL: Mutex> = Mutex::new(HashSet::new()); - - /// Per-profile failed unlock attempt tracking for rate-limiting. - static ref FAILED_ATTEMPTS: Mutex> = Mutex::new(HashMap::new()); - - /// Per-profile lock serializing the whole check-lockout -> verify -> record - /// window. `check_lockout` and `record_failed_attempt` each take and release - /// `FAILED_ATTEMPTS` independently, with an Argon2 verification between them, - /// so without this a burst of concurrent attempts all read the same stale - /// count before any of them increments it and one lockout window admits as - /// many guesses as there are worker threads. - static ref ATTEMPT_LOCKS: Mutex>>> = - Mutex::new(HashMap::new()); -} +/// Per-profile snapshot of plaintext file mtimes captured at launch time. +/// Used by `complete_after_quit` to skip re-encrypting unchanged files. +static LAUNCH_SNAPSHOTS: std::sync::LazyLock< + Mutex>>, +> = std::sync::LazyLock::new(|| Mutex::new(HashMap::new())); +/// Profile IDs whose ephemeral dir is currently populated and matches the +/// on-disk encrypted state, so we can skip re-decrypting on the next launch +/// when `keep_decrypted_profiles_in_ram` is enabled. +static POPULATED_EPHEMERAL: std::sync::LazyLock>> = + std::sync::LazyLock::new(|| Mutex::new(HashSet::new())); +/// Per-profile failed unlock attempt tracking for rate-limiting. +static FAILED_ATTEMPTS: std::sync::LazyLock>> = + std::sync::LazyLock::new(|| Mutex::new(HashMap::new())); +/// Per-profile lock serializing the whole check-lockout -> verify -> record +/// window. `check_lockout` and `record_failed_attempt` each take and release +/// `FAILED_ATTEMPTS` independently, with an Argon2 verification between them, +/// so without this a burst of concurrent attempts all read the same stale +/// count before any of them increments it and one lockout window admits as +/// many guesses as there are worker threads. +static ATTEMPT_LOCKS: std::sync::LazyLock>>>> = + std::sync::LazyLock::new(|| Mutex::new(HashMap::new())); /// The attempt lock for one profile. The std map lock is released before the /// caller awaits the returned lock, so it is never held across an await. diff --git a/src-tauri/src/profile_importer.rs b/src-tauri/src/profile_importer.rs index 264bf021..53d9fd42 100644 --- a/src-tauri/src/profile_importer.rs +++ b/src-tauri/src/profile_importer.rs @@ -1206,9 +1206,8 @@ pub async fn import_browser_profiles( .map_err(error_to_code_string) } -lazy_static::lazy_static! { - static ref PROFILE_IMPORTER: ProfileImporter = ProfileImporter::new(); -} +static PROFILE_IMPORTER: std::sync::LazyLock = + std::sync::LazyLock::new(ProfileImporter::new); #[cfg(test)] mod tests { diff --git a/src-tauri/src/proxy_manager.rs b/src-tauri/src/proxy_manager.rs index 96ac9429..c3852cf7 100644 --- a/src-tauri/src/proxy_manager.rs +++ b/src-tauri/src/proxy_manager.rs @@ -2688,9 +2688,8 @@ impl ProxyManager { } // Create a singleton instance of the proxy manager -lazy_static::lazy_static! { - pub static ref PROXY_MANAGER: ProxyManager = ProxyManager::new(); -} +pub static PROXY_MANAGER: std::sync::LazyLock = + std::sync::LazyLock::new(ProxyManager::new); #[cfg(test)] mod tests { diff --git a/src-tauri/src/proxy_runner.rs b/src-tauri/src/proxy_runner.rs index a4ac98c5..760f0355 100644 --- a/src-tauri/src/proxy_runner.rs +++ b/src-tauri/src/proxy_runner.rs @@ -5,10 +5,9 @@ use crate::proxy_storage::{ use std::path::{Path, PathBuf}; use std::process::Stdio; use std::sync::atomic::{AtomicBool, Ordering}; -lazy_static::lazy_static! { - static ref PROXY_PROCESSES: std::sync::Mutex> = - std::sync::Mutex::new(std::collections::HashMap::new()); -} +static PROXY_PROCESSES: std::sync::LazyLock< + std::sync::Mutex>, +> = std::sync::LazyLock::new(|| std::sync::Mutex::new(std::collections::HashMap::new())); static SIDECAR_VERSION_VERIFIED: AtomicBool = AtomicBool::new(false); const RETAINED_PROXY_LOGS: usize = 20; diff --git a/src-tauri/src/recorder.rs b/src-tauri/src/recorder.rs index 9bc6340c..bbd1dbba 100644 --- a/src-tauri/src/recorder.rs +++ b/src-tauri/src/recorder.rs @@ -57,9 +57,8 @@ struct RecorderState { pending_is_password: bool, } -lazy_static::lazy_static! { - static ref RECORDER: Arc> = Arc::new(AsyncMutex::new(RecorderState::default())); -} +static RECORDER: std::sync::LazyLock>> = + std::sync::LazyLock::new(|| Arc::new(AsyncMutex::new(RecorderState::default()))); fn err(code: &str) -> String { json!({ "code": code }).to_string() diff --git a/src-tauri/src/settings_manager.rs b/src-tauri/src/settings_manager.rs index d57d5fe1..8580c2ec 100644 --- a/src-tauri/src/settings_manager.rs +++ b/src-tauri/src/settings_manager.rs @@ -1177,9 +1177,8 @@ pub fn get_system_info() -> SystemInfo { } // Global singleton instance -lazy_static::lazy_static! { - static ref SETTINGS_MANAGER: SettingsManager = SettingsManager::new(); -} +static SETTINGS_MANAGER: std::sync::LazyLock = + std::sync::LazyLock::new(SettingsManager::new); #[cfg(test)] mod tests { diff --git a/src-tauri/src/sync/engine.rs b/src-tauri/src/sync/engine.rs index 624c6163..31662542 100644 --- a/src-tauri/src/sync/engine.rs +++ b/src-tauri/src/sync/engine.rs @@ -39,10 +39,8 @@ impl ProfileSyncOutcome { } } -lazy_static::lazy_static! { - static ref SYNC_CANCEL_FLAGS: StdMutex>> = - StdMutex::new(HashMap::new()); -} +static SYNC_CANCEL_FLAGS: std::sync::LazyLock>>> = + std::sync::LazyLock::new(|| StdMutex::new(HashMap::new())); fn register_sync_cancel(profile_id: &str) -> Arc { let mut map = SYNC_CANCEL_FLAGS.lock().unwrap(); diff --git a/src-tauri/src/tag_manager.rs b/src-tauri/src/tag_manager.rs index 5b532079..49034f34 100644 --- a/src-tauri/src/tag_manager.rs +++ b/src-tauri/src/tag_manager.rs @@ -75,6 +75,5 @@ pub fn get_all_tags() -> Result, String> { .map_err(|e| format!("Failed to get tags: {e}")) } -lazy_static::lazy_static! { - pub static ref TAG_MANAGER: std::sync::Mutex = std::sync::Mutex::new(TagManager::new()); -} +pub static TAG_MANAGER: std::sync::LazyLock> = + std::sync::LazyLock::new(|| std::sync::Mutex::new(TagManager::new())); diff --git a/src-tauri/src/team_lock.rs b/src-tauri/src/team_lock.rs index 54cc93b8..0ae8584f 100644 --- a/src-tauri/src/team_lock.rs +++ b/src-tauri/src/team_lock.rs @@ -1,4 +1,3 @@ -use lazy_static::lazy_static; use reqwest::Client; use serde::{Deserialize, Serialize}; use std::collections::HashMap; @@ -37,9 +36,8 @@ pub struct ProfileLockManager { connected: Mutex, } -lazy_static! { - pub static ref PROFILE_LOCK: ProfileLockManager = ProfileLockManager::new(); -} +pub static PROFILE_LOCK: std::sync::LazyLock = + std::sync::LazyLock::new(ProfileLockManager::new); // Keep backward compatibility alias pub use PROFILE_LOCK as TEAM_LOCK; diff --git a/src-tauri/src/vpn/mod.rs b/src-tauri/src/vpn/mod.rs index 710adb24..b27b887d 100644 --- a/src-tauri/src/vpn/mod.rs +++ b/src-tauri/src/vpn/mod.rs @@ -19,8 +19,9 @@ pub use storage::VpnStorage; pub use tunnel::{TunnelManager, VpnTunnel}; pub use wireguard::WireGuardTunnel; -use once_cell::sync::Lazy; +use std::sync::LazyLock; use std::sync::Mutex; /// Global VPN storage instance -pub static VPN_STORAGE: Lazy> = Lazy::new(|| Mutex::new(VpnStorage::new())); +pub static VPN_STORAGE: LazyLock> = + LazyLock::new(|| Mutex::new(VpnStorage::new())); diff --git a/src-tauri/src/wayfern_manager.rs b/src-tauri/src/wayfern_manager.rs index f41a9646..4f9f1530 100644 --- a/src-tauri/src/wayfern_manager.rs +++ b/src-tauri/src/wayfern_manager.rs @@ -3442,9 +3442,8 @@ fn kill_browser_process(pid: u32) { force_kill_process(pid); } -lazy_static::lazy_static! { - static ref WAYFERN_MANAGER: WayfernManager = WayfernManager::new(); -} +static WAYFERN_MANAGER: std::sync::LazyLock = + std::sync::LazyLock::new(WayfernManager::new); /// Deterministically derive a pleasant, distinct window frame color from a /// profile id so concurrent profile windows are visually distinguishable even diff --git a/src-tauri/src/wayfern_terms.rs b/src-tauri/src/wayfern_terms.rs index 07895cf7..9596a9f7 100644 --- a/src-tauri/src/wayfern_terms.rs +++ b/src-tauri/src/wayfern_terms.rs @@ -192,9 +192,8 @@ impl WayfernTermsManager { } } -lazy_static::lazy_static! { - static ref WAYFERN_TERMS_MANAGER: WayfernTermsManager = WayfernTermsManager::new(); -} +static WAYFERN_TERMS_MANAGER: std::sync::LazyLock = + std::sync::LazyLock::new(WayfernTermsManager::new); #[cfg(test)] mod tests { diff --git a/src-tauri/src/window_decorations.rs b/src-tauri/src/window_decorations.rs index 57705f01..1ebea044 100644 --- a/src-tauri/src/window_decorations.rs +++ b/src-tauri/src/window_decorations.rs @@ -98,9 +98,8 @@ pub fn use_client_side_decorations() -> bool { mod imp { use std::sync::Mutex; - lazy_static::lazy_static! { - static ref LAYOUT: Mutex> = Mutex::new(None); - } + static LAYOUT: std::sync::LazyLock>> = + std::sync::LazyLock::new(|| Mutex::new(None)); fn store(layout: Option) { if let Ok(mut slot) = LAYOUT.lock() { diff --git a/src/generated/licenses.json b/src/generated/licenses.json index 0e146f98..ba211433 100644 --- a/src/generated/licenses.json +++ b/src/generated/licenses.json @@ -1815,10 +1815,6 @@ "name": "kurbo", "license": "Apache-2.0 OR MIT" }, - { - "name": "lazy_static", - "license": "Apache-2.0 OR MIT" - }, { "name": "lebe", "license": "BSD-3-Clause"