Improve warnings when trying to update outside of pending suspense boundaries on the server (#2575)

* Improve warnings when trying to update outside of pending suspense boundaries on the server

* remove suspense resolve log
This commit is contained in:
Evan Almloff authored and GitHub committed 2024-07-17 19:32:33 -07:00
1 parent 88af3e7eff
commit e794be5d78
14 files changed
+409 -313

No files matched your search

+33 -6
View File
@@ -22,10 +22,12 @@ pub struct Runtime {
pub(crate) scope_states: RefCell<Vec<Option<Scope>>>,
// We use this to track the current scope
pub(crate) scope_stack: RefCell<Vec<ScopeId>>,
// This stack should only be modified through [`Runtime::with_scope_on_stack`] to ensure that the stack is correctly restored
scope_stack: RefCell<Vec<ScopeId>>,
// We use this to track the current suspense location. Generally this lines up with the scope stack, but it may be different for children of a suspense boundary
pub(crate) suspense_stack: RefCell<Vec<SuspenseLocation>>,
// This stack should only be modified through [`Runtime::with_suspense_location`] to ensure that the stack is correctly restored
suspense_stack: RefCell<Vec<SuspenseLocation>>,
// We use this to track the current task
pub(crate) current_task: Cell<Option<Task>>,
@@ -123,21 +125,46 @@ impl Runtime {
o
}
/// Get the current suspense location
pub(crate) fn current_suspense_location(&self) -> Option<SuspenseLocation> {
self.suspense_stack.borrow().last().cloned()
}
/// Run a callback a [`SuspenseLocation`] at the top of the stack
pub(crate) fn with_suspense_location<O>(
&self,
suspense_location: SuspenseLocation,
f: impl FnOnce() -> O,
) -> O {
self.suspense_stack.borrow_mut().push(suspense_location);
let o = f();
self.suspense_stack.borrow_mut().pop();
o
}
/// Run a callback with the current scope at the top of the stack
pub(crate) fn with_scope_on_stack<O>(&self, scope: ScopeId, f: impl FnOnce() -> O) -> O {
self.push_scope(scope);
let o = f();
self.pop_scope();
o
}
/// Push a scope onto the stack
pub(crate) fn push_scope(&self, scope: ScopeId) {
fn push_scope(&self, scope: ScopeId) {
let suspense_location = self
.scope_states
.borrow()
.get(scope.0)
.and_then(|s| s.as_ref())
.map(|s| s.suspense_boundary())
.map(|s| s.suspense_location())
.unwrap_or_default();
self.suspense_stack.borrow_mut().push(suspense_location);
self.scope_stack.borrow_mut().push(scope);
}
/// Pop a scope off the stack
pub(crate) fn pop_scope(&self) {
fn pop_scope(&self) {
self.scope_stack.borrow_mut().pop();
self.suspense_stack.borrow_mut().pop();
}
@@ -200,7 +227,7 @@ impl Runtime {
// If this is not a suspended scope, and we are under a frozen context, then we should
let scopes = self.scope_states.borrow();
let scope = &scopes[scope_id.0].as_ref().unwrap();
!matches!(scope.suspense_boundary(), SuspenseLocation::UnderSuspense(suspense) if suspense.suspended())
!matches!(scope.suspense_location(), SuspenseLocation::UnderSuspense(suspense) if suspense.has_suspended_tasks())
}
}