@npmcli/arborist 2.8.2 → 2.9.0

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 +28 -15
  14. package/lib/arborist/audit.js +2 -1
  15. package/lib/arborist/build-ideal-tree.js +139 -72
  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 +37 -20
  20. package/lib/arborist/load-workspaces.js +4 -2
  21. package/lib/arborist/rebuild.js +34 -17
  22. package/lib/arborist/reify.js +153 -76
  23. package/lib/audit-report.js +44 -23
  24. package/lib/calc-dep-flags.js +18 -9
  25. package/lib/can-place-dep.js +59 -30
  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 +111 -37
  39. package/lib/printable.js +46 -25
  40. package/lib/realpath.js +12 -6
  41. package/lib/shrinkwrap.js +164 -90
  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 +44 -22
  48. package/lib/yarn-lock.js +34 -21
  49. package/package.json +8 -10
@@ -10,8 +10,9 @@
10
10
 
11
11
  const gatherDepSet = require('./gather-dep-set.js')
12
12
  const optionalSet = node => {
13
- if (!node.optional)
13
+ if (!node.optional) {
14
14
  return new Set()
15
+ }
15
16
 
16
17
  // start with the node, then walk up the dependency graph until we
17
18
  // get to the boundaries that define the optional set. since the
@@ -21,8 +22,9 @@ const optionalSet = node => {
21
22
  const set = new Set([node])
22
23
  for (const node of set) {
23
24
  for (const edge of node.edgesIn) {
24
- if (!edge.optional)
25
+ if (!edge.optional) {
25
26
  set.add(edge.from)
27
+ }
26
28
  }
27
29
  }
28
30
 
@@ -15,12 +15,14 @@ const peerEntrySets = node => {
15
15
  const unionSet = new Set([node])
16
16
  for (const node of unionSet) {
17
17
  for (const edge of node.edgesOut.values()) {
18
- if (edge.valid && edge.peer && edge.to)
18
+ if (edge.valid && edge.peer && edge.to) {
19
19
  unionSet.add(edge.to)
20
+ }
20
21
  }
21
22
  for (const edge of node.edgesIn) {
22
- if (edge.valid && edge.peer)
23
+ if (edge.valid && edge.peer) {
23
24
  unionSet.add(edge.from)
25
+ }
24
26
  }
25
27
  }
26
28
  const entrySets = new Map()
@@ -28,16 +30,18 @@ const peerEntrySets = node => {
28
30
  for (const edge of peer.edgesIn) {
29
31
  // if not valid, it doesn't matter anyway. either it's been previously
30
32
  // overridden, or it's the thing we're interested in replacing.
31
- if (!edge.valid)
33
+ if (!edge.valid) {
32
34
  continue
35
+ }
33
36
  // this is the entry point into the peer set
34
37
  if (!edge.peer || edge.from.isTop) {
35
38
  // get the subset of peer brought in by this peer entry edge
36
39
  const sub = new Set([peer])
37
40
  for (const peer of sub) {
38
41
  for (const edge of peer.edgesOut.values()) {
39
- if (edge.valid && edge.peer && edge.to)
42
+ if (edge.valid && edge.peer && edge.to) {
40
43
  sub.add(edge.to)
44
+ }
41
45
  }
42
46
  }
43
47
  // if this subset does not include the node we are focused on,
@@ -60,8 +64,9 @@ const peerEntrySets = node => {
60
64
  // Edge(a->b) => Set(b, d, e, f, g)
61
65
  // Edge(a->d) => Set(d, e, f, g)
62
66
  // }
63
- if (sub.has(node))
67
+ if (sub.has(node)) {
64
68
  entrySets.set(edge, sub)
69
+ }
65
70
  }
66
71
  }
67
72
  }
package/lib/place-dep.js CHANGED
@@ -7,6 +7,7 @@
7
7
  // and saves a set of what was placed and what needs re-evaluation as
8
8
  // a result.
9
9
 
10
+ const localeCompare = require('@isaacs/string-locale-compare')('en')
10
11
  const log = require('proc-log')
11
12
  const deepestNestingTarget = require('./deepest-nesting-target.js')
12
13
  const CanPlaceDep = require('./can-place-dep.js')
@@ -63,6 +64,8 @@ class PlaceDep {
63
64
  this.parent = parent
64
65
  this.peerConflict = null
65
66
 
67
+ this.needEvaluation = new Set()
68
+
66
69
  this.checks = new Map()
67
70
 
68
71
  this.place()
@@ -85,8 +88,9 @@ class PlaceDep {
85
88
  !edge.error &&
86
89
  !explicitRequest &&
87
90
  !updateNames.includes(edge.name) &&
88
- !this.isVulnerable(edge.to))
91
+ !this.isVulnerable(edge.to)) {
89
92
  return
93
+ }
90
94
 
91
95
  // walk up the tree until we hit either a top/root node, or a place
92
96
  // where the dep is not a peer dep.
@@ -110,8 +114,9 @@ class PlaceDep {
110
114
  // but we CAN place it under a, so the correct thing to do is keep
111
115
  // walking up the tree.
112
116
  const targetEdge = target.edgesOut.get(edge.name)
113
- if (!target.isTop && targetEdge && targetEdge.peer)
117
+ if (!target.isTop && targetEdge && targetEdge.peer) {
114
118
  continue
119
+ }
115
120
 
116
121
  const cpd = new CanPlaceDep({
117
122
  dep,
@@ -141,34 +146,39 @@ class PlaceDep {
141
146
  // should treat (b) and (d) as OK, and place them in the last place
142
147
  // where they did not themselves conflict, and skip c@2 if conflict
143
148
  // is ok by virtue of being forced or not ours and not strict.
144
- if (cpd.canPlaceSelf !== CONFLICT)
149
+ if (cpd.canPlaceSelf !== CONFLICT) {
145
150
  canPlaceSelf = cpd
151
+ }
146
152
 
147
153
  // we found a place this can go, along with all its peer friends.
148
154
  // we break when we get the first conflict
149
- if (cpd.canPlace !== CONFLICT)
155
+ if (cpd.canPlace !== CONFLICT) {
150
156
  canPlace = cpd
151
- else
157
+ } else {
152
158
  break
159
+ }
153
160
 
154
161
  // if it's a load failure, just plop it in the first place attempted,
155
162
  // since we're going to crash the build or prune it out anyway.
156
163
  // but, this will frequently NOT be a successful canPlace, because
157
164
  // it'll have no version or other information.
158
- if (dep.errors.length)
165
+ if (dep.errors.length) {
159
166
  break
167
+ }
160
168
 
161
169
  // nest packages like npm v1 and v2
162
170
  // very disk-inefficient
163
- if (legacyBundling)
171
+ if (legacyBundling) {
164
172
  break
173
+ }
165
174
 
166
175
  // when installing globally, or just in global style, we never place
167
176
  // deps above the first level.
168
177
  if (globalStyle) {
169
178
  const rp = target.resolveParent
170
- if (rp && rp.isProjectRoot)
179
+ if (rp && rp.isProjectRoot) {
171
180
  break
181
+ }
172
182
  }
173
183
  }
174
184
 
@@ -183,8 +193,9 @@ class PlaceDep {
183
193
  if (!canPlace) {
184
194
  // if not forced, or it's our dep, or strictPeerDeps is set, then
185
195
  // this is an ERESOLVE error.
186
- if (!this.conflictOk)
196
+ if (!this.conflictOk) {
187
197
  return this.failPeerConflict()
198
+ }
188
199
 
189
200
  // ok! we're gonna allow the conflict, but we should still warn
190
201
  // if we have a current, then we treat CONFLICT as a KEEP.
@@ -237,8 +248,9 @@ class PlaceDep {
237
248
  // it's a conflict. Treat it as a KEEP, but warn and move on.
238
249
  if (placementType === KEEP) {
239
250
  // this was an overridden peer dep
240
- if (edge.peer && !edge.valid)
251
+ if (edge.peer && !edge.valid) {
241
252
  this.warnPeerConflict()
253
+ }
242
254
 
243
255
  // if we get a KEEP in a update scenario, then we MAY have something
244
256
  // already duplicating this unnecessarily! For example:
@@ -287,21 +299,24 @@ class PlaceDep {
287
299
  })
288
300
 
289
301
  this.oldDep = target.children.get(this.name)
290
- if (this.oldDep)
302
+ if (this.oldDep) {
291
303
  this.replaceOldDep()
292
- else
304
+ } else {
293
305
  this.placed.parent = target
306
+ }
294
307
 
295
308
  // if it's an overridden peer dep, warn about it
296
- if (edge.peer && !this.placed.satisfies(edge))
309
+ if (edge.peer && !this.placed.satisfies(edge)) {
297
310
  this.warnPeerConflict()
311
+ }
298
312
 
299
313
  // If the edge is not an error, then we're updating something, and
300
314
  // MAY end up putting a better/identical node further up the tree in
301
315
  // a way that causes an unnecessary duplication. If so, remove the
302
316
  // now-unnecessary node.
303
- if (edge.valid && edge.to && edge.to !== this.placed)
317
+ if (edge.valid && edge.to && edge.to !== this.placed) {
304
318
  this.pruneDedupable(edge.to, false)
319
+ }
305
320
 
306
321
  // in case we just made some duplicates that can be removed,
307
322
  // prune anything deeper in the tree that can be replaced by this
@@ -310,8 +325,9 @@ class PlaceDep {
310
325
  this.pruneDedupable(node, false)
311
326
  // only walk the direct children of the ones we kept
312
327
  if (node.root === target.root) {
313
- for (const kid of node.children.values())
328
+ for (const kid of node.children.values()) {
314
329
  this.pruneDedupable(kid, false)
330
+ }
315
331
  }
316
332
  }
317
333
  }
@@ -323,8 +339,9 @@ class PlaceDep {
323
339
  // otherwise they'd be gone and the peer set would change throughout
324
340
  // this loop.
325
341
  for (const peerEdge of this.placed.edgesOut.values()) {
326
- if (peerEdge.valid || !peerEdge.peer || peerEdge.overridden)
342
+ if (peerEdge.valid || !peerEdge.peer || peerEdge.overridden) {
327
343
  continue
344
+ }
328
345
 
329
346
  const peer = virtualRoot.children.get(peerEdge.name)
330
347
 
@@ -332,12 +349,14 @@ class PlaceDep {
332
349
  // it's an optional peer dep. If it's not being properly met (ie,
333
350
  // peerEdge.valid is false), then this is likely heading for an
334
351
  // ERESOLVE error, unless it can walk further up the tree.
335
- if (!peer)
352
+ if (!peer) {
336
353
  continue
354
+ }
337
355
 
338
356
  // overridden peerEdge, just accept what's there already
339
- if (!peer.satisfies(peerEdge))
357
+ if (!peer.satisfies(peerEdge)) {
340
358
  continue
359
+ }
341
360
 
342
361
  this.children.push(new PlaceDep({
343
362
  parent: this,
@@ -349,6 +368,8 @@ class PlaceDep {
349
368
  }
350
369
 
351
370
  replaceOldDep () {
371
+ const target = this.oldDep.parent
372
+
352
373
  // XXX handle replacing an entire peer group?
353
374
  // what about cases where we need to push some other peer groups deeper
354
375
  // into the tree? all the tree updating should be done here, and track
@@ -363,11 +384,51 @@ class PlaceDep {
363
384
  // later anyway.
364
385
  const oldDeps = []
365
386
  for (const [name, edge] of this.oldDep.edgesOut.entries()) {
366
- if (!this.placed.edgesOut.has(name) && edge.to)
387
+ if (!this.placed.edgesOut.has(name) && edge.to) {
367
388
  oldDeps.push(...gatherDepSet([edge.to], e => e.to !== edge.to))
389
+ }
368
390
  }
391
+
392
+ // gather all peer edgesIn which are at this level, and will not be
393
+ // satisfied by the new dependency. Those are the peer sets that need
394
+ // to be either warned about (if they cannot go deeper), or removed and
395
+ // re-placed (if they can).
396
+ const prunePeerSets = []
397
+ for (const edge of this.oldDep.edgesIn) {
398
+ if (this.placed.satisfies(edge) ||
399
+ !edge.peer ||
400
+ edge.from.parent !== target ||
401
+ edge.overridden) {
402
+ // not a peer dep, not invalid, or not from this level, so it's fine
403
+ // to just let it re-evaluate as a problemEdge later, or let it be
404
+ // satisfied by the new dep being placed.
405
+ continue
406
+ }
407
+ for (const entryEdge of peerEntrySets(edge.from).keys()) {
408
+ // either this one needs to be pruned and re-evaluated, or marked
409
+ // as overridden and warned about. If the entryEdge comes in from
410
+ // the root, then we have to leave it alone, and in that case, it
411
+ // will have already warned or crashed by getting to this point.
412
+ const entryNode = entryEdge.to
413
+ const deepestTarget = deepestNestingTarget(entryNode)
414
+ if (deepestTarget !== target && !entryEdge.from.isRoot) {
415
+ prunePeerSets.push(...gatherDepSet([entryNode], e => {
416
+ return e.to !== entryNode && !e.overridden
417
+ }))
418
+ } else {
419
+ this.warnPeerConflict(edge, this.dep)
420
+ }
421
+ }
422
+ }
423
+
369
424
  this.placed.replace(this.oldDep)
370
425
  this.pruneForReplacement(this.placed, oldDeps)
426
+ for (const dep of prunePeerSets) {
427
+ for (const edge of dep.edgesIn) {
428
+ this.needEvaluation.add(edge.from)
429
+ }
430
+ dep.root = null
431
+ }
371
432
  }
372
433
 
373
434
  pruneForReplacement (node, oldDeps) {
@@ -377,8 +438,9 @@ class PlaceDep {
377
438
  .filter(e => e.to && !e.valid).map(e => e.to))
378
439
  for (const dep of oldDeps) {
379
440
  const set = gatherDepSet([dep], e => e.to !== dep && e.valid)
380
- for (const dep of set)
441
+ for (const dep of set) {
381
442
  invalidDeps.add(dep)
443
+ }
382
444
  }
383
445
 
384
446
  // ignore dependency edges from the node being replaced, but
@@ -388,8 +450,9 @@ class PlaceDep {
388
450
  edge.from !== node && edge.to !== node && edge.valid)
389
451
 
390
452
  // now just delete whatever's left, because it's junk
391
- for (const dep of deps)
453
+ for (const dep of deps) {
392
454
  dep.root = null
455
+ }
393
456
  }
394
457
 
395
458
  // prune all the nodes in a branch of the tree that can be safely removed
@@ -402,24 +465,27 @@ class PlaceDep {
402
465
  // the dep set, except for this node we're deduping, so that we
403
466
  // also prune deps that would be made extraneous.
404
467
  const deps = gatherDepSet([node], e => e.to !== node && e.valid)
405
- for (const node of deps)
468
+ for (const node of deps) {
406
469
  node.root = null
470
+ }
407
471
  return
408
472
  }
409
473
  if (descend) {
410
474
  // sort these so that they're deterministically ordered
411
475
  // otherwise, resulting tree shape is dependent on the order
412
476
  // in which they happened to be resolved.
413
- const nodeSort = (a, b) => a.location.localeCompare(b.location, 'en')
477
+ const nodeSort = (a, b) => localeCompare(a.location, b.location)
414
478
 
415
479
  const children = [...node.children.values()].sort(nodeSort)
416
- for (const child of children)
480
+ for (const child of children) {
417
481
  this.pruneDedupable(child)
482
+ }
418
483
  const fsChildren = [...node.fsChildren].sort(nodeSort)
419
484
  for (const topNode of fsChildren) {
420
485
  const children = [...topNode.children.values()].sort(nodeSort)
421
- for (const child of children)
486
+ for (const child of children) {
422
487
  this.pruneDedupable(child)
488
+ }
423
489
  }
424
490
  }
425
491
  }
@@ -432,11 +498,13 @@ class PlaceDep {
432
498
  const { edge } = this.top
433
499
  const { from: node } = edge
434
500
 
435
- if (node.isWorkspace || node.isProjectRoot)
501
+ if (node.isWorkspace || node.isProjectRoot) {
436
502
  return true
503
+ }
437
504
 
438
- if (!edge.peer)
505
+ if (!edge.peer) {
439
506
  return false
507
+ }
440
508
 
441
509
  // re-entry case. check if any non-peer edges come from the project,
442
510
  // or any entryEdges on peer groups are from the root.
@@ -446,32 +514,37 @@ class PlaceDep {
446
514
  hasPeerEdges = true
447
515
  continue
448
516
  }
449
- if (edge.from.isWorkspace || edge.from.isProjectRoot)
517
+ if (edge.from.isWorkspace || edge.from.isProjectRoot) {
450
518
  return true
519
+ }
451
520
  }
452
521
  if (hasPeerEdges) {
453
522
  for (const edge of peerEntrySets(node).keys()) {
454
- if (edge.from.isWorkspace || edge.from.isProjectRoot)
523
+ if (edge.from.isWorkspace || edge.from.isProjectRoot) {
455
524
  return true
525
+ }
456
526
  }
457
527
  }
458
528
 
459
529
  return false
460
530
  }
461
531
 
462
- warnPeerConflict () {
463
- this.edge.overridden = true
464
- const expl = this.explainPeerConflict()
532
+ warnPeerConflict (edge, dep) {
533
+ edge = edge || this.edge
534
+ dep = dep || this.dep
535
+ edge.overridden = true
536
+ const expl = this.explainPeerConflict(edge, dep)
465
537
  log.warn('ERESOLVE', 'overriding peer dependency', expl)
466
538
  }
467
539
 
468
- failPeerConflict () {
469
- const expl = this.explainPeerConflict()
540
+ failPeerConflict (edge, dep) {
541
+ edge = edge || this.top.edge
542
+ dep = dep || this.top.dep
543
+ const expl = this.explainPeerConflict(edge, dep)
470
544
  throw Object.assign(new Error('could not resolve'), expl)
471
545
  }
472
546
 
473
- explainPeerConflict () {
474
- const { edge, dep } = this.top
547
+ explainPeerConflict (edge, dep) {
475
548
  const { from: node } = edge
476
549
  const curNode = node.resolve(edge.name)
477
550
 
@@ -541,8 +614,9 @@ class PlaceDep {
541
614
  get allChildren () {
542
615
  const set = new Set(this.children)
543
616
  for (const child of set) {
544
- for (const grandchild of child.children)
617
+ for (const grandchild of child.children) {
545
618
  set.add(grandchild)
619
+ }
546
620
  }
547
621
  return [...set]
548
622
  }
package/lib/printable.js CHANGED
@@ -1,63 +1,81 @@
1
1
  // helper function to output a clearer visualization
2
2
  // of the current node and its descendents
3
3
 
4
+ const localeCompare = require('@isaacs/string-locale-compare')('en')
4
5
  const util = require('util')
5
6
  const relpath = require('./relpath.js')
6
7
 
7
8
  class ArboristNode {
8
9
  constructor (tree, path) {
9
10
  this.name = tree.name
10
- if (tree.packageName && tree.packageName !== this.name)
11
+ if (tree.packageName && tree.packageName !== this.name) {
11
12
  this.packageName = tree.packageName
12
- if (tree.version)
13
+ }
14
+ if (tree.version) {
13
15
  this.version = tree.version
16
+ }
14
17
  this.location = tree.location
15
18
  this.path = tree.path
16
- if (tree.realpath !== this.path)
19
+ if (tree.realpath !== this.path) {
17
20
  this.realpath = tree.realpath
18
- if (tree.resolved !== null)
21
+ }
22
+ if (tree.resolved !== null) {
19
23
  this.resolved = tree.resolved
20
- if (tree.extraneous)
24
+ }
25
+ if (tree.extraneous) {
21
26
  this.extraneous = true
22
- if (tree.dev)
27
+ }
28
+ if (tree.dev) {
23
29
  this.dev = true
24
- if (tree.optional)
30
+ }
31
+ if (tree.optional) {
25
32
  this.optional = true
26
- if (tree.devOptional && !tree.dev && !tree.optional)
33
+ }
34
+ if (tree.devOptional && !tree.dev && !tree.optional) {
27
35
  this.devOptional = true
28
- if (tree.peer)
36
+ }
37
+ if (tree.peer) {
29
38
  this.peer = true
30
- if (tree.inBundle)
39
+ }
40
+ if (tree.inBundle) {
31
41
  this.bundled = true
32
- if (tree.inDepBundle)
42
+ }
43
+ if (tree.inDepBundle) {
33
44
  this.bundler = tree.getBundler().location
34
- if (tree.isProjectRoot)
45
+ }
46
+ if (tree.isProjectRoot) {
35
47
  this.isProjectRoot = true
36
- if (tree.isWorkspace)
48
+ }
49
+ if (tree.isWorkspace) {
37
50
  this.isWorkspace = true
51
+ }
38
52
  const bd = tree.package && tree.package.bundleDependencies
39
- if (bd && bd.length)
53
+ if (bd && bd.length) {
40
54
  this.bundleDependencies = bd
41
- if (tree.inShrinkwrap)
55
+ }
56
+ if (tree.inShrinkwrap) {
42
57
  this.inShrinkwrap = true
43
- else if (tree.hasShrinkwrap)
58
+ } else if (tree.hasShrinkwrap) {
44
59
  this.hasShrinkwrap = true
45
- if (tree.error)
60
+ }
61
+ if (tree.error) {
46
62
  this.error = treeError(tree.error)
47
- if (tree.errors && tree.errors.length)
63
+ }
64
+ if (tree.errors && tree.errors.length) {
48
65
  this.errors = tree.errors.map(treeError)
66
+ }
49
67
 
50
68
  // edgesOut sorted by name
51
69
  if (tree.edgesOut.size) {
52
70
  this.edgesOut = new Map([...tree.edgesOut.entries()]
53
- .sort(([a], [b]) => a.localeCompare(b, 'en'))
71
+ .sort(([a], [b]) => localeCompare(a, b))
54
72
  .map(([name, edge]) => [name, new EdgeOut(edge)]))
55
73
  }
56
74
 
57
75
  // edgesIn sorted by location
58
76
  if (tree.edgesIn.size) {
59
77
  this.edgesIn = new Set([...tree.edgesIn]
60
- .sort((a, b) => a.from.location.localeCompare(b.from.location, 'en'))
78
+ .sort((a, b) => localeCompare(a.from.location, b.from.location))
61
79
  .map(edge => new EdgeIn(edge)))
62
80
  }
63
81
 
@@ -69,14 +87,14 @@ class ArboristNode {
69
87
  // fsChildren sorted by path
70
88
  if (tree.fsChildren.size) {
71
89
  this.fsChildren = new Set([...tree.fsChildren]
72
- .sort(({path: a}, {path: b}) => a.localeCompare(b, 'en'))
90
+ .sort(({path: a}, {path: b}) => localeCompare(a, b))
73
91
  .map(tree => printableTree(tree, path)))
74
92
  }
75
93
 
76
94
  // children sorted by name
77
95
  if (tree.children.size) {
78
96
  this.children = new Map([...tree.children.entries()]
79
- .sort(([a], [b]) => a.localeCompare(b, 'en'))
97
+ .sort(([a], [b]) => localeCompare(a, b))
80
98
  .map(([name, tree]) => [name, printableTree(tree, path)]))
81
99
  }
82
100
  }
@@ -109,10 +127,12 @@ class Edge {
109
127
  this.type = edge.type
110
128
  this.name = edge.name
111
129
  this.spec = edge.spec || '*'
112
- if (edge.error)
130
+ if (edge.error) {
113
131
  this.error = edge.error
114
- if (edge.overridden)
132
+ }
133
+ if (edge.overridden) {
115
134
  this.overridden = edge.overridden
135
+ }
116
136
  }
117
137
  }
118
138
 
@@ -151,8 +171,9 @@ class EdgeIn extends Edge {
151
171
  }
152
172
 
153
173
  const printableTree = (tree, path = []) => {
154
- if (!tree)
174
+ if (!tree) {
155
175
  return tree
176
+ }
156
177
 
157
178
  const Cls = tree.isLink ? ArboristLink
158
179
  : tree.sourceReference ? ArboristVirtualNode
package/lib/realpath.js CHANGED
@@ -14,18 +14,21 @@ const { resolve, basename, dirname } = require('path')
14
14
  const realpathCached = (path, rpcache, stcache, depth) => {
15
15
  // just a safety against extremely deep eloops
16
16
  /* istanbul ignore next */
17
- if (depth > 2000)
17
+ if (depth > 2000) {
18
18
  throw eloop(path)
19
+ }
19
20
 
20
21
  path = resolve(path)
21
- if (rpcache.has(path))
22
+ if (rpcache.has(path)) {
22
23
  return Promise.resolve(rpcache.get(path))
24
+ }
23
25
 
24
26
  const dir = dirname(path)
25
27
  const base = basename(path)
26
28
 
27
- if (base && rpcache.has(dir))
29
+ if (base && rpcache.has(dir)) {
28
30
  return realpathChild(dir, base, rpcache, stcache, depth)
31
+ }
29
32
 
30
33
  // if it's the root, then we know it's real
31
34
  if (!base) {
@@ -40,8 +43,9 @@ const realpathCached = (path, rpcache, stcache, depth) => {
40
43
  }
41
44
 
42
45
  const lstatCached = (path, stcache) => {
43
- if (stcache.has(path))
46
+ if (stcache.has(path)) {
44
47
  return Promise.resolve(stcache.get(path))
48
+ }
45
49
 
46
50
  const p = lstat(path).then(st => {
47
51
  stcache.set(path, st)
@@ -66,8 +70,9 @@ const realpathChild = (dir, base, rpcache, stcache, depth) => {
66
70
  const realdir = rpcache.get(dir)
67
71
  // that unpossible
68
72
  /* istanbul ignore next */
69
- if (typeof realdir === 'undefined')
73
+ if (typeof realdir === 'undefined') {
70
74
  throw new Error('in realpathChild without parent being in realpath cache')
75
+ }
71
76
 
72
77
  const realish = resolve(realdir, base)
73
78
  return lstatCached(realish, stcache).then(st => {
@@ -78,8 +83,9 @@ const realpathChild = (dir, base, rpcache, stcache, depth) => {
78
83
 
79
84
  return readlink(realish).then(target => {
80
85
  const resolved = resolve(realdir, target)
81
- if (realish === resolved)
86
+ if (realish === resolved) {
82
87
  throw eloop(realish)
88
+ }
83
89
 
84
90
  return realpathCached(resolved, rpcache, stcache, depth + 1)
85
91
  }).then(real => {