dioxus_core/
generational_box.rs1use std::{
6 any::{Any, TypeId},
7 cell::RefCell,
8};
9
10use generational_box::{AnyStorage, Owner, SyncStorage, UnsyncStorage};
11
12use crate::{innerlude::current_scope_id, Runtime, ScopeId};
13
14pub fn with_owner<S: AnyStorage, F: FnOnce() -> R, R>(owner: Owner<S>, f: F) -> R {
18 let old_owner = set_owner(Some(owner));
19 let result = f();
20 set_owner(old_owner);
21 result
22}
23
24fn set_owner<S: AnyStorage>(owner: Option<Owner<S>>) -> Option<Owner<S>> {
26 let id = TypeId::of::<S>();
27 if id == TypeId::of::<SyncStorage>() {
28 SYNC_OWNER.with(|cell| {
29 std::mem::replace(
30 &mut *cell.borrow_mut(),
31 owner.map(|owner| {
32 *(Box::new(owner) as Box<dyn Any>)
33 .downcast::<Owner<SyncStorage>>()
34 .unwrap()
35 }),
36 )
37 .map(|owner| *(Box::new(owner) as Box<dyn Any>).downcast().unwrap())
38 })
39 } else {
40 UNSYNC_OWNER.with(|cell| {
41 std::mem::replace(
42 &mut *cell.borrow_mut(),
43 owner.map(|owner| {
44 *(Box::new(owner) as Box<dyn Any>)
45 .downcast::<Owner<UnsyncStorage>>()
46 .unwrap()
47 }),
48 )
49 .map(|owner| *(Box::new(owner) as Box<dyn Any>).downcast().unwrap())
50 })
51 }
52}
53
54thread_local! {
55 static SYNC_OWNER: RefCell<Option<Owner<SyncStorage>>> = const { RefCell::new(None) };
56 static UNSYNC_OWNER: RefCell<Option<Owner<UnsyncStorage>>> = const { RefCell::new(None) };
57}
58
59pub fn current_owner<S: AnyStorage>() -> Owner<S> {
63 let id = TypeId::of::<S>();
64 let override_owner = if id == TypeId::of::<SyncStorage>() {
65 SYNC_OWNER.with(|cell| {
66 let owner = cell.borrow();
67
68 owner.clone().map(|owner| {
69 *(Box::new(owner) as Box<dyn Any>)
70 .downcast::<Owner<S>>()
71 .unwrap()
72 })
73 })
74 } else {
75 UNSYNC_OWNER.with(|cell| {
76 cell.borrow().clone().map(|owner| {
77 *(Box::new(owner) as Box<dyn Any>)
78 .downcast::<Owner<S>>()
79 .unwrap()
80 })
81 })
82 };
83 if let Some(owner) = override_owner {
84 return owner;
85 }
86
87 current_scope_id().expect("in a virtual dom").owner()
89}
90
91impl ScopeId {
92 #[track_caller]
94 pub fn owner<S: AnyStorage>(self) -> Owner<S> {
95 Runtime::with_scope(self, |cx| cx.owner::<S>()).unwrap_or_else(|e| panic!("{}", e))
96 }
97}