Skip to content

Commit

Permalink
refactor(daemon): Synchronize host makeGuest()
Browse files Browse the repository at this point in the history
  • Loading branch information
rekmarks committed Mar 8, 2024
1 parent 9623f98 commit 45e718a
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 42 deletions.
10 changes: 9 additions & 1 deletion packages/daemon/src/daemon.js
Original file line number Diff line number Diff line change
Expand Up @@ -1015,7 +1015,7 @@ const makeDaemonCore = async (
};

/** @type {import('./types.js').DaemonCore['incarnateGuest']} */
const incarnateGuest = async hostFormulaIdentifier => {
const incarnateGuest = async (hostFormulaIdentifier, hooks) => {
const {
guestFormulaNumber,
hostHandleFormulaIdentifier,
Expand All @@ -1041,6 +1041,14 @@ const makeDaemonCore = async (
]),
);

await hooks.execute({
guestFormulaIdentifier: serializeFormulaIdentifier({
type: 'guest',
number: ownFormulaNumber,
node: ownNodeIdentifier,
}),
});

return harden({
guestFormulaNumber: ownFormulaNumber,
hostHandleFormulaIdentifier: hostHandle.formulaIdentifier,
Expand Down
74 changes: 36 additions & 38 deletions packages/daemon/src/host.js
Original file line number Diff line number Diff line change
Expand Up @@ -132,48 +132,48 @@ export const makeHostMaker = ({
* @returns {Promise<{formulaIdentifier: string, value: Promise<import('./types.js').EndoGuest>}>}
*/
const makeGuest = async (petName, { introducedNames = {} } = {}) => {
/** @type {string | undefined} */
let formulaIdentifier;
if (petName !== undefined) {
formulaIdentifier = petStore.identifyLocal(petName);
}
const formulaIdentifier = petStore.identifyLocal(petName);
if (formulaIdentifier !== undefined) {
if (formulaIdentifier.startsWith('guest:')) {
throw new Error(
`Existing pet name does not designate a guest powers capability: ${q(
petName,
)}`,
);
}

if (formulaIdentifier === undefined) {
const { value, formulaIdentifier: guestFormulaIdentifier } =
// Behold, recursion:
// eslint-disable-next-line no-use-before-define
await incarnateGuest(hostFormulaIdentifier);
// TODO: move to hook
if (petName !== undefined) {
assertPetName(petName);
await petStore.write(petName, guestFormulaIdentifier);
// TODO: Should this be awaited?
introduceNamesToParty(formulaIdentifier, introducedNames);
const guestController =
provideControllerForFormulaIdentifier(formulaIdentifier);
return {
formulaIdentifier,
value: /** @type {Promise<import('./types.js').EndoGuest>} */ (
guestController.external
),
};
}
}

return {
value: Promise.resolve(value),
formulaIdentifier: guestFormulaIdentifier,
};
} else if (!formulaIdentifier.startsWith('guest:')) {
throw new Error(
`Existing pet name does not designate a guest powers capability: ${q(
petName,
)}`,
/** @type {AsyncHooks<import('./types.js').GuestHookParams>} */
const hooks = makeAsyncHooks();
if (petName !== undefined) {
hooks.add(identifiers =>
petStore.write(petName, identifiers.guestFormulaIdentifier),
);
}

if (introducedNames !== undefined) {
// TODO: move to hook
introduceNamesToParty(formulaIdentifier, introducedNames);
}
const newGuestController =
/** @type {import('./types.js').Controller<any, any>} */ (
provideControllerForFormulaIdentifier(formulaIdentifier)
);
const { value, formulaIdentifier } =
// Behold, recursion:
// eslint-disable-next-line no-use-before-define
await incarnateGuest(hostFormulaIdentifier, hooks);
// TODO: Should this be awaited?
introduceNamesToParty(formulaIdentifier, introducedNames);

return {
value: Promise.resolve(value),
formulaIdentifier,
value: /** @type {Promise<import('./types.js').EndoGuest>} */ (
newGuestController.external
),
};
};

Expand Down Expand Up @@ -280,7 +280,7 @@ export const makeHostMaker = ({
));
if (guestFormulaIdentifier === undefined) {
throw new Error(
`panic: provideGuest must return an guest with a corresponding formula identifier`,
`panic: makeGuest must return a guest with a corresponding formula identifier`,
);
}
}
Expand Down Expand Up @@ -308,7 +308,7 @@ export const makeHostMaker = ({
throw new Error('Evaluator requires one pet name for each code name');
}

/** @type {AsyncHooks<import('./types.js').EvalFormulaHooks>} */
/** @type {AsyncHooks<import('./types.js').EvalHookParams>} */
const hooks = makeAsyncHooks();

const workerFormulaIdentifier = provideWorkerFormulaIdentifierSync(
Expand Down Expand Up @@ -469,9 +469,7 @@ export const makeHostMaker = ({
);
}

if (introducedNames !== undefined) {
introduceNamesToParty(formulaIdentifier, introducedNames);
}
introduceNamesToParty(formulaIdentifier, introducedNames);
const newHostController =
/** @type {import('./types.js').Controller<>} */ (
provideControllerForFormulaIdentifier(formulaIdentifier)
Expand Down
2 changes: 2 additions & 0 deletions packages/daemon/src/pet-store.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,12 +85,14 @@ export const makePetStoreMaker = (filePowers, locator) => {
assertValidName(petName);
assertValidFormulaIdentifier(formulaIdentifier, petName);

// TODO: Return early if the formula identifier is the same.
if (petNames.has(petName)) {
// Perform cleanup on the overwritten pet name.
const formulaPetNames = formulaIdentifiers.get(petName);
if (formulaPetNames !== undefined) {
formulaPetNames.delete(petName);
}
// TODO: Should this only happen if something is actually deleted?
changesTopic.publisher.next({ remove: petName });
}

Expand Down
13 changes: 10 additions & 3 deletions packages/daemon/src/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ type GuestFormula = {
worker: string;
};

export type GuestHookParams = {
guestFormulaIdentifier: string;
};

type LeastAuthorityFormula = {
type: 'least-authority';
};
Expand All @@ -105,7 +109,7 @@ type EvalFormula = {
// TODO formula slots
};

export type EvalFormulaHooks = {
export type EvalHookParams = {
endowmentFormulaIdentifiers: string[];
evalFormulaIdentifier: string;
workerFormulaIdentifier: string;
Expand Down Expand Up @@ -751,7 +755,10 @@ export interface DaemonCore {
leastAuthorityFormulaIdentifier: string,
specifiedWorkerFormulaIdentifier?: string | undefined,
) => IncarnateResult<EndoHost>;
incarnateGuest: (hostFormulaIdentifier: string) => IncarnateResult<EndoGuest>;
incarnateGuest: (
hostFormulaIdentifier: string,
hooks: AsyncHooks<GuestHookParams>,
) => IncarnateResult<EndoGuest>;
incarnateReadableBlob: (
contentSha512: string,
) => IncarnateResult<FarEndoReadable>;
Expand All @@ -760,7 +767,7 @@ export interface DaemonCore {
source: string,
codeNames: string[],
endowmentFormulaIdsOrPaths: (string | string[])[],
hooks: AsyncHooks<EvalFormulaHooks>,
hooks: AsyncHooks<EvalHookParams>,
specifiedWorkerFormulaIdentifier?: string,
) => IncarnateResult<unknown>;
incarnateUnconfined: (
Expand Down

0 comments on commit 45e718a

Please sign in to comment.