mirror of
https://github.com/nodejs/node.git
synced 2025-05-21 17:44:15 +00:00

PR-URL: https://github.com/nodejs/node/pull/36459 Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Myles Borins <myles.borins@gmail.com>
135 lines
3.3 KiB
JavaScript
135 lines
3.3 KiB
JavaScript
const debug = require('./debug.js')
|
|
const relpath = require('./relpath.js')
|
|
const Node = require('./node.js')
|
|
const _loadDeps = Symbol.for('Arborist.Node._loadDeps')
|
|
const _target = Symbol.for('_target')
|
|
const {dirname} = require('path')
|
|
// defined by Node class
|
|
const _delistFromMeta = Symbol.for('_delistFromMeta')
|
|
const _refreshLocation = Symbol.for('_refreshLocation')
|
|
class Link extends Node {
|
|
constructor (options) {
|
|
const { root, realpath, target, parent, fsParent } = options
|
|
|
|
if (!realpath && !(target && target.path))
|
|
throw new TypeError('must provide realpath for Link node')
|
|
|
|
super({
|
|
...options,
|
|
realpath: realpath || target.path,
|
|
root: root || (parent ? parent.root
|
|
: fsParent ? fsParent.root
|
|
: target ? target.root
|
|
: null),
|
|
})
|
|
|
|
this.target = target || new Node({
|
|
...options,
|
|
path: realpath,
|
|
parent: null,
|
|
fsParent: null,
|
|
root: this.root,
|
|
})
|
|
}
|
|
|
|
get version () {
|
|
return this.target ? this.target.version : this.package.version || ''
|
|
}
|
|
|
|
get target () {
|
|
return this[_target]
|
|
}
|
|
|
|
set target (target) {
|
|
const current = this[_target]
|
|
if (target === current)
|
|
return
|
|
|
|
if (current && current.then) {
|
|
debug(() => {
|
|
throw Object.assign(new Error('cannot set target while awaiting'), {
|
|
path: this.path,
|
|
realpath: this.realpath,
|
|
})
|
|
})
|
|
}
|
|
|
|
if (target && target.then) {
|
|
// can set to a promise during an async tree build operation
|
|
// wait until then to assign it.
|
|
this[_target] = target
|
|
target.then(node => {
|
|
this[_target] = null
|
|
this.target = node
|
|
})
|
|
return
|
|
}
|
|
|
|
if (!target) {
|
|
if (current && current.linksIn)
|
|
current.linksIn.delete(this)
|
|
if (this.path) {
|
|
this[_delistFromMeta]()
|
|
this[_target] = null
|
|
this.package = {}
|
|
this[_refreshLocation]()
|
|
} else
|
|
this[_target] = null
|
|
return
|
|
}
|
|
|
|
if (!this.path) {
|
|
// temp node pending assignment to a tree
|
|
// we know it's not in the inventory yet, because no path.
|
|
if (target.path)
|
|
this.realpath = target.path
|
|
else
|
|
target.path = target.realpath = this.realpath
|
|
target.root = this.root
|
|
this[_target] = target
|
|
target.linksIn.add(this)
|
|
this.package = target.package
|
|
return
|
|
}
|
|
|
|
// have to refresh metadata, because either realpath or package
|
|
// is very likely changing.
|
|
this[_delistFromMeta]()
|
|
this.package = target.package
|
|
this.realpath = target.path
|
|
this[_refreshLocation]()
|
|
|
|
target.root = this.root
|
|
}
|
|
|
|
// a link always resolves to the relative path to its target
|
|
get resolved () {
|
|
// the path/realpath guard is there for the benefit of setting
|
|
// these things in the "wrong" order
|
|
return this.path && this.realpath
|
|
? `file:${relpath(dirname(this.path), this.realpath)}`
|
|
: null
|
|
}
|
|
|
|
set resolved (r) {}
|
|
|
|
// deps are resolved on the target, not the Link
|
|
// so this is a no-op
|
|
[_loadDeps] () {}
|
|
|
|
// links can't have children, only their targets can
|
|
// fix it to an empty list so that we can still call
|
|
// things that iterate over them, just as a no-op
|
|
get children () {
|
|
return new Map()
|
|
}
|
|
|
|
set children (c) {}
|
|
|
|
get isLink () {
|
|
return true
|
|
}
|
|
}
|
|
|
|
module.exports = Link
|