@npmcli/arborist 2.8.2 → 2.8.3

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.
Files changed (49) hide show
  1. package/bin/actual.js +4 -2
  2. package/bin/audit.js +12 -6
  3. package/bin/dedupe.js +6 -3
  4. package/bin/funding.js +4 -2
  5. package/bin/ideal.js +2 -1
  6. package/bin/lib/logging.js +4 -3
  7. package/bin/lib/options.js +14 -12
  8. package/bin/lib/timers.js +6 -3
  9. package/bin/license.js +9 -5
  10. package/bin/prune.js +6 -3
  11. package/bin/reify.js +6 -3
  12. package/bin/virtual.js +4 -2
  13. package/lib/add-rm-pkg-deps.js +25 -14
  14. package/lib/arborist/audit.js +2 -1
  15. package/lib/arborist/build-ideal-tree.js +129 -68
  16. package/lib/arborist/deduper.js +2 -1
  17. package/lib/arborist/index.js +8 -4
  18. package/lib/arborist/load-actual.js +28 -13
  19. package/lib/arborist/load-virtual.js +34 -18
  20. package/lib/arborist/load-workspaces.js +4 -2
  21. package/lib/arborist/rebuild.js +31 -16
  22. package/lib/arborist/reify.js +153 -76
  23. package/lib/audit-report.js +42 -22
  24. package/lib/calc-dep-flags.js +18 -9
  25. package/lib/can-place-dep.js +56 -28
  26. package/lib/case-insensitive-map.js +4 -2
  27. package/lib/consistent-resolve.js +2 -1
  28. package/lib/deepest-nesting-target.js +4 -2
  29. package/lib/dep-valid.js +8 -4
  30. package/lib/diff.js +74 -22
  31. package/lib/edge.js +26 -13
  32. package/lib/gather-dep-set.js +2 -1
  33. package/lib/inventory.js +12 -6
  34. package/lib/link.js +14 -9
  35. package/lib/node.js +216 -113
  36. package/lib/optional-set.js +4 -2
  37. package/lib/peer-entry-sets.js +10 -5
  38. package/lib/place-dep.js +56 -29
  39. package/lib/printable.js +41 -21
  40. package/lib/realpath.js +12 -6
  41. package/lib/shrinkwrap.js +162 -89
  42. package/lib/signal-handling.js +6 -3
  43. package/lib/spec-from-lock.js +7 -4
  44. package/lib/tracker.js +24 -18
  45. package/lib/tree-check.js +12 -6
  46. package/lib/version-from-tgz.js +4 -2
  47. package/lib/vuln.js +28 -16
  48. package/lib/yarn-lock.js +27 -15
  49. package/package.json +7 -10
@@ -63,8 +63,9 @@ class AuditReport extends Map {
63
63
  prod = false
64
64
  }
65
65
  }
66
- if (prod)
66
+ if (prod) {
67
67
  dependencies.prod++
68
+ }
68
69
  }
69
70
 
70
71
  // if it doesn't have any topVulns, then it's fixable with audit fix
