wip: before scheduler simplify

This commit is contained in:
Jonathan Kelley committed 2021-09-19 22:10:00 -04:00
1 parent 9971ff215d
commit c16b92ee7e
6 files changed
+77 -53

No files matched your search

+43 -44
View File
@@ -98,15 +98,26 @@ impl<'src, P> Context<'src, P> {
/// Create a subscription that schedules a future render for the reference component
///
/// ## Notice: you should prefer using prepare_update and get_scope_id
///
pub fn schedule_update(&self) -> Rc<dyn Fn() + 'static> {
self.scope.memoized_updater.clone()
}
pub fn prepare_update(&self) -> Rc<dyn Fn(ScopeId)> {
/// Schedule an update for any component given its ScopeId.
///
/// A component's ScopeId can be obtained from `use_hook` or the [`Context::scope_id`] method.
///
/// This method should be used when you want to schedule an update for a component
pub fn schedule_update_any(&self) -> Rc<dyn Fn(ScopeId)> {
self.scope.shared.schedule_any_immediate.clone()
}
/// Get the [`ScopeId`] of a mounted component.
///
/// `ScopeId` is not unique for the lifetime of the VirtualDom - a ScopeId will be reused if a component is unmounted.
pub fn scope_id(&self) -> ScopeId {
self.scope.our_arena_idx
}
/// Take a lazy VNode structure and actually build it with the context of the VDom's efficient VNode allocator.
///
/// This function consumes the context and absorb the lifetime, so these VNodes *must* be returned.
@@ -151,24 +162,6 @@ impl<'src, P> Context<'src, P> {
(self.scope.shared.submit_task)(task)
}
/// Add a state globally accessible to child components via tree walking
pub fn add_shared_state<T: 'static>(self, val: T) {
self.scope
.shared_contexts
.borrow_mut()
.insert(TypeId::of::<T>(), Rc::new(val))
.map(|_| {
log::warn!("A shared state was replaced with itself. This is does not result in a panic, but is probably not what you are trying to do");
});
}
pub fn try_consume_shared_state<T: 'static>(self) -> Option<Rc<T>> {
let getter = &self.scope.shared.get_shared_context;
let ty = TypeId::of::<T>();
let idx = self.scope.our_arena_idx;
getter(idx, ty).map(|f| f.downcast().expect("TypeID already validated"))
}
/// This hook enables the ability to expose state to children further down the VirtualDOM Tree.
///
/// This is a hook, so it should not be called conditionally!
@@ -185,45 +178,44 @@ impl<'src, P> Context<'src, P> {
/// struct SharedState(&'static str);
///
/// static App: FC<()> = |cx| {
/// cx.provide_state(|| SharedState("world"));
/// cx.use_provide_state(|| SharedState("world"));
/// rsx!(cx, Child {})
/// }
///
/// static Child: FC<()> = |cx| {
/// let state = cx.consume_state::<SharedState>();
/// let state = cx.use_consume_state::<SharedState>();
/// rsx!(cx, div { "hello {state.0}" })
/// }
/// ```
pub fn provide_state<T, F>(self, init: F) -> &'src Rc<T>
pub fn use_provide_state<T, F>(self, init: F) -> &'src Rc<T>
where
T: 'static,
F: FnOnce() -> T,
{
//
let ty = TypeId::of::<T>();
let contains_key = self.scope.shared_contexts.borrow().contains_key(&ty);
let is_initialized = self.use_hook(
|_| false,
|s| {
let i = s.clone();
let i = *s;
*s = true;
i
},
|_| {},
);
match (is_initialized, contains_key) {
// Do nothing, already initialized and already exists
(true, true) => {}
if !is_initialized {
self.scope
.shared_contexts
.borrow_mut()
.insert(TypeId::of::<T>(), Rc::new(init()))
.map(|_| {
log::warn!(
"A shared state was replaced with itself. \
This is does not result in a panic, but is probably not what you are trying to do"
);
});
}
// Needs to be initialized
(false, false) => self.add_shared_state(init()),
_ => debug_assert!(false, "Cannot initialize two contexts of the same type"),
};
self.consume_state().unwrap()
self.use_consume_state().unwrap()
}
/// Uses a context, storing the cached value around
@@ -231,10 +223,15 @@ impl<'src, P> Context<'src, P> {
/// If a context is not found on the first search, then this call will be "dud", always returning "None" even if a
/// context was added later. This allows using another hook as a fallback
///
pub fn consume_state<T: 'static>(self) -> Option<&'src Rc<T>> {
pub fn use_consume_state<T: 'static>(self) -> Option<&'src Rc<T>> {
struct UseContextHook<C>(Option<Rc<C>>);
self.use_hook(
move |_| UseContextHook(self.try_consume_shared_state::<T>()),
move |_| {
let getter = &self.scope.shared.get_shared_context;
let ty = TypeId::of::<T>();
let idx = self.scope.our_arena_idx;
UseContextHook(getter(idx, ty).map(|f| f.downcast().unwrap()))
},
move |hook| hook.0.as_ref(),
|_| {},
)
@@ -262,19 +259,21 @@ impl<'src, P> Context<'src, P> {
self,
initializer: Init,
runner: Run,
_cleanup: Cleanup,
cleanup: Cleanup,
) -> Output
where
State: 'static,
Output: 'src,
Init: FnOnce(usize) -> State,
Run: FnOnce(&'src mut State) -> Output,
Cleanup: FnOnce(State),
Cleanup: FnOnce(&mut State) + 'static,
{
// If the idx is the same as the hook length, then we need to add the current hook
if self.scope.hooks.at_end() {
let new_state = initializer(self.scope.hooks.len());
self.scope.hooks.push(new_state);
self.scope.hooks.push_hook(
initializer(self.scope.hooks.len()),
Box::new(|raw| cleanup(raw.downcast_mut::<State>().unwrap())),
);
}
const ERR_MSG: &str = r###"