Skip to content

Commit

Permalink
fix(liveslots): move passStyleOf from vatGlobals to inescapableGlobal…
Browse files Browse the repository at this point in the history
…Properties (#10005)

Previously, liveslots added the special `PassStyleOfEndowmentSymbol` on `vatGlobals`. This enabled the first-level vat bundle (the one that defines buildRootObject, e.g. ZCF) to use the same passStyleOf as liveslots is using, with a real WeakMap for its memoization cache.

However, child Compartments of that vat, such as the ones contract bundles are loaded into, do not automatically get the same global, and ZCF does not pass any special options to `importBundle()`, which would enable that.

This commit attaches the symbol to `inescapableGlobalProperties`, rather than `vatGlobals`. Those properties are automatically (indeed unavoidably) copied onto the `globalThis` of each child Compartment, recursively. This is stronger than we need: we're ok with a Compartment choosing to omit or change this property.

This allows contract code which does `import { passStyleOf } from '@endo/pass-style'` to get the correct/fast/cheap version too.

fixes #9981
  • Loading branch information
mergify[bot] authored Aug 31, 2024
2 parents a7d06d8 + e40a8b9 commit 661af66
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 12 deletions.
10 changes: 7 additions & 3 deletions packages/SwingSet/test/vat-env.test.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
// @ts-nocheck
// eslint-disable-next-line import/order
import { test, VatData } from '../tools/prepare-test-env-ava.js';

// eslint-disable-next-line import/order
import bundleSource from '@endo/bundle-source';
import { initSwingStore } from '@agoric/swing-store';
import { buildVatController } from '../src/index.js';

Expand Down Expand Up @@ -75,8 +76,9 @@ async function testForExpectedGlobals(t, workerType) {
},
defaultManagerType: workerType,
};
const bundle = await bundleSource(config.vats.bootstrap.sourceSpec);
const kernelStorage = initSwingStore().kernelStorage;
const c = await buildVatController(config, [], {
const c = await buildVatController(config, [bundle], {
kernelStorage,
});
t.teardown(c.shutdown);
Expand All @@ -98,7 +100,9 @@ async function testForExpectedGlobals(t, workerType) {
'VatData.makeScalarBigSetStore: function',
'VatData.makeScalarBigWeakSetStore: function',
'global has passStyleOf: true',
'global passStyleOf is special: false',
'passStyleOf delegates to global: true',
'child compartment has matching passStyleOf: true',
'grandchild compartment has matching passStyleOf: true',
]);
}

Expand Down
39 changes: 34 additions & 5 deletions packages/SwingSet/test/vat-envtest.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,30 @@
import { Far } from '@endo/far';
import { passStyleOf } from '@endo/pass-style';
import { PassStyleOfEndowmentSymbol } from '@endo/pass-style/endow.js';
import { importBundle } from '@endo/import-bundle';

export function buildRootObject(vatPowers) {
export function meta() {
return { globalThis, passStyleOf };
}

const endowments = {
console,
// See https://github.com/Agoric/agoric-sdk/issues/9515
assert: globalThis.assert,
VatData: globalThis.VatData,
};

export async function recurse(bundle) {
return importBundle(bundle, { endowments });
}

export function buildRootObject(vatPowers, vatParameters) {
const log = vatPowers.testLog;
const { argv } = vatParameters;
const [bundle] = argv;

return Far('root', {
bootstrap(_vats) {
async bootstrap(_vats) {
log(`control sample: ${typeof notThere}`);
log(`harden: ${typeof harden}`);
log(`VatData: ${typeof VatData}`);
Expand All @@ -18,9 +36,20 @@ export function buildRootObject(vatPowers) {
const globalPassStyleOf =
globalThis && globalThis[PassStyleOfEndowmentSymbol];
log(`global has passStyleOf: ${!!globalPassStyleOf}`);
log(
`global passStyleOf is special: ${globalPassStyleOf !== passStyleOf}`,
);
// we expect globalPassStyleOf and passStyleOf to be the same
// thing, because @endo/pass-style delegates to the version it
// finds on globalThis
const d1 = globalPassStyleOf === passStyleOf;
log(`passStyleOf delegates to global: ${d1}`);

// make sure sub-compartments automatically get passStyleOf too
const c1 = await importBundle(bundle, { endowments });
const m1 = c1.meta().passStyleOf === passStyleOf;
log(`child compartment has matching passStyleOf: ${m1}`);

const c2 = await c1.recurse(bundle);
const m2 = c2.meta().passStyleOf === passStyleOf;
log(`grandchild compartment has matching passStyleOf: ${m2}`);
},
});
}
2 changes: 1 addition & 1 deletion packages/swingset-liveslots/src/liveslots.js
Original file line number Diff line number Diff line change
Expand Up @@ -1208,12 +1208,12 @@ function build(
makeScalarBigSetStore: collectionManager.makeScalarBigSetStore,
makeScalarBigWeakSetStore: collectionManager.makeScalarBigWeakSetStore,
},
[PassStyleOfEndowmentSymbol]: passStyleOf,
});

const inescapableGlobalProperties = harden({
WeakMap: vom.VirtualObjectAwareWeakMap,
WeakSet: vom.VirtualObjectAwareWeakSet,
[PassStyleOfEndowmentSymbol]: passStyleOf,
});

function getRetentionStats() {
Expand Down
9 changes: 6 additions & 3 deletions packages/swingset-liveslots/test/vat-environment.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,15 @@ test('vat globals', async t => {
t.is(typeof vatGlobals.VatData.makeScalarBigWeakMapStore, 'function');
t.is(typeof vatGlobals.VatData.makeScalarBigSetStore, 'function');
t.is(typeof vatGlobals.VatData.makeScalarBigWeakSetStore, 'function');
t.is(typeof vatGlobals[PassStyleOfEndowmentSymbol], 'function');
// this is the passStyleOf created by liveslots, with a real WeakMap
t.is(vatGlobals[PassStyleOfEndowmentSymbol], passStyleOf);

t.is(typeof inescapableGlobalProperties.WeakMap, 'function');
t.not(inescapableGlobalProperties.WeakMap, WeakMap);
t.is(typeof inescapableGlobalProperties.WeakSet, 'function');
t.not(inescapableGlobalProperties.WeakSet, WeakSet);
t.is(
typeof inescapableGlobalProperties[PassStyleOfEndowmentSymbol],
'function',
);
// this is the passStyleOf created by liveslots, with a real WeakMap
t.is(inescapableGlobalProperties[PassStyleOfEndowmentSymbol], passStyleOf);
});

0 comments on commit 661af66

Please sign in to comment.