1 | import { dep, Slot } from "optimism";
|
2 | // Contextual Slot that acquires its value when custom read functions are
|
3 | // called in Policies#readField.
|
4 | export var cacheSlot = new Slot();
|
5 | var cacheInfoMap = new WeakMap();
|
6 | function getCacheInfo(cache) {
|
7 | var info = cacheInfoMap.get(cache);
|
8 | if (!info) {
|
9 | cacheInfoMap.set(cache, (info = {
|
10 | vars: new Set(),
|
11 | dep: dep(),
|
12 | }));
|
13 | }
|
14 | return info;
|
15 | }
|
16 | export function forgetCache(cache) {
|
17 | getCacheInfo(cache).vars.forEach(function (rv) { return rv.forgetCache(cache); });
|
18 | }
|
19 | // Calling forgetCache(cache) serves to silence broadcasts and allows the
|
20 | // cache to be garbage collected. However, the varsByCache WeakMap
|
21 | // preserves the set of reactive variables that were previously associated
|
22 | // with this cache, which makes it possible to "recall" the cache at a
|
23 | // later time, by reattaching it to those variables. If the cache has been
|
24 | // garbage collected in the meantime, because it is no longer reachable,
|
25 | // you won't be able to call recallCache(cache), and the cache will
|
26 | // automatically disappear from the varsByCache WeakMap.
|
27 | export function recallCache(cache) {
|
28 | getCacheInfo(cache).vars.forEach(function (rv) { return rv.attachCache(cache); });
|
29 | }
|
30 | export function makeVar(value) {
|
31 | var caches = new Set();
|
32 | var listeners = new Set();
|
33 | var rv = function (newValue) {
|
34 | if (arguments.length > 0) {
|
35 | if (value !== newValue) {
|
36 | value = newValue;
|
37 | caches.forEach(function (cache) {
|
38 | // Invalidate any fields with custom read functions that
|
39 | // consumed this variable, so query results involving those
|
40 | // fields will be recomputed the next time we read them.
|
41 | getCacheInfo(cache).dep.dirty(rv);
|
42 | // Broadcast changes to any caches that have previously read
|
43 | // from this variable.
|
44 | broadcast(cache);
|
45 | });
|
46 | // Finally, notify any listeners added via rv.onNextChange.
|
47 | var oldListeners = Array.from(listeners);
|
48 | listeners.clear();
|
49 | oldListeners.forEach(function (listener) { return listener(value); });
|
50 | }
|
51 | }
|
52 | else {
|
53 | // When reading from the variable, obtain the current cache from
|
54 | // context via cacheSlot. This isn't entirely foolproof, but it's
|
55 | // the same system that powers varDep.
|
56 | var cache = cacheSlot.getValue();
|
57 | if (cache) {
|
58 | attach(cache);
|
59 | getCacheInfo(cache).dep(rv);
|
60 | }
|
61 | }
|
62 | return value;
|
63 | };
|
64 | rv.onNextChange = function (listener) {
|
65 | listeners.add(listener);
|
66 | return function () {
|
67 | listeners.delete(listener);
|
68 | };
|
69 | };
|
70 | var attach = (rv.attachCache = function (cache) {
|
71 | caches.add(cache);
|
72 | getCacheInfo(cache).vars.add(rv);
|
73 | return rv;
|
74 | });
|
75 | rv.forgetCache = function (cache) { return caches.delete(cache); };
|
76 | return rv;
|
77 | }
|
78 | function broadcast(cache) {
|
79 | if (cache.broadcastWatches) {
|
80 | cache.broadcastWatches();
|
81 | }
|
82 | }
|
83 | //# sourceMappingURL=reactiveVars.js.map |
\ | No newline at end of file |