makeDefaultCapTPImportExportTables = ({
  gcImports,
  releaseSlot,
  makeRemoteKit,
}) => {
  /** @type {Map<CapTPSlot, any>} */
  const slotToExported = new Map();
  const slotToImported = makeFinalizingMap(
    /**
     * @param {CapTPSlot} slotID
     */
    slotID => {
      releaseSlot(slotID);
    },
    { weakValues: gcImports },
  );

  let lastExportID = 0;
  let lastPromiseID = 0;

  /**
   * Called when we have encountered a new value that needs to be assigned a slot.
   *
   * @param {any} val
   * @returns {CapTPSlot}
   */
  const makeSlotForValue = val => {
    /** @type {CapTPSlot} */
    let slot;
    if (isPromise(val)) {
      // This is a promise, so we're going to increment the lastPromiseID
      // and use that to construct the slot name.  Promise slots are prefaced
      // with 'p+'.
      lastPromiseID += 1;
      slot = `p+${lastPromiseID}`;
    } else {
      // Since this isn't a promise, we instead increment the lastExportId and
      // use that to construct the slot name.  Non-promises are prefaced with
      // 'o+' for normal objects.
      lastExportID += 1;
      slot = `o+${lastExportID}`;
    }
    return slot;
  };

  /**
   * Called when we have a new slot that needs to be made into a value.
   *
   * @param {CapTPSlot} slot
   * @param {string | undefined} iface
   * @returns {{val: any, settler: Settler }}
   */
  const makeValueForSlot = (slot, iface) => {
    let val;
    // Make a new handled promise for the slot.
    const { promise, settler } = makeRemoteKit(slot);
    if (slot[0] === 'o' || slot[0] === 't') {
      // A new remote presence
      // Use Remotable rather than Far to make a remote from a presence
      val = Remotable(iface, undefined, settler.resolveWithPresence());
    } else if (slot[0] === 'p') {
      val = promise;
    } else {
      Fail`Unknown slot type ${slot}`;
    }
    return { val, settler };
  };

  return {
    makeSlotForValue,
    makeValueForSlot,
    hasImport: slot => slotToImported.has(slot),
    getImport: slot => slotToImported.get(slot),
    markAsImported: (slot, val) => slotToImported.set(slot, val),
    hasExport: slot => slotToExported.has(slot),
    getExport: slot => slotToExported.get(slot),
    markAsExported: (slot, val) => slotToExported.set(slot, val),
    deleteExport: slot => slotToExported.delete(slot),
    didDisconnect: () => slotToImported.clearWithoutFinalizing(),
  };
}
@typedef {object} CapTPImportExportTables 
@property {(value: any) => CapTPSlot} makeSlotForValue
@property {(slot: CapTPSlot, iface: string | undefined) => any} makeValueForSlot
@property {(slot: CapTPSlot) => boolean} hasImport
@property {(slot: CapTPSlot) => any} getImport
@property {(slot: CapTPSlot, value: any) => void} markAsImported
@property {(slot: CapTPSlot) => boolean} hasExport
@property {(slot: CapTPSlot) => any} getExport
@property {(slot: CapTPSlot, value: any) => void} markAsExported
@property {(slot: CapTPSlot) => void} deleteExport
@property {() => void} didDisconnect
@typedef {object} MakeCapTPImportExportTablesOptions
@property {boolean} gcImports
@property {(slot: CapTPSlot) => void} releaseSlot
@property {(slot: CapTPSlot) => RemoteKit} makeRemoteKit
@param {MakeCapTPImportExportTablesOptions} options
@returns {CapTPImportExportTables}