UNPKG

5.32 kBJavaScriptView Raw
1import { defaultMemoize, defaultEqualityCheck } from './defaultMemoize';
2export { defaultMemoize, defaultEqualityCheck };
3
4function getDependencies(funcs) {
5 var dependencies = Array.isArray(funcs[0]) ? funcs[0] : funcs;
6
7 if (!dependencies.every(function (dep) {
8 return typeof dep === 'function';
9 })) {
10 var dependencyTypes = dependencies.map(function (dep) {
11 return typeof dep === 'function' ? "function " + (dep.name || 'unnamed') + "()" : typeof dep;
12 }).join(', ');
13 throw new Error("createSelector expects all input-selectors to be functions, but received the following types: [" + dependencyTypes + "]");
14 }
15
16 return dependencies;
17}
18
19export function createSelectorCreator(memoize) {
20 for (var _len = arguments.length, memoizeOptionsFromArgs = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
21 memoizeOptionsFromArgs[_key - 1] = arguments[_key];
22 }
23
24 var createSelector = function createSelector() {
25 for (var _len2 = arguments.length, funcs = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
26 funcs[_key2] = arguments[_key2];
27 }
28
29 var _recomputations = 0;
30
31 var _lastResult; // Due to the intricacies of rest params, we can't do an optional arg after `...funcs`.
32 // So, start by declaring the default value here.
33 // (And yes, the words 'memoize' and 'options' appear too many times in this next sequence.)
34
35
36 var directlyPassedOptions = {
37 memoizeOptions: undefined
38 }; // Normally, the result func or "output selector" is the last arg
39
40 var resultFunc = funcs.pop(); // If the result func is actually an _object_, assume it's our options object
41
42 if (typeof resultFunc === 'object') {
43 directlyPassedOptions = resultFunc; // and pop the real result func off
44
45 resultFunc = funcs.pop();
46 }
47
48 if (typeof resultFunc !== 'function') {
49 throw new Error("createSelector expects an output function after the inputs, but received: [" + typeof resultFunc + "]");
50 } // Determine which set of options we're using. Prefer options passed directly,
51 // but fall back to options given to createSelectorCreator.
52
53
54 var _directlyPassedOption = directlyPassedOptions,
55 _directlyPassedOption2 = _directlyPassedOption.memoizeOptions,
56 memoizeOptions = _directlyPassedOption2 === void 0 ? memoizeOptionsFromArgs : _directlyPassedOption2; // Simplifying assumption: it's unlikely that the first options arg of the provided memoizer
57 // is an array. In most libs I've looked at, it's an equality function or options object.
58 // Based on that, if `memoizeOptions` _is_ an array, we assume it's a full
59 // user-provided array of options. Otherwise, it must be just the _first_ arg, and so
60 // we wrap it in an array so we can apply it.
61
62 var finalMemoizeOptions = Array.isArray(memoizeOptions) ? memoizeOptions : [memoizeOptions];
63 var dependencies = getDependencies(funcs);
64 var memoizedResultFunc = memoize.apply(void 0, [function recomputationWrapper() {
65 _recomputations++; // apply arguments instead of spreading for performance.
66
67 return resultFunc.apply(null, arguments);
68 }].concat(finalMemoizeOptions)); // If a selector is called with the exact same arguments we don't need to traverse our dependencies again.
69
70 var selector = memoize(function dependenciesChecker() {
71 var params = [];
72 var length = dependencies.length;
73
74 for (var i = 0; i < length; i++) {
75 // apply arguments instead of spreading and mutate a local list of params for performance.
76 // @ts-ignore
77 params.push(dependencies[i].apply(null, arguments));
78 } // apply arguments instead of spreading for performance.
79
80
81 _lastResult = memoizedResultFunc.apply(null, params);
82 return _lastResult;
83 });
84 Object.assign(selector, {
85 resultFunc: resultFunc,
86 memoizedResultFunc: memoizedResultFunc,
87 dependencies: dependencies,
88 lastResult: function lastResult() {
89 return _lastResult;
90 },
91 recomputations: function recomputations() {
92 return _recomputations;
93 },
94 resetRecomputations: function resetRecomputations() {
95 return _recomputations = 0;
96 }
97 });
98 return selector;
99 }; // @ts-ignore
100
101
102 return createSelector;
103}
104export var createSelector = /* #__PURE__ */createSelectorCreator(defaultMemoize);
105// Manual definition of state and output arguments
106export var createStructuredSelector = function createStructuredSelector(selectors, selectorCreator) {
107 if (selectorCreator === void 0) {
108 selectorCreator = createSelector;
109 }
110
111 if (typeof selectors !== 'object') {
112 throw new Error('createStructuredSelector expects first argument to be an object ' + ("where each property is a selector, instead received a " + typeof selectors));
113 }
114
115 var objectKeys = Object.keys(selectors);
116 var resultSelector = selectorCreator( // @ts-ignore
117 objectKeys.map(function (key) {
118 return selectors[key];
119 }), function () {
120 for (var _len3 = arguments.length, values = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
121 values[_key3] = arguments[_key3];
122 }
123
124 return values.reduce(function (composition, value, index) {
125 composition[objectKeys[index]] = value;
126 return composition;
127 }, {});
128 });
129 return resultSelector;
130};
\No newline at end of file