From 2ddbd78d45f9d16b6866689217bdd8d360c8d2d6 Mon Sep 17 00:00:00 2001 From: "Mark S. Miller" Date: Tue, 14 May 2024 12:56:36 -0700 Subject: [PATCH] fixup! bijections no longer weak --- packages/async-flow/src/async-flow.js | 6 ++--- .../src/{weak-bijection.js => bijection.js} | 27 +++++++++++-------- packages/async-flow/src/replay-membrane.js | 2 +- packages/async-flow/src/types.js | 4 +-- ...ak-bijection.test.js => bijection.test.js} | 4 +-- packages/async-flow/test/convert.test.js | 4 +-- packages/async-flow/test/equate.test.js | 4 +-- .../test/replay-membrane-settlement.test.js | 8 +++--- .../async-flow/test/replay-membrane.test.js | 12 ++++----- 9 files changed, 38 insertions(+), 33 deletions(-) rename packages/async-flow/src/{weak-bijection.js => bijection.js} (76%) rename packages/async-flow/test/{weak-bijection.test.js => bijection.test.js} (94%) diff --git a/packages/async-flow/src/async-flow.js b/packages/async-flow/src/async-flow.js index 0132c023f798..f4f6504e9946 100644 --- a/packages/async-flow/src/async-flow.js +++ b/packages/async-flow/src/async-flow.js @@ -6,7 +6,7 @@ import { PromiseWatcherI } from '@agoric/base-zone'; import { prepareVowTools, toPassableCap, VowShape } from '@agoric/vow'; import { makeReplayMembrane } from './replay-membrane.js'; import { prepareLogStore } from './log-store.js'; -import { prepareWeakBijection } from './weak-bijection.js'; +import { prepareBijection } from './bijection.js'; import { LogEntryShape, FlowStateShape } from './type-guards.js'; const { defineProperties } = Object; @@ -42,7 +42,7 @@ export const prepareAsyncFlowTools = (outerZone, outerOptions = {}) => { const { vowTools = prepareVowTools(outerZone), makeLogStore = prepareLogStore(outerZone), - makeWeakBijection = prepareWeakBijection(outerZone), + makeBijection = prepareBijection(outerZone), } = outerOptions; const { watch, makeVowKit } = vowTools; @@ -95,7 +95,7 @@ export const prepareAsyncFlowTools = (outerZone, outerOptions = {}) => { activationArgs => { harden(activationArgs); const log = makeLogStore(); - const bijection = makeWeakBijection(); + const bijection = makeBijection(); return { activationArgs, // replay starts by reactivating with these diff --git a/packages/async-flow/src/weak-bijection.js b/packages/async-flow/src/bijection.js similarity index 76% rename from packages/async-flow/src/weak-bijection.js rename to packages/async-flow/src/bijection.js index fdd48a080829..8f06b3d55f96 100644 --- a/packages/async-flow/src/weak-bijection.js +++ b/packages/async-flow/src/bijection.js @@ -4,7 +4,7 @@ import { Far } from '@endo/pass-style'; import { toPassableCap } from '@agoric/vow'; import { makeEphemera } from './ephemera.js'; -const WeakBijectionI = M.interface('WeakBijection', { +const BijectionI = M.interface('Bijection', { reset: M.call().returns(), init: M.call(M.any(), M.any()).returns(), hasGuest: M.call(M.any()).returns(M.boolean()), @@ -22,10 +22,15 @@ const WeakBijectionI = M.interface('WeakBijection', { * @param {string} name */ const makeVowishStore = name => { - // The vowMap would be needed if we supported enumeration, - // in order to reconstruct the original keys. - // const vowMap = new Map(); - const map = new WeakMap(); + // This internal map could be (and was) a WeakMap. But there are various ways + // in which a WeakMap is more expensive than a Map. The main advantage is + // that a WeakMap can drop entries whose keys are not otherwise retained. + // But async-flow only uses a bijection together with a log-store that happens + // to durably retain all the host-side keys of the associated bijection, so + // this additional feature of the bijection is irrelevant. When the bijection + // is reset or revived in a new incarnation, these vowishStores will be gone + // anyway, dropping all the guest-side objects. + const map = new Map(); return Far(name, { init: (k, v) => { @@ -51,13 +56,13 @@ const makeVowishStore = name => { /** * @param {Zone} zone */ -export const prepareWeakBijection = zone => { - /** @type {Ephemera} */ +export const prepareBijection = zone => { + /** @type {Ephemera} */ const g2h = makeEphemera(() => makeVowishStore('guestToHost')); - /** @type {Ephemera} */ + /** @type {Ephemera} */ const h2g = makeEphemera(() => makeVowishStore('hostToGuest')); - return zone.exoClass('WeakBijection', WeakBijectionI, () => ({}), { + return zone.exoClass('Bijection', BijectionI, () => ({}), { reset() { const { self } = this; @@ -120,8 +125,8 @@ export const prepareWeakBijection = zone => { }, }); }; -harden(prepareWeakBijection); +harden(prepareBijection); /** - * @typedef {ReturnType>} WeakBijection + * @typedef {ReturnType>} Bijection */ diff --git a/packages/async-flow/src/replay-membrane.js b/packages/async-flow/src/replay-membrane.js index b54d6a9102aa..b56134a1d64f 100644 --- a/packages/async-flow/src/replay-membrane.js +++ b/packages/async-flow/src/replay-membrane.js @@ -11,7 +11,7 @@ const { fromEntries, defineProperties } = Object; /** * @param {LogStore} log - * @param {WeakBijection} bijection + * @param {Bijection} bijection * @param {VowTools} vowTools * @param {(vowish: Promise | Vow) => void} watchWake * @param {(problem: Error) => never} panic diff --git a/packages/async-flow/src/types.js b/packages/async-flow/src/types.js index 842574673906..f018c081a516 100644 --- a/packages/async-flow/src/types.js +++ b/packages/async-flow/src/types.js @@ -4,7 +4,7 @@ * @import {Zone} from '@agoric/base-zone' * @import {Vow, VowTools} from '@agoric/vow' * @import {LogStore} from './log-store.js' - * @import {WeakBijection} from './weak-bijection.js' + * @import {Bijection} from './bijection.js' * @import {ReplayMembrane} from './replay-membrane.js' */ @@ -47,7 +47,7 @@ * @typedef {object} PreparationOptions * @property {VowTools} [vowTools] * @property {() => LogStore} [makeLogStore] - * @property {() => WeakBijection} [makeWeakBijection] + * @property {() => Bijection} [makeBijection] */ /** diff --git a/packages/async-flow/test/weak-bijection.test.js b/packages/async-flow/test/bijection.test.js similarity index 94% rename from packages/async-flow/test/weak-bijection.test.js rename to packages/async-flow/test/bijection.test.js index e4900e6f9da0..b75a861720ec 100644 --- a/packages/async-flow/test/weak-bijection.test.js +++ b/packages/async-flow/test/bijection.test.js @@ -13,7 +13,7 @@ import { makeHeapZone } from '@agoric/zone/heap.js'; import { makeVirtualZone } from '@agoric/zone/virtual.js'; import { makeDurableZone } from '@agoric/zone/durable.js'; -import { prepareWeakBijection } from '../src/weak-bijection.js'; +import { prepareBijection } from '../src/bijection.js'; /** * @param {any} t @@ -21,7 +21,7 @@ import { prepareWeakBijection } from '../src/weak-bijection.js'; */ const testBijection = (t, zone) => { const { makeVowKit } = prepareVowTools(zone); - const makeBijection = prepareWeakBijection(zone); + const makeBijection = prepareBijection(zone); const bij = zone.makeOnce('bij', makeBijection); const h1 = zone.exo('h1', undefined, {}); diff --git a/packages/async-flow/test/convert.test.js b/packages/async-flow/test/convert.test.js index ab4cb38fd7ae..e5373ef73e29 100644 --- a/packages/async-flow/test/convert.test.js +++ b/packages/async-flow/test/convert.test.js @@ -16,7 +16,7 @@ import { makeVirtualZone } from '@agoric/zone/virtual.js'; import { makeDurableZone } from '@agoric/zone/durable.js'; import { makeConvertKit } from '../src/convert.js'; -import { prepareWeakBijection } from '../src/weak-bijection.js'; +import { prepareBijection } from '../src/bijection.js'; /** * @param {any} t @@ -25,7 +25,7 @@ import { prepareWeakBijection } from '../src/weak-bijection.js'; */ const testConvert = (t, zone, showOnConsole = false) => { const { makeVowKit } = prepareVowTools(zone); - const makeBijection = prepareWeakBijection(zone); + const makeBijection = prepareBijection(zone); const bij = zone.makeOnce('bij', makeBijection); const makeGuestForHostRemotable = hRem => { diff --git a/packages/async-flow/test/equate.test.js b/packages/async-flow/test/equate.test.js index 92004ae14324..c90040a42a6e 100644 --- a/packages/async-flow/test/equate.test.js +++ b/packages/async-flow/test/equate.test.js @@ -15,7 +15,7 @@ import { makeHeapZone } from '@agoric/zone/heap.js'; import { makeVirtualZone } from '@agoric/zone/virtual.js'; import { makeDurableZone } from '@agoric/zone/durable.js'; -import { prepareWeakBijection } from '../src/weak-bijection.js'; +import { prepareBijection } from '../src/bijection.js'; import { makeEquate } from '../src/equate.js'; /** @@ -25,7 +25,7 @@ import { makeEquate } from '../src/equate.js'; */ const testEquate = (t, zone, showOnConsole = false) => { const { makeVowKit } = prepareVowTools(zone); - const makeBijection = prepareWeakBijection(zone); + const makeBijection = prepareBijection(zone); const bij = zone.makeOnce('bij', makeBijection); t.throws(() => zone.makeOnce('equate', () => makeEquate(bij)), { diff --git a/packages/async-flow/test/replay-membrane-settlement.test.js b/packages/async-flow/test/replay-membrane-settlement.test.js index 7276f57300b8..6537eadb0c54 100644 --- a/packages/async-flow/test/replay-membrane-settlement.test.js +++ b/packages/async-flow/test/replay-membrane-settlement.test.js @@ -14,7 +14,7 @@ import { makeVirtualZone } from '@agoric/zone/virtual.js'; import { makeDurableZone } from '@agoric/zone/durable.js'; import { prepareLogStore } from '../src/log-store.js'; -import { prepareWeakBijection } from '../src/weak-bijection.js'; +import { prepareBijection } from '../src/bijection.js'; import { makeReplayMembrane } from '../src/replay-membrane.js'; const watchWake = _vowish => {}; @@ -36,7 +36,7 @@ const testFirstPlay = async (t, zone) => { const vowTools = prepareVowTools(zone); const { makeVowKit } = vowTools; const makeLogStore = prepareLogStore(zone); - const makeBijection = prepareWeakBijection(zone); + const makeBijection = prepareBijection(zone); const makePingee = preparePingee(zone); const { vow: v1, resolver: r1 } = zone.makeOnce('v1', () => makeVowKit()); const { vow: _v2, resolver: _r2 } = zone.makeOnce('v2', () => makeVowKit()); @@ -77,7 +77,7 @@ const testFirstPlay = async (t, zone) => { const testReplay = async (t, zone) => { const vowTools = prepareVowTools(zone); prepareLogStore(zone); - prepareWeakBijection(zone); + prepareBijection(zone); preparePingee(zone); const { vow: v1 } = zone.makeOnce('v1', () => Fail`need v1`); const { vow: v2, resolver: r2 } = zone.makeOnce('v2', () => Fail`need v2`); @@ -85,7 +85,7 @@ const testReplay = async (t, zone) => { const log = /** @type {LogStore} */ ( zone.makeOnce('log', () => Fail`need log`) ); - const bij = /** @type {WeakBijection} */ ( + const bij = /** @type {Bijection} */ ( zone.makeOnce('bij', () => Fail`need bij`) ); diff --git a/packages/async-flow/test/replay-membrane.test.js b/packages/async-flow/test/replay-membrane.test.js index 1f3f218d6d44..9183877fbc91 100644 --- a/packages/async-flow/test/replay-membrane.test.js +++ b/packages/async-flow/test/replay-membrane.test.js @@ -15,7 +15,7 @@ import { makeVirtualZone } from '@agoric/zone/virtual.js'; import { makeDurableZone } from '@agoric/zone/durable.js'; import { prepareLogStore } from '../src/log-store.js'; -import { prepareWeakBijection } from '../src/weak-bijection.js'; +import { prepareBijection } from '../src/bijection.js'; import { makeReplayMembrane } from '../src/replay-membrane.js'; const watchWake = _vowish => {}; @@ -55,7 +55,7 @@ const testFirstPlay = async (t, zone, showOnConsole = false) => { const vowTools = prepareVowTools(zone); const { makeVowKit } = vowTools; const makeLogStore = prepareLogStore(zone); - const makeBijection = prepareWeakBijection(zone); + const makeBijection = prepareBijection(zone); const makeOrchestra = prepareOrchestra(zone); const { vow: v1, resolver: r1 } = makeVowKit(); const { vow: v2, resolver: r2 } = makeVowKit(); @@ -120,13 +120,13 @@ const testFirstPlay = async (t, zone, showOnConsole = false) => { const testBadReplay = async (t, zone) => { const vowTools = prepareVowTools(zone); prepareLogStore(zone); - prepareWeakBijection(zone); + prepareBijection(zone); prepareOrchestra(zone); const log = /** @type {LogStore} */ ( zone.makeOnce('log', () => Fail`need log`) ); - const bij = /** @type {WeakBijection} */ ( + const bij = /** @type {Bijection} */ ( zone.makeOnce('bij', () => Fail`need bij`) ); @@ -166,13 +166,13 @@ const testBadReplay = async (t, zone) => { const testGoodReplay = async (t, zone) => { const vowTools = prepareVowTools(zone); prepareLogStore(zone); - prepareWeakBijection(zone); + prepareBijection(zone); prepareOrchestra(zone, 2); // 2 is new incarnation behavior change const log = /** @type {LogStore} */ ( zone.makeOnce('log', () => Fail`need log`) ); - const bij = /** @type {WeakBijection} */ ( + const bij = /** @type {Bijection} */ ( zone.makeOnce('bij', () => Fail`need bij`) );