diff options
author | Gar <gar+gh@danger.computer> | 2021-09-28 20:05:08 +0300 |
---|---|---|
committer | Gar <gar+gh@danger.computer> | 2021-09-28 20:05:08 +0300 |
commit | e94ddeaca1e75ecc8f54ebcb3df222965e3635d1 (patch) | |
tree | b2ec351450e8392bebd0410fe6367101a1e1b4b2 /node_modules/@npmcli/arborist/lib/place-dep.js | |
parent | 075fe50565ae5c66df727cdd7df9dd5ed8cd4015 (diff) |
deps: @npmcli/arborist@2.9.0
* fix: avoid infinite loops in peer dep replacements
* fix: use Intl.Collator for string sorting when available
* feat(vuln): expose isDirect
Diffstat (limited to 'node_modules/@npmcli/arborist/lib/place-dep.js')
-rw-r--r-- | node_modules/@npmcli/arborist/lib/place-dep.js | 63 |
1 files changed, 55 insertions, 8 deletions
diff --git a/node_modules/@npmcli/arborist/lib/place-dep.js b/node_modules/@npmcli/arborist/lib/place-dep.js index d7cc7d935..6edd94a38 100644 --- a/node_modules/@npmcli/arborist/lib/place-dep.js +++ b/node_modules/@npmcli/arborist/lib/place-dep.js @@ -7,6 +7,7 @@ // and saves a set of what was placed and what needs re-evaluation as // a result. +const localeCompare = require('@isaacs/string-locale-compare')('en') const log = require('proc-log') const deepestNestingTarget = require('./deepest-nesting-target.js') const CanPlaceDep = require('./can-place-dep.js') @@ -63,6 +64,8 @@ class PlaceDep { this.parent = parent this.peerConflict = null + this.needEvaluation = new Set() + this.checks = new Map() this.place() @@ -365,6 +368,8 @@ class PlaceDep { } replaceOldDep () { + const target = this.oldDep.parent + // XXX handle replacing an entire peer group? // what about cases where we need to push some other peer groups deeper // into the tree? all the tree updating should be done here, and track @@ -383,8 +388,47 @@ class PlaceDep { oldDeps.push(...gatherDepSet([edge.to], e => e.to !== edge.to)) } } + + // gather all peer edgesIn which are at this level, and will not be + // satisfied by the new dependency. Those are the peer sets that need + // to be either warned about (if they cannot go deeper), or removed and + // re-placed (if they can). + const prunePeerSets = [] + for (const edge of this.oldDep.edgesIn) { + if (this.placed.satisfies(edge) || + !edge.peer || + edge.from.parent !== target || + edge.overridden) { + // not a peer dep, not invalid, or not from this level, so it's fine + // to just let it re-evaluate as a problemEdge later, or let it be + // satisfied by the new dep being placed. + continue + } + for (const entryEdge of peerEntrySets(edge.from).keys()) { + // either this one needs to be pruned and re-evaluated, or marked + // as overridden and warned about. If the entryEdge comes in from + // the root, then we have to leave it alone, and in that case, it + // will have already warned or crashed by getting to this point. + const entryNode = entryEdge.to + const deepestTarget = deepestNestingTarget(entryNode) + if (deepestTarget !== target && !entryEdge.from.isRoot) { + prunePeerSets.push(...gatherDepSet([entryNode], e => { + return e.to !== entryNode && !e.overridden + })) + } else { + this.warnPeerConflict(edge, this.dep) + } + } + } + this.placed.replace(this.oldDep) this.pruneForReplacement(this.placed, oldDeps) + for (const dep of prunePeerSets) { + for (const edge of dep.edgesIn) { + this.needEvaluation.add(edge.from) + } + dep.root = null + } } pruneForReplacement (node, oldDeps) { @@ -430,7 +474,7 @@ class PlaceDep { // sort these so that they're deterministically ordered // otherwise, resulting tree shape is dependent on the order // in which they happened to be resolved. - const nodeSort = (a, b) => a.location.localeCompare(b.location, 'en') + const nodeSort = (a, b) => localeCompare(a.location, b.location) const children = [...node.children.values()].sort(nodeSort) for (const child of children) { @@ -485,19 +529,22 @@ class PlaceDep { return false } - warnPeerConflict () { - this.edge.overridden = true - const expl = this.explainPeerConflict() + warnPeerConflict (edge, dep) { + edge = edge || this.edge + dep = dep || this.dep + edge.overridden = true + const expl = this.explainPeerConflict(edge, dep) log.warn('ERESOLVE', 'overriding peer dependency', expl) } - failPeerConflict () { - const expl = this.explainPeerConflict() + failPeerConflict (edge, dep) { + edge = edge || this.top.edge + dep = dep || this.top.dep + const expl = this.explainPeerConflict(edge, dep) throw Object.assign(new Error('could not resolve'), expl) } - explainPeerConflict () { - const { edge, dep } = this.top + explainPeerConflict (edge, dep) { const { from: node } = edge const curNode = node.resolve(edge.name) |