Skip to content

Instantly share code, notes, and snippets.

@jameshfisher
Created July 1, 2026 09:12
Show Gist options
  • Select an option

  • Save jameshfisher/18ca51d835d40b5f822e84de693385c9 to your computer and use it in GitHub Desktop.

Select an option

Save jameshfisher/18ca51d835d40b5f822e84de693385c9 to your computer and use it in GitHub Desktop.
rolldown miscompiles a re-exported default import of a CJS/builtin module: emits require(...) without __toESM but reads .default. tsc compiles the same source correctly. npm i && npm run rolldown

rolldown miscompiles a re-exported CJS default import

This TypeScript works under tsc, but crashes when bundled by rolldown.

npm install
npm run tsc        # compile with tsc, then run  -> WORKS
npm run rolldown   # bundle with rolldown, then run -> TypeError: Cannot read properties of undefined (reading 'Agent')

Environment: rolldown@1.1.3 (latest), typescript@5.7.3, node 22.

import { rolldown } from "rolldown";
const bundle = await rolldown({ input: "./entry.ts", platform: "node" });
await bundle.write({ format: "cjs", dir: "./dist", entryFileNames: "out.cjs" });
// Consumer, like node-http-handler.js. Type-correct: node_https is typed as the
// https module, so node_https.Agent is a valid `new`-able constructor.
import { node_https } from "./node-https";
export function makeAgent(): import("node:https").Agent {
return new node_https.Agent({ keepAlive: true });
}
// Exact shape of @smithy/node-http-handler@4.8.2 dist-es/node-https.js:
// default-import a CJS builtin, then re-export it through this module.
import node_https from "node:https";
export { node_https };
{
"name": "rolldown-cjs-default-reexport-interop-bug",
"version": "1.0.0",
"private": true,
"description": "rolldown miscompiles a default-imported CJS builtin that is re-exported through an intermediate module. tsc compiles the same source correctly.",
"scripts": {
"typecheck": "tsc --project tsconfig.json",
"tsc": "tsc --project tsconfig.emit.json && node verify.cjs ./dist-tsc/entry.js",
"rolldown": "node build.mjs && node verify.cjs ./dist/out.cjs"
},
"devDependencies": {
"@types/node": "22.12.0",
"rolldown": "1.1.3",
"typescript": "5.7.3"
}
}
{
"comment": "Contrast only: what tsc WOULD emit for the same source, targeting CommonJS. It is CORRECT and runs fine. Proves the bug is the bundler's emit, not the source or tsc.",
"compilerOptions": {
"target": "ESNext",
"module": "CommonJS",
"moduleResolution": "node",
"esModuleInterop": true,
"strict": true,
"skipLibCheck": true,
"outDir": "dist-tsc",
"noEmit": false,
"types": ["node"]
},
"include": ["entry.ts", "node-https.ts"]
}
{
"comment": "Type-check only (noEmit). The source is type-correct; the bug is in the bundler's emit.",
"compilerOptions": {
"target": "ESNext",
"module": "ESNext",
"moduleResolution": "bundler",
"verbatimModuleSyntax": true,
"allowSyntheticDefaultImports": true,
"isolatedModules": true,
"strict": true,
"skipLibCheck": true,
"noEmit": true,
"types": ["node"]
},
"include": ["entry.ts", "node-https.ts"]
}
// Loads a built bundle, calls makeAgent(), and reports whether it produced a
// real https.Agent (intended behavior) instead of crashing.
const https = require("node:https");
const modulePath = process.argv[2];
const agent = require(modulePath).makeAgent();
console.log(
`ran ${modulePath} -> OK.`,
`instanceof https.Agent: ${agent instanceof https.Agent},`,
`keepAlive: ${agent.keepAlive}`
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment