Skip to content

fix(arborist): do not hoist undeclared workspaces in linked strategy#9076

Merged
wraithgar merged 3 commits intonpm:latestfrom
manzoorwanijk:fix/workspace-hoisting-in-linked-strategy
Mar 7, 2026
Merged

fix(arborist): do not hoist undeclared workspaces in linked strategy#9076
wraithgar merged 3 commits intonpm:latestfrom
manzoorwanijk:fix/workspace-hoisting-in-linked-strategy

Conversation

@manzoorwanijk
Copy link
Contributor

In continuation of our exploration of using install-strategy=linked in the Gutenberg monorepo, which powers the WordPress Block Editor.

Summary

With install-strategy=linked, all workspace packages are unconditionally symlinked into the root node_modules/, regardless of whether the root declares them as dependencies. This defeats the strict isolation that the linked strategy is supposed to provide — any workspace can import any other workspace without declaring it as a dependency.

The root cause is two-fold:

  1. assignCommonProperties() includes all workspaces in root's localDependencies because npm auto-creates type: 'workspace' edges from root to every workspace
  2. createIsolatedTree() unconditionally creates a workspace Link entry in root.children at node_modules/<wsName> for every workspace

The fix:

  1. Filters undeclared workspace deps in #assignCommonProperties() so they don't enter root's localDependencies
  2. Only creates root-level workspace symlinks (node_modules/<wsName>) for declared dependencies

Before (broken)

node_modules/@scope/a -> packages/a    # root doesn't depend on @scope/a
node_modules/@scope/b -> packages/b    # root doesn't depend on @scope/b

After (fixed)

packages/a/node_modules/@scope/b -> packages/b   # @scope/a depends on @scope/b

No symlinks at root node_modules/ since root doesn't depend on either workspace.

References

Fixes #9072
Related to #6537 (same problem with --install-strategy=nested)

@manzoorwanijk manzoorwanijk requested a review from a team as a code owner March 7, 2026 01:12
…d as dependencies

With install-strategy=linked, all workspace packages were unconditionally symlinked into root node_modules/ regardless of whether root declared them as dependencies. Filter undeclared workspace deps in assignCommonProperties so they don't enter root's localDependencies, and only create root-level workspace links for explicitly declared dependencies.
@manzoorwanijk manzoorwanijk requested a review from wraithgar March 7, 2026 16:11
@wraithgar wraithgar merged commit ff51827 into npm:latest Mar 7, 2026
16 checks passed
@manzoorwanijk manzoorwanijk deleted the fix/workspace-hoisting-in-linked-strategy branch March 7, 2026 23:37
manzoorwanijk added a commit to manzoorwanijk/npm-cli that referenced this pull request Mar 9, 2026
wraithgar pushed a commit that referenced this pull request Mar 9, 2026
Cherry pick of:
- 5fd40b6 (#9076)
- e2c2443 (#9081)

Additional changes:

- Ported `shouldOmit` method to v10's `Node` class (exists on `latest`
but was missing on v10) with full test coverage
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] Linked install strategy hoists all workspace packages to root node_modules

2 participants