Skip to content

Commit b5bbc4a

Browse files
committed
fix(redis-worker): guard resilient require shim
1 parent be87bcb commit b5bbc4a

4 files changed

Lines changed: 66 additions & 5 deletions

File tree

packages/redis-worker/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
"@internal/tracing": "workspace:*",
3838
"@types/lodash.omit": "^4.5.7",
3939
"@types/seedrandom": "^3.0.8",
40+
"esbuild": "^0.23.0",
4041
"rimraf": "6.0.1",
4142
"tsdown": "0.22.10",
4243
"tsx": "4.17.0"
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { build } from "esbuild";
2+
import { mkdtempSync, readFileSync, rmSync } from "node:fs";
3+
import { tmpdir } from "node:os";
4+
import { join } from "node:path";
5+
import { createRequire } from "node:module";
6+
import { fileURLToPath } from "node:url";
7+
import { spawnSync } from "node:child_process";
8+
import { afterAll, expect, test } from "vitest";
9+
10+
const packageDir = fileURLToPath(new URL("../", import.meta.url));
11+
const tempDir = mkdtempSync(join(tmpdir(), "redis-worker-build-output-"));
12+
13+
const require = createRequire(import.meta.url);
14+
15+
afterAll(() => {
16+
rmSync(tempDir, { recursive: true, force: true });
17+
});
18+
19+
test("the ESM output can be rebundled and loaded as CommonJS", async () => {
20+
const buildResult = spawnSync("pnpm", ["exec", "tsdown"], {
21+
cwd: packageDir,
22+
encoding: "utf8",
23+
});
24+
const buildOutput = [buildResult.stdout, buildResult.stderr].filter(Boolean).join("\n");
25+
26+
expect(buildResult.error, buildOutput).toBeUndefined();
27+
expect(buildResult.status, buildOutput).toBe(0);
28+
29+
const esmPath = join(packageDir, "dist/index.js");
30+
const esmOutput = readFileSync(esmPath, "utf8");
31+
expect(esmOutput).not.toMatch(/\b[\w$]*createRequire[\w$]*\s*\(\s*import\.meta\.url\s*\)/);
32+
33+
const cjsPath = join(tempDir, "index.cjs");
34+
await build({
35+
entryPoints: [esmPath],
36+
outfile: cjsPath,
37+
bundle: true,
38+
format: "cjs",
39+
platform: "node",
40+
logLevel: "silent",
41+
});
42+
43+
expect(() => require(cjsPath)).not.toThrow();
44+
}, 30_000);

packages/redis-worker/tsdown.config.ts

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,15 +60,28 @@ export default defineConfig({
6060
{
6161
name: "resilient-create-require",
6262
renderChunk(code: string) {
63-
if (!code.includes("createRequire(import.meta.url)")) return null;
63+
const unsafeCreateRequire = /(\b[\w$]*createRequire[\w$]*\s*\()\s*import\.meta\.url\s*\)/g;
64+
const patched = code.replace(
65+
unsafeCreateRequire,
66+
"$1import.meta.url || process.cwd() + '/index.js')"
67+
);
68+
69+
if (patched === code) return null;
70+
6471
return {
65-
code: code.replaceAll(
66-
"createRequire(import.meta.url)",
67-
"createRequire(import.meta.url || process.cwd() + '/index.js')"
68-
),
72+
code: patched,
6973
map: null,
7074
};
7175
},
76+
generateBundle(_options, bundle) {
77+
const unsafeCreateRequire = /\b[\w$]*createRequire[\w$]*\s*\(\s*import\.meta\.url\s*\)/;
78+
79+
for (const output of Object.values(bundle)) {
80+
if (output.type === "chunk" && unsafeCreateRequire.test(output.code)) {
81+
throw new Error(`Unsafe createRequire helper remained in ${output.fileName}`);
82+
}
83+
}
84+
},
7285
},
7386
],
7487
});

pnpm-lock.yaml

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)