UNPKG

3.34 kBJavaScriptView Raw
1// function utils
2import { lruQueue } from './lruQueue.js';
3/**
4 * Memoize a given function by caching the computed result.
5 * The cache of a memoized function can be cleared by deleting the `cache`
6 * property of the function.
7 *
8 * @param {function} fn The function to be memoized.
9 * Must be a pure function.
10 * @param {Object} [options]
11 * @param {function(args: Array): string} [options.hasher]
12 * A custom hash builder. Is JSON.stringify by default.
13 * @param {number | undefined} [options.limit]
14 * Maximum number of values that may be cached. Undefined indicates
15 * unlimited (default)
16 * @return {function} Returns the memoized function
17 */
18
19export function memoize(fn) {
20 var {
21 hasher,
22 limit
23 } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
24 limit = limit == null ? Number.POSITIVE_INFINITY : limit;
25 hasher = hasher == null ? JSON.stringify : hasher;
26 return function memoize() {
27 if (typeof memoize.cache !== 'object') {
28 memoize.cache = {
29 values: new Map(),
30 lru: lruQueue(limit || Number.POSITIVE_INFINITY)
31 };
32 }
33
34 var args = [];
35
36 for (var i = 0; i < arguments.length; i++) {
37 args[i] = arguments[i];
38 }
39
40 var hash = hasher(args);
41
42 if (memoize.cache.values.has(hash)) {
43 memoize.cache.lru.hit(hash);
44 return memoize.cache.values.get(hash);
45 }
46
47 var newVal = fn.apply(fn, args);
48 memoize.cache.values.set(hash, newVal);
49 memoize.cache.values.delete(memoize.cache.lru.hit(hash));
50 return newVal;
51 };
52}
53/**
54 * Memoize a given function by caching all results and the arguments,
55 * and comparing against the arguments of previous results before
56 * executing again.
57 * This is less performant than `memoize` which calculates a hash,
58 * which is very fast to compare. Use `memoizeCompare` only when it is
59 * not possible to create a unique serializable hash from the function
60 * arguments.
61 * The isEqual function must compare two sets of arguments
62 * and return true when equal (can be a deep equality check for example).
63 * @param {function} fn
64 * @param {function(a: *, b: *) : boolean} isEqual
65 * @returns {function}
66 */
67
68export function memoizeCompare(fn, isEqual) {
69 var memoize = function memoize() {
70 var args = [];
71
72 for (var i = 0; i < arguments.length; i++) {
73 args[i] = arguments[i];
74 }
75
76 for (var c = 0; c < memoize.cache.length; c++) {
77 var cached = memoize.cache[c];
78
79 if (isEqual(args, cached.args)) {
80 // TODO: move this cache entry to the top so recently used entries move up?
81 return cached.res;
82 }
83 }
84
85 var res = fn.apply(fn, args);
86 memoize.cache.unshift({
87 args,
88 res
89 });
90 return res;
91 };
92
93 memoize.cache = [];
94 return memoize;
95}
96/**
97 * Find the maximum number of arguments expected by a typed function.
98 * @param {function} fn A typed function
99 * @return {number} Returns the maximum number of expected arguments.
100 * Returns -1 when no signatures where found on the function.
101 */
102
103export function maxArgumentCount(fn) {
104 return Object.keys(fn.signatures || {}).reduce(function (args, signature) {
105 var count = (signature.match(/,/g) || []).length + 1;
106 return Math.max(args, count);
107 }, -1);
108}
\No newline at end of file