diff --git a/packages/core/src/scopes.rs b/packages/core/src/scopes.rs index 2e4bf3651..2b9f32f8d 100644 --- a/packages/core/src/scopes.rs +++ b/packages/core/src/scopes.rs @@ -11,7 +11,7 @@ use crate::{ }; use bumpalo::{boxed::Box as BumpBox, Bump}; use bumpslab::{BumpSlab, Slot}; -use rustc_hash::{FxHashMap, FxHashSet}; +use rustc_hash::FxHashSet; use slab::{Slab, VacantEntry}; use std::{ any::{Any, TypeId}, @@ -173,7 +173,7 @@ pub struct ScopeState { pub(crate) hooks: RefCell>>>, pub(crate) hook_idx: Cell, - pub(crate) shared_contexts: RefCell>>, + pub(crate) shared_contexts: RefCell)>>, pub(crate) tasks: Rc, pub(crate) spawned_tasks: RefCell>, @@ -347,7 +347,9 @@ impl<'src> ScopeState { pub fn has_context(&self) -> Option { self.shared_contexts .borrow() - .get(&TypeId::of::())? + .iter() + .find(|(k, _)| *k == TypeId::of::()) + .map(|(_, v)| v)? .downcast_ref::() .cloned() } @@ -364,8 +366,13 @@ impl<'src> ScopeState { while let Some(parent_ptr) = search_parent { // safety: all parent pointers are valid thanks to the bump arena let parent = unsafe { &*parent_ptr }; - if let Some(shared) = parent.shared_contexts.borrow().get(&TypeId::of::()) { - return shared.downcast_ref::().cloned(); + if let Some(shared) = parent + .shared_contexts + .borrow() + .iter() + .find(|(k, _)| *k == TypeId::of::()) + { + return shared.1.downcast_ref::().cloned(); } search_parent = parent.parent; } @@ -394,13 +401,21 @@ impl<'src> ScopeState { /// } /// ``` pub fn provide_context(&self, value: T) -> T { - let value2 = value.clone(); + let mut contexts = self.shared_contexts.borrow_mut(); - self.shared_contexts - .borrow_mut() - .insert(TypeId::of::(), Box::new(value)); + // If the context exists, swap it out for the new value + for ctx in contexts.iter_mut() { + // Swap the ptr directly + if let Some(ctx) = ctx.1.downcast_mut::() { + std::mem::swap(ctx, &mut value.clone()); + return value; + } + } - value2 + // Else, just push it + contexts.push((TypeId::of::(), Box::new(value.clone()))); + + value } /// Pushes the future onto the poll queue to be polled after the component renders.