Skip to content

Commit 1206f8b

Browse files
authored
fix: consolidate isolated node/link attributes (#9069)
1 parent 3b96929 commit 1206f8b

File tree

5 files changed

+224
-202
lines changed

5 files changed

+224
-202
lines changed

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

Lines changed: 47 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ const pacote = require('pacote')
33
const { join } = require('node:path')
44
const { depth } = require('treeverse')
55
const crypto = require('node:crypto')
6+
const { IsolatedNode, IsolatedLink } = require('../isolated-classes.js')
67

78
// generate short hash key based on the dependency tree starting at this node
89
const getKey = (startNode) => {
@@ -36,40 +37,20 @@ module.exports = cls => class IsolatedReifier extends cls {
3637
#processedEdges = new Set()
3738
#workspaceProxies = new Map()
3839

39-
#generateChild (node, location, pkg, inStore, root) {
40-
const newChild = {
41-
binPaths: [],
42-
children: new Map(),
43-
edgesIn: new Set(),
44-
edgesOut: new Map(),
45-
fsChildren: new Set(),
46-
/* istanbul ignore next -- emulate Node */
47-
getBundler () {
48-
return null
49-
},
50-
global: false,
51-
globalTop: false,
52-
hasShrinkwrap: false,
53-
inDepBundle: false,
54-
integrity: null,
55-
isInStore: inStore,
56-
isLink: false,
57-
isProjectRoot: false,
58-
isRoot: false,
59-
isTop: false,
40+
#generateChild (node, location, pkg, isInStore, root) {
41+
const newChild = new IsolatedNode({
42+
isInStore,
6043
location,
6144
name: node.packageName || node.name,
6245
optional: node.optional,
6346
package: pkg,
6447
parent: root,
65-
path: join(this.idealGraph.root.localPath, location),
66-
realpath: join(this.idealGraph.root.localPath, location),
48+
path: join(this.idealGraph.localPath, location),
6749
resolved: node.resolved,
6850
root,
69-
top: { path: this.idealGraph.root.localPath },
70-
version: pkg.version,
71-
}
72-
newChild.target = newChild
51+
})
52+
// XXX top is from place-dep not lib/node.js
53+
newChild.top = { path: this.idealGraph.localPath }
7354
root.children.set(newChild.location, newChild)
7455
root.inventory.set(newChild.location, newChild)
7556
}
@@ -92,15 +73,17 @@ module.exports = cls => class IsolatedReifier extends cls {
9273
const idealTree = this.idealTree
9374
const omit = new Set(this.options.omit)
9475

76+
// XXX this sometimes acts like a node too
9577
this.idealGraph = {
9678
external: [],
9779
isProjectRoot: true,
9880
localLocation: idealTree.location,
9981
localPath: idealTree.path,
82+
path: idealTree.path,
10083
}
10184
this.counter = 0
10285

103-
this.idealGraph.workspaces = await Promise.all(Array.from(idealTree.fsChildren.values(), w => this.workspaceProxy(w)))
86+
this.idealGraph.workspaces = await Promise.all(Array.from(idealTree.fsChildren.values(), w => this.#workspaceProxy(w)))
10487
const processed = new Set()
10588
const queue = [idealTree, ...idealTree.fsChildren]
10689
while (queue.length !== 0) {
@@ -110,45 +93,43 @@ module.exports = cls => class IsolatedReifier extends cls {
11093
}
11194
processed.add(next.location)
11295
next.edgesOut.forEach(edge => {
113-
if (edge.to && !(next.package.bundleDependencies || next.package.bundledDependencies || []).includes(edge.to.name)) {
114-
if (!edge.to.shouldOmit?.(omit)) {
115-
queue.push(edge.to)
116-
}
96+
if (edge.to && !(next.package.bundleDependencies || next.package.bundledDependencies || []).includes(edge.to.name) && !edge.to.shouldOmit?.(omit)) {
97+
queue.push(edge.to)
11798
}
11899
})
119100
// local `file:` deps are in fsChildren but are not workspaces.
120101
// they are already handled as workspace-like proxies above and should not go through the external/store extraction path.
121102
if (!next.isProjectRoot && !next.isWorkspace && !next.inert && !idealTree.fsChildren.has(next) && !idealTree.fsChildren.has(next.target)) {
122-
this.idealGraph.external.push(await this.externalProxy(next))
103+
this.idealGraph.external.push(await this.#externalProxy(next))
123104
}
124105
}
125106

126-
await this.assignCommonProperties(idealTree, this.idealGraph)
107+
await this.#assignCommonProperties(idealTree, this.idealGraph)
127108
}
128109

129-
async workspaceProxy (node) {
110+
async #workspaceProxy (node) {
130111
if (this.#workspaceProxies.has(node)) {
131112
return this.#workspaceProxies.get(node)
132113
}
133114
const result = {}
134-
// XXX this goes recursive if we don't set here because assignCommonProperties also calls this.workspaceProxy
115+
// XXX this goes recursive if we don't set here because assignCommonProperties also calls this.#workspaceProxy
135116
this.#workspaceProxies.set(node, result)
136117
result.localLocation = node.location
137118
result.localPath = node.path
138119
result.isWorkspace = true
139120
result.resolved = node.resolved
140-
await this.assignCommonProperties(node, result)
121+
await this.#assignCommonProperties(node, result)
141122
return result
142123
}
143124

144-
async externalProxy (node) {
125+
async #externalProxy (node) {
145126
if (this.#externalProxies.has(node)) {
146127
return this.#externalProxies.get(node)
147128
}
148129
const result = {}
149-
// XXX this goes recursive if we don't set here because assignCommonProperties also calls this.externalProxy
130+
// XXX this goes recursive if we don't set here because assignCommonProperties also calls this.#externalProxy
150131
this.#externalProxies.set(node, result)
151-
await this.assignCommonProperties(node, result, !node.hasShrinkwrap)
132+
await this.#assignCommonProperties(node, result, !node.hasShrinkwrap)
152133
if (node.hasShrinkwrap) {
153134
const dir = join(
154135
node.root.path,
@@ -190,15 +171,15 @@ module.exports = cls => class IsolatedReifier extends cls {
190171
return result
191172
}
192173

193-
async assignCommonProperties (node, result, populateDeps = true) {
174+
async #assignCommonProperties (node, result, populateDeps = true) {
194175
result.root = this.idealGraph
176+
// XXX does anything need this?
195177
result.id = this.counter++
196178
/* istanbul ignore next - packageName is always set for real packages */
197179
result.name = result.isWorkspace ? (node.packageName || node.name) : node.name
198180
result.packageName = node.packageName || node.name
199181
result.package = { ...node.package }
200182
result.package.bundleDependencies = undefined
201-
result.hasInstallScript = node.hasInstallScript
202183

203184
if (!populateDeps) {
204185
return
@@ -228,9 +209,9 @@ module.exports = cls => class IsolatedReifier extends cls {
228209
// local `file:` deps (non-workspace fsChildren) should be treated as local dependencies, not external, so they get symlinked directly instead of being extracted into the store.
229210
const isLocal = (n) => n.isWorkspace || node.fsChildren?.has(n)
230211
const optionalDeps = edges.filter(edge => edge.optional).map(edge => edge.to.target)
231-
result.localDependencies = await Promise.all(nonOptionalDeps.filter(isLocal).map(n => this.workspaceProxy(n)))
232-
result.externalDependencies = await Promise.all(nonOptionalDeps.filter(n => !isLocal(n) && !n.inert).map(n => this.externalProxy(n)))
233-
result.externalOptionalDependencies = await Promise.all(optionalDeps.filter(n => !n.inert).map(n => this.externalProxy(n)))
212+
result.localDependencies = await Promise.all(nonOptionalDeps.filter(isLocal).map(n => this.#workspaceProxy(n)))
213+
result.externalDependencies = await Promise.all(nonOptionalDeps.filter(n => !isLocal(n) && !n.inert).map(n => this.#externalProxy(n)))
214+
result.externalOptionalDependencies = await Promise.all(optionalDeps.filter(n => !n.inert).map(n => this.#externalProxy(n)))
234215
result.dependencies = [
235216
...result.externalDependencies,
236217
...result.localDependencies,
@@ -290,79 +271,27 @@ module.exports = cls => class IsolatedReifier extends cls {
290271

291272
async createIsolatedTree () {
292273
await this.makeIdealGraph()
293-
294274
const bundledTree = await this.#createBundledTree()
295275

296-
const root = {
297-
binPaths: [],
298-
children: new Map(),
299-
edgesIn: new Set(),
300-
edgesOut: new Map(),
301-
fsChildren: new Set(),
302-
global: false,
303-
hasShrinkwrap: false,
304-
integrity: null,
305-
inventory: new Map(),
306-
isLink: false,
307-
isProjectRoot: true,
308-
isRoot: true,
309-
isTop: true,
310-
linksIn: new Set(),
311-
meta: { loadedFromDisk: false },
312-
package: this.idealGraph.root.package,
313-
parent: null,
314-
path: this.idealGraph.root.localPath,
315-
realpath: this.idealGraph.root.localPath,
316-
// TODO: we should probably not reference this.idealTree
317-
resolved: this.idealTree.resolved,
318-
tops: new Set(),
319-
workspaces: new Map(),
320-
}
321-
root.inventory.set('', root)
276+
const root = new IsolatedNode(this.idealGraph)
322277
root.root = root
323-
root.target = root
324-
// TODO inventory.query is a stub; audit-report needs 'packageName' support
325-
root.inventory.query = () => {
326-
return []
327-
}
278+
root.inventory.set('', root)
328279
const processed = new Set()
329280
for (const c of this.idealGraph.workspaces) {
330281
const wsName = c.packageName
331-
const workspace = {
332-
binPaths: [],
333-
children: new Map(),
334-
edgesIn: new Set(),
335-
edgesOut: new Map(),
336-
fsChildren: new Set(),
337-
hasInstallScript: c.hasInstallScript,
338-
isLink: false,
339-
isRoot: false,
340-
linksIn: new Set(),
282+
// XXX parent? root?
283+
const workspace = new IsolatedNode({
341284
location: c.localLocation,
342285
name: wsName,
343286
package: c.package,
344287
path: c.localPath,
345-
realpath: c.localPath,
346288
resolved: c.resolved,
347-
}
348-
workspace.target = workspace
289+
})
349290
root.fsChildren.add(workspace)
350291
root.inventory.set(workspace.location, workspace)
351292

352293
// Create workspace Link entry in children for _diffTrees lookup
353-
const wsLink = {
354-
binPaths: [],
355-
children: new Map(),
356-
edgesIn: new Set(),
357-
edgesOut: new Map(),
358-
fsChildren: new Set(),
359-
global: false,
360-
globalTop: false,
361-
isLink: true,
362-
isProjectRoot: false,
363-
isRoot: false,
364-
isTop: false,
365-
linksIn: new Set(),
294+
const wsLink = new IsolatedLink({
366295
location: join('node_modules', wsName),
367296
name: wsName,
368297
package: workspace.package,
@@ -371,7 +300,7 @@ module.exports = cls => class IsolatedReifier extends cls {
371300
realpath: workspace.path,
372301
root,
373302
target: workspace,
374-
}
303+
})
375304
root.children.set(wsLink.name, wsLink)
376305
root.inventory.set(wsLink.location, wsLink)
377306
root.workspaces.set(wsName, workspace.path)
@@ -468,35 +397,29 @@ module.exports = cls => class IsolatedReifier extends cls {
468397
}
469398
}
470399

471-
const link = {
472-
binPaths: [],
473-
children: new Map(),
474-
edgesIn: new Set(),
475-
edgesOut: new Map(),
476-
fsChildren: new Set(),
477-
global: false,
478-
globalTop: false,
479-
isLink: true,
480-
isProjectRoot: false,
481-
isRoot: false,
400+
const pkg = {
401+
_id: dep.package._id,
402+
bin: target.package.bin,
403+
bundleDependencies: undefined,
404+
deprecated: undefined,
405+
scripts: dep.package.scripts,
406+
version: dep.package.version,
407+
}
408+
const link = new IsolatedLink({
482409
isStoreLink: true,
483-
isTop: false,
484410
location: join(nmFolder, dep.name),
485411
name: toKey,
486412
optional,
487-
// TODO _id: 'abc' ?
488-
package: { _id: 'abc', bundleDependencies: undefined, deprecated: undefined, bin: target.package.bin, scripts: dep.package.scripts },
489413
parent: root,
414+
package: pkg,
490415
path: join(dep.root.localPath, nmFolder, dep.name),
491416
realpath: target.path,
492-
resolved: external
493-
? `file:.store/${toKey}/node_modules/${dep.packageName}`
494-
: dep.resolved,
417+
resolved: external ? `file:.store/${toKey}/node_modules/${dep.packageName}` : dep.resolved,
495418
root,
496419
target,
497-
version: dep.version,
498-
top: { path: dep.root.localPath },
499-
}
420+
})
421+
// XXX top is from place-dep not lib/link.js
422+
link.top = { path: dep.root.localPath }
500423
const newEdge1 = { optional, from, to: link }
501424
from.edgesOut.set(dep.name, newEdge1)
502425
link.edgesIn.add(newEdge1)

0 commit comments

Comments
 (0)