Skip to content

Commit 5ab8e87

Browse files
committed
Bench: cover Bun's isolated .bun store
Bun 1.3.2+ installs with the isolated linker by default, keeping every package only in node_modules/.bun/<name>@<version>/node_modules/<name>. #496 taught the npm crawler (scan, apply's resolver, VEX) to walk that store, but the suite only had a hoisted Bun layout, so the new walk was never timed and a regression back to "2700 lockfile-only packages" would have gone unnoticed. Add bun-isolated/{hosted,rescan}: the same text bun.lock as bun/*, with a pnpm-shaped .bun store, per-entry dependency links, Bun's .bun/node_modules hoist links and root links for direct deps only. A pre-#496 binary fails it (lockfileOnlyPackages: got 2700, want 0). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
1 parent 045d7ec commit 5ab8e87

3 files changed

Lines changed: 52 additions & 3 deletions

File tree

‎crates/socket-patch-bench/README.md‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,9 @@ Each scenario is one project and one `scan` invocation:
3535

3636
Package managers (`<pm>`), each in its native lockfile format and install
3737
layout: `npm`, `pnpm` (isolated `.pnpm` store with symlinks), `yarn-classic`,
38-
`yarn-berry` (node-modules linker), `bun` (text `bun.lock`), `vlt`
39-
(`.vlt` store), `pip` (hash-pinned `requirements.txt`), `uv`, `pylock`
38+
`yarn-berry` (node-modules linker), `bun` (text `bun.lock`, hoisted),
39+
`bun-isolated` (the same lockfile, Bun 1.3's isolated `.bun` store),
40+
`vlt` (`.vlt` store), `pip` (hash-pinned `requirements.txt`), `uv`, `pylock`
4041
(PEP 751), `poetry`, `pipenv`, `pdm`, `bundler`, `composer`, `cargo`,
4142
`golang`, `nuget` and `maven`. Deno has no hosted rewrite and is not
4243
benchmarked separately.

‎crates/socket-patch-bench/src/fixtures/mod.rs‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,13 @@ pub static ALL: &[Pm] = &[
132132
patched: 60,
133133
build: npm::build_bun,
134134
},
135+
Pm {
136+
name: "bun-isolated",
137+
description: "bun (text bun.lock v1, isolated node_modules/.bun store)",
138+
packages: 3000,
139+
patched: 60,
140+
build: npm::build_bun_isolated,
141+
},
135142
Pm {
136143
name: "vlt",
137144
description: "vlt (vlt-lock.json v1, node_modules/.vlt store)",

‎crates/socket-patch-bench/src/fixtures/npm.rs‎

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//! npm-family projects. One deterministic dependency graph is written out
2-
//! as each package manager's lockfile and install layout, so the six
2+
//! as each package manager's lockfile and install layout, so the seven
33
//! scenarios differ only in what each package manager puts on disk.
44
55
use std::collections::BTreeMap;
@@ -689,6 +689,47 @@ pub fn build_bun(t: &mut Tree, size: Size) -> std::io::Result<Fixture> {
689689
Ok(fixture(&g, g.patches(false), &["bun.lock"], &[]))
690690
}
691691

692+
/// Bun's isolated linker (the default since Bun 1.3.2): the same text
693+
/// `bun.lock`, but every package lives only in the pnpm-shaped store
694+
/// `node_modules/.bun/<name>@<version>/node_modules/<name>` (scoped
695+
/// `@scope+leaf@…`), its dependencies linked beside it, the root linking
696+
/// direct dependencies only, and `.bun/node_modules` holding Bun's hoist
697+
/// links.
698+
pub fn build_bun_isolated(t: &mut Tree, size: Size) -> std::io::Result<Fixture> {
699+
let g = graph("bun-isolated", size);
700+
t.write("project/package.json", g.package_json())?;
701+
t.write("project/bun.lock", bun_lock(&g))?;
702+
let mut rng = Rng::new("bun-isolated-install");
703+
for p in &g.pkgs {
704+
let entry = format!("project/node_modules/.bun/{}/node_modules", p.store_key());
705+
write_package(t, &format!("{entry}/{}", p.name), p, &mut rng)?;
706+
for (d, v) in &p.deps {
707+
let Some(dep) = g.resolve(p, d, v) else {
708+
continue;
709+
};
710+
let up = "../".repeat(1 + d.matches('/').count());
711+
let target = format!("{up}../{}/node_modules/{d}", dep.store_key());
712+
t.symlink(&target, &format!("{entry}/{d}"))?;
713+
}
714+
if !p.is_nested() {
715+
let up = "../".repeat(1 + p.name.matches('/').count());
716+
t.symlink(
717+
&format!("{up}{}/node_modules/{}", p.store_key(), p.name),
718+
&format!("project/node_modules/.bun/node_modules/{}", p.name),
719+
)?;
720+
}
721+
}
722+
for p in g.direct() {
723+
let up = "../".repeat(p.name.matches('/').count());
724+
t.symlink(
725+
&format!("{up}.bun/{}/node_modules/{}", p.store_key(), p.name),
726+
&format!("project/node_modules/{}", p.name),
727+
)?;
728+
}
729+
t.mkdir("home")?;
730+
Ok(fixture(&g, g.patches(false), &["bun.lock"], &[]))
731+
}
732+
692733
// ── vlt ────────────────────────────────────────────────────────────────
693734

694735
fn vlt_id(p: &Pkg) -> String {

0 commit comments

Comments
 (0)