UNPKG

6.25 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3var merge_styles_1 = require("@uifabric/merge-styles");
4var _initializedStylesheetResets = false;
5var _resetCounter = 0;
6var _emptyObject = { empty: true };
7var _dictionary = {};
8var _weakMap = typeof WeakMap === 'undefined' ? null : WeakMap;
9/**
10 * Test utility for providing a custom weakmap.
11 *
12 * @internal
13 * */
14function setMemoizeWeakMap(weakMap) {
15 _weakMap = weakMap;
16}
17exports.setMemoizeWeakMap = setMemoizeWeakMap;
18/**
19 * Reset memoizations.
20 */
21function resetMemoizations() {
22 _resetCounter++;
23}
24exports.resetMemoizations = resetMemoizations;
25/**
26 * Memoize decorator to be used on class methods. WARNING: the `this` reference
27 * will be inaccessible within a memoized method, given that a cached method's `this`
28 * would not be instance-specific.
29 *
30 * @public
31 */
32function memoize(target, key, descriptor) {
33 // We bind to "null" to prevent people from inadvertently pulling values from "this",
34 // rather than passing them in as input values which can be memoized.
35 var fn = memoizeFunction(descriptor.value && descriptor.value.bind(null));
36 return {
37 configurable: true,
38 get: function () {
39 return fn;
40 },
41 };
42}
43exports.memoize = memoize;
44/**
45 * Memoizes a function; when you pass in the same parameters multiple times, it returns a cached result.
46 * Be careful when passing in objects, you need to pass in the same INSTANCE for caching to work. Otherwise
47 * it will grow the cache unnecessarily. Also avoid using default values that evaluate functions; passing in
48 * undefined for a value and relying on a default function will execute it the first time, but will not
49 * re-evaluate subsequent times which may have been unexpected.
50 *
51 * By default, the cache will reset after 100 permutations, to avoid abuse cases where the function is
52 * unintendedly called with unique objects. Without a reset, the cache could grow infinitely, so we safeguard
53 * by resetting. To override this behavior, pass a value of 0 to the maxCacheSize parameter.
54 *
55 * @public
56 * @param cb - The function to memoize.
57 * @param maxCacheSize - Max results to cache. If the cache exceeds this value, it will reset on the next call.
58 * @param ignoreNullOrUndefinedResult - Flag to decide whether to cache callback result if it is undefined/null.
59 * If the flag is set to true, the callback result is recomputed every time till the callback result is
60 * not undefined/null for the first time, and then the non-undefined/null version gets cached.
61 * @returns A memoized version of the function.
62 */
63function memoizeFunction(cb, maxCacheSize, ignoreNullOrUndefinedResult) {
64 if (maxCacheSize === void 0) { maxCacheSize = 100; }
65 if (ignoreNullOrUndefinedResult === void 0) { ignoreNullOrUndefinedResult = false; }
66 // Avoid breaking scenarios which don't have weak map.
67 if (!_weakMap) {
68 return cb;
69 }
70 if (!_initializedStylesheetResets) {
71 var stylesheet = merge_styles_1.Stylesheet.getInstance();
72 if (stylesheet && stylesheet.onReset) {
73 merge_styles_1.Stylesheet.getInstance().onReset(resetMemoizations);
74 }
75 _initializedStylesheetResets = true;
76 }
77 var rootNode;
78 var cacheSize = 0;
79 var localResetCounter = _resetCounter;
80 return function memoizedFunction() {
81 var args = [];
82 for (var _i = 0; _i < arguments.length; _i++) {
83 args[_i] = arguments[_i];
84 }
85 var currentNode = rootNode;
86 if (rootNode === undefined ||
87 localResetCounter !== _resetCounter ||
88 (maxCacheSize > 0 && cacheSize > maxCacheSize)) {
89 rootNode = _createNode();
90 cacheSize = 0;
91 localResetCounter = _resetCounter;
92 }
93 currentNode = rootNode;
94 // Traverse the tree until we find the match.
95 for (var i = 0; i < args.length; i++) {
96 var arg = _normalizeArg(args[i]);
97 if (!currentNode.map.has(arg)) {
98 currentNode.map.set(arg, _createNode());
99 }
100 currentNode = currentNode.map.get(arg);
101 }
102 if (!currentNode.hasOwnProperty('value')) {
103 currentNode.value = cb.apply(void 0, args);
104 cacheSize++;
105 }
106 if (ignoreNullOrUndefinedResult && (currentNode.value === null || currentNode.value === undefined)) {
107 currentNode.value = cb.apply(void 0, args);
108 }
109 return currentNode.value;
110 };
111}
112exports.memoizeFunction = memoizeFunction;
113/**
114 * Creates a memoizer for a single-value function, backed by a WeakMap.
115 * With a WeakMap, the memoized values are only kept as long as the source objects,
116 * ensuring that there is no memory leak.
117 *
118 * This function assumes that the input values passed to the wrapped function will be
119 * `function` or `object` types. To memoize functions which accept other inputs, use
120 * `memoizeFunction`, which memoizes against arbitrary inputs using a lookup cache.
121 *
122 * @public
123 */
124function createMemoizer(getValue) {
125 if (!_weakMap) {
126 // Without a `WeakMap` implementation, memoization is not possible.
127 return getValue;
128 }
129 var cache = new _weakMap();
130 function memoizedGetValue(input) {
131 if (!input || (typeof input !== 'function' && typeof input !== 'object')) {
132 // A WeakMap can only be used to test against reference values, i.e. 'function' and 'object'.
133 // All other inputs cannot be memoized against in this manner.
134 return getValue(input);
135 }
136 if (cache.has(input)) {
137 return cache.get(input);
138 }
139 var value = getValue(input);
140 cache.set(input, value);
141 return value;
142 }
143 return memoizedGetValue;
144}
145exports.createMemoizer = createMemoizer;
146function _normalizeArg(val) {
147 if (!val) {
148 return _emptyObject;
149 }
150 else if (typeof val === 'object' || typeof val === 'function') {
151 return val;
152 }
153 else if (!_dictionary[val]) {
154 _dictionary[val] = { val: val };
155 }
156 return _dictionary[val];
157}
158function _createNode() {
159 return {
160 map: _weakMap ? new _weakMap() : null,
161 };
162}
163//# sourceMappingURL=memoize.js.map
\No newline at end of file