Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
f6ae01c
compile: resolve every spelling of an embedded Worker entry point aga…
dylan-conway Aug 27, 2026
dceb99b
bound the .js rewrite by the buffer; test: module imports, plus an ab…
dylan-conway Aug 27, 2026
54a781a
resolve embedded modules in the resolver, not in web_worker; give emb…
dylan-conway Aug 27, 2026
24a04e6
[autofix.ci] apply automated fixes
autofix-ci[bot] Aug 27, 2026
e9f6c8a
clippy: redundant closure
dylan-conway Aug 27, 2026
6e354cf
Merge branch 'claude/compile-worker-resolution' of github.com:oven-sh…
dylan-conway Aug 27, 2026
aefd861
only ask the resolver about the embedded graph for relative or embedd…
dylan-conway Aug 27, 2026
352c71f
StandaloneModuleGraph::find returns the graph's 'static name (no inte…
dylan-conway Aug 27, 2026
1cf6ecc
[autofix.ci] apply automated fixes
autofix-ci[bot] Aug 27, 2026
7da4862
resolve_embedded(): the one rule for mapping a specifier to an embedd…
dylan-conway Aug 27, 2026
07b5998
[autofix.ci] apply automated fixes
autofix-ci[bot] Aug 27, 2026
8527399
review: StandaloneModuleGraph::resolve() as a provided trait method (…
dylan-conway Aug 27, 2026
b70170f
Merge branch 'claude/compile-worker-resolution' of github.com:oven-sh…
dylan-conway Aug 27, 2026
4f667dc
[autofix.ci] apply automated fixes
autofix-ci[bot] Aug 27, 2026
8b180a7
tests: nested dirs, precedence vs the cwd, canonical resolved names, …
dylan-conway Aug 27, 2026
56b1fa2
[autofix.ci] apply automated fixes
autofix-ci[bot] Aug 27, 2026
58f54a5
test: Buffer.alloc for the long specifier
dylan-conway Aug 27, 2026
628cc87
a specifier with a trailing separator names no embedded module (the W…
dylan-conway Aug 27, 2026
db817ad
test: onerror on every awaited Worker
dylan-conway Aug 27, 2026
16597a1
[autofix.ci] apply automated fixes
autofix-ci[bot] Aug 27, 2026
33e07d2
Merge remote-tracking branch 'origin/main' into claude/compile-worker…
dylan-conway Aug 27, 2026
423537c
spell the trailing-separator check without an index
dylan-conway Aug 27, 2026
0a9dbd1
[autofix.ci] apply automated fixes
autofix-ci[bot] Aug 27, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 34 additions & 64 deletions src/jsc/web_worker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1290,71 +1290,41 @@ unsafe fn resolve_entry_point_specifier<'s>(
) -> Option<&'s [u8]> {
// SAFETY: per fn contract; read-only field.
if let Some(graph) = unsafe { (*parent).standalone_module_graph } {
if graph.find(str).is_some() {
return Some(str);
}

// Since `bun build --compile` renames files to `.js` by default, we
// need to do the reverse of our file extension mapping.
//
// new Worker("./foo") -> new Worker("./foo.js")
// new Worker("./foo.ts") -> new Worker("./foo.js")
// new Worker("./foo.jsx") -> new Worker("./foo.js")
// new Worker("./foo.mjs") -> new Worker("./foo.js")
// new Worker("./foo.mts") -> new Worker("./foo.js")
// new Worker("./foo.cjs") -> new Worker("./foo.js")
// new Worker("./foo.cts") -> new Worker("./foo.js")
// new Worker("./foo.tsx") -> new Worker("./foo.js")
// A relative specifier is relative to the embedded root; an absolute one (spelled out, or from
// `new URL("./w.js", import.meta.url)`) may arrive in the platform's path syntax. Either way the
// graph's own name for the file is what the module loader recognizes, so return that. Entry
// points are embedded under a `.js` name whatever their source extension was, so also try the
// name `bun build --compile` would have given the file:
//
if str.starts_with(b"./") || str.starts_with(b"../") {
'try_from_extension: {
let mut pathbuf = bun_paths::path_buffer_pool::get();
let base_path = graph.base_public_path_with_default_suffix();
let base = bun_paths::resolve_path::join_abs_string_buf::<bun_paths::platform::Loose>(
base_path,
&mut pathbuf[..],
&[str],
);
let base_len = base.len();
let extname_len = bun_paths::extension(base).len();
// `extname` cannot be held as a sub-slice of `pathbuf` while
// writing into `pathbuf` — compare
// by re-slicing after dropping the mutable borrow.
let extname = &pathbuf[base_len - extname_len..base_len];

// ./foo -> ./foo.js
if extname.is_empty() {
pathbuf[base_len..base_len + 3].copy_from_slice(b".js");
if let Some(js_file) = graph.find(&pathbuf[0..base_len + 3]) {
return Some(js_file);
}
break 'try_from_extension;
}

// ./foo.ts -> ./foo.js
if extname == b".ts" {
pathbuf[base_len - 3..base_len].copy_from_slice(b".js");
if let Some(js_file) = graph.find(&pathbuf[0..base_len]) {
return Some(js_file);
}
break 'try_from_extension;
}

if extname.len() == 4 {
const EXTS: [&[u8]; 6] = [b".tsx", b".jsx", b".mjs", b".mts", b".cts", b".cjs"];
for ext in EXTS {
if extname == ext {
let js_len = b".js".len();
pathbuf[base_len - ext.len()..base_len - ext.len() + js_len]
.copy_from_slice(b".js");
let as_js = &pathbuf[0..base_len - ext.len() + js_len];
if let Some(js_file) = graph.find(as_js) {
return Some(js_file);
}
break 'try_from_extension;
}
}
}
// new Worker("./foo") -> /$bunfs/root/foo.js
// new Worker("./foo.ts") -> /$bunfs/root/foo.js (also .tsx .jsx .mjs .mts .cjs .cts)
// new Worker(new URL("./foo.mjs", import.meta.url)) -> the same
let mut pathbuf = bun_paths::path_buffer_pool::get();
let path: &[u8] = if str.starts_with(b"./") || str.starts_with(b"../") {
bun_paths::resolve_path::join_abs_string_buf::<bun_paths::platform::Loose>(
graph.base_public_path_with_default_suffix(),
&mut pathbuf[..],
&[str],
)
} else {
let len = str.len().min(pathbuf.len() - 3);
pathbuf[..len].copy_from_slice(&str[..len]);
&pathbuf[..len]
};
let path_len = path.len();
if let Some(name) = graph.find(&pathbuf[..path_len]) {
return Some(name);
}
let extension_len = bun_paths::extension(&pathbuf[..path_len]).len();
let is_source_extension = matches!(
&pathbuf[path_len - extension_len..path_len],
b"" | b".ts" | b".tsx" | b".jsx" | b".mjs" | b".mts" | b".cjs" | b".cts"
);
if is_source_extension {
let stem_len = path_len - extension_len;
pathbuf[stem_len..stem_len + 3].copy_from_slice(b".js");
if let Some(name) = graph.find(&pathbuf[..stem_len + 3]) {
return Some(name);
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved
}
}
}
Expand Down
36 changes: 36 additions & 0 deletions test/bundler/bundler_compile.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,42 @@ describe("bundler", () => {
outfile: "dist/out",
run: { stdout: "Hello, world!\nWorker loaded!\n", file: "dist/out", setCwd: true },
});
// Every way of naming an embedded worker entry point resolves against the executable, not the cwd: a relative
// specifier with the source extension, with the embedded `.js` extension, or with none, and a `file:` URL made from
// import.meta.url with either extension (absolute, and in the platform's path syntax on Windows).
itBundled("compile/WorkerSpecifierForms", {
backend: "cli",
compile: true,
files: {
"/entry.ts": /* js */ `
import { rmSync } from "fs";
rmSync("./wjs.js", { force: true });
rmSync("./wts.ts", { force: true });
rmSync("./wmjs.mjs", { force: true });
process.chdir(require("os").tmpdir());
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved
const specs = [
"./wjs.js", "./wjs", "./wts.ts", "./wts", "./wmjs.mjs",
new URL("./wjs.js", import.meta.url), new URL("./wts.ts", import.meta.url), new URL("./wmjs.mjs", import.meta.url),
new URL("./wts.ts", import.meta.url).href,
];
for (const spec of specs) {
const w = new Worker(spec);
const msg = await new Promise(resolve => {
w.onmessage = e => resolve(e.data);
w.onerror = e => resolve("error: " + e.message);
});
w.terminate();
console.log(msg);
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved
`,
"/wjs.js": `postMessage("wjs");`,
"/wts.ts": `postMessage("wts" as string);`,
"/wmjs.mjs": `postMessage("wmjs");`,
},
entryPointsRaw: ["./entry.ts", "./wjs.js", "./wts.ts", "./wmjs.mjs"],
outfile: "dist/out",
run: { stdout: "wjs\nwjs\nwts\nwts\nwmjs\nwjs\nwts\nwmjs\nwts\n", file: "dist/out", setCwd: true },
});
itBundled("compile/WorkerRelativePathTSExtension", {
backend: "cli",
compile: true,
Expand Down
Loading