From d2def8adf1a1c8f16ff9f390427a70df28187eec Mon Sep 17 00:00:00 2001 From: Chip Morningstar Date: Thu, 16 Jan 2025 16:48:12 -0800 Subject: [PATCH] chore: Clean up and document `dummyMeterControl` Closes #341 --- packages/kernel/src/dummyMeterControl.ts | 65 +++++++++++++++++++++--- 1 file changed, 58 insertions(+), 7 deletions(-) diff --git a/packages/kernel/src/dummyMeterControl.ts b/packages/kernel/src/dummyMeterControl.ts index 95cfa07ab..690a6935e 100644 --- a/packages/kernel/src/dummyMeterControl.ts +++ b/packages/kernel/src/dummyMeterControl.ts @@ -1,22 +1,51 @@ import { assert } from '@endo/errors'; -/* eslint-disable jsdoc/require-jsdoc */ +import type { MeterControl } from './ag-types.js'; -export function makeDummyMeterControl(): unknown { +/** + * Liveslots must be given a MeterControl object so it can turn metering on and + * off in metered execution environments. We have no metering, so this produces + * an object that obeys the MeterControl API but doesn't actually do anything. + * + * @returns a dummy MeterControl object. + */ +export function makeDummyMeterControl(): MeterControl { + /** Depth of metering disablement */ let meteringDisabled = 0; + /** + * Test if metering is disabled. + * + * @returns true iff metering is currently off. + */ function isMeteringDisabled(): boolean { - return Boolean(meteringDisabled); + return meteringDisabled > 0; } + /** + * Require metering to be on. + * + * @param message - Error message to throw if metering is off. + */ function assertIsMetered(message: string): void { - assert(!meteringDisabled, message); + assert(meteringDisabled === 0, message); } + /** + * Require metering to be off. + * + * @param message - Error message to throw if metering is on. + */ function assertNotMetered(message: string): void { - assert(Boolean(meteringDisabled), message); + assert(meteringDisabled > 0, message); } + /** + * Execute a thunk with metering off. + * + * @param thunk - The thunk to execute. + * @returns whatever `thunk` returns. + */ function runWithoutMetering(thunk: () => unknown): unknown { meteringDisabled += 1; try { @@ -26,6 +55,12 @@ export function makeDummyMeterControl(): unknown { } } + /** + * Execute an aynchronous thunk with metering off. + * + * @param thunk - The thunk to execute. + * @returns a promise for whatever `thunk` returns. + */ async function runWithoutMeteringAsync( thunk: () => unknown, ): Promise { @@ -37,8 +72,24 @@ export function makeDummyMeterControl(): unknown { }); } - // return a version of func that runs outside metering - function unmetered(func: (...args: unknown[]) => unknown): unknown { + /** + * Return a version of func that runs outside metering. Since we have no + * metering, everything actually runs outside metering, so func itself would + * do, but we need to wrap it anyway to account for the nesting depth of + * metering disablement. + * + * @param func - The function to wrap. + * @returns A version of `func` that runs without being metered. + */ + function unmetered( + func: (...args: unknown[]) => unknown, + ): (...args: unknown[]) => unknown { + /** + * A version of `func` with `runWithoutMetering` wrapped around it. + * + * @param args - The args to `func`. + * @returns whatever `func` returns. + */ function wrapped(...args: unknown[]): unknown { return runWithoutMetering(() => func(...args)); }