diff --git a/.changeset/unlucky-garlics-fetch.md b/.changeset/unlucky-garlics-fetch.md new file mode 100644 index 0000000000..91f8c5b025 --- /dev/null +++ b/.changeset/unlucky-garlics-fetch.md @@ -0,0 +1,12 @@ +--- +"@pnpm/resolve-dependencies": minor +--- + +We are building the dependency tree only until there are new packages or the packages repeat in a unique order. This is needed later during peer dependencies resolution. + +So we resolve `foo > bar > qar > foo`. +But we stop on `foo > bar > qar > foo > qar`. +In the second example, there's no reason to walk qar again when qar is included the first time, the dependencies of foo are already resolved and included as parent dependencies of qar. So during peers resolution, qar cannot possibly get any new or different peers resolved, after the first ocurrence. + +However, in the next example we would analyze the second qar as well, because zoo is a new parent package: +`foo > bar > qar > zoo > qar` diff --git a/packages/resolve-dependencies/src/nodeIdUtils.ts b/packages/resolve-dependencies/src/nodeIdUtils.ts index bdf79d61d6..a934181d74 100644 --- a/packages/resolve-dependencies/src/nodeIdUtils.ts +++ b/packages/resolve-dependencies/src/nodeIdUtils.ts @@ -1,5 +1,10 @@ export function nodeIdContainsSequence (nodeId: string, pkgId1: string, pkgId2: string) { - return nodeId.includes(`>${pkgId1}>${pkgId2}>`) + const pkgIds = splitNodeId(nodeId) + pkgIds.pop() + const pkg1Index = pkgIds.indexOf(pkgId1) + if (pkg1Index === -1) return false + const pkg2Index = pkgIds.indexOf(pkgId2) + return pkg2Index > -1 && pkg1Index < pkg2Index } export function createNodeId (parentNodeId: string, pkgId: string) { diff --git a/packages/resolve-dependencies/src/resolveDependencies.ts b/packages/resolve-dependencies/src/resolveDependencies.ts index 392cd79f8c..9fa510a91a 100644 --- a/packages/resolve-dependencies/src/resolveDependencies.ts +++ b/packages/resolve-dependencies/src/resolveDependencies.ts @@ -595,6 +595,21 @@ async function resolveDependency ( } } + // We are building the dependency tree only until there are new packages + // or the packages repeat in a unique order. + // This is needed later during peer dependencies resolution. + // + // So we resolve foo > bar > qar > foo + // But we stop on foo > bar > qar > foo > qar + // In the second example, there's no reason to walk qar again + // when qar is included the first time, the dependencies of foo + // are already resolved and included as parent dependencies of qar. + // So during peers resolution, qar cannot possibly get any new or different + // peers resolved, after the first ocurrence. + // + // However, in the next example we would analyze the second qar as well, + // because zoo is a new parent package: + // foo > bar > qar > zoo > qar if ( nodeIdContainsSequence( options.parentPkg.nodeId,