|
|
|
|
@ -165,252 +165,200 @@ function convertDataDescriptorToAccessor(obj, prop, message) {
|
|
|
|
|
* Determine if namespace is ignored.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
function isignored (namespace) {
|
|
|
|
|
if (process.noDeprecation) {
|
|
|
|
|
// --no-deprecation support
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var str = process.env.NO_DEPRECATION || ''
|
|
|
|
|
// 生成一个唯一的键,用于标识调用者的弃用消息
|
|
|
|
|
var key = caller
|
|
|
|
|
? depSite.join(':') + '__' + caller.join(':') // 如果有调用者,组合依赖站点和调用者信息
|
|
|
|
|
: undefined; // 如果没有调用者,键为 undefined
|
|
|
|
|
|
|
|
|
|
// namespace ignored
|
|
|
|
|
return containsNamespace(str, namespace)
|
|
|
|
|
// 检查该键是否已经被警告过
|
|
|
|
|
if (key !== undefined && key in this._warned) {
|
|
|
|
|
// 如果已经发出警告,则提前返回
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Determine if namespace is traced.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
function istraced (namespace) {
|
|
|
|
|
if (process.traceDeprecation) {
|
|
|
|
|
// --trace-deprecation support
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
// 将该键标记为已警告
|
|
|
|
|
this._warned[key] = true;
|
|
|
|
|
|
|
|
|
|
var str = process.env.TRACE_DEPRECATION || ''
|
|
|
|
|
|
|
|
|
|
// namespace traced
|
|
|
|
|
return containsNamespace(str, namespace)
|
|
|
|
|
// 生成自动弃用消息
|
|
|
|
|
var msg = message; // 首先使用提供的消息
|
|
|
|
|
if (!msg) {
|
|
|
|
|
// 如果没有提供消息,则根据调用位置生成默认消息
|
|
|
|
|
msg = callSite === depSite || !callSite.name
|
|
|
|
|
? defaultMessage(depSite) // 如果调用位置与依赖站点相同或没有名称,使用依赖站点生成默认消息
|
|
|
|
|
: defaultMessage(callSite); // 否则,使用调用位置生成默认消息
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Display deprecation message.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
function log (message, site) {
|
|
|
|
|
var haslisteners = eehaslisteners(process, 'deprecation')
|
|
|
|
|
|
|
|
|
|
// abort early if no destination
|
|
|
|
|
if (!haslisteners && this._ignored) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var caller
|
|
|
|
|
var callFile
|
|
|
|
|
var callSite
|
|
|
|
|
var depSite
|
|
|
|
|
var i = 0
|
|
|
|
|
var seen = false
|
|
|
|
|
var stack = getStack()
|
|
|
|
|
var file = this._file
|
|
|
|
|
|
|
|
|
|
if (site) {
|
|
|
|
|
// provided site
|
|
|
|
|
depSite = site
|
|
|
|
|
callSite = callSiteLocation(stack[1])
|
|
|
|
|
callSite.name = depSite.name
|
|
|
|
|
file = callSite[0]
|
|
|
|
|
} else {
|
|
|
|
|
// get call site
|
|
|
|
|
i = 2
|
|
|
|
|
depSite = callSiteLocation(stack[i])
|
|
|
|
|
callSite = depSite
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// get caller of deprecated thing in relation to file
|
|
|
|
|
for (; i < stack.length; i++) {
|
|
|
|
|
caller = callSiteLocation(stack[i])
|
|
|
|
|
callFile = caller[0]
|
|
|
|
|
|
|
|
|
|
if (callFile === file) {
|
|
|
|
|
seen = true
|
|
|
|
|
} else if (callFile === this._file) {
|
|
|
|
|
file = this._file
|
|
|
|
|
} else if (seen) {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var key = caller
|
|
|
|
|
? depSite.join(':') + '__' + caller.join(':')
|
|
|
|
|
: undefined
|
|
|
|
|
|
|
|
|
|
if (key !== undefined && key in this._warned) {
|
|
|
|
|
// already warned
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this._warned[key] = true
|
|
|
|
|
|
|
|
|
|
// generate automatic message from call site
|
|
|
|
|
var msg = message
|
|
|
|
|
if (!msg) {
|
|
|
|
|
msg = callSite === depSite || !callSite.name
|
|
|
|
|
? defaultMessage(depSite)
|
|
|
|
|
: defaultMessage(callSite)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// emit deprecation if listeners exist
|
|
|
|
|
if (haslisteners) {
|
|
|
|
|
var err = DeprecationError(this._namespace, msg, stack.slice(i))
|
|
|
|
|
process.emit('deprecation', err)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// format and write message
|
|
|
|
|
var format = process.stderr.isTTY
|
|
|
|
|
? formatColor
|
|
|
|
|
: formatPlain
|
|
|
|
|
var output = format.call(this, msg, caller, stack.slice(i))
|
|
|
|
|
process.stderr.write(output + '\n', 'utf8')
|
|
|
|
|
// 如果存在监听器,则发出弃用事件
|
|
|
|
|
if (haslisteners) {
|
|
|
|
|
// 创建一个弃用错误对象并发出事件
|
|
|
|
|
var err = DeprecationError(this._namespace, msg, stack.slice(i));
|
|
|
|
|
process.emit('deprecation', err); // 发出 'deprecation' 事件
|
|
|
|
|
return; // 结束函数
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 格式化并写入消息
|
|
|
|
|
var format = process.stderr.isTTY // 检查标准错误输出是否为 TTY
|
|
|
|
|
? formatColor // 如果是 TTY,使用彩色格式
|
|
|
|
|
: formatPlain; // 否则,使用普通格式
|
|
|
|
|
var output = format.call(this, msg, caller, stack.slice(i)); // 格式化输出消息
|
|
|
|
|
process.stderr.write(output + '\n', 'utf8'); // 将消息写入标准错误输出
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get call site location as array.
|
|
|
|
|
* 获取调用位置的文件位置作为数组。
|
|
|
|
|
*/
|
|
|
|
|
function callSiteLocation(callSite) {
|
|
|
|
|
var file = callSite.getFileName() || '<anonymous>'; // 获取文件名,如果没有则标记为 '<anonymous>'
|
|
|
|
|
var line = callSite.getLineNumber(); // 获取行号
|
|
|
|
|
var colm = callSite.getColumnNumber(); // 获取列号
|
|
|
|
|
|
|
|
|
|
function callSiteLocation (callSite) {
|
|
|
|
|
var file = callSite.getFileName() || '<anonymous>'
|
|
|
|
|
var line = callSite.getLineNumber()
|
|
|
|
|
var colm = callSite.getColumnNumber()
|
|
|
|
|
|
|
|
|
|
// 如果调用位置是 eval,则获取 eval 的原始位置
|
|
|
|
|
if (callSite.isEval()) {
|
|
|
|
|
file = callSite.getEvalOrigin() + ', ' + file
|
|
|
|
|
file = callSite.getEvalOrigin() + ', ' + file; // 组合 eval 原始位置和文件名
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var site = [file, line, colm]
|
|
|
|
|
var site = [file, line, colm]; // 创建位置数组
|
|
|
|
|
|
|
|
|
|
site.callSite = callSite
|
|
|
|
|
site.name = callSite.getFunctionName()
|
|
|
|
|
site.callSite = callSite; // 将原始调用位置附加到数组
|
|
|
|
|
site.name = callSite.getFunctionName(); // 获取函数名称并附加
|
|
|
|
|
|
|
|
|
|
return site
|
|
|
|
|
return site; // 返回位置数组
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Generate a default message from the site.
|
|
|
|
|
* 从调用位置生成默认消息。
|
|
|
|
|
*/
|
|
|
|
|
function defaultMessage(site) {
|
|
|
|
|
var callSite = site.callSite; // 获取调用位置
|
|
|
|
|
var funcName = site.name; // 获取函数名称
|
|
|
|
|
|
|
|
|
|
function defaultMessage (site) {
|
|
|
|
|
var callSite = site.callSite
|
|
|
|
|
var funcName = site.name
|
|
|
|
|
|
|
|
|
|
// make useful anonymous name
|
|
|
|
|
// 为匿名函数生成有用的名称
|
|
|
|
|
if (!funcName) {
|
|
|
|
|
funcName = '<anonymous@' + formatLocation(site) + '>'
|
|
|
|
|
funcName = '<anonymous@' + formatLocation(site) + '>'; // 如果没有函数名,生成匿名名称
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var context = callSite.getThis()
|
|
|
|
|
var typeName = context && callSite.getTypeName()
|
|
|
|
|
var context = callSite.getThis(); // 获取调用上下文
|
|
|
|
|
var typeName = context && callSite.getTypeName(); // 获取类型名称
|
|
|
|
|
|
|
|
|
|
// ignore useless type name
|
|
|
|
|
// 忽略无用的类型名称
|
|
|
|
|
if (typeName === 'Object') {
|
|
|
|
|
typeName = undefined
|
|
|
|
|
typeName = undefined; // 如果类型名称是 'Object',则设置为 undefined
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// make useful type name
|
|
|
|
|
// 为有用的类型名称
|
|
|
|
|
if (typeName === 'Function') {
|
|
|
|
|
typeName = context.name || typeName
|
|
|
|
|
typeName = context.name || typeName; // 如果上下文是函数,使用上下文的名称
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 生成默认消息
|
|
|
|
|
return typeName && callSite.getMethodName()
|
|
|
|
|
? typeName + '.' + funcName
|
|
|
|
|
: funcName
|
|
|
|
|
? typeName + '.' + funcName // 如果有类型名称和方法名称,组合成 '类型名.函数名'
|
|
|
|
|
: funcName; // 否则,仅返回函数名称
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Format deprecation message without color.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
function formatPlain (msg, caller, stack) {
|
|
|
|
|
var timestamp = new Date().toUTCString()
|
|
|
|
|
/**
|
|
|
|
|
* 格式化普通的弃用消息。
|
|
|
|
|
* @param {string} msg - 弃用消息。
|
|
|
|
|
* @param {Object} caller - 调用者信息。
|
|
|
|
|
* @param {Array} stack - 堆栈跟踪数组。
|
|
|
|
|
* @returns {string} - 格式化后的弃用消息。
|
|
|
|
|
*/
|
|
|
|
|
function formatPlain(msg, caller, stack) {
|
|
|
|
|
var timestamp = new Date().toUTCString(); // 获取当前时间的 UTC 字符串表示
|
|
|
|
|
|
|
|
|
|
// 组合格式化的消息,包括时间戳、命名空间和弃用消息
|
|
|
|
|
var formatted = timestamp +
|
|
|
|
|
' ' + this._namespace +
|
|
|
|
|
' deprecated ' + msg
|
|
|
|
|
' ' + this._namespace +
|
|
|
|
|
' deprecated ' + msg;
|
|
|
|
|
|
|
|
|
|
// add stack trace
|
|
|
|
|
// 添加堆栈跟踪
|
|
|
|
|
if (this._traced) {
|
|
|
|
|
for (var i = 0; i < stack.length; i++) {
|
|
|
|
|
formatted += '\n at ' + stack[i].toString()
|
|
|
|
|
formatted += '\n at ' + stack[i].toString(); // 将每个堆栈条目添加到消息中
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return formatted
|
|
|
|
|
return formatted; // 返回格式化后的消息
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 如果有调用者信息,则添加调用者位置
|
|
|
|
|
if (caller) {
|
|
|
|
|
formatted += ' at ' + formatLocation(caller)
|
|
|
|
|
formatted += ' at ' + formatLocation(caller); // 格式化调用位置并添加
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return formatted
|
|
|
|
|
return formatted; // 返回最终格式化后的消息
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Format deprecation message with color.
|
|
|
|
|
* 使用颜色格式化弃用消息。
|
|
|
|
|
* @param {string} msg - 弃用消息。
|
|
|
|
|
* @param {Object} caller - 调用者信息。
|
|
|
|
|
* @param {Array} stack - 堆栈跟踪数组。
|
|
|
|
|
* @returns {string} - 格式化后的彩色弃用消息。
|
|
|
|
|
*/
|
|
|
|
|
function formatColor(msg, caller, stack) {
|
|
|
|
|
// 组合格式化的消息,使用 ANSI 转义码为不同部分添加颜色
|
|
|
|
|
var formatted = '\x1b[36;1m' + this._namespace + '\x1b[22;39m' + // 粗体青色命名空间
|
|
|
|
|
' \x1b[33;1mdeprecated\x1b[22;39m' + // 粗体黄色 'deprecated'
|
|
|
|
|
' \x1b[0m' + msg + '\x1b[39m'; // 重置颜色并添加消息
|
|
|
|
|
|
|
|
|
|
function formatColor (msg, caller, stack) {
|
|
|
|
|
var formatted = '\x1b[36;1m' + this._namespace + '\x1b[22;39m' + // bold cyan
|
|
|
|
|
' \x1b[33;1mdeprecated\x1b[22;39m' + // bold yellow
|
|
|
|
|
' \x1b[0m' + msg + '\x1b[39m' // reset
|
|
|
|
|
|
|
|
|
|
// add stack trace
|
|
|
|
|
// 添加堆栈跟踪
|
|
|
|
|
if (this._traced) {
|
|
|
|
|
for (var i = 0; i < stack.length; i++) {
|
|
|
|
|
formatted += '\n \x1b[36mat ' + stack[i].toString() + '\x1b[39m' // cyan
|
|
|
|
|
formatted += '\n \x1b[36mat ' + stack[i].toString() + '\x1b[39m'; // 在堆栈条目前添加 'at' 和颜色
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return formatted
|
|
|
|
|
return formatted; // 返回格式化后的消息
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 如果有调用者信息,则添加调用者位置
|
|
|
|
|
if (caller) {
|
|
|
|
|
formatted += ' \x1b[36m' + formatLocation(caller) + '\x1b[39m' // cyan
|
|
|
|
|
formatted += ' \x1b[36m' + formatLocation(caller) + '\x1b[39m'; // 格式化调用位置并添加颜色
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return formatted
|
|
|
|
|
return formatted; // 返回最终格式化后的消息
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Format call site location.
|
|
|
|
|
* 格式化调用位置。
|
|
|
|
|
* @param {Array} callSite - 调用位置数组,包含文件名、行号和列号。
|
|
|
|
|
* @returns {string} - 格式化后的调用位置字符串。
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
function formatLocation (callSite) {
|
|
|
|
|
function formatLocation(callSite) {
|
|
|
|
|
// 返回相对路径、行号和列号的组合
|
|
|
|
|
return relative(basePath, callSite[0]) +
|
|
|
|
|
':' + callSite[1] +
|
|
|
|
|
':' + callSite[2]
|
|
|
|
|
':' + callSite[1] +
|
|
|
|
|
':' + callSite[2];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the stack as array of call sites.
|
|
|
|
|
* 获取调用堆栈作为调用位置数组。
|
|
|
|
|
* @returns {Array} - 堆栈跟踪数组。
|
|
|
|
|
*/
|
|
|
|
|
function getStack() {
|
|
|
|
|
var limit = Error.stackTraceLimit; // 保存当前的堆栈跟踪限制
|
|
|
|
|
var obj = {}; // 创建一个对象用于捕获堆栈
|
|
|
|
|
var prep = Error.prepareStackTrace; // 保存原始的 prepareStackTrace 函数
|
|
|
|
|
|
|
|
|
|
function getStack () {
|
|
|
|
|
var limit = Error.stackTraceLimit
|
|
|
|
|
var obj = {}
|
|
|
|
|
var prep = Error.prepareStackTrace
|
|
|
|
|
// 设置自定义的堆栈准备函数
|
|
|
|
|
Error.prepareStackTrace = prepareObjectStackTrace;
|
|
|
|
|
Error.stackTraceLimit = Math.max(10, limit); // 确保堆栈跟踪限制至少为 10
|
|
|
|
|
|
|
|
|
|
Error.prepareStackTrace = prepareObjectStackTrace
|
|
|
|
|
Error.stackTraceLimit = Math.max(10, limit)
|
|
|
|
|
// 捕获堆栈
|
|
|
|
|
Error.captureStackTrace(obj);
|
|
|
|
|
|
|
|
|
|
// capture the stack
|
|
|
|
|
Error.captureStackTrace(obj)
|
|
|
|
|
// 从堆栈中切除当前函数
|
|
|
|
|
var stack = obj.stack.slice(1);
|
|
|
|
|
|
|
|
|
|
// slice this function off the top
|
|
|
|
|
var stack = obj.stack.slice(1)
|
|
|
|
|
// 恢复原始的堆栈准备函数和堆栈跟踪限制
|
|
|
|
|
Error.prepareStackTrace = prep;
|
|
|
|
|
Error.stackTraceLimit = limit;
|
|
|
|
|
|
|
|
|
|
Error.prepareStackTrace = prep
|
|
|
|
|
Error.stackTraceLimit = limit
|
|
|
|
|
|
|
|
|
|
return stack
|
|
|
|
|
return stack; // 返回堆栈数组
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|