node/deps/npm/node_modules/@npmcli/arborist/lib/tree-check.js
Ruy Adorno f51a0e4b85
deps: upgrade npm to 7.1.1
PR-URL: https://github.com/nodejs/node/pull/36459
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Myles Borins <myles.borins@gmail.com>
2020-12-11 17:59:18 -05:00

105 lines
2.9 KiB
JavaScript

const debug = require('./debug.js')
const checkTree = (tree, checkUnreachable = true) => {
// this can only happen in tests where we have a "tree" object
// that isn't actually a tree.
if (!tree.root || !tree.root.inventory)
return tree
const { inventory } = tree.root
const seen = new Set()
const check = (node, via = tree, viaType = 'self') => {
if (!node || seen.has(node) || node.then)
return
if (node.isRoot && node !== tree.root) {
throw Object.assign(new Error('double root'), {
node: node.path,
realpath: node.realpath,
tree: tree.path,
root: tree.root.path,
via: via.path,
viaType,
})
}
if (node.root !== tree.root) {
throw Object.assign(new Error('node from other root in tree'), {
node: node.path,
realpath: node.realpath,
tree: tree.path,
root: tree.root.path,
via: via.path,
viaType,
otherRoot: node.root && node.root.path,
})
}
if (!node.isRoot && node.inventory.size !== 0) {
throw Object.assign(new Error('non-root has non-zero inventory'), {
node: node.path,
tree: tree.path,
root: tree.root.path,
via: via.path,
viaType,
inventory: [...node.inventory.values()].map(node =>
[node.path, node.location]),
})
}
if (!node.isRoot && !inventory.has(node) && !node.dummy) {
throw Object.assign(new Error('not in inventory'), {
node: node.path,
tree: tree.path,
root: tree.root.path,
via: via.path,
viaType,
})
}
const devEdges = [...node.edgesOut.values()].filter(e => e.dev)
if (!node.isTop && devEdges.length) {
throw Object.assign(new Error('dev edges on non-top node'), {
node: node.path,
tree: tree.path,
root: tree.root.path,
via: via.path,
viaType,
devEdges: devEdges.map(e => [e.type, e.name, e.spec, e.error]),
})
}
const { parent, fsParent, target } = node
seen.add(node)
check(parent, node, 'parent')
check(fsParent, node, 'fsParent')
check(target, node, 'target')
for (const kid of node.children.values())
check(kid, node, 'children')
for (const kid of node.fsChildren)
check(kid, node, 'fsChildren')
for (const link of node.linksIn)
check(link, node, 'linksIn')
for (const top of node.tops)
check(top, node, 'tops')
}
check(tree)
if (checkUnreachable) {
for (const node of inventory.values()) {
if (!seen.has(node) && node !== tree.root) {
throw Object.assign(new Error('unreachable in inventory'), {
node: node.path,
realpath: node.realpath,
location: node.location,
root: tree.root.path,
tree: tree.path,
})
}
}
}
return tree
}
// should only ever run this check in debug mode
module.exports = tree => tree
debug(() => module.exports = checkTree)