From 6560b8d952a613cefbd900186aa38df53bc201d1 Mon Sep 17 00:00:00 2001 From: isaacs Date: Thu, 15 Oct 2020 16:00:49 -0700 Subject: [PATCH] @npmcli/arborist@1.0.2 --- node_modules/@npmcli/arborist/README.md | 4 +- .../arborist/lib/arborist/build-ideal-tree.js | 140 ++++++++---------- .../@npmcli/arborist/lib/arborist/reify.js | 2 +- node_modules/@npmcli/arborist/package.json | 2 +- package-lock.json | 18 +-- package.json | 2 +- 6 files changed, 79 insertions(+), 89 deletions(-) diff --git a/node_modules/@npmcli/arborist/README.md b/node_modules/@npmcli/arborist/README.md index c8efd37b74741..cda5f8b9085be 100644 --- a/node_modules/@npmcli/arborist/README.md +++ b/node_modules/@npmcli/arborist/README.md @@ -2,10 +2,10 @@ Inspect and manage `node_modules` trees. -![a tree with the word ARBORIST superimposed on it](https://raw.githubusercontent.com/npm/arborist/master/logo.svg?sanitize=true) +![a tree with the word ARBORIST superimposed on it](https://raw.githubusercontent.com/npm/arborist/main/logo.svg?sanitize=true) There's more documentation [in the notes -folder](https://github.com/npm/arborist/tree/master/notes). +folder](https://github.com/npm/arborist/tree/main/notes). ## USAGE diff --git a/node_modules/@npmcli/arborist/lib/arborist/build-ideal-tree.js b/node_modules/@npmcli/arborist/lib/arborist/build-ideal-tree.js index 368ca30597f9e..1f36776351f83 100644 --- a/node_modules/@npmcli/arborist/lib/arborist/build-ideal-tree.js +++ b/node_modules/@npmcli/arborist/lib/arborist/build-ideal-tree.js @@ -1023,6 +1023,7 @@ This is a one-time fix-up, please be patient... edge: edge.explain(), peerConflict, strictPeerDeps: this[_strictPeerDeps], + force: this[_force], } } @@ -1040,7 +1041,7 @@ This is a one-time fix-up, please be patient... // place dep, requested by node, to satisfy edge // XXX split this out into a separate method or mixin? It's quite a lot // of functionality that ought to have its own unit tests more conveniently. - [_placeDep] (dep, node, edge, peerEntryEdge = null) { + [_placeDep] (dep, node, edge, peerEntryEdge = null, peerPath = []) { if (edge.to && !edge.error && !this[_updateNames].includes(edge.name) && @@ -1057,7 +1058,7 @@ This is a one-time fix-up, please be patient... let target let canPlace = null for (let check = start; check; check = check.resolveParent) { - const cp = this[_canPlaceDep](dep, check, edge, peerEntryEdge) + const cp = this[_canPlaceDep](dep, check, edge, peerEntryEdge, peerPath) // anything other than a conflict is fine to proceed with if (cp !== CONFLICT) { @@ -1095,14 +1096,29 @@ This is a one-time fix-up, please be patient... // Can only get KEEP here if the original edge was valid, // and we're checking for an update but it's already up to date. if (canPlace === KEEP) { - dep.parent = null + if (edge.peer && !target.children.get(edge.name).satisfies(edge)) { + // this is an overridden peer dep + this[_warnPeerConflict](edge) + } return [] } // figure out which of this node's peer deps will get placed as well const virtualRoot = dep.parent - const placed = [dep] + const newDep = new dep.constructor({ + name: dep.name, + pkg: dep.package, + resolved: dep.resolved, + integrity: dep.integrity, + legacyPeerDeps: this.legacyPeerDeps, + error: dep.errors[0], + ...(dep.target ? { target: dep.target } : {}), + }) + if (this[_loadFailures].has(dep)) + this[_loadFailures].add(newDep) + + const placed = [newDep] const oldChild = target.children.get(edge.name) if (oldChild) { // if we're replacing, we should also remove any nodes for edges that @@ -1113,34 +1129,39 @@ This is a one-time fix-up, please be patient... // later anyway. const oldDeps = [] for (const [name, edge] of oldChild.edgesOut.entries()) { - if (!dep.edgesOut.has(name) && edge.to) + if (!newDep.edgesOut.has(name) && edge.to) oldDeps.push(edge.to) } - dep.replace(oldChild) - this[_pruneForReplacement](dep, oldDeps) + newDep.replace(oldChild) + this[_pruneForReplacement](newDep, oldDeps) // this may also create some invalid edges, for example if we're // intentionally causing something to get nested which was previously // placed in this location. - for (const edge of dep.edgesIn) { - if (edge.invalid) { - this[_depsQueue].push(edge.from) - this[_depsSeen].delete(edge.from) + for (const edgeIn of newDep.edgesIn) { + if (edgeIn.invalid && edgeIn !== edge) { + this[_depsQueue].push(edgeIn.from) + this[_depsSeen].delete(edgeIn.from) } } } else - dep.parent = target + newDep.parent = target + + if (edge.peer && !newDep.satisfies(edge)) { + // this is an overridden peer dep + this[_warnPeerConflict](edge) + } // If the edge is not an error, then we're updating something, and // MAY end up putting a better/identical node further up the tree in // a way that causes an unnecessary duplication. If so, remove the // now-unnecessary node. - if (edge.valid && edge.to.parent !== target && dep.canReplace(edge.to)) + if (edge.valid && edge.to.parent !== target && newDep.canReplace(edge.to)) edge.to.parent = null // visit any dependents who are upset by this change // if it's an angry overridden peer edge, however, make sure we // skip over it! - for (const edgeIn of dep.edgesIn) { + for (const edgeIn of newDep.edgesIn) { if (edgeIn !== edge && !edgeIn.valid && !this[_depsSeen].has(edge.from)) { this.addTracker('idealTree', edgeIn.from.name, edgeIn.from.location) this[_depsQueue].push(edgeIn.from) @@ -1150,12 +1171,12 @@ This is a one-time fix-up, please be patient... // in case we just made some duplicates that can be removed, // prune anything deeper in the tree that can be replaced by this if (this.idealTree) { - for (const node of this.idealTree.inventory.query('name', dep.name)) { - if (node !== dep && + for (const node of this.idealTree.inventory.query('name', newDep.name)) { + if (node !== newDep && node.isDescendantOf(target) && !node.inShrinkwrap && !node.inBundle && - node.canReplaceWith(dep)) { + node.canReplaceWith(newDep)) { // don't prune if the dupe is necessary! // root (a, d) // +-- a (b, c2) @@ -1168,35 +1189,28 @@ This is a one-time fix-up, please be patient... const mask = node.parent !== target && node.parent.parent !== target && - node.parent.parent.resolve(dep.name) + node.parent.parent.resolve(newDep.name) - if (!mask || mask === dep || node.canReplaceWith(mask)) + if (!mask || mask === newDep || node.canReplaceWith(mask)) node.parent = null } } } // also place its unmet or invalid peer deps at this location - // note that dep has now been removed from the virtualRoot set + // note that newDep has now been removed from the virtualRoot set // by virtue of being placed in the target's node_modules. - const peers = [] - // double loop so that we don't yank things out and then fail to find - // them in the virtualRoot's children. - for (const peerEdge of dep.edgesOut.values()) { + // loop through any peer deps from the thing we just placed, and place + // those ones as well. it's safe to do this with the virtual nodes, + // because we're copying rather than moving them out of the virtual root, + // otherwise they'd be gone and the peer set would change throughout + // this loop. + for (const peerEdge of newDep.edgesOut.values()) { if (!peerEdge.peer || peerEdge.valid) continue const peer = virtualRoot.children.get(peerEdge.name) - // since we re-use virtualRoots, it's possible that the node was - // already placed somewhere in the tree, and thus plucked off the - // virtual root. however, in that case, it should have been no - // longer a missing/invalid peer dep, so something is messed up. - if (peer) - peers.push([peer, peerEdge]) - } - - for (const [peer, peerEdge] of peers) { const peerPlaced = this[_placeDep]( - peer, dep, peerEdge, peerEntryEdge || edge) + peer, newDep, peerEdge, peerEntryEdge || edge) placed.push(...peerPlaced) } @@ -1245,11 +1259,9 @@ This is a one-time fix-up, please be patient... // checking, because either we're leaving it alone, or it won't work anyway. // When we check peers, we pass along the peerEntryEdge to track the // original edge that caused us to load the family of peer dependencies. - [_canPlaceDep] (dep, target, edge, peerEntryEdge = null) { + [_canPlaceDep] (dep, target, edge, peerEntryEdge = null, peerPath = []) { const entryEdge = peerEntryEdge || edge const source = this[_peerSetSource].get(dep) - const virtualRoot = dep.parent - const vrEdge = virtualRoot.edgesOut.get(edge.name) const isSource = target === source const { isRoot, isWorkspace } = source || {} @@ -1266,7 +1278,7 @@ This is a one-time fix-up, please be patient... const { version: newVer } = dep const tryReplace = curVer && newVer && semver.gte(newVer, curVer) if (tryReplace && dep.canReplace(current)) { - const res = this[_canPlacePeers](dep, target, edge, REPLACE, peerEntryEdge) + const res = this[_canPlacePeers](dep, target, edge, REPLACE, peerEntryEdge, peerPath) /* istanbul ignore else - It's extremely rare that a replaceable * node would be a conflict, if the current one wasn't a conflict, * but it is theoretically possible if peer deps are pinned. In @@ -1276,12 +1288,14 @@ This is a one-time fix-up, please be patient... } // ok, can't replace the current with new one, but maybe current is ok? + // no need to check if it's a peer that's valid to be here, because + // peers are always placed along with their entry source if (edge.satisfiedBy(current)) return KEEP // if we prefer deduping, then try replacing newer with older if (this[_preferDedupe] && !tryReplace && dep.canReplace(current)) { - const res = this[_canPlacePeers](dep, target, edge, REPLACE, peerEntryEdge) + const res = this[_canPlacePeers](dep, target, edge, REPLACE, peerEntryEdge, peerPath) /* istanbul ignore else - It's extremely rare that a replaceable * node would be a conflict, if the current one wasn't a conflict, * but it is theoretically possible if peer deps are pinned. In @@ -1333,7 +1347,7 @@ This is a one-time fix-up, please be patient... } } if (canReplace) { - const ret = this[_canPlacePeers](dep, target, edge, REPLACE, peerEntryEdge) + const ret = this[_canPlacePeers](dep, target, edge, REPLACE, peerEntryEdge, peerPath) /* istanbul ignore else - extremely rare that the peer set would * conflict if we can replace the node in question, but theoretically * possible, if peer deps are pinned aggressively. */ @@ -1352,18 +1366,6 @@ This is a one-time fix-up, please be patient... } } - if (vrEdge && vrEdge.satisfiedBy(current)) { - /* istanbul ignore else - If the virtual root was satisfied, in - * such a way that it was an override, and it's NOT forced, and is - * ours, or is in strict mode, then it would have crashed during - * the creation of the peerSet. Nevertheless, this is a good check - * to ensure we're not warning when we should be conflicting. */ - if (this[_force] || !isMine && !this[_strictPeerDeps]) { - this[_warnPeerConflict](edge) - return KEEP - } - } - // no justification for overriding, and no agreement possible. return CONFLICT } @@ -1386,21 +1388,8 @@ This is a one-time fix-up, please be patient... // a specific name, however, or if a dep makes an incompatible change // to its peer dep in a non-semver-major version bump, or if the parent // is unbounded in its dependency list. - if (!targetEdge.satisfiedBy(dep)) { - if (isSource) { - // conflicted peer dep. accept what's there, if overriding - /* istanbul ignore else - If it's the source, and the source's edge - * is not valid, then either we crashed when creating the peer set, - * or it's forced, or it's not ours and not strict. Keep this check - * to avoid relying on action at a distance, however. */ - if (this[_force] || !isMine && !this[_strictPeerDeps]) { - this[_warnPeerConflict](edge) - return KEEP - } - } - + if (!targetEdge.satisfiedBy(dep)) return CONFLICT - } } // check to see what that name resolves to here, and who may depend on @@ -1419,30 +1408,30 @@ This is a one-time fix-up, please be patient... } // no objections! ok to place here - return this[_canPlacePeers](dep, target, edge, OK, peerEntryEdge) + return this[_canPlacePeers](dep, target, edge, OK, peerEntryEdge, peerPath) } // make sure the family of peer deps can live here alongside it. // this doesn't guarantee that THIS solution will be the one we take, // but it does establish that SOME solution exists at this level in // the tree. - [_canPlacePeers] (dep, target, edge, ret, peerEntryEdge) { - if (!dep.parent || peerEntryEdge) + [_canPlacePeers] (dep, target, edge, ret, peerEntryEdge, peerPath) { + // do not go in cycles when we're resolving a peer group + if (!dep.parent || peerEntryEdge && peerPath.includes(dep)) return ret + peerPath = [...peerPath, dep] for (const peer of dep.parent.children.values()) { if (peer === dep) continue - const peerEdge = dep.edgesOut.get(peer.name) || - [...peer.edgesIn].find(e => e.peer) - - /* istanbul ignore if - pretty sure this is impossible, but just - being cautious */ + // we only have to pick the first one, because ALL peer edgesIn will + // be checked before we decide to accept an existing dep in the tree + const peerEdge = [...peer.edgesIn].find(e => e.peer && e !== edge) if (!peerEdge) continue - const canPlacePeer = this[_canPlaceDep](peer, target, peerEdge, edge) + const canPlacePeer = this[_canPlaceDep](peer, target, peerEdge, edge, peerPath) if (canPlacePeer !== CONFLICT) continue @@ -1564,6 +1553,7 @@ This is a one-time fix-up, please be patient... for (const node of this[_loadFailures]) { if (!node.optional) throw node.errors[0] + const set = optionalSet(node) for (const node of set) node.parent = null diff --git a/node_modules/@npmcli/arborist/lib/arborist/reify.js b/node_modules/@npmcli/arborist/lib/arborist/reify.js index 8fe88edb8f722..57ecf071fbaff 100644 --- a/node_modules/@npmcli/arborist/lib/arborist/reify.js +++ b/node_modules/@npmcli/arborist/lib/arborist/reify.js @@ -400,7 +400,7 @@ module.exports = cls => class Reifier extends cls { // and no 'bundled: true' setting. // Do the best with what we have, or else remove it from the tree // entirely, since we can't possibly reify it. - const res = node.resolved ? this[_registryResolved](node.resolved) + const res = node.resolved ? `${node.name}@${this[_registryResolved](node.resolved)}` : node.package.name && node.version ? `${node.package.name}@${node.version}` : null diff --git a/node_modules/@npmcli/arborist/package.json b/node_modules/@npmcli/arborist/package.json index 0bfeb079e9edd..4172b9323f4d5 100644 --- a/node_modules/@npmcli/arborist/package.json +++ b/node_modules/@npmcli/arborist/package.json @@ -1,6 +1,6 @@ { "name": "@npmcli/arborist", - "version": "1.0.0", + "version": "1.0.2", "description": "Manage node_modules trees", "dependencies": { "@npmcli/installed-package-contents": "^1.0.5", diff --git a/package-lock.json b/package-lock.json index 7d3139926b903..d099ca8cb7412 100644 --- a/package-lock.json +++ b/package-lock.json @@ -47,6 +47,7 @@ "mkdirp", "mkdirp-infer-owner", "ms", + "node-gyp", "nopt", "npm-audit-report", "npm-package-arg", @@ -72,12 +73,11 @@ "uuid", "validate-npm-package-name", "which", - "write-file-atomic", - "node-gyp" + "write-file-atomic" ], "license": "Artistic-2.0", "dependencies": { - "@npmcli/arborist": "^1.0.0", + "@npmcli/arborist": "^1.0.2", "@npmcli/ci-detect": "^1.2.0", "@npmcli/config": "^1.2.1", "@npmcli/run-script": "^1.7.0", @@ -381,9 +381,9 @@ } }, "node_modules/@npmcli/arborist": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/arborist/-/arborist-1.0.0.tgz", - "integrity": "sha512-SZgRAltGY/+hpiHP1a/DtJM8rND8An02yQGgp6wV2Cmp9lcQ/gWTT+dTqW1F3Hbw1oP6voHePdTzv4f77cj7uQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@npmcli/arborist/-/arborist-1.0.2.tgz", + "integrity": "sha512-YBlU3HcRI7Q1dVQa4ljf/ifKxbAZELe+e66NP/vNFrv6pv4oVrOOkBrMCC/0tareDKKpxtHoGS5oVFwCF8ZzGg==", "inBundle": true, "dependencies": { "@npmcli/installed-package-contents": "^1.0.5", @@ -8477,9 +8477,9 @@ } }, "@npmcli/arborist": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/arborist/-/arborist-1.0.0.tgz", - "integrity": "sha512-SZgRAltGY/+hpiHP1a/DtJM8rND8An02yQGgp6wV2Cmp9lcQ/gWTT+dTqW1F3Hbw1oP6voHePdTzv4f77cj7uQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@npmcli/arborist/-/arborist-1.0.2.tgz", + "integrity": "sha512-YBlU3HcRI7Q1dVQa4ljf/ifKxbAZELe+e66NP/vNFrv6pv4oVrOOkBrMCC/0tareDKKpxtHoGS5oVFwCF8ZzGg==", "requires": { "@npmcli/installed-package-contents": "^1.0.5", "@npmcli/map-workspaces": "^1.0.1", diff --git a/package.json b/package.json index 5228b153da5c6..37e7ca31282e7 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,7 @@ "./package.json": "./package.json" }, "dependencies": { - "@npmcli/arborist": "^1.0.0", + "@npmcli/arborist": "^1.0.2", "@npmcli/ci-detect": "^1.2.0", "@npmcli/config": "^1.2.1", "@npmcli/run-script": "^1.7.0",