@@ -159,7 +159,8 @@ fn propagate(self: Node) -> Unit {
159
159
dependency.propagate()
160
160
// If a dependency's value changed, the node needs to be recomputed
161
161
if dependency.is_changed() {
162
- // remove all outgoing_edges, since they will be reconstructed during evaluate
162
+ // remove all incoming_edges and outgoing_edges, since they will be reconstructed during evaluate
163
+ self.incoming_edges().clear()
163
164
self.outgoing_edges().clear()
164
165
self.evaluate()
165
166
return
@@ -288,13 +289,25 @@ impl[A : Eq] Node for Thunk[A] with set_dirty(self, new_dirty) {
288
289
}
289
290
290
291
impl[A : Eq] Node for Thunk[A] with evaluate(self) {
292
+ // push self into node_stack top
293
+ // now self is active target
291
294
node_stack.push(self)
295
+ // `self.thunk` might contains `source.get()`,
296
+ // such as `s1.get()`, `s2.get()` and `s3.get()`
297
+ //
298
+ // when call `Thunk::get` or `Cell::get`,
299
+ // they will treat `node_stack.last()` as themself's target.
300
+ // if source is `Cell`, then it only record `incoming_edges`.
301
+ // if source is `Thunk`, then it record `incoming_edges` and `outgoing_edges`, connect each other.
302
+ //
292
303
let value = (self.thunk)()
293
304
self.is_changed = match self.value {
294
305
None => true
295
306
Some(v) => v != value
296
307
}
297
308
self.value = Some(value)
309
+ // pop self from node_stack
310
+ // now self is no longer active target
298
311
node_stack.unsafe_pop() |> ignore
299
312
}
300
313
```
@@ -327,6 +340,7 @@ fn &Node::propagate(self : &Node) -> Unit {
327
340
for dependency in self.outgoing_edges() {
328
341
dependency.propagate()
329
342
if dependency.is_changed() {
343
+ self.incoming_edges().clear()
330
344
self.outgoing_edges().clear()
331
345
self.evaluate()
332
346
return
0 commit comments