From fb973bb80728e2a703b326d99d295ad881e11d96 Mon Sep 17 00:00:00 2001 From: clover caruso Date: Tue, 3 Feb 2026 03:26:50 -0800 Subject: [PATCH] fix: lru revival must revive all state resolves #44 (tho cant reproduce it's exact error in a test). coverage on this module is really high so its probably a revive bug. --- lib/Lru.test.ts | 16 ++++++++++++++++ lib/Lru.ts | 10 ++++++++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/lib/Lru.test.ts b/lib/Lru.test.ts index 003a250e6874d6c481eeae108263bf2383424520..39fb0bbc73eee8075bcd31dfb81c8510c2ce9110 100644 --- a/lib/Lru.test.ts +++ b/lib/Lru.test.ts @@ -23,6 +23,7 @@ test("lru basic", () => { ["c", 5, 1], ]); lru.capacity = 10; + lru.set("a", -1); lru.set("a", 0); lru.set("z", 1); lru.set("x", 1); @@ -132,6 +133,21 @@ test("throws on evicting a locked item", () => { void lru.lock("e"); assert.throws(() => lru.ensureUnusedCapacity(3), RangeError); }); +test("revival", () => { + let lru = new Lru({ capacity: 3, sizeFn: (v) => 1 }); + lru.set("a", 1); + lru.set("b", 2); + lru.set("c", 3); + lru.set("d", 4); + const state = lru.serialize(); + lru = new Lru({ capacity: 3, sizeFn: (v) => 1 }); + lru.revive(state); + assert.equal(lru.get("c"), 3); + assert.equal(lru.get("a"), undefined); + lru.set("e", 5); + assert.equal(lru.get("d"), 4); + assert.equal(lru.get("e"), 5); +}); import assert from "node:assert"; import { test } from "node:test"; diff --git a/lib/Lru.ts b/lib/Lru.ts index 474f484ba3fba40382c423fc829342a4c79741c1..4cb35d4cac1139eb80477beb3b0135fa16c27c12 100644 --- a/lib/Lru.ts +++ b/lib/Lru.ts @@ -232,7 +232,8 @@ export class Lru extends Map { const order = this.#order; let prev: Order | null = null; let pk!: K; - for (let i = entries.length - 1; i > 0; i -= 1) { + let totalSize = 0; + for (let i = entries.length - 1; i >= 0; i -= 1) { const [ik, iv, size] = UNWRAP(entries[i]); const kv = map(ik, iv); if (!kv) continue; @@ -240,9 +241,14 @@ export class Lru extends Map { super.set(k, v); const current: Order = [size, none, prev ? pk : none, 0]; if (prev) prev[1] = k; - order.set(k, prev = current); + else this.#tail = k; + order.set(k, current); + prev = current; pk = k; + totalSize += size; } + if (prev) this.#head = pk; + this.#used = totalSize; } } -- 2.54.0