Fix worker bundling path resolution

The issue was that worker unique keys were using import_record_index
instead of source_index, preventing correct chunk mapping.

Changes:
- js_printer.zig: Use source_index from import record for worker unique keys
- LinkerContext.zig: Validate worker indices against file count (not chunk count)
- Chunk.zig: Use entry_point_chunk_indices mapping for worker path resolution

This allows the bundler to correctly map from source files to their
corresponding worker chunks, just like dynamic imports and SCBs.

Test results:
- bundler_worker_verify.test.ts:  PASS
- bundler_worker_basic.test.ts:  PASS
- bundler_worker_simple.test.ts:  PASS

Workers now correctly resolve to their chunk paths (e.g., ./worker-axd28k5g.js)
instead of incorrectly pointing to the entry file.
This commit is contained in:
Claude Bot
2025-10-05 14:29:02 +00:00
parent b2344889bb
commit 84fa417e8f
3 changed files with 10 additions and 6 deletions

View File

@@ -215,7 +215,7 @@ pub const Chunk = struct {
},
.chunk => chunks[index].final_rel_path,
.scb => chunks[entry_point_chunks_for_scb[index]].final_rel_path,
.worker => chunks[index].final_rel_path,
.worker => chunks[entry_point_chunks_for_scb[index]].final_rel_path,
.html_import => {
count += std.fmt.count("{}", .{HTMLImportManifest.formatEscapedJSON(.{
.index = index,
@@ -303,7 +303,7 @@ pub const Chunk = struct {
break :brk piece_chunk.final_rel_path;
},
.worker => brk: {
const piece_chunk = chunks[index];
const piece_chunk = chunks[entry_point_chunks_for_scb[index]];
if (enable_source_map_shifts) {
shift.before.advance(piece_chunk.unique_key);

View File

@@ -2625,7 +2625,7 @@ pub const LinkerContext = struct {
bun.Output.debugWarn("Invalid output piece boundary", .{});
break;
},
.worker => if (index >= count) {
.worker => if (index >= c.graph.files.len) {
if (bun.Environment.isDebug)
bun.Output.debugWarn("Invalid output piece boundary", .{});
break;

View File

@@ -2207,18 +2207,22 @@ fn NewPrinter(
p.printSpaceBeforeIdentifier();
p.addSourceMapping(expr.loc);
p.print("new Worker(");
// Generate a unique key for the worker instead of the direct path
// This will be resolved to the actual worker chunk path later
if (p.options.unique_key_prefix.len > 0) {
const unique_key = std.fmt.allocPrint(p.options.allocator, "{s}W{d:0>8}", .{ p.options.unique_key_prefix, e.import_record_index }) catch unreachable;
const import_record = p.importRecord(e.import_record_index);
// Use the source_index from the import record, not the import_record_index
// This allows the linker to map from source_index to chunk_index using entry_point_chunk_indices
const source_index = import_record.source_index.get();
const unique_key = std.fmt.allocPrint(p.options.allocator, "{s}W{d:0>8}", .{ p.options.unique_key_prefix, source_index }) catch unreachable;
defer p.options.allocator.free(unique_key);
p.printStringLiteralUTF8(unique_key, true);
} else {
// Fallback to direct path if unique_key_prefix is not available
p.printStringLiteralUTF8(p.importRecord(e.import_record_index).path.text, true);
}
// Print options if present and not missing
if (e.options.data != .e_missing) {
p.print(",");