diff --git a/src/bundler/linker_context/computeChunks.zig b/src/bundler/linker_context/computeChunks.zig index 15f825b601..82b19346d0 100644 --- a/src/bundler/linker_context/computeChunks.zig +++ b/src/bundler/linker_context/computeChunks.zig @@ -249,9 +249,29 @@ pub noinline fn computeChunks( var sorted_keys = try BabyList(string).initCapacity(temp_allocator, js_chunks.count()); - // JS Chunks sorted_keys.appendSliceAssumeCapacity(js_chunks.keys()); - sorted_keys.sortAsc(); + + // sort by entry_point_id to ensure the main entry point (id=0) comes first, + // then by key for determinism among the rest. + const ChunkSortContext = struct { + chunks: *const bun.StringArrayHashMap(Chunk), + + pub fn lessThan(ctx: @This(), a_key: string, b_key: string) bool { + const a_chunk = ctx.chunks.get(a_key) orelse return true; + const b_chunk = ctx.chunks.get(b_key) orelse return false; + const a_id = a_chunk.entry_point.entry_point_id; + const b_id = b_chunk.entry_point.entry_point_id; + + // Main entry point (id=0) always comes first + if (a_id == 0 and b_id != 0) return true; + if (b_id == 0 and a_id != 0) return false; + + // Otherwise sort alphabetically by key for determinism + return bun.strings.order(a_key, b_key) == .lt; + } + }; + + sorted_keys.sort(ChunkSortContext, .{ .chunks = &js_chunks }); var js_chunk_indices_with_css = try BabyList(u32).initCapacity(temp_allocator, js_chunks_with_css); for (sorted_keys.slice()) |key| { const chunk = js_chunks.get(key) orelse unreachable; diff --git a/src/collections/baby_list.zig b/src/collections/baby_list.zig index bac768a269..400ffdfe4b 100644 --- a/src/collections/baby_list.zig +++ b/src/collections/baby_list.zig @@ -349,6 +349,10 @@ pub fn BabyList(comptime Type: type) type { bun.strings.sortAsc(this.slice()); } + pub fn sort(this: *Self, comptime Context: type, context: Context) void { + std.sort.pdq(Type, this.slice(), context, Context.lessThan); + } + pub fn writableSlice( this: *Self, allocator: std.mem.Allocator, diff --git a/test/bundler/bundler_compile.test.ts b/test/bundler/bundler_compile.test.ts index 766e2a7fed..6be7076f73 100644 --- a/test/bundler/bundler_compile.test.ts +++ b/test/bundler/bundler_compile.test.ts @@ -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"); + }); });