Skip to content

Commit 05319f0

Browse files
authored
fix: code cleanup (#8677)
- constructor logic was consolidated. It takes place in the main Arborist constructor when possible, allowing us to see all of the constructor at once and find any duplications or problems. It's evident that our approach to options/this.options needs some attention. - Some small single-use methods were inlined into the code that called them. In many cases this prevented re-pulling variables from `this`. - remove unused param from call to `#linkFromSpec`. The function is not expecting a fourth parameter. - remove unused private attributes, `#dryRun` and `#savePrefix` are not used anymore
1 parent 4bff14b commit 05319f0

File tree

9 files changed

+81
-110
lines changed

9 files changed

+81
-110
lines changed

workspaces/arborist/lib/arborist/build-ideal-tree.js

Lines changed: 17 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ const _flagsSuspect = Symbol.for('flagsSuspect')
4242
const _setWorkspaces = Symbol.for('setWorkspaces')
4343
const _updateNames = Symbol.for('updateNames')
4444
const _resolvedAdd = Symbol.for('resolvedAdd')
45-
const _usePackageLock = Symbol.for('usePackageLock')
4645
const _rpcache = Symbol.for('realpathCache')
4746
const _stcache = Symbol.for('statCache')
4847

@@ -101,39 +100,28 @@ module.exports = cls => class IdealTreeBuilder extends cls {
101100
constructor (options) {
102101
super(options)
103102

104-
// normalize trailing slash
105-
const registry = options.registry || 'https://registry.npmjs.org'
106-
options.registry = this.registry = registry.replace(/(?<!\/)\/+$/, '') + '/'
107-
108103
const {
109104
follow = false,
110105
installStrategy = 'hoisted',
111-
idealTree = null,
112-
installLinks = false,
113-
legacyPeerDeps = false,
114-
packageLock = true,
115106
strictPeerDeps = false,
116-
workspaces,
117107
global,
118108
} = options
119109

120110
this.#strictPeerDeps = !!strictPeerDeps
121111

122-
this.idealTree = idealTree
123-
this.installLinks = installLinks
124-
this.legacyPeerDeps = legacyPeerDeps
125-
126-
this[_usePackageLock] = packageLock
127112
this.#installStrategy = global ? 'shallow' : installStrategy
128113
this.#follow = !!follow
129114

130-
if (workspaces?.length && global) {
131-
throw new Error('Cannot operate on workspaces in global mode')
132-
}
133-
134115
this[_updateAll] = false
135116
this[_updateNames] = []
136117
this[_resolvedAdd] = []
118+
119+
// caches for cached realpath calls
120+
const cwd = process.cwd()
121+
// assume that the cwd is real enough for our purposes
122+
this[_rpcache] = new Map([[cwd, cwd]])
123+
this[_stcache] = new Map()
124+
this[_flagsSuspect] = false
137125
}
138126

139127
get explicitRequests () {
@@ -298,7 +286,7 @@ module.exports = cls => class IdealTreeBuilder extends cls {
298286
.then(root => {
299287
if (this.options.global) {
300288
return root
301-
} else if (!this[_usePackageLock] || this[_updateAll]) {
289+
} else if (!this.options.usePackageLock || this[_updateAll]) {
302290
return Shrinkwrap.reset({
303291
path: this.path,
304292
lockfileVersion: this.options.lockfileVersion,
@@ -1231,7 +1219,7 @@ This is a one-time fix-up, please be patient...
12311219
}
12321220
}
12331221

1234-
#nodeFromSpec (name, spec, parent, edge) {
1222+
async #nodeFromSpec (name, spec, parent, edge) {
12351223
// pacote will slap integrity on its options, so we have to clone
12361224
// the object so it doesn't get mutated.
12371225
// Don't bother to load the manifest for link deps, because the target
@@ -1260,7 +1248,13 @@ This is a one-time fix-up, please be patient...
12601248
// Decide whether to link or copy the dependency
12611249
const shouldLink = (isWorkspace || isProjectInternalFileSpec || !installLinks) && !isTransitiveFileDep
12621250
if (spec.type === 'directory' && shouldLink) {
1263-
return this.#linkFromSpec(name, spec, parent, edge)
1251+
const realpath = spec.fetchSpec
1252+
const { content: pkg } = await PackageJson.normalize(realpath).catch(() => {
1253+
return { content: {} }
1254+
})
1255+
const link = new Link({ name, parent, realpath, pkg, installLinks, legacyPeerDeps })
1256+
this.#linkNodes.add(link)
1257+
return link
12641258
}
12651259

12661260
// if the spec matches a workspace name, then see if the workspace node will satisfy the edge. if it does, we return the workspace node to make sure it takes priority.
@@ -1301,17 +1295,6 @@ This is a one-time fix-up, please be patient...
13011295
})
13021296
}
13031297

1304-
async #linkFromSpec (name, spec, parent) {
1305-
const realpath = spec.fetchSpec
1306-
const { installLinks, legacyPeerDeps } = this
1307-
const { content: pkg } = await PackageJson.normalize(realpath).catch(() => {
1308-
return { content: {} }
1309-
})
1310-
const link = new Link({ name, parent, realpath, pkg, installLinks, legacyPeerDeps })
1311-
this.#linkNodes.add(link)
1312-
return link
1313-
}
1314-
13151298
// load all peer deps and meta-peer deps into the node's parent
13161299
// At the end of this, the node's peer-type outward edges are all
13171300
// resolved, and so are all of theirs, but other dep types are not.
@@ -1446,6 +1429,7 @@ This is a one-time fix-up, please be patient...
14461429
// and add it to the _depsQueue
14471430
//
14481431
// call buildDepStep if anything was added to the queue; otherwise, we're done
1432+
// XXX load-virtual also has a #resolveLinks, is there overlap?
14491433
#resolveLinks () {
14501434
for (const link of this.#linkNodes) {
14511435
this.#linkNodes.delete(link)

workspaces/arborist/lib/arborist/index.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,34 @@ class Arborist extends Base {
6868
constructor (options = {}) {
6969
const timeEnd = time.start('arborist:ctor')
7070
super(options)
71+
72+
// normalize trailing slash
73+
const registry = options.registry || 'https://registry.npmjs.org'
74+
options.registry = this.registry = registry.replace(/(?<!\/)\/+$/, '') + '/'
75+
76+
// TODO as we consolidate constructors it's more apparent that we are not parsing options and using this.options consistently
77+
const {
78+
actualTree,
79+
global,
80+
idealTree = null,
81+
installLinks = false,
82+
legacyPeerDeps = false,
83+
virtualTree,
84+
workspaces,
85+
} = options
86+
87+
if (workspaces?.length && global) {
88+
throw new Error('Cannot operate on workspaces in global mode')
89+
}
90+
91+
// the tree of nodes on disk
92+
this.actualTree = actualTree
93+
this.idealTree = idealTree
94+
this.installLinks = installLinks
95+
this.legacyPeerDeps = legacyPeerDeps
96+
// the virtual tree we load from a shrinkwrap
97+
this.virtualTree = virtualTree
98+
7199
this.options = {
72100
nodeVersion: process.version,
73101
...options,
@@ -88,6 +116,7 @@ class Arborist extends Base {
88116
replaceRegistryHost: options.replaceRegistryHost,
89117
savePrefix: 'savePrefix' in options ? options.savePrefix : '^',
90118
scriptShell: options.scriptShell,
119+
usePackageLock: 'packageLock' in options ? options.packageLock : true,
91120
workspaces: options.workspaces || [],
92121
workspacesEnabled: options.workspacesEnabled !== false,
93122
}
@@ -104,6 +133,7 @@ class Arborist extends Base {
104133
this.cache = resolve(this.options.cache)
105134
this.diff = null
106135
this.path = resolve(this.options.path)
136+
this.scriptsRun = new Set()
107137
timeEnd()
108138
}
109139

workspaces/arborist/lib/arborist/isolated-reifier.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
const _makeIdealGraph = Symbol('makeIdealGraph')
22
const _createIsolatedTree = Symbol.for('createIsolatedTree')
3-
const _createBundledTree = Symbol('createBundledTree')
43
const { mkdirSync } = require('node:fs')
54
const pacote = require('pacote')
65
const { join } = require('node:path')
@@ -162,7 +161,7 @@ module.exports = cls => class IsolatedReifier extends cls {
162161
result.hasInstallScript = node.hasInstallScript
163162
}
164163

165-
async [_createBundledTree] () {
164+
async #createBundledTree () {
166165
// TODO: make sure that idealTree object exists
167166
const idealTree = this.idealTree
168167
// TODO: test workspaces having bundled deps
@@ -217,7 +216,7 @@ module.exports = cls => class IsolatedReifier extends cls {
217216

218217
const proxiedIdealTree = this.idealGraph
219218

220-
const bundledTree = await this[_createBundledTree]()
219+
const bundledTree = await this.#createBundledTree()
221220

222221
const treeHash = (startNode) => {
223222
// generate short hash based on the dependency tree

workspaces/arborist/lib/arborist/load-actual.js

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -41,19 +41,6 @@ module.exports = cls => class ActualLoader extends cls {
4141
#topNodes = new Set()
4242
#transplantFilter
4343

44-
constructor (options) {
45-
super(options)
46-
47-
// the tree of nodes on disk
48-
this.actualTree = options.actualTree
49-
50-
// caches for cached realpath calls
51-
const cwd = process.cwd()
52-
// assume that the cwd is real enough for our purposes
53-
this[_rpcache] = new Map([[cwd, cwd]])
54-
this[_stcache] = new Map()
55-
}
56-
5744
// public method
5845
// TODO remove options param in next semver major
5946
async loadActual (options = {}) {

workspaces/arborist/lib/arborist/load-virtual.js

Lines changed: 16 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,6 @@ const setWorkspaces = Symbol.for('setWorkspaces')
1818
module.exports = cls => class VirtualLoader extends cls {
1919
#rootOptionProvided
2020

21-
constructor (options) {
22-
super(options)
23-
24-
// the virtual tree we load from a shrinkwrap
25-
this.virtualTree = options.virtualTree
26-
this[flagsSuspect] = false
27-
}
28-
2921
// public method
3022
async loadVirtual (options = {}) {
3123
if (this.virtualTree) {
@@ -77,7 +69,21 @@ module.exports = cls => class VirtualLoader extends cls {
7769
this.#checkRootEdges(s, root)
7870
root.meta = s
7971
this.virtualTree = root
80-
const { links, nodes } = this.#resolveNodes(s, root)
72+
// separate out link metadata, and create Node objects for nodes
73+
const links = new Map()
74+
const nodes = new Map([['', root]])
75+
for (const [location, meta] of Object.entries(s.data.packages)) {
76+
// skip the root because we already got it
77+
if (!location) {
78+
continue
79+
}
80+
81+
if (meta.link) {
82+
links.set(location, meta)
83+
} else {
84+
nodes.set(location, this.#loadNode(location, meta))
85+
}
86+
}
8187
await this.#resolveLinks(links, nodes)
8288
if (!(s.originalLockfileVersion >= 2)) {
8389
this.#assignBundles(nodes)
@@ -160,27 +166,9 @@ module.exports = cls => class VirtualLoader extends cls {
160166
}
161167
}
162168

163-
// separate out link metadata, and create Node objects for nodes
164-
#resolveNodes (s, root) {
165-
const links = new Map()
166-
const nodes = new Map([['', root]])
167-
for (const [location, meta] of Object.entries(s.data.packages)) {
168-
// skip the root because we already got it
169-
if (!location) {
170-
continue
171-
}
172-
173-
if (meta.link) {
174-
links.set(location, meta)
175-
} else {
176-
nodes.set(location, this.#loadNode(location, meta))
177-
}
178-
}
179-
return { links, nodes }
180-
}
181-
182169
// links is the set of metadata, and nodes is the map of non-Link nodes
183170
// Set the targets to nodes in the set, if we have them (we might not)
171+
// XXX build-ideal-tree also has a #resolveLinks, is there overlap?
184172
async #resolveLinks (links, nodes) {
185173
for (const [location, meta] of links.entries()) {
186174
const targetPath = resolve(this.path, meta.resolved)

workspaces/arborist/lib/arborist/rebuild.js

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,12 @@ const _trashList = Symbol.for('trashList')
2424
module.exports = cls => class Builder extends cls {
2525
#doHandleOptionalFailure
2626
#oldMeta = null
27-
#queues
28-
29-
constructor (options) {
30-
super(options)
31-
32-
this.scriptsRun = new Set()
33-
this.#resetQueues()
27+
#queues = {
28+
preinstall: [],
29+
install: [],
30+
postinstall: [],
31+
prepare: [],
32+
bin: [],
3433
}
3534

3635
async rebuild ({ nodes, handleOptionalFailure = false } = {}) {
@@ -62,7 +61,13 @@ module.exports = cls => class Builder extends cls {
6261

6362
// build link deps
6463
if (linkNodes.size) {
65-
this.#resetQueues()
64+
this.#queues = {
65+
preinstall: [],
66+
install: [],
67+
postinstall: [],
68+
prepare: [],
69+
bin: [],
70+
}
6671
await this.#build(linkNodes, { type: 'links' })
6772
}
6873

@@ -132,16 +137,6 @@ module.exports = cls => class Builder extends cls {
132137
}
133138
}
134139

135-
#resetQueues () {
136-
this.#queues = {
137-
preinstall: [],
138-
install: [],
139-
postinstall: [],
140-
prepare: [],
141-
bin: [],
142-
}
143-
}
144-
145140
async #build (nodes, { type = 'deps' }) {
146141
const timeEnd = time.start(`build:${type}`)
147142

workspaces/arborist/lib/arborist/reify.js

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,9 @@ const _rollbackRetireShallowNodes = Symbol.for('rollbackRetireShallowNodes')
5757
const _rollbackCreateSparseTree = Symbol.for('rollbackCreateSparseTree')
5858
const _rollbackMoveBackRetiredUnchanged = Symbol.for('rollbackMoveBackRetiredUnchanged')
5959
const _saveIdealTree = Symbol.for('saveIdealTree')
60-
const _reifyPackages = Symbol.for('reifyPackages')
6160

6261
// defined by build-ideal-tree mixin
6362
const _resolvedAdd = Symbol.for('resolvedAdd')
64-
const _usePackageLock = Symbol.for('usePackageLock')
6563
// used by build-ideal-tree mixin
6664
const _addNodeToTrashList = Symbol.for('addNodeToTrashList')
6765

@@ -70,12 +68,10 @@ const _createIsolatedTree = Symbol.for('createIsolatedTree')
7068
module.exports = cls => class Reifier extends cls {
7169
#bundleMissing = new Set() // child nodes we'd EXPECT to be included in a bundle, but aren't
7270
#bundleUnpacked = new Set() // the nodes we unpack to read their bundles
73-
#dryRun
7471
#nmValidated = new Set()
7572
#omit
7673
#retiredPaths = {}
7774
#retiredUnchanged = {}
78-
#savePrefix
7975
#shrinkwrapInflated = new Set()
8076
#sparseTreeDirs = new Set()
8177
#sparseTreeRoots = new Set()
@@ -122,7 +118,7 @@ module.exports = cls => class Reifier extends cls {
122118
this.idealTree = await this[_createIsolatedTree]()
123119
}
124120
await this[_diffTrees]()
125-
await this[_reifyPackages]()
121+
await this.#reifyPackages()
126122
if (linked) {
127123
// swap back in the idealTree
128124
// so that the lockfile is preserved
@@ -261,7 +257,7 @@ module.exports = cls => class Reifier extends cls {
261257
return treeCheck(this.actualTree)
262258
}
263259

264-
async [_reifyPackages] () {
260+
async #reifyPackages () {
265261
// we don't submit the audit report or write to disk on dry runs
266262
if (this.options.dryRun) {
267263
return
@@ -1496,7 +1492,7 @@ module.exports = cls => class Reifier extends cls {
14961492

14971493
// before now edge specs could be changing, affecting the `requires` field
14981494
// in the package lock, so we hold off saving to the very last action
1499-
if (this[_usePackageLock]) {
1495+
if (this.options.usePackageLock) {
15001496
// preserve indentation, if possible
15011497
let format = this.idealTree.package[Symbol.for('indent')]
15021498
if (format === undefined) {

workspaces/arborist/lib/optional-set.js

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,6 @@
1010

1111
const gatherDepSet = require('./gather-dep-set.js')
1212
const optionalSet = node => {
13-
if (!node.optional) {
14-
return new Set()
15-
}
16-
1713
// start with the node, then walk up the dependency graph until we
1814
// get to the boundaries that define the optional set. since the
1915
// node is optional, we know that all paths INTO this area of the

0 commit comments

Comments
 (0)