mirror of
https://github.com/leptos-rs/leptos.git
synced 2025-12-27 09:54:41 -05:00
feat: allow joining two context trees
This commit is contained in:
@@ -167,6 +167,7 @@ impl Owner {
|
||||
.map(|parent| parent.read().or_poisoned().arena.clone())
|
||||
.unwrap_or_default(),
|
||||
paused: false,
|
||||
joined_owners: Vec::new(),
|
||||
})),
|
||||
#[cfg(feature = "hydration")]
|
||||
shared_context,
|
||||
@@ -201,6 +202,7 @@ impl Owner {
|
||||
#[cfg(feature = "sandboxed-arenas")]
|
||||
arena: Default::default(),
|
||||
paused: false,
|
||||
joined_owners: Vec::new(),
|
||||
})),
|
||||
#[cfg(feature = "hydration")]
|
||||
shared_context,
|
||||
@@ -226,6 +228,7 @@ impl Owner {
|
||||
#[cfg(feature = "sandboxed-arenas")]
|
||||
arena,
|
||||
paused,
|
||||
joined_owners: Vec::new(),
|
||||
})),
|
||||
#[cfg(feature = "hydration")]
|
||||
shared_context: self.shared_context.clone(),
|
||||
@@ -455,6 +458,7 @@ pub(crate) struct OwnerInner {
|
||||
#[cfg(feature = "sandboxed-arenas")]
|
||||
arena: Arc<RwLock<ArenaMap>>,
|
||||
paused: bool,
|
||||
joined_owners: Vec<Owner>,
|
||||
}
|
||||
|
||||
impl Debug for OwnerInner {
|
||||
|
||||
@@ -3,9 +3,19 @@ use or_poisoned::OrPoisoned;
|
||||
use std::{
|
||||
any::{Any, TypeId},
|
||||
collections::VecDeque,
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
impl Owner {
|
||||
#[doc(hidden)]
|
||||
pub fn join_contexts(&self, other: &Owner) {
|
||||
self.inner
|
||||
.write()
|
||||
.or_poisoned()
|
||||
.joined_owners
|
||||
.push(other.clone());
|
||||
}
|
||||
|
||||
fn provide_context<T: Send + Sync + 'static>(&self, value: T) {
|
||||
self.inner
|
||||
.write()
|
||||
@@ -26,17 +36,26 @@ impl Owner {
|
||||
if let Some(context) = contexts.remove(&ty) {
|
||||
context.downcast::<T>().ok().map(|n| *n)
|
||||
} else {
|
||||
while let Some(ref this_parent) = parent.clone() {
|
||||
let mut this_parent = this_parent.write().or_poisoned();
|
||||
let contexts = &mut this_parent.contexts;
|
||||
let value = contexts.remove(&ty);
|
||||
let downcast =
|
||||
value.and_then(|context| context.downcast::<T>().ok());
|
||||
if let Some(value) = downcast {
|
||||
return Some(*value);
|
||||
} else {
|
||||
parent =
|
||||
this_parent.parent.as_ref().and_then(|p| p.upgrade());
|
||||
let parent = inner.parent.as_ref().and_then(|p| p.upgrade());
|
||||
let joined = inner
|
||||
.joined_owners
|
||||
.iter()
|
||||
.map(|owner| Arc::clone(&owner.inner));
|
||||
for parent in parent.into_iter().chain(joined) {
|
||||
while let Some(ref this_parent) = parent.clone() {
|
||||
let mut this_parent = this_parent.write().or_poisoned();
|
||||
let contexts = &mut this_parent.contexts;
|
||||
let value = contexts.remove(&ty);
|
||||
let downcast =
|
||||
value.and_then(|context| context.downcast::<T>().ok());
|
||||
if let Some(value) = downcast {
|
||||
return Some(*value);
|
||||
} else {
|
||||
parent = this_parent
|
||||
.parent
|
||||
.as_ref()
|
||||
.and_then(|p| p.upgrade());
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
@@ -49,22 +68,31 @@ impl Owner {
|
||||
) -> Option<R> {
|
||||
let ty = TypeId::of::<T>();
|
||||
let inner = self.inner.read().or_poisoned();
|
||||
let mut parent = inner.parent.as_ref().and_then(|p| p.upgrade());
|
||||
let contexts = &inner.contexts;
|
||||
let reference = if let Some(context) = contexts.get(&ty) {
|
||||
context.downcast_ref::<T>()
|
||||
} else {
|
||||
while let Some(ref this_parent) = parent.clone() {
|
||||
let this_parent = this_parent.read().or_poisoned();
|
||||
let contexts = &this_parent.contexts;
|
||||
let value = contexts.get(&ty);
|
||||
let downcast =
|
||||
value.and_then(|context| context.downcast_ref::<T>());
|
||||
if let Some(value) = downcast {
|
||||
return Some(cb(value));
|
||||
} else {
|
||||
parent =
|
||||
this_parent.parent.as_ref().and_then(|p| p.upgrade());
|
||||
let parent = inner.parent.as_ref().and_then(|p| p.upgrade());
|
||||
let joined = inner
|
||||
.joined_owners
|
||||
.iter()
|
||||
.map(|owner| Arc::clone(&owner.inner));
|
||||
for parent in parent.into_iter().chain(joined) {
|
||||
let mut parent = Some(parent);
|
||||
while let Some(ref this_parent) = parent.clone() {
|
||||
let this_parent = this_parent.read().or_poisoned();
|
||||
let contexts = &this_parent.contexts;
|
||||
let value = contexts.get(&ty);
|
||||
let downcast =
|
||||
value.and_then(|context| context.downcast_ref::<T>());
|
||||
if let Some(value) = downcast {
|
||||
return Some(cb(value));
|
||||
} else {
|
||||
parent = this_parent
|
||||
.parent
|
||||
.as_ref()
|
||||
.and_then(|p| p.upgrade());
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
@@ -83,17 +111,26 @@ impl Owner {
|
||||
let reference = if let Some(context) = contexts.get_mut(&ty) {
|
||||
context.downcast_mut::<T>()
|
||||
} else {
|
||||
while let Some(ref this_parent) = parent.clone() {
|
||||
let mut this_parent = this_parent.write().or_poisoned();
|
||||
let contexts = &mut this_parent.contexts;
|
||||
let value = contexts.get_mut(&ty);
|
||||
let downcast =
|
||||
value.and_then(|context| context.downcast_mut::<T>());
|
||||
if let Some(value) = downcast {
|
||||
return Some(cb(value));
|
||||
} else {
|
||||
parent =
|
||||
this_parent.parent.as_ref().and_then(|p| p.upgrade());
|
||||
let parent = inner.parent.as_ref().and_then(|p| p.upgrade());
|
||||
let joined = inner
|
||||
.joined_owners
|
||||
.iter()
|
||||
.map(|owner| Arc::clone(&owner.inner));
|
||||
for parent in parent.into_iter().chain(joined) {
|
||||
while let Some(ref this_parent) = parent.clone() {
|
||||
let mut this_parent = this_parent.write().or_poisoned();
|
||||
let contexts = &mut this_parent.contexts;
|
||||
let value = contexts.get_mut(&ty);
|
||||
let downcast =
|
||||
value.and_then(|context| context.downcast_mut::<T>());
|
||||
if let Some(value) = downcast {
|
||||
return Some(cb(value));
|
||||
} else {
|
||||
parent = this_parent
|
||||
.parent
|
||||
.as_ref()
|
||||
.and_then(|p| p.upgrade());
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
|
||||
Reference in New Issue
Block a user