Clone for EventHandler<'_, T> {
- fn clone(&self) -> Self {
- Self {
- callback: self.callback,
- }
- }
-}
-
/// Virtual Components for custom user-defined components
/// Only supports the functional syntax
pub struct VComponent<'src> {
@@ -405,7 +399,7 @@ impl AnyProps for VComponentProps
{
}
// Safety:
- // this will downcat the other ptr as our swallowed type!
+ // this will downcast the other ptr as our swallowed type!
// you *must* make this check *before* calling this method
// if your functions are not the same, then you will downcast a pointer into a different type (UB)
unsafe fn memoize(&self, other: &dyn AnyProps) -> bool {
@@ -677,7 +671,7 @@ impl<'a> NodeFactory<'a> {
pub fn event_handler(self, f: impl FnMut(T) + 'a) -> EventHandler<'a, T> {
let handler: &mut dyn FnMut(T) = self.bump.alloc(f);
let caller = unsafe { BumpBox::from_raw(handler as *mut dyn FnMut(T)) };
- let callback = self.bump.alloc(RefCell::new(Some(caller)));
+ let callback = RefCell::new(Some(caller));
EventHandler { callback }
}
}
diff --git a/packages/core/src/scopes.rs b/packages/core/src/scopes.rs
index 65511470e..77c648d18 100644
--- a/packages/core/src/scopes.rs
+++ b/packages/core/src/scopes.rs
@@ -70,7 +70,7 @@ impl ScopeArena {
}
/// Safety:
- /// - Obtaining a mutable refernece to any Scope is unsafe
+ /// - Obtaining a mutable reference to any Scope is unsafe
/// - Scopes use interior mutability when sharing data into components
pub(crate) fn get_scope(&self, id: ScopeId) -> Option<&ScopeState> {
unsafe { self.scopes.borrow().get(&id).map(|f| &**f) }
@@ -101,7 +101,7 @@ impl ScopeArena {
let parent_scope = parent_scope.map(|f| self.get_scope_raw(f)).flatten();
/*
- This scopearena aggressively reuse old scopes when possible.
+ This scopearena aggressively reuses old scopes when possible.
We try to minimize the new allocations for props/arenas.
However, this will probably lead to some sort of fragmentation.
@@ -198,12 +198,9 @@ impl ScopeArena {
// run the hooks (which hold an &mut Reference)
// recursively call ensure_drop_safety on all children
items.borrowed_props.drain(..).for_each(|comp| {
- let scope_id = comp
- .scope
- .get()
- .expect("VComponents should be associated with a valid Scope");
-
- self.ensure_drop_safety(scope_id);
+ if let Some(scope_id) = comp.scope.get() {
+ self.ensure_drop_safety(scope_id);
+ }
drop(comp.props.take());
});
@@ -670,6 +667,60 @@ impl ScopeState {
value
}
+ /// Provide a context for the root component from anywhere in your app.
+ ///
+ ///
+ /// # Example
+ ///
+ /// ```rust, ignore
+ /// struct SharedState(&'static str);
+ ///
+ /// static App: Component = |cx| {
+ /// cx.use_hook(|_| cx.provide_root_context(SharedState("world")));
+ /// rsx!(cx, Child {})
+ /// }
+ ///
+ /// static Child: Component = |cx| {
+ /// let state = cx.consume_state::();
+ /// rsx!(cx, div { "hello {state.0}" })
+ /// }
+ /// ```
+ pub fn provide_root_context(&self, value: T) -> Rc {
+ let value = Rc::new(value);
+
+ // if we *are* the root component, then we can just provide the context directly
+ if self.scope_id() == ScopeId(0) {
+ self.shared_contexts
+ .borrow_mut()
+ .insert(TypeId::of::(), value.clone())
+ .map(|f| f.downcast::().ok())
+ .flatten();
+ return value;
+ }
+
+ let mut search_parent = self.parent_scope;
+
+ while let Some(parent) = search_parent.take() {
+ let parent = unsafe { &*parent };
+
+ if parent.scope_id() == ScopeId(0) {
+ let exists = parent
+ .shared_contexts
+ .borrow_mut()
+ .insert(TypeId::of::(), value.clone());
+
+ if exists.is_some() {
+ log::warn!("Context already provided to parent scope - replacing it");
+ }
+ return value;
+ }
+
+ search_parent = parent.parent_scope;
+ }
+
+ unreachable!("all apps have a root scope")
+ }
+
/// Try to retrieve a SharedState with type T from the any parent Scope.
pub fn consume_context(&self) -> Option> {
if let Some(shared) = self.shared_contexts.borrow().get(&TypeId::of::()) {
@@ -700,6 +751,11 @@ impl ScopeState {
self.tasks.push_fut(fut)
}
+ /// Spawns the future but does not return the TaskId
+ pub fn spawn(&self, fut: impl Future