From 5afebde3827f0de2b7f210bb69e17033ff699d8b Mon Sep 17 00:00:00 2001 From: Marcel Date: Tue, 12 May 2026 22:09:07 +0200 Subject: [PATCH] refactor(eslint): ban async vi.mock factories with dynamic import in body MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Generalise the no-restricted-syntax rule from the literal pdfjs-dist selector (added in #535) to also catch the underlying mechanism named in ADR-012 / #553: any `vi.mock(..., async () => { ... await import(...) ... })` produces a late birpc roundtrip during worker teardown. Selector: vi.mock CallExpression whose second argument is an ArrowFunctionExpression with async=true and whose subtree contains an AwaitExpression > ImportExpression. Both rules coexist — the literal pdfjs-dist rule still enforces the libLoader prop injection pattern (catches sync forms too); the new rule enforces the sync-factory invariant universally. Demonstrated by planting a synthetic offender locally and watching ESLint flag it with the new rule's message. Co-Authored-By: Claude Opus 4.7 (1M context) --- frontend/eslint.config.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/frontend/eslint.config.js b/frontend/eslint.config.js index a56c710b..88aa8a53 100644 --- a/frontend/eslint.config.js +++ b/frontend/eslint.config.js @@ -82,6 +82,17 @@ export default defineConfig( "CallExpression[callee.object.name='vi'][callee.property.name='mock'] > Literal[value=/^pdfjs-dist/]", message: "Banned: vi.mock('pdfjs-dist', factory) causes a birpc teardown race in browser-mode specs — see ADR 012. Use the libLoader prop injection pattern instead." + }, + { + // ADR 012 / #553. The named mechanism: an async vi.mock factory whose + // body performs `await import(...)` produces a late birpc roundtrip + // during worker teardown. The factory body must be synchronous; if + // you need to share state between the spec and the mock, use + // `vi.hoisted` (see DropZone.svelte.spec.ts). + selector: + "CallExpression[callee.object.name='vi'][callee.property.name='mock'][arguments.1.type='ArrowFunctionExpression'][arguments.1.async=true]:has(AwaitExpression > ImportExpression)", + message: + 'Banned: vi.mock(..., async () => { await import(...) }) causes a birpc teardown race in browser-mode specs — see ADR 012. Use a synchronous factory + vi.hoisted instead.' } ] }