diff --git a/src/index.ts b/src/index.ts index 3cc1ab8..89b403e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2113,17 +2113,18 @@ export class LRUCache { load(arr: [K, LRUCache.Entry][]) { this.clear() for (const [key, entry] of arr) { - if (entry.start) { + const options = { ...entry } + if (options.start) { // entry.start is a portable timestamp, but we may be using // node's performance.now(), so calculate the offset, so that // we get the intended remaining TTL, no matter how long it's // been on ice. // // it's ok for this to be a bit slow, it's a rare operation. - const age = Date.now() - entry.start - entry.start = this.#perf.now() - age + const age = Date.now() - options.start + options.start = this.#perf.now() - age } - this.#set(key, entry.value, entry) + this.#set(key, entry.value, options) } } diff --git a/test/load.ts b/test/load.ts index 710afe6..51aa202 100644 --- a/test/load.ts +++ b/test/load.ts @@ -10,3 +10,24 @@ const d = new LRU(c) d.load(c.dump()) t.strictSame(d, c) + +t.test('loading TTL entries does not mutate the reusable dump', t => { + const source = new LRU({ max: 5, ttl: 60_000 }) + source.set('key', 'value') + const entries = source.dump() + const snapshot = structuredClone(entries) + const first = new LRU({ max: 5 }) + const second = new LRU({ max: 5 }) + + first.load(entries) + t.strictSame( + entries, + snapshot, + 'preserves portable timestamps in the input', + ) + second.load(entries) + t.equal(first.get('key'), 'value') + t.equal(second.get('key'), 'value') + t.ok(second.getRemainingTTL('key') > 0) + t.end() +})