(keysBudget)
| 1254 | * @returns {WeakMap<K,V>} |
| 1255 | */ |
| 1256 | const makeLRUCacheMap= (keysBudget)=>{ |
| 1257 | if( !isSafeInteger(keysBudget)|| keysBudget< 0) { |
| 1258 | throw TypeError('keysBudget must be a safe non-negative integer number'); |
| 1259 | } |
| 1260 | /** @typedef {DoublyLinkedCell<WeakMap<K, V> | undefined>} LRUCacheCell */ |
| 1261 | /** @type {WeakMap<K, LRUCacheCell>} */ |
| 1262 | const keyToCell= new WeakMap(); |
| 1263 | let size= 0; // `size` must remain <= `keysBudget` |
| 1264 | // As a sigil, `head` uniquely is not in the `keyToCell` map. |
| 1265 | /** @type {LRUCacheCell} */ |
| 1266 | const head= makeSelfCell(undefined); |
| 1267 | |
| 1268 | const touchCell= (key)=>{ |
| 1269 | const cell= keyToCell.get(key); |
| 1270 | if( cell=== undefined|| cell.data=== undefined) { |
| 1271 | // Either the key was GCed, or the cell was condemned. |
| 1272 | return undefined; |
| 1273 | } |
| 1274 | // Becomes most recently used |
| 1275 | spliceOut(cell); |
| 1276 | spliceAfter(head, cell); |
| 1277 | return cell; |
| 1278 | }; |
| 1279 | |
| 1280 | /** |
| 1281 | * @param {K} key |
| 1282 | */ |
| 1283 | const has= (key)=>touchCell(key)!== undefined; |
| 1284 | freeze(has); |
| 1285 | |
| 1286 | /** |
| 1287 | * @param {K} key |
| 1288 | */ |
| 1289 | // UNTIL https://github.com/endojs/endo/issues/1514 |
| 1290 | // Prefer: const get = key => touchCell(key)?.data?.get(key); |
| 1291 | const get= (key)=>{ |
| 1292 | const cell= touchCell(key); |
| 1293 | return cell&& cell.data&& cell.data.get(key); |
| 1294 | }; |
| 1295 | freeze(get); |
| 1296 | |
| 1297 | /** |
| 1298 | * @param {K} key |
| 1299 | * @param {V} value |
| 1300 | */ |
| 1301 | const set= (key, value)=> { |
| 1302 | if( keysBudget< 1) { |
| 1303 | // eslint-disable-next-line no-use-before-define |
| 1304 | return lruCacheMap; // Implements WeakMap.set |
| 1305 | } |
| 1306 | |
| 1307 | let cell= touchCell(key); |
| 1308 | if( cell=== undefined) { |
| 1309 | cell= makeSelfCell(undefined); |
| 1310 | spliceAfter(head, cell); // start most recently used |
| 1311 | } |
| 1312 | if( !cell.data) { |
| 1313 | // Either a fresh cell or a reused condemned cell. |
no test coverage detected