import { Trie } from "@wry/trie"; import { StrongCache } from "@wry/caches"; import { Entry } from "./entry.js"; import { parentEntrySlot } from "./context.js"; // These helper functions are important for making optimism work with // asynchronous code. In order to register parent-child dependencies, // optimism needs to know about any currently active parent computations. // In ordinary synchronous code, the parent context is implicit in the // execution stack, but asynchronous code requires some extra guidance in // order to propagate context from one async task segment to the next. export { bindContext, noContext, nonReactive, setTimeout, asyncFromGen, Slot, } from "./context.js"; // A lighter-weight dependency, similar to OptimisticWrapperFunction, except // with only one argument, no makeCacheKey, no wrapped function to recompute, // and no result value. Useful for representing dependency leaves in the graph // of computation. Subscriptions are supported. export { dep } from "./dep.js"; // The defaultMakeCacheKey function is remarkably powerful, because it gives // a unique object for any shallow-identical list of arguments. If you need // to implement a custom makeCacheKey function, you may find it helpful to // delegate the final work to defaultMakeCacheKey, which is why we export it // here. However, you may want to avoid defaultMakeCacheKey if your runtime // does not support WeakMap, or you have the ability to return a string key. // In those cases, just write your own custom makeCacheKey functions. let defaultKeyTrie; export function defaultMakeCacheKey(...args) { const trie = defaultKeyTrie || (defaultKeyTrie = new Trie(typeof WeakMap === "function")); return trie.lookupArray(args); } // If you're paranoid about memory leaks, or you want to avoid using WeakMap // under the hood, but you still need the behavior of defaultMakeCacheKey, // import this constructor to create your own tries. export { Trie as KeyTrie }; ; const caches = new Set(); export function wrap(originalFunction, { max = Math.pow(2, 16), keyArgs, makeCacheKey = defaultMakeCacheKey, normalizeResult, subscribe, cache: cacheOption = StrongCache, } = Object.create(null)) { const cache = typeof cacheOption === "function" ? new cacheOption(max, entry => entry.dispose()) : cacheOption; const optimistic = function () { const key = makeCacheKey.apply(null, keyArgs ? keyArgs.apply(null, arguments) : arguments); if (key === void 0) { return originalFunction.apply(null, arguments); } let entry = cache.get(key); if (!entry) { cache.set(key, entry = new Entry(originalFunction)); entry.normalizeResult = normalizeResult; entry.subscribe = subscribe; // Give the Entry the ability to trigger cache.delete(key), even though // the Entry itself does not know about key or cache. entry.forget = () => cache.delete(key); } const value = entry.recompute(Array.prototype.slice.call(arguments)); // Move this entry to the front of the least-recently used queue, // since we just finished computing its value. cache.set(key, entry); caches.add(cache); // Clean up any excess entries in the cache, but only if there is no // active parent entry, meaning we're not in the middle of a larger // computation that might be flummoxed by the cleaning. if (!parentEntrySlot.hasValue()) { caches.forEach(cache => cache.clean()); caches.clear(); } return value; }; Object.defineProperty(optimistic, "size", { get: () => cache.size, configurable: false, enumerable: false, }); Object.freeze(optimistic.options = { max, keyArgs, makeCacheKey, normalizeResult, subscribe, cache, }); function dirtyKey(key) { const entry = key && cache.get(key); if (entry) { entry.setDirty(); } } optimistic.dirtyKey = dirtyKey; optimistic.dirty = function dirty() { dirtyKey(makeCacheKey.apply(null, arguments)); }; function peekKey(key) { const entry = key && cache.get(key); if (entry) { return entry.peek(); } } optimistic.peekKey = peekKey; optimistic.peek = function peek() { return peekKey(makeCacheKey.apply(null, arguments)); }; function forgetKey(key) { return key ? cache.delete(key) : false; } optimistic.forgetKey = forgetKey; optimistic.forget = function forget() { return forgetKey(makeCacheKey.apply(null, arguments)); }; optimistic.makeCacheKey = makeCacheKey; optimistic.getKey = keyArgs ? function getKey() { return makeCacheKey.apply(null, keyArgs.apply(null, arguments)); } : makeCacheKey; return Object.freeze(optimistic); } //# sourceMappingURL=index.js.map