install: resolve bun update --latest at the row, so package.json never holds a temporary latest - #44485
Draft
robobun wants to merge 7 commits into
Draft
install: resolve bun update --latest at the row, so package.json never holds a temporary latest#44485robobun wants to merge 7 commits into
bun update --latest at the row, so package.json never holds a temporary latest#44485robobun wants to merge 7 commits into
Conversation
…ckage.json free of a temporary latest
…tled catalogs as written
… as it did with the temporary literal
…the target package ids looked up once
… literal under bun update --latest
Collaborator
Author
|
Status: draft, tests pass locally, self-review in progress How this was reproduced, on main and on 1.4.2, with a loopback registry (
With this branch the pin holds in 1 to 3, and both files stay byte-identical in 4.
|
Collaborator
Author
|
Updated 6:27 PM PT - Oct 2nd, 2026
✅ @autofix-ci[bot], your commit 8e82052d6e41c2a9d180035fd9cd871fc99cf3a7 passed in 🧪 To try this PR locally: bunx bun-pr 44485That installs a local version of the PR into your bun-44485 --bun |
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
bun update --latestmoves a package off the version an override pins. With"overrides": {"kept": "catalog:"}and catalogkept: 1.0.0it prints^ kept 1.0.0 -> 2.0.0. package.json, bun.lock's catalog and--frozen-lockfilestill say 1.0.0.$nameand selector overrides lose the pin too.bun update --latest -ron an up-to-date catalog writes"kept": "latest"into package.json.latestinto the package.json that the install parses (PackageJSONEditor.rs:516,:740,:1398). Overrides read it.Fix
version_pick(PackageManagerEnqueue.rs) makes a targeted row resolve thelatestdist-tag, as-r --latestalready did (install: honor --recursive/--filter in non-interactive bun update; re-resolve every named-update target #36360).latestonly when acatalog:dependency uses it, and only in the parsed map (steer_used_catalogs_to_latest). An entry that only an override reads stays a pin, as in pnpm 12.8.1.test/cli/install/bun-update-lockfile-sync.test.ts(34 new cells, 20 fail on main). Other suites: see Notes.Background
catalog:takes the root catalog's version.$nametakes the range the root declares forname. A selector key applies only to a dependent whose range overlaps it.Downsides
bun update -r --latestnow moves directpeerDependenciesand patched packages, as the plain form does.$namereferent moves in the same run, the overridden row keeps the old version (before:latest). install: re-resolve rows whose override or catalog value changed in the package.json write-back #43981 re-resolves it.PackageManagergrows 24 bytes. Release binary size is not measured (see Notes).Notes
Where the temporary value went before. A bare or named
bun update --latestrewrote each direct dependency of the invoking package.json tolatestbefore the install, and a bare one rewrote every root catalog entry. The install parsed that text. Four readers took the temporary value for the declared one:PackageManagerEnqueue.rsoverride hop,dedupe::effective_versionlatest, the entry is restored, bun.lock contradicts its own catalog$nameoverrideOverrideMap.rsparse_override_valuelatestfor this runOverrideMap.rsscoped_rule_for^2.0.0sync_lockfilepackage_json_write_back.rs"latest"reaches package.json (-r,--filter) or bun.lock's catalog (member cwd) when no entry moves. An optional dependency that does not resolve keeps"latest"What changed.
edit_update_entriesandeditonly record the declared literals.record_catalog_entries(wasedit_catalogs_before_update) only records the catalog entries. Nothing prints a temporary value into the package.json cache entry.version_pickdecides once per row: the command isbun update --latest, no override or catalog replaced the row's version, and a workspace that the command targets declares the row (with names: the row names a request). Its consumers are the manifest lookup, the exact-version cache shortcut and the peer pass. A patched package is not held for such a row. The baseline for "never move below what bun.lock has" islocked_version_in_lockfilefor every form.locked_version_of_invoking_workspace_rowis deleted.update_target_declaresis the one owner test. The-r/--filtertarget package ids are looked up once (PackageManager::update_target_ids).Lockfile::is_root_dependencyandLockfile::is_dependency_of_workspace_inare deleted. The second one scanned every package for each resolved row.steer_used_catalogs_to_latestruns after each root parse that a resolve uses (the differ and the new-lockfile path). It reads the dependency lists of the root and of every member from the package.json cache, which the root parse has just filled.sync_lockfilecopies the root's catalogs again when they were steered and the root was not edited.Behaviour changes.
-r --latestand--filter --latest: directpeerDependenciesand patched packages now move tolatest. The plain form always moved them, and docs/pm/cli/update.mdx says--latestmoves patched packages.--latest: selector and$nameoverrides, the workspace link and a knownnpm:alias redirect now see the declared range. Before, the temporary dist-tag bypassed them.bun update."latest"in package.json.Duplicate dependencywarning quotes the declared literal, not"latest".Reference behaviour. pnpm 12.8.1,
pnpm update --latest, same shapes: a catalog entry that only an override reads stays, and the row stays. With a directcatalog:dependency the entry moves and the override follows."kept": "$pin"keeps the pin. Whenpinitself moves,keptstays on the old version andpnpm install --frozen-lockfilethen exits 1.Still open. A row that must follow a
$namereferent or a catalog entry that moves in the same command keeps the old version. bun.lock then records the new override value, and--frozen-lockfilepasses. That is the state of #43975 forbun update <name>. #43981 re-resolves such rows after the write-back.resolve_catalog_literalsstill trusts any row declaredcatalog:, also one that a literal override resolved.Costs, from the diff.
bun install: oneto_updatetest per enqueued registry row. The three-termlatest_for_targetexpression per manifest lookup is gone. Oneupdating_catalogs.is_empty()test per install.bun update --latestwith a catalog: one print and one JSON parse of the root package.json fewer (the temporary value needed them). One pass over the dependency lists of every workspace package.json (cache hits, no file read). One string append and oneDependency::parseper used entry.bun update -r --latest: one scan of the package list per command. Before: up to two scans per resolved row.size_of::<PackageManager>(): +24 bytes, oneVec<PackageID>.bloaty,valgrind,perforstrace, and a release build did not finish there.Suites run with the debug build.
bun-update,bun-update-transitive,bun-update-lockfile-sync,catalogs,overrides,nested-overrides,bun-add,bun-add-catalog,bun-add-filter,bun-audit,bun-patch,bun-dedupe,bun-prune,bun-workspaces,bun-install-registry,lockfile-only,minimum-release-age,bun-update-security-*undertest/cli/install/, andtest/cli/update_interactive_install.test.ts.