@npmcli/arborist 6.2.7 → 6.2.9

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.
@@ -31,75 +31,75 @@ const Link = require('../link.js')
31
31
  const addRmPkgDeps = require('../add-rm-pkg-deps.js')
32
32
  const optionalSet = require('../optional-set.js')
33
33
  const { checkEngine, checkPlatform } = require('npm-install-checks')
34
-
35
34
  const relpath = require('../relpath.js')
35
+ const resetDepFlags = require('../reset-dep-flags.js')
36
36
 
37
37
  // note: some of these symbols are shared so we can hit
38
38
  // them with unit tests and reuse them across mixins
39
- const _complete = Symbol('complete')
40
- const _depsSeen = Symbol('depsSeen')
41
- const _depsQueue = Symbol('depsQueue')
42
- const _currentDep = Symbol('currentDep')
43
39
  const _updateAll = Symbol.for('updateAll')
44
- const _mutateTree = Symbol('mutateTree')
45
40
  const _flagsSuspect = Symbol.for('flagsSuspect')
46
41
  const _workspaces = Symbol.for('workspaces')
47
- const _prune = Symbol('prune')
48
- const _preferDedupe = Symbol('preferDedupe')
49
- const _parseSettings = Symbol('parseSettings')
50
- const _initTree = Symbol('initTree')
51
- const _applyUserRequests = Symbol('applyUserRequests')
52
- const _applyUserRequestsToNode = Symbol('applyUserRequestsToNode')
53
- const _inflateAncientLockfile = Symbol('inflateAncientLockfile')
54
- const _buildDeps = Symbol('buildDeps')
55
- const _buildDepStep = Symbol('buildDepStep')
56
- const _nodeFromEdge = Symbol('nodeFromEdge')
57
- const _nodeFromSpec = Symbol('nodeFromSpec')
58
- const _fetchManifest = Symbol('fetchManifest')
59
- const _problemEdges = Symbol('problemEdges')
60
- const _manifests = Symbol('manifests')
61
- const _loadWorkspaces = Symbol.for('loadWorkspaces')
62
- const _linkFromSpec = Symbol('linkFromSpec')
63
- const _loadPeerSet = Symbol('loadPeerSet')
42
+ const _setWorkspaces = Symbol.for('setWorkspaces')
64
43
  const _updateNames = Symbol.for('updateNames')
65
- const _fixDepFlags = Symbol('fixDepFlags')
66
- const _resolveLinks = Symbol('resolveLinks')
67
- const _rootNodeFromPackage = Symbol('rootNodeFromPackage')
68
- const _add = Symbol('add')
69
44
  const _resolvedAdd = Symbol.for('resolvedAdd')
70
- const _queueNamedUpdates = Symbol('queueNamedUpdates')
71
- const _queueVulnDependents = Symbol('queueVulnDependents')
72
- const _avoidRange = Symbol('avoidRange')
73
- const _shouldUpdateNode = Symbol('shouldUpdateNode')
74
- const resetDepFlags = require('../reset-dep-flags.js')
75
- const _loadFailures = Symbol('loadFailures')
76
- const _pruneFailedOptional = Symbol('pruneFailedOptional')
77
- const _linkNodes = Symbol('linkNodes')
78
- const _follow = Symbol('follow')
79
- const _installStrategy = Symbol('installStrategy')
80
- const _globalRootNode = Symbol('globalRootNode')
81
45
  const _usePackageLock = Symbol.for('usePackageLock')
82
46
  const _rpcache = Symbol.for('realpathCache')
83
47
  const _stcache = Symbol.for('statCache')
84
- const _strictPeerDeps = Symbol('strictPeerDeps')
85
- const _checkEngineAndPlatform = Symbol('checkEngineAndPlatform')
86
- const _virtualRoots = Symbol('virtualRoots')
87
- const _virtualRoot = Symbol('virtualRoot')
88
48
  const _includeWorkspaceRoot = Symbol.for('includeWorkspaceRoot')
89
49
 
90
- const _failPeerConflict = Symbol('failPeerConflict')
91
- const _explainPeerConflict = Symbol('explainPeerConflict')
92
- const _edgesOverridden = Symbol('edgesOverridden')
93
50
  // exposed symbol for unit testing the placeDep method directly
94
51
  const _peerSetSource = Symbol.for('peerSetSource')
95
52
 
96
53
  // used by Reify mixin
97
54
  const _force = Symbol.for('force')
98
- const _explicitRequests = Symbol('explicitRequests')
99
55
  const _global = Symbol.for('global')
100
56
  const _idealTreePrune = Symbol.for('idealTreePrune')
101
57
 
58
+ // Push items in, pop them sorted by depth and then path
59
+ class DepsQueue {
60
+ #deps = []
61
+ #sorted = true
62
+
63
+ get length () {
64
+ return this.#deps.length
65
+ }
66
+
67
+ push (item) {
68
+ if (!this.#deps.includes(item)) {
69
+ this.#sorted = false
70
+ this.#deps.push(item)
71
+ }
72
+ }
73
+
74
+ pop () {
75
+ if (!this.#sorted) {
76
+ // sort physically shallower deps up to the front of the queue, because
77
+ // they'll affect things deeper in, then alphabetical
78
+ this.#deps.sort((a, b) =>
79
+ (a.depth - b.depth) || localeCompare(a.path, b.path))
80
+ this.#sorted = true
81
+ }
82
+ return this.#deps.shift()
83
+ }
84
+ }
85
+
102
86
  module.exports = cls => class IdealTreeBuilder extends cls {
87
+ #complete
88
+ #currentDep = null
89
+ #depsQueue = new DepsQueue()
90
+ #depsSeen = new Set()
91
+ #explicitRequests = new Set()
92
+ #follow
93
+ #installStrategy
94
+ #linkNodes = new Set()
95
+ #loadFailures = new Set()
96
+ #manifests = new Map()
97
+ #mutateTree = false
98
+ #preferDedupe = false
99
+ #prune
100
+ #strictPeerDeps
101
+ #virtualRoots = new Map()
102
+
103
103
  constructor (options) {
104
104
  super(options)
105
105
 
@@ -123,7 +123,7 @@ module.exports = cls => class IdealTreeBuilder extends cls {
123
123
 
124
124
  this[_workspaces] = workspaces || []
125
125
  this[_force] = !!force
126
- this[_strictPeerDeps] = !!strictPeerDeps
126
+ this.#strictPeerDeps = !!strictPeerDeps
127
127
 
128
128
  this.idealTree = idealTree
129
129
  this.installLinks = installLinks
@@ -131,38 +131,27 @@ module.exports = cls => class IdealTreeBuilder extends cls {
131
131
 
132
132
  this[_usePackageLock] = packageLock
133
133
  this[_global] = !!global
134
- this[_installStrategy] = global ? 'shallow' : installStrategy
135
- this[_follow] = !!follow
134
+ this.#installStrategy = global ? 'shallow' : installStrategy
135
+ this.#follow = !!follow
136
136
 
137
137
  if (this[_workspaces].length && this[_global]) {
138
138
  throw new Error('Cannot operate on workspaces in global mode')
139
139
  }
140
140
 
141
- this[_explicitRequests] = new Set()
142
- this[_preferDedupe] = false
143
- this[_depsSeen] = new Set()
144
- this[_depsQueue] = []
145
- this[_currentDep] = null
146
- this[_updateNames] = []
147
141
  this[_updateAll] = false
148
- this[_mutateTree] = false
149
- this[_loadFailures] = new Set()
150
- this[_linkNodes] = new Set()
151
- this[_manifests] = new Map()
152
- this[_edgesOverridden] = new Set()
142
+ this[_updateNames] = []
153
143
  this[_resolvedAdd] = []
154
144
 
155
145
  // a map of each module in a peer set to the thing that depended on
156
146
  // that set of peers in the first place. Use a WeakMap so that we
157
147
  // don't hold onto references for nodes that are garbage collected.
158
148
  this[_peerSetSource] = new WeakMap()
159
- this[_virtualRoots] = new Map()
160
149
 
161
150
  this[_includeWorkspaceRoot] = includeWorkspaceRoot
162
151
  }
163
152
 
164
153
  get explicitRequests () {
165
- return new Set(this[_explicitRequests])
154
+ return new Set(this.#explicitRequests)
166
155
  }
167
156
 
168
157
  // public method
@@ -195,19 +184,19 @@ module.exports = cls => class IdealTreeBuilder extends cls {
195
184
  // from there, we start adding nodes to it to satisfy the deps requested
196
185
  // by the package.json in the root.
197
186
 
198
- this[_parseSettings](options)
187
+ this.#parseSettings(options)
199
188
 
200
189
  // start tracker block
201
190
  this.addTracker('idealTree')
202
191
 
203
192
  try {
204
- await this[_initTree]()
205
- await this[_inflateAncientLockfile]()
206
- await this[_applyUserRequests](options)
207
- await this[_buildDeps]()
208
- await this[_fixDepFlags]()
209
- await this[_pruneFailedOptional]()
210
- await this[_checkEngineAndPlatform]()
193
+ await this.#initTree()
194
+ await this.#inflateAncientLockfile()
195
+ await this.#applyUserRequests(options)
196
+ await this.#buildDeps()
197
+ await this.#fixDepFlags()
198
+ await this.#pruneFailedOptional()
199
+ await this.#checkEngineAndPlatform()
211
200
  } finally {
212
201
  process.emit('timeEnd', 'idealTree')
213
202
  this.finishTracker('idealTree')
@@ -216,7 +205,7 @@ module.exports = cls => class IdealTreeBuilder extends cls {
216
205
  return treeCheck(this.idealTree)
217
206
  }
218
207
 
219
- async [_checkEngineAndPlatform] () {
208
+ async #checkEngineAndPlatform () {
220
209
  const { engineStrict, npmVersion, nodeVersion } = this.options
221
210
  for (const node of this.idealTree.inventory.values()) {
222
211
  if (!node.optional) {
@@ -237,7 +226,7 @@ module.exports = cls => class IdealTreeBuilder extends cls {
237
226
  }
238
227
  }
239
228
 
240
- [_parseSettings] (options) {
229
+ #parseSettings (options) {
241
230
  const update = options.update === true ? { all: true }
242
231
  : Array.isArray(options.update) ? { names: options.update }
243
232
  : options.update || {}
@@ -246,8 +235,8 @@ module.exports = cls => class IdealTreeBuilder extends cls {
246
235
  update.names = []
247
236
  }
248
237
 
249
- this[_complete] = !!options.complete
250
- this[_preferDedupe] = !!options.preferDedupe
238
+ this.#complete = !!options.complete
239
+ this.#preferDedupe = !!options.preferDedupe
251
240
 
252
241
  // validates list of update names, they must
253
242
  // be dep names only, no semver ranges are supported
@@ -267,11 +256,11 @@ module.exports = cls => class IdealTreeBuilder extends cls {
267
256
 
268
257
  this[_updateAll] = update.all
269
258
  // we prune by default unless explicitly set to boolean false
270
- this[_prune] = options.prune !== false
259
+ this.#prune = options.prune !== false
271
260
 
272
261
  // set if we add anything, but also set here if we know we'll make
273
262
  // changes and thus have to maybe prune later.
274
- this[_mutateTree] = !!(
263
+ this.#mutateTree = !!(
275
264
  options.add ||
276
265
  options.rm ||
277
266
  update.all ||
@@ -281,20 +270,23 @@ module.exports = cls => class IdealTreeBuilder extends cls {
281
270
 
282
271
  // load the initial tree, either the virtualTree from a shrinkwrap,
283
272
  // or just the root node from a package.json
284
- [_initTree] () {
273
+ async #initTree () {
285
274
  process.emit('time', 'idealTree:init')
286
- return (
287
- this[_global] ? this[_globalRootNode]()
288
- : rpj(this.path + '/package.json').then(
289
- pkg => this[_rootNodeFromPackage](pkg),
290
- er => {
291
- if (er.code === 'EJSONPARSE') {
292
- throw er
293
- }
294
- return this[_rootNodeFromPackage]({})
275
+ let root
276
+ if (this[_global]) {
277
+ root = await this.#globalRootNode()
278
+ } else {
279
+ try {
280
+ const pkg = await rpj(this.path + '/package.json')
281
+ root = await this.#rootNodeFromPackage(pkg)
282
+ } catch (err) {
283
+ if (err.code === 'EJSONPARSE') {
284
+ throw err
295
285
  }
296
- ))
297
- .then(root => this[_loadWorkspaces](root))
286
+ root = await this.#rootNodeFromPackage({})
287
+ }
288
+ }
289
+ return this[_setWorkspaces](root)
298
290
  // ok to not have a virtual tree. probably initial install.
299
291
  // When updating all, we load the shrinkwrap, but don't bother
300
292
  // to build out the full virtual tree from it, since we'll be
@@ -336,12 +328,18 @@ module.exports = cls => class IdealTreeBuilder extends cls {
336
328
  // the depsQueue so that we'll fix it later
337
329
  depth({
338
330
  tree,
339
- getChildren: (node) => [...node.edgesOut.values()].map(edge => edge.to),
331
+ getChildren: (node) => {
332
+ const children = []
333
+ for (const edge of node.edgesOut.values()) {
334
+ children.push(edge.to)
335
+ }
336
+ return children
337
+ },
340
338
  filter: node => node,
341
339
  visit: node => {
342
340
  for (const edge of node.edgesOut.values()) {
343
341
  if (!edge.valid) {
344
- this[_depsQueue].push(node)
342
+ this.#depsQueue.push(node)
345
343
  break // no need to continue the loop after the first hit
346
344
  }
347
345
  }
@@ -356,8 +354,8 @@ module.exports = cls => class IdealTreeBuilder extends cls {
356
354
  })
357
355
  }
358
356
 
359
- async [_globalRootNode] () {
360
- const root = await this[_rootNodeFromPackage]({ dependencies: {} })
357
+ async #globalRootNode () {
358
+ const root = await this.#rootNodeFromPackage({ dependencies: {} })
361
359
  // this is a gross kludge to handle the fact that we don't save
362
360
  // metadata on the root node in global installs, because the "root"
363
361
  // node is something like /usr/local/lib.
@@ -371,7 +369,7 @@ module.exports = cls => class IdealTreeBuilder extends cls {
371
369
  return root
372
370
  }
373
371
 
374
- async [_rootNodeFromPackage] (pkg) {
372
+ async #rootNodeFromPackage (pkg) {
375
373
  // if the path doesn't exist, then we explode at this point. Note that
376
374
  // this is not a problem for reify(), since it creates the root path
377
375
  // before ever loading trees.
@@ -414,19 +412,19 @@ module.exports = cls => class IdealTreeBuilder extends cls {
414
412
 
415
413
  // process the add/rm requests by modifying the root node, and the
416
414
  // update.names request by queueing nodes dependent on those named.
417
- async [_applyUserRequests] (options) {
415
+ async #applyUserRequests (options) {
418
416
  process.emit('time', 'idealTree:userRequests')
419
417
  const tree = this.idealTree.target
420
418
 
421
419
  if (!this[_workspaces].length) {
422
- await this[_applyUserRequestsToNode](tree, options)
420
+ await this.#applyUserRequestsToNode(tree, options)
423
421
  } else {
424
422
  const nodes = this.workspaceNodes(tree, this[_workspaces])
425
423
  if (this[_includeWorkspaceRoot]) {
426
424
  nodes.push(tree)
427
425
  }
428
426
  const appliedRequests = nodes.map(
429
- node => this[_applyUserRequestsToNode](node, options)
427
+ node => this.#applyUserRequestsToNode(node, options)
430
428
  )
431
429
  await Promise.all(appliedRequests)
432
430
  }
@@ -434,12 +432,12 @@ module.exports = cls => class IdealTreeBuilder extends cls {
434
432
  process.emit('timeEnd', 'idealTree:userRequests')
435
433
  }
436
434
 
437
- async [_applyUserRequestsToNode] (tree, options) {
435
+ async #applyUserRequestsToNode (tree, options) {
438
436
  // If we have a list of package names to update, and we know it's
439
437
  // going to update them wherever they are, add any paths into those
440
438
  // named nodes to the buildIdealTree queue.
441
439
  if (!this[_global] && this[_updateNames].length) {
442
- this[_queueNamedUpdates]()
440
+ this.#queueNamedUpdates()
443
441
  }
444
442
 
445
443
  // global updates only update the globalTop nodes, but we need to know
@@ -448,7 +446,8 @@ module.exports = cls => class IdealTreeBuilder extends cls {
448
446
  if (this[_global] && (this[_updateAll] || this[_updateNames].length)) {
449
447
  const nm = resolve(this.path, 'node_modules')
450
448
  const paths = await readdirScoped(nm).catch(() => [])
451
- for (const name of paths.map((p) => p.replace(/\\/g, '/'))) {
449
+ for (const p of paths) {
450
+ const name = p.replace(/\\/g, '/')
452
451
  tree.package.dependencies = tree.package.dependencies || {}
453
452
  const updateName = this[_updateNames].includes(name)
454
453
  if (this[_updateAll] || updateName) {
@@ -470,7 +469,7 @@ module.exports = cls => class IdealTreeBuilder extends cls {
470
469
  }
471
470
 
472
471
  if (this.auditReport && this.auditReport.size > 0) {
473
- await this[_queueVulnDependents](options)
472
+ await this.#queueVulnDependents(options)
474
473
  }
475
474
 
476
475
  const { add, rm } = options
@@ -478,12 +477,12 @@ module.exports = cls => class IdealTreeBuilder extends cls {
478
477
  if (rm && rm.length) {
479
478
  addRmPkgDeps.rm(tree.package, rm)
480
479
  for (const name of rm) {
481
- this[_explicitRequests].add({ from: tree, name, action: 'DELETE' })
480
+ this.#explicitRequests.add({ from: tree, name, action: 'DELETE' })
482
481
  }
483
482
  }
484
483
 
485
484
  if (add && add.length) {
486
- await this[_add](tree, options)
485
+ await this.#add(tree, options)
487
486
  }
488
487
 
489
488
  // triggers a refresh of all edgesOut. this has to be done BEFORE
@@ -495,19 +494,19 @@ module.exports = cls => class IdealTreeBuilder extends cls {
495
494
 
496
495
  for (const spec of this[_resolvedAdd]) {
497
496
  if (spec.tree === tree) {
498
- this[_explicitRequests].add(tree.edgesOut.get(spec.name))
497
+ this.#explicitRequests.add(tree.edgesOut.get(spec.name))
499
498
  }
500
499
  }
501
500
  for (const name of globalExplicitUpdateNames) {
502
- this[_explicitRequests].add(tree.edgesOut.get(name))
501
+ this.#explicitRequests.add(tree.edgesOut.get(name))
503
502
  }
504
503
 
505
- this[_depsQueue].push(tree)
504
+ this.#depsQueue.push(tree)
506
505
  }
507
506
 
508
507
  // This returns a promise because we might not have the name yet, and need to
509
508
  // call pacote.manifest to find the name.
510
- async [_add] (tree, { add, saveType = null, saveBundle = false }) {
509
+ async #add (tree, { add, saveType = null, saveBundle = false }) {
511
510
  // If we have a link it will need to be added relative to the target's path
512
511
  const path = tree.target.path
513
512
 
@@ -564,7 +563,7 @@ module.exports = cls => class IdealTreeBuilder extends cls {
564
563
  // what's in the bundle at each published manifest. Without that, we
565
564
  // can't possibly fix bundled deps without breaking a ton of other stuff,
566
565
  // and leaving the user subject to getting it overwritten later anyway.
567
- async [_queueVulnDependents] (options) {
566
+ async #queueVulnDependents (options) {
568
567
  for (const vuln of this.auditReport.values()) {
569
568
  for (const node of vuln.nodes) {
570
569
  const bundler = node.getBundler()
@@ -584,7 +583,7 @@ module.exports = cls => class IdealTreeBuilder extends cls {
584
583
 
585
584
  for (const edge of node.edgesIn) {
586
585
  this.addTracker('idealTree', edge.from.name, edge.from.location)
587
- this[_depsQueue].push(edge.from)
586
+ this.#depsQueue.push(edge.from)
588
587
  }
589
588
  }
590
589
  }
@@ -629,7 +628,7 @@ module.exports = cls => class IdealTreeBuilder extends cls {
629
628
  log.warn('audit', `Updating ${fixName} to ${version}, ` +
630
629
  `which is ${breakingMessage}.`)
631
630
 
632
- await this[_add](node, { add: [`${fixName}@${version}`] })
631
+ await this.#add(node, { add: [`${fixName}@${version}`] })
633
632
  nodesTouched.add(node)
634
633
  }
635
634
  }
@@ -639,7 +638,7 @@ module.exports = cls => class IdealTreeBuilder extends cls {
639
638
  }
640
639
  }
641
640
 
642
- [_avoidRange] (name) {
641
+ #avoidRange (name) {
643
642
  if (!this.auditReport) {
644
643
  return null
645
644
  }
@@ -650,7 +649,7 @@ module.exports = cls => class IdealTreeBuilder extends cls {
650
649
  return vuln.range
651
650
  }
652
651
 
653
- [_queueNamedUpdates] () {
652
+ #queueNamedUpdates () {
654
653
  // ignore top nodes, since they are not loaded the same way, and
655
654
  // probably have their own project associated with them.
656
655
 
@@ -661,25 +660,19 @@ module.exports = cls => class IdealTreeBuilder extends cls {
661
660
 
662
661
  // XXX this could be faster by doing a series of inventory.query('name')
663
662
  // calls rather than walking over everything in the tree.
664
- const set = this.idealTree.inventory
665
- .filter(n => this[_shouldUpdateNode](n))
666
- // XXX add any invalid edgesOut to the queue
667
- for (const node of set) {
668
- for (const edge of node.edgesIn) {
669
- this.addTracker('idealTree', edge.from.name, edge.from.location)
670
- this[_depsQueue].push(edge.from)
663
+ for (const node of this.idealTree.inventory.values()) {
664
+ // XXX add any invalid edgesOut to the queue
665
+ if (this[_updateNames].includes(node.name) &&
666
+ !node.isTop && !node.inDepBundle && !node.inShrinkwrap) {
667
+ for (const edge of node.edgesIn) {
668
+ this.addTracker('idealTree', edge.from.name, edge.from.location)
669
+ this.#depsQueue.push(edge.from)
670
+ }
671
671
  }
672
672
  }
673
673
  }
674
674
 
675
- [_shouldUpdateNode] (node) {
676
- return this[_updateNames].includes(node.name) &&
677
- !node.isTop &&
678
- !node.inDepBundle &&
679
- !node.inShrinkwrap
680
- }
681
-
682
- async [_inflateAncientLockfile] () {
675
+ async #inflateAncientLockfile () {
683
676
  const { meta, inventory } = this.idealTree
684
677
  const ancient = meta.ancientLockfile
685
678
  const old = meta.loadedFromDisk && !(meta.originalLockfileVersion >= 2)
@@ -764,38 +757,33 @@ This is a one-time fix-up, please be patient...
764
757
  // at this point we have a virtual tree with the actual root node's
765
758
  // package deps, which may be partly or entirely incomplete, invalid
766
759
  // or extraneous.
767
- [_buildDeps] () {
760
+ #buildDeps () {
768
761
  process.emit('time', 'idealTree:buildDeps')
769
762
  const tree = this.idealTree.target
770
763
  tree.assertRootOverrides()
771
- this[_depsQueue].push(tree)
764
+ this.#depsQueue.push(tree)
772
765
  // XXX also push anything that depends on a node with a name
773
766
  // in the override list
774
767
  log.silly('idealTree', 'buildDeps')
775
768
  this.addTracker('idealTree', tree.name, '')
776
- return this[_buildDepStep]()
769
+ return this.#buildDepStep()
777
770
  .then(() => process.emit('timeEnd', 'idealTree:buildDeps'))
778
771
  }
779
772
 
780
- async [_buildDepStep] () {
773
+ async #buildDepStep () {
781
774
  // removes tracker of previous dependency in the queue
782
- if (this[_currentDep]) {
783
- const { location, name } = this[_currentDep]
775
+ if (this.#currentDep) {
776
+ const { location, name } = this.#currentDep
784
777
  process.emit('timeEnd', `idealTree:${location || '#root'}`)
785
778
  this.finishTracker('idealTree', name, location)
786
- this[_currentDep] = null
779
+ this.#currentDep = null
787
780
  }
788
781
 
789
- if (!this[_depsQueue].length) {
790
- return this[_resolveLinks]()
782
+ if (!this.#depsQueue.length) {
783
+ return this.#resolveLinks()
791
784
  }
792
785
 
793
- // sort physically shallower deps up to the front of the queue,
794
- // because they'll affect things deeper in, then alphabetical
795
- this[_depsQueue].sort((a, b) =>
796
- (a.depth - b.depth) || localeCompare(a.path, b.path))
797
-
798
- const node = this[_depsQueue].shift()
786
+ const node = this.#depsQueue.pop()
799
787
  const bd = node.package.bundleDependencies
800
788
  const hasBundle = bd && Array.isArray(bd) && bd.length
801
789
  const { hasShrinkwrap } = node
@@ -804,14 +792,14 @@ This is a one-time fix-up, please be patient...
804
792
  // tree, skip over it and process the rest of the queue. If a node has
805
793
  // a shrinkwrap, also skip it, because it's going to get its deps
806
794
  // satisfied by whatever's in that file anyway.
807
- if (this[_depsSeen].has(node) ||
795
+ if (this.#depsSeen.has(node) ||
808
796
  node.root !== this.idealTree ||
809
- hasShrinkwrap && !this[_complete]) {
810
- return this[_buildDepStep]()
797
+ hasShrinkwrap && !this.#complete) {
798
+ return this.#buildDepStep()
811
799
  }
812
800
 
813
- this[_depsSeen].add(node)
814
- this[_currentDep] = node
801
+ this.#depsSeen.add(node)
802
+ this.#currentDep = node
815
803
  process.emit('time', `idealTree:${node.location || '#root'}`)
816
804
 
817
805
  // if we're loading a _complete_ ideal tree, for a --package-lock-only
@@ -821,7 +809,7 @@ This is a one-time fix-up, please be patient...
821
809
  // ideal tree by reading bundles/shrinkwraps in place.
822
810
  // Don't bother if the node is from the actual tree and hasn't
823
811
  // been resolved, because we can't fetch it anyway, could be anything!
824
- const crackOpen = this[_complete] &&
812
+ const crackOpen = this.#complete &&
825
813
  node !== this.idealTree &&
826
814
  node.resolved &&
827
815
  (hasBundle || hasShrinkwrap)
@@ -891,7 +879,7 @@ This is a one-time fix-up, please be patient...
891
879
 
892
880
  const tasks = []
893
881
  const peerSource = this[_peerSetSource].get(node) || node
894
- for (const edge of this[_problemEdges](node)) {
882
+ for (const edge of this.#problemEdges(node)) {
895
883
  if (edge.peerConflicted) {
896
884
  continue
897
885
  }
@@ -902,7 +890,7 @@ This is a one-time fix-up, please be patient...
902
890
  // so we VR the node itself if the edge is not a peer
903
891
  const source = edge.peer ? peerSource : node
904
892
 
905
- const virtualRoot = this[_virtualRoot](source, true)
893
+ const virtualRoot = this.#virtualRoot(source, true)
906
894
  // reuse virtual root if we already have one, but don't
907
895
  // try to do the override ahead of time, since we MAY be able
908
896
  // to create a more correct tree than the virtual root could.
@@ -926,7 +914,7 @@ This is a one-time fix-up, please be patient...
926
914
  const required = new Set([edge.from])
927
915
  const parent = edge.peer ? virtualRoot : null
928
916
  const dep = vrDep && vrDep.satisfies(edge) ? vrDep
929
- : await this[_nodeFromEdge](edge, parent, null, required)
917
+ : await this.#nodeFromEdge(edge, parent, null, required)
930
918
 
931
919
  /* istanbul ignore next */
932
920
  debug(() => {
@@ -938,25 +926,24 @@ This is a one-time fix-up, please be patient...
938
926
  tasks.push({ edge, dep })
939
927
  }
940
928
 
941
- const placeDeps = tasks
942
- .sort((a, b) => localeCompare(a.edge.name, b.edge.name))
943
- .map(({ edge, dep }) => new PlaceDep({
929
+ const placeDeps = tasks.sort((a, b) => localeCompare(a.edge.name, b.edge.name))
930
+
931
+ const promises = []
932
+ for (const { edge, dep } of placeDeps) {
933
+ const pd = new PlaceDep({
944
934
  edge,
945
935
  dep,
946
936
 
947
937
  auditReport: this.auditReport,
948
- explicitRequest: this[_explicitRequests].has(edge),
938
+ explicitRequest: this.#explicitRequests.has(edge),
949
939
  force: this[_force],
950
940
  installLinks: this.installLinks,
951
- installStrategy: this[_installStrategy],
941
+ installStrategy: this.#installStrategy,
952
942
  legacyPeerDeps: this.legacyPeerDeps,
953
- preferDedupe: this[_preferDedupe],
954
- strictPeerDeps: this[_strictPeerDeps],
943
+ preferDedupe: this.#preferDedupe,
944
+ strictPeerDeps: this.#strictPeerDeps,
955
945
  updateNames: this[_updateNames],
956
- }))
957
-
958
- const promises = []
959
- for (const pd of placeDeps) {
946
+ })
960
947
  // placing a dep is actually a tree of placing the dep itself
961
948
  // and all of its peer group that aren't already met by the tree
962
949
  depth({
@@ -971,18 +958,18 @@ This is a one-time fix-up, please be patient...
971
958
 
972
959
  // we placed something, that means we changed the tree
973
960
  if (placed.errors.length) {
974
- this[_loadFailures].add(placed)
961
+ this.#loadFailures.add(placed)
975
962
  }
976
- this[_mutateTree] = true
963
+ this.#mutateTree = true
977
964
  if (cpd.canPlaceSelf === OK) {
978
965
  for (const edgeIn of placed.edgesIn) {
979
966
  if (edgeIn === edge) {
980
967
  continue
981
968
  }
982
969
  const { from, valid, peerConflicted } = edgeIn
983
- if (!peerConflicted && !valid && !this[_depsSeen].has(from)) {
970
+ if (!peerConflicted && !valid && !this.#depsSeen.has(from)) {
984
971
  this.addTracker('idealTree', from.name, from.location)
985
- this[_depsQueue].push(edgeIn.from)
972
+ this.#depsQueue.push(edgeIn.from)
986
973
  }
987
974
  }
988
975
  } else {
@@ -1000,8 +987,8 @@ This is a one-time fix-up, please be patient...
1000
987
  if (!valid && !peerConflicted) {
1001
988
  // if it's already been visited, we have to re-visit
1002
989
  // otherwise, just enqueue normally.
1003
- this[_depsSeen].delete(edgeIn.from)
1004
- this[_depsQueue].push(edgeIn.from)
990
+ this.#depsSeen.delete(edgeIn.from)
991
+ this.#depsQueue.push(edgeIn.from)
1005
992
  }
1006
993
  }
1007
994
  }
@@ -1018,45 +1005,48 @@ This is a one-time fix-up, please be patient...
1018
1005
 
1019
1006
  // lastly, also check for the missing deps of the node we placed,
1020
1007
  // and any holes created by pruning out conflicted peer sets.
1021
- this[_depsQueue].push(placed)
1008
+ this.#depsQueue.push(placed)
1022
1009
  for (const dep of pd.needEvaluation) {
1023
- this[_depsSeen].delete(dep)
1024
- this[_depsQueue].push(dep)
1010
+ this.#depsSeen.delete(dep)
1011
+ this.#depsQueue.push(dep)
1025
1012
  }
1026
1013
 
1027
1014
  // pre-fetch any problem edges, since we'll need these soon
1028
1015
  // if it fails at this point, though, dont' worry because it
1029
1016
  // may well be an optional dep that has gone missing. it'll
1030
1017
  // fail later anyway.
1031
- promises.push(...this[_problemEdges](placed).map(e =>
1032
- this[_fetchManifest](npa.resolve(e.name, e.spec, fromPath(placed, e)))
1033
- .catch(er => null)))
1018
+ for (const e of this.#problemEdges(placed)) {
1019
+ promises.push(
1020
+ this.#fetchManifest(npa.resolve(e.name, e.spec, fromPath(placed, e)))
1021
+ .catch(er => null)
1022
+ )
1023
+ }
1034
1024
  },
1035
1025
  })
1036
1026
  }
1037
1027
 
1038
1028
  for (const { to } of node.edgesOut.values()) {
1039
1029
  if (to && to.isLink && to.target) {
1040
- this[_linkNodes].add(to)
1030
+ this.#linkNodes.add(to)
1041
1031
  }
1042
1032
  }
1043
1033
 
1044
1034
  await Promise.all(promises)
1045
- return this[_buildDepStep]()
1035
+ return this.#buildDepStep()
1046
1036
  }
1047
1037
 
1048
1038
  // loads a node from an edge, and then loads its peer deps (and their
1049
1039
  // peer deps, on down the line) into a virtual root parent.
1050
- async [_nodeFromEdge] (edge, parent_, secondEdge, required) {
1040
+ async #nodeFromEdge (edge, parent_, secondEdge, required) {
1051
1041
  // create a virtual root node with the same deps as the node that
1052
1042
  // is requesting this one, so that we can get all the peer deps in
1053
1043
  // a context where they're likely to be resolvable.
1054
1044
  // Note that the virtual root will also have virtual copies of the
1055
1045
  // targets of any child Links, so that they resolve appropriately.
1056
- const parent = parent_ || this[_virtualRoot](edge.from)
1046
+ const parent = parent_ || this.#virtualRoot(edge.from)
1057
1047
 
1058
1048
  const spec = npa.resolve(edge.name, edge.spec, edge.from.path)
1059
- const first = await this[_nodeFromSpec](edge.name, spec, parent, edge)
1049
+ const first = await this.#nodeFromSpec(edge.name, spec, parent, edge)
1060
1050
 
1061
1051
  // we might have a case where the parent has a peer dependency on
1062
1052
  // `foo@*` which resolves to v2, but another dep in the set has a
@@ -1071,7 +1061,7 @@ This is a one-time fix-up, please be patient...
1071
1061
  secondEdge.from.path
1072
1062
  )
1073
1063
  const second = secondEdge && !secondEdge.valid
1074
- ? await this[_nodeFromSpec](edge.name, spec2, parent, secondEdge)
1064
+ ? await this.#nodeFromSpec(edge.name, spec2, parent, secondEdge)
1075
1065
  : null
1076
1066
 
1077
1067
  // pick the second one if they're both happy with that, otherwise first
@@ -1098,12 +1088,12 @@ This is a one-time fix-up, please be patient...
1098
1088
  }
1099
1089
 
1100
1090
  // otherwise, we have to make sure that our peers can go along with us.
1101
- return this[_loadPeerSet](node, required)
1091
+ return this.#loadPeerSet(node, required)
1102
1092
  }
1103
1093
 
1104
- [_virtualRoot] (node, reuse = false) {
1105
- if (reuse && this[_virtualRoots].has(node)) {
1106
- return this[_virtualRoots].get(node)
1094
+ #virtualRoot (node, reuse = false) {
1095
+ if (reuse && this.#virtualRoots.has(node)) {
1096
+ return this.#virtualRoots.get(node)
1107
1097
  }
1108
1098
 
1109
1099
  const vr = new Node({
@@ -1126,11 +1116,11 @@ This is a one-time fix-up, please be patient...
1126
1116
  }
1127
1117
  }
1128
1118
 
1129
- this[_virtualRoots].set(node, vr)
1119
+ this.#virtualRoots.set(node, vr)
1130
1120
  return vr
1131
1121
  }
1132
1122
 
1133
- [_problemEdges] (node) {
1123
+ #problemEdges (node) {
1134
1124
  // skip over any bundled deps, they're not our problem.
1135
1125
  // Note that this WILL fetch bundled meta-deps which are also dependencies
1136
1126
  // but not listed as bundled deps. When reifying, we first unpack any
@@ -1145,85 +1135,90 @@ This is a one-time fix-up, please be patient...
1145
1135
  : node.package.bundleDependencies
1146
1136
  const bundled = new Set(bd || [])
1147
1137
 
1148
- return [...node.edgesOut.values()]
1149
- .filter(edge => {
1150
- // If it's included in a bundle, we take whatever is specified.
1151
- if (bundled.has(edge.name)) {
1152
- return false
1153
- }
1154
-
1155
- // If it's already been logged as a load failure, skip it.
1156
- if (edge.to && this[_loadFailures].has(edge.to)) {
1157
- return false
1158
- }
1138
+ const problems = []
1139
+ for (const edge of node.edgesOut.values()) {
1140
+ // If it's included in a bundle, we take whatever is specified.
1141
+ if (bundled.has(edge.name)) {
1142
+ continue
1143
+ }
1159
1144
 
1160
- // If it's shrinkwrapped, we use what the shrinkwap wants.
1161
- if (edge.to && edge.to.inShrinkwrap) {
1162
- return false
1163
- }
1145
+ // If it's already been logged as a load failure, skip it.
1146
+ if (edge.to && this.#loadFailures.has(edge.to)) {
1147
+ continue
1148
+ }
1164
1149
 
1165
- // If the edge has no destination, that's a problem, unless
1166
- // if it's peerOptional and not explicitly requested.
1167
- if (!edge.to) {
1168
- return edge.type !== 'peerOptional' ||
1169
- this[_explicitRequests].has(edge)
1170
- }
1150
+ // If it's shrinkwrapped, we use what the shrinkwap wants.
1151
+ if (edge.to && edge.to.inShrinkwrap) {
1152
+ continue
1153
+ }
1171
1154
 
1172
- // If the edge has an error, there's a problem.
1173
- if (!edge.valid) {
1174
- return true
1155
+ // If the edge has no destination, that's a problem, unless
1156
+ // if it's peerOptional and not explicitly requested.
1157
+ if (!edge.to) {
1158
+ if (edge.type !== 'peerOptional' ||
1159
+ this.#explicitRequests.has(edge)) {
1160
+ problems.push(edge)
1175
1161
  }
1162
+ continue
1163
+ }
1176
1164
 
1177
- // If the edge is a workspace, and it's valid, leave it alone
1178
- if (edge.to.isWorkspace) {
1179
- return false
1180
- }
1165
+ // If the edge has an error, there's a problem.
1166
+ if (!edge.valid) {
1167
+ problems.push(edge)
1168
+ continue
1169
+ }
1181
1170
 
1182
- // user explicitly asked to update this package by name, problem
1183
- if (this[_updateNames].includes(edge.name)) {
1184
- return true
1185
- }
1171
+ // If the edge is a workspace, and it's valid, leave it alone
1172
+ if (edge.to.isWorkspace) {
1173
+ continue
1174
+ }
1186
1175
 
1187
- // fixing a security vulnerability with this package, problem
1188
- if (this.auditReport && this.auditReport.isVulnerable(edge.to)) {
1189
- return true
1190
- }
1176
+ // user explicitly asked to update this package by name, problem
1177
+ if (this[_updateNames].includes(edge.name)) {
1178
+ problems.push(edge)
1179
+ continue
1180
+ }
1191
1181
 
1192
- // user has explicitly asked to install this package, problem
1193
- if (this[_explicitRequests].has(edge)) {
1194
- return true
1195
- }
1182
+ // fixing a security vulnerability with this package, problem
1183
+ if (this.auditReport && this.auditReport.isVulnerable(edge.to)) {
1184
+ problems.push(edge)
1185
+ continue
1186
+ }
1196
1187
 
1197
- // No problems!
1198
- return false
1199
- })
1188
+ // user has explicitly asked to install this package, problem
1189
+ if (this.#explicitRequests.has(edge)) {
1190
+ problems.push(edge)
1191
+ continue
1192
+ }
1193
+ }
1194
+ return problems
1200
1195
  }
1201
1196
 
1202
- async [_fetchManifest] (spec) {
1197
+ async #fetchManifest (spec) {
1203
1198
  const options = {
1204
1199
  ...this.options,
1205
- avoid: this[_avoidRange](spec.name),
1200
+ avoid: this.#avoidRange(spec.name),
1206
1201
  }
1207
1202
  // get the intended spec and stored metadata from yarn.lock file,
1208
1203
  // if available and valid.
1209
1204
  spec = this.idealTree.meta.checkYarnLock(spec, options)
1210
1205
 
1211
- if (this[_manifests].has(spec.raw)) {
1212
- return this[_manifests].get(spec.raw)
1206
+ if (this.#manifests.has(spec.raw)) {
1207
+ return this.#manifests.get(spec.raw)
1213
1208
  } else {
1214
1209
  const cleanRawSpec = cleanUrl(spec.rawSpec)
1215
1210
  log.silly('fetch manifest', spec.raw.replace(spec.rawSpec, cleanRawSpec))
1216
1211
  const p = pacote.manifest(spec, options)
1217
1212
  .then(mani => {
1218
- this[_manifests].set(spec.raw, mani)
1213
+ this.#manifests.set(spec.raw, mani)
1219
1214
  return mani
1220
1215
  })
1221
- this[_manifests].set(spec.raw, p)
1216
+ this.#manifests.set(spec.raw, p)
1222
1217
  return p
1223
1218
  }
1224
1219
  }
1225
1220
 
1226
- [_nodeFromSpec] (name, spec, parent, edge) {
1221
+ #nodeFromSpec (name, spec, parent, edge) {
1227
1222
  // pacote will slap integrity on its options, so we have to clone
1228
1223
  // the object so it doesn't get mutated.
1229
1224
  // Don't bother to load the manifest for link deps, because the target
@@ -1234,7 +1229,7 @@ This is a one-time fix-up, please be patient...
1234
1229
  // spec is a directory, link it unless installLinks is set or it's a workspace
1235
1230
  // TODO post arborist refactor, will need to check for installStrategy=linked
1236
1231
  if (spec.type === 'directory' && (isWorkspace || !installLinks)) {
1237
- return this[_linkFromSpec](name, spec, parent, edge)
1232
+ return this.#linkFromSpec(name, spec, parent, edge)
1238
1233
  }
1239
1234
 
1240
1235
  // if the spec matches a workspace name, then see if the workspace node will
@@ -1249,7 +1244,7 @@ This is a one-time fix-up, please be patient...
1249
1244
 
1250
1245
  // spec isn't a directory, and either isn't a workspace or the workspace we have
1251
1246
  // doesn't satisfy the edge. try to fetch a manifest and build a node from that.
1252
- return this[_fetchManifest](spec)
1247
+ return this.#fetchManifest(spec)
1253
1248
  .then(pkg => new Node({ name, pkg, parent, installLinks, legacyPeerDeps }), error => {
1254
1249
  error.requiredBy = edge.from.location || '.'
1255
1250
 
@@ -1263,17 +1258,17 @@ This is a one-time fix-up, please be patient...
1263
1258
  installLinks,
1264
1259
  legacyPeerDeps,
1265
1260
  })
1266
- this[_loadFailures].add(n)
1261
+ this.#loadFailures.add(n)
1267
1262
  return n
1268
1263
  })
1269
1264
  }
1270
1265
 
1271
- [_linkFromSpec] (name, spec, parent, edge) {
1266
+ #linkFromSpec (name, spec, parent, edge) {
1272
1267
  const realpath = spec.fetchSpec
1273
1268
  const { installLinks, legacyPeerDeps } = this
1274
1269
  return rpj(realpath + '/package.json').catch(() => ({})).then(pkg => {
1275
1270
  const link = new Link({ name, parent, realpath, pkg, installLinks, legacyPeerDeps })
1276
- this[_linkNodes].add(link)
1271
+ this.#linkNodes.add(link)
1277
1272
  return link
1278
1273
  })
1279
1274
  }
@@ -1291,7 +1286,7 @@ This is a one-time fix-up, please be patient...
1291
1286
  // gets placed first. In non-strict mode, we behave strictly if the
1292
1287
  // virtual root is based on the root project, and allow non-peer parent
1293
1288
  // deps to override, but throw if no preference can be determined.
1294
- async [_loadPeerSet] (node, required) {
1289
+ async #loadPeerSet (node, required) {
1295
1290
  const peerEdges = [...node.edgesOut.values()]
1296
1291
  // we typically only install non-optional peers, but we have to
1297
1292
  // factor them into the peerSet so that we can avoid conflicts
@@ -1307,12 +1302,12 @@ This is a one-time fix-up, please be patient...
1307
1302
  const parentEdge = node.parent.edgesOut.get(edge.name)
1308
1303
  const { isProjectRoot, isWorkspace } = node.parent.sourceReference
1309
1304
  const isMine = isProjectRoot || isWorkspace
1310
- const conflictOK = this[_force] || !isMine && !this[_strictPeerDeps]
1305
+ const conflictOK = this[_force] || !isMine && !this.#strictPeerDeps
1311
1306
 
1312
1307
  if (!edge.to) {
1313
1308
  if (!parentEdge) {
1314
1309
  // easy, just put the thing there
1315
- await this[_nodeFromEdge](edge, node.parent, null, required)
1310
+ await this.#nodeFromEdge(edge, node.parent, null, required)
1316
1311
  continue
1317
1312
  } else {
1318
1313
  // if the parent's edge is very broad like >=1, and the edge in
@@ -1323,7 +1318,7 @@ This is a one-time fix-up, please be patient...
1323
1318
  // a conflict. this is always a problem in strict mode, never
1324
1319
  // in force mode, and a problem in non-strict mode if this isn't
1325
1320
  // on behalf of our project. in all such cases, we warn at least.
1326
- const dep = await this[_nodeFromEdge](
1321
+ const dep = await this.#nodeFromEdge(
1327
1322
  parentEdge,
1328
1323
  node.parent,
1329
1324
  edge,
@@ -1344,7 +1339,7 @@ This is a one-time fix-up, please be patient...
1344
1339
  }
1345
1340
 
1346
1341
  // problem
1347
- this[_failPeerConflict](edge, parentEdge)
1342
+ this.#failPeerConflict(edge, parentEdge)
1348
1343
  }
1349
1344
  }
1350
1345
 
@@ -1352,9 +1347,9 @@ This is a one-time fix-up, please be patient...
1352
1347
  // See if the thing we WOULD be happy with is also going to satisfy
1353
1348
  // the other dependents on the current node.
1354
1349
  const current = edge.to
1355
- const dep = await this[_nodeFromEdge](edge, null, null, required)
1350
+ const dep = await this.#nodeFromEdge(edge, null, null, required)
1356
1351
  if (dep.canReplace(current)) {
1357
- await this[_nodeFromEdge](edge, node.parent, null, required)
1352
+ await this.#nodeFromEdge(edge, node.parent, null, required)
1358
1353
  continue
1359
1354
  }
1360
1355
 
@@ -1371,17 +1366,17 @@ This is a one-time fix-up, please be patient...
1371
1366
  }
1372
1367
 
1373
1368
  // ok, it's the root, or we're in unforced strict mode, so this is bad
1374
- this[_failPeerConflict](edge, parentEdge)
1369
+ this.#failPeerConflict(edge, parentEdge)
1375
1370
  }
1376
1371
  return node
1377
1372
  }
1378
1373
 
1379
- [_failPeerConflict] (edge, currentEdge) {
1380
- const expl = this[_explainPeerConflict](edge, currentEdge)
1374
+ #failPeerConflict (edge, currentEdge) {
1375
+ const expl = this.#explainPeerConflict(edge, currentEdge)
1381
1376
  throw Object.assign(new Error('unable to resolve dependency tree'), expl)
1382
1377
  }
1383
1378
 
1384
- [_explainPeerConflict] (edge, currentEdge) {
1379
+ #explainPeerConflict (edge, currentEdge) {
1385
1380
  const node = edge.from
1386
1381
  const curNode = node.resolve(edge.name)
1387
1382
  const current = curNode.explain()
@@ -1393,12 +1388,12 @@ This is a one-time fix-up, please be patient...
1393
1388
  // the tree handling logic.
1394
1389
  currentEdge: currentEdge ? currentEdge.explain() : null,
1395
1390
  edge: edge.explain(),
1396
- strictPeerDeps: this[_strictPeerDeps],
1391
+ strictPeerDeps: this.#strictPeerDeps,
1397
1392
  force: this[_force],
1398
1393
  }
1399
1394
  }
1400
1395
 
1401
- // go through all the links in the this[_linkNodes] set
1396
+ // go through all the links in the this.#linkNodes set
1402
1397
  // for each one:
1403
1398
  // - if outside the root, ignore it, assume it's fine, it's not our problem
1404
1399
  // - if a node in the tree already, assign the target to that node.
@@ -1406,9 +1401,9 @@ This is a one-time fix-up, please be patient...
1406
1401
  // and add it to the _depsQueue
1407
1402
  //
1408
1403
  // call buildDepStep if anything was added to the queue, otherwise we're done
1409
- [_resolveLinks] () {
1410
- for (const link of this[_linkNodes]) {
1411
- this[_linkNodes].delete(link)
1404
+ #resolveLinks () {
1405
+ for (const link of this.#linkNodes) {
1406
+ this.#linkNodes.delete(link)
1412
1407
 
1413
1408
  // link we never ended up placing, skip it
1414
1409
  if (link.root !== this.idealTree) {
@@ -1419,34 +1414,34 @@ This is a one-time fix-up, please be patient...
1419
1414
  const external = !link.target.isDescendantOf(tree)
1420
1415
 
1421
1416
  // outside the root, somebody else's problem, ignore it
1422
- if (external && !this[_follow]) {
1417
+ if (external && !this.#follow) {
1423
1418
  continue
1424
1419
  }
1425
1420
 
1426
1421
  // didn't find a parent for it or it has not been seen yet
1427
1422
  // so go ahead and process it.
1428
1423
  const unseenLink = (link.target.parent || link.target.fsParent) &&
1429
- !this[_depsSeen].has(link.target)
1424
+ !this.#depsSeen.has(link.target)
1430
1425
 
1431
- if (this[_follow] &&
1426
+ if (this.#follow &&
1432
1427
  !link.target.parent &&
1433
1428
  !link.target.fsParent ||
1434
1429
  unseenLink) {
1435
1430
  this.addTracker('idealTree', link.target.name, link.target.location)
1436
- this[_depsQueue].push(link.target)
1431
+ this.#depsQueue.push(link.target)
1437
1432
  }
1438
1433
  }
1439
1434
 
1440
- if (this[_depsQueue].length) {
1441
- return this[_buildDepStep]()
1435
+ if (this.#depsQueue.length) {
1436
+ return this.#buildDepStep()
1442
1437
  }
1443
1438
  }
1444
1439
 
1445
- [_fixDepFlags] () {
1440
+ #fixDepFlags () {
1446
1441
  process.emit('time', 'idealTree:fixDepFlags')
1447
1442
  const metaFromDisk = this.idealTree.meta.loadedFromDisk
1448
1443
  const flagsSuspect = this[_flagsSuspect]
1449
- const mutateTree = this[_mutateTree]
1444
+ const mutateTree = this.#mutateTree
1450
1445
  // if the options set prune:false, then we don't prune, but we still
1451
1446
  // mark the extraneous items in the tree if we modified it at all.
1452
1447
  // If we did no modifications, we just iterate over the extraneous nodes.
@@ -1481,21 +1476,28 @@ This is a one-time fix-up, please be patient...
1481
1476
  // then the tree is suspect. Prune what is marked as extraneous.
1482
1477
  // otherwise, don't bother.
1483
1478
  const needPrune = metaFromDisk && (mutateTree || flagsSuspect)
1484
- if (this[_prune] && needPrune) {
1479
+ if (this.#prune && needPrune) {
1485
1480
  this[_idealTreePrune]()
1481
+ for (const node of this.idealTree.inventory.values()) {
1482
+ if (node.extraneous) {
1483
+ node.parent = null
1484
+ }
1485
+ }
1486
1486
  }
1487
1487
 
1488
1488
  process.emit('timeEnd', 'idealTree:fixDepFlags')
1489
1489
  }
1490
1490
 
1491
1491
  [_idealTreePrune] () {
1492
- for (const node of this.idealTree.inventory.filter(n => n.extraneous)) {
1493
- node.parent = null
1492
+ for (const node of this.idealTree.inventory.values()) {
1493
+ if (node.extraneous) {
1494
+ node.parent = null
1495
+ }
1494
1496
  }
1495
1497
  }
1496
1498
 
1497
- [_pruneFailedOptional] () {
1498
- for (const node of this[_loadFailures]) {
1499
+ #pruneFailedOptional () {
1500
+ for (const node of this.#loadFailures) {
1499
1501
  if (!node.optional) {
1500
1502
  throw node.errors[0]
1501
1503
  }