From c9cf3e9ee597c717acf5a325e35e35a726f9d933 Mon Sep 17 00:00:00 2001 From: Karlis Gangis Date: Thu, 18 Jun 2026 12:44:16 +0300 Subject: [PATCH 1/3] fix: make sure hoistingLimits are not bypassed --- packages/yarnpkg-nm/sources/hoist.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/yarnpkg-nm/sources/hoist.ts b/packages/yarnpkg-nm/sources/hoist.ts index c8004459745a..4a351c86aa5f 100644 --- a/packages/yarnpkg-nm/sources/hoist.ts +++ b/packages/yarnpkg-nm/sources/hoist.ts @@ -802,7 +802,6 @@ const cloneTree = (tree: HoisterTree, options: InternalHoistOptions): HoisterWor const isSeen = !!workNode; if (!workNode) { const {name, identName, reference, peerNames, hoistPriority, dependencyKind} = node; - const dependenciesNmHoistingLimits = options.hoistingLimits.get(parentNode.locator); workNode = { name, references: new Set([reference]), @@ -814,7 +813,7 @@ const cloneTree = (tree: HoisterTree, options: InternalHoistOptions): HoisterWor peerNames: new Set(peerNames), reasons: new Map(), decoupled: true, - isHoistBorder: dependenciesNmHoistingLimits ? dependenciesNmHoistingLimits.has(name) : false, + isHoistBorder: false, hoistPriority: hoistPriority || 0, dependencyKind: dependencyKind || HoisterDependencyKind.REGULAR, hoistedFrom: new Map(), @@ -823,6 +822,9 @@ const cloneTree = (tree: HoisterTree, options: InternalHoistOptions): HoisterWor seenNodes.set(node, workNode); } + if (!workNode.isHoistBorder && options.hoistingLimits.get(parentNode.locator)?.has(node.name)) + workNode.isHoistBorder = true; + parentNode.dependencies.set(node.name, workNode); parentNode.originalDependencies.set(node.name, workNode); From bc03f57de649646348e7a70f933ee0ebbd7dc079 Mon Sep 17 00:00:00 2001 From: Karlis Gangis Date: Thu, 18 Jun 2026 13:07:21 +0300 Subject: [PATCH 2/3] add .yarn/versions file --- .yarn/versions/3bda9cd7.yml | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 .yarn/versions/3bda9cd7.yml diff --git a/.yarn/versions/3bda9cd7.yml b/.yarn/versions/3bda9cd7.yml new file mode 100644 index 000000000000..4aae89e5563f --- /dev/null +++ b/.yarn/versions/3bda9cd7.yml @@ -0,0 +1,25 @@ +releases: + "@yarnpkg/cli": patch + "@yarnpkg/nm": patch + "@yarnpkg/plugin-nm": patch + +declined: + - "@yarnpkg/plugin-compat" + - "@yarnpkg/plugin-constraints" + - "@yarnpkg/plugin-dlx" + - "@yarnpkg/plugin-essentials" + - "@yarnpkg/plugin-init" + - "@yarnpkg/plugin-interactive-tools" + - "@yarnpkg/plugin-npm-cli" + - "@yarnpkg/plugin-pack" + - "@yarnpkg/plugin-patch" + - "@yarnpkg/plugin-pnp" + - "@yarnpkg/plugin-pnpm" + - "@yarnpkg/plugin-stage" + - "@yarnpkg/plugin-typescript" + - "@yarnpkg/plugin-version" + - "@yarnpkg/plugin-workspace-tools" + - "@yarnpkg/builder" + - "@yarnpkg/core" + - "@yarnpkg/doctor" + - "@yarnpkg/pnpify" From d1185dcda7116ec01af0ab19e825ec69d58c3aae Mon Sep 17 00:00:00 2001 From: Karlis Gangis Date: Thu, 18 Jun 2026 13:17:02 +0300 Subject: [PATCH 3/3] add unit test for hoistingLimits fix --- packages/yarnpkg-nm/tests/hoist.test.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/packages/yarnpkg-nm/tests/hoist.test.ts b/packages/yarnpkg-nm/tests/hoist.test.ts index 2c15dea9c6d9..5adb15c8cd2d 100644 --- a/packages/yarnpkg-nm/tests/hoist.test.ts +++ b/packages/yarnpkg-nm/tests/hoist.test.ts @@ -666,4 +666,18 @@ describe(`hoist`, () => { }; expect(getTreeHeight(hoist(toTree(tree), {check: true}))).toEqual(4); }); + + it(`should hoistingLimits when top level dependency matches a transitive dependency`, () => { + // . -> A -> B -> C + // -> B -> C + // with hoistingLimits: dependencies, C should not be hoisted to the top + const tree = { + '.': {dependencies: [`A`, `B`]}, + A: {dependencies: [`B`]}, + B: {dependencies: [`C`]}, + }; + const hoistedTree = hoist(toTree(tree), {check: true, hoistingLimits: new Map([[`.@`, new Set([`A`, `B`])]])}); + const C = Array.from(hoistedTree.dependencies).filter(x => x.name === `C`); + expect(C).toEqual([]); + }); });