Skip to content

Commit 56c7bff

Browse files
larixermerceyz
authored andcommitted
fix(nm): apply hoisting algorithm on aliased dependencies (#4237)
* Apply hoisting algorithm on aliased dependencies * Adds a unit test to check hoisting of the aliased packages * Updates conditions to detect hoisting loops to account for aliases
1 parent 3276aa4 commit 56c7bff

File tree

4 files changed

+49
-10
lines changed

4 files changed

+49
-10
lines changed

.yarn/versions/6983a0de.yml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
releases:
2+
"@yarnpkg/cli": patch
3+
"@yarnpkg/nm": patch
4+
"@yarnpkg/plugin-nm": patch
5+
"@yarnpkg/pnpify": patch
6+
7+
declined:
8+
- "@yarnpkg/plugin-compat"
9+
- "@yarnpkg/plugin-constraints"
10+
- "@yarnpkg/plugin-dlx"
11+
- "@yarnpkg/plugin-essentials"
12+
- "@yarnpkg/plugin-init"
13+
- "@yarnpkg/plugin-interactive-tools"
14+
- "@yarnpkg/plugin-npm-cli"
15+
- "@yarnpkg/plugin-pack"
16+
- "@yarnpkg/plugin-patch"
17+
- "@yarnpkg/plugin-pnp"
18+
- "@yarnpkg/plugin-pnpm"
19+
- "@yarnpkg/plugin-stage"
20+
- "@yarnpkg/plugin-typescript"
21+
- "@yarnpkg/plugin-version"
22+
- "@yarnpkg/plugin-workspace-tools"
23+
- "@yarnpkg/builder"
24+
- "@yarnpkg/core"
25+
- "@yarnpkg/doctor"

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ Yarn now accepts sponsorships! Please give a look at our [OpenCollective](https:
88

99
### Installs
1010
- The pnpm linker no longer tries to remove `node_modules` directory, when `node-modules` linker is active
11+
- The nm linker applies hoisting algorithm on aliased dependencies
1112

1213
**Note:** features in `master` can be tried out by running `yarn set version from sources` in your project (existing contrib plugins are updated automatically, while new contrib plugins can be added by running `yarn plugin import from sources <name>`).
1314

packages/yarnpkg-nm/sources/hoist.ts

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ export enum HoisterDependencyKind {
5252
export type HoisterTree = {name: PackageName, identName: PackageName, reference: string, dependencies: Set<HoisterTree>, peerNames: Set<PackageName>, hoistPriority?: number, dependencyKind?: HoisterDependencyKind};
5353
export type HoisterResult = {name: PackageName, identName: PackageName, references: Set<string>, dependencies: Set<HoisterResult>};
5454
type Locator = string;
55+
type AliasedLocator = string & { __aliasedLocator: true };
5556
type Ident = string;
5657
type HoisterWorkTree = {name: PackageName, references: Set<string>, ident: Ident, locator: Locator, dependencies: Map<PackageName, HoisterWorkTree>, originalDependencies: Map<PackageName, HoisterWorkTree>, hoistedDependencies: Map<PackageName, HoisterWorkTree>, peerNames: ReadonlySet<PackageName>, decoupled: boolean, reasons: Map<PackageName, string>, isHoistBorder: boolean, hoistedFrom: Map<PackageName, Array<string>>, hoistedTo: Map<PackageName, string>, hoistPriority: number, dependencyKind: HoisterDependencyKind};
5758

@@ -576,6 +577,8 @@ const getNodeHoistInfo = (rootNode: HoisterWorkTree, rootNodePathLocators: Set<L
576577
}
577578
};
578579

580+
const getAliasedLocator = (node: HoisterWorkTree): AliasedLocator => `${node.name}@${node.locator}` as AliasedLocator;
581+
579582
/**
580583
* Performs actual graph transformation, by hoisting packages to the root node.
581584
*
@@ -591,10 +594,11 @@ const hoistGraph = (tree: HoisterWorkTree, rootNodePath: Array<HoisterWorkTree>,
591594
let anotherRoundNeeded = false;
592595
let isGraphChanged = false;
593596

594-
const hoistNodeDependencies = (nodePath: Array<HoisterWorkTree>, locatorPath: Array<Locator>, parentNode: HoisterWorkTree, newNodes: Set<HoisterWorkTree>) => {
597+
const hoistNodeDependencies = (nodePath: Array<HoisterWorkTree>, locatorPath: Array<Locator>, aliasedLocatorPath: Array<AliasedLocator>, parentNode: HoisterWorkTree, newNodes: Set<HoisterWorkTree>) => {
595598
if (seenNodes.has(parentNode))
596599
return;
597-
const nextLocatorPath = [...locatorPath, parentNode.locator];
600+
const nextLocatorPath = [...locatorPath, getAliasedLocator(parentNode)];
601+
const nextAliasedLocatorPath = [...aliasedLocatorPath, getAliasedLocator(parentNode)];
598602

599603
const dependantTree = new Map<PackageName, Set<PackageName>>();
600604
const hoistInfos = new Map<HoisterWorkTree, HoistInfo>();
@@ -679,11 +683,11 @@ const hoistGraph = (tree: HoisterWorkTree, rootNodePath: Array<HoisterWorkTree>,
679683
if ((hoistableIdent === node.ident || !parentNode.reasons.has(node.name)) && hoistInfo.isHoistable !== Hoistable.YES)
680684
parentNode.reasons.set(node.name, hoistInfo.reason!);
681685

682-
if (!node.isHoistBorder && nextLocatorPath.indexOf(node.locator) < 0) {
686+
if (!node.isHoistBorder && nextAliasedLocatorPath.indexOf(getAliasedLocator(node)) < 0) {
683687
seenNodes.add(parentNode);
684688
const decoupledNode = decoupleGraphNode(parentNode, node);
685689

686-
hoistNodeDependencies([...nodePath, parentNode], [...locatorPath, parentNode.locator], decoupledNode, nextNewNodes);
690+
hoistNodeDependencies([...nodePath, parentNode], nextLocatorPath, nextAliasedLocatorPath, decoupledNode, nextNewNodes);
687691

688692
seenNodes.delete(parentNode);
689693
}
@@ -693,6 +697,7 @@ const hoistGraph = (tree: HoisterWorkTree, rootNodePath: Array<HoisterWorkTree>,
693697

694698
let newNodes;
695699
let nextNewNodes = new Set(getSortedRegularDependencies(rootNode));
700+
const aliasedRootNodePathLocators = Array.from(rootNodePath).map(x => getAliasedLocator(x));
696701
do {
697702
newNodes = nextNewNodes;
698703
nextNewNodes = new Set();
@@ -701,7 +706,7 @@ const hoistGraph = (tree: HoisterWorkTree, rootNodePath: Array<HoisterWorkTree>,
701706
continue;
702707
const decoupledDependency = decoupleGraphNode(rootNode, dep);
703708

704-
hoistNodeDependencies([], Array.from(rootNodePathLocators), decoupledDependency, nextNewNodes);
709+
hoistNodeDependencies([], Array.from(rootNodePathLocators), aliasedRootNodePathLocators, decoupledDependency, nextNewNodes);
705710
}
706711
} while (nextNewNodes.size > 0);
707712

@@ -1011,8 +1016,7 @@ const dumpDepTree = (tree: HoisterWorkTree) => {
10111016
if (!pkg.peerNames.has(dep.name) && dep !== pkg) {
10121017
const reason = pkg.reasons.get(dep.name);
10131018
const identName = getIdentName(dep.locator);
1014-
const hoistedFrom = pkg.hoistedFrom.get(dep.name) || [];
1015-
str += `${prefix}${idx < dependencies.length - 1 ? `├─` : `└─`}${(parents.has(dep) ? `>` : ``) + (identName !== dep.name ? `a:${dep.name}:` : ``) + prettyPrintLocator(dep.locator) + (reason ? ` ${reason}` : ``) + (dep !== pkg && hoistedFrom.length > 0 ? `, hoisted from: ${hoistedFrom.join(`, `)}` : ``)}\n`;
1019+
str += `${prefix}${idx < dependencies.length - 1 ? `├─` : `└─`}${(parents.has(dep) ? `>` : ``) + (identName !== dep.name ? `a:${dep.name}:` : ``) + prettyPrintLocator(dep.locator) + (reason ? ` ${reason}` : ``)}\n`;
10161020
str += dumpPackage(dep, parents, `${prefix}${idx < dependencies.length - 1 ? `│ ` : ` `}`);
10171021
}
10181022
}

packages/yarnpkg-nm/tests/hoist.test.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ import {hoist, HoisterTree, HoisterResult, HoisterDependencyKind} from '../sourc
22

33
const toTree = (obj: any, key: string = `.`, nodes = new Map()): HoisterTree => {
44
let node = nodes.get(key);
5-
const identName = key.match(/@?[^@]+/)![0];
5+
const name = key.match(/@?[^@]+/)![0];
66
if (!node) {
77
node = {
8-
name: identName,
9-
identName,
8+
name,
9+
identName: (obj[key] || {}).identName || name,
1010
reference: key.match(/@?[^@]+@?(.+)?/)![1] || ``,
1111
dependencies: new Set<HoisterTree>(),
1212
peerNames: new Set<string>((obj[key] || {}).peerNames || []),
@@ -551,4 +551,13 @@ describe(`hoist`, () => {
551551

552552
expect(getTreeHeight(hoist(toTree(tree), {check: true}))).toEqual(5);
553553
});
554+
555+
it(`should hoist aliased packages`, () => {
556+
const tree = {
557+
'.': {dependencies: [`Aalias`]},
558+
Aalias: {identName: `A`, dependencies: [`A`]},
559+
A: {dependencies: [`B`]},
560+
};
561+
expect(getTreeHeight(hoist(toTree(tree), {check: true}))).toEqual(3);
562+
});
554563
});

0 commit comments

Comments
 (0)