diff --git a/.changes/core-unmanage.md b/.changes/core-unmanage.md new file mode 100644 index 000000000..d84ba49d0 --- /dev/null +++ b/.changes/core-unmanage.md @@ -0,0 +1,6 @@ +--- +"tauri": "patch:feat" +--- + +Add `Manager::unmanage` to remove previously managed state. + diff --git a/Cargo.lock b/Cargo.lock index 1dffea238..e2e0f1a88 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -875,7 +875,7 @@ dependencies = [ "toml 0.8.19", "ureq", "which 6.0.3", - "windows 0.58.0", + "windows", "x509-certificate", ] @@ -2068,8 +2068,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "531e46835a22af56d1e3b66f04844bed63158bc094a628bec1d321d9b4c44bf2" dependencies = [ "bit-set", - "regex-automata 0.4.7", - "regex-syntax 0.8.4", + "regex-automata", + "regex-syntax", ] [[package]] @@ -2496,19 +2496,6 @@ dependencies = [ "x11", ] -[[package]] -name = "generator" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc16584ff22b460a382b7feec54b23d2908d858152e5739a120b949293bd74e" -dependencies = [ - "cc", - "libc", - "log", - "rustversion", - "windows 0.48.0", -] - [[package]] name = "generic-array" version = "0.14.7" @@ -2664,8 +2651,8 @@ dependencies = [ "aho-corasick", "bstr", "log", - "regex-automata 0.4.7", - "regex-syntax 0.8.4", + "regex-automata", + "regex-syntax", ] [[package]] @@ -3111,7 +3098,7 @@ dependencies = [ "globset", "log", "memchr", - "regex-automata 0.4.7", + "regex-automata", "same-file", "walkdir", "winapi-util", @@ -3858,21 +3845,6 @@ dependencies = [ "value-bag", ] -[[package]] -name = "loom" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff50ecb28bb86013e935fb6683ab1f6d3a20016f123c76fd4c27470076ac30f5" -dependencies = [ - "cfg-if", - "generator", - "scoped-tls", - "serde", - "serde_json", - "tracing", - "tracing-subscriber", -] - [[package]] name = "loop9" version = "0.1.5" @@ -3935,15 +3907,6 @@ dependencies = [ "tendril", ] -[[package]] -name = "matchers" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" -dependencies = [ - "regex-automata 0.1.10", -] - [[package]] name = "matches" version = "0.1.10" @@ -4321,16 +4284,6 @@ dependencies = [ "notify", ] -[[package]] -name = "nu-ansi-term" -version = "0.46.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" -dependencies = [ - "overload", - "winapi", -] - [[package]] name = "num" version = "0.4.3" @@ -4750,12 +4703,6 @@ dependencies = [ "windows-sys 0.59.0", ] -[[package]] -name = "overload" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" - [[package]] name = "owo-colors" version = "4.0.0" @@ -5507,7 +5454,7 @@ dependencies = [ "rand 0.8.5", "rand_chacha 0.3.1", "rand_xorshift", - "regex-syntax 0.8.4", + "regex-syntax", "rusty-fork", "tempfile", "unarray", @@ -5841,17 +5788,8 @@ checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.7", - "regex-syntax 0.8.4", -] - -[[package]] -name = "regex-automata" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" -dependencies = [ - "regex-syntax 0.6.29", + "regex-automata", + "regex-syntax", ] [[package]] @@ -5862,15 +5800,9 @@ checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.4", + "regex-syntax", ] -[[package]] -name = "regex-syntax" -version = "0.6.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" - [[package]] name = "regex-syntax" version = "0.8.4" @@ -6323,12 +6255,6 @@ dependencies = [ "syn 2.0.77", ] -[[package]] -name = "scoped-tls" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" - [[package]] name = "scopeguard" version = "1.2.0" @@ -6703,15 +6629,6 @@ dependencies = [ "keccak", ] -[[package]] -name = "sharded-slab" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" -dependencies = [ - "lazy_static", -] - [[package]] name = "shared_child" version = "1.0.1" @@ -6987,15 +6904,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" -[[package]] -name = "state" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b8c4a4445d81357df8b1a650d0d0d6fbbbfe99d064aa5e02f3e4022061476d8" -dependencies = [ - "loom", -] - [[package]] name = "static_assertions" version = "1.1.0" @@ -7274,7 +7182,7 @@ dependencies = [ "tao-macros", "unicode-segmentation", "url", - "windows 0.58.0", + "windows", "windows-core 0.58.0", "windows-version", "x11-dl", @@ -7354,7 +7262,6 @@ dependencies = [ "serde_repr", "serialize-to-javascript", "specta", - "state", "swift-rs", "tauri", "tauri-build", @@ -7372,7 +7279,7 @@ dependencies = [ "webkit2gtk", "webview2-com", "window-vibrancy", - "windows 0.58.0", + "windows", ] [[package]] @@ -7701,7 +7608,7 @@ dependencies = [ "tauri-utils 2.0.0-rc.12", "thiserror", "url", - "windows 0.58.0", + "windows", ] [[package]] @@ -7725,7 +7632,7 @@ dependencies = [ "url", "webkit2gtk", "webview2-com", - "windows 0.58.0", + "windows", "wry", ] @@ -7949,16 +7856,6 @@ dependencies = [ "syn 2.0.77", ] -[[package]] -name = "thread_local" -version = "1.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" -dependencies = [ - "cfg-if", - "once_cell", -] - [[package]] name = "tiff" version = "0.9.1" @@ -8274,36 +8171,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", - "valuable", -] - -[[package]] -name = "tracing-log" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" -dependencies = [ - "log", - "once_cell", - "tracing-core", -] - -[[package]] -name = "tracing-subscriber" -version = "0.3.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" -dependencies = [ - "matchers", - "nu-ansi-term", - "once_cell", - "regex", - "sharded-slab", - "smallvec", - "thread_local", - "tracing", - "tracing-core", - "tracing-log", ] [[package]] @@ -8643,12 +8510,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "valuable" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" - [[package]] name = "value-bag" version = "1.9.0" @@ -8920,7 +8781,7 @@ checksum = "6f61ff3d9d0ee4efcb461b14eb3acfda2702d10dc329f339303fc3e57215ae2c" dependencies = [ "webview2-com-macros", "webview2-com-sys", - "windows 0.58.0", + "windows", "windows-core 0.58.0", "windows-implement", "windows-interface", @@ -8944,7 +8805,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3a3e2eeb58f82361c93f9777014668eb3d07e7d174ee4c819575a9208011886" dependencies = [ "thiserror", - "windows 0.58.0", + "windows", "windows-core 0.58.0", ] @@ -9022,15 +8883,6 @@ dependencies = [ "windows-version", ] -[[package]] -name = "windows" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" -dependencies = [ - "windows-targets 0.48.5", -] - [[package]] name = "windows" version = "0.58.0" @@ -9482,7 +9334,7 @@ dependencies = [ "webkit2gtk", "webkit2gtk-sys", "webview2-com", - "windows 0.58.0", + "windows", "windows-core 0.58.0", "windows-version", "x11-dl", diff --git a/crates/tauri/Cargo.toml b/crates/tauri/Cargo.toml index 5f4ea2c0e..10b982f6e 100644 --- a/crates/tauri/Cargo.toml +++ b/crates/tauri/Cargo.toml @@ -65,7 +65,6 @@ tauri-utils = { version = "2.0.0-rc.12", features = [ tauri-runtime-wry = { version = "2.0.0-rc.13", path = "../tauri-runtime-wry", optional = true } getrandom = "0.2" serde_repr = "0.1" -state = "0.6" http = "1.1" dirs = "5" percent-encoding = "2.3" diff --git a/crates/tauri/src/ipc/authority.rs b/crates/tauri/src/ipc/authority.rs index a15cfb017..19eda03c9 100644 --- a/crates/tauri/src/ipc/authority.rs +++ b/crates/tauri/src/ipc/authority.rs @@ -8,7 +8,6 @@ use std::sync::Arc; use serde::de::DeserializeOwned; use serde::Serialize; -use state::TypeMap; use tauri_utils::acl::{ capability::{Capability, CapabilityFile, PermissionEntry}, @@ -24,7 +23,7 @@ use tauri_utils::platform::Target; use url::Url; use crate::{ipc::InvokeError, sealed::ManagerBase, Runtime}; -use crate::{AppHandle, Manager}; +use crate::{AppHandle, Manager, StateManager}; use super::{CommandArg, CommandItem}; @@ -232,7 +231,7 @@ impl RuntimeAuthority { let command_cache = resolved_acl .command_scope .keys() - .map(|key| (*key, ::new())) + .map(|key| (*key, StateManager::new())) .collect(); Self { acl, @@ -242,7 +241,7 @@ impl RuntimeAuthority { command_scope: resolved_acl.command_scope, global_scope: resolved_acl.global_scope, command_cache, - global_scope_cache: Default::default(), + global_scope_cache: StateManager::new(), }, } } @@ -297,7 +296,7 @@ impl RuntimeAuthority { global_scope_entry.allow.extend(global_scope.allow); global_scope_entry.deny.extend(global_scope.deny); - self.scope_manager.global_scope_cache = Default::default(); + self.scope_manager.global_scope_cache = StateManager::new(); } // denied commands @@ -708,8 +707,8 @@ impl<'a, R: Runtime, T: ScopeObject> CommandArg<'a, R> for GlobalScope { pub struct ScopeManager { command_scope: BTreeMap, global_scope: BTreeMap, - command_cache: BTreeMap, - global_scope_cache: TypeMap![Send + Sync], + command_cache: BTreeMap, + global_scope_cache: StateManager, } /// Marks a type as a scope object. @@ -737,7 +736,7 @@ impl ScopeManager { key: &str, ) -> crate::Result> { match self.global_scope_cache.try_get::>() { - Some(cached) => Ok(cached.clone()), + Some(cached) => Ok(cached.inner().clone()), None => { let mut allow = Vec::new(); let mut deny = Vec::new(); @@ -774,7 +773,7 @@ impl ScopeManager { ) -> crate::Result> { let cache = self.command_cache.get(key).unwrap(); match cache.try_get::>() { - Some(cached) => Ok(cached.clone()), + Some(cached) => Ok(cached.inner().clone()), None => { let resolved_scope = self .command_scope diff --git a/crates/tauri/src/lib.rs b/crates/tauri/src/lib.rs index a4779df7d..e9d11696a 100644 --- a/crates/tauri/src/lib.rs +++ b/crates/tauri/src/lib.rs @@ -699,6 +699,14 @@ pub trait Manager: sealed::ManagerBase { self.manager().state().set(state) } + /// Removes the state managed by the application for T. Returns `true` if it was actually removed + fn unmanage(&self) -> bool + where + T: Send + Sync + 'static, + { + self.manager().state().unmanage::() + } + /// Retrieves the managed state for the type `T`. /// /// # Panics diff --git a/crates/tauri/src/state.rs b/crates/tauri/src/state.rs index 843e55329..5a1dafec5 100644 --- a/crates/tauri/src/state.rs +++ b/crates/tauri/src/state.rs @@ -2,11 +2,18 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: MIT +use std::{ + any::{Any, TypeId}, + cell::UnsafeCell, + collections::HashMap, + hash::BuildHasherDefault, + sync::Mutex, +}; + use crate::{ ipc::{CommandArg, CommandItem, InvokeError}, Runtime, }; -use state::TypeMap; /// A guard for a state value. /// @@ -56,31 +63,98 @@ impl<'r, 'de: 'r, T: Send + Sync + 'static, R: Runtime> CommandArg<'de, R> for S } } +// Taken from: https://github.com/SergioBenitez/state/blob/556c1b94db8ce8427a0e72de7983ab5a9af4cc41/src/ident_hash.rs +// This is a _super_ stupid hash. It just uses its input as the hash value. This +// hash is meant to be used _only_ for "prehashed" values. In particular, we use +// this so that hashing a TypeId is essentially a noop. This is because TypeIds +// are already unique integers. +#[derive(Default)] +struct IdentHash(u64); + +impl std::hash::Hasher for IdentHash { + fn finish(&self) -> u64 { + self.0 + } + + fn write(&mut self, bytes: &[u8]) { + for byte in bytes { + self.write_u8(*byte); + } + } + + fn write_u8(&mut self, i: u8) { + self.0 = (self.0 << 8) | (i as u64); + } + + fn write_u64(&mut self, i: u64) { + self.0 = i; + } +} + +type TypeIdMap = HashMap, BuildHasherDefault>; + /// The Tauri state manager. #[derive(Debug)] -pub struct StateManager(pub(crate) TypeMap![Send + Sync]); +pub struct StateManager { + map: Mutex>, +} + +// SAFETY: data is accessed behind a lock +unsafe impl Sync for StateManager {} +unsafe impl Send for StateManager {} impl StateManager { pub(crate) fn new() -> Self { - Self(::new()) + Self { + map: Default::default(), + } + } + + fn with_map_ref<'a, F: FnOnce(&'a TypeIdMap) -> R, R>(&'a self, f: F) -> R { + let map = self.map.lock().unwrap(); + let map = map.get(); + // SAFETY: safe to access since we are holding a lock + f(unsafe { &*map }) + } + + fn with_map_mut R, R>(&self, f: F) -> R { + let mut map = self.map.lock().unwrap(); + let map = map.get_mut(); + f(map) } pub(crate) fn set(&self, state: T) -> bool { - self.0.set(state) + self.with_map_mut(|map| { + let type_id = TypeId::of::(); + let already_set = map.contains_key(&type_id); + if !already_set { + map.insert(type_id, Box::new(state) as Box); + } + !already_set + }) + } + + pub(crate) fn unmanage(&self) -> bool { + self.with_map_mut(|map| { + let type_id = TypeId::of::(); + map.remove(&type_id).is_some() + }) } /// Gets the state associated with the specified type. pub fn get(&self) -> State<'_, T> { - State( - self - .0 - .try_get() - .expect("state: get() called before set() for given type"), - ) + self + .try_get() + .expect("state: get() when given type is not managed") } /// Gets the state associated with the specified type. pub fn try_get(&self) -> Option> { - self.0.try_get().map(State) + self.with_map_ref(|map| { + map + .get(&TypeId::of::()) + .and_then(|ptr| ptr.downcast_ref::()) + .map(State) + }) } }