You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Generalise the notifying semantics to freezing (#223)
* Rename `notifying` to `frozen`
This reflects an upcoming change which broadens its scope.
* Freeze out both `watch` and `unwatch`
* Separate out the steps of this algorithm
* Freeze the graph during execution of the `watched` callback
* Spell out the `unwatch` algorithm in steps
* Freeze the graph during execution of the `unwatched` callback
* Correct nesting
Copy file name to clipboardexpand all lines: README.md
+22-12
Original file line number
Diff line number
Diff line change
@@ -443,7 +443,7 @@ Some aspects of the algorithm:
443
443
Signal algorithms need to reference certain global state. This state is global for the entire thread, or "agent".
444
444
445
445
- `computing`: The innermost computed or effect Signal currently being reevaluated due to a `.get` or `.run` call, or `undefined`. Initially `undefined`.
446
-
- `notifying`: Boolean denoting whether there is an `notify`callback currently executing. Initially `false`.
446
+
- `frozen`: Boolean denoting whether there is a callback currently executing which requires that the graph not be modified. Initially `false`.
447
447
- `generation`: An incrementing integer, starting at 0, used to track how current a value is while avoiding circularities.
448
448
449
449
### The `Signal` namespace
@@ -473,22 +473,22 @@ Signal algorithms need to reference certain global state. This state is global f
473
473
474
474
#### Method: `Signal.State.prototype.get()`
475
475
476
-
1. If `notifying` is true, throw an exception.
476
+
1. If `frozen` is true, throw an exception.
477
477
1. If `computing` is not `undefined`, add this Signal to `computing`'s `sources` set.
478
478
1. NOTE: We do not add `computing` to this Signal's `sinks` set until it is watched by a Watcher.
1. If the current execution context is `notifying`, throw an exception.
483
+
1. If the current execution context is `frozen`, throw an exception.
484
484
1. Run the "set Signal value" algorithm with this Signal and the first parameter for the value.
485
485
1. If that algorithm returned `~clean~`, then return undefined.
486
486
1. Set the `state` of all `sinks` of this Signal to (if it is a Computed Signal) `~dirty~` if they were previously clean, or (if it is a Watcher) `~pending~` if it was previously `~watching~`.
487
487
1. Set the `state` of all of the sinks' Computed Signal dependencies (recursively) to `~checked~` if they were previously `~clean~` (that is, leave dirty markings in place), or for Watchers, `~pending~` if previously `~watching~`.
488
488
1. For each previously `~watching~` Watcher encountered in that recursive search, then in depth-first order,
489
-
1. Set `notifying` to true.
489
+
1. Set `frozen` to true.
490
490
1. Calling their `notify` callback (saving aside any exception thrown, but ignoring the return value of `notify`).
491
-
1. Restore `notifying` to false.
491
+
1. Restore `frozen` to false.
492
492
1. Set the `state` of the Watcher to `~waiting~`.
493
493
1. If any exception was thrown from the `notify` callbacks, propagate it to the caller after all `notify` callbacks have run. If there are multiple exceptions, then package them up together into an AggregateError and throw that.
494
494
1. Return undefined.
@@ -548,7 +548,7 @@ With [AsyncContext](https://github.com/tc39/proposal-async-context), the callbac
548
548
549
549
#### Method: `Signal.Computed.prototype.get`
550
550
551
-
1. If the current execution context is `notifying` or if this Signal has the state `~computing~`, or if this signal is an Effect and `computing` a computed Signal, throw an exception.
551
+
1. If the current execution context is `frozen` or if this Signal has the state `~computing~`, or if this signal is an Effect and `computing` a computed Signal, throw an exception.
552
552
1. If `computing` is not `undefined`, add this Signal to `computing`'s `sources` set.
553
553
1. NOTE: We do not add `computing` to this Signal's `sinks` set until/unless it becomes watched by a Watcher.
554
554
1. If this Signal's state is `~dirty~` or `~checked~`: Repeat the following steps until this Signal is `~clean~`:
@@ -601,18 +601,28 @@ With [AsyncContext](https://github.com/tc39/proposal-async-context), the callbac
1. If any of the arguments is not a signal, throw an exception.
605
606
1. Append all arguments to the end of this object's `signals`.
606
-
1. Add this watcher to each of the newly watched signals as a sink.
607
-
1. Add this watcher as a `sink` to each Signal. If this was the first sink, then recurse up to sources to add that signal as a sink, and call the `watched` callback if it exists.
607
+
1. For each newly-watched signal, in left-to-right order,
608
+
1. Add this watcher as a `sink` to that signal.
609
+
1. If this was the first sink, then recurse up to sources to add that signal as a sink.
610
+
1. Set `frozen` to true.
611
+
1. Call the `watched` callback if it exists.
612
+
1. Restore `frozen` to true.
608
613
1. If the Signal's `state` is `~waiting~`, then set it to `~watching~`.
0 commit comments