From db61658b66a41c110f838396aaf9c0d4a122c36d Mon Sep 17 00:00:00 2001 From: Jason Mulligan Date: Sun, 29 Oct 2023 11:18:59 -0400 Subject: [PATCH] Fixing `keys()` for empty caches --- dist/tiny-lru.cjs | 6 +++--- dist/tiny-lru.js | 6 +++--- dist/tiny-lru.min.js | 4 ++-- dist/tiny-lru.min.js.map | 2 +- dist/tiny-lru.umd.js | 6 +++--- dist/tiny-lru.umd.min.js | 4 ++-- dist/tiny-lru.umd.min.js.map | 2 +- package-lock.json | 4 ++-- package.json | 2 +- src/lru.js | 4 ++-- test/lru.js | 4 ++++ 11 files changed, 24 insertions(+), 20 deletions(-) diff --git a/dist/tiny-lru.cjs b/dist/tiny-lru.cjs index 02274e9..d3f9203 100644 --- a/dist/tiny-lru.cjs +++ b/dist/tiny-lru.cjs @@ -3,7 +3,7 @@ * * @copyright 2023 Jason Mulligan * @license BSD-3-Clause - * @version 11.2.4 + * @version 11.2.5 */ 'use strict'; @@ -111,10 +111,10 @@ class LRU { const result = []; let x = this.first; - do { + while (x !== null) { result.push(x.key); x = x.next; - } while (x !== null); + } return result; } diff --git a/dist/tiny-lru.js b/dist/tiny-lru.js index 810aea0..9a2d077 100644 --- a/dist/tiny-lru.js +++ b/dist/tiny-lru.js @@ -3,7 +3,7 @@ * * @copyright 2023 Jason Mulligan * @license BSD-3-Clause - * @version 11.2.4 + * @version 11.2.5 */ class LRU { constructor (max = 0, ttl = 0, resetTtl = false) { @@ -109,10 +109,10 @@ class LRU { const result = []; let x = this.first; - do { + while (x !== null) { result.push(x.key); x = x.next; - } while (x !== null); + } return result; } diff --git a/dist/tiny-lru.min.js b/dist/tiny-lru.min.js index 9c0f419..c405328 100644 --- a/dist/tiny-lru.min.js +++ b/dist/tiny-lru.min.js @@ -1,5 +1,5 @@ /*! 2023 Jason Mulligan - @version 11.2.4 + @version 11.2.5 */ -class t{constructor(t=0,s=0,e=!1){this.first=null,this.items=Object.create(null),this.last=null,this.max=t,this.resetTtl=e,this.size=0,this.ttl=s}clear(){return this.first=null,this.items=Object.create(null),this.last=null,this.size=0,this}delete(t){if(this.has(t)){const s=this.items[t];delete this.items[t],this.size--,null!==s.prev&&(s.prev.next=s.next),null!==s.next&&(s.next.prev=s.prev),this.first===s&&(this.first=s.next),this.last===s&&(this.last=s.prev)}return this}entries(t=this.keys()){return t.map((t=>[t,this.get(t)]))}evict(t=!1){if(t||this.size>0){const t=this.first;delete this.items[t.key],0==--this.size?(this.first=null,this.last=null):(this.first=t.next,this.first.prev=null)}return this}expiresAt(t){let s;return this.has(t)&&(s=this.items[t].expiry),s}get(t){let s;if(this.has(t)){const e=this.items[t];this.ttl>0&&e.expiry<=Date.now()?this.delete(t):(s=e.value,this.set(t,s,!0))}return s}has(t){return t in this.items}keys(){const t=[];let s=this.first;do{t.push(s.key),s=s.next}while(null!==s);return t}set(t,s,e=!1,i=this.resetTtl){let h;if(e||this.has(t)){if(h=this.items[t],h.value=s,!1===e&&i&&(h.expiry=this.ttl>0?Date.now()+this.ttl:this.ttl),this.last!==h){const t=this.last,s=h.next,e=h.prev;this.first===h&&(this.first=h.next),h.next=null,h.prev=this.last,t.next=h,null!==e&&(e.next=s),null!==s&&(s.prev=e)}}else this.max>0&&this.size===this.max&&this.evict(!0),h=this.items[t]={expiry:this.ttl>0?Date.now()+this.ttl:this.ttl,key:t,prev:this.last,next:null,value:s},1==++this.size?this.first=h:this.last.next=h;return this.last=h,this}values(t=this.keys()){return t.map((t=>this.get(t)))}}function s(s=1e3,e=0,i=!1){if(isNaN(s)||s<0)throw new TypeError("Invalid max value");if(isNaN(e)||e<0)throw new TypeError("Invalid ttl value");if("boolean"!=typeof i)throw new TypeError("Invalid resetTtl value");return new t(s,e,i)}export{t as LRU,s as lru};//# sourceMappingURL=tiny-lru.min.js.map +class t{constructor(t=0,s=0,e=!1){this.first=null,this.items=Object.create(null),this.last=null,this.max=t,this.resetTtl=e,this.size=0,this.ttl=s}clear(){return this.first=null,this.items=Object.create(null),this.last=null,this.size=0,this}delete(t){if(this.has(t)){const s=this.items[t];delete this.items[t],this.size--,null!==s.prev&&(s.prev.next=s.next),null!==s.next&&(s.next.prev=s.prev),this.first===s&&(this.first=s.next),this.last===s&&(this.last=s.prev)}return this}entries(t=this.keys()){return t.map((t=>[t,this.get(t)]))}evict(t=!1){if(t||this.size>0){const t=this.first;delete this.items[t.key],0==--this.size?(this.first=null,this.last=null):(this.first=t.next,this.first.prev=null)}return this}expiresAt(t){let s;return this.has(t)&&(s=this.items[t].expiry),s}get(t){let s;if(this.has(t)){const e=this.items[t];this.ttl>0&&e.expiry<=Date.now()?this.delete(t):(s=e.value,this.set(t,s,!0))}return s}has(t){return t in this.items}keys(){const t=[];let s=this.first;for(;null!==s;)t.push(s.key),s=s.next;return t}set(t,s,e=!1,i=this.resetTtl){let h;if(e||this.has(t)){if(h=this.items[t],h.value=s,!1===e&&i&&(h.expiry=this.ttl>0?Date.now()+this.ttl:this.ttl),this.last!==h){const t=this.last,s=h.next,e=h.prev;this.first===h&&(this.first=h.next),h.next=null,h.prev=this.last,t.next=h,null!==e&&(e.next=s),null!==s&&(s.prev=e)}}else this.max>0&&this.size===this.max&&this.evict(!0),h=this.items[t]={expiry:this.ttl>0?Date.now()+this.ttl:this.ttl,key:t,prev:this.last,next:null,value:s},1==++this.size?this.first=h:this.last.next=h;return this.last=h,this}values(t=this.keys()){return t.map((t=>this.get(t)))}}function s(s=1e3,e=0,i=!1){if(isNaN(s)||s<0)throw new TypeError("Invalid max value");if(isNaN(e)||e<0)throw new TypeError("Invalid ttl value");if("boolean"!=typeof i)throw new TypeError("Invalid resetTtl value");return new t(s,e,i)}export{t as LRU,s as lru};//# sourceMappingURL=tiny-lru.min.js.map diff --git a/dist/tiny-lru.min.js.map b/dist/tiny-lru.min.js.map index 99c188f..27d0a8c 100644 --- a/dist/tiny-lru.min.js.map +++ b/dist/tiny-lru.min.js.map @@ -1 +1 @@ -{"version":3,"file":"tiny-lru.min.js","sources":["../src/lru.js"],"sourcesContent":["export class LRU {\r\n\tconstructor (max = 0, ttl = 0, resetTtl = false) {\r\n\t\tthis.first = null;\r\n\t\tthis.items = Object.create(null);\r\n\t\tthis.last = null;\r\n\t\tthis.max = max;\r\n\t\tthis.resetTtl = resetTtl;\r\n\t\tthis.size = 0;\r\n\t\tthis.ttl = ttl;\r\n\t}\r\n\r\n\tclear () {\r\n\t\tthis.first = null;\r\n\t\tthis.items = Object.create(null);\r\n\t\tthis.last = null;\r\n\t\tthis.size = 0;\r\n\r\n\t\treturn this;\r\n\t}\r\n\r\n\tdelete (key) {\r\n\t\tif (this.has(key)) {\r\n\t\t\tconst item = this.items[key];\r\n\r\n\t\t\tdelete this.items[key];\r\n\t\t\tthis.size--;\r\n\r\n\t\t\tif (item.prev !== null) {\r\n\t\t\t\titem.prev.next = item.next;\r\n\t\t\t}\r\n\r\n\t\t\tif (item.next !== null) {\r\n\t\t\t\titem.next.prev = item.prev;\r\n\t\t\t}\r\n\r\n\t\t\tif (this.first === item) {\r\n\t\t\t\tthis.first = item.next;\r\n\t\t\t}\r\n\r\n\t\t\tif (this.last === item) {\r\n\t\t\t\tthis.last = item.prev;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn this;\r\n\t}\r\n\r\n\tentries (keys = this.keys()) {\r\n\t\treturn keys.map(key => [key, this.get(key)]);\r\n\t}\r\n\r\n\tevict (bypass = false) {\r\n\t\tif (bypass || this.size > 0) {\r\n\t\t\tconst item = this.first;\r\n\r\n\t\t\tdelete this.items[item.key];\r\n\r\n\t\t\tif (--this.size === 0) {\r\n\t\t\t\tthis.first = null;\r\n\t\t\t\tthis.last = null;\r\n\t\t\t} else {\r\n\t\t\t\tthis.first = item.next;\r\n\t\t\t\tthis.first.prev = null;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn this;\r\n\t}\r\n\r\n\texpiresAt (key) {\r\n\t\tlet result;\r\n\r\n\t\tif (this.has(key)) {\r\n\t\t\tresult = this.items[key].expiry;\r\n\t\t}\r\n\r\n\t\treturn result;\r\n\t}\r\n\r\n\tget (key) {\r\n\t\tlet result;\r\n\r\n\t\tif (this.has(key)) {\r\n\t\t\tconst item = this.items[key];\r\n\r\n\t\t\tif (this.ttl > 0 && item.expiry <= Date.now()) {\r\n\t\t\t\tthis.delete(key);\r\n\t\t\t} else {\r\n\t\t\t\tresult = item.value;\r\n\t\t\t\tthis.set(key, result, true);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn result;\r\n\t}\r\n\r\n\thas (key) {\r\n\t\treturn key in this.items;\r\n\t}\r\n\r\n\tkeys () {\r\n\t\tconst result = [];\r\n\t\tlet x = this.first;\r\n\r\n\t\tdo {\r\n\t\t\tresult.push(x.key);\r\n\t\t\tx = x.next;\r\n\t\t} while (x !== null);\r\n\r\n\t\treturn result;\r\n\t}\r\n\r\n\tset (key, value, bypass = false, resetTtl = this.resetTtl) {\r\n\t\tlet item;\r\n\r\n\t\tif (bypass || this.has(key)) {\r\n\t\t\titem = this.items[key];\r\n\t\t\titem.value = value;\r\n\r\n\t\t\tif (bypass === false && resetTtl) {\r\n\t\t\t\titem.expiry = this.ttl > 0 ? Date.now() + this.ttl : this.ttl;\r\n\t\t\t}\r\n\r\n\t\t\tif (this.last !== item) {\r\n\t\t\t\tconst last = this.last,\r\n\t\t\t\t\tnext = item.next,\r\n\t\t\t\t\tprev = item.prev;\r\n\r\n\t\t\t\tif (this.first === item) {\r\n\t\t\t\t\tthis.first = item.next;\r\n\t\t\t\t}\r\n\r\n\t\t\t\titem.next = null;\r\n\t\t\t\titem.prev = this.last;\r\n\t\t\t\tlast.next = item;\r\n\r\n\t\t\t\tif (prev !== null) {\r\n\t\t\t\t\tprev.next = next;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (next !== null) {\r\n\t\t\t\t\tnext.prev = prev;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tif (this.max > 0 && this.size === this.max) {\r\n\t\t\t\tthis.evict(true);\r\n\t\t\t}\r\n\r\n\t\t\titem = this.items[key] = {\r\n\t\t\t\texpiry: this.ttl > 0 ? Date.now() + this.ttl : this.ttl,\r\n\t\t\t\tkey: key,\r\n\t\t\t\tprev: this.last,\r\n\t\t\t\tnext: null,\r\n\t\t\t\tvalue\r\n\t\t\t};\r\n\r\n\t\t\tif (++this.size === 1) {\r\n\t\t\t\tthis.first = item;\r\n\t\t\t} else {\r\n\t\t\t\tthis.last.next = item;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tthis.last = item;\r\n\r\n\t\treturn this;\r\n\t}\r\n\r\n\tvalues (keys = this.keys()) {\r\n\t\treturn keys.map(key => this.get(key));\r\n\t}\r\n}\r\n\r\nexport function lru (max = 1000, ttl = 0, resetTtl = false) {\r\n\tif (isNaN(max) || max < 0) {\r\n\t\tthrow new TypeError(\"Invalid max value\");\r\n\t}\r\n\r\n\tif (isNaN(ttl) || ttl < 0) {\r\n\t\tthrow new TypeError(\"Invalid ttl value\");\r\n\t}\r\n\r\n\tif (typeof resetTtl !== \"boolean\") {\r\n\t\tthrow new TypeError(\"Invalid resetTtl value\");\r\n\t}\r\n\r\n\treturn new LRU(max, ttl, resetTtl);\r\n}\r\n"],"names":["LRU","constructor","max","ttl","resetTtl","this","first","items","Object","create","last","size","clear","key","has","item","prev","next","entries","keys","map","get","evict","bypass","expiresAt","result","expiry","Date","now","delete","value","set","x","push","values","lru","isNaN","TypeError"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"tiny-lru.min.js","sources":["../src/lru.js"],"sourcesContent":["export class LRU {\r\n\tconstructor (max = 0, ttl = 0, resetTtl = false) {\r\n\t\tthis.first = null;\r\n\t\tthis.items = Object.create(null);\r\n\t\tthis.last = null;\r\n\t\tthis.max = max;\r\n\t\tthis.resetTtl = resetTtl;\r\n\t\tthis.size = 0;\r\n\t\tthis.ttl = ttl;\r\n\t}\r\n\r\n\tclear () {\r\n\t\tthis.first = null;\r\n\t\tthis.items = Object.create(null);\r\n\t\tthis.last = null;\r\n\t\tthis.size = 0;\r\n\r\n\t\treturn this;\r\n\t}\r\n\r\n\tdelete (key) {\r\n\t\tif (this.has(key)) {\r\n\t\t\tconst item = this.items[key];\r\n\r\n\t\t\tdelete this.items[key];\r\n\t\t\tthis.size--;\r\n\r\n\t\t\tif (item.prev !== null) {\r\n\t\t\t\titem.prev.next = item.next;\r\n\t\t\t}\r\n\r\n\t\t\tif (item.next !== null) {\r\n\t\t\t\titem.next.prev = item.prev;\r\n\t\t\t}\r\n\r\n\t\t\tif (this.first === item) {\r\n\t\t\t\tthis.first = item.next;\r\n\t\t\t}\r\n\r\n\t\t\tif (this.last === item) {\r\n\t\t\t\tthis.last = item.prev;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn this;\r\n\t}\r\n\r\n\tentries (keys = this.keys()) {\r\n\t\treturn keys.map(key => [key, this.get(key)]);\r\n\t}\r\n\r\n\tevict (bypass = false) {\r\n\t\tif (bypass || this.size > 0) {\r\n\t\t\tconst item = this.first;\r\n\r\n\t\t\tdelete this.items[item.key];\r\n\r\n\t\t\tif (--this.size === 0) {\r\n\t\t\t\tthis.first = null;\r\n\t\t\t\tthis.last = null;\r\n\t\t\t} else {\r\n\t\t\t\tthis.first = item.next;\r\n\t\t\t\tthis.first.prev = null;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn this;\r\n\t}\r\n\r\n\texpiresAt (key) {\r\n\t\tlet result;\r\n\r\n\t\tif (this.has(key)) {\r\n\t\t\tresult = this.items[key].expiry;\r\n\t\t}\r\n\r\n\t\treturn result;\r\n\t}\r\n\r\n\tget (key) {\r\n\t\tlet result;\r\n\r\n\t\tif (this.has(key)) {\r\n\t\t\tconst item = this.items[key];\r\n\r\n\t\t\tif (this.ttl > 0 && item.expiry <= Date.now()) {\r\n\t\t\t\tthis.delete(key);\r\n\t\t\t} else {\r\n\t\t\t\tresult = item.value;\r\n\t\t\t\tthis.set(key, result, true);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn result;\r\n\t}\r\n\r\n\thas (key) {\r\n\t\treturn key in this.items;\r\n\t}\r\n\r\n\tkeys () {\r\n\t\tconst result = [];\r\n\t\tlet x = this.first;\r\n\r\n\t\twhile (x !== null) {\r\n\t\t\tresult.push(x.key);\r\n\t\t\tx = x.next;\r\n\t\t}\r\n\r\n\t\treturn result;\r\n\t}\r\n\r\n\tset (key, value, bypass = false, resetTtl = this.resetTtl) {\r\n\t\tlet item;\r\n\r\n\t\tif (bypass || this.has(key)) {\r\n\t\t\titem = this.items[key];\r\n\t\t\titem.value = value;\r\n\r\n\t\t\tif (bypass === false && resetTtl) {\r\n\t\t\t\titem.expiry = this.ttl > 0 ? Date.now() + this.ttl : this.ttl;\r\n\t\t\t}\r\n\r\n\t\t\tif (this.last !== item) {\r\n\t\t\t\tconst last = this.last,\r\n\t\t\t\t\tnext = item.next,\r\n\t\t\t\t\tprev = item.prev;\r\n\r\n\t\t\t\tif (this.first === item) {\r\n\t\t\t\t\tthis.first = item.next;\r\n\t\t\t\t}\r\n\r\n\t\t\t\titem.next = null;\r\n\t\t\t\titem.prev = this.last;\r\n\t\t\t\tlast.next = item;\r\n\r\n\t\t\t\tif (prev !== null) {\r\n\t\t\t\t\tprev.next = next;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (next !== null) {\r\n\t\t\t\t\tnext.prev = prev;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tif (this.max > 0 && this.size === this.max) {\r\n\t\t\t\tthis.evict(true);\r\n\t\t\t}\r\n\r\n\t\t\titem = this.items[key] = {\r\n\t\t\t\texpiry: this.ttl > 0 ? Date.now() + this.ttl : this.ttl,\r\n\t\t\t\tkey: key,\r\n\t\t\t\tprev: this.last,\r\n\t\t\t\tnext: null,\r\n\t\t\t\tvalue\r\n\t\t\t};\r\n\r\n\t\t\tif (++this.size === 1) {\r\n\t\t\t\tthis.first = item;\r\n\t\t\t} else {\r\n\t\t\t\tthis.last.next = item;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tthis.last = item;\r\n\r\n\t\treturn this;\r\n\t}\r\n\r\n\tvalues (keys = this.keys()) {\r\n\t\treturn keys.map(key => this.get(key));\r\n\t}\r\n}\r\n\r\nexport function lru (max = 1000, ttl = 0, resetTtl = false) {\r\n\tif (isNaN(max) || max < 0) {\r\n\t\tthrow new TypeError(\"Invalid max value\");\r\n\t}\r\n\r\n\tif (isNaN(ttl) || ttl < 0) {\r\n\t\tthrow new TypeError(\"Invalid ttl value\");\r\n\t}\r\n\r\n\tif (typeof resetTtl !== \"boolean\") {\r\n\t\tthrow new TypeError(\"Invalid resetTtl value\");\r\n\t}\r\n\r\n\treturn new LRU(max, ttl, resetTtl);\r\n}\r\n"],"names":["LRU","constructor","max","ttl","resetTtl","this","first","items","Object","create","last","size","clear","key","has","item","prev","next","entries","keys","map","get","evict","bypass","expiresAt","result","expiry","Date","now","delete","value","set","x","push","values","lru","isNaN","TypeError"],"mappings":"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"} \ No newline at end of file diff --git a/dist/tiny-lru.umd.js b/dist/tiny-lru.umd.js index c1cf7dc..e5390df 100644 --- a/dist/tiny-lru.umd.js +++ b/dist/tiny-lru.umd.js @@ -3,7 +3,7 @@ * * @copyright 2023 Jason Mulligan * @license BSD-3-Clause - * @version 11.2.4 + * @version 11.2.5 */ (function(g,f){typeof exports==='object'&&typeof module!=='undefined'?f(exports):typeof define==='function'&&define.amd?define(['exports'],f):(g=typeof globalThis!=='undefined'?globalThis:g||self,f(g.lru={}));})(this,(function(exports){'use strict';class LRU { constructor (max = 0, ttl = 0, resetTtl = false) { @@ -109,10 +109,10 @@ const result = []; let x = this.first; - do { + while (x !== null) { result.push(x.key); x = x.next; - } while (x !== null); + } return result; } diff --git a/dist/tiny-lru.umd.min.js b/dist/tiny-lru.umd.min.js index f90387c..36aa596 100644 --- a/dist/tiny-lru.umd.min.js +++ b/dist/tiny-lru.umd.min.js @@ -1,5 +1,5 @@ /*! 2023 Jason Mulligan - @version 11.2.4 + @version 11.2.5 */ -!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).lru={})}(this,(function(t){"use strict";class e{constructor(t=0,e=0,s=!1){this.first=null,this.items=Object.create(null),this.last=null,this.max=t,this.resetTtl=s,this.size=0,this.ttl=e}clear(){return this.first=null,this.items=Object.create(null),this.last=null,this.size=0,this}delete(t){if(this.has(t)){const e=this.items[t];delete this.items[t],this.size--,null!==e.prev&&(e.prev.next=e.next),null!==e.next&&(e.next.prev=e.prev),this.first===e&&(this.first=e.next),this.last===e&&(this.last=e.prev)}return this}entries(t=this.keys()){return t.map((t=>[t,this.get(t)]))}evict(t=!1){if(t||this.size>0){const t=this.first;delete this.items[t.key],0==--this.size?(this.first=null,this.last=null):(this.first=t.next,this.first.prev=null)}return this}expiresAt(t){let e;return this.has(t)&&(e=this.items[t].expiry),e}get(t){let e;if(this.has(t)){const s=this.items[t];this.ttl>0&&s.expiry<=Date.now()?this.delete(t):(e=s.value,this.set(t,e,!0))}return e}has(t){return t in this.items}keys(){const t=[];let e=this.first;do{t.push(e.key),e=e.next}while(null!==e);return t}set(t,e,s=!1,i=this.resetTtl){let l;if(s||this.has(t)){if(l=this.items[t],l.value=e,!1===s&&i&&(l.expiry=this.ttl>0?Date.now()+this.ttl:this.ttl),this.last!==l){const t=this.last,e=l.next,s=l.prev;this.first===l&&(this.first=l.next),l.next=null,l.prev=this.last,t.next=l,null!==s&&(s.next=e),null!==e&&(e.prev=s)}}else this.max>0&&this.size===this.max&&this.evict(!0),l=this.items[t]={expiry:this.ttl>0?Date.now()+this.ttl:this.ttl,key:t,prev:this.last,next:null,value:e},1==++this.size?this.first=l:this.last.next=l;return this.last=l,this}values(t=this.keys()){return t.map((t=>this.get(t)))}}t.LRU=e,t.lru=function(t=1e3,s=0,i=!1){if(isNaN(t)||t<0)throw new TypeError("Invalid max value");if(isNaN(s)||s<0)throw new TypeError("Invalid ttl value");if("boolean"!=typeof i)throw new TypeError("Invalid resetTtl value");return new e(t,s,i)}}));//# sourceMappingURL=tiny-lru.umd.min.js.map +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).lru={})}(this,(function(t){"use strict";class e{constructor(t=0,e=0,s=!1){this.first=null,this.items=Object.create(null),this.last=null,this.max=t,this.resetTtl=s,this.size=0,this.ttl=e}clear(){return this.first=null,this.items=Object.create(null),this.last=null,this.size=0,this}delete(t){if(this.has(t)){const e=this.items[t];delete this.items[t],this.size--,null!==e.prev&&(e.prev.next=e.next),null!==e.next&&(e.next.prev=e.prev),this.first===e&&(this.first=e.next),this.last===e&&(this.last=e.prev)}return this}entries(t=this.keys()){return t.map((t=>[t,this.get(t)]))}evict(t=!1){if(t||this.size>0){const t=this.first;delete this.items[t.key],0==--this.size?(this.first=null,this.last=null):(this.first=t.next,this.first.prev=null)}return this}expiresAt(t){let e;return this.has(t)&&(e=this.items[t].expiry),e}get(t){let e;if(this.has(t)){const s=this.items[t];this.ttl>0&&s.expiry<=Date.now()?this.delete(t):(e=s.value,this.set(t,e,!0))}return e}has(t){return t in this.items}keys(){const t=[];let e=this.first;for(;null!==e;)t.push(e.key),e=e.next;return t}set(t,e,s=!1,i=this.resetTtl){let l;if(s||this.has(t)){if(l=this.items[t],l.value=e,!1===s&&i&&(l.expiry=this.ttl>0?Date.now()+this.ttl:this.ttl),this.last!==l){const t=this.last,e=l.next,s=l.prev;this.first===l&&(this.first=l.next),l.next=null,l.prev=this.last,t.next=l,null!==s&&(s.next=e),null!==e&&(e.prev=s)}}else this.max>0&&this.size===this.max&&this.evict(!0),l=this.items[t]={expiry:this.ttl>0?Date.now()+this.ttl:this.ttl,key:t,prev:this.last,next:null,value:e},1==++this.size?this.first=l:this.last.next=l;return this.last=l,this}values(t=this.keys()){return t.map((t=>this.get(t)))}}t.LRU=e,t.lru=function(t=1e3,s=0,i=!1){if(isNaN(t)||t<0)throw new TypeError("Invalid max value");if(isNaN(s)||s<0)throw new TypeError("Invalid ttl value");if("boolean"!=typeof i)throw new TypeError("Invalid resetTtl value");return new e(t,s,i)}}));//# sourceMappingURL=tiny-lru.umd.min.js.map diff --git a/dist/tiny-lru.umd.min.js.map b/dist/tiny-lru.umd.min.js.map index 8ac4f98..e2cafb5 100644 --- a/dist/tiny-lru.umd.min.js.map +++ b/dist/tiny-lru.umd.min.js.map @@ -1 +1 @@ -{"version":3,"file":"tiny-lru.umd.min.js","sources":["../src/lru.js"],"sourcesContent":["export class LRU {\r\n\tconstructor (max = 0, ttl = 0, resetTtl = false) {\r\n\t\tthis.first = null;\r\n\t\tthis.items = Object.create(null);\r\n\t\tthis.last = null;\r\n\t\tthis.max = max;\r\n\t\tthis.resetTtl = resetTtl;\r\n\t\tthis.size = 0;\r\n\t\tthis.ttl = ttl;\r\n\t}\r\n\r\n\tclear () {\r\n\t\tthis.first = null;\r\n\t\tthis.items = Object.create(null);\r\n\t\tthis.last = null;\r\n\t\tthis.size = 0;\r\n\r\n\t\treturn this;\r\n\t}\r\n\r\n\tdelete (key) {\r\n\t\tif (this.has(key)) {\r\n\t\t\tconst item = this.items[key];\r\n\r\n\t\t\tdelete this.items[key];\r\n\t\t\tthis.size--;\r\n\r\n\t\t\tif (item.prev !== null) {\r\n\t\t\t\titem.prev.next = item.next;\r\n\t\t\t}\r\n\r\n\t\t\tif (item.next !== null) {\r\n\t\t\t\titem.next.prev = item.prev;\r\n\t\t\t}\r\n\r\n\t\t\tif (this.first === item) {\r\n\t\t\t\tthis.first = item.next;\r\n\t\t\t}\r\n\r\n\t\t\tif (this.last === item) {\r\n\t\t\t\tthis.last = item.prev;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn this;\r\n\t}\r\n\r\n\tentries (keys = this.keys()) {\r\n\t\treturn keys.map(key => [key, this.get(key)]);\r\n\t}\r\n\r\n\tevict (bypass = false) {\r\n\t\tif (bypass || this.size > 0) {\r\n\t\t\tconst item = this.first;\r\n\r\n\t\t\tdelete this.items[item.key];\r\n\r\n\t\t\tif (--this.size === 0) {\r\n\t\t\t\tthis.first = null;\r\n\t\t\t\tthis.last = null;\r\n\t\t\t} else {\r\n\t\t\t\tthis.first = item.next;\r\n\t\t\t\tthis.first.prev = null;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn this;\r\n\t}\r\n\r\n\texpiresAt (key) {\r\n\t\tlet result;\r\n\r\n\t\tif (this.has(key)) {\r\n\t\t\tresult = this.items[key].expiry;\r\n\t\t}\r\n\r\n\t\treturn result;\r\n\t}\r\n\r\n\tget (key) {\r\n\t\tlet result;\r\n\r\n\t\tif (this.has(key)) {\r\n\t\t\tconst item = this.items[key];\r\n\r\n\t\t\tif (this.ttl > 0 && item.expiry <= Date.now()) {\r\n\t\t\t\tthis.delete(key);\r\n\t\t\t} else {\r\n\t\t\t\tresult = item.value;\r\n\t\t\t\tthis.set(key, result, true);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn result;\r\n\t}\r\n\r\n\thas (key) {\r\n\t\treturn key in this.items;\r\n\t}\r\n\r\n\tkeys () {\r\n\t\tconst result = [];\r\n\t\tlet x = this.first;\r\n\r\n\t\tdo {\r\n\t\t\tresult.push(x.key);\r\n\t\t\tx = x.next;\r\n\t\t} while (x !== null);\r\n\r\n\t\treturn result;\r\n\t}\r\n\r\n\tset (key, value, bypass = false, resetTtl = this.resetTtl) {\r\n\t\tlet item;\r\n\r\n\t\tif (bypass || this.has(key)) {\r\n\t\t\titem = this.items[key];\r\n\t\t\titem.value = value;\r\n\r\n\t\t\tif (bypass === false && resetTtl) {\r\n\t\t\t\titem.expiry = this.ttl > 0 ? Date.now() + this.ttl : this.ttl;\r\n\t\t\t}\r\n\r\n\t\t\tif (this.last !== item) {\r\n\t\t\t\tconst last = this.last,\r\n\t\t\t\t\tnext = item.next,\r\n\t\t\t\t\tprev = item.prev;\r\n\r\n\t\t\t\tif (this.first === item) {\r\n\t\t\t\t\tthis.first = item.next;\r\n\t\t\t\t}\r\n\r\n\t\t\t\titem.next = null;\r\n\t\t\t\titem.prev = this.last;\r\n\t\t\t\tlast.next = item;\r\n\r\n\t\t\t\tif (prev !== null) {\r\n\t\t\t\t\tprev.next = next;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (next !== null) {\r\n\t\t\t\t\tnext.prev = prev;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tif (this.max > 0 && this.size === this.max) {\r\n\t\t\t\tthis.evict(true);\r\n\t\t\t}\r\n\r\n\t\t\titem = this.items[key] = {\r\n\t\t\t\texpiry: this.ttl > 0 ? Date.now() + this.ttl : this.ttl,\r\n\t\t\t\tkey: key,\r\n\t\t\t\tprev: this.last,\r\n\t\t\t\tnext: null,\r\n\t\t\t\tvalue\r\n\t\t\t};\r\n\r\n\t\t\tif (++this.size === 1) {\r\n\t\t\t\tthis.first = item;\r\n\t\t\t} else {\r\n\t\t\t\tthis.last.next = item;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tthis.last = item;\r\n\r\n\t\treturn this;\r\n\t}\r\n\r\n\tvalues (keys = this.keys()) {\r\n\t\treturn keys.map(key => this.get(key));\r\n\t}\r\n}\r\n\r\nexport function lru (max = 1000, ttl = 0, resetTtl = false) {\r\n\tif (isNaN(max) || max < 0) {\r\n\t\tthrow new TypeError(\"Invalid max value\");\r\n\t}\r\n\r\n\tif (isNaN(ttl) || ttl < 0) {\r\n\t\tthrow new TypeError(\"Invalid ttl value\");\r\n\t}\r\n\r\n\tif (typeof resetTtl !== \"boolean\") {\r\n\t\tthrow new TypeError(\"Invalid resetTtl value\");\r\n\t}\r\n\r\n\treturn new LRU(max, ttl, resetTtl);\r\n}\r\n"],"names":["g","f","exports","module","define","amd","globalThis","self","lru","this","LRU","constructor","max","ttl","resetTtl","first","items","Object","create","last","size","clear","key","has","item","prev","next","entries","keys","map","get","evict","bypass","expiresAt","result","expiry","Date","now","delete","value","set","x","push","values","isNaN","TypeError"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"tiny-lru.umd.min.js","sources":["../src/lru.js"],"sourcesContent":["export class LRU {\r\n\tconstructor (max = 0, ttl = 0, resetTtl = false) {\r\n\t\tthis.first = null;\r\n\t\tthis.items = Object.create(null);\r\n\t\tthis.last = null;\r\n\t\tthis.max = max;\r\n\t\tthis.resetTtl = resetTtl;\r\n\t\tthis.size = 0;\r\n\t\tthis.ttl = ttl;\r\n\t}\r\n\r\n\tclear () {\r\n\t\tthis.first = null;\r\n\t\tthis.items = Object.create(null);\r\n\t\tthis.last = null;\r\n\t\tthis.size = 0;\r\n\r\n\t\treturn this;\r\n\t}\r\n\r\n\tdelete (key) {\r\n\t\tif (this.has(key)) {\r\n\t\t\tconst item = this.items[key];\r\n\r\n\t\t\tdelete this.items[key];\r\n\t\t\tthis.size--;\r\n\r\n\t\t\tif (item.prev !== null) {\r\n\t\t\t\titem.prev.next = item.next;\r\n\t\t\t}\r\n\r\n\t\t\tif (item.next !== null) {\r\n\t\t\t\titem.next.prev = item.prev;\r\n\t\t\t}\r\n\r\n\t\t\tif (this.first === item) {\r\n\t\t\t\tthis.first = item.next;\r\n\t\t\t}\r\n\r\n\t\t\tif (this.last === item) {\r\n\t\t\t\tthis.last = item.prev;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn this;\r\n\t}\r\n\r\n\tentries (keys = this.keys()) {\r\n\t\treturn keys.map(key => [key, this.get(key)]);\r\n\t}\r\n\r\n\tevict (bypass = false) {\r\n\t\tif (bypass || this.size > 0) {\r\n\t\t\tconst item = this.first;\r\n\r\n\t\t\tdelete this.items[item.key];\r\n\r\n\t\t\tif (--this.size === 0) {\r\n\t\t\t\tthis.first = null;\r\n\t\t\t\tthis.last = null;\r\n\t\t\t} else {\r\n\t\t\t\tthis.first = item.next;\r\n\t\t\t\tthis.first.prev = null;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn this;\r\n\t}\r\n\r\n\texpiresAt (key) {\r\n\t\tlet result;\r\n\r\n\t\tif (this.has(key)) {\r\n\t\t\tresult = this.items[key].expiry;\r\n\t\t}\r\n\r\n\t\treturn result;\r\n\t}\r\n\r\n\tget (key) {\r\n\t\tlet result;\r\n\r\n\t\tif (this.has(key)) {\r\n\t\t\tconst item = this.items[key];\r\n\r\n\t\t\tif (this.ttl > 0 && item.expiry <= Date.now()) {\r\n\t\t\t\tthis.delete(key);\r\n\t\t\t} else {\r\n\t\t\t\tresult = item.value;\r\n\t\t\t\tthis.set(key, result, true);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn result;\r\n\t}\r\n\r\n\thas (key) {\r\n\t\treturn key in this.items;\r\n\t}\r\n\r\n\tkeys () {\r\n\t\tconst result = [];\r\n\t\tlet x = this.first;\r\n\r\n\t\twhile (x !== null) {\r\n\t\t\tresult.push(x.key);\r\n\t\t\tx = x.next;\r\n\t\t}\r\n\r\n\t\treturn result;\r\n\t}\r\n\r\n\tset (key, value, bypass = false, resetTtl = this.resetTtl) {\r\n\t\tlet item;\r\n\r\n\t\tif (bypass || this.has(key)) {\r\n\t\t\titem = this.items[key];\r\n\t\t\titem.value = value;\r\n\r\n\t\t\tif (bypass === false && resetTtl) {\r\n\t\t\t\titem.expiry = this.ttl > 0 ? Date.now() + this.ttl : this.ttl;\r\n\t\t\t}\r\n\r\n\t\t\tif (this.last !== item) {\r\n\t\t\t\tconst last = this.last,\r\n\t\t\t\t\tnext = item.next,\r\n\t\t\t\t\tprev = item.prev;\r\n\r\n\t\t\t\tif (this.first === item) {\r\n\t\t\t\t\tthis.first = item.next;\r\n\t\t\t\t}\r\n\r\n\t\t\t\titem.next = null;\r\n\t\t\t\titem.prev = this.last;\r\n\t\t\t\tlast.next = item;\r\n\r\n\t\t\t\tif (prev !== null) {\r\n\t\t\t\t\tprev.next = next;\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (next !== null) {\r\n\t\t\t\t\tnext.prev = prev;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tif (this.max > 0 && this.size === this.max) {\r\n\t\t\t\tthis.evict(true);\r\n\t\t\t}\r\n\r\n\t\t\titem = this.items[key] = {\r\n\t\t\t\texpiry: this.ttl > 0 ? Date.now() + this.ttl : this.ttl,\r\n\t\t\t\tkey: key,\r\n\t\t\t\tprev: this.last,\r\n\t\t\t\tnext: null,\r\n\t\t\t\tvalue\r\n\t\t\t};\r\n\r\n\t\t\tif (++this.size === 1) {\r\n\t\t\t\tthis.first = item;\r\n\t\t\t} else {\r\n\t\t\t\tthis.last.next = item;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tthis.last = item;\r\n\r\n\t\treturn this;\r\n\t}\r\n\r\n\tvalues (keys = this.keys()) {\r\n\t\treturn keys.map(key => this.get(key));\r\n\t}\r\n}\r\n\r\nexport function lru (max = 1000, ttl = 0, resetTtl = false) {\r\n\tif (isNaN(max) || max < 0) {\r\n\t\tthrow new TypeError(\"Invalid max value\");\r\n\t}\r\n\r\n\tif (isNaN(ttl) || ttl < 0) {\r\n\t\tthrow new TypeError(\"Invalid ttl value\");\r\n\t}\r\n\r\n\tif (typeof resetTtl !== \"boolean\") {\r\n\t\tthrow new TypeError(\"Invalid resetTtl value\");\r\n\t}\r\n\r\n\treturn new LRU(max, ttl, resetTtl);\r\n}\r\n"],"names":["g","f","exports","module","define","amd","globalThis","self","lru","this","LRU","constructor","max","ttl","resetTtl","first","items","Object","create","last","size","clear","key","has","item","prev","next","entries","keys","map","get","evict","bypass","expiresAt","result","expiry","Date","now","delete","value","set","x","push","values","isNaN","TypeError"],"mappings":"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"} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index b26ae26..eae389b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "tiny-lru", - "version": "11.2.4", + "version": "11.2.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "tiny-lru", - "version": "11.2.4", + "version": "11.2.5", "license": "BSD-3-Clause", "devDependencies": { "@rollup/plugin-terser": "^0.4.3", diff --git a/package.json b/package.json index 88571cf..db93161 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "tiny-lru", "description": "Tiny LRU cache for Client or Server", - "version": "11.2.4", + "version": "11.2.5", "homepage": "https://github.com/avoidwork/tiny-lru", "author": "Jason Mulligan ", "repository": { diff --git a/src/lru.js b/src/lru.js index ae615c6..56dd414 100644 --- a/src/lru.js +++ b/src/lru.js @@ -102,10 +102,10 @@ export class LRU { const result = []; let x = this.first; - do { + while (x !== null) { result.push(x.key); x = x.next; - } while (x !== null); + } return result; } diff --git a/test/lru.js b/test/lru.js index e3122c4..944df2b 100644 --- a/test/lru.js +++ b/test/lru.js @@ -51,6 +51,10 @@ describe("Testing functionality", function () { assert.strictEqual(JSON.stringify(this.cache.keys()), JSON.stringify(this.items), "Should be equal arrays"); }); + it("It should have no keys() when empty", function () { + assert.strictEqual(JSON.stringify(this.cache.keys()), JSON.stringify([]), "Should be equal"); + }); + it("It should have entries()", function () { this.items.forEach(i => this.cache.set(i, false)); const entries = this.cache.entries();