source: node_modules/reselect/dist/reselect.mjs

main
Last change on this file was d24f17c, checked in by Aleksandar Panovski <apano77@…>, 15 months ago

Initial commit

  • Property mode set to 100644
File size: 21.4 KB
Line 
1// src/devModeChecks/identityFunctionCheck.ts
2var runIdentityFunctionCheck = (resultFunc, inputSelectorsResults, outputSelectorResult) => {
3 if (inputSelectorsResults.length === 1 && inputSelectorsResults[0] === outputSelectorResult) {
4 let isInputSameAsOutput = false;
5 try {
6 const emptyObject = {};
7 if (resultFunc(emptyObject) === emptyObject)
8 isInputSameAsOutput = true;
9 } catch {
10 }
11 if (isInputSameAsOutput) {
12 let stack = void 0;
13 try {
14 throw new Error();
15 } catch (e) {
16 ;
17 ({ stack } = e);
18 }
19 console.warn(
20 "The result function returned its own inputs without modification. e.g\n`createSelector([state => state.todos], todos => todos)`\nThis could lead to inefficient memoization and unnecessary re-renders.\nEnsure transformation logic is in the result function, and extraction logic is in the input selectors.",
21 { stack }
22 );
23 }
24 }
25};
26
27// src/devModeChecks/inputStabilityCheck.ts
28var runInputStabilityCheck = (inputSelectorResultsObject, options, inputSelectorArgs) => {
29 const { memoize, memoizeOptions } = options;
30 const { inputSelectorResults, inputSelectorResultsCopy } = inputSelectorResultsObject;
31 const createAnEmptyObject = memoize(() => ({}), ...memoizeOptions);
32 const areInputSelectorResultsEqual = createAnEmptyObject.apply(null, inputSelectorResults) === createAnEmptyObject.apply(null, inputSelectorResultsCopy);
33 if (!areInputSelectorResultsEqual) {
34 let stack = void 0;
35 try {
36 throw new Error();
37 } catch (e) {
38 ;
39 ({ stack } = e);
40 }
41 console.warn(
42 "An input selector returned a different result when passed same arguments.\nThis means your output selector will likely run more frequently than intended.\nAvoid returning a new reference inside your input selector, e.g.\n`createSelector([state => state.todos.map(todo => todo.id)], todoIds => todoIds.length)`",
43 {
44 arguments: inputSelectorArgs,
45 firstInputs: inputSelectorResults,
46 secondInputs: inputSelectorResultsCopy,
47 stack
48 }
49 );
50 }
51};
52
53// src/devModeChecks/setGlobalDevModeChecks.ts
54var globalDevModeChecks = {
55 inputStabilityCheck: "once",
56 identityFunctionCheck: "once"
57};
58var setGlobalDevModeChecks = (devModeChecks) => {
59 Object.assign(globalDevModeChecks, devModeChecks);
60};
61
62// src/utils.ts
63var NOT_FOUND = "NOT_FOUND";
64function assertIsFunction(func, errorMessage = `expected a function, instead received ${typeof func}`) {
65 if (typeof func !== "function") {
66 throw new TypeError(errorMessage);
67 }
68}
69function assertIsObject(object, errorMessage = `expected an object, instead received ${typeof object}`) {
70 if (typeof object !== "object") {
71 throw new TypeError(errorMessage);
72 }
73}
74function assertIsArrayOfFunctions(array, errorMessage = `expected all items to be functions, instead received the following types: `) {
75 if (!array.every((item) => typeof item === "function")) {
76 const itemTypes = array.map(
77 (item) => typeof item === "function" ? `function ${item.name || "unnamed"}()` : typeof item
78 ).join(", ");
79 throw new TypeError(`${errorMessage}[${itemTypes}]`);
80 }
81}
82var ensureIsArray = (item) => {
83 return Array.isArray(item) ? item : [item];
84};
85function getDependencies(createSelectorArgs) {
86 const dependencies = Array.isArray(createSelectorArgs[0]) ? createSelectorArgs[0] : createSelectorArgs;
87 assertIsArrayOfFunctions(
88 dependencies,
89 `createSelector expects all input-selectors to be functions, but received the following types: `
90 );
91 return dependencies;
92}
93function collectInputSelectorResults(dependencies, inputSelectorArgs) {
94 const inputSelectorResults = [];
95 const { length } = dependencies;
96 for (let i = 0; i < length; i++) {
97 inputSelectorResults.push(dependencies[i].apply(null, inputSelectorArgs));
98 }
99 return inputSelectorResults;
100}
101var getDevModeChecksExecutionInfo = (firstRun, devModeChecks) => {
102 const { identityFunctionCheck, inputStabilityCheck } = {
103 ...globalDevModeChecks,
104 ...devModeChecks
105 };
106 return {
107 identityFunctionCheck: {
108 shouldRun: identityFunctionCheck === "always" || identityFunctionCheck === "once" && firstRun,
109 run: runIdentityFunctionCheck
110 },
111 inputStabilityCheck: {
112 shouldRun: inputStabilityCheck === "always" || inputStabilityCheck === "once" && firstRun,
113 run: runInputStabilityCheck
114 }
115 };
116};
117
118// src/autotrackMemoize/autotracking.ts
119var $REVISION = 0;
120var CURRENT_TRACKER = null;
121var Cell = class {
122 revision = $REVISION;
123 _value;
124 _lastValue;
125 _isEqual = tripleEq;
126 constructor(initialValue, isEqual = tripleEq) {
127 this._value = this._lastValue = initialValue;
128 this._isEqual = isEqual;
129 }
130 // Whenever a storage value is read, it'll add itself to the current tracker if
131 // one exists, entangling its state with that cache.
132 get value() {
133 CURRENT_TRACKER?.add(this);
134 return this._value;
135 }
136 // Whenever a storage value is updated, we bump the global revision clock,
137 // assign the revision for this storage to the new value, _and_ we schedule a
138 // rerender. This is important, and it's what makes autotracking _pull_
139 // based. We don't actively tell the caches which depend on the storage that
140 // anything has happened. Instead, we recompute the caches when needed.
141 set value(newValue) {
142 if (this.value === newValue)
143 return;
144 this._value = newValue;
145 this.revision = ++$REVISION;
146 }
147};
148function tripleEq(a, b) {
149 return a === b;
150}
151var TrackingCache = class {
152 _cachedValue;
153 _cachedRevision = -1;
154 _deps = [];
155 hits = 0;
156 fn;
157 constructor(fn) {
158 this.fn = fn;
159 }
160 clear() {
161 this._cachedValue = void 0;
162 this._cachedRevision = -1;
163 this._deps = [];
164 this.hits = 0;
165 }
166 get value() {
167 if (this.revision > this._cachedRevision) {
168 const { fn } = this;
169 const currentTracker = /* @__PURE__ */ new Set();
170 const prevTracker = CURRENT_TRACKER;
171 CURRENT_TRACKER = currentTracker;
172 this._cachedValue = fn();
173 CURRENT_TRACKER = prevTracker;
174 this.hits++;
175 this._deps = Array.from(currentTracker);
176 this._cachedRevision = this.revision;
177 }
178 CURRENT_TRACKER?.add(this);
179 return this._cachedValue;
180 }
181 get revision() {
182 return Math.max(...this._deps.map((d) => d.revision), 0);
183 }
184};
185function getValue(cell) {
186 if (!(cell instanceof Cell)) {
187 console.warn("Not a valid cell! ", cell);
188 }
189 return cell.value;
190}
191function setValue(storage, value) {
192 if (!(storage instanceof Cell)) {
193 throw new TypeError(
194 "setValue must be passed a tracked store created with `createStorage`."
195 );
196 }
197 storage.value = storage._lastValue = value;
198}
199function createCell(initialValue, isEqual = tripleEq) {
200 return new Cell(initialValue, isEqual);
201}
202function createCache(fn) {
203 assertIsFunction(
204 fn,
205 "the first parameter to `createCache` must be a function"
206 );
207 return new TrackingCache(fn);
208}
209
210// src/autotrackMemoize/tracking.ts
211var neverEq = (a, b) => false;
212function createTag() {
213 return createCell(null, neverEq);
214}
215function dirtyTag(tag, value) {
216 setValue(tag, value);
217}
218var consumeCollection = (node) => {
219 let tag = node.collectionTag;
220 if (tag === null) {
221 tag = node.collectionTag = createTag();
222 }
223 getValue(tag);
224};
225var dirtyCollection = (node) => {
226 const tag = node.collectionTag;
227 if (tag !== null) {
228 dirtyTag(tag, null);
229 }
230};
231
232// src/autotrackMemoize/proxy.ts
233var REDUX_PROXY_LABEL = Symbol();
234var nextId = 0;
235var proto = Object.getPrototypeOf({});
236var ObjectTreeNode = class {
237 constructor(value) {
238 this.value = value;
239 this.value = value;
240 this.tag.value = value;
241 }
242 proxy = new Proxy(this, objectProxyHandler);
243 tag = createTag();
244 tags = {};
245 children = {};
246 collectionTag = null;
247 id = nextId++;
248};
249var objectProxyHandler = {
250 get(node, key) {
251 function calculateResult() {
252 const { value } = node;
253 const childValue = Reflect.get(value, key);
254 if (typeof key === "symbol") {
255 return childValue;
256 }
257 if (key in proto) {
258 return childValue;
259 }
260 if (typeof childValue === "object" && childValue !== null) {
261 let childNode = node.children[key];
262 if (childNode === void 0) {
263 childNode = node.children[key] = createNode(childValue);
264 }
265 if (childNode.tag) {
266 getValue(childNode.tag);
267 }
268 return childNode.proxy;
269 } else {
270 let tag = node.tags[key];
271 if (tag === void 0) {
272 tag = node.tags[key] = createTag();
273 tag.value = childValue;
274 }
275 getValue(tag);
276 return childValue;
277 }
278 }
279 const res = calculateResult();
280 return res;
281 },
282 ownKeys(node) {
283 consumeCollection(node);
284 return Reflect.ownKeys(node.value);
285 },
286 getOwnPropertyDescriptor(node, prop) {
287 return Reflect.getOwnPropertyDescriptor(node.value, prop);
288 },
289 has(node, prop) {
290 return Reflect.has(node.value, prop);
291 }
292};
293var ArrayTreeNode = class {
294 constructor(value) {
295 this.value = value;
296 this.value = value;
297 this.tag.value = value;
298 }
299 proxy = new Proxy([this], arrayProxyHandler);
300 tag = createTag();
301 tags = {};
302 children = {};
303 collectionTag = null;
304 id = nextId++;
305};
306var arrayProxyHandler = {
307 get([node], key) {
308 if (key === "length") {
309 consumeCollection(node);
310 }
311 return objectProxyHandler.get(node, key);
312 },
313 ownKeys([node]) {
314 return objectProxyHandler.ownKeys(node);
315 },
316 getOwnPropertyDescriptor([node], prop) {
317 return objectProxyHandler.getOwnPropertyDescriptor(node, prop);
318 },
319 has([node], prop) {
320 return objectProxyHandler.has(node, prop);
321 }
322};
323function createNode(value) {
324 if (Array.isArray(value)) {
325 return new ArrayTreeNode(value);
326 }
327 return new ObjectTreeNode(value);
328}
329function updateNode(node, newValue) {
330 const { value, tags, children } = node;
331 node.value = newValue;
332 if (Array.isArray(value) && Array.isArray(newValue) && value.length !== newValue.length) {
333 dirtyCollection(node);
334 } else {
335 if (value !== newValue) {
336 let oldKeysSize = 0;
337 let newKeysSize = 0;
338 let anyKeysAdded = false;
339 for (const _key in value) {
340 oldKeysSize++;
341 }
342 for (const key in newValue) {
343 newKeysSize++;
344 if (!(key in value)) {
345 anyKeysAdded = true;
346 break;
347 }
348 }
349 const isDifferent = anyKeysAdded || oldKeysSize !== newKeysSize;
350 if (isDifferent) {
351 dirtyCollection(node);
352 }
353 }
354 }
355 for (const key in tags) {
356 const childValue = value[key];
357 const newChildValue = newValue[key];
358 if (childValue !== newChildValue) {
359 dirtyCollection(node);
360 dirtyTag(tags[key], newChildValue);
361 }
362 if (typeof newChildValue === "object" && newChildValue !== null) {
363 delete tags[key];
364 }
365 }
366 for (const key in children) {
367 const childNode = children[key];
368 const newChildValue = newValue[key];
369 const childValue = childNode.value;
370 if (childValue === newChildValue) {
371 continue;
372 } else if (typeof newChildValue === "object" && newChildValue !== null) {
373 updateNode(childNode, newChildValue);
374 } else {
375 deleteNode(childNode);
376 delete children[key];
377 }
378 }
379}
380function deleteNode(node) {
381 if (node.tag) {
382 dirtyTag(node.tag, null);
383 }
384 dirtyCollection(node);
385 for (const key in node.tags) {
386 dirtyTag(node.tags[key], null);
387 }
388 for (const key in node.children) {
389 deleteNode(node.children[key]);
390 }
391}
392
393// src/lruMemoize.ts
394function createSingletonCache(equals) {
395 let entry;
396 return {
397 get(key) {
398 if (entry && equals(entry.key, key)) {
399 return entry.value;
400 }
401 return NOT_FOUND;
402 },
403 put(key, value) {
404 entry = { key, value };
405 },
406 getEntries() {
407 return entry ? [entry] : [];
408 },
409 clear() {
410 entry = void 0;
411 }
412 };
413}
414function createLruCache(maxSize, equals) {
415 let entries = [];
416 function get(key) {
417 const cacheIndex = entries.findIndex((entry) => equals(key, entry.key));
418 if (cacheIndex > -1) {
419 const entry = entries[cacheIndex];
420 if (cacheIndex > 0) {
421 entries.splice(cacheIndex, 1);
422 entries.unshift(entry);
423 }
424 return entry.value;
425 }
426 return NOT_FOUND;
427 }
428 function put(key, value) {
429 if (get(key) === NOT_FOUND) {
430 entries.unshift({ key, value });
431 if (entries.length > maxSize) {
432 entries.pop();
433 }
434 }
435 }
436 function getEntries() {
437 return entries;
438 }
439 function clear() {
440 entries = [];
441 }
442 return { get, put, getEntries, clear };
443}
444var referenceEqualityCheck = (a, b) => a === b;
445function createCacheKeyComparator(equalityCheck) {
446 return function areArgumentsShallowlyEqual(prev, next) {
447 if (prev === null || next === null || prev.length !== next.length) {
448 return false;
449 }
450 const { length } = prev;
451 for (let i = 0; i < length; i++) {
452 if (!equalityCheck(prev[i], next[i])) {
453 return false;
454 }
455 }
456 return true;
457 };
458}
459function lruMemoize(func, equalityCheckOrOptions) {
460 const providedOptions = typeof equalityCheckOrOptions === "object" ? equalityCheckOrOptions : { equalityCheck: equalityCheckOrOptions };
461 const {
462 equalityCheck = referenceEqualityCheck,
463 maxSize = 1,
464 resultEqualityCheck
465 } = providedOptions;
466 const comparator = createCacheKeyComparator(equalityCheck);
467 let resultsCount = 0;
468 const cache = maxSize === 1 ? createSingletonCache(comparator) : createLruCache(maxSize, comparator);
469 function memoized() {
470 let value = cache.get(arguments);
471 if (value === NOT_FOUND) {
472 value = func.apply(null, arguments);
473 resultsCount++;
474 if (resultEqualityCheck) {
475 const entries = cache.getEntries();
476 const matchingEntry = entries.find(
477 (entry) => resultEqualityCheck(entry.value, value)
478 );
479 if (matchingEntry) {
480 value = matchingEntry.value;
481 resultsCount !== 0 && resultsCount--;
482 }
483 }
484 cache.put(arguments, value);
485 }
486 return value;
487 }
488 memoized.clearCache = () => {
489 cache.clear();
490 memoized.resetResultsCount();
491 };
492 memoized.resultsCount = () => resultsCount;
493 memoized.resetResultsCount = () => {
494 resultsCount = 0;
495 };
496 return memoized;
497}
498
499// src/autotrackMemoize/autotrackMemoize.ts
500function autotrackMemoize(func) {
501 const node = createNode(
502 []
503 );
504 let lastArgs = null;
505 const shallowEqual = createCacheKeyComparator(referenceEqualityCheck);
506 const cache = createCache(() => {
507 const res = func.apply(null, node.proxy);
508 return res;
509 });
510 function memoized() {
511 if (!shallowEqual(lastArgs, arguments)) {
512 updateNode(node, arguments);
513 lastArgs = arguments;
514 }
515 return cache.value;
516 }
517 memoized.clearCache = () => {
518 return cache.clear();
519 };
520 return memoized;
521}
522
523// src/weakMapMemoize.ts
524var StrongRef = class {
525 constructor(value) {
526 this.value = value;
527 }
528 deref() {
529 return this.value;
530 }
531};
532var Ref = typeof WeakRef !== "undefined" ? WeakRef : StrongRef;
533var UNTERMINATED = 0;
534var TERMINATED = 1;
535function createCacheNode() {
536 return {
537 s: UNTERMINATED,
538 v: void 0,
539 o: null,
540 p: null
541 };
542}
543function weakMapMemoize(func, options = {}) {
544 let fnNode = createCacheNode();
545 const { resultEqualityCheck } = options;
546 let lastResult;
547 let resultsCount = 0;
548 function memoized() {
549 let cacheNode = fnNode;
550 const { length } = arguments;
551 for (let i = 0, l = length; i < l; i++) {
552 const arg = arguments[i];
553 if (typeof arg === "function" || typeof arg === "object" && arg !== null) {
554 let objectCache = cacheNode.o;
555 if (objectCache === null) {
556 cacheNode.o = objectCache = /* @__PURE__ */ new WeakMap();
557 }
558 const objectNode = objectCache.get(arg);
559 if (objectNode === void 0) {
560 cacheNode = createCacheNode();
561 objectCache.set(arg, cacheNode);
562 } else {
563 cacheNode = objectNode;
564 }
565 } else {
566 let primitiveCache = cacheNode.p;
567 if (primitiveCache === null) {
568 cacheNode.p = primitiveCache = /* @__PURE__ */ new Map();
569 }
570 const primitiveNode = primitiveCache.get(arg);
571 if (primitiveNode === void 0) {
572 cacheNode = createCacheNode();
573 primitiveCache.set(arg, cacheNode);
574 } else {
575 cacheNode = primitiveNode;
576 }
577 }
578 }
579 const terminatedNode = cacheNode;
580 let result;
581 if (cacheNode.s === TERMINATED) {
582 result = cacheNode.v;
583 } else {
584 result = func.apply(null, arguments);
585 resultsCount++;
586 }
587 terminatedNode.s = TERMINATED;
588 if (resultEqualityCheck) {
589 const lastResultValue = lastResult?.deref?.() ?? lastResult;
590 if (lastResultValue != null && resultEqualityCheck(lastResultValue, result)) {
591 result = lastResultValue;
592 resultsCount !== 0 && resultsCount--;
593 }
594 const needsWeakRef = typeof result === "object" && result !== null || typeof result === "function";
595 lastResult = needsWeakRef ? new Ref(result) : result;
596 }
597 terminatedNode.v = result;
598 return result;
599 }
600 memoized.clearCache = () => {
601 fnNode = createCacheNode();
602 memoized.resetResultsCount();
603 };
604 memoized.resultsCount = () => resultsCount;
605 memoized.resetResultsCount = () => {
606 resultsCount = 0;
607 };
608 return memoized;
609}
610
611// src/createSelectorCreator.ts
612function createSelectorCreator(memoizeOrOptions, ...memoizeOptionsFromArgs) {
613 const createSelectorCreatorOptions = typeof memoizeOrOptions === "function" ? {
614 memoize: memoizeOrOptions,
615 memoizeOptions: memoizeOptionsFromArgs
616 } : memoizeOrOptions;
617 const createSelector2 = (...createSelectorArgs) => {
618 let recomputations = 0;
619 let dependencyRecomputations = 0;
620 let lastResult;
621 let directlyPassedOptions = {};
622 let resultFunc = createSelectorArgs.pop();
623 if (typeof resultFunc === "object") {
624 directlyPassedOptions = resultFunc;
625 resultFunc = createSelectorArgs.pop();
626 }
627 assertIsFunction(
628 resultFunc,
629 `createSelector expects an output function after the inputs, but received: [${typeof resultFunc}]`
630 );
631 const combinedOptions = {
632 ...createSelectorCreatorOptions,
633 ...directlyPassedOptions
634 };
635 const {
636 memoize,
637 memoizeOptions = [],
638 argsMemoize = weakMapMemoize,
639 argsMemoizeOptions = [],
640 devModeChecks = {}
641 } = combinedOptions;
642 const finalMemoizeOptions = ensureIsArray(memoizeOptions);
643 const finalArgsMemoizeOptions = ensureIsArray(argsMemoizeOptions);
644 const dependencies = getDependencies(createSelectorArgs);
645 const memoizedResultFunc = memoize(function recomputationWrapper() {
646 recomputations++;
647 return resultFunc.apply(
648 null,
649 arguments
650 );
651 }, ...finalMemoizeOptions);
652 let firstRun = true;
653 const selector = argsMemoize(function dependenciesChecker() {
654 dependencyRecomputations++;
655 const inputSelectorResults = collectInputSelectorResults(
656 dependencies,
657 arguments
658 );
659 lastResult = memoizedResultFunc.apply(null, inputSelectorResults);
660 if (process.env.NODE_ENV !== "production") {
661 const { identityFunctionCheck, inputStabilityCheck } = getDevModeChecksExecutionInfo(firstRun, devModeChecks);
662 if (identityFunctionCheck.shouldRun) {
663 identityFunctionCheck.run(
664 resultFunc,
665 inputSelectorResults,
666 lastResult
667 );
668 }
669 if (inputStabilityCheck.shouldRun) {
670 const inputSelectorResultsCopy = collectInputSelectorResults(
671 dependencies,
672 arguments
673 );
674 inputStabilityCheck.run(
675 { inputSelectorResults, inputSelectorResultsCopy },
676 { memoize, memoizeOptions: finalMemoizeOptions },
677 arguments
678 );
679 }
680 if (firstRun)
681 firstRun = false;
682 }
683 return lastResult;
684 }, ...finalArgsMemoizeOptions);
685 return Object.assign(selector, {
686 resultFunc,
687 memoizedResultFunc,
688 dependencies,
689 dependencyRecomputations: () => dependencyRecomputations,
690 resetDependencyRecomputations: () => {
691 dependencyRecomputations = 0;
692 },
693 lastResult: () => lastResult,
694 recomputations: () => recomputations,
695 resetRecomputations: () => {
696 recomputations = 0;
697 },
698 memoize,
699 argsMemoize
700 });
701 };
702 Object.assign(createSelector2, {
703 withTypes: () => createSelector2
704 });
705 return createSelector2;
706}
707var createSelector = /* @__PURE__ */ createSelectorCreator(weakMapMemoize);
708
709// src/createStructuredSelector.ts
710var createStructuredSelector = Object.assign(
711 (inputSelectorsObject, selectorCreator = createSelector) => {
712 assertIsObject(
713 inputSelectorsObject,
714 `createStructuredSelector expects first argument to be an object where each property is a selector, instead received a ${typeof inputSelectorsObject}`
715 );
716 const inputSelectorKeys = Object.keys(inputSelectorsObject);
717 const dependencies = inputSelectorKeys.map(
718 (key) => inputSelectorsObject[key]
719 );
720 const structuredSelector = selectorCreator(
721 dependencies,
722 (...inputSelectorResults) => {
723 return inputSelectorResults.reduce((composition, value, index) => {
724 composition[inputSelectorKeys[index]] = value;
725 return composition;
726 }, {});
727 }
728 );
729 return structuredSelector;
730 },
731 { withTypes: () => createStructuredSelector }
732);
733export {
734 createSelector,
735 createSelectorCreator,
736 createStructuredSelector,
737 lruMemoize,
738 referenceEqualityCheck,
739 setGlobalDevModeChecks,
740 autotrackMemoize as unstable_autotrackMemoize,
741 weakMapMemoize
742};
743//# sourceMappingURL=reselect.mjs.map
Note: See TracBrowser for help on using the repository browser.