@@ -104,8 +105,9 @@ class AuditReport extends Map {
104
105
  async run () {
105
106
  this.report = await this[_getReport]()
106
107
  this.log.silly('audit report', this.report)
107
- if (this.report)
108
+ if (this.report) {
108
109
  await this[_init]()
110
+ }
109
111
  return this
110
112
  }
111
113
 
@@ -119,8 +121,9 @@ class AuditReport extends Map {
119
121
 
120
122
  const promises = []
121
123
  for (const [name, advisories] of Object.entries(this.report)) {
122
- for (const advisory of advisories)
124
+ for (const advisory of advisories) {
123
125
  promises.push(this.calculator.calculate(name, advisory))
126
+ }
124
127
  }
125
128
 
126
129
  // now the advisories are calculated with a set of versions
@@ -136,43 +139,51 @@ class AuditReport extends Map {
136
139
  // adding multiple advisories with the same range is fine, but no
137
140
  // need to search for nodes we already would have added.
138
141
  const k = `${name}@${range}`
139
- if (seen.has(k))
142
+ if (seen.has(k)) {
140
143
  continue
144
+ }
141
145
 
142
146
  seen.add(k)
143
147
 
144
148
  const vuln = this.get(name) || new Vuln({ name, advisory })
145
- if (this.has(name))
149
+ if (this.has(name)) {
146
150
  vuln.addAdvisory(advisory)
151
+ }
147
152
  super.set(name, vuln)
148
153
 
149
154
  const p = []
150
155
  for (const node of this.tree.inventory.query('packageName', name)) {
151
- if (!shouldAudit(node, this[_omit], this.filterSet))
156
+ if (!shouldAudit(node, this[_omit], this.filterSet)) {
152
157
  continue
158
+ }
153
159
 
154
160
  // if not vulnerable by this advisory, keep searching
155
- if (!advisory.testVersion(node.version))
161
+ if (!advisory.testVersion(node.version)) {
156
162
  continue
163
+ }
157
164
 
158
165
  // we will have loaded the source already if this is a metavuln
159
- if (advisory.type === 'metavuln')
166
+ if (advisory.type === 'metavuln') {
160
167
  vuln.addVia(this.get(advisory.dependency))
168
+ }
161
169
 
162
170
  // already marked this one, no need to do it again
163
- if (vuln.nodes.has(node))
171
+ if (vuln.nodes.has(node)) {
164
172
  continue
173
+ }
165
174
 
166
175
  // haven't marked this one yet. get its dependents.
167
176
  vuln.nodes.add(node)
168
177
  for (const { from: dep, spec } of node.edgesIn) {
169
- if (dep.isTop && !vuln.topNodes.has(dep))
178
+ if (dep.isTop && !vuln.topNodes.has(dep)) {
170
179
  this[_checkTopNode](dep, vuln, spec)
171
- else {
180
+ } else {
172
181
  // calculate a metavuln, if necessary
173
- p.push(this.calculator.calculate(dep.packageName, advisory).then(meta => {
174
- if (meta.testVersion(dep.version, spec))
182
+ const calc = this.calculator.calculate(dep.packageName, advisory)
183
+ p.push(calc.then(meta => {
184
+ if (meta.testVersion(dep.version, spec)) {
175
185
  advisories.add(meta)
186
+ }
176
187
  }))
177
188
  }
178
189
  }
@@ -193,9 +204,11 @@ class AuditReport extends Map {
193
204
  // the nodes it references, then remove it from the advisory list.
194
205
  // happens when using omit with old audit endpoint.
195
206
  for (const advisory of vuln.advisories) {
196
- const relevant = [...vuln.nodes].some(n => advisory.testVersion(n.version))
197
- if (!relevant)
207
+ const relevant = [...vuln.nodes]
208
+ .some(n => advisory.testVersion(n.version))
209
+ if (!relevant) {
198
210
  vuln.deleteAdvisory(advisory)
211
+ }
199
212
  }
200
213
  }
201
214
  process.emit('timeEnd', 'auditReport:init')
@@ -221,18 +234,21 @@ class AuditReport extends Map {
221
234
  // this will always be set to at least {name, versions:{}}
222
235
  const paku = vuln.packument
223
236
 
224
- if (!vuln.testSpec(spec))
237
+ if (!vuln.testSpec(spec)) {
225
238
  return true
239
+ }
226
240
 
227
241
  // similarly, even if we HAVE a packument, but we're looking for it
228
242
  // somewhere other than the registry, and we got something vulnerable,
229
243
  // then we're stuck with it.
230
244
  const specObj = npa(spec)
231
- if (!specObj.registry)
245
+ if (!specObj.registry) {
232
246
  return false
247
+ }
233
248
 
234
- if (specObj.subSpec)
249
+ if (specObj.subSpec) {
235
250
  spec = specObj.subSpec.rawSpec
251
+ }
236
252
 
237
253
  // We don't provide fixes for top nodes other than root, but we
238
254
  // still check to see if the node is fixable with a different version,
@@ -287,8 +303,9 @@ class AuditReport extends Map {
287
303
 
288
304
  async [_getReport] () {
289
305
  // if we're not auditing, just return false
290
- if (this.options.audit === false || this.tree.inventory.size === 1)
306
+ if (this.options.audit === false || this.tree.inventory.size === 1) {
291
307
  return null
308
+ }
292
309
 
293
310
  process.emit('time', 'auditReport:getReport')
294
311
  try {
@@ -299,8 +316,9 @@ class AuditReport extends Map {
299
316
 
300
317
  // no sense asking if we don't have anything to audit,
301
318
  // we know it'll be empty
302
- if (!Object.keys(body).length)
319
+ if (!Object.keys(body).length) {
303
320
  return null
321
+ }
304
322
 
305
323
  const res = await fetch('/-/npm/v1/security/advisories/bulk', {
306
324
  ...this.options,
@@ -353,13 +371,15 @@ const prepareBulkData = (tree, omit, filterSet) => {
353
371
  for (const name of tree.inventory.query('packageName')) {
354
372
  const set = new Set()
355
373
  for (const node of tree.inventory.query('packageName', name)) {
356
- if (!shouldAudit(node, omit, filterSet))
374
+ if (!shouldAudit(node, omit, filterSet)) {
357
375
  continue
376
+ }
358
377
 
359
378
  set.add(node.version)
360
379
  }
361
- if (set.size)
380
+ if (set.size) {
362
381
  payload[name] = [...set]
382
+ }
363
383
  }
364
384
  return payload
365
385
  }
@@ -11,7 +11,8 @@ const calcDepFlags = (tree, resetRoot = true) => {
11
11
  tree,
12
12
  visit: node => calcDepFlagsStep(node),
13
13
  filter: node => node,
14
- getChildren: (node, tree) => [...tree.edgesOut.values()].map(edge => edge.to),
14
+ getChildren: (node, tree) =>
15
+ [...tree.edgesOut.values()].map(edge => edge.to),
15
16
  })
16
17
  return ret
17
18
  }
@@ -39,8 +40,9 @@ const calcDepFlagsStep = (node) => {
39
40
 
40
41
  node.edgesOut.forEach(({peer, optional, dev, to}) => {
41
42
  // if the dep is missing, then its flags are already maximally unset
42
- if (!to)
43
+ if (!to) {
43
44
  return
45
+ }
44
46
 
45
47
  // everything with any kind of edge into it is not extraneous
46
48
  to.extraneous = false
@@ -59,28 +61,34 @@ const calcDepFlagsStep = (node) => {
59
61
  !node.optional && !optional
60
62
  const unsetPeer = !node.peer && !peer
61
63
 
62
- if (unsetPeer)
64
+ if (unsetPeer) {
63
65
  unsetFlag(to, 'peer')
66
+ }
64
67
 
65
- if (unsetDevOpt)
68
+ if (unsetDevOpt) {
66
69
  unsetFlag(to, 'devOptional')
70
+ }
67
71
 
68
- if (unsetDev)
72
+ if (unsetDev) {
69
73
  unsetFlag(to, 'dev')
74
+ }
70
75
 
71
- if (unsetOpt)
76
+ if (unsetOpt) {
72
77
  unsetFlag(to, 'optional')
78
+ }
73
79
  })
74
80
 
75
81
  return node
76
82
  }
77
83
 
78
84
  const resetParents = (node, flag) => {
79
- if (node[flag])
85
+ if (node[flag]) {
80
86
  return
87
+ }
81
88
 
82
- for (let p = node; p && (p === node || p[flag]); p = p.resolveParent)
89
+ for (let p = node; p && (p === node || p[flag]); p = p.resolveParent) {
83
90
  p[flag] = false
91
+ }
84
92
  }
85
93
 
86
94
  // typically a short walk, since it only traverses deps that
@@ -92,8 +100,9 @@ const unsetFlag = (node, flag) => {
92
100
  tree: node,
93
101
  visit: node => {
94
102
  node.extraneous = node[flag] = false
95
- if (node.isLink)
103
+ if (node.isLink) {
96
104
  node.target.extraneous = node.target[flag] = false
105
+ }
97
106
  },
98
107
  getChildren: node => [...node.target.edgesOut.values()]
99
108
  .filter(edge => edge.to && edge.to[flag] &&
@@ -64,14 +64,17 @@ class CanPlaceDep {
64
64
  } = options
65
65
 
66
66
  debug(() => {
67
- if (!dep)
67
+ if (!dep) {
68
68
  throw new Error('no dep provided to CanPlaceDep')
69
+ }
69
70
 
70
- if (!target)
71
+ if (!target) {
71
72
  throw new Error('no target provided to CanPlaceDep')
73
+ }
72
74
 
73
- if (!edge)
75
+ if (!edge) {
74
76
  throw new Error('no edge provided to CanPlaceDep')
77
+ }
75
78
 
76
79
  this._treeSnapshot = JSON.stringify([...target.root.inventory.entries()]
77
80
  .map(([loc, {packageName, version, resolved}]) => {
@@ -108,8 +111,9 @@ class CanPlaceDep {
108
111
  this.edgeOverride = !dep.satisfies(edge)
109
112
 
110
113
  this.canPlace = this.checkCanPlace()
111
- if (!this.canPlaceSelf)
114
+ if (!this.canPlaceSelf) {
112
115
  this.canPlaceSelf = this.canPlace
116
+ }
113
117
 
114
118
  debug(() => {
115
119
  const treeSnapshot = JSON.stringify([...target.root.inventory.entries()]
@@ -131,15 +135,18 @@ class CanPlaceDep {
131
135
 
132
136
  // if the dep failed to load, we're going to fail the build or
133
137
  // prune it out anyway, so just move forward placing/replacing it.
134
- if (dep.errors.length)
138
+ if (dep.errors.length) {
135
139
  return current ? REPLACE : OK
140
+ }
136
141
 
137
142
  // cannot place peers inside their dependents, except for tops
138
- if (targetEdge && targetEdge.peer && !target.isTop)
143
+ if (targetEdge && targetEdge.peer && !target.isTop) {
139
144
  return CONFLICT
145
+ }
140
146
 
141
- if (targetEdge && !dep.satisfies(targetEdge) && targetEdge !== this.edge)
147
+ if (targetEdge && !dep.satisfies(targetEdge) && targetEdge !== this.edge) {
142
148
  return CONFLICT
149
+ }
143
150
 
144
151
  return current ? this.checkCanPlaceCurrent() : this.checkCanPlaceNoCurrent()
145
152
  }
@@ -150,8 +157,9 @@ class CanPlaceDep {
150
157
  const { preferDedupe, explicitRequest, current, target, edge, dep } = this
151
158
 
152
159
  if (dep.matches(current)) {
153
- if (current.satisfies(edge) || this.edgeOverride)
160
+ if (current.satisfies(edge) || this.edgeOverride) {
154
161
  return explicitRequest ? REPLACE : KEEP
162
+ }
155
163
  }
156
164
 
157
165
  const { version: curVer } = current
@@ -163,19 +171,22 @@ class CanPlaceDep {
163
171
  * but it is theoretically possible if peer deps are pinned. In
164
172
  * that case we treat it like any other conflict, and keep trying */
165
173
  const cpp = this.canPlacePeers(REPLACE)
166
- if (cpp !== CONFLICT)
174
+ if (cpp !== CONFLICT) {
167
175
  return cpp
176
+ }
168
177
  }
169
178
 
170
179
  // ok, can't replace the current with new one, but maybe current is ok?
171
- if (current.satisfies(edge) && (!explicitRequest || preferDedupe))
180
+ if (current.satisfies(edge) && (!explicitRequest || preferDedupe)) {
172
181
  return KEEP
182
+ }
173
183
 
174
184
  // if we prefer deduping, then try replacing newer with older
175
185
  if (preferDedupe && !tryReplace && dep.canReplace(current)) {
176
186
  const cpp = this.canPlacePeers(REPLACE)
177
- if (cpp !== CONFLICT)
187
+ if (cpp !== CONFLICT) {
178
188
  return cpp
189
+ }
179
190
  }
180
191
 
181
192
  // Check for interesting cases!
@@ -185,29 +196,33 @@ class CanPlaceDep {
185
196
  const myDeepest = this.deepestNestingTarget
186
197
 
187
198
  // ok, i COULD be placed deeper, so leave the current one alone.
188
- if (target !== myDeepest)
199
+ if (target !== myDeepest) {
189
200
  return CONFLICT
201
+ }
190
202
 
191
203
  // if we are not checking a peerDep, then we MUST place it here, in the
192
204
  // target that has a non-peer dep on it.
193
- if (!edge.peer && target === edge.from)
205
+ if (!edge.peer && target === edge.from) {
194
206
  return this.canPlacePeers(REPLACE)
207
+ }
195
208
 
196
209
  // if we aren't placing a peer in a set, then we're done here.
197
210
  // This is ignored because it SHOULD be redundant, as far as I can tell,
198
211
  // with the deepest target and target===edge.from tests. But until we
199
212
  // can prove that isn't possible, this condition is here for safety.
200
213
  /* istanbul ignore if - allegedly impossible */
201
- if (!this.parent && !edge.peer)
214
+ if (!this.parent && !edge.peer) {
202
215
  return CONFLICT
216
+ }
203
217
 
204
218
  // check the deps in the peer group for each edge into that peer group
205
219
  // if ALL of them can be pushed deeper, or if it's ok to replace its
206
220
  // members with the contents of the new peer group, then we're good.
207
221
  let canReplace = true
208
222
  for (const [entryEdge, currentPeers] of peerEntrySets(current)) {
209
- if (entryEdge === this.edge || entryEdge === this.peerEntryEdge)
223
+ if (entryEdge === this.edge || entryEdge === this.peerEntryEdge) {
210
224
  continue
225
+ }
211
226
 
212
227
  // First, see if it's ok to just replace the peerSet entirely.
213
228
  // we do this by walking out from the entryEdge, because in a case like
@@ -231,8 +246,9 @@ class CanPlaceDep {
231
246
  const entryNode = entryEdge.to
232
247
  const entryRep = dep.parent.children.get(entryNode.name)
233
248
  if (entryRep) {
234
- if (entryRep.canReplace(entryNode, dep.parent.children.keys()))
249
+ if (entryRep.canReplace(entryNode, dep.parent.children.keys())) {
235
250
  continue
251
+ }
236
252
  }
237
253
 
238
254
  let canClobber = !entryRep
@@ -240,12 +256,14 @@ class CanPlaceDep {
240
256
  const peerReplacementWalk = new Set([entryNode])
241
257
  OUTER: for (const currentPeer of peerReplacementWalk) {
242
258
  for (const edge of currentPeer.edgesOut.values()) {
243
- if (!edge.peer || !edge.valid)
259
+ if (!edge.peer || !edge.valid) {
244
260
  continue
261
+ }
245
262
  const rep = dep.parent.children.get(edge.name)
246
263
  if (!rep) {
247
- if (edge.to)
264
+ if (edge.to) {
248
265
  peerReplacementWalk.add(edge.to)
266
+ }
249
267
  continue
250
268
  }
251
269
  if (!rep.satisfies(edge)) {
@@ -255,14 +273,16 @@ class CanPlaceDep {
255
273
  }
256
274
  }
257
275
  }
258
- if (canClobber)
276
+ if (canClobber) {
259
277
  continue
278
+ }
260
279
 
261
280
  // ok, we can't replace, but maybe we can nest the current set deeper?
262
281
  let canNestCurrent = true
263
282
  for (const currentPeer of currentPeers) {
264
- if (!canNestCurrent)
283
+ if (!canNestCurrent) {
265
284
  break
285
+ }
266
286
 
267
287
  // still possible to nest this peerSet
268
288
  const curDeep = deepestNestingTarget(entryEdge.from, currentPeer.name)
@@ -270,14 +290,16 @@ class CanPlaceDep {
270
290
  canNestCurrent = false
271
291
  canReplace = false
272
292
  }
273
- if (canNestCurrent)
293
+ if (canNestCurrent) {
274
294
  continue
295
+ }
275
296
  }
276
297
  }
277
298
 
278
299
  // if we can nest or replace all the current peer groups, we can replace.
279
- if (canReplace)
300
+ if (canReplace) {
280
301
  return this.canPlacePeers(REPLACE)
302
+ }
281
303
 
282
304
  return CONFLICT
283
305
  }
@@ -293,8 +315,9 @@ class CanPlaceDep {
293
315
  if (current) {
294
316
  for (const edge of current.edgesIn.values()) {
295
317
  if (edge.from.isDescendantOf(target) && edge.valid) {
296
- if (!dep.satisfies(edge))
318
+ if (!dep.satisfies(edge)) {
297
319
  return CONFLICT
320
+ }
298
321
  }
299
322
  }
300
323
  }
@@ -316,8 +339,9 @@ class CanPlaceDep {
316
339
  get allChildren () {
317
340
  const set = new Set(this.children)
318
341
  for (const child of set) {
319
- for (const grandchild of child.children)
342
+ for (const grandchild of child.children) {
320
343
  set.add(grandchild)
344
+ }
321
345
  }
322
346
  return [...set]
323
347
  }
@@ -329,15 +353,17 @@ class CanPlaceDep {
329
353
  // check if peers can go here. returns state or CONFLICT
330
354
  canPlacePeers (state) {
331
355
  this.canPlaceSelf = state
332
- if (this._canPlacePeers)
356
+ if (this._canPlacePeers) {
333
357
  return this._canPlacePeers
358
+ }
334
359
 
335
360
  // TODO: represent peerPath in ERESOLVE error somehow?
336
361
  const peerPath = [...this.peerPath, this.dep]
337
362
  let sawConflict = false
338
363
  for (const peerEdge of this.dep.edgesOut.values()) {
339
- if (!peerEdge.peer || !peerEdge.to || peerPath.includes(peerEdge.to))
364
+ if (!peerEdge.peer || !peerEdge.to || peerPath.includes(peerEdge.to)) {
340
365
  continue
366
+ }
341
367
  const peer = peerEdge.to
342
368
  // it may be the case that the *initial* dep can be nested, but a peer
343
369
  // of that dep needs to be placed shallower, because the target has
@@ -354,13 +380,15 @@ class CanPlaceDep {
354
380
  })
355
381
  /* istanbul ignore next */
356
382
  debug(() => {
357
- if (this.children.some(c => c.dep === cpp.dep))
383
+ if (this.children.some(c => c.dep === cpp.dep)) {
358
384
  throw new Error('checking same dep repeatedly')
385
+ }
359
386
  })
360
387
  this.children.push(cpp)
361
388
 
362
- if (cpp.canPlace === CONFLICT)
389
+ if (cpp.canPlace === CONFLICT) {
363
390
  sawConflict = true
391
+ }
364
392
  }
365
393
 
366
394
  this._canPlacePeers = sawConflict ? CONFLICT : state
@@ -10,8 +10,9 @@ module.exports = class Map extends OGMap {
10
10
  constructor (items = []) {
11
11
  super()
12
12
  this[_keys] = new OGMap()
13
- for (const [key, val] of items)
13
+ for (const [key, val] of items) {
14
14
  this.set(key, val)
15
+ }
15
16
  }
16
17
 
17
18
  [_normKey] (key) {
@@ -26,8 +27,9 @@ module.exports = class Map extends OGMap {
26
27
 
27
28
  set (key, val) {
28
29
  const normKey = this[_normKey](key)
29
- if (this[_keys].has(normKey))
30
+ if (this[_keys].has(normKey)) {
30
31
  super.delete(this[_keys].get(normKey))
32
+ }
31
33
  this[_keys].set(normKey, key)
32
34
  return super.set(key, val)
33
35
  }
@@ -5,8 +5,9 @@
5
5
  const npa = require('npm-package-arg')
6
6
  const relpath = require('./relpath.js')
7
7
  const consistentResolve = (resolved, fromPath, toPath, relPaths = false) => {
8
- if (!resolved)
8
+ if (!resolved) {
9
9
  return null
10
+ }
10
11
 
11
12
  try {
12
13
  const hostedOpt = { noCommittish: false }
@@ -5,11 +5,13 @@
5
5
  const deepestNestingTarget = (start, name) => {
6
6
  for (const target of start.ancestry()) {
7
7
  // note: this will skip past the first target if edge is peer
8
- if (target.isProjectRoot || !target.resolveParent || target.globalTop)
8
+ if (target.isProjectRoot || !target.resolveParent || target.globalTop) {
9
9
  return target
10
+ }
10
11
  const targetEdge = target.edgesOut.get(name)
11
- if (!targetEdge || !targetEdge.peer)
12
+ if (!targetEdge || !targetEdge.peer) {
12
13
  return target
14
+ }
13
15
  }
14
16
  }
15
17
 
package/lib/dep-valid.js CHANGED
@@ -44,8 +44,9 @@ const depValid = (child, requested, requestor) => {
44
44
 
45
45
  switch (requested.type) {
46
46
  case 'range':
47
- if (requested.fetchSpec === '*')
47
+ if (requested.fetchSpec === '*') {
48
48
  return true
49
+ }
49
50
  // fallthrough
50
51
  case 'version':
51
52
  // if it's a version or a range other than '*', semver it
@@ -108,17 +109,20 @@ const depValid = (child, requested, requestor) => {
108
109
  }
109
110
 
110
111
  const tarballValid = (child, requested, requestor) => {
111
- if (child.isLink)
112
+ if (child.isLink) {
112
113
  return false
114
+ }
113
115
 
114
- if (child.resolved)
116
+ if (child.resolved) {
115
117
  return child.resolved.replace(/\\/g, '/') === `file:${requested.fetchSpec.replace(/\\/g, '/')}`
118
+ }
116
119
 
117
120
  // if we have a legacy mutated package.json file. we can't be 100%
118
121
  // sure that it resolved to the same file, but if it was the same
119
122
  // request, that's a pretty good indicator of sameness.
120
- if (child.package._requested)
123
+ if (child.package._requested) {
121
124
  return child.package._requested.saveSpec === requested.saveSpec
125
+ }
122
126
 
123
127
  // ok, we're probably dealing with some legacy cruft here, not much
124
128
  // we can do at this point unfortunately.