Skip to content

Commit baaca43

Browse files
committed
fix(cache): Fixed an issue with dependency collection when triggering an effect.
- Temporarily disable dependency collection when triggering an effect to avoid incorrect tracking. - Added test cases to verify the fix.
1 parent b318a43 commit baaca43

File tree

2 files changed

+31
-1
lines changed

2 files changed

+31
-1
lines changed

cache/src/signal.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,18 @@ impl<T> Signal<T> {
3434

3535
/// Runs all dependent effects.
3636
fn flush_effects(&self) {
37+
// When triggering an Effect, dependencies are not collected for that Effect.
38+
//
39+
// The issue arises from the creation of Effect A, which may trigger Effect B.
40+
// In Effect B, the signal get operation causes incorrect tracking of Effect A.
41+
// In this case, dependency tracking for Effect A should not be performed
42+
// until Effect B exits the triggering phase.
43+
//
44+
// The root cause of this issue is a temporary violation of the assumption that
45+
// "an Effect is always the end point of the call chain."
46+
let creating_effect = unsafe { crate::call_stack::CREATING_EFFECT };
47+
unsafe { crate::call_stack::CREATING_EFFECT = false };
48+
3749
self.effects.borrow_mut().retain(|w| {
3850
if let Some(e) = w.upgrade() {
3951
e.run();
@@ -42,6 +54,8 @@ impl<T> Signal<T> {
4254
false
4355
}
4456
});
57+
58+
unsafe { crate::call_stack::CREATING_EFFECT = creating_effect };
4559
}
4660

4761
#[allow(non_snake_case)]
@@ -103,7 +117,8 @@ impl<T> Signal<T> {
103117
}
104118

105119
// Track effects in the call stack
106-
if let Some(e) = call_stack::current_effect_peak()
120+
if unsafe { call_stack::CREATING_EFFECT }
121+
&& let Some(e) = call_stack::current_effect_peak()
107122
&& !self.effects.borrow().iter().any(|w| Weak::ptr_eq(w, &e))
108123
{
109124
self.effects.borrow_mut().push(e);

macros/tests/effect.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,21 @@ fn complex_dependency_effect_test() {
125125
assert_eq!(unsafe { EFFECT_F_CALLED }, 1);
126126
}
127127

128+
signal!(
129+
static mut LOOP_A: i32 = 10;
130+
);
131+
132+
#[test]
133+
fn loop_effect_test() {
134+
let _ = Rc::into_raw(effect!(|| {
135+
LOOP_A();
136+
}));
137+
138+
let _ = Rc::into_raw(effect!(|| {
139+
LOOP_A_set(20);
140+
}));
141+
}
142+
128143
signal!(
129144
static mut SWITCH_A: bool = true;
130145
);

0 commit comments

Comments
 (0)