You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
blockvote/node_modules/depd/index.js

502 lines
14 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/*!
* depd
* Copyright(c) 2014-2018 Douglas Christopher Wilson
* MIT Licensed
*/
/**
* Module dependencies.
*/
var relative = require('path').relative
/**
* Module exports.
*/
module.exports = depd
/**
* Get the path to base files on.
*/
var basePath = process.cwd()
/**
* Determine if namespace is contained in the string.
*/
function containsNamespace (str, namespace) {
var vals = str.split(/[ ,]+/)
var ns = String(namespace).toLowerCase()
for (var i = 0; i < vals.length; i++) {
var val = vals[i]
// namespace contained
if (val && (val === '*' || val.toLowerCase() === ns)) {
return true
}
}
return false
}
/**
* Convert a data descriptor to accessor descriptor.
*/
function containsNamespace(str, namespace) {
// 使用正则表达式将字符串按空格或逗号分割成数组
var vals = str.split(/[ ,]+/);
// 将命名空间转换为小写以进行不区分大小写的比较
var ns = String(namespace).toLowerCase();
// 遍历分割后的数组
for (var i = 0; i < vals.length; i++) {
var val = vals[i];
// 如果 val 存在,并且等于 '*' 或者等于指定的命名空间,则返回 true
if (val && (val === '*' || val.toLowerCase() === ns)) {
return true;
}
}
// 如果没有找到匹配的命名空间,则返回 false
return false;
}
/**
* 将数据描述符转换为访问器描述符。
* @param {Object} obj - 要修改的对象。
* @param {string} prop - 要转换的属性名。
* @param {string} message - 相关消息(未使用)。
* @returns {Object} - 返回转换后的描述符。
*/
function convertDataDescriptorToAccessor(obj, prop, message) {
// 获取对象的属性描述符
var descriptor = Object.getOwnPropertyDescriptor(obj, prop);
// 获取属性的值
var value = descriptor.value;
// 定义 getter 方法,返回属性的值
descriptor.get = function getter() { return value; };
// 如果属性是可写的,则定义 setter 方法
if (descriptor.writable) {
descriptor.set = function setter(val) { return (value = val); };
}
// 删除原有的值和可写性描述符
delete descriptor.value;
delete descriptor.writable;
// 使用新的描述符重新定义对象的属性
Object.defineProperty(obj, prop, descriptor);
// 返回转换后的描述符
return descriptor;
}
/**
* Create arguments string to keep arity.
*/
/**
* 检查给定的字符串中是否包含指定的命名空间。
* @param {string} str - 要检查的字符串,可能包含多个命名空间。
* @param {string} namespace - 要查找的命名空间。
* @returns {boolean} - 如果字符串中包含命名空间,则返回 true否则返回 false。
*/
function containsNamespace(str, namespace) {
// 使用正则表达式将字符串按空格或逗号分割成数组
var vals = str.split(/[ ,]+/);
// 将命名空间转换为小写以进行不区分大小写的比较
var ns = String(namespace).toLowerCase();
// 遍历分割后的数组
for (var i = 0; i < vals.length; i++) {
var val = vals[i];
// 如果 val 存在,并且等于 '*' 或者等于指定的命名空间,则返回 true
if (val && (val === '*' || val.toLowerCase() === ns)) {
return true;
}
}
// 如果没有找到匹配的命名空间,则返回 false
return false;
}
/**
* 将数据描述符转换为访问器描述符。
* @param {Object} obj - 要修改的对象。
* @param {string} prop - 要转换的属性名。
* @param {string} message - 相关消息(未使用)。
* @returns {Object} - 返回转换后的描述符。
*/
function convertDataDescriptorToAccessor(obj, prop, message) {
// 获取对象的属性描述符
var descriptor = Object.getOwnPropertyDescriptor(obj, prop);
// 获取属性的值
var value = descriptor.value;
// 定义 getter 方法,返回属性的值
descriptor.get = function getter() { return value; };
// 如果属性是可写的,则定义 setter 方法
if (descriptor.writable) {
descriptor.set = function setter(val) { return (value = val); };
}
// 删除原有的值和可写性描述符
delete descriptor.value;
delete descriptor.writable;
// 使用新的描述符重新定义对象的属性
Object.defineProperty(obj, prop, descriptor);
// 返回转换后的描述符
return descriptor;
}
/**
* Determine if namespace is ignored.
*/
// 生成一个唯一的键,用于标识调用者的弃用消息
var key = caller
? depSite.join(':') + '__' + caller.join(':') // 如果有调用者,组合依赖站点和调用者信息
: undefined; // 如果没有调用者,键为 undefined
// 检查该键是否已经被警告过
if (key !== undefined && key in this._warned) {
// 如果已经发出警告,则提前返回
return;
}
// 将该键标记为已警告
this._warned[key] = true;
// 生成自动弃用消息
var msg = message; // 首先使用提供的消息
if (!msg) {
// 如果没有提供消息,则根据调用位置生成默认消息
msg = callSite === depSite || !callSite.name
? defaultMessage(depSite) // 如果调用位置与依赖站点相同或没有名称,使用依赖站点生成默认消息
: defaultMessage(callSite); // 否则,使用调用位置生成默认消息
}
// 如果存在监听器,则发出弃用事件
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'); // 将消息写入标准错误输出
/**
* 获取调用位置的文件位置作为数组。
*/
function callSiteLocation(callSite) {
var file = callSite.getFileName() || '<anonymous>'; // 获取文件名,如果没有则标记为 '<anonymous>'
var line = callSite.getLineNumber(); // 获取行号
var colm = callSite.getColumnNumber(); // 获取列号
// 如果调用位置是 eval则获取 eval 的原始位置
if (callSite.isEval()) {
file = callSite.getEvalOrigin() + ', ' + file; // 组合 eval 原始位置和文件名
}
var site = [file, line, colm]; // 创建位置数组
site.callSite = callSite; // 将原始调用位置附加到数组
site.name = callSite.getFunctionName(); // 获取函数名称并附加
return site; // 返回位置数组
}
/**
* 从调用位置生成默认消息。
*/
function defaultMessage(site) {
var callSite = site.callSite; // 获取调用位置
var funcName = site.name; // 获取函数名称
// 为匿名函数生成有用的名称
if (!funcName) {
funcName = '<anonymous@' + formatLocation(site) + '>'; // 如果没有函数名,生成匿名名称
}
var context = callSite.getThis(); // 获取调用上下文
var typeName = context && callSite.getTypeName(); // 获取类型名称
// 忽略无用的类型名称
if (typeName === 'Object') {
typeName = undefined; // 如果类型名称是 'Object',则设置为 undefined
}
// 为有用的类型名称
if (typeName === 'Function') {
typeName = context.name || typeName; // 如果上下文是函数,使用上下文的名称
}
// 生成默认消息
return typeName && callSite.getMethodName()
? typeName + '.' + funcName // 如果有类型名称和方法名称,组合成 '类型名.函数名'
: funcName; // 否则,仅返回函数名称
}
/**
* Format deprecation message without color.
*/
/**
* 格式化普通的弃用消息。
* @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;
// 添加堆栈跟踪
if (this._traced) {
for (var i = 0; i < stack.length; i++) {
formatted += '\n at ' + stack[i].toString(); // 将每个堆栈条目添加到消息中
}
return formatted; // 返回格式化后的消息
}
// 如果有调用者信息,则添加调用者位置
if (caller) {
formatted += ' at ' + formatLocation(caller); // 格式化调用位置并添加
}
return formatted; // 返回最终格式化后的消息
}
/**
* 使用颜色格式化弃用消息。
* @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'; // 重置颜色并添加消息
// 添加堆栈跟踪
if (this._traced) {
for (var i = 0; i < stack.length; i++) {
formatted += '\n \x1b[36mat ' + stack[i].toString() + '\x1b[39m'; // 在堆栈条目前添加 'at' 和颜色
}
return formatted; // 返回格式化后的消息
}
// 如果有调用者信息,则添加调用者位置
if (caller) {
formatted += ' \x1b[36m' + formatLocation(caller) + '\x1b[39m'; // 格式化调用位置并添加颜色
}
return formatted; // 返回最终格式化后的消息
}
/**
* 格式化调用位置。
* @param {Array} callSite - 调用位置数组,包含文件名、行号和列号。
* @returns {string} - 格式化后的调用位置字符串。
*/
function formatLocation(callSite) {
// 返回相对路径、行号和列号的组合
return relative(basePath, callSite[0]) +
':' + callSite[1] +
':' + callSite[2];
}
/**
* 获取调用堆栈作为调用位置数组。
* @returns {Array} - 堆栈跟踪数组。
*/
function getStack() {
var limit = Error.stackTraceLimit; // 保存当前的堆栈跟踪限制
var obj = {}; // 创建一个对象用于捕获堆栈
var prep = Error.prepareStackTrace; // 保存原始的 prepareStackTrace 函数
// 设置自定义的堆栈准备函数
Error.prepareStackTrace = prepareObjectStackTrace;
Error.stackTraceLimit = Math.max(10, limit); // 确保堆栈跟踪限制至少为 10
// 捕获堆栈
Error.captureStackTrace(obj);
// 从堆栈中切除当前函数
var stack = obj.stack.slice(1);
// 恢复原始的堆栈准备函数和堆栈跟踪限制
Error.prepareStackTrace = prep;
Error.stackTraceLimit = limit;
return stack; // 返回堆栈数组
}
/**
* Capture call site stack from v8.
*/
function prepareObjectStackTrace (obj, stack) {
return stack
}
/**
* Return a wrapped function in a deprecation message.
*/
function wrapfunction (fn, message) {
if (typeof fn !== 'function') {
throw new TypeError('argument fn must be a function')
}
var args = createArgumentsString(fn.length)
var stack = getStack()
var site = callSiteLocation(stack[1])
site.name = fn.name
// eslint-disable-next-line no-new-func
var deprecatedfn = new Function('fn', 'log', 'deprecate', 'message', 'site',
'"use strict"\n' +
'return function (' + args + ') {' +
'log.call(deprecate, message, site)\n' +
'return fn.apply(this, arguments)\n' +
'}')(fn, log, this, message, site)
return deprecatedfn
}
/**
* Wrap property in a deprecation message.
*/
function wrapproperty (obj, prop, message) {
if (!obj || (typeof obj !== 'object' && typeof obj !== 'function')) {
throw new TypeError('argument obj must be object')
}
var descriptor = Object.getOwnPropertyDescriptor(obj, prop)
if (!descriptor) {
throw new TypeError('must call property on owner object')
}
if (!descriptor.configurable) {
throw new TypeError('property must be configurable')
}
var deprecate = this
var stack = getStack()
var site = callSiteLocation(stack[1])
// set site name
site.name = prop
// convert data descriptor
if ('value' in descriptor) {
descriptor = convertDataDescriptorToAccessor(obj, prop, message)
}
var get = descriptor.get
var set = descriptor.set
// wrap getter
if (typeof get === 'function') {
descriptor.get = function getter () {
log.call(deprecate, message, site)
return get.apply(this, arguments)
}
}
// wrap setter
if (typeof set === 'function') {
descriptor.set = function setter () {
log.call(deprecate, message, site)
return set.apply(this, arguments)
}
}
Object.defineProperty(obj, prop, descriptor)
}
/**
* Create DeprecationError for deprecation
*/
function DeprecationError (namespace, message, stack) {
var error = new Error()
var stackString
Object.defineProperty(error, 'constructor', {
value: DeprecationError
})
Object.defineProperty(error, 'message', {
configurable: true,
enumerable: false,
value: message,
writable: true
})
Object.defineProperty(error, 'name', {
enumerable: false,
configurable: true,
value: 'DeprecationError',
writable: true
})
Object.defineProperty(error, 'namespace', {
configurable: true,
enumerable: false,
value: namespace,
writable: true
})
Object.defineProperty(error, 'stack', {
configurable: true,
enumerable: false,
get: function () {
if (stackString !== undefined) {
return stackString
}
// prepare stack trace
return (stackString = createStackString.call(this, stack))
},
set: function setter (val) {
stackString = val
}
})
return error
}