Repository navigation
Fix package.json workspaces read five ways (#1900) - #1971
Mikola Lysenko (mikolalysenko) merged 3 commits into
Conversation
Assisted-by: Claude Code:claude-opus-5-5
Five places parsed a package.json `workspaces` field by hand and disagreed on what a malformed field means: a list with a non-string item, `null`, or the wrong type. Depending on the caller, the same manifest made the Bun member walk read no members, made patch discovery skip the bad item silently, or made the yarn workspace warning and the upgrade hint think workspaces were declared. npm 10.9, yarn 1.22.22 and Bun 1.4.4 all refuse to install a list with a non-string item, and npm and Bun also refuse `null`, a string, and a non-array `packages`. A new formats::package_json::Workspaces reader classifies the field once (absent, patterns, or malformed), and every caller reads it: - governing-root refusals and the npm crawler's extra roots keep reading a malformed field's string items, so they still refuse or crawl on the safe side; - the Bun member walk treats a malformed field as unreadable and falls back to bun.lock; - patch discovery records the malformed manifest as unknown, so a project patch cannot be ruled out silently; - the yarn classic warning and the upgrade hint need at least one pattern string. Assisted-by: Claude Code:claude-opus-5-5
Review follow-up for #1900. Patch discovery no longer flags every npm package as possibly user-patched when a package.json carries a malformed `workspaces` field. pnpm ignores the field and yarn 1 installs some malformed shapes, and the string patterns are still walked, so the flag added no safety. Callers now read the shared reader directly instead of going through a wrapper in the hosted module, and the module doc says which readers widen and which treat a malformed field as unreadable. Assisted-by: Claude Code:claude-opus-5-5
|
BugBot review Generated by Claude Code |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit f5135db. Configure here.
|
Ready for review at
Generated by Claude Code |
Final review briefWhat it does: Adds one Risk: low. Every behaviour change only affects manifests that npm and Bun refuse to install ( Look here:
Verified: I read the full diff against #1900. Targeted Changes I made: none. Open questions / nits (non-blocking):
Auto-merge is armed, so approving sends this straight to the merge queue. Generated by Claude Code |
Wenxin Jiang (Wenxin-Jiang)
left a comment
There was a problem hiding this comment.
[agent] Reviewed f5135db9a56fb1e6c420063986a21f9cda9fc355. Checked shared package.json workspace shapes, malformed-field handling and widening versus exact readers. No major correctness issues found. Validation: source and regression-test review plus the available exact-head CI checks; no local test pass is claimed.
LLM Description written by Claude Code:claude-opus-5-5
Fixes #1900
Summary
A
package.jsonworkspacesfield is now read by one helper,formats::package_json::Workspaces. It classifies the field as absent, a pattern list, or malformed, and every caller that parsed the field by hand now reads it:hosted::governing_root(member refusals; also the npm crawler's extra roots and the yarnrc redirect)Workspaces::listed_patterns: same widening behaviour, wrapper removednpm_crawler::bun_workspace_pattern_members_syncnullread as "no members"null) is unreadable, so it falls back tobun.lockor keeps every entryupdate::channel::declares_workspaces[1]includedvendor::yarn_classic_workspace_member_risk["a",1]still warnspatch::user_patchesRoot cause
Five readers parsed the same field by hand, and each decided on its own what a malformed field (a non-string item,
null, the wrong type) means.The issue's open question: fail closed or skip?
I probed it locally:
workspaces["a", 1]null"a"{"packages":"a"}{"nohoist":[]}A non-string item breaks every install, so the shared reader classifies it as
Malformed. What a caller does with that depends on which way is safe for it:Review notes (
/code-review high)Fixed:
hosted::governing_root::workspace_patternswrapper is removed, and import grouping is fixed.Not changed, with reasons:
[1](no string item) no longer counts as declaring workspaces for the yarn upgrade hint or the yarn classic warning. Every package manager refuses to install that manifest, so there is no member install for the warning to protect, and no workingyarncommand for the hint to suggest.bun.lock. Bun cannot install from that manifest, so the lock it last wrote is the member set on disk. With no lock,Nonekeeps every entry, which is the safe side.governing_root::package_json_declares_workspacesstays as it is. It is a presence check for vlt's precedence ("aworkspaceskey with any value"), not a parse of the field's shape.&stritems instead of owned strings would save allocations, but the gain is negligible on these one-shot probes.Test evidence
New tests, red on
main's call-site code and green after the switch (except the guard test noted below):formats::package_json::tests::{classifies_every_shape, parse_ignores_a_bom_and_rejects_non_json, widening_readers_keep_a_malformed_fields_strings}: the table test the issue asks for (absent,null, empty, object form, non-string item,!pattern).crawlers::npm_crawler::tests::yarnrc_and_bun_workspaces_read_past_one_bom_only:null→None(wasSome([])).update::channel::tests::declares_workspaces_reads_the_shared_field_rule:[1]→ false (was true).vendor::berry_migration_risk_tests::issue_691_…:[1]→ no warning (was a warning);["a",1]still warns.patch::user_patches::tests::malformed_workspaces_still_walk_their_string_patterns: member patches are found under["packages/*", 1], and unrelated packages are not flagged.Guard test (passes on
maintoo; it pins that the shared reader keepsuser_patches' existing behaviour):patch::user_patches::tests::malformed_workspaces_still_walk_their_string_patterns(moved out of the red-on-main list above after the final review).Commands run locally:
cargo fmt --all -- --check: passes.cargo clippy --workspace --all-features -- -D warnings: passes.cargo test --workspace --all-features --no-fail-fast: 15,338 passed, 11 failed. None of the failures are caused by this PR:e2e_bun_lockb. One rollback reaches the live blob API (fixed in Fix bun.lockb nightly e2e reaching the live blob API #1905). In the other, the local Bun 1.4.4's own lock migration prints different output.workspacespass after the review fixes:in_process_redirect,in_process_vendor,in_process_vendor_bun_takeover,in_process_alternate_installers,in_process_redirect_pnpm,scan_vendor_e2e. The only exceptions are the same root-only write-failure tests.workspaceshandling, so nothing to change.Per-issue checklist:
workspacesthrough one helper: five readers disagree on non-string items, null and empty lists #1900: one reader, used by all five sites; the malformed rule is decided by the probe above; each changed site has a regression test.https://claude.ai/code/session_011f9aeT3W3otMfyaPAWqHzf
Generated by Claude Code