authorgravatar for git@paperclover.netclover caruso <git@paperclover.net> 2026-02-03 03:26:50-08:00
committergravatar for git@paperclover.netclover caruso <git@paperclover.net> 2026-02-03 03:44:47-08:00
logfb973bb80728e2a703b326d99d295ad881e11d96
tree4ef94d2282cc24f44f0eb0134c2b7aa9cb89dff2
parent6249c9f2acd13afd89ef2ee201902c3567c8d29e
signature Signed by SSH key SHA256:xbd+BjjhyBfwk7GVoURf9Yx0gzDerHbvYv7SddNWmAs

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.

2 files changed, 24 insertions(+), 2 deletions(-)

lib/Lru.test.ts+16
......@@ -23,6 +23,7 @@ test("lru basic", () => {
2323 ["c", 5, 1],
2424 ]);
2525 lru.capacity = 10;
26 lru.set("a", -1);
2627 lru.set("a", 0);
2728 lru.set("z", 1);
2829 lru.set("x", 1);
......@@ -132,6 +133,21 @@ test("throws on evicting a locked item", () => {
132133 void lru.lock("e");
133134 assert.throws(() => lru.ensureUnusedCapacity(3), RangeError);
134135});
136test("revival", () => {
137 let lru = new Lru<string, number>({ capacity: 3, sizeFn: (v) => 1 });
138 lru.set("a", 1);
139 lru.set("b", 2);
140 lru.set("c", 3);
141 lru.set("d", 4);
142 const state = lru.serialize();
143 lru = new Lru({ capacity: 3, sizeFn: (v) => 1 });
144 lru.revive(state);
145 assert.equal(lru.get("c"), 3);
146 assert.equal(lru.get("a"), undefined);
147 lru.set("e", 5);
148 assert.equal(lru.get("d"), 4);
149 assert.equal(lru.get("e"), 5);
150});
135151
136152import assert from "node:assert";
137153import { test } from "node:test";
lib/Lru.ts+8-2
......@@ -232,7 +232,8 @@ export class Lru<K, V> extends Map<K, V> {
232232 const order = this.#order;
233233 let prev: Order<K> | null = null;
234234 let pk!: K;
235 for (let i = entries.length - 1; i > 0; i -= 1) {
235 let totalSize = 0;
236 for (let i = entries.length - 1; i >= 0; i -= 1) {
236237 const [ik, iv, size] = UNWRAP(entries[i]);
237238 const kv = map(ik, iv);
238239 if (!kv) continue;
......@@ -240,9 +241,14 @@ export class Lru<K, V> extends Map<K, V> {
240241 super.set(k, v);
241242 const current: Order<K> = [size, none, prev ? pk : none, 0];
242243 if (prev) prev[1] = k;
243 order.set(k, prev = current);
244 else this.#tail = k;
245 order.set(k, current);
246 prev = current;
244247 pk = k;
248 totalSize += size;
245249 }
250 if (prev) this.#head = pk;
251 this.#used = totalSize;
246252 }
247253}
248254