@pnpm/installing.deps-resolver 1100.1.4 → 1100.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/hoistPeers.js CHANGED
@@ -62,7 +62,8 @@ export function getHoistableOptionalPeers(allMissingOptionalPeers, allPreferredV
62
62
  if (!allPreferredVersions[missingOptionalPeerName])
63
63
  continue;
64
64
  let maxSatisfyingVersion;
65
- for (const [version, specType] of Object.entries(allPreferredVersions[missingOptionalPeerName])) {
65
+ for (const [version, selector] of Object.entries(allPreferredVersions[missingOptionalPeerName])) {
66
+ const specType = typeof selector === 'string' ? selector : selector.selectorType;
66
67
  if (specType === 'version' &&
67
68
  ranges.every(range => semver.satisfies(version, range)) &&
68
69
  (!maxSatisfyingVersion || semver.gt(version, maxSatisfyingVersion))) {
@@ -244,7 +244,8 @@ async function resolvePeersOfNode(currentAlias, nodeId, parentParentPkgs, ctx) {
244
244
  const _parentPkgsMatch = parentPkgsMatch.bind(null, ctx.dependenciesTree);
245
245
  for (const [newParentPkgName, newParentPkg] of Object.entries(newParentPkgs)) {
246
246
  if (parentPkgs[newParentPkgName]) {
247
- if (!_parentPkgsMatch(parentPkgs[newParentPkgName], newParentPkg)) {
247
+ if (!_parentPkgsMatch(parentPkgs[newParentPkgName], newParentPkg) ||
248
+ inheritedParentPkgBreaksPeerDiamond(ctx, parentPkgs, parentPkgs[newParentPkgName], newParentPkg, children)) {
248
249
  newParentPkg.occurrence = parentPkgs[newParentPkgName].occurrence + 1;
249
250
  parentPkgs[newParentPkgName] = newParentPkg;
250
251
  }
@@ -361,8 +362,15 @@ async function resolvePeersOfNode(currentAlias, nodeId, parentParentPkgs, ctx) {
361
362
  };
362
363
  async function calculateDepPath(peerIds, pendingPeerNodes, cycles) {
363
364
  const cyclicPeerAliases = new Set();
365
+ const pendingPeerAliases = new Set(pendingPeerNodes.map(({ alias }) => alias));
364
366
  for (const cycle of cycles) {
365
- if (cycle.includes(currentAlias)) {
367
+ // A cycle has to be short-circuited at this level whenever any of
368
+ // its members is involved in the current resolution — either as
369
+ // currentAlias or among the pending peers we are about to await.
370
+ // When a cycle member hits the `findHit` cache instead of running
371
+ // its own calculateDepPath, only the awaiting siblings at this
372
+ // level can release the cached promise. See pnpm/pnpm#11999.
373
+ if (cycle.includes(currentAlias) || cycle.some((alias) => pendingPeerAliases.has(alias))) {
366
374
  for (const peerAlias of cycle) {
367
375
  cyclicPeerAliases.add(peerAlias);
368
376
  }
@@ -445,6 +453,59 @@ function parentPkgsMatch(dependenciesTree, currentParentPkg, newParentPkg) {
445
453
  return true;
446
454
  return currentParentResolvedPkg.name === newParentResolvedPkg.name;
447
455
  }
456
+ // A package that is both inherited from an ancestor and present among the
457
+ // current node's own children is normally not duplicated: the inherited
458
+ // instance is reused (see https://github.com/pnpm/pnpm/issues/8370). That reuse
459
+ // is unsafe when a sibling peer-depends both this package and one of this
460
+ // package's own peer dependencies. The sibling must see a single, consistent
461
+ // instance of that shared peer, but the inherited instance resolved it in a
462
+ // different context. In that case the node's own child has to be used instead.
463
+ // See https://github.com/pnpm/pnpm/issues/12079
464
+ function inheritedParentPkgBreaksPeerDiamond(ctx, parentPkgs, inheritedParentPkg, ownChildParentPkg, children) {
465
+ if (inheritedParentPkg.nodeId == null || ownChildParentPkg.nodeId == null)
466
+ return false;
467
+ if (inheritedParentPkg.nodeId === ownChildParentPkg.nodeId)
468
+ return false;
469
+ const inheritedContext = ctx.parentPkgsOfNode.get(inheritedParentPkg.nodeId);
470
+ if (inheritedContext == null)
471
+ return false;
472
+ const parentPkg = ctx.dependenciesTree.get(ownChildParentPkg.nodeId)?.resolvedPackage;
473
+ if (parentPkg == null)
474
+ return false;
475
+ const conflictingPeers = new Set();
476
+ for (const peerName of Object.keys(parentPkg.peerDependencies)) {
477
+ if (!ctx.allPeerDepNames.has(peerName))
478
+ continue;
479
+ const inheritedPeer = inheritedContext[peerName];
480
+ const currentPeer = parentPkgs[peerName];
481
+ if (inheritedPeer == null || currentPeer == null)
482
+ continue;
483
+ if (parentPeerDiffers(ctx.dependenciesTree, currentPeer, inheritedPeer)) {
484
+ conflictingPeers.add(peerName);
485
+ }
486
+ }
487
+ if (conflictingPeers.size === 0)
488
+ return false;
489
+ for (const childNodeId of Object.values(children)) {
490
+ const childPeerDependencies = ctx.dependenciesTree.get(childNodeId)?.resolvedPackage?.peerDependencies;
491
+ if (childPeerDependencies == null || childPeerDependencies[parentPkg.name] == null)
492
+ continue;
493
+ for (const peerName of conflictingPeers) {
494
+ if (childPeerDependencies[peerName] != null)
495
+ return true;
496
+ }
497
+ }
498
+ return false;
499
+ }
500
+ function parentPeerDiffers(dependenciesTree, currentPeer, inheritedPeer) {
501
+ if (inheritedPeer.pkgIdWithPatchHash != null) {
502
+ if (currentPeer.nodeId == null || (typeof currentPeer.nodeId === 'string' && currentPeer.nodeId.startsWith('link:'))) {
503
+ return true;
504
+ }
505
+ return dependenciesTree.get(currentPeer.nodeId)?.resolvedPackage?.pkgIdWithPatchHash !== inheritedPeer.pkgIdWithPatchHash;
506
+ }
507
+ return currentPeer.version !== inheritedPeer.version;
508
+ }
448
509
  function findHit(ctx, parentPkgs, pkgIdWithPatchHash) {
449
510
  const cacheItems = ctx.peersCache.get(pkgIdWithPatchHash);
450
511
  if (!cacheItems)
@@ -25,7 +25,19 @@ export function updateLockfile({ dependenciesGraph, lockfile, prefix, registries
25
25
  return pruneSharedLockfile(lockfile, { warn, dependenciesGraph });
26
26
  }
27
27
  function toLockfileDependency(pkg, opts) {
28
- const lockfileResolution = toLockfileResolution({ name: pkg.name, version: pkg.version }, pkg.resolution, opts.registry, opts.lockfileIncludeTarballUrl);
28
+ let lockfileResolution = toLockfileResolution({ name: pkg.name, version: pkg.version }, pkg.resolution, opts.registry, opts.lockfileIncludeTarballUrl);
29
+ if ('tarball' in lockfileResolution &&
30
+ lockfileResolution.integrity == null &&
31
+ lockfileResolution.type === undefined) {
32
+ const prevResolution = opts.prevSnapshot?.resolution;
33
+ if (prevResolution != null &&
34
+ 'tarball' in prevResolution &&
35
+ prevResolution.type === undefined &&
36
+ prevResolution.tarball === lockfileResolution.tarball &&
37
+ prevResolution.integrity != null) {
38
+ lockfileResolution = { ...lockfileResolution, integrity: prevResolution.integrity };
39
+ }
40
+ }
29
41
  const newResolvedDeps = updateResolvedDeps(opts.updatedDeps, opts.depGraph);
30
42
  const newResolvedOptionalDeps = updateResolvedDeps(opts.updatedOptionalDeps, opts.depGraph);
31
43
  const result = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pnpm/installing.deps-resolver",
3
- "version": "1100.1.4",
3
+ "version": "1100.1.6",
4
4
  "description": "Resolves dependency graph of a package",
5
5
  "keywords": [
6
6
  "pnpm",
@@ -32,7 +32,7 @@
32
32
  "normalize-path": "^3.0.0",
33
33
  "p-defer": "^4.0.1",
34
34
  "path-exists": "^5.0.0",
35
- "promise-share": "^2.0.0",
35
+ "promise-share": "^2.0.1",
36
36
  "ramda": "npm:@pnpm/ramda@0.28.1",
37
37
  "rename-overwrite": "^7.0.1",
38
38
  "safe-promise-defer": "^2.0.0",
@@ -40,30 +40,30 @@
40
40
  "semver-range-intersect": "^0.3.1",
41
41
  "validate-npm-package-name": "7.0.2",
42
42
  "version-selector-type": "^3.0.0",
43
+ "@pnpm/catalogs.resolver": "1100.0.0",
43
44
  "@pnpm/catalogs.types": "1100.0.0",
44
- "@pnpm/constants": "1100.0.0",
45
- "@pnpm/config.version-policy": "1100.1.2",
46
45
  "@pnpm/core-loggers": "1100.1.2",
47
46
  "@pnpm/deps.graph-hasher": "1100.2.2",
48
- "@pnpm/deps.path": "1100.0.5",
47
+ "@pnpm/constants": "1100.0.0",
49
48
  "@pnpm/deps.peer-range": "1100.0.1",
50
- "@pnpm/catalogs.resolver": "1100.0.0",
51
- "@pnpm/hooks.types": "1100.0.9",
49
+ "@pnpm/error": "1100.0.0",
50
+ "@pnpm/config.version-policy": "1100.1.2",
52
51
  "@pnpm/fetching.pick-fetcher": "1100.0.9",
53
52
  "@pnpm/lockfile.preferred-versions": "1100.0.12",
54
- "@pnpm/lockfile.types": "1100.0.8",
53
+ "@pnpm/hooks.types": "1100.0.9",
55
54
  "@pnpm/lockfile.utils": "1100.0.10",
56
- "@pnpm/patching.config": "1100.0.5",
57
55
  "@pnpm/lockfile.pruner": "1100.0.8",
58
- "@pnpm/pkg-manifest.reader": "1100.0.5",
59
- "@pnpm/resolving.npm-resolver": "1101.3.3",
60
- "@pnpm/error": "1100.0.0",
61
56
  "@pnpm/patching.types": "1100.0.0",
62
- "@pnpm/resolving.resolver-base": "1100.3.1",
57
+ "@pnpm/pkg-manifest.utils": "1100.2.1",
58
+ "@pnpm/lockfile.types": "1100.0.8",
59
+ "@pnpm/pkg-manifest.reader": "1100.0.5",
60
+ "@pnpm/resolving.npm-resolver": "1101.4.0",
61
+ "@pnpm/types": "1101.2.0",
63
62
  "@pnpm/store.controller-types": "1100.1.2",
63
+ "@pnpm/deps.path": "1100.0.5",
64
64
  "@pnpm/workspace.spec-parser": "1100.0.0",
65
- "@pnpm/pkg-manifest.utils": "1100.2.1",
66
- "@pnpm/types": "1101.2.0"
65
+ "@pnpm/patching.config": "1100.0.5",
66
+ "@pnpm/resolving.resolver-base": "1100.3.1"
67
67
  },
68
68
  "peerDependencies": {
69
69
  "@pnpm/logger": "^1001.0.1"
@@ -74,8 +74,8 @@
74
74
  "@types/ramda": "0.31.1",
75
75
  "@types/semver": "7.7.1",
76
76
  "@types/validate-npm-package-name": "^4.0.2",
77
- "@pnpm/installing.deps-resolver": "1100.1.4",
78
- "@pnpm/logger": "1100.0.0"
77
+ "@pnpm/logger": "1100.0.0",
78
+ "@pnpm/installing.deps-resolver": "1100.1.6"
79
79
  },
80
80
  "engines": {
81
81
  "node": ">=22.13"