fix memo and resource caller information (#2443)

This commit is contained in:
Evan Almloff authored and GitHub committed 2024-06-06 17:01:42 -07:00
1 parent 489758d5ba
commit 5e57779435
3 files changed
+36 -10

No files matched your search

+11 -2
View File
@@ -68,15 +68,18 @@ use std::{cell::Cell, future::Future, rc::Rc};
/// } /// }
/// ``` /// ```
#[must_use = "Consider using `cx.spawn` to run a future without reading its value"] #[must_use = "Consider using `cx.spawn` to run a future without reading its value"]
#[track_caller]
pub fn use_resource<T, F>(mut future: impl FnMut() -> F + 'static) -> Resource<T> pub fn use_resource<T, F>(mut future: impl FnMut() -> F + 'static) -> Resource<T>
where where
T: 'static, T: 'static,
F: Future<Output = T> + 'static, F: Future<Output = T> + 'static,
{ {
let location = std::panic::Location::caller();
let mut value = use_signal(|| None); let mut value = use_signal(|| None);
let mut state = use_signal(|| UseResourceState::Pending); let mut state = use_signal(|| UseResourceState::Pending);
let (rc, changed) = use_hook(|| { let (rc, changed) = use_hook(|| {
let (rc, changed) = ReactiveContext::new(); let (rc, changed) = ReactiveContext::new_with_origin(location);
(rc, Rc::new(Cell::new(Some(changed)))) (rc, Rc::new(Cell::new(Some(changed))))
}); });
@@ -92,7 +95,13 @@ where
// Run each poll in the context of the reactive scope // Run each poll in the context of the reactive scope
// This ensures the scope is properly subscribed to the future's dependencies // This ensures the scope is properly subscribed to the future's dependencies
let res = future::poll_fn(|cx| rc.run_in(|| fut.poll_unpin(cx))).await; let res = future::poll_fn(|cx| {
rc.run_in(|| {
tracing::trace_span!("polling resource", location = %location)
.in_scope(|| fut.poll_unpin(cx))
})
})
.await;
// Set the value and state // Set the value and state
state.set(UseResourceState::Ready); state.set(UseResourceState::Ready);
+15 -8
View File
@@ -5,7 +5,6 @@ use crate::{CopyValue, ReadOnlySignal};
use std::{ use std::{
cell::RefCell, cell::RefCell,
ops::Deref, ops::Deref,
panic::Location,
sync::{atomic::AtomicBool, Arc}, sync::{atomic::AtomicBool, Arc},
}; };
@@ -36,7 +35,18 @@ where
impl<T: 'static> Memo<T> { impl<T: 'static> Memo<T> {
/// Create a new memo /// Create a new memo
#[track_caller] #[track_caller]
pub fn new(mut f: impl FnMut() -> T + 'static) -> Self pub fn new(f: impl FnMut() -> T + 'static) -> Self
where
T: PartialEq,
{
Self::new_with_location(f, std::panic::Location::caller())
}
/// Create a new memo with an explicit location
pub fn new_with_location(
mut f: impl FnMut() -> T + 'static,
location: &'static std::panic::Location<'static>,
) -> Self
where where
T: PartialEq, T: PartialEq,
{ {
@@ -50,11 +60,8 @@ impl<T: 'static> Memo<T> {
let _ = tx.unbounded_send(()); let _ = tx.unbounded_send(());
} }
}; };
let rc = ReactiveContext::new_with_callback( let rc =
callback, ReactiveContext::new_with_callback(callback, current_scope_id().unwrap(), location);
current_scope_id().unwrap(),
Location::caller(),
);
// Create a new signal in that context, wiring up its dependencies and subscribers // Create a new signal in that context, wiring up its dependencies and subscribers
let mut recompute = move || rc.run_in(&mut f); let mut recompute = move || rc.run_in(&mut f);
@@ -64,7 +71,7 @@ impl<T: 'static> Memo<T> {
dirty, dirty,
callback: recompute, callback: recompute,
}); });
let state: Signal<T> = Signal::new(value); let state: Signal<T> = Signal::new_with_caller(value, location);
let memo = Memo { let memo = Memo {
inner: state, inner: state,
+10
View File
@@ -91,6 +91,16 @@ impl<T: PartialEq + 'static> Signal<T> {
pub fn memo(f: impl FnMut() -> T + 'static) -> Memo<T> { pub fn memo(f: impl FnMut() -> T + 'static) -> Memo<T> {
Memo::new(f) Memo::new(f)
} }
/// Creates a new unsync Selector with an explicit location. The selector will be run immediately and whenever any signal it reads changes.
///
/// Selectors can be used to efficiently compute derived data from signals.
pub fn memo_with_location(
f: impl FnMut() -> T + 'static,
location: &'static std::panic::Location<'static>,
) -> Memo<T> {
Memo::new_with_location(f, location)
}
} }
impl<T: 'static, S: Storage<SignalData<T>>> Signal<T, S> { impl<T: 'static, S: Storage<SignalData<T>>> Signal<T, S> {