fix(bundler): fix --compile with 8+ embedded files (#25859)

## Summary

Fixes #20821

When `bun build --compile` was used with 8 or more embedded files, the
compiled binary would silently fail to execute any code (exit code 0, no
output).

**Root cause:** Chunks were sorted alphabetically by their `entry_bits`
key bytes. For entry point 0, the key starts with bit 0 set (byte
pattern `0x01`), but for entry point 8, the key has bit 8 set in the
byte (pattern `0x00, 0x01`). Alphabetically, `0x00 < 0x01`, so entry
point 8's chunk sorted before entry point 0.

This caused the wrong entry point to be identified as the main entry,
resulting in asset wrapper code being executed instead of the user's
code.

**Fix:** Custom sort that ensures `entry_point_id=0` (the main entry
point) always sorts first, with remaining chunks sorted alphabetically
for determinism.

## Test plan

- Added regression test `compile/ManyEmbeddedFiles` that embeds 8 files
and verifies the main entry point runs correctly
- Verified manually with reproduction case from issue

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Dylan Conway
2026-01-06 15:05:01 -08:00
committed by GitHub
parent 46801ec926
commit 4c492c66b8
3 changed files with 46 additions and 2 deletions

View File

@@ -735,4 +735,24 @@ const server = serve({
.env(bunEnv)
.throws(true);
});
// When compiling with 8+ entry points, the main entry point should still run correctly.
test("compile with 8+ entry points runs main entry correctly", async () => {
const dir = tempDirWithFiles("compile-many-entries", {
"app.js": `console.log("IT WORKS");`,
"assets/file-1": "",
"assets/file-2": "",
"assets/file-3": "",
"assets/file-4": "",
"assets/file-5": "",
"assets/file-6": "",
"assets/file-7": "",
"assets/file-8": "",
});
await Bun.$`${bunExe()} build --compile app.js assets/* --outfile app`.cwd(dir).env(bunEnv).throws(true);
const result = await Bun.$`./app`.cwd(dir).env(bunEnv).nothrow();
expect(result.stdout.toString().trim()).toBe("IT WORKS");
});
});