tc39 / proposal-signals

A proposal to add signals to JavaScript.
MIT License
2.87k stars 54 forks source link

When a watcher for a computed depending on two sources is notified, if one source updates and a watcher is added during notification to the other source, an internal error is thrown #192

Open dead-claudia opened 3 weeks ago

dead-claudia commented 3 weeks ago

Repro for 0.1.0: link

Source:

const WA = new Signal.subtle.Watcher(() => {
  console.log("watch WA")
  WC.watch(C)
})

const WC = new Signal.subtle.Watcher(() => {
  console.log("watch WC")
})

const A = new Signal.Computed(() => {
  console.log("get A")
  B.get()
  C.get()
  console.log("get A end")
})

const B = new Signal.State(1)
const C = new Signal.State(1)

A.get()
WA.watch(A)

B.set(2)
dead-claudia commented 3 weeks ago

Same issue when reusing WA: link

Source:

const WA = new Signal.subtle.Watcher(() => {
  console.log("watch WA")
  WA.watch(C)
})

const A = new Signal.Computed(() => {
  console.log("get A")
  B.get()
  C.get()
  console.log("get A end")
})

const B = new Signal.State(1)
const C = new Signal.State(1)

A.get()
WA.watch(A)

B.set(2)
robbiespeed commented 3 weeks ago

I suspect this Error is intentional in order to avoid any mutation of the graph (other than dirtying) during the dirtying phase. Calling .watch(signal) will potentially and add new consumer<->producer links to the graph, which might or might not trigger the Watchers notify callback again in the same dirtying phase.

dead-claudia commented 3 weeks ago

C isn't dirty, only A and B are. And when pre-added, WC isn't notified, only WA.