1 | "use strict";
|
2 |
|
3 |
|
4 |
|
5 | Object.defineProperty(exports, "__esModule", { value: true });
|
6 | exports.LRUCache = void 0;
|
7 | const perf = typeof performance === 'object' &&
|
8 | performance &&
|
9 | typeof performance.now === 'function'
|
10 | ? performance
|
11 | : Date;
|
12 | const warned = new Set();
|
13 |
|
14 | const PROCESS = (typeof process === 'object' && !!process ? process : {});
|
15 |
|
16 | const emitWarning = (msg, type, code, fn) => {
|
17 | typeof PROCESS.emitWarning === 'function'
|
18 | ? PROCESS.emitWarning(msg, type, code, fn)
|
19 | : console.error(`[${code}] ${type}: ${msg}`);
|
20 | };
|
21 | let AC = globalThis.AbortController;
|
22 | let AS = globalThis.AbortSignal;
|
23 |
|
24 | if (typeof AC === 'undefined') {
|
25 |
|
26 | AS = class AbortSignal {
|
27 | onabort;
|
28 | _onabort = [];
|
29 | reason;
|
30 | aborted = false;
|
31 | addEventListener(_, fn) {
|
32 | this._onabort.push(fn);
|
33 | }
|
34 | };
|
35 |
|
36 | AC = class AbortController {
|
37 | constructor() {
|
38 | warnACPolyfill();
|
39 | }
|
40 | signal = new AS();
|
41 | abort(reason) {
|
42 | if (this.signal.aborted)
|
43 | return;
|
44 |
|
45 | this.signal.reason = reason;
|
46 |
|
47 | this.signal.aborted = true;
|
48 |
|
49 | for (const fn of this.signal._onabort) {
|
50 | fn(reason);
|
51 | }
|
52 | this.signal.onabort?.(reason);
|
53 | }
|
54 | };
|
55 | let printACPolyfillWarning = PROCESS.env?.LRU_CACHE_IGNORE_AC_WARNING !== '1';
|
56 | const warnACPolyfill = () => {
|
57 | if (!printACPolyfillWarning)
|
58 | return;
|
59 | printACPolyfillWarning = false;
|
60 | emitWarning('AbortController is not defined. If using lru-cache in ' +
|
61 | 'node 14, load an AbortController polyfill from the ' +
|
62 | '`node-abort-controller` package. A minimal polyfill is ' +
|
63 | 'provided for use by LRUCache.fetch(), but it should not be ' +
|
64 | 'relied upon in other contexts (eg, passing it to other APIs that ' +
|
65 | 'use AbortController/AbortSignal might have undesirable effects). ' +
|
66 | 'You may disable this with LRU_CACHE_IGNORE_AC_WARNING=1 in the env.', 'NO_ABORT_CONTROLLER', 'ENOTSUP', warnACPolyfill);
|
67 | };
|
68 | }
|
69 |
|
70 | const shouldWarn = (code) => !warned.has(code);
|
71 | const TYPE = Symbol('type');
|
72 | const isPosInt = (n) => n && n === Math.floor(n) && n > 0 && isFinite(n);
|
73 |
|
74 |
|
75 |
|
76 |
|
77 |
|
78 |
|
79 |
|
80 |
|
81 |
|
82 | const getUintArray = (max) => !isPosInt(max)
|
83 | ? null
|
84 | : max <= Math.pow(2, 8)
|
85 | ? Uint8Array
|
86 | : max <= Math.pow(2, 16)
|
87 | ? Uint16Array
|
88 | : max <= Math.pow(2, 32)
|
89 | ? Uint32Array
|
90 | : max <= Number.MAX_SAFE_INTEGER
|
91 | ? ZeroArray
|
92 | : null;
|
93 |
|
94 | class ZeroArray extends Array {
|
95 | constructor(size) {
|
96 | super(size);
|
97 | this.fill(0);
|
98 | }
|
99 | }
|
100 | class Stack {
|
101 | heap;
|
102 | length;
|
103 |
|
104 | static #constructing = false;
|
105 | static create(max) {
|
106 | const HeapCls = getUintArray(max);
|
107 | if (!HeapCls)
|
108 | return [];
|
109 | Stack.#constructing = true;
|
110 | const s = new Stack(max, HeapCls);
|
111 | Stack.#constructing = false;
|
112 | return s;
|
113 | }
|
114 | constructor(max, HeapCls) {
|
115 |
|
116 | if (!Stack.#constructing) {
|
117 | throw new TypeError('instantiate Stack using Stack.create(n)');
|
118 | }
|
119 |
|
120 | this.heap = new HeapCls(max);
|
121 | this.length = 0;
|
122 | }
|
123 | push(n) {
|
124 | this.heap[this.length++] = n;
|
125 | }
|
126 | pop() {
|
127 | return this.heap[--this.length];
|
128 | }
|
129 | }
|
130 |
|
131 |
|
132 |
|
133 |
|
134 |
|
135 |
|
136 |
|
137 |
|
138 |
|
139 | class LRUCache {
|
140 |
|
141 |
|
142 |
|
143 | #max;
|
144 | #maxSize;
|
145 | #dispose;
|
146 | #disposeAfter;
|
147 | #fetchMethod;
|
148 | |
149 |
|
150 |
|
151 | ttl;
|
152 | |
153 |
|
154 |
|
155 | ttlResolution;
|
156 | |
157 |
|
158 |
|
159 | ttlAutopurge;
|
160 | |
161 |
|
162 |
|
163 | updateAgeOnGet;
|
164 | |
165 |
|
166 |
|
167 | updateAgeOnHas;
|
168 | |
169 |
|
170 |
|
171 | allowStale;
|
172 | |
173 |
|
174 |
|
175 | noDisposeOnSet;
|
176 | |
177 |
|
178 |
|
179 | noUpdateTTL;
|
180 | |
181 |
|
182 |
|
183 | maxEntrySize;
|
184 | |
185 |
|
186 |
|
187 | sizeCalculation;
|
188 | |
189 |
|
190 |
|
191 | noDeleteOnFetchRejection;
|
192 | |
193 |
|
194 |
|
195 | noDeleteOnStaleGet;
|
196 | |
197 |
|
198 |
|
199 | allowStaleOnFetchAbort;
|
200 | |
201 |
|
202 |
|
203 | allowStaleOnFetchRejection;
|
204 | |
205 |
|
206 |
|
207 | ignoreFetchAbort;
|
208 |
|
209 | #size;
|
210 | #calculatedSize;
|
211 | #keyMap;
|
212 | #keyList;
|
213 | #valList;
|
214 | #next;
|
215 | #prev;
|
216 | #head;
|
217 | #tail;
|
218 | #free;
|
219 | #disposed;
|
220 | #sizes;
|
221 | #starts;
|
222 | #ttls;
|
223 | #hasDispose;
|
224 | #hasFetchMethod;
|
225 | #hasDisposeAfter;
|
226 | |
227 |
|
228 |
|
229 |
|
230 |
|
231 |
|
232 |
|
233 |
|
234 |
|
235 | static unsafeExposeInternals(c) {
|
236 | return {
|
237 |
|
238 | starts: c.#starts,
|
239 | ttls: c.#ttls,
|
240 | sizes: c.#sizes,
|
241 | keyMap: c.#keyMap,
|
242 | keyList: c.#keyList,
|
243 | valList: c.#valList,
|
244 | next: c.#next,
|
245 | prev: c.#prev,
|
246 | get head() {
|
247 | return c.#head;
|
248 | },
|
249 | get tail() {
|
250 | return c.#tail;
|
251 | },
|
252 | free: c.#free,
|
253 |
|
254 | isBackgroundFetch: (p) => c.#isBackgroundFetch(p),
|
255 | backgroundFetch: (k, index, options, context) => c.#backgroundFetch(k, index, options, context),
|
256 | moveToTail: (index) => c.#moveToTail(index),
|
257 | indexes: (options) => c.#indexes(options),
|
258 | rindexes: (options) => c.#rindexes(options),
|
259 | isStale: (index) => c.#isStale(index),
|
260 | };
|
261 | }
|
262 |
|
263 | |
264 |
|
265 |
|
266 | get max() {
|
267 | return this.#max;
|
268 | }
|
269 | |
270 |
|
271 |
|
272 | get maxSize() {
|
273 | return this.#maxSize;
|
274 | }
|
275 | |
276 |
|
277 |
|
278 | get calculatedSize() {
|
279 | return this.#calculatedSize;
|
280 | }
|
281 | |
282 |
|
283 |
|
284 | get size() {
|
285 | return this.#size;
|
286 | }
|
287 | |
288 |
|
289 |
|
290 | get fetchMethod() {
|
291 | return this.#fetchMethod;
|
292 | }
|
293 | |
294 |
|
295 |
|
296 | get dispose() {
|
297 | return this.#dispose;
|
298 | }
|
299 | |
300 |
|
301 |
|
302 | get disposeAfter() {
|
303 | return this.#disposeAfter;
|
304 | }
|
305 | constructor(options) {
|
306 | const { max = 0, ttl, ttlResolution = 1, ttlAutopurge, updateAgeOnGet, updateAgeOnHas, allowStale, dispose, disposeAfter, noDisposeOnSet, noUpdateTTL, maxSize = 0, maxEntrySize = 0, sizeCalculation, fetchMethod, noDeleteOnFetchRejection, noDeleteOnStaleGet, allowStaleOnFetchRejection, allowStaleOnFetchAbort, ignoreFetchAbort, } = options;
|
307 | if (max !== 0 && !isPosInt(max)) {
|
308 | throw new TypeError('max option must be a nonnegative integer');
|
309 | }
|
310 | const UintArray = max ? getUintArray(max) : Array;
|
311 | if (!UintArray) {
|
312 | throw new Error('invalid max value: ' + max);
|
313 | }
|
314 | this.#max = max;
|
315 | this.#maxSize = maxSize;
|
316 | this.maxEntrySize = maxEntrySize || this.#maxSize;
|
317 | this.sizeCalculation = sizeCalculation;
|
318 | if (this.sizeCalculation) {
|
319 | if (!this.#maxSize && !this.maxEntrySize) {
|
320 | throw new TypeError('cannot set sizeCalculation without setting maxSize or maxEntrySize');
|
321 | }
|
322 | if (typeof this.sizeCalculation !== 'function') {
|
323 | throw new TypeError('sizeCalculation set to non-function');
|
324 | }
|
325 | }
|
326 | if (fetchMethod !== undefined &&
|
327 | typeof fetchMethod !== 'function') {
|
328 | throw new TypeError('fetchMethod must be a function if specified');
|
329 | }
|
330 | this.#fetchMethod = fetchMethod;
|
331 | this.#hasFetchMethod = !!fetchMethod;
|
332 | this.#keyMap = new Map();
|
333 | this.#keyList = new Array(max).fill(undefined);
|
334 | this.#valList = new Array(max).fill(undefined);
|
335 | this.#next = new UintArray(max);
|
336 | this.#prev = new UintArray(max);
|
337 | this.#head = 0;
|
338 | this.#tail = 0;
|
339 | this.#free = Stack.create(max);
|
340 | this.#size = 0;
|
341 | this.#calculatedSize = 0;
|
342 | if (typeof dispose === 'function') {
|
343 | this.#dispose = dispose;
|
344 | }
|
345 | if (typeof disposeAfter === 'function') {
|
346 | this.#disposeAfter = disposeAfter;
|
347 | this.#disposed = [];
|
348 | }
|
349 | else {
|
350 | this.#disposeAfter = undefined;
|
351 | this.#disposed = undefined;
|
352 | }
|
353 | this.#hasDispose = !!this.#dispose;
|
354 | this.#hasDisposeAfter = !!this.#disposeAfter;
|
355 | this.noDisposeOnSet = !!noDisposeOnSet;
|
356 | this.noUpdateTTL = !!noUpdateTTL;
|
357 | this.noDeleteOnFetchRejection = !!noDeleteOnFetchRejection;
|
358 | this.allowStaleOnFetchRejection = !!allowStaleOnFetchRejection;
|
359 | this.allowStaleOnFetchAbort = !!allowStaleOnFetchAbort;
|
360 | this.ignoreFetchAbort = !!ignoreFetchAbort;
|
361 |
|
362 | if (this.maxEntrySize !== 0) {
|
363 | if (this.#maxSize !== 0) {
|
364 | if (!isPosInt(this.#maxSize)) {
|
365 | throw new TypeError('maxSize must be a positive integer if specified');
|
366 | }
|
367 | }
|
368 | if (!isPosInt(this.maxEntrySize)) {
|
369 | throw new TypeError('maxEntrySize must be a positive integer if specified');
|
370 | }
|
371 | this.#initializeSizeTracking();
|
372 | }
|
373 | this.allowStale = !!allowStale;
|
374 | this.noDeleteOnStaleGet = !!noDeleteOnStaleGet;
|
375 | this.updateAgeOnGet = !!updateAgeOnGet;
|
376 | this.updateAgeOnHas = !!updateAgeOnHas;
|
377 | this.ttlResolution =
|
378 | isPosInt(ttlResolution) || ttlResolution === 0
|
379 | ? ttlResolution
|
380 | : 1;
|
381 | this.ttlAutopurge = !!ttlAutopurge;
|
382 | this.ttl = ttl || 0;
|
383 | if (this.ttl) {
|
384 | if (!isPosInt(this.ttl)) {
|
385 | throw new TypeError('ttl must be a positive integer if specified');
|
386 | }
|
387 | this.#initializeTTLTracking();
|
388 | }
|
389 |
|
390 | if (this.#max === 0 && this.ttl === 0 && this.#maxSize === 0) {
|
391 | throw new TypeError('At least one of max, maxSize, or ttl is required');
|
392 | }
|
393 | if (!this.ttlAutopurge && !this.#max && !this.#maxSize) {
|
394 | const code = 'LRU_CACHE_UNBOUNDED';
|
395 | if (shouldWarn(code)) {
|
396 | warned.add(code);
|
397 | const msg = 'TTL caching without ttlAutopurge, max, or maxSize can ' +
|
398 | 'result in unbounded memory consumption.';
|
399 | emitWarning(msg, 'UnboundedCacheWarning', code, LRUCache);
|
400 | }
|
401 | }
|
402 | }
|
403 | |
404 |
|
405 |
|
406 | getRemainingTTL(key) {
|
407 | return this.#keyMap.has(key) ? Infinity : 0;
|
408 | }
|
409 | #initializeTTLTracking() {
|
410 | const ttls = new ZeroArray(this.#max);
|
411 | const starts = new ZeroArray(this.#max);
|
412 | this.#ttls = ttls;
|
413 | this.#starts = starts;
|
414 | this.#setItemTTL = (index, ttl, start = perf.now()) => {
|
415 | starts[index] = ttl !== 0 ? start : 0;
|
416 | ttls[index] = ttl;
|
417 | if (ttl !== 0 && this.ttlAutopurge) {
|
418 | const t = setTimeout(() => {
|
419 | if (this.#isStale(index)) {
|
420 | this.delete(this.#keyList[index]);
|
421 | }
|
422 | }, ttl + 1);
|
423 |
|
424 |
|
425 | if (t.unref) {
|
426 | t.unref();
|
427 | }
|
428 |
|
429 | }
|
430 | };
|
431 | this.#updateItemAge = index => {
|
432 | starts[index] = ttls[index] !== 0 ? perf.now() : 0;
|
433 | };
|
434 | this.#statusTTL = (status, index) => {
|
435 | if (ttls[index]) {
|
436 | const ttl = ttls[index];
|
437 | const start = starts[index];
|
438 |
|
439 | if (!ttl || !start)
|
440 | return;
|
441 | status.ttl = ttl;
|
442 | status.start = start;
|
443 | status.now = cachedNow || getNow();
|
444 | const age = status.now - start;
|
445 | status.remainingTTL = ttl - age;
|
446 | }
|
447 | };
|
448 |
|
449 |
|
450 | let cachedNow = 0;
|
451 | const getNow = () => {
|
452 | const n = perf.now();
|
453 | if (this.ttlResolution > 0) {
|
454 | cachedNow = n;
|
455 | const t = setTimeout(() => (cachedNow = 0), this.ttlResolution);
|
456 |
|
457 |
|
458 | if (t.unref) {
|
459 | t.unref();
|
460 | }
|
461 |
|
462 | }
|
463 | return n;
|
464 | };
|
465 | this.getRemainingTTL = key => {
|
466 | const index = this.#keyMap.get(key);
|
467 | if (index === undefined) {
|
468 | return 0;
|
469 | }
|
470 | const ttl = ttls[index];
|
471 | const start = starts[index];
|
472 | if (!ttl || !start) {
|
473 | return Infinity;
|
474 | }
|
475 | const age = (cachedNow || getNow()) - start;
|
476 | return ttl - age;
|
477 | };
|
478 | this.#isStale = index => {
|
479 | const s = starts[index];
|
480 | const t = ttls[index];
|
481 | return !!t && !!s && (cachedNow || getNow()) - s > t;
|
482 | };
|
483 | }
|
484 |
|
485 | #updateItemAge = () => { };
|
486 | #statusTTL = () => { };
|
487 | #setItemTTL = () => { };
|
488 |
|
489 | #isStale = () => false;
|
490 | #initializeSizeTracking() {
|
491 | const sizes = new ZeroArray(this.#max);
|
492 | this.#calculatedSize = 0;
|
493 | this.#sizes = sizes;
|
494 | this.#removeItemSize = index => {
|
495 | this.#calculatedSize -= sizes[index];
|
496 | sizes[index] = 0;
|
497 | };
|
498 | this.#requireSize = (k, v, size, sizeCalculation) => {
|
499 |
|
500 |
|
501 | if (this.#isBackgroundFetch(v)) {
|
502 | return 0;
|
503 | }
|
504 | if (!isPosInt(size)) {
|
505 | if (sizeCalculation) {
|
506 | if (typeof sizeCalculation !== 'function') {
|
507 | throw new TypeError('sizeCalculation must be a function');
|
508 | }
|
509 | size = sizeCalculation(v, k);
|
510 | if (!isPosInt(size)) {
|
511 | throw new TypeError('sizeCalculation return invalid (expect positive integer)');
|
512 | }
|
513 | }
|
514 | else {
|
515 | throw new TypeError('invalid size value (must be positive integer). ' +
|
516 | 'When maxSize or maxEntrySize is used, sizeCalculation ' +
|
517 | 'or size must be set.');
|
518 | }
|
519 | }
|
520 | return size;
|
521 | };
|
522 | this.#addItemSize = (index, size, status) => {
|
523 | sizes[index] = size;
|
524 | if (this.#maxSize) {
|
525 | const maxSize = this.#maxSize - sizes[index];
|
526 | while (this.#calculatedSize > maxSize) {
|
527 | this.#evict(true);
|
528 | }
|
529 | }
|
530 | this.#calculatedSize += sizes[index];
|
531 | if (status) {
|
532 | status.entrySize = size;
|
533 | status.totalCalculatedSize = this.#calculatedSize;
|
534 | }
|
535 | };
|
536 | }
|
537 | #removeItemSize = _i => { };
|
538 | #addItemSize = (_i, _s, _st) => { };
|
539 | #requireSize = (_k, _v, size, sizeCalculation) => {
|
540 | if (size || sizeCalculation) {
|
541 | throw new TypeError('cannot set size without setting maxSize or maxEntrySize on cache');
|
542 | }
|
543 | return 0;
|
544 | };
|
545 | *#indexes({ allowStale = this.allowStale } = {}) {
|
546 | if (this.#size) {
|
547 | for (let i = this.#tail; true;) {
|
548 | if (!this.#isValidIndex(i)) {
|
549 | break;
|
550 | }
|
551 | if (allowStale || !this.#isStale(i)) {
|
552 | yield i;
|
553 | }
|
554 | if (i === this.#head) {
|
555 | break;
|
556 | }
|
557 | else {
|
558 | i = this.#prev[i];
|
559 | }
|
560 | }
|
561 | }
|
562 | }
|
563 | *#rindexes({ allowStale = this.allowStale } = {}) {
|
564 | if (this.#size) {
|
565 | for (let i = this.#head; true;) {
|
566 | if (!this.#isValidIndex(i)) {
|
567 | break;
|
568 | }
|
569 | if (allowStale || !this.#isStale(i)) {
|
570 | yield i;
|
571 | }
|
572 | if (i === this.#tail) {
|
573 | break;
|
574 | }
|
575 | else {
|
576 | i = this.#next[i];
|
577 | }
|
578 | }
|
579 | }
|
580 | }
|
581 | #isValidIndex(index) {
|
582 | return (index !== undefined &&
|
583 | this.#keyMap.get(this.#keyList[index]) === index);
|
584 | }
|
585 | |
586 |
|
587 |
|
588 |
|
589 | *entries() {
|
590 | for (const i of this.#indexes()) {
|
591 | if (this.#valList[i] !== undefined &&
|
592 | this.#keyList[i] !== undefined &&
|
593 | !this.#isBackgroundFetch(this.#valList[i])) {
|
594 | yield [this.#keyList[i], this.#valList[i]];
|
595 | }
|
596 | }
|
597 | }
|
598 | |
599 |
|
600 |
|
601 |
|
602 |
|
603 |
|
604 | *rentries() {
|
605 | for (const i of this.#rindexes()) {
|
606 | if (this.#valList[i] !== undefined &&
|
607 | this.#keyList[i] !== undefined &&
|
608 | !this.#isBackgroundFetch(this.#valList[i])) {
|
609 | yield [this.#keyList[i], this.#valList[i]];
|
610 | }
|
611 | }
|
612 | }
|
613 | |
614 |
|
615 |
|
616 |
|
617 | *keys() {
|
618 | for (const i of this.#indexes()) {
|
619 | const k = this.#keyList[i];
|
620 | if (k !== undefined &&
|
621 | !this.#isBackgroundFetch(this.#valList[i])) {
|
622 | yield k;
|
623 | }
|
624 | }
|
625 | }
|
626 | |
627 |
|
628 |
|
629 |
|
630 |
|
631 |
|
632 | *rkeys() {
|
633 | for (const i of this.#rindexes()) {
|
634 | const k = this.#keyList[i];
|
635 | if (k !== undefined &&
|
636 | !this.#isBackgroundFetch(this.#valList[i])) {
|
637 | yield k;
|
638 | }
|
639 | }
|
640 | }
|
641 | |
642 |
|
643 |
|
644 |
|
645 | *values() {
|
646 | for (const i of this.#indexes()) {
|
647 | const v = this.#valList[i];
|
648 | if (v !== undefined &&
|
649 | !this.#isBackgroundFetch(this.#valList[i])) {
|
650 | yield this.#valList[i];
|
651 | }
|
652 | }
|
653 | }
|
654 | |
655 |
|
656 |
|
657 |
|
658 |
|
659 |
|
660 | *rvalues() {
|
661 | for (const i of this.#rindexes()) {
|
662 | const v = this.#valList[i];
|
663 | if (v !== undefined &&
|
664 | !this.#isBackgroundFetch(this.#valList[i])) {
|
665 | yield this.#valList[i];
|
666 | }
|
667 | }
|
668 | }
|
669 | |
670 |
|
671 |
|
672 |
|
673 | [Symbol.iterator]() {
|
674 | return this.entries();
|
675 | }
|
676 | |
677 |
|
678 |
|
679 |
|
680 | [Symbol.toStringTag] = 'LRUCache';
|
681 | |
682 |
|
683 |
|
684 |
|
685 | find(fn, getOptions = {}) {
|
686 | for (const i of this.#indexes()) {
|
687 | const v = this.#valList[i];
|
688 | const value = this.#isBackgroundFetch(v)
|
689 | ? v.__staleWhileFetching
|
690 | : v;
|
691 | if (value === undefined)
|
692 | continue;
|
693 | if (fn(value, this.#keyList[i], this)) {
|
694 | return this.get(this.#keyList[i], getOptions);
|
695 | }
|
696 | }
|
697 | }
|
698 | |
699 |
|
700 |
|
701 |
|
702 |
|
703 |
|
704 | forEach(fn, thisp = this) {
|
705 | for (const i of this.#indexes()) {
|
706 | const v = this.#valList[i];
|
707 | const value = this.#isBackgroundFetch(v)
|
708 | ? v.__staleWhileFetching
|
709 | : v;
|
710 | if (value === undefined)
|
711 | continue;
|
712 | fn.call(thisp, value, this.#keyList[i], this);
|
713 | }
|
714 | }
|
715 | |
716 |
|
717 |
|
718 |
|
719 | rforEach(fn, thisp = this) {
|
720 | for (const i of this.#rindexes()) {
|
721 | const v = this.#valList[i];
|
722 | const value = this.#isBackgroundFetch(v)
|
723 | ? v.__staleWhileFetching
|
724 | : v;
|
725 | if (value === undefined)
|
726 | continue;
|
727 | fn.call(thisp, value, this.#keyList[i], this);
|
728 | }
|
729 | }
|
730 | |
731 |
|
732 |
|
733 |
|
734 | purgeStale() {
|
735 | let deleted = false;
|
736 | for (const i of this.#rindexes({ allowStale: true })) {
|
737 | if (this.#isStale(i)) {
|
738 | this.delete(this.#keyList[i]);
|
739 | deleted = true;
|
740 | }
|
741 | }
|
742 | return deleted;
|
743 | }
|
744 | |
745 |
|
746 |
|
747 |
|
748 |
|
749 |
|
750 | info(key) {
|
751 | const i = this.#keyMap.get(key);
|
752 | if (i === undefined)
|
753 | return undefined;
|
754 | const v = this.#valList[i];
|
755 | const value = this.#isBackgroundFetch(v)
|
756 | ? v.__staleWhileFetching
|
757 | : v;
|
758 | if (value === undefined)
|
759 | return undefined;
|
760 | const entry = { value };
|
761 | if (this.#ttls && this.#starts) {
|
762 | const ttl = this.#ttls[i];
|
763 | const start = this.#starts[i];
|
764 | if (ttl && start) {
|
765 | const remain = ttl - (perf.now() - start);
|
766 | entry.ttl = remain;
|
767 | entry.start = Date.now();
|
768 | }
|
769 | }
|
770 | if (this.#sizes) {
|
771 | entry.size = this.#sizes[i];
|
772 | }
|
773 | return entry;
|
774 | }
|
775 | |
776 |
|
777 |
|
778 |
|
779 | dump() {
|
780 | const arr = [];
|
781 | for (const i of this.#indexes({ allowStale: true })) {
|
782 | const key = this.#keyList[i];
|
783 | const v = this.#valList[i];
|
784 | const value = this.#isBackgroundFetch(v)
|
785 | ? v.__staleWhileFetching
|
786 | : v;
|
787 | if (value === undefined || key === undefined)
|
788 | continue;
|
789 | const entry = { value };
|
790 | if (this.#ttls && this.#starts) {
|
791 | entry.ttl = this.#ttls[i];
|
792 |
|
793 |
|
794 | const age = perf.now() - this.#starts[i];
|
795 | entry.start = Math.floor(Date.now() - age);
|
796 | }
|
797 | if (this.#sizes) {
|
798 | entry.size = this.#sizes[i];
|
799 | }
|
800 | arr.unshift([key, entry]);
|
801 | }
|
802 | return arr;
|
803 | }
|
804 | |
805 |
|
806 |
|
807 |
|
808 |
|
809 | load(arr) {
|
810 | this.clear();
|
811 | for (const [key, entry] of arr) {
|
812 | if (entry.start) {
|
813 |
|
814 |
|
815 |
|
816 |
|
817 |
|
818 |
|
819 | const age = Date.now() - entry.start;
|
820 | entry.start = perf.now() - age;
|
821 | }
|
822 | this.set(key, entry.value, entry);
|
823 | }
|
824 | }
|
825 | |
826 |
|
827 |
|
828 |
|
829 |
|
830 |
|
831 | set(k, v, setOptions = {}) {
|
832 | if (v === undefined) {
|
833 | this.delete(k);
|
834 | return this;
|
835 | }
|
836 | const { ttl = this.ttl, start, noDisposeOnSet = this.noDisposeOnSet, sizeCalculation = this.sizeCalculation, status, } = setOptions;
|
837 | let { noUpdateTTL = this.noUpdateTTL } = setOptions;
|
838 | const size = this.#requireSize(k, v, setOptions.size || 0, sizeCalculation);
|
839 |
|
840 |
|
841 | if (this.maxEntrySize && size > this.maxEntrySize) {
|
842 | if (status) {
|
843 | status.set = 'miss';
|
844 | status.maxEntrySizeExceeded = true;
|
845 | }
|
846 |
|
847 | this.delete(k);
|
848 | return this;
|
849 | }
|
850 | let index = this.#size === 0 ? undefined : this.#keyMap.get(k);
|
851 | if (index === undefined) {
|
852 |
|
853 | index = (this.#size === 0
|
854 | ? this.#tail
|
855 | : this.#free.length !== 0
|
856 | ? this.#free.pop()
|
857 | : this.#size === this.#max
|
858 | ? this.#evict(false)
|
859 | : this.#size);
|
860 | this.#keyList[index] = k;
|
861 | this.#valList[index] = v;
|
862 | this.#keyMap.set(k, index);
|
863 | this.#next[this.#tail] = index;
|
864 | this.#prev[index] = this.#tail;
|
865 | this.#tail = index;
|
866 | this.#size++;
|
867 | this.#addItemSize(index, size, status);
|
868 | if (status)
|
869 | status.set = 'add';
|
870 | noUpdateTTL = false;
|
871 | }
|
872 | else {
|
873 |
|
874 | this.#moveToTail(index);
|
875 | const oldVal = this.#valList[index];
|
876 | if (v !== oldVal) {
|
877 | if (this.#hasFetchMethod && this.#isBackgroundFetch(oldVal)) {
|
878 | oldVal.__abortController.abort(new Error('replaced'));
|
879 | const { __staleWhileFetching: s } = oldVal;
|
880 | if (s !== undefined && !noDisposeOnSet) {
|
881 | if (this.#hasDispose) {
|
882 | this.#dispose?.(s, k, 'set');
|
883 | }
|
884 | if (this.#hasDisposeAfter) {
|
885 | this.#disposed?.push([s, k, 'set']);
|
886 | }
|
887 | }
|
888 | }
|
889 | else if (!noDisposeOnSet) {
|
890 | if (this.#hasDispose) {
|
891 | this.#dispose?.(oldVal, k, 'set');
|
892 | }
|
893 | if (this.#hasDisposeAfter) {
|
894 | this.#disposed?.push([oldVal, k, 'set']);
|
895 | }
|
896 | }
|
897 | this.#removeItemSize(index);
|
898 | this.#addItemSize(index, size, status);
|
899 | this.#valList[index] = v;
|
900 | if (status) {
|
901 | status.set = 'replace';
|
902 | const oldValue = oldVal && this.#isBackgroundFetch(oldVal)
|
903 | ? oldVal.__staleWhileFetching
|
904 | : oldVal;
|
905 | if (oldValue !== undefined)
|
906 | status.oldValue = oldValue;
|
907 | }
|
908 | }
|
909 | else if (status) {
|
910 | status.set = 'update';
|
911 | }
|
912 | }
|
913 | if (ttl !== 0 && !this.#ttls) {
|
914 | this.#initializeTTLTracking();
|
915 | }
|
916 | if (this.#ttls) {
|
917 | if (!noUpdateTTL) {
|
918 | this.#setItemTTL(index, ttl, start);
|
919 | }
|
920 | if (status)
|
921 | this.#statusTTL(status, index);
|
922 | }
|
923 | if (!noDisposeOnSet && this.#hasDisposeAfter && this.#disposed) {
|
924 | const dt = this.#disposed;
|
925 | let task;
|
926 | while ((task = dt?.shift())) {
|
927 | this.#disposeAfter?.(...task);
|
928 | }
|
929 | }
|
930 | return this;
|
931 | }
|
932 | |
933 |
|
934 |
|
935 |
|
936 | pop() {
|
937 | try {
|
938 | while (this.#size) {
|
939 | const val = this.#valList[this.#head];
|
940 | this.#evict(true);
|
941 | if (this.#isBackgroundFetch(val)) {
|
942 | if (val.__staleWhileFetching) {
|
943 | return val.__staleWhileFetching;
|
944 | }
|
945 | }
|
946 | else if (val !== undefined) {
|
947 | return val;
|
948 | }
|
949 | }
|
950 | }
|
951 | finally {
|
952 | if (this.#hasDisposeAfter && this.#disposed) {
|
953 | const dt = this.#disposed;
|
954 | let task;
|
955 | while ((task = dt?.shift())) {
|
956 | this.#disposeAfter?.(...task);
|
957 | }
|
958 | }
|
959 | }
|
960 | }
|
961 | #evict(free) {
|
962 | const head = this.#head;
|
963 | const k = this.#keyList[head];
|
964 | const v = this.#valList[head];
|
965 | if (this.#hasFetchMethod && this.#isBackgroundFetch(v)) {
|
966 | v.__abortController.abort(new Error('evicted'));
|
967 | }
|
968 | else if (this.#hasDispose || this.#hasDisposeAfter) {
|
969 | if (this.#hasDispose) {
|
970 | this.#dispose?.(v, k, 'evict');
|
971 | }
|
972 | if (this.#hasDisposeAfter) {
|
973 | this.#disposed?.push([v, k, 'evict']);
|
974 | }
|
975 | }
|
976 | this.#removeItemSize(head);
|
977 |
|
978 | if (free) {
|
979 | this.#keyList[head] = undefined;
|
980 | this.#valList[head] = undefined;
|
981 | this.#free.push(head);
|
982 | }
|
983 | if (this.#size === 1) {
|
984 | this.#head = this.#tail = 0;
|
985 | this.#free.length = 0;
|
986 | }
|
987 | else {
|
988 | this.#head = this.#next[head];
|
989 | }
|
990 | this.#keyMap.delete(k);
|
991 | this.#size--;
|
992 | return head;
|
993 | }
|
994 | |
995 |
|
996 |
|
997 |
|
998 |
|
999 |
|
1000 |
|
1001 |
|
1002 | has(k, hasOptions = {}) {
|
1003 | const { updateAgeOnHas = this.updateAgeOnHas, status } = hasOptions;
|
1004 | const index = this.#keyMap.get(k);
|
1005 | if (index !== undefined) {
|
1006 | const v = this.#valList[index];
|
1007 | if (this.#isBackgroundFetch(v) &&
|
1008 | v.__staleWhileFetching === undefined) {
|
1009 | return false;
|
1010 | }
|
1011 | if (!this.#isStale(index)) {
|
1012 | if (updateAgeOnHas) {
|
1013 | this.#updateItemAge(index);
|
1014 | }
|
1015 | if (status) {
|
1016 | status.has = 'hit';
|
1017 | this.#statusTTL(status, index);
|
1018 | }
|
1019 | return true;
|
1020 | }
|
1021 | else if (status) {
|
1022 | status.has = 'stale';
|
1023 | this.#statusTTL(status, index);
|
1024 | }
|
1025 | }
|
1026 | else if (status) {
|
1027 | status.has = 'miss';
|
1028 | }
|
1029 | return false;
|
1030 | }
|
1031 | |
1032 |
|
1033 |
|
1034 |
|
1035 |
|
1036 |
|
1037 |
|
1038 | peek(k, peekOptions = {}) {
|
1039 | const { allowStale = this.allowStale } = peekOptions;
|
1040 | const index = this.#keyMap.get(k);
|
1041 | if (index === undefined ||
|
1042 | (!allowStale && this.#isStale(index))) {
|
1043 | return;
|
1044 | }
|
1045 | const v = this.#valList[index];
|
1046 |
|
1047 | return this.#isBackgroundFetch(v) ? v.__staleWhileFetching : v;
|
1048 | }
|
1049 | #backgroundFetch(k, index, options, context) {
|
1050 | const v = index === undefined ? undefined : this.#valList[index];
|
1051 | if (this.#isBackgroundFetch(v)) {
|
1052 | return v;
|
1053 | }
|
1054 | const ac = new AC();
|
1055 | const { signal } = options;
|
1056 |
|
1057 | signal?.addEventListener('abort', () => ac.abort(signal.reason), {
|
1058 | signal: ac.signal,
|
1059 | });
|
1060 | const fetchOpts = {
|
1061 | signal: ac.signal,
|
1062 | options,
|
1063 | context,
|
1064 | };
|
1065 | const cb = (v, updateCache = false) => {
|
1066 | const { aborted } = ac.signal;
|
1067 | const ignoreAbort = options.ignoreFetchAbort && v !== undefined;
|
1068 | if (options.status) {
|
1069 | if (aborted && !updateCache) {
|
1070 | options.status.fetchAborted = true;
|
1071 | options.status.fetchError = ac.signal.reason;
|
1072 | if (ignoreAbort)
|
1073 | options.status.fetchAbortIgnored = true;
|
1074 | }
|
1075 | else {
|
1076 | options.status.fetchResolved = true;
|
1077 | }
|
1078 | }
|
1079 | if (aborted && !ignoreAbort && !updateCache) {
|
1080 | return fetchFail(ac.signal.reason);
|
1081 | }
|
1082 |
|
1083 | const bf = p;
|
1084 | if (this.#valList[index] === p) {
|
1085 | if (v === undefined) {
|
1086 | if (bf.__staleWhileFetching) {
|
1087 | this.#valList[index] = bf.__staleWhileFetching;
|
1088 | }
|
1089 | else {
|
1090 | this.delete(k);
|
1091 | }
|
1092 | }
|
1093 | else {
|
1094 | if (options.status)
|
1095 | options.status.fetchUpdated = true;
|
1096 | this.set(k, v, fetchOpts.options);
|
1097 | }
|
1098 | }
|
1099 | return v;
|
1100 | };
|
1101 | const eb = (er) => {
|
1102 | if (options.status) {
|
1103 | options.status.fetchRejected = true;
|
1104 | options.status.fetchError = er;
|
1105 | }
|
1106 | return fetchFail(er);
|
1107 | };
|
1108 | const fetchFail = (er) => {
|
1109 | const { aborted } = ac.signal;
|
1110 | const allowStaleAborted = aborted && options.allowStaleOnFetchAbort;
|
1111 | const allowStale = allowStaleAborted || options.allowStaleOnFetchRejection;
|
1112 | const noDelete = allowStale || options.noDeleteOnFetchRejection;
|
1113 | const bf = p;
|
1114 | if (this.#valList[index] === p) {
|
1115 |
|
1116 |
|
1117 | const del = !noDelete || bf.__staleWhileFetching === undefined;
|
1118 | if (del) {
|
1119 | this.delete(k);
|
1120 | }
|
1121 | else if (!allowStaleAborted) {
|
1122 |
|
1123 |
|
1124 |
|
1125 |
|
1126 | this.#valList[index] = bf.__staleWhileFetching;
|
1127 | }
|
1128 | }
|
1129 | if (allowStale) {
|
1130 | if (options.status && bf.__staleWhileFetching !== undefined) {
|
1131 | options.status.returnedStale = true;
|
1132 | }
|
1133 | return bf.__staleWhileFetching;
|
1134 | }
|
1135 | else if (bf.__returned === bf) {
|
1136 | throw er;
|
1137 | }
|
1138 | };
|
1139 | const pcall = (res, rej) => {
|
1140 | const fmp = this.#fetchMethod?.(k, v, fetchOpts);
|
1141 | if (fmp && fmp instanceof Promise) {
|
1142 | fmp.then(v => res(v === undefined ? undefined : v), rej);
|
1143 | }
|
1144 |
|
1145 |
|
1146 |
|
1147 | ac.signal.addEventListener('abort', () => {
|
1148 | if (!options.ignoreFetchAbort ||
|
1149 | options.allowStaleOnFetchAbort) {
|
1150 | res(undefined);
|
1151 |
|
1152 | if (options.allowStaleOnFetchAbort) {
|
1153 | res = v => cb(v, true);
|
1154 | }
|
1155 | }
|
1156 | });
|
1157 | };
|
1158 | if (options.status)
|
1159 | options.status.fetchDispatched = true;
|
1160 | const p = new Promise(pcall).then(cb, eb);
|
1161 | const bf = Object.assign(p, {
|
1162 | __abortController: ac,
|
1163 | __staleWhileFetching: v,
|
1164 | __returned: undefined,
|
1165 | });
|
1166 | if (index === undefined) {
|
1167 |
|
1168 | this.set(k, bf, { ...fetchOpts.options, status: undefined });
|
1169 | index = this.#keyMap.get(k);
|
1170 | }
|
1171 | else {
|
1172 | this.#valList[index] = bf;
|
1173 | }
|
1174 | return bf;
|
1175 | }
|
1176 | #isBackgroundFetch(p) {
|
1177 | if (!this.#hasFetchMethod)
|
1178 | return false;
|
1179 | const b = p;
|
1180 | return (!!b &&
|
1181 | b instanceof Promise &&
|
1182 | b.hasOwnProperty('__staleWhileFetching') &&
|
1183 | b.__abortController instanceof AC);
|
1184 | }
|
1185 | async fetch(k, fetchOptions = {}) {
|
1186 | const {
|
1187 |
|
1188 | allowStale = this.allowStale, updateAgeOnGet = this.updateAgeOnGet, noDeleteOnStaleGet = this.noDeleteOnStaleGet,
|
1189 |
|
1190 | ttl = this.ttl, noDisposeOnSet = this.noDisposeOnSet, size = 0, sizeCalculation = this.sizeCalculation, noUpdateTTL = this.noUpdateTTL,
|
1191 |
|
1192 | noDeleteOnFetchRejection = this.noDeleteOnFetchRejection, allowStaleOnFetchRejection = this.allowStaleOnFetchRejection, ignoreFetchAbort = this.ignoreFetchAbort, allowStaleOnFetchAbort = this.allowStaleOnFetchAbort, context, forceRefresh = false, status, signal, } = fetchOptions;
|
1193 | if (!this.#hasFetchMethod) {
|
1194 | if (status)
|
1195 | status.fetch = 'get';
|
1196 | return this.get(k, {
|
1197 | allowStale,
|
1198 | updateAgeOnGet,
|
1199 | noDeleteOnStaleGet,
|
1200 | status,
|
1201 | });
|
1202 | }
|
1203 | const options = {
|
1204 | allowStale,
|
1205 | updateAgeOnGet,
|
1206 | noDeleteOnStaleGet,
|
1207 | ttl,
|
1208 | noDisposeOnSet,
|
1209 | size,
|
1210 | sizeCalculation,
|
1211 | noUpdateTTL,
|
1212 | noDeleteOnFetchRejection,
|
1213 | allowStaleOnFetchRejection,
|
1214 | allowStaleOnFetchAbort,
|
1215 | ignoreFetchAbort,
|
1216 | status,
|
1217 | signal,
|
1218 | };
|
1219 | let index = this.#keyMap.get(k);
|
1220 | if (index === undefined) {
|
1221 | if (status)
|
1222 | status.fetch = 'miss';
|
1223 | const p = this.#backgroundFetch(k, index, options, context);
|
1224 | return (p.__returned = p);
|
1225 | }
|
1226 | else {
|
1227 |
|
1228 | const v = this.#valList[index];
|
1229 | if (this.#isBackgroundFetch(v)) {
|
1230 | const stale = allowStale && v.__staleWhileFetching !== undefined;
|
1231 | if (status) {
|
1232 | status.fetch = 'inflight';
|
1233 | if (stale)
|
1234 | status.returnedStale = true;
|
1235 | }
|
1236 | return stale ? v.__staleWhileFetching : (v.__returned = v);
|
1237 | }
|
1238 |
|
1239 |
|
1240 | const isStale = this.#isStale(index);
|
1241 | if (!forceRefresh && !isStale) {
|
1242 | if (status)
|
1243 | status.fetch = 'hit';
|
1244 | this.#moveToTail(index);
|
1245 | if (updateAgeOnGet) {
|
1246 | this.#updateItemAge(index);
|
1247 | }
|
1248 | if (status)
|
1249 | this.#statusTTL(status, index);
|
1250 | return v;
|
1251 | }
|
1252 |
|
1253 |
|
1254 | const p = this.#backgroundFetch(k, index, options, context);
|
1255 | const hasStale = p.__staleWhileFetching !== undefined;
|
1256 | const staleVal = hasStale && allowStale;
|
1257 | if (status) {
|
1258 | status.fetch = isStale ? 'stale' : 'refresh';
|
1259 | if (staleVal && isStale)
|
1260 | status.returnedStale = true;
|
1261 | }
|
1262 | return staleVal ? p.__staleWhileFetching : (p.__returned = p);
|
1263 | }
|
1264 | }
|
1265 | |
1266 |
|
1267 |
|
1268 |
|
1269 |
|
1270 |
|
1271 | get(k, getOptions = {}) {
|
1272 | const { allowStale = this.allowStale, updateAgeOnGet = this.updateAgeOnGet, noDeleteOnStaleGet = this.noDeleteOnStaleGet, status, } = getOptions;
|
1273 | const index = this.#keyMap.get(k);
|
1274 | if (index !== undefined) {
|
1275 | const value = this.#valList[index];
|
1276 | const fetching = this.#isBackgroundFetch(value);
|
1277 | if (status)
|
1278 | this.#statusTTL(status, index);
|
1279 | if (this.#isStale(index)) {
|
1280 | if (status)
|
1281 | status.get = 'stale';
|
1282 |
|
1283 | if (!fetching) {
|
1284 | if (!noDeleteOnStaleGet) {
|
1285 | this.delete(k);
|
1286 | }
|
1287 | if (status && allowStale)
|
1288 | status.returnedStale = true;
|
1289 | return allowStale ? value : undefined;
|
1290 | }
|
1291 | else {
|
1292 | if (status &&
|
1293 | allowStale &&
|
1294 | value.__staleWhileFetching !== undefined) {
|
1295 | status.returnedStale = true;
|
1296 | }
|
1297 | return allowStale ? value.__staleWhileFetching : undefined;
|
1298 | }
|
1299 | }
|
1300 | else {
|
1301 | if (status)
|
1302 | status.get = 'hit';
|
1303 |
|
1304 |
|
1305 |
|
1306 |
|
1307 |
|
1308 | if (fetching) {
|
1309 | return value.__staleWhileFetching;
|
1310 | }
|
1311 | this.#moveToTail(index);
|
1312 | if (updateAgeOnGet) {
|
1313 | this.#updateItemAge(index);
|
1314 | }
|
1315 | return value;
|
1316 | }
|
1317 | }
|
1318 | else if (status) {
|
1319 | status.get = 'miss';
|
1320 | }
|
1321 | }
|
1322 | #connect(p, n) {
|
1323 | this.#prev[n] = p;
|
1324 | this.#next[p] = n;
|
1325 | }
|
1326 | #moveToTail(index) {
|
1327 |
|
1328 |
|
1329 |
|
1330 |
|
1331 |
|
1332 |
|
1333 |
|
1334 |
|
1335 | if (index !== this.#tail) {
|
1336 | if (index === this.#head) {
|
1337 | this.#head = this.#next[index];
|
1338 | }
|
1339 | else {
|
1340 | this.#connect(this.#prev[index], this.#next[index]);
|
1341 | }
|
1342 | this.#connect(this.#tail, index);
|
1343 | this.#tail = index;
|
1344 | }
|
1345 | }
|
1346 | |
1347 |
|
1348 |
|
1349 |
|
1350 | delete(k) {
|
1351 | let deleted = false;
|
1352 | if (this.#size !== 0) {
|
1353 | const index = this.#keyMap.get(k);
|
1354 | if (index !== undefined) {
|
1355 | deleted = true;
|
1356 | if (this.#size === 1) {
|
1357 | this.clear();
|
1358 | }
|
1359 | else {
|
1360 | this.#removeItemSize(index);
|
1361 | const v = this.#valList[index];
|
1362 | if (this.#isBackgroundFetch(v)) {
|
1363 | v.__abortController.abort(new Error('deleted'));
|
1364 | }
|
1365 | else if (this.#hasDispose || this.#hasDisposeAfter) {
|
1366 | if (this.#hasDispose) {
|
1367 | this.#dispose?.(v, k, 'delete');
|
1368 | }
|
1369 | if (this.#hasDisposeAfter) {
|
1370 | this.#disposed?.push([v, k, 'delete']);
|
1371 | }
|
1372 | }
|
1373 | this.#keyMap.delete(k);
|
1374 | this.#keyList[index] = undefined;
|
1375 | this.#valList[index] = undefined;
|
1376 | if (index === this.#tail) {
|
1377 | this.#tail = this.#prev[index];
|
1378 | }
|
1379 | else if (index === this.#head) {
|
1380 | this.#head = this.#next[index];
|
1381 | }
|
1382 | else {
|
1383 | const pi = this.#prev[index];
|
1384 | this.#next[pi] = this.#next[index];
|
1385 | const ni = this.#next[index];
|
1386 | this.#prev[ni] = this.#prev[index];
|
1387 | }
|
1388 | this.#size--;
|
1389 | this.#free.push(index);
|
1390 | }
|
1391 | }
|
1392 | }
|
1393 | if (this.#hasDisposeAfter && this.#disposed?.length) {
|
1394 | const dt = this.#disposed;
|
1395 | let task;
|
1396 | while ((task = dt?.shift())) {
|
1397 | this.#disposeAfter?.(...task);
|
1398 | }
|
1399 | }
|
1400 | return deleted;
|
1401 | }
|
1402 | |
1403 |
|
1404 |
|
1405 | clear() {
|
1406 | for (const index of this.#rindexes({ allowStale: true })) {
|
1407 | const v = this.#valList[index];
|
1408 | if (this.#isBackgroundFetch(v)) {
|
1409 | v.__abortController.abort(new Error('deleted'));
|
1410 | }
|
1411 | else {
|
1412 | const k = this.#keyList[index];
|
1413 | if (this.#hasDispose) {
|
1414 | this.#dispose?.(v, k, 'delete');
|
1415 | }
|
1416 | if (this.#hasDisposeAfter) {
|
1417 | this.#disposed?.push([v, k, 'delete']);
|
1418 | }
|
1419 | }
|
1420 | }
|
1421 | this.#keyMap.clear();
|
1422 | this.#valList.fill(undefined);
|
1423 | this.#keyList.fill(undefined);
|
1424 | if (this.#ttls && this.#starts) {
|
1425 | this.#ttls.fill(0);
|
1426 | this.#starts.fill(0);
|
1427 | }
|
1428 | if (this.#sizes) {
|
1429 | this.#sizes.fill(0);
|
1430 | }
|
1431 | this.#head = 0;
|
1432 | this.#tail = 0;
|
1433 | this.#free.length = 0;
|
1434 | this.#calculatedSize = 0;
|
1435 | this.#size = 0;
|
1436 | if (this.#hasDisposeAfter && this.#disposed) {
|
1437 | const dt = this.#disposed;
|
1438 | let task;
|
1439 | while ((task = dt?.shift())) {
|
1440 | this.#disposeAfter?.(...task);
|
1441 | }
|
1442 | }
|
1443 | }
|
1444 | }
|
1445 | exports.LRUCache = LRUCache;
|
1446 |
|
\ | No newline at end of file |