@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
package/lib/node.js CHANGED
@@ -120,8 +120,9 @@ class Node {
120
120
  // should be equal if not a link
121
121
  this.path = path ? resolve(path) : null
122
122
 
123
- if (!this.name && (!this.path || this.path !== dirname(this.path)))
123
+ if (!this.name && (!this.path || this.path !== dirname(this.path))) {
124
124
  throw new TypeError('could not detect node name from path or package')
125
+ }
125
126
 
126
127
  this.realpath = !this.isLink ? this.path : resolve(realpath)
127
128
 
@@ -142,8 +143,9 @@ class Node {
142
143
  //
143
144
  // Otherwise, hopefully a shrinkwrap will help us out.
144
145
  const resolved = consistentResolve(pkg._resolved)
145
- if (resolved && !(/^file:/.test(resolved) && pkg._where))
146
+ if (resolved && !(/^file:/.test(resolved) && pkg._where)) {
146
147
  this.resolved = resolved
148
+ }
147
149
  }
148
150
  this.integrity = integrity || pkg._integrity || null
149
151
  this.hasShrinkwrap = hasShrinkwrap || pkg._hasShrinkwrap || false
@@ -215,18 +217,21 @@ class Node {
215
217
  // see parent/root setters below.
216
218
  // root is set to parent's root if we have a parent, otherwise if it's
217
219
  // null, then it's set to the node itself.
218
- if (!parent && !fsParent)
220
+ if (!parent && !fsParent) {
219
221
  this.root = root || null
222
+ }
220
223
 
221
224
  // mostly a convenience for testing, but also a way to create
222
225
  // trees in a more declarative way than setting parent on each
223
226
  if (children) {
224
- for (const c of children)
227
+ for (const c of children) {
225
228
  new Node({ ...c, parent: this })
229
+ }
226
230
  }
227
231
  if (fsChildren) {
228
- for (const c of fsChildren)
232
+ for (const c of fsChildren) {
229
233
  new Node({ ...c, fsParent: this })
234
+ }
230
235
  }
231
236
 
232
237
  // now load all the dep edges
@@ -239,8 +244,9 @@ class Node {
239
244
 
240
245
  set meta (meta) {
241
246
  this[_meta] = meta
242
- if (meta)
247
+ if (meta) {
243
248
  meta.add(this)
249
+ }
244
250
  }
245
251
 
246
252
  get global () {
@@ -260,8 +266,9 @@ class Node {
260
266
  // deletes edges if they already exists
261
267
  if (this[_workspaces]) {
262
268
  for (const name of this[_workspaces].keys()) {
263
- if (!workspaces.has(name))
269
+ if (!workspaces.has(name)) {
264
270
  this.edgesOut.get(name).detach()
271
+ }
265
272
  }
266
273
  }
267
274
 
@@ -271,8 +278,9 @@ class Node {
271
278
  }
272
279
 
273
280
  get binPaths () {
274
- if (!this.parent)
281
+ if (!this.parent) {
275
282
  return []
283
+ }
276
284
 
277
285
  return getBinPaths({
278
286
  pkg: this[_package],
@@ -319,8 +327,9 @@ class Node {
319
327
  // only do this more than once at the root level, so the resolve() calls
320
328
  // are only one level deep, and there's not much to be saved, anyway.
321
329
  // simpler to just toss them all out.
322
- for (const edge of this.edgesOut.values())
330
+ for (const edge of this.edgesOut.values()) {
323
331
  edge.detach()
332
+ }
324
333
 
325
334
  this[_explanation] = null
326
335
  /* istanbul ignore next - should be impossible */
@@ -341,8 +350,9 @@ class Node {
341
350
  // node.explain(nodes seen already, edge we're trying to satisfy
342
351
  // if edge is not specified, it lists every edge into the node.
343
352
  explain (edge = null, seen = []) {
344
- if (this[_explanation])
353
+ if (this[_explanation]) {
345
354
  return this[_explanation]
355
+ }
346
356
 
347
357
  return this[_explanation] = this[_explain](edge, seen)
348
358
  }
@@ -374,11 +384,13 @@ class Node {
374
384
  }
375
385
  }
376
386
 
377
- if (this.sourceReference)
387
+ if (this.sourceReference) {
378
388
  return this.sourceReference.explain(edge, seen)
389
+ }
379
390
 
380
- if (seen.includes(this))
391
+ if (seen.includes(this)) {
381
392
  return why
393
+ }
382
394
 
383
395
  why.location = this.location
384
396
  why.isWorkspace = this.isWorkspace
@@ -387,56 +399,64 @@ class Node {
387
399
  seen = seen.concat(this)
388
400
 
389
401
  why.dependents = []
390
- if (edge)
402
+ if (edge) {
391
403
  why.dependents.push(edge.explain(seen))
392
- else {
404
+ } else {
393
405
  // ignore invalid edges, since those aren't satisfied by this thing,
394
406
  // and are not keeping it held in this spot anyway.
395
407
  const edges = []
396
408
  for (const edge of this.edgesIn) {
397
- if (!edge.valid && !edge.from.isProjectRoot)
409
+ if (!edge.valid && !edge.from.isProjectRoot) {
398
410
  continue
411
+ }
399
412
 
400
413
  edges.push(edge)
401
414
  }
402
- for (const edge of edges)
415
+ for (const edge of edges) {
403
416
  why.dependents.push(edge.explain(seen))
417
+ }
404
418
  }
405
419
 
406
- if (this.linksIn.size)
420
+ if (this.linksIn.size) {
407
421
  why.linksIn = [...this.linksIn].map(link => link[_explain](edge, seen))
422
+ }
408
423
 
409
424
  return why
410
425
  }
411
426
 
412
427
  isDescendantOf (node) {
413
428
  for (let p = this; p; p = p.resolveParent) {
414
- if (p === node)
429
+ if (p === node) {
415
430
  return true
431
+ }
416
432
  }
417
433
  return false
418
434
  }
419
435
 
420
436
  getBundler (path = []) {
421
437
  // made a cycle, definitely not bundled!
422
- if (path.includes(this))
438
+ if (path.includes(this)) {
423
439
  return null
440
+ }
424
441
 
425
442
  path.push(this)
426
443
 
427
444
  const parent = this[_parent]
428
- if (!parent)
445
+ if (!parent) {
429
446
  return null
447
+ }
430
448
 
431
449
  const pBundler = parent.getBundler(path)
432
- if (pBundler)
450
+ if (pBundler) {
433
451
  return pBundler
452
+ }
434
453
 
435
454
  const ppkg = parent.package
436
455
  const bd = ppkg && ppkg.bundleDependencies
437
456
  // explicit bundling
438
- if (Array.isArray(bd) && bd.includes(this.name))
457
+ if (Array.isArray(bd) && bd.includes(this.name)) {
439
458
  return parent
459
+ }
440
460
 
441
461
  // deps that are deduped up to the bundling level are bundled.
442
462
  // however, if they get their dep met further up than that,
@@ -444,11 +464,13 @@ class Node {
444
464
  // unmet bundled deps will not cause your deps to be bundled.
445
465
  for (const edge of this.edgesIn) {
446
466
  const eBundler = edge.from.getBundler(path)
447
- if (!eBundler)
467
+ if (!eBundler) {
448
468
  continue
469
+ }
449
470
 
450
- if (eBundler === parent)
471
+ if (eBundler === parent) {
451
472
  return eBundler
473
+ }
452
474
  }
453
475
 
454
476
  return null
@@ -467,8 +489,9 @@ class Node {
467
489
  }
468
490
 
469
491
  get isWorkspace () {
470
- if (this.isProjectRoot)
492
+ if (this.isProjectRoot) {
471
493
  return false
494
+ }
472
495
  const { root } = this
473
496
  const { type, to } = root.edgesOut.get(this.packageName) || {}
474
497
  return type === 'workspace' && to && (to.target === this || to === this)
@@ -486,15 +509,17 @@ class Node {
486
509
  }
487
510
 
488
511
  * ancestry () {
489
- for (let anc = this; anc; anc = anc.resolveParent)
512
+ for (let anc = this; anc; anc = anc.resolveParent) {
490
513
  yield anc
514
+ }
491
515
  }
492
516
 
493
517
  set root (root) {
494
518
  // setting to null means this is the new root
495
519
  // should only ever be one step
496
- while (root && root.root !== root)
520
+ while (root && root.root !== root) {
497
521
  root = root.root
522
+ }
498
523
 
499
524
  root = root || this
500
525
 
@@ -504,8 +529,9 @@ class Node {
504
529
  // can't set the root (yet) if there's no way to determine location
505
530
  // this allows us to do new Node({...}) and then set the root later.
506
531
  // just make the assignment so we don't lose it, and move on.
507
- if (!this.path || !root.realpath || !root.path)
532
+ if (!this.path || !root.realpath || !root.path) {
508
533
  return this[_root] = root
534
+ }
509
535
 
510
536
  // temporarily become a root node
511
537
  this[_root] = this
@@ -521,8 +547,9 @@ class Node {
521
547
  if (this.isLink) {
522
548
  if (target) {
523
549
  target.linksIn.delete(this)
524
- if (target.root === this)
550
+ if (target.root === this) {
525
551
  target[_delistFromMeta]()
552
+ }
526
553
  }
527
554
  this[_target] = null
528
555
  }
@@ -539,16 +566,17 @@ class Node {
539
566
  this[_fsParent] = null
540
567
  }
541
568
 
542
- if (root === this)
569
+ if (root === this) {
543
570
  this[_refreshLocation]()
544
- else {
571
+ } else {
545
572
  // setting to some different node.
546
573
  const loc = relpath(root.realpath, this.path)
547
574
  const current = root.inventory.get(loc)
548
575
 
549
576
  // clobber whatever is there now
550
- if (current)
577
+ if (current) {
551
578
  current.root = null
579
+ }
552
580
 
553
581
  this[_root] = root
554
582
  // set this.location and add to inventory
@@ -556,8 +584,9 @@ class Node {
556
584
 
557
585
  // try to find our parent/fsParent in the new root inventory
558
586
  for (const p of walkUp(dirname(this.path))) {
559
- if (p === this.path)
587
+ if (p === this.path) {
560
588
  continue
589
+ }
561
590
  const ploc = relpath(root.realpath, p)
562
591
  const parent = root.inventory.get(ploc)
563
592
  if (parent) {
@@ -576,8 +605,9 @@ class Node {
576
605
  const isParent = this.location === childLoc
577
606
  if (isParent) {
578
607
  const oldChild = parent.children.get(this.name)
579
- if (oldChild && oldChild !== this)
608
+ if (oldChild && oldChild !== this) {
580
609
  oldChild.root = null
610
+ }
581
611
  if (this.parent) {
582
612
  this.parent.children.delete(this.name)
583
613
  this.parent[_reloadNamedEdges](this.name)
@@ -586,13 +616,15 @@ class Node {
586
616
  this[_parent] = parent
587
617
  // don't do it for links, because they don't have a target yet
588
618
  // we'll hit them up a bit later on.
589
- if (!this.isLink)
619
+ if (!this.isLink) {
590
620
  parent[_reloadNamedEdges](this.name)
621
+ }
591
622
  } else {
592
623
  /* istanbul ignore if - should be impossible, since we break
593
624
  * all fsParent/child relationships when moving? */
594
- if (this.fsParent)
625
+ if (this.fsParent) {
595
626
  this.fsParent.fsChildren.delete(this)
627
+ }
596
628
  parent.fsChildren.add(this)
597
629
  this[_fsParent] = parent
598
630
  }
@@ -601,10 +633,11 @@ class Node {
601
633
  }
602
634
 
603
635
  // if it doesn't have a parent, it's a top node
604
- if (!this.parent)
636
+ if (!this.parent) {
605
637
  root.tops.add(this)
606
- else
638
+ } else {
607
639
  root.tops.delete(this)
640
+ }
608
641
 
609
642
  // assign parentage for any nodes that need to have this as a parent
610
643
  // this can happen when we have a node at nm/a/nm/b added *before*
@@ -614,24 +647,30 @@ class Node {
614
647
  const nmloc = `${this.location}${this.location ? '/' : ''}node_modules/`
615
648
  const isChild = n => n.location === nmloc + n.name
616
649
  // check dirname so that /foo isn't treated as the fsparent of /foo-bar
617
- const isFsChild = n => dirname(n.path).startsWith(this.path) &&
618
- n !== this &&
619
- !n.parent &&
620
- (!n.fsParent || n.fsParent === this || dirname(this.path).startsWith(n.fsParent.path))
650
+ const isFsChild = n => {
651
+ return dirname(n.path).startsWith(this.path) &&
652
+ n !== this &&
653
+ !n.parent &&
654
+ (!n.fsParent ||
655
+ n.fsParent === this ||
656
+ dirname(this.path).startsWith(n.fsParent.path))
657
+ }
621
658
  const isKid = n => isChild(n) || isFsChild(n)
622
659
 
623
660
  // only walk top nodes, since anything else already has a parent.
624
661
  for (const child of root.tops) {
625
- if (!isKid(child))
662
+ if (!isKid(child)) {
626
663
  continue
664
+ }
627
665
 
628
666
  // set up the internal parentage links
629
- if (this.isLink)
667
+ if (this.isLink) {
630
668
  child.root = null
631
- else {
669
+ } else {
632
670
  // can't possibly have a parent, because it's in tops
633
- if (child.fsParent)
671
+ if (child.fsParent) {
634
672
  child.fsParent.fsChildren.delete(child)
673
+ }
635
674
  child[_fsParent] = null
636
675
  if (isChild(child)) {
637
676
  this.children.set(child.name, child)
@@ -648,13 +687,15 @@ class Node {
648
687
  // to that realpath, or a thing at that realpath if we're adding a link
649
688
  // (if we're adding a regular node, we already deleted the old one)
650
689
  for (const node of root.inventory.query('realpath', this.realpath)) {
651
- if (node === this)
690
+ if (node === this) {
652
691
  continue
692
+ }
653
693
 
654
694
  /* istanbul ignore next - should be impossible */
655
695
  debug(() => {
656
- if (node.root !== root)
696
+ if (node.root !== root) {
657
697
  throw new Error('inventory contains node from other root')
698
+ }
658
699
  })
659
700
 
660
701
  if (this.isLink) {
@@ -663,8 +704,9 @@ class Node {
663
704
  this[_package] = target.package
664
705
  target.linksIn.add(this)
665
706
  // reload edges here, because now we have a target
666
- if (this.parent)
707
+ if (this.parent) {
667
708
  this.parent[_reloadNamedEdges](this.name)
709
+ }
668
710
  break
669
711
  } else {
670
712
  /* istanbul ignore else - should be impossible */
@@ -672,8 +714,9 @@ class Node {
672
714
  node[_target] = this
673
715
  node[_package] = this.package
674
716
  this.linksIn.add(node)
675
- if (node.parent)
717
+ if (node.parent) {
676
718
  node.parent[_reloadNamedEdges](node.name)
719
+ }
677
720
  } else {
678
721
  debug(() => {
679
722
  throw Object.assign(new Error('duplicate node in root setter'), {
@@ -690,14 +733,16 @@ class Node {
690
733
  // reload all edgesIn where the root doesn't match, so we don't have
691
734
  // cross-tree dependency graphs
692
735
  for (const edge of this.edgesIn) {
693
- if (edge.from.root !== root)
736
+ if (edge.from.root !== root) {
694
737
  edge.reload()
738
+ }
695
739
  }
696
740
  // reload all edgesOut where root doens't match, or is missing, since
697
741
  // it might not be missing in the new tree
698
742
  for (const edge of this.edgesOut.values()) {
699
- if (!edge.to || edge.to.root !== root)
743
+ if (!edge.to || edge.to.root !== root) {
700
744
  edge.reload()
745
+ }
701
746
  }
702
747
 
703
748
  // now make sure our family comes along for the ride!
@@ -721,15 +766,17 @@ class Node {
721
766
  }
722
767
  }
723
768
  for (const child of family) {
724
- if (child.root !== root)
769
+ if (child.root !== root) {
725
770
  child.root = root
771
+ }
726
772
  }
727
773
 
728
774
  // if we had a target, and didn't find one in the new root, then bring
729
775
  // it over as well, but only if we're setting the link into a new root,
730
776
  // as we don't want to lose the target any time we remove a link.
731
- if (this.isLink && target && !this.target && root !== this)
777
+ if (this.isLink && target && !this.target && root !== this) {
732
778
  target.root = root
779
+ }
733
780
 
734
781
  // tree should always be valid upon root setter completion.
735
782
  treeCheck(this)
@@ -741,11 +788,13 @@ class Node {
741
788
  }
742
789
 
743
790
  [_loadWorkspaces] () {
744
- if (!this[_workspaces])
791
+ if (!this[_workspaces]) {
745
792
  return
793
+ }
746
794
 
747
- for (const [name, path] of this[_workspaces].entries())
795
+ for (const [name, path] of this[_workspaces].entries()) {
748
796
  new Edge({ from: this, name, spec: `file:${path}`, type: 'workspace' })
797
+ }
749
798
  }
750
799
 
751
800
  [_loadDeps] () {
@@ -764,10 +813,11 @@ class Node {
764
813
  const peerDependencies = {}
765
814
  const peerOptional = {}
766
815
  for (const [name, dep] of Object.entries(pd)) {
767
- if (pm[name] && pm[name].optional)
816
+ if (pm[name] && pm[name].optional) {
768
817
  peerOptional[name] = dep
769
- else
818
+ } else {
770
819
  peerDependencies[name] = dep
820
+ }
771
821
  }
772
822
  this[_loadDepType](peerDependencies, 'peer')
773
823
  this[_loadDepType](peerOptional, 'peerOptional')
@@ -784,8 +834,9 @@ class Node {
784
834
  } = sourceReference || {}
785
835
  const thisDev = isTop && !globalTop && path
786
836
  const srcDev = !sourceReference || srcTop && !srcGlobalTop && srcPath
787
- if (thisDev && srcDev)
837
+ if (thisDev && srcDev) {
788
838
  this[_loadDepType](this.package.devDependencies, 'dev')
839
+ }
789
840
  }
790
841
 
791
842
  [_loadDepType] (deps, type) {
@@ -794,8 +845,9 @@ class Node {
794
845
  // prioritize a new edge over an existing one
795
846
  for (const [name, spec] of Object.entries(deps || {})) {
796
847
  const current = this.edgesOut.get(name)
797
- if (!current || current.type !== 'workspace')
848
+ if (!current || current.type !== 'workspace') {
798
849
  new Edge({ from: this, name, spec, accept: ad[name], type })
850
+ }
799
851
  }
800
852
  }
801
853
 
@@ -803,25 +855,29 @@ class Node {
803
855
  const parent = this[_fsParent]
804
856
  /* istanbul ignore next - should be impossible */
805
857
  debug(() => {
806
- if (parent === this)
858
+ if (parent === this) {
807
859
  throw new Error('node set to its own fsParent')
860
+ }
808
861
  })
809
862
  return parent
810
863
  }
811
864
 
812
865
  set fsParent (fsParent) {
813
866
  if (!fsParent) {
814
- if (this[_fsParent])
867
+ if (this[_fsParent]) {
815
868
  this.root = null
869
+ }
816
870
  return
817
871
  }
818
872
 
819
873
  debug(() => {
820
- if (fsParent === this)
874
+ if (fsParent === this) {
821
875
  throw new Error('setting node to its own fsParent')
876
+ }
822
877
 
823
- if (fsParent.realpath === this.realpath)
878
+ if (fsParent.realpath === this.realpath) {
824
879
  throw new Error('setting fsParent to same path')
880
+ }
825
881
 
826
882
  // the initial set MUST be an actual walk-up from the realpath
827
883
  // subsequent sets will re-root on the new fsParent's path.
@@ -837,16 +893,19 @@ class Node {
837
893
  }
838
894
  })
839
895
 
840
- if (fsParent.isLink)
896
+ if (fsParent.isLink) {
841
897
  fsParent = fsParent.target
898
+ }
842
899
 
843
900
  // setting a thing to its own fsParent is not normal, but no-op for safety
844
- if (this === fsParent || fsParent.realpath === this.realpath)
901
+ if (this === fsParent || fsParent.realpath === this.realpath) {
845
902
  return
903
+ }
846
904
 
847
905
  // nothing to do
848
- if (this[_fsParent] === fsParent)
906
+ if (this[_fsParent] === fsParent) {
849
907
  return
908
+ }
850
909
 
851
910
  const oldFsParent = this[_fsParent]
852
911
  const newPath = !oldFsParent ? this.path
@@ -874,11 +933,13 @@ class Node {
874
933
  }
875
934
 
876
935
  // update this.path/realpath for this and all children/fsChildren
877
- if (pathChange)
936
+ if (pathChange) {
878
937
  this[_changePath](newPath)
938
+ }
879
939
 
880
- if (oldParent)
940
+ if (oldParent) {
881
941
  oldParent[_reloadNamedEdges](oldName)
942
+ }
882
943
 
883
944
  // clobbers anything at that path, resets all appropriate references
884
945
  this.root = fsParent.root
@@ -894,11 +955,13 @@ class Node {
894
955
  // will go ahead and create the invalid state, and then try to resolve
895
956
  // it with more tree construction, because it's a user request.
896
957
  canReplaceWith (node, ignorePeers = []) {
897
- if (node.name !== this.name)
958
+ if (node.name !== this.name) {
898
959
  return false
960
+ }
899
961
 
900
- if (node.packageName !== this.packageName)
962
+ if (node.packageName !== this.packageName) {
901
963
  return false
964
+ }
902
965
 
903
966
  ignorePeers = new Set(ignorePeers)
904
967
 
@@ -915,12 +978,14 @@ class Node {
915
978
  edge.from.parent === this.parent &&
916
979
  edge.peer &&
917
980
  ignorePeers.has(edge.from.name)
918
- if (ignored)
981
+ if (ignored) {
919
982
  continue
983
+ }
920
984
 
921
985
  // only care about edges that don't originate from this node
922
- if (!depSet.has(edge.from) && !edge.satisfiedBy(node))
986
+ if (!depSet.has(edge.from) && !edge.satisfiedBy(node)) {
923
987
  return false
988
+ }
924
989
  }
925
990
 
926
991
  return true
@@ -935,41 +1000,49 @@ class Node {
935
1000
  // to if it was removed, or nothing is depending on it in the first place.
936
1001
  canDedupe (preferDedupe = false) {
937
1002
  // not allowed to mess with shrinkwraps or bundles
938
- if (this.inDepBundle || this.inShrinkwrap)
1003
+ if (this.inDepBundle || this.inShrinkwrap) {
939
1004
  return false
1005
+ }
940
1006
 
941
1007
  // it's a top level pkg, or a dep of one
942
- if (!this.resolveParent || !this.resolveParent.resolveParent)
1008
+ if (!this.resolveParent || !this.resolveParent.resolveParent) {
943
1009
  return false
1010
+ }
944
1011
 
945
1012
  // no one wants it, remove it
946
- if (this.edgesIn.size === 0)
1013
+ if (this.edgesIn.size === 0) {
947
1014
  return true
1015
+ }
948
1016
 
949
1017
  const other = this.resolveParent.resolveParent.resolve(this.name)
950
1018
 
951
1019
  // nothing else, need this one
952
- if (!other)
1020
+ if (!other) {
953
1021
  return false
1022
+ }
954
1023
 
955
1024
  // if it's the same thing, then always fine to remove
956
- if (other.matches(this))
1025
+ if (other.matches(this)) {
957
1026
  return true
1027
+ }
958
1028
 
959
1029
  // if the other thing can't replace this, then skip it
960
- if (!other.canReplace(this))
1030
+ if (!other.canReplace(this)) {
961
1031
  return false
1032
+ }
962
1033
 
963
1034
  // if we prefer dedupe, or if the version is greater/equal, take the other
964
- if (preferDedupe || semver.gte(other.version, this.version))
1035
+ if (preferDedupe || semver.gte(other.version, this.version)) {
965
1036
  return true
1037
+ }
966
1038
 
967
1039
  return false
968
1040
  }
969
1041
 
970
1042
  satisfies (requested) {
971
- if (requested instanceof Edge)
1043
+ if (requested instanceof Edge) {
972
1044
  return this.name === requested.name && requested.satisfiedBy(this)
1045
+ }
973
1046
 
974
1047
  const parsed = npa(requested)
975
1048
  const { name = this.name, rawSpec: spec } = parsed
@@ -983,29 +1056,35 @@ class Node {
983
1056
 
984
1057
  matches (node) {
985
1058
  // if the nodes are literally the same object, obviously a match.
986
- if (node === this)
1059
+ if (node === this) {
987
1060
  return true
1061
+ }
988
1062
 
989
1063
  // if the names don't match, they're different things, even if
990
1064
  // the package contents are identical.
991
- if (node.name !== this.name)
1065
+ if (node.name !== this.name) {
992
1066
  return false
1067
+ }
993
1068
 
994
1069
  // if they're links, they match if the targets match
995
- if (this.isLink)
1070
+ if (this.isLink) {
996
1071
  return node.isLink && this.target.matches(node.target)
1072
+ }
997
1073
 
998
1074
  // if they're two project root nodes, they're different if the paths differ
999
- if (this.isProjectRoot && node.isProjectRoot)
1075
+ if (this.isProjectRoot && node.isProjectRoot) {
1000
1076
  return this.path === node.path
1077
+ }
1001
1078
 
1002
1079
  // if the integrity matches, then they're the same.
1003
- if (this.integrity && node.integrity)
1080
+ if (this.integrity && node.integrity) {
1004
1081
  return this.integrity === node.integrity
1082
+ }
1005
1083
 
1006
1084
  // if no integrity, check resolved
1007
- if (this.resolved && node.resolved)
1085
+ if (this.resolved && node.resolved) {
1008
1086
  return this.resolved === node.resolved
1087
+ }
1009
1088
 
1010
1089
  // if no resolved, check both package name and version
1011
1090
  // otherwise, conclude that they are different things
@@ -1031,39 +1110,44 @@ class Node {
1031
1110
  // parent's children map, and leave it at that.
1032
1111
  const nameMatch = node.parent &&
1033
1112
  node.parent.children.get(this.name) === node
1034
- if (nameMatch)
1113
+ if (nameMatch) {
1035
1114
  this.path = resolve(node.parent.path, 'node_modules', this.name)
1036
- else {
1115
+ } else {
1037
1116
  this.path = node.path
1038
1117
  this.name = node.name
1039
1118
  }
1040
1119
 
1041
- if (!this.isLink)
1120
+ if (!this.isLink) {
1042
1121
  this.realpath = this.path
1122
+ }
1043
1123
  this[_refreshLocation]()
1044
1124
 
1045
1125
  // keep children when a node replaces another
1046
1126
  if (!this.isLink) {
1047
- for (const kid of node.children.values())
1127
+ for (const kid of node.children.values()) {
1048
1128
  kid.parent = this
1129
+ }
1049
1130
  }
1050
1131
 
1051
- if (!node.isRoot)
1132
+ if (!node.isRoot) {
1052
1133
  this.root = node.root
1134
+ }
1053
1135
 
1054
1136
  treeCheck(this)
1055
1137
  }
1056
1138
 
1057
1139
  get inShrinkwrap () {
1058
- return this.parent && (this.parent.hasShrinkwrap || this.parent.inShrinkwrap)
1140
+ return this.parent &&
1141
+ (this.parent.hasShrinkwrap || this.parent.inShrinkwrap)
1059
1142
  }
1060
1143
 
1061
1144
  get parent () {
1062
1145
  const parent = this[_parent]
1063
1146
  /* istanbul ignore next - should be impossible */
1064
1147
  debug(() => {
1065
- if (parent === this)
1148
+ if (parent === this) {
1066
1149
  throw new Error('node set to its own parent')
1150
+ }
1067
1151
  })
1068
1152
  return parent
1069
1153
  }
@@ -1083,23 +1167,27 @@ class Node {
1083
1167
  if (!parent) {
1084
1168
  // but only delete it if we actually had a parent in the first place
1085
1169
  // otherwise it's just setting to null when it's already null
1086
- if (this[_parent])
1170
+ if (this[_parent]) {
1087
1171
  this.root = null
1172
+ }
1088
1173
  return
1089
1174
  }
1090
1175
 
1091
- if (parent.isLink)
1176
+ if (parent.isLink) {
1092
1177
  parent = parent.target
1178
+ }
1093
1179
 
1094
1180
  // setting a thing to its own parent is not normal, but no-op for safety
1095
- if (this === parent)
1181
+ if (this === parent) {
1096
1182
  return
1183
+ }
1097
1184
 
1098
1185
  const oldParent = this[_parent]
1099
1186
 
1100
1187
  // nothing to do
1101
- if (oldParent === parent)
1188
+ if (oldParent === parent) {
1102
1189
  return
1190
+ }
1103
1191
 
1104
1192
  // ok now we know something is actually changing, and parent is not a link
1105
1193
  const newPath = resolve(parent.path, 'node_modules', this.name)
@@ -1116,8 +1204,9 @@ class Node {
1116
1204
  }
1117
1205
 
1118
1206
  // update this.path/realpath for this and all children/fsChildren
1119
- if (pathChange)
1207
+ if (pathChange) {
1120
1208
  this[_changePath](newPath)
1209
+ }
1121
1210
 
1122
1211
  // clobbers anything at that path, resets all appropriate references
1123
1212
  this.root = parent.root
@@ -1127,16 +1216,19 @@ class Node {
1127
1216
  // Removes the node from its root the metadata and inventory.
1128
1217
  [_delistFromMeta] () {
1129
1218
  const root = this.root
1130
- if (!root.realpath || !this.path)
1219
+ if (!root.realpath || !this.path) {
1131
1220
  return
1221
+ }
1132
1222
  root.inventory.delete(this)
1133
1223
  root.tops.delete(this)
1134
- if (root.meta)
1224
+ if (root.meta) {
1135
1225
  root.meta.delete(this.path)
1226
+ }
1136
1227
  /* istanbul ignore next - should be impossible */
1137
1228
  debug(() => {
1138
- if ([...root.inventory.values()].includes(this))
1229
+ if ([...root.inventory.values()].includes(this)) {
1139
1230
  throw new Error('failed to delist')
1231
+ }
1140
1232
  })
1141
1233
  }
1142
1234
 
@@ -1148,8 +1240,9 @@ class Node {
1148
1240
  this.path = newPath
1149
1241
  const namePattern = /(?:^|\/|\\)node_modules[\\/](@[^/\\]+[\\/][^\\/]+|[^\\/]+)$/
1150
1242
  const nameChange = newPath.match(namePattern)
1151
- if (nameChange && this.name !== nameChange[1])
1243
+ if (nameChange && this.name !== nameChange[1]) {
1152
1244
  this.name = nameChange[1].replace(/\\/g, '/')
1245
+ }
1153
1246
 
1154
1247
  // if we move a link target, update link realpaths
1155
1248
  if (!this.isLink) {
@@ -1161,10 +1254,12 @@ class Node {
1161
1254
  }
1162
1255
  }
1163
1256
  // if we move /x to /y, then a module at /x/a/b becomes /y/a/b
1164
- for (const child of this.fsChildren)
1257
+ for (const child of this.fsChildren) {
1165
1258
  child[_changePath](resolve(newPath, relative(oldPath, child.path)))
1166
- for (const [name, child] of this.children.entries())
1259
+ }
1260
+ for (const [name, child] of this.children.entries()) {
1167
1261
  child[_changePath](resolve(newPath, 'node_modules', name))
1262
+ }
1168
1263
 
1169
1264
  this[_refreshLocation]()
1170
1265
  }
@@ -1179,8 +1274,9 @@ class Node {
1179
1274
  this.location = loc
1180
1275
 
1181
1276
  root.inventory.add(this)
1182
- if (root.meta)
1277
+ if (root.meta) {
1183
1278
  root.meta.add(this)
1279
+ }
1184
1280
  }
1185
1281
 
1186
1282
  addEdgeOut (edge) {
@@ -1191,8 +1287,9 @@ class Node {
1191
1287
  this.edgesIn.add(edge)
1192
1288
 
1193
1289
  // try to get metadata from the yarn.lock file
1194
- if (this.root.meta)
1290
+ if (this.root.meta) {
1195
1291
  this.root.meta.addEdge(edge)
1292
+ }
1196
1293
  }
1197
1294
 
1198
1295
  [_reloadNamedEdges] (name, rootLoc = this.location) {
@@ -1202,13 +1299,16 @@ class Node {
1202
1299
  edge.to.location === `${rootLoc}/node_modules/${edge.name}`
1203
1300
  const sameResolved = edge && this.resolve(name) === edge.to
1204
1301
  const recheck = rootLocResolved || !sameResolved
1205
- if (edge && recheck)
1302
+ if (edge && recheck) {
1206
1303
  edge.reload(true)
1207
- for (const c of this.children.values())
1304
+ }
1305
+ for (const c of this.children.values()) {
1208
1306
  c[_reloadNamedEdges](name, rootLoc)
1307
+ }
1209
1308
 
1210
- for (const c of this.fsChildren)
1309
+ for (const c of this.fsChildren) {
1211
1310
  c[_reloadNamedEdges](name, rootLoc)
1311
+ }
1212
1312
  }
1213
1313
 
1214
1314
  get isLink () {
@@ -1255,15 +1355,18 @@ class Node {
1255
1355
  /* istanbul ignore next - should be impossible,
1256
1356
  * but I keep doing this mistake in tests */
1257
1357
  debug(() => {
1258
- if (typeof name !== 'string' || !name)
1358
+ if (typeof name !== 'string' || !name) {
1259
1359
  throw new Error('non-string passed to Node.resolve')
1360
+ }
1260
1361
  })
1261
1362
  const mine = this.children.get(name)
1262
- if (mine)
1363
+ if (mine) {
1263
1364
  return mine
1365
+ }
1264
1366
  const resolveParent = this.resolveParent
1265
- if (resolveParent)
1367
+ if (resolveParent) {
1266
1368
  return resolveParent.resolve(name)
1369
+ }
1267
1370
  return null
1268
1371
  }
1269
1372