Adding/removing watchers during execution of `set`
prophile opened this issue · comments
In "Method: Signal.State.prototype.set(newValue)", we have:
6: For each previously
~watching~
Watcher encountered in that recursive search, then in depth-first order,
i. Setnotifying
to true while calling theirnotify
callback (saving aside any exception thrown, but ignoring the return value ofnotify
), and then restorenotifying
to false.
A watcher's notify
callback is permitted to call .watch
or .unwatch
(neither of their algorithms specify a notifying === false
check) and it's not clear what's supposed to happen in that case – if one watcher calls .unwatch
on another which would be notified by this algorithm but has not yet been so notified, should this stage of the algorithm still notify it or not?
Consider the following code:
const state = new Signal.State(0)
const watcherA = new Signal.subtle.Watcher(() => {
console.log("notified A")
});
const watcherB = new Signal.subtle.Watcher(() => {
console.log("notified B")
watcherA.unwatch(state);
});
watcherB.watch(state);
watcherA.watch(state);
state.set(1);
Should this print "notified B" and "notified A", or just "notified B"?
My reading of the current specification is that "previously ~watching~
Watcher" implies it should log both because they were both encountered in the search before running callbacks, but the polyfill in f7c550b just logs "notified B".
If I'm not mistaken adding watchers during notify already is an error, so it would follow that removing them should be as well.
This is definitely an area that needs further definition either way though, especially considering watcher.watch()
currently acts as a reset (something that needs to be defined further as well) and will never error in notify, but watcher.watch(signal)
will error.
Fixed by #223