makeLRUCacheMap = keysBudget => {
  if (!isSafeInteger(keysBudget) || keysBudget < 0) {
    // eslint-disable-next-line no-restricted-globals
    throw TypeError('keysBudget must be a safe non-negative integer number');
  }
  /** @typedef {DoublyLinkedCell<WeakMap<K, V> | undefined>} LRUCacheCell */
  /** @type {WeakMap<K, LRUCacheCell>} */
  // eslint-disable-next-line no-restricted-globals
  const keyToCell = new WeakMap();
  let size = 0; // `size` must remain <= `keysBudget`
  // As a sigil, `head` uniquely is not in the `keyToCell` map.
  /** @type {LRUCacheCell} */
  const head = makeSelfCell(undefined);

  const touchCell = key => {
    const cell = keyToCell.get(key);
    if (cell === undefined || cell.data === undefined) {
      // Either the key was GCed, or the cell was condemned.
      return undefined;
    }
    // Becomes most recently used
    spliceOut(cell);
    spliceAfter(head, cell);
    return cell;
  };

  /**
   * @param {K} key
   */
  const has = key => touchCell(key) !== undefined;
  freeze(has);

  /**
   * @param {K} key
   */
  // UNTIL https://github.com/endojs/endo/issues/1514
  // Prefer: const get = key => touchCell(key)?.data?.get(key);
  const get = key => {
    const cell = touchCell(key);
    return cell && cell.data && cell.data.get(key);
  };
  freeze(get);

  /**
   * @param {K} key
   * @param {V} value
   */
  const set = (key, value) => {
    if (keysBudget < 1) {
      // eslint-disable-next-line no-use-before-define
      return lruCacheMap; // Implements WeakMap.set
    }

    let cell = touchCell(key);
    if (cell === undefined) {
      cell = makeSelfCell(undefined);
      spliceAfter(head, cell); // start most recently used
    }
    if (!cell.data) {
      // Either a fresh cell or a reused condemned cell.
      size += 1;
      // Add its data.
      // eslint-disable-next-line no-restricted-globals
      cell.data = new WeakMap();
      // Advertise the cell for this key.
      keyToCell.set(key, cell);
      while (size > keysBudget) {
        const condemned = head.prev;
        spliceOut(condemned); // Drop least recently used
        condemned.data = undefined;
        size -= 1;
      }
    }

    // Update the data.
    cell.data.set(key, value);

    // eslint-disable-next-line no-use-before-define
    return lruCacheMap; // Implements WeakMap.set
  };
  freeze(set);

  // "delete" is a keyword.
  /**
   * @param {K} key
   */
  const deleteIt = key => {
    const cell = keyToCell.get(key);
    if (cell === undefined) {
      return false;
    }
    spliceOut(cell);
    keyToCell.delete(key);
    if (cell.data === undefined) {
      // Already condemned.
      return false;
    }

    cell.data = undefined;
    size -= 1;
    return true;
  };
  freeze(deleteIt);

  const lruCacheMap = freeze({
    has,
    get,
    set,
    delete: deleteIt,
    // eslint-disable-next-line jsdoc/check-types
    [/** @type {typeof Symbol.toStringTag} */ (toStringTagSymbol)]:
      'LRUCacheMap',
  });
  return lruCacheMap;
}
The LRUCacheMap is used within the implementation of `assert` and so
at a layer below SES or harden. Thus, we give it a `WeakMap`-like interface
rather than a `WeakMapStore`-like interface. To work before `lockdown`,
the implementation must use `freeze` manually, but still exhaustively.

It implements the WeakMap interface, and holds its keys weakly.  Cached
values are only held while the key is held by the user and the key/value
bookkeeping cell has not been pushed off the end of the cache by `budget`
number of more recently referenced cells.  If the key is dropped by the user,
the value will no longer be held by the cache, but the bookkeeping cell
itself will stay in memory.

@template {{}} K
@template {unknown} V
@param {number} keysBudget
@returns {WeakMap<K,V>}