From fc569cefd2a1aae93c349fd1aedb2040cb20ce3d Mon Sep 17 00:00:00 2001 From: "Mark S. Miller" Date: Sat, 13 Jul 2024 15:41:51 -0700 Subject: [PATCH] refactor: insert `await null;`s needed for await safety (#2347) Closes: #XXXX Refs: #XXXX ## Description Prior to this PR, `yarn lint` warns about many violations of our `await` safety rules. In vscode, I was very pleasantly surprised to learn about the automated fixes offered interactively for these: ![image](https://github.com/user-attachments/assets/6be443de-dcd8-4e1a-b714-6a1f1106bd61) For each of these, I accepted the "insert `await null;` before..." option. Uniquely for the one shown in the above screenshot I needed to do an additional manual readjustment to move the `// eslint-disable-next-line ...` so it would still be about the next line. Caveats: - I applied the automated fix manually, without reading the code in question or in any other way validating that this change is correctness preserving. My only evidence at the moment is that all the tests still pass. - I would have loved to mark this PR with `refactor:` or at least `fix:`. But I marked it with `fix!` because there's no reason yet to think these changes are either correctness preserving or compat. - I applied the automated change blindly even to the test files, even though we're not normally concerned about `await` safety there. Indeed, we should also change our lint configuration so `await` safety is unenforced for those. After this PR, we should also change our `await` safety enforcement for non-test files from "warning" to "error", to keep these from creeping back in. - I applied the automated fix to the test files anyway since test code still often serves as precedent-by-example for production code. Since the automated fix made it easy to do this, I decided it was better to improve our test-code-as-precedent. Obviously, this should not be merged until we're confident that these changes are correctness preserving. I don't know of any way to do so other than careful manual review. Perhaps as part of the same review, we might also conclude that it is compat, in which case we can change back from `fix!` to `fix:` or even hopefully `refactor:`. For the various "considerations" below, I'll answer under the assumption that we have already reviewed these changes for correctness, and deemed them all to be correctness preserving. Obviously, until that happens, this PR is fatal re all the considerations below. Update: As suggested by review comments, I moved those inserted `await null;`s to the top of their respective functions. Update: Between @kriskowal 's evaluation comments below and my own inspection, I'm reasonably confident that this PR should count as a refactor, so I'm changing the title from `fix!...` to `refactor:...`. ### Security Considerations Assuming the changes are correctness preserving, `await` safety aids security. ### Scaling Considerations none ### Documentation Considerations we already need to explain `await` safety. This PR doesn't change that, but repairs our code so that we practice what we will preach. ### Testing Considerations A bit distressing that all tests pass without any further intervention. This perhaps indicates a failure to test for the semantics that are changed by these extra awaits. ### Compatibility Considerations If this change is correctness preserving, then it is likely also compat. But not necessarily. The extra awaits introduce extra turn delays and extra interleaving points. ### Upgrade Considerations If this PR is correctness preserving and compat, then there are unlikely to be any upgrade considerations. But I don't know that for sure, so we should also worry about this during review. --- packages/base64/test/bench-main.js | 1 + packages/captp/test/export-hook.test.js | 1 + packages/captp/test/gc.test.js | 1 + packages/captp/test/trap.test.js | 1 + packages/captp/test/traplib.js | 1 + packages/check-bundle/lite.js | 1 + packages/cli/src/client.js | 1 + packages/cli/src/commands/accept.js | 1 + packages/cli/src/commands/list.js | 1 + packages/cli/src/commands/log.js | 1 + packages/cli/src/commands/make.js | 2 ++ packages/cli/src/commands/run.js | 1 + packages/cli/src/commands/store.js | 1 + packages/cli/src/context.js | 1 + .../common/test/apply-labeling-error.test.js | 1 + packages/compartment-mapper/src/archive-lite.js | 1 + .../src/import-archive-lite.js | 2 ++ packages/compartment-mapper/src/import-hook.js | 1 + packages/compartment-mapper/src/link.js | 1 + packages/compartment-mapper/src/node-modules.js | 1 + packages/compartment-mapper/src/node-powers.js | 2 ++ packages/compartment-mapper/src/search.js | 1 + packages/compartment-mapper/test/policy.test.js | 1 + packages/compartment-mapper/test/scaffold.js | 2 ++ .../test/snapshots/error-handling.test.js.md | 12 ++++++++++-- .../test/snapshots/error-handling.test.js.snap | Bin 787 -> 799 bytes packages/compartment-mapper/test/stack.test.js | 1 + packages/daemon/index.js | 1 + packages/daemon/src/daemon-node-powers.js | 3 ++- packages/daemon/src/serve-private-port-http.js | 1 + packages/daemon/src/web-server-node-powers.js | 1 + packages/daemon/src/web-server-node.js | 2 +- packages/daemon/test/context-consumer.js | 1 + packages/eventual-send/test/e.test.js | 3 +++ .../eventual-send/test/eventual-send.test.js | 3 +++ packages/eventual-send/test/thenable.test.js | 1 + packages/exo/test/exo-only-throwables.test.js | 1 + .../exo/test/legacy-guard-tolerance.test.js | 1 + packages/far/test/e.test.js | 3 +++ packages/import-bundle/src/index.js | 1 + .../import-bundle/test/import-bundle.test.js | 1 + packages/lp32/test/lp32.test.js | 1 + packages/netstring/test/netstring.test.js | 2 ++ packages/ses/src/module-load.js | 2 ++ ...ipate-async-iterator-helpers-shimmed.test.js | 1 + packages/ses/test/error/aggregate-error.test.js | 1 + packages/ses/test/import-gauntlet.test.js | 1 + packages/ses/test/import-stack-traces.test.js | 1 + packages/ses/test/import.test.js | 2 ++ .../test/tame-domains-after-lockdown.test.js | 1 + .../test/static-module-record.test.js | 2 ++ packages/stream-node/test/stream-node.test.js | 3 +++ packages/stream/index.js | 3 +++ packages/stream/test/map.test.js | 3 +++ packages/stream/test/prime.test.js | 3 +++ packages/stream/test/pump.test.js | 1 + packages/stream/test/stream.test.js | 3 +++ 57 files changed, 90 insertions(+), 4 deletions(-) diff --git a/packages/base64/test/bench-main.js b/packages/base64/test/bench-main.js index 4424c66a1b..ab9b3e7671 100644 --- a/packages/base64/test/bench-main.js +++ b/packages/base64/test/bench-main.js @@ -16,6 +16,7 @@ async function main() { const log = (typeof console !== 'undefined' && console.log) || print; /** @type {typeof Date.now} */ const now = await (async () => { + await null; try { const { performance } = await import('perf_hooks'); if (performance.now) { diff --git a/packages/captp/test/export-hook.test.js b/packages/captp/test/export-hook.test.js index 541e44708e..ec211463ac 100644 --- a/packages/captp/test/export-hook.test.js +++ b/packages/captp/test/export-hook.test.js @@ -6,6 +6,7 @@ import { Far } from '@endo/marshal'; import { E, makeLoopback } from '../src/loopback.js'; test('exportHook', async t => { + await null; const exports = []; const { makeFar } = makeLoopback('us', { diff --git a/packages/captp/test/gc.test.js b/packages/captp/test/gc.test.js index af3eb3622c..918dc094cb 100644 --- a/packages/captp/test/gc.test.js +++ b/packages/captp/test/gc.test.js @@ -7,6 +7,7 @@ import { detectEngineGC } from './engine-gc.js'; import { makeGcAndFinalize } from './gc-and-finalize.js'; const isolated = async (t, makeFar) => { + await null; const local = Far('local', { method: () => 'local', }); diff --git a/packages/captp/test/trap.test.js b/packages/captp/test/trap.test.js index fc478182e3..37c02396c1 100644 --- a/packages/captp/test/trap.test.js +++ b/packages/captp/test/trap.test.js @@ -16,6 +16,7 @@ import { const dirname = url.fileURLToPath(new URL('./', import.meta.url)); const makeWorkerTests = isHost => async t => { + await null; const initFn = isHost ? makeHost : makeGuest; for (let len = 0; len < MIN_TRANSFER_BUFFER_LENGTH; len += 1) { t.throws(() => initFn(() => {}, new SharedArrayBuffer(len)), { diff --git a/packages/captp/test/traplib.js b/packages/captp/test/traplib.js index 41fdf09029..7b6138dc7a 100644 --- a/packages/captp/test/traplib.js +++ b/packages/captp/test/traplib.js @@ -24,6 +24,7 @@ export const createHostBootstrap = makeTrapHandler => { }; export const runTrapTests = async (t, Trap, bs, unwrapsPromises) => { + await null; // Demonstrate async compatibility of traps. const pn = E(E(bs).getTraps(3)).getN(); t.is(Promise.resolve(pn), pn); diff --git a/packages/check-bundle/lite.js b/packages/check-bundle/lite.js index b8c54f2e60..20691423ab 100644 --- a/packages/check-bundle/lite.js +++ b/packages/check-bundle/lite.js @@ -22,6 +22,7 @@ export const checkBundle = async ( computeSha512, bundleName = '', ) => { + await null; assert.typeof( bundle, 'object', diff --git a/packages/cli/src/client.js b/packages/cli/src/client.js index 2846913eec..da944090c7 100644 --- a/packages/cli/src/client.js +++ b/packages/cli/src/client.js @@ -13,6 +13,7 @@ export const provideEndoClient = async ( cancelled, bootstrap, ) => { + await null; try { // It is okay to fail to connect because the daemon is not running. return await makeEndoClient(name, sockPath, cancelled, bootstrap); diff --git a/packages/cli/src/commands/accept.js b/packages/cli/src/commands/accept.js index e3391f3d6c..a590f573e5 100644 --- a/packages/cli/src/commands/accept.js +++ b/packages/cli/src/commands/accept.js @@ -12,6 +12,7 @@ const fromAsync = async iterable => { }; export const accept = async ({ guestName, agentNames }) => { + await null; process.stdin.setEncoding('utf-8'); const invitationLocator = (await fromAsync(process.stdin)).join('').trim(); return withEndoAgent(agentNames, { os, process }, async ({ agent }) => { diff --git a/packages/cli/src/commands/list.js b/packages/cli/src/commands/list.js index 1138a8f741..c43d231885 100644 --- a/packages/cli/src/commands/list.js +++ b/packages/cli/src/commands/list.js @@ -36,6 +36,7 @@ const pad = (fieldVal, width, minPad = 2) => { export const list = async ({ directory, follow, json, verbose }) => withEndoHost({ os, process }, async ({ host: agent }) => { + await null; if (directory !== undefined) { const directoryPath = parsePetNamePath(directory); agent = E(agent).lookup(...directoryPath); diff --git a/packages/cli/src/commands/log.js b/packages/cli/src/commands/log.js index 83efe283f3..c555cffcb3 100644 --- a/packages/cli/src/commands/log.js +++ b/packages/cli/src/commands/log.js @@ -24,6 +24,7 @@ const delay = async (ms, cancelled) => { export const log = async ({ follow, ping }) => withInterrupt(async ({ cancelled }) => { + await null; const logCheckIntervalMs = ping !== undefined ? Number(ping) : 5_000; const { username, homedir } = os.userInfo(); diff --git a/packages/cli/src/commands/make.js b/packages/cli/src/commands/make.js index b22bdc19e6..0a6d7dde81 100644 --- a/packages/cli/src/commands/make.js +++ b/packages/cli/src/commands/make.js @@ -22,6 +22,7 @@ export const makeCommand = async ({ agentNames, powersName, }) => { + await null; if (filePath !== undefined && importPath !== undefined) { console.error('Specify only one of [file] or --UNCONFINED '); process.exitCode = 1; @@ -61,6 +62,7 @@ export const makeCommand = async ({ } await withEndoAgent(agentNames, { os, process }, async ({ agent }) => { + await null; // Prepare a bundle, with the given name. if (bundleReaderRef !== undefined) { await E(agent).storeBlob(bundleReaderRef, bundleName); diff --git a/packages/cli/src/commands/run.js b/packages/cli/src/commands/run.js index 4b528d4226..81ee0d7804 100644 --- a/packages/cli/src/commands/run.js +++ b/packages/cli/src/commands/run.js @@ -44,6 +44,7 @@ export const run = async ({ agentNames, { os, process }, async ({ bootstrap, agent }) => { + await null; let powersP; if (powersName === 'NONE') { powersP = E(bootstrap).leastAuthority(); diff --git a/packages/cli/src/commands/store.js b/packages/cli/src/commands/store.js index c42cad028e..7c70a04232 100644 --- a/packages/cli/src/commands/store.js +++ b/packages/cli/src/commands/store.js @@ -76,6 +76,7 @@ export const store = async ({ const parsedName = parsePetNamePath(name); await withEndoAgent(agentNames, { os, process }, async ({ agent }) => { + await null; if (storeText !== undefined) { await E(agent).storeValue(storeText, parsedName); } else if (storeJson !== undefined) { diff --git a/packages/cli/src/context.js b/packages/cli/src/context.js index 8c0f2863f4..6c0b90ebd2 100644 --- a/packages/cli/src/context.js +++ b/packages/cli/src/context.js @@ -7,6 +7,7 @@ import { provideEndoClient } from './client.js'; import { parsePetNamePath } from './pet-name.js'; export const withInterrupt = async callback => { + await null; const { promise: cancelled, reject: cancel } = makePromiseKit(); cancelled.catch(() => {}); process.once('SIGINT', () => cancel(Error('SIGINT'))); diff --git a/packages/common/test/apply-labeling-error.test.js b/packages/common/test/apply-labeling-error.test.js index 9af308764a..4675824020 100644 --- a/packages/common/test/apply-labeling-error.test.js +++ b/packages/common/test/apply-labeling-error.test.js @@ -4,6 +4,7 @@ import { Fail } from '@endo/errors'; import { applyLabelingError } from '../apply-labeling-error.js'; test('test applyLabelingError', async t => { + await null; t.is( applyLabelingError(x => x * 2, [8]), 16, diff --git a/packages/compartment-mapper/src/archive-lite.js b/packages/compartment-mapper/src/archive-lite.js index 000790718d..f48f62e0c3 100644 --- a/packages/compartment-mapper/src/archive-lite.js +++ b/packages/compartment-mapper/src/archive-lite.js @@ -226,6 +226,7 @@ const renameSources = (sources, compartmentRenames) => { * @param {Sources} sources */ const addSourcesToArchive = async (archive, sources) => { + await null; for (const compartment of keys(sources).sort()) { const modules = sources[compartment]; const compartmentLocation = resolveLocation(`${compartment}/`, 'file:///'); diff --git a/packages/compartment-mapper/src/import-archive-lite.js b/packages/compartment-mapper/src/import-archive-lite.js index 01de9ff02c..774e8e0773 100644 --- a/packages/compartment-mapper/src/import-archive-lite.js +++ b/packages/compartment-mapper/src/import-archive-lite.js @@ -105,6 +105,7 @@ const makeArchiveImportHookMaker = ( const { modules } = compartmentDescriptor; /** @type {ImportHook} */ const importHook = async moduleSpecifier => { + await null; // per-module: const module = modules[moduleSpecifier]; if (module === undefined) { @@ -280,6 +281,7 @@ export const parseArchive = async ( archiveLocation = '', options = {}, ) => { + await null; const { computeSha512 = undefined, expectedSha512 = undefined, diff --git a/packages/compartment-mapper/src/import-hook.js b/packages/compartment-mapper/src/import-hook.js index 5d73be530d..aad21e4ad1 100644 --- a/packages/compartment-mapper/src/import-hook.js +++ b/packages/compartment-mapper/src/import-hook.js @@ -209,6 +209,7 @@ export const makeImportHookMaker = ( /** @type {ImportHook} */ const importHook = async moduleSpecifier => { + await null; compartmentDescriptor.retained = true; // per-module: diff --git a/packages/compartment-mapper/src/link.js b/packages/compartment-mapper/src/link.js index d1bd8646ac..fa529a309a 100644 --- a/packages/compartment-mapper/src/link.js +++ b/packages/compartment-mapper/src/link.js @@ -84,6 +84,7 @@ const makeExtensionParser = ( moduleTransforms, ) => { return async (bytes, specifier, location, packageLocation, options) => { + await null; let language; const extension = parseExtension(location); diff --git a/packages/compartment-mapper/src/node-modules.js b/packages/compartment-mapper/src/node-modules.js index 5509d3cd35..faa2a5168c 100644 --- a/packages/compartment-mapper/src/node-modules.js +++ b/packages/compartment-mapper/src/node-modules.js @@ -152,6 +152,7 @@ const readDescriptorWithMemo = async (memo, maybeRead, packageLocation) => { * } | undefined>} */ const findPackage = async (readDescriptor, canonical, directory, name) => { + await null; for (;;) { // eslint-disable-next-line no-await-in-loop const packageLocation = await canonical( diff --git a/packages/compartment-mapper/src/node-powers.js b/packages/compartment-mapper/src/node-powers.js index 1ea242cdb6..0f315fe9c3 100644 --- a/packages/compartment-mapper/src/node-powers.js +++ b/packages/compartment-mapper/src/node-powers.js @@ -104,6 +104,7 @@ const makeReadPowersSloppy = ({ fs, url = undefined, crypto = undefined }) => { * @param {string} location */ const canonical = async location => { + await null; try { if (location.endsWith('/')) { const realPath = await fs.promises.realpath( @@ -157,6 +158,7 @@ const makeWritePowersSloppy = ({ fs, url = undefined }) => { * @param {Uint8Array} data */ const write = async (location, data) => { + await null; try { return await fs.promises.writeFile(fileURLToPath(location), data); } catch (error) { diff --git a/packages/compartment-mapper/src/search.js b/packages/compartment-mapper/src/search.js index 098516cd96..406c39990c 100644 --- a/packages/compartment-mapper/src/search.js +++ b/packages/compartment-mapper/src/search.js @@ -33,6 +33,7 @@ const resolveLocation = (rel, abs) => new URL(rel, abs).toString(); * @returns {Promise<{data:T, directory: string, location:string, packageDescriptorLocation: string}>} */ export const searchDescriptor = async (location, readDescriptor) => { + await null; let directory = resolveLocation('./', location); for (;;) { const packageDescriptorLocation = resolveLocation( diff --git a/packages/compartment-mapper/test/policy.test.js b/packages/compartment-mapper/test/policy.test.js index 7884ab9d43..72f1e87572 100644 --- a/packages/compartment-mapper/test/policy.test.js +++ b/packages/compartment-mapper/test/policy.test.js @@ -5,6 +5,7 @@ import { moduleify, scaffold, sanitizePaths } from './scaffold.js'; function combineAssertions(...assertionFunctions) { return async (...args) => { + await null; for (const assertion of assertionFunctions) { // eslint-disable-next-line no-await-in-loop await assertion(...args); diff --git a/packages/compartment-mapper/test/scaffold.js b/packages/compartment-mapper/test/scaffold.js index bc4fe9dd9f..7876649d46 100644 --- a/packages/compartment-mapper/test/scaffold.js +++ b/packages/compartment-mapper/test/scaffold.js @@ -62,6 +62,7 @@ const builtinLocation = new URL( // application package. export async function setup() { + await null; if (modules === undefined) { const utility = await loadLocation(readPowers, builtinLocation); const { namespace } = await utility.import({ globals }); @@ -98,6 +99,7 @@ export function scaffold( testFunc = testFunc.failing || testFunc; } return testFunc(title, async t => { + await null; const compartmentInstrumentation = compartmentInstrumentationFactory(); let namespace; try { diff --git a/packages/compartment-mapper/test/snapshots/error-handling.test.js.md b/packages/compartment-mapper/test/snapshots/error-handling.test.js.md index 500b959374..9b368bdb31 100644 --- a/packages/compartment-mapper/test/snapshots/error-handling.test.js.md +++ b/packages/compartment-mapper/test/snapshots/error-handling.test.js.md @@ -84,7 +84,11 @@ Generated by [AVA](https://avajs.dev). `Error: Cannot find external module "missing" in package file://.../compartment-mapper/test/fixtures-error-handling/node_modules/cjs/␊ at importHook (file://.../compartment-mapper/src/import-hook.js:…)␊ - at async asyncTrampoline (file://.../ses/src/module-load.js:…)` + at async asyncTrampoline (file://.../ses/src/module-load.js:…)␊ + at async drainQueue (file://.../ses/src/module-load.js:…)␊ + at async load (file://.../ses/src/module-load.js:…)␊ + at async file://.../compartment-mapper/test/scaffold.js:…␊ + at async file://.../compartment-mapper/test/scaffold.js:…` ## fixtures-error-handling / cjs / importLocation @@ -92,7 +96,11 @@ Generated by [AVA](https://avajs.dev). `Error: Cannot find external module "missing" in package file://.../compartment-mapper/test/fixtures-error-handling/node_modules/cjs/␊ at importHook (file://.../compartment-mapper/src/import-hook.js:…)␊ - at async asyncTrampoline (file://.../ses/src/module-load.js:…)` + at async asyncTrampoline (file://.../ses/src/module-load.js:…)␊ + at async drainQueue (file://.../ses/src/module-load.js:…)␊ + at async load (file://.../ses/src/module-load.js:…)␊ + at async file://.../compartment-mapper/test/scaffold.js:…␊ + at async file://.../compartment-mapper/test/scaffold.js:…` ## fixtures-error-handling / cjs / makeArchive / parseArchive diff --git a/packages/compartment-mapper/test/snapshots/error-handling.test.js.snap b/packages/compartment-mapper/test/snapshots/error-handling.test.js.snap index 376992fd849cca90cf901c0843fdf788e7d8b19d..429e695ad84223dfaf3011f8e58541da9af78462 100644 GIT binary patch literal 799 zcmV+)1K|8YRzVy#!?_xQu}TnG_fZh2c9Dpyf((BQZ0HvgX@)7^20`txkLE$yRYa zdc5_#^`dn$&gigE>cSCnK_OUGYCx*OTo818mLiva&vbxG$S~+*OwftApe|#+@3TOq z8ETu7v|fr?Mw(eNmff&aCRIpZDtW`mq^twmuOXKqX)!ML5+N5wU>6QhN@XG9G6Wh~ z(h|kx%2I9&mvL=fce$*m003ygCRz>m<5*LSw#pW4PfcXVFrx!j#d<~d{GRFlKKr#Z zktj2|WDJ_I3>Mjt2{4M3mVk7wRdaAd)0Qv+i>HBJSJn0v`XJ&R+E^qzd{kK+Ixaqnk`uxMux{|k_)5Uz5GAW zT_1wSt0M?QZWBPrG(~*mfOJ4QAn)N!9BOW-h%Bmk^O^X)hTy;<=n#A;2u}O_KVf@s zNw%wREl0Pb+tI!GbkFJ11wGT;rF&VU`C03NQvKOQ zD(@#6(@Y62X+@Yca``Eze8u>O*fE*Yo~u08*q(DPb1u8ZH%R5OrTTJt&2dqClN|T) zv`2yUX+%M8X$jZOJBVhfU8y>k#-a?ag-%WSww&mL8qU<28hBOXVCpZvs)(kqIoAti zq%6M|^o(Z`)D(I&DpNGn<(O;P8K8je@{ShvP%1f2Rc_w={jspu;Q&RBH)Rp~>7_b_j%CNPV|iUH d&*==#WVxv`=xBB{JDTsC=0A0$0p7VM002RAgG&Ga literal 787 zcmV+u1MK`kRzV5SFhROOz_Nq6ytm%tCrC4SnT{AX~ zTDbCB;U9|#00000000B+n9Xj}Koo`BMhJ-=utvIM)k?7~wo!#tRjrD|&!!tz=yrS^ zPcoh{Gvoa1V8M=;C<`8pCqcHGVz+7Rw517Xvapn7=FH5w=d+W09-RrrM&|nuvfK)q z_98yDnI_|r)=GOZ%204QfB?uO5P(n^zEun@SCSivsfm>}U(dr3Eq>hTcD5dG<*)5W zTTgeM@0`w3I?9#$aEx3~2v!vukf<;d1YJK!kV}7Py1*r*$VNCI=tf*nKL~u^512|) z)HWe$y#&*gbYRKY;D)URQib%Xls5sHBTFmmZM94)xu@8qRrLqul83Ii$ zX^G-;X9+ik%Ry~l_qnYn003yg##&7d1_Mn4w540HTUp4E35;ezIoHeG^M|JY>&wr* zxkTaUigVD+Bx`dZ!!U}Jm{yb`aQ`C5pDs5fZT-fd&wtiFC5**QiW-%WV1dyUO z^S9T7*Xh-Q_oCy1x8cDH`GAZ))+%|2X-#6m`Eo@pYwrneX|ZGx7#W_Ri7$e3|MGu9 zcYO$++#W%ga2o?cswv`A2c!ei0r>#W#EIs%LS$aeo1cl_Y6y-Uf)2rd1;J|0{}Zdwl)tID8a7k@pYSE-Boo;GUIj>uLz2x_3>GeuInylt~)Y&B8Kb#GTS)ZoFGD|CX zzwD;8NbQR2TpEj#U7K22^i8qQdo@|8QyF+wek5b85qB8UP&xd)uj>af5yvaozkw+IJ<_qlgs%o`0S1)sU zs8kmR+pq$+8r`DV)5LOPv&WI`$aZ9}i|ody^h#YL$FgJDvAiypmvo61vfR`qax^=d R9nB9-^KXZ0n6kws008I=e^meg diff --git a/packages/compartment-mapper/test/stack.test.js b/packages/compartment-mapper/test/stack.test.js index 6e98d4aef2..348061568d 100644 --- a/packages/compartment-mapper/test/stack.test.js +++ b/packages/compartment-mapper/test/stack.test.js @@ -41,6 +41,7 @@ test('archive stack trace source', async t => { // Whereas, we expect the same program executed directly from local files to // have a fully qualified file URL in the stack trace. test('disk stack trace source', async t => { + await null; let error; try { await importLocation(readPowers, fixtureLocation); diff --git a/packages/daemon/index.js b/packages/daemon/index.js index 8158e4be55..f6adadb885 100644 --- a/packages/daemon/index.js +++ b/packages/daemon/index.js @@ -144,6 +144,7 @@ const enoentOk = error => { }; export const clean = async (config = defaultConfig) => { + await null; if (process.platform !== 'win32') { await removePath(config.sockPath).catch(enoentOk); } diff --git a/packages/daemon/src/daemon-node-powers.js b/packages/daemon/src/daemon-node-powers.js index 389a920df5..d9b609c3bf 100644 --- a/packages/daemon/src/daemon-node-powers.js +++ b/packages/daemon/src/daemon-node-powers.js @@ -367,7 +367,8 @@ export const makeDaemonicPersistencePowers = ( return filePowers.readFileText(storagePath); }; const json = async () => { - return JSON.parse(await text()); + const jsonSrc = await text(); + return JSON.parse(jsonSrc); }; return harden({ sha512: () => sha512, diff --git a/packages/daemon/src/serve-private-port-http.js b/packages/daemon/src/serve-private-port-http.js index f7ebb20a1a..f95d0a4aaf 100644 --- a/packages/daemon/src/serve-private-port-http.js +++ b/packages/daemon/src/serve-private-port-http.js @@ -18,6 +18,7 @@ export const servePrivatePortHttp = ( const connectionClosedPromises = new Set(); const respond = async request => { + await null; if (request.method === 'GET') { if (request.url === '/') { return { diff --git a/packages/daemon/src/web-server-node-powers.js b/packages/daemon/src/web-server-node-powers.js index 98e04cfcc9..370a1ff78b 100644 --- a/packages/daemon/src/web-server-node-powers.js +++ b/packages/daemon/src/web-server-node-powers.js @@ -79,6 +79,7 @@ export const makeHttpPowers = ({ http, ws }) => { server.on('request', (req, res) => { (async () => { + await null; if (req.method === undefined || req.url === undefined) { return; } diff --git a/packages/daemon/src/web-server-node.js b/packages/daemon/src/web-server-node.js index dea9b4cec3..b01690e69b 100644 --- a/packages/daemon/src/web-server-node.js +++ b/packages/daemon/src/web-server-node.js @@ -110,6 +110,7 @@ export const make = async (_powers, context) => { } (async () => { + await null; const { reader: frameReader, writer: frameWriter, @@ -137,7 +138,6 @@ export const make = async (_powers, context) => { // TODO set up heart monitor E.sendOnly(webletBootstrap).ping(); - // eslint-disable-next-line no-use-before-define E(webletBootstrap) .makeBundle( await E(/** @type {any} */ (webletBundle)).json(), diff --git a/packages/daemon/test/context-consumer.js b/packages/daemon/test/context-consumer.js index 916084b371..6d7bb1819d 100644 --- a/packages/daemon/test/context-consumer.js +++ b/packages/daemon/test/context-consumer.js @@ -11,6 +11,7 @@ export const ContextConsumerInterface = M.interface( export const make = async (_powers, context) => { return makeExo('Context consumer', ContextConsumerInterface, { async awaitCancellation() { + await null; try { await E(context).whenCancelled(); } catch { diff --git a/packages/eventual-send/test/e.test.js b/packages/eventual-send/test/e.test.js index a0f1c05c31..c972f9faae 100644 --- a/packages/eventual-send/test/e.test.js +++ b/packages/eventual-send/test/e.test.js @@ -39,6 +39,7 @@ test('E.when', async t => { }); test('E method calls', async t => { + await null; const x = { double(n) { return 2 * n; @@ -144,6 +145,7 @@ test('E method call undefined receiver', async t => { }); test('E shortcuts', async t => { + await null; const x = { name: 'buddy', val: 123, @@ -166,6 +168,7 @@ test('E shortcuts', async t => { }); test('E.get', async t => { + await null; const x = { name: 'buddy', val: 123, diff --git a/packages/eventual-send/test/eventual-send.test.js b/packages/eventual-send/test/eventual-send.test.js index 65088e247a..1771255d31 100644 --- a/packages/eventual-send/test/eventual-send.test.js +++ b/packages/eventual-send/test/eventual-send.test.js @@ -155,6 +155,7 @@ test('handlers are always async', async t => { }); test('new HandledPromise expected errors', async t => { + await null; const handler = { get(o, _key) { return o; @@ -259,6 +260,7 @@ test('new HandledPromise expected errors', async t => { }); test('new HandledPromise(executor, undefined)', async t => { + await null; const handledP = new HandledPromise((_, _2, resolveWithPresence) => { setTimeout(() => { const o = { @@ -308,6 +310,7 @@ test('handled promises are promises', t => { }); test('eventual send expected errors', async t => { + await null; t.is( await HandledPromise.get(true, 'toString'), true.toString, diff --git a/packages/eventual-send/test/thenable.test.js b/packages/eventual-send/test/thenable.test.js index 2d52914b19..2f194ada3f 100644 --- a/packages/eventual-send/test/thenable.test.js +++ b/packages/eventual-send/test/thenable.test.js @@ -20,6 +20,7 @@ test( ); const verifyThenAttack = async (t, resolve) => { + await null; const p = new Promise(_ => {}); let getHappened = false; let callHappened = false; diff --git a/packages/exo/test/exo-only-throwables.test.js b/packages/exo/test/exo-only-throwables.test.js index 95fea0017a..aaa8beacf1 100644 --- a/packages/exo/test/exo-only-throwables.test.js +++ b/packages/exo/test/exo-only-throwables.test.js @@ -24,6 +24,7 @@ const thrower = makeExo( ); test('exo only throwables', async t => { + await null; const e = makeError('test error', undefined, { sanitize: false, }); diff --git a/packages/exo/test/legacy-guard-tolerance.test.js b/packages/exo/test/legacy-guard-tolerance.test.js index ec15546b58..d77d3e1542 100644 --- a/packages/exo/test/legacy-guard-tolerance.test.js +++ b/packages/exo/test/legacy-guard-tolerance.test.js @@ -16,6 +16,7 @@ import { import { makeExo } from '../src/exo-makers.js'; test('legacy guard tolerance', async t => { + await null; const aag = M.await(88); const laag = makeLegacyAwaitArgGuard({ argGuard: 88, diff --git a/packages/far/test/e.test.js b/packages/far/test/e.test.js index f3c617a8f2..c224bf258a 100644 --- a/packages/far/test/e.test.js +++ b/packages/far/test/e.test.js @@ -40,6 +40,7 @@ test('E.when', async t => { }); test('E method calls', async t => { + await null; const x = { double(n) { return 2 * n; @@ -166,6 +167,7 @@ test('E method call undefined receiver', async t => { }); test('E shortcuts', async t => { + await null; const x = { name: 'buddy', val: 123, @@ -188,6 +190,7 @@ test('E shortcuts', async t => { }); test('E.get', async t => { + await null; const x = { name: 'buddy', val: 123, diff --git a/packages/import-bundle/src/index.js b/packages/import-bundle/src/index.js index 487f18a8af..81b42886c9 100644 --- a/packages/import-bundle/src/index.js +++ b/packages/import-bundle/src/index.js @@ -14,6 +14,7 @@ import { wrapInescapableCompartment } from './compartment-wrapper.js'; // object (with .default, and maybe other properties for named exports) export async function importBundle(bundle, options = {}, powers = {}) { + await null; const { bundleUrl = undefined, filePrefix, diff --git a/packages/import-bundle/test/import-bundle.test.js b/packages/import-bundle/test/import-bundle.test.js index 7599bf7f2e..7b37bcdb48 100644 --- a/packages/import-bundle/test/import-bundle.test.js +++ b/packages/import-bundle/test/import-bundle.test.js @@ -49,6 +49,7 @@ async function testBundle1(t, b1, mode, ew) { } test('test import', async t => { + await null; // nestedEvaluate requires a 'require' endowment, but doesn't call it function req(what) { console.log(`require(${what})`); diff --git a/packages/lp32/test/lp32.test.js b/packages/lp32/test/lp32.test.js index b3ba3d8ada..7219f6648a 100644 --- a/packages/lp32/test/lp32.test.js +++ b/packages/lp32/test/lp32.test.js @@ -176,6 +176,7 @@ test('round-trip varying messages', async t => { const [input, output] = makePipe(); const producer = (async () => { + await null; /** @type {import('@endo/stream').Writer} */ const w = makeLp32Writer(output); for (let i = 0; i < array.length; i += 1) { diff --git a/packages/netstring/test/netstring.test.js b/packages/netstring/test/netstring.test.js index 4a3309ee9f..4fd882990a 100644 --- a/packages/netstring/test/netstring.test.js +++ b/packages/netstring/test/netstring.test.js @@ -212,6 +212,7 @@ test('concurrent chunked writes', async t => { }); test('writer closes anywhere within chunk', async t => { + await null; for (let count = 0; count < 4; count += 1) { const pipe = makePipe(); const writer = makeNetstringWriter(pipe[1], { chunked: true }); @@ -243,6 +244,7 @@ const varyingMessages = async (t, opts) => { const [input, output] = makePipe(); const producer = (async () => { + await null; /** @type {import('@endo/stream').Writer} */ const w = makeNetstringWriter(output, opts); for (let i = 0; i < array.length; i += 1) { diff --git a/packages/ses/src/module-load.js b/packages/ses/src/module-load.js index 1f9af99fba..7388fab975 100644 --- a/packages/ses/src/module-load.js +++ b/packages/ses/src/module-load.js @@ -34,6 +34,7 @@ const { Fail, details: X, quote: q, note: annotateError } = assert; const noop = () => {}; async function asyncTrampoline(generatorFunc, args, errorWrapper) { + await null; const iterator = generatorFunc(...args); let result = generatorNext(iterator); while (!result.done) { @@ -349,6 +350,7 @@ function asyncJobQueue() { * @returns {Promise>} */ const drainQueue = async () => { + await null; for (const job of pendingJobs) { // eslint-disable-next-line no-await-in-loop await job; diff --git a/packages/ses/test/anticipate-async-iterator-helpers-shimmed.test.js b/packages/ses/test/anticipate-async-iterator-helpers-shimmed.test.js index d98c0b5d0f..2fd787db4d 100644 --- a/packages/ses/test/anticipate-async-iterator-helpers-shimmed.test.js +++ b/packages/ses/test/anticipate-async-iterator-helpers-shimmed.test.js @@ -7,6 +7,7 @@ import './lockdown-safe.js'; import test from 'ava'; test('shimmed async-iterator helpers', async t => { + await null; t.deepEqual( await (async function* g(i) { // eslint-disable-next-line no-plusplus diff --git a/packages/ses/test/error/aggregate-error.test.js b/packages/ses/test/error/aggregate-error.test.js index 5c0b0b2466..82f397799c 100644 --- a/packages/ses/test/error/aggregate-error.test.js +++ b/packages/ses/test/error/aggregate-error.test.js @@ -32,6 +32,7 @@ test('aggregate error', t => { }); test('Promise.any aggregate error', async t => { + await null; if (typeof AggregateError === 'undefined') { t.pass('skip test on platforms prior to AggregateError'); return; diff --git a/packages/ses/test/import-gauntlet.test.js b/packages/ses/test/import-gauntlet.test.js index 776b2a3b2b..0135fd546e 100644 --- a/packages/ses/test/import-gauntlet.test.js +++ b/packages/ses/test/import-gauntlet.test.js @@ -394,6 +394,7 @@ test('importHook returning a ModuleInstance with a precompiled functor', async t { resolveHook: resolveNode, importHook: async moduleSpecifier => { + await null; if (moduleSpecifier === './precompiled.js') { const baseRecord = await importHook(moduleSpecifier); return { diff --git a/packages/ses/test/import-stack-traces.test.js b/packages/ses/test/import-stack-traces.test.js index 466af54cb6..54efaaca80 100644 --- a/packages/ses/test/import-stack-traces.test.js +++ b/packages/ses/test/import-stack-traces.test.js @@ -3,6 +3,7 @@ import '../index.js'; import { resolveNode, makeNodeImporter } from './node.js'; test('preserve file names in stack traces', async t => { + await null; if (Error().stack != null) { t.plan(1); } else { diff --git a/packages/ses/test/import.test.js b/packages/ses/test/import.test.js index 7f623e9913..29a78e78aa 100644 --- a/packages/ses/test/import.test.js +++ b/packages/ses/test/import.test.js @@ -439,6 +439,7 @@ test('module alias', async t => { const wrappedImportHook = makeImportHook('https://example.com'); const importHook = async specifier => { + await null; const candidates = [specifier, `${specifier}.js`, `${specifier}/index.js`]; for (const candidate of candidates) { // eslint-disable-next-line no-await-in-loop @@ -498,6 +499,7 @@ test('import reflexive module alias', async t => { const wrappedImportHook = makeImportHook('https://example.com'); const importHook = async specifier => { + await null; const candidates = [specifier, `${specifier}.js`, `${specifier}/index.js`]; for (const candidate of candidates) { // eslint-disable-next-line no-await-in-loop diff --git a/packages/ses/test/tame-domains-after-lockdown.test.js b/packages/ses/test/tame-domains-after-lockdown.test.js index c7506e3a1e..3c28c579e2 100644 --- a/packages/ses/test/tame-domains-after-lockdown.test.js +++ b/packages/ses/test/tame-domains-after-lockdown.test.js @@ -4,6 +4,7 @@ import test from 'ava'; lockdown({ domainTaming: 'safe' }); test('import domains after lockdown', async t => { + await null; try { await import('domain'); t.fail('importing domain should throw'); diff --git a/packages/static-module-record/test/static-module-record.test.js b/packages/static-module-record/test/static-module-record.test.js index 3ade9f7fa3..1acb0c28c2 100644 --- a/packages/static-module-record/test/static-module-record.test.js +++ b/packages/static-module-record/test/static-module-record.test.js @@ -412,6 +412,7 @@ export function F(arg) { return arg; } }); test('hoist default async export named function', async t => { + await null; const { namespace } = initialize( t, `\ @@ -427,6 +428,7 @@ export default async function F(arg) { return arg; } }); test('hoist default async export anonymous function', async t => { + await null; const { namespace } = initialize( t, `\ diff --git a/packages/stream-node/test/stream-node.test.js b/packages/stream-node/test/stream-node.test.js index f5e716f3c1..f55b41607c 100644 --- a/packages/stream-node/test/stream-node.test.js +++ b/packages/stream-node/test/stream-node.test.js @@ -36,6 +36,7 @@ test('stream to and from Node.js reader/writer', async (/** @type {import('ava') }); const makeProducer = async () => { + await null; let chunkLength = 1; for (let i = 0; i < scratch.byteLength; ) { const j = i + chunkLength; @@ -100,6 +101,7 @@ test('stream write error (EPIPE due to exit)', async (/** @type {import('ava').E }); const makeProducer = async () => { + await null; let chunkLength = 1; for (let i = 0; i < scratch.byteLength; ) { const j = i + chunkLength; @@ -154,6 +156,7 @@ test('stream writer abort', async (/** @type {import('ava').ExecutionContext} */ }); const makeProducer = async () => { + await null; try { await writer.throw(Error('Abort')); } catch (error) { diff --git a/packages/stream/index.js b/packages/stream/index.js index 1c2de21662..155c19d483 100644 --- a/packages/stream/index.js +++ b/packages/stream/index.js @@ -156,6 +156,7 @@ export const prime = (generator, primer) => { /** @param {TWrite} value */ async next(value) { if (result === undefined) { + // eslint-disable-next-line @jessie.js/safe-await-separator result = await first; if (result.done) { return result; @@ -166,6 +167,7 @@ export const prime = (generator, primer) => { /** @param {TReturn} value */ async return(value) { if (result === undefined) { + // eslint-disable-next-line @jessie.js/safe-await-separator result = await first; if (result.done) { return result; @@ -176,6 +178,7 @@ export const prime = (generator, primer) => { /** @param {Error} error */ async throw(error) { if (result === undefined) { + // eslint-disable-next-line @jessie.js/safe-await-separator result = await first; if (result.done) { throw error; diff --git a/packages/stream/test/map.test.js b/packages/stream/test/map.test.js index 5cf75c1eed..76524d1f8f 100644 --- a/packages/stream/test/map.test.js +++ b/packages/stream/test/map.test.js @@ -19,6 +19,7 @@ test('map reader', async (/** @type {import('ava').Assertions} */ t) => { const order = ['', 'Hello, World!', '\x00', '😇 ']; const makeProducer = async () => { + await null; for (const value of order) { // eslint-disable-next-line no-await-in-loop const { done, value: actual } = await produceTo.next(value); @@ -31,6 +32,7 @@ test('map reader', async (/** @type {import('ava').Assertions} */ t) => { }; const makeConsumer = async () => { + await null; for (const expected of order) { // eslint-disable-next-line no-await-in-loop const { done, value: actual } = await consumeFrom.next(undefined); @@ -60,6 +62,7 @@ test('transcoding stream terminated with cause', async (/** @type {import('ava') }; const makeConsumer = async () => { + await null; try { for await (const _ of consumeFrom) { t.fail(); diff --git a/packages/stream/test/prime.test.js b/packages/stream/test/prime.test.js index b3a18b7432..388d4c15b4 100644 --- a/packages/stream/test/prime.test.js +++ b/packages/stream/test/prime.test.js @@ -27,6 +27,7 @@ test('prime single return', async (/** @type {import('ava').ExecutionContext} */ }); test('prime empty throw in', async (/** @type {import('ava').ExecutionContext} */ t) => { + await null; async function* empty() { return 'Z'; } @@ -58,6 +59,7 @@ test('prime single throw in', async (/** @type {import('ava').ExecutionContext} }); test('prime single throw', async (/** @type {import('ava').ExecutionContext} */ t) => { + await null; async function* empty() { throw Error('Abort'); } @@ -81,6 +83,7 @@ test('prime empty case', async (/** @type {import('ava').ExecutionContext} */ t) }); test('prime throw case', async (/** @type {import('ava').ExecutionContext} */ t) => { + await null; async function* temperamental() { throw Error('Abort'); } diff --git a/packages/stream/test/pump.test.js b/packages/stream/test/pump.test.js index 2693e2d23c..0b7173d9e2 100644 --- a/packages/stream/test/pump.test.js +++ b/packages/stream/test/pump.test.js @@ -256,6 +256,7 @@ test('pump iterator protocol target next throws', async (/** @type {import('ava' }); test('pump iterator protocol target return throws', async (/** @type {import('ava').ExecutionContext} */ t) => { + await null; const source = { /** @param {undefined} value */ async next(value) { diff --git a/packages/stream/test/stream.test.js b/packages/stream/test/stream.test.js index c4edacdab1..59bd0836f0 100644 --- a/packages/stream/test/stream.test.js +++ b/packages/stream/test/stream.test.js @@ -9,6 +9,7 @@ test('stream', async (/** @type {import('ava').Assertions} */ t) => { const order = [10, 20, 30]; const makeProducer = async () => { + await null; for (const expected of order) { // eslint-disable-next-line no-await-in-loop const { done, value: actual } = await produceTo.next(expected); @@ -21,6 +22,7 @@ test('stream', async (/** @type {import('ava').Assertions} */ t) => { }; const makeConsumer = async () => { + await null; for (const expected of order) { // eslint-disable-next-line no-await-in-loop const { done, value: actual } = await consumeFrom.next(expected); @@ -43,6 +45,7 @@ test('stream terminated with cause', async (/** @type {import('ava').Assertions} }; const makeConsumer = async () => { + await null; try { for await (const _ of consumeFrom) { t.fail();