| author | |
| committer | |
| log | fb973bb80728e2a703b326d99d295ad881e11d96 |
| tree | 4ef94d2282cc24f44f0eb0134c2b7aa9cb89dff2 |
| parent | 6249c9f2acd13afd89ef2ee201902c3567c8d29e |
| signature | Signed by SSH key SHA256:xbd+BjjhyBfwk7GVoURf9Yx0gzDerHbvYv7SddNWmAs |
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", () => { | ... | @@ -23,6 +23,7 @@ test("lru basic", () => { |
| 23 | ["c", 5, 1], | 23 | ["c", 5, 1], |
| 24 | ]); | 24 | ]); |
| 25 | lru.capacity = 10; | 25 | lru.capacity = 10; |
| 26 | lru.set("a", -1); | ||
| 26 | lru.set("a", 0); | 27 | lru.set("a", 0); |
| 27 | lru.set("z", 1); | 28 | lru.set("z", 1); |
| 28 | lru.set("x", 1); | 29 | lru.set("x", 1); |
| ... | @@ -132,6 +133,21 @@ test("throws on evicting a locked item", () => { | ... | @@ -132,6 +133,21 @@ test("throws on evicting a locked item", () => { |
| 132 | void lru.lock("e"); | 133 | void lru.lock("e"); |
| 133 | assert.throws(() => lru.ensureUnusedCapacity(3), RangeError); | 134 | assert.throws(() => lru.ensureUnusedCapacity(3), RangeError); |
| 134 | }); | 135 | }); |
| 136 | test("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 | }); | ||
| 135 | 151 | ||
| 136 | import assert from "node:assert"; | 152 | import assert from "node:assert"; |
| 137 | import { test } from "node:test"; | 153 | import { test } from "node:test"; |
lib/Lru.ts+8-2| ... | @@ -232,7 +232,8 @@ export class Lru<K, V> extends Map<K, V> { | ... | @@ -232,7 +232,8 @@ export class Lru<K, V> extends Map<K, V> { |
| 232 | const order = this.#order; | 232 | const order = this.#order; |
| 233 | let prev: Order<K> | null = null; | 233 | let prev: Order<K> | null = null; |
| 234 | let pk!: K; | 234 | 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) { | ||
| 236 | const [ik, iv, size] = UNWRAP(entries[i]); | 237 | const [ik, iv, size] = UNWRAP(entries[i]); |
| 237 | const kv = map(ik, iv); | 238 | const kv = map(ik, iv); |
| 238 | if (!kv) continue; | 239 | if (!kv) continue; |
| ... | @@ -240,9 +241,14 @@ export class Lru<K, V> extends Map<K, V> { | ... | @@ -240,9 +241,14 @@ export class Lru<K, V> extends Map<K, V> { |
| 240 | super.set(k, v); | 241 | super.set(k, v); |
| 241 | const current: Order<K> = [size, none, prev ? pk : none, 0]; | 242 | const current: Order<K> = [size, none, prev ? pk : none, 0]; |
| 242 | if (prev) prev[1] = k; | 243 | if (prev) prev[1] = k; |
| 243 | order.set(k, prev = current); | 244 | else this.#tail = k; |
| 245 | order.set(k, current); | ||
| 246 | prev = current; | ||
| 244 | pk = k; | 247 | pk = k; |
| 248 | totalSize += size; | ||
| 245 | } | 249 | } |
| 250 | if (prev) this.#head = pk; | ||
| 251 | this.#used = totalSize; | ||
| 246 | } | 252 | } |
| 247 | } | 253 | } |
| 248 | 254 |