A topological order respecting signals library inspired by SolidJS. What's topological ordering you ask? Check out the readme to understand the problem with most signal libraries.
add support for more signals and more types of contexts (or perhapse add support for context plugins).
some of the first ones that come to mind:
singal classes
async signals: computed variants of these signals should return SignalUpdate.ABORTED in its run method if their promise has not been resolved, which should cascade into aborting all observing signals. as for async state signals, they should hold back their id firing until their set value's promise has been resolved
deep diffable object signal: an object that signals the difference in its deep entries to its observers. deleted entries should either use undefined or some unique symbol. the diff must be described as a tree graph of non-leaf nodes containing keys, and leaf nodes containing new/updated values
context plugins
async context: should be capable of handling multiple parallel id firing
debounce plugin: should debounce when the same id is fired too quickly with not enough delay
throttle plugin: should throttle when the same id is fired
debouncedThrottle plugin: should throttle fired id, and behave as a debouncer for the final collection of throttled id firings. this would insure that the very final id firing always goes through
I just realized that the Context's update cycle mechanism is not actually topologically ordered.
the 3eff039 commit adds the test file /test/simple_signal2.test.ts, in which the traversal of ids is:
expected traversal: A, B, D, G, C, E, H, F, I, J
actual traversal by the update cycle: A, B, D, G, C, E, H,I, J, F
as you can see, signal F was supposed to be executed before I and J, but instead, it is pushed to the very end.
the directed acyclic graph looks as the following:
F gets skipped in the middle because it is already visited once from either B or D, but its resolution is delayed because of its unvisited dependencies C and E.
however, when C and E are visited, they propagate forward to H and then I.
in I's perspective, F has been resolved, since it has been visited. however, the reality is that while it has been visited, it was awaiting dependency resolution of C and E, and it hasn't been resolved yet.
the forward propagation model is indeed problematic. you should either stick backward resolution or forward propagation, but not both at the same time.