tc39 / proposal-signals

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

Calling `.watch` inside a `Computed` callback #211

Open prophile opened 2 weeks ago

prophile commented 2 weeks ago

Consider the following code:

let watcherB
const state = new Signal.State(false)
const computed = new Signal.Computed(() => {
  if (state.get()) {
    watcherB.watch(computed)
    return 1
  } else {
    return 0
  }
})

computed.get()
watcherB = new Signal.subtle.Watcher(() => {
  console.log("B notified")
});
const watcherA = new Signal.subtle.Watcher(() => {
  console.log("A notified")
});
watcherA.watch(computed)
state.set(true)

During the execution of its callback, computed makes itself watched by watcherB. The semantics as they currently stand mean that both by the spec and the polyfill at f7c550b, only "A notified" is logged. This is probably right, but is also potentially quite surprising, and may be best spelled out explicitly?

I foresee browsers doing creative strategies to optimise Signal as long as the semantics are compatible with the "push-dirty pull-execute" semantics spelled out; I worry that a case like this might end up changing behaviour there unless it's more explicitly spelled out.

littledan commented 5 days ago

What is it that you'd like to be spelled out? I don't see how "B notified" would ever run here.

To align browser behavior: let's add more tests for this stuff!