1import Module from "node:module";
2
3// The harness runs vite in-process inside the playwright worker.
4// `@tailwindcss/node`'s ESM build registers an async module-customization
5// loader (`esm-cache.loader.mjs`) at import time; on node >= 24 that loader
6// combined with playwright's own sync transform hooks makes subsequent
7// `require()` calls from ESM-imported CJS modules fail with `Expected a
8// string ... for the "source" from the "load" hook but got undefined/null`,
9// killing every in-process vite build/dev server. Tailwind skips the
10// registration under bun (it is purely a config-import cache), so dropping
11// it is safe. Imported for its side effect from Playwright.ts so every
12// playwright worker process is guarded before vite loads tailwind.
13let installed = false;
14
15export const installTailwindNodeCompat = (): void => {
16 if (installed) return;
17 installed = true;
18 const originalRegister = Module.register.bind(Module);
19 Module.register = ((specifier: unknown, ...rest: Array<never>) => {
20 if (String(specifier).includes("esm-cache")) return;
21 return (originalRegister as (...args: Array<unknown>) => unknown)(
22 specifier,
23 ...rest,
24 );
25 }) as typeof Module.register;
26 // Propagate the patched `register` into the `node:module` ESM namespace —
27 // tailwind calls it through an ESM named-import binding, which snapshots
28 // builtin exports at namespace creation.
29 Module.syncBuiltinESMExports();
30};