UNPKG

3.25 kBJavaScriptView Raw
1import { dep, Slot } from "optimism";
2// Contextual Slot that acquires its value when custom read functions are
3// called in Policies#readField.
4export var cacheSlot = new Slot();
5var cacheInfoMap = new WeakMap();
6function 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}
16export 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.
27export function recallCache(cache) {
28 getCacheInfo(cache).vars.forEach(function (rv) { return rv.attachCache(cache); });
29}
30export 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}
78function broadcast(cache) {
79 if (cache.broadcastWatches) {
80 cache.broadcastWatches();
81 }
82}
83//# sourceMappingURL=reactiveVars.js.map
\No newline at end of file