Compare commits

...

4 Commits

Author SHA1 Message Date
Claude Bot
716f652681 ci: retrigger build with http.zig fix
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-09 20:47:53 +00:00
Claude Bot
6912f902f1 fix(http): access server_name through SharedPtr.get()
The SSLConfig is wrapped in a SharedPtr, so fields must be accessed
via .get() rather than directly on the shared pointer wrapper.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-09 20:46:53 +00:00
Claude Bot
f7dbebe144 ci: retry after transient Windows aarch64 download failure
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-09 20:37:10 +00:00
Claude Bot
36c610bfbb fix(compile): resolve workers created with new URL() and --format=esm
When `--format=esm` is used with `bun build --compile`, `import.meta.url`
resolves to a virtual bunfs path (e.g. `/$bunfs/root/app`). This means
`new Worker(new URL("./worker.ts", import.meta.url))` produces an absolute
bunfs path like `/$bunfs/root/worker.ts`. The worker resolver only tried
extension remapping (.ts -> .js) for relative paths (`./` or `../`), so it
failed to find the worker in the standalone module graph.

Extract extension remapping into a shared `tryExtensionRemap` helper and
also apply it to absolute bunfs paths, so workers created via the
`new URL(...)` pattern work correctly with `--format=esm`.

Closes #27936

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-09 20:37:10 +00:00
3 changed files with 109 additions and 31 deletions

View File

@@ -80,6 +80,46 @@ export fn WebWorker__updatePtr(worker: *WebWorker, ptr: *anyopaque) bool {
return true;
}
/// Try to remap file extensions to `.js` for standalone module graph lookup.
/// `base` is the full path to look up, `pathbuf` must contain the same bytes
/// (at least up to `base.len`). Returns the graph entry name on match.
fn tryExtensionRemap(graph: *const bun.StandaloneModuleGraph, base: []const u8, pathbuf: *bun.PathBuffer) ?[]const u8 {
const extname = std.fs.path.extension(base);
// foo -> foo.js
if (extname.len == 0) {
pathbuf[base.len..][0..3].* = ".js".*;
if (graph.find(pathbuf[0 .. base.len + 3])) |js_file| {
return js_file.name;
}
return null;
}
// foo.ts -> foo.js
if (bun.strings.eqlComptime(extname, ".ts")) {
pathbuf[base.len - 3 .. base.len][0..3].* = ".js".*;
if (graph.find(pathbuf[0..base.len])) |js_file| {
return js_file.name;
}
return null;
}
if (extname.len == 4) {
inline for (.{ ".tsx", ".jsx", ".mjs", ".mts", ".cts", ".cjs" }) |ext| {
if (bun.strings.eqlComptime(extname, ext)) {
pathbuf[base.len - ext.len ..][0..".js".len].* = ".js".*;
const as_js = pathbuf[0 .. base.len - ext.len + ".js".len];
if (graph.find(as_js)) |js_file| {
return js_file.name;
}
return null;
}
}
}
return null;
}
fn resolveEntryPointSpecifier(
parent: *jsc.VirtualMachine,
str: []const u8,
@@ -104,45 +144,33 @@ fn resolveEntryPointSpecifier(
// new Worker("./foo.cts") -> new Worker("./foo.js")
// new Worker("./foo.tsx") -> new Worker("./foo.js")
//
// When --format=esm is used, import.meta.url resolves to a
// bunfs path (e.g. /$bunfs/root/app), so
// new Worker(new URL("./worker.ts", import.meta.url))
// produces an absolute bunfs path like /$bunfs/root/worker.ts.
// We need to handle extension remapping for these paths too.
//
if (bun.strings.hasPrefixComptime(str, "./") or bun.strings.hasPrefixComptime(str, "../")) try_from_extension: {
var pathbuf: bun.PathBuffer = undefined;
var base = str;
base = bun.path.joinAbsStringBuf(bun.StandaloneModuleGraph.base_public_path_with_default_suffix, &pathbuf, &.{str}, .loose);
const extname = std.fs.path.extension(base);
// ./foo -> ./foo.js
if (extname.len == 0) {
pathbuf[base.len..][0..3].* = ".js".*;
if (graph.find(pathbuf[0 .. base.len + 3])) |js_file| {
return js_file.name;
}
break :try_from_extension;
if (tryExtensionRemap(graph, base, &pathbuf)) |js_file| {
return js_file;
}
// ./foo.ts -> ./foo.js
if (bun.strings.eqlComptime(extname, ".ts")) {
pathbuf[base.len - 3 .. base.len][0..3].* = ".js".*;
if (graph.find(pathbuf[0..base.len])) |js_file| {
return js_file.name;
}
break :try_from_extension;
break :try_from_extension;
} else if (bun.StandaloneModuleGraph.isBunStandaloneFilePath(str)) try_bunfs_extension: {
// The specifier is already an absolute bunfs path (e.g. from
// new URL("./worker.ts", import.meta.url) with --format=esm).
// Try extension remapping directly on this path.
var pathbuf: bun.PathBuffer = undefined;
@memcpy(pathbuf[0..str.len], str);
if (tryExtensionRemap(graph, str, &pathbuf)) |js_file| {
return js_file;
}
if (extname.len == 4) {
inline for (.{ ".tsx", ".jsx", ".mjs", ".mts", ".cts", ".cjs" }) |ext| {
if (bun.strings.eqlComptime(extname, ext)) {
pathbuf[base.len - ext.len ..][0..".js".len].* = ".js".*;
const as_js = pathbuf[0 .. base.len - ext.len + ".js".len];
if (graph.find(as_js)) |js_file| {
return js_file.name;
}
break :try_from_extension;
}
}
}
break :try_bunfs_extension;
}
}

View File

@@ -46,7 +46,7 @@ fn getTlsHostname(client: *const HTTPClient, allowProxyUrl: bool) []const u8 {
}
// Prefer the explicit TLS server_name (e.g. from Node.js servername option)
if (client.tls_props) |props| {
if (props.server_name) |sn| {
if (props.get().server_name) |sn| {
const sn_slice = bun.sliceTo(sn, 0);
if (sn_slice.len > 0) return sn_slice;
}

View File

@@ -219,6 +219,56 @@ describe("bundler", () => {
setCwd: true,
},
});
// https://github.com/oven-sh/bun/issues/27936
itBundled("compile/WorkerNewURLImportMetaESM", {
backend: "cli",
compile: true,
format: "esm",
files: {
"/entry.ts": /* js */ `
import {rmSync} from 'fs';
// Verify we're not just importing from the filesystem
rmSync("./worker.ts", {force: true});
console.log("Hello, world!");
new Worker(new URL("./worker.ts", import.meta.url));
`,
"/worker.ts": /* js */ `
console.log("Worker loaded!");
`.trim(),
},
entryPointsRaw: ["./entry.ts", "./worker.ts"],
outfile: "dist/out",
run: {
stdout: "Hello, world!\nWorker loaded!\n",
file: "dist/out",
setCwd: true,
},
});
itBundled("compile/WorkerNewURLImportMetaBytecodeESM", {
backend: "cli",
compile: true,
bytecode: true,
format: "esm",
files: {
"/entry.ts": /* js */ `
import {rmSync} from 'fs';
// Verify we're not just importing from the filesystem
rmSync("./worker.ts", {force: true});
console.log("Hello, world!");
new Worker(new URL("./worker.ts", import.meta.url));
`,
"/worker.ts": /* js */ `
console.log("Worker loaded!");
`.trim(),
},
entryPointsRaw: ["./entry.ts", "./worker.ts"],
outfile: "dist/out",
run: {
stdout: "Hello, world!\nWorker loaded!\n",
file: "dist/out",
setCwd: true,
},
});
// https://github.com/oven-sh/bun/issues/8697
itBundled("compile/EmbeddedFileOutfile", {
compile: true,