11use serde:: { Deserialize , Serialize } ;
2- use std:: any:: Any ;
2+ use std:: any:: { Any , TypeId } ;
33use std:: collections:: hash_map:: DefaultHasher ;
4+ use std:: collections:: HashMap ;
45use std:: fmt:: Debug ;
56use std:: hash:: { Hash , Hasher } ;
7+ use std:: sync:: Arc ;
68
79use crate :: core:: event_registry:: { EventCallback , EventRegistry } ;
810use crate :: hooks:: hook_store:: HookStore ;
@@ -112,6 +114,9 @@ impl Element {
112114 }
113115}
114116
117+ /// A snapshot of a view's context map, cheaply clonable via `Arc`.
118+ pub type ContextSnapshot = HashMap < TypeId , Arc < dyn Any + Send + Sync > > ;
119+
115120/// A stateful component that produces an element tree.
116121pub trait View : Send + Sync + ' static {
117122 /// Build the element tree for this view.
@@ -134,9 +139,9 @@ pub struct BuildContext<'a> {
134139 widget_id_counter : usize ,
135140 /// Child views registered during this build via `child_view()`.
136141 pub ( crate ) child_views : Vec < ChildViewEntry > ,
137- /// Access to ancestor HookStores for context lookup (read-only view) .
138- /// Maps ViewId -> reference to ancestor contexts .
139- pub ( crate ) ancestor_contexts : Vec < ( ViewId , * const HookStore ) > ,
142+ /// Cloned snapshots of ancestor context maps for safe context lookup.
143+ /// Each entry is a ( ViewId, context map) pair, cheaply cloned via Arc .
144+ pub ( crate ) ancestor_contexts : Vec < ( ViewId , ContextSnapshot ) > ,
140145}
141146
142147/// Cleanup function returned by an effect callback.
@@ -292,11 +297,12 @@ impl<'a> BuildContext<'a> {
292297 let mut child_ctx =
293298 BuildContext :: with_view_id ( & mut owned_store, self . rebuild_tx . clone ( ) , child_view_id) ;
294299 child_ctx. reset ( ) ;
295- // Set ancestor contexts: current view's store + all ancestors above
300+ // Set ancestor contexts: current view's store + all ancestors above.
301+ // Clone via Arc::clone per entry (cheap reference count bump).
296302 child_ctx. ancestor_contexts = self . ancestor_contexts . clone ( ) ;
297303 child_ctx
298304 . ancestor_contexts
299- . push ( ( self . current_view_id , self . store as * const HookStore ) ) ;
305+ . push ( ( self . current_view_id , self . store . contexts . clone ( ) ) ) ;
300306
301307 let mut element = view. build ( & mut child_ctx) ;
302308 element. assign_ids ( & mut child_ctx) ;
@@ -329,12 +335,9 @@ impl<'a> BuildContext<'a> {
329335 if let Some ( val) = self . store . contexts . get ( & type_id) {
330336 return Some ( val. as_ref ( ) ) ;
331337 }
332- // Walk ancestors from nearest to farthest
333- for ( _view_id, store_ptr) in self . ancestor_contexts . iter ( ) . rev ( ) {
334- // SAFETY: ancestor_contexts are set up during build traversal and the
335- // stores remain valid for the duration of the build
336- let store = unsafe { & * * store_ptr } ;
337- if let Some ( val) = store. contexts . get ( & type_id) {
338+ // Walk ancestors from nearest to farthest (safe — no raw pointers)
339+ for ( _view_id, contexts) in self . ancestor_contexts . iter ( ) . rev ( ) {
340+ if let Some ( val) = contexts. get ( & type_id) {
338341 return Some ( val. as_ref ( ) ) ;
339342 }
340343 }
0 commit comments