7 #10

Merged
pamj3bxuk merged 5 commits from cunchu_zc into main 1 year ago

1006
node_modules/minipass/index.js generated vendored

File diff suppressed because it is too large Load Diff

116
node_modules/minizlib/constants.js generated vendored

@ -2,114 +2,228 @@
// Node v6 didn't export this, so we just hard code the version and rely
// on all the other hard-coded values from zlib v4736. When node v6
// support drops, we can just export the realZlibConstants object.
// 尝试获取 'zlib' 模块中的 'constants' 属性,如果获取失败(例如 'zlib' 模块不存在或没有 'constants' 属性),
// 则使用一个包含 'ZLIB_VERNUM: 4736' 的对象作为替代(这里使用了 istanbul ignore next 注释,可能是用于在测试覆盖时忽略该行,
// 表示该行在测试中不需要特别关注其执行情况)
const realZlibConstants = require('zlib').constants ||
/* istanbul ignore next */ { ZLIB_VERNUM: 4736 }
/* istanbul ignore next */ { ZLIB_VERNUM: 4736 };
// 使用 Object.freeze 冻结对象,防止其被修改,通过 Object.assign 将多个对象合并为一个新对象,并将其作为模块的导出内容。
// 首先创建一个继承自 null 的空对象Object.create(null))作为基础对象,然后将一系列属性添加到这个基础对象上。
module.exports = Object.freeze(Object.assign(Object.create(null), {
// 以下是定义的一系列常量及其对应的值,这些常量大概率与 zlib 相关的压缩、解压操作及配置等方面有关。
// 表示不进行刷新操作的常量,常用于 zlib 相关的流操作等场景,值为 0
Z_NO_FLUSH: 0,
// 表示部分刷新的常量,在某些特定的流数据处理中间阶段可能会用到,值为 1
Z_PARTIAL_FLUSH: 1,
// 表示同步刷新的常量,用于强制将缓冲数据立即刷新处理,值为 2
Z_SYNC_FLUSH: 2,
// 表示完全刷新的常量,可能涉及更彻底的数据处理和刷新,值为 3
Z_FULL_FLUSH: 3,
// 用于标记压缩或解压操作完成的常量,值为 4
Z_FINISH: 4,
// 可能与数据块相关的一个标识常量,具体含义需结合 zlib 具体使用场景,值为 5
Z_BLOCK: 5,
// 表示操作成功的常量,通常用于判断 zlib 相关函数调用的返回结果,值为 0
Z_OK: 0,
// 表示流已经到达结束状态的常量,比如在解压完成等情况时使用,值为 1
Z_STREAM_END: 1,
// 表示需要字典(可能用于特定的压缩算法辅助解压等情况)的常量,值为 2
Z_NEED_DICT: 2,
// 表示出现了系统错误errno 相关,通常关联底层系统调用错误情况)的常量,值为 -1
Z_ERRNO: -1,
// 表示流出现错误的常量,比如流的初始化、配置等方面出现问题,值为 -2
Z_STREAM_ERROR: -2,
// 表示数据出现错误的常量,可能是传入的数据格式不符合要求等情况,值为 -3
Z_DATA_ERROR: -3,
// 表示内存相关错误的常量,比如内存分配不足等情况,值为 -4
Z_MEM_ERROR: -4,
// 表示缓冲区相关错误的常量,例如缓冲区溢出、不足等问题,值为 -5
Z_BUF_ERROR: -5,
// 表示版本相关错误的常量,可能是使用的 zlib 版本与期望不符等情况,值为 -6
Z_VERSION_ERROR: -6,
// 表示不进行压缩的配置常量,对应压缩等级等相关设置,值为 0
Z_NO_COMPRESSION: 0,
// 表示以最快速度进行压缩的配置常量,牺牲一定的压缩率来换取速度,值为 1
Z_BEST_SPEED: 1,
// 表示以最佳压缩效果进行压缩的配置常量,可能会消耗更多时间和资源来获得最高的压缩率,值为 9
Z_BEST_COMPRESSION: 9,
// 表示使用默认压缩配置的常量,具体的默认压缩程度由 zlib 内部定义,值为 -1
Z_DEFAULT_COMPRESSION: -1,
// 可能是一种压缩策略相关的常量,具体含义取决于 zlib 具体实现中的压缩算法逻辑,值为 1
Z_FILTERED: 1,
// 可能表示仅使用哈夫曼编码(一种数据编码方式常用于压缩)的常量,值为 2
Z_HUFFMAN_ONLY: 2,
// 可能是与行程长度编码(一种简单的数据压缩编码方式)相关的常量,值为 3
Z_RLE: 3,
// 可能是一种固定模式(具体针对压缩算法中的某些固定配置情况)的常量,值为 4
Z_FIXED: 4,
// 表示默认压缩策略的常量,对应压缩算法中的策略选择,值为 0
Z_DEFAULT_STRATEGY: 0,
// 表示使用 deflate 压缩算法的标识常量,常用于指定具体的压缩方法,值为 1
DEFLATE: 1,
// 表示使用 inflate 解压算法的标识常量,用于指定解压操作,值为 2
INFLATE: 2,
// 表示使用 gzip 格式进行压缩或解压相关操作的标识常量gzip 是一种常见的压缩文件格式,值为 3
GZIP: 3,
// 表示对 gzip 格式文件进行解压操作的标识常量,与 GZIP 相对应,值为 4
GUNZIP: 4,
// 表示使用原始 deflate 算法(可能不包含 gzip 等格式的额外头部等信息)进行压缩的标识常量,值为 5
DEFLATERAW: 5,
// 表示使用原始 inflate 算法(对应 DEFLATERAW 进行解压操作)的标识常量,值为 6
INFLATERAW: 6,
// 可能是一个通用的解压相关的标识常量,具体含义取决于具体使用场景,值为 7
UNZIP: 7,
// 表示使用 Brotli 算法进行解码操作的标识常量Brotli 是一种新的压缩算法,值为 8
BROTLI_DECODE: 8,
// 表示使用 Brotli 算法进行编码(压缩)操作的标识常量,值为 9
BROTLI_ENCODE: 9,
// 表示 Brotli 算法中最小窗口位数的常量,窗口位数与压缩算法中的数据处理范围等相关,值为 8
Z_MIN_WINDOWBITS: 8,
// 表示 Brotli 算法中最大窗口位数的常量,限定了窗口位数的上限,值为 15
Z_MAX_WINDOWBITS: 15,
// 表示 Brotli 算法中默认窗口位数的常量,通常在未指定时使用的窗口位数设置,值为 15
Z_DEFAULT_WINDOWBITS: 15,
// 表示 Brotli 算法中最小数据块大小的常量,在处理数据块时的下限,值为 64
Z_MIN_CHUNK: 64,
// 表示 Brotli 算法中最大数据块大小的常量,理论上可以处理的最大数据块尺寸(这里设置为无穷大),值为 Infinity
Z_MAX_CHUNK: Infinity,
// 表示 Brotli 算法中默认数据块大小的常量,通常处理数据块时的默认尺寸,值为 16384
Z_DEFAULT_CHUNK: 16384,
// 表示 Brotli 算法中最小内存级别(可能与内存使用、分配策略相关)的常量,值为 1
Z_MIN_MEMLEVEL: 1,
// 表示 Brotli 算法中最大内存级别(限定内存使用相关策略的上限)的常量,值为 9
Z_MAX_MEMLEVEL: 9,
// 表示 Brotli 算法中默认内存级别(未指定时使用的内存级别设置)的常量,值为 8
Z_DEFAULT_MEMLEVEL: 8,
// 表示 Brotli 算法中最小压缩级别(类似压缩程度的设置,负数可能有特殊含义)的常量,值为 -1
Z_MIN_LEVEL: -1,
// 表示 Brotli 算法中最大压缩级别(限定压缩程度上限)的常量,值为 9
Z_MAX_LEVEL: 9,
// 表示 Brotli 算法中默认压缩级别(未指定时使用的压缩级别设置)的常量,值为 -1
Z_DEFAULT_LEVEL: -1,
// 表示 Brotli 算法中处理操作类型为常规处理的常量,对应具体操作阶段的标识,值为 0
BROTLI_OPERATION_PROCESS: 0,
// 表示 Brotli 算法中处理操作类型为刷新操作的常量,可能用于及时刷新缓冲数据等情况,值为 1
BROTLI_OPERATION_FLUSH: 1,
// 表示 Brotli 算法中处理操作类型为完成操作(类似结束整个压缩或解压流程)的常量,值为 2
BROTLI_OPERATION_FINISH: 2,
// 表示 Brotli 算法中处理操作类型为发出元数据(可能在特定场景下向外提供相关数据信息)的常量,值为 3
BROTLI_OPERATION_EMIT_METADATA: 3,
// 表示 Brotli 算法中通用模式(可能适用于多种类型数据的一种默认模式)的常量,值为 0
BROTLI_MODE_GENERIC: 0,
// 表示 Brotli 算法中文本模式(针对文本数据进行优化处理的模式)的常量,值为 1
BROTLI_MODE_TEXT: 1,
// 表示 Brotli 算法中字体模式(可能针对字体文件等特定数据类型优化)的常量,值为 2
BROTLI_MODE_FONT: 2,
// 表示 Brotli 算法中默认模式(未指定具体模式时使用的模式设置)的常量,值为 0
BROTLI_DEFAULT_MODE: 0,
// 表示 Brotli 算法中最小质量(可能与压缩后数据质量、还原效果等相关)的常量,值为 0
BROTLI_MIN_QUALITY: 0,
// 表示 Brotli 算法中最大质量(限定质量相关指标上限)的常量,值为 11
BROTLI_MAX_QUALITY: 11,
// 表示 Brotli 算法中默认质量(未指定质量时使用的质量设置)的常量,值为 11
BROTLI_DEFAULT_QUALITY: 11,
// 表示 Brotli 算法中最小窗口位数(与前面类似,可能在不同场景下的窗口位数限制)的常量,值为 10
BROTLI_MIN_WINDOW_BITS: 10,
// 表示 Brotli 算法中最大窗口位数(限定窗口位数范围上限)的常量,值为 24
BROTLI_MAX_WINDOW_BITS: 24,
// 表示 Brotli 算法中较大的最大窗口位数(可能用于特殊情况或更高要求场景下的窗口位数设置)的常量,值为 30
BROTLI_LARGE_MAX_WINDOW_BITS: 30,
// 表示 Brotli 算法中默认窗口(可能是综合考虑各种因素后的常用窗口设置)的常量,值为 22
BROTLI_DEFAULT_WINDOW: 22,
// 表示 Brotli 算法中最小输入块位数(与输入数据块大小、处理方式相关的设置)的常量,值为 16
BROTLI_MIN_INPUT_BLOCK_BITS: 16,
// 表示 Brotli 算法中最大输入块位数(限定输入块位数上限)的常量,值为 24
BROTLI_MAX_INPUT_BLOCK_BITS: 24,
// 表示 Brotli 算法中参数类型为模式相关(用于设置算法模式相关参数)的常量,值为 0
BROTLI_PARAM_MODE: 0,
// 表示 Brotli 算法中参数类型为质量相关(用于调整压缩质量相关参数)的常量,值为 1
BROTLI_PARAM_QUALITY: 1,
// 表示 Brotli 算法中参数类型为窗口大小相关(用于设置窗口位数等相关参数)的常量,值为 2
BROTLI_PARAM_LGWIN: 2,
// 表示 Brotli 算法中参数类型为块大小相关(用于设置数据块相关参数)的常量,值为 3
BROTLI_PARAM_LGBLOCK: 3,
// 表示 Brotli 算法中参数类型为禁用字面量上下文建模(可能是一种高级的压缩算法特性控制参数)的常量,值为 4
BROTLI_PARAM_DISABLE_LITERAL_CONTEXT_MODELING: 4,
// 表示 Brotli 算法中参数类型为大小提示(可能用于提前告知算法期望的数据大小等情况)的常量,值为 5
BROTLI_PARAM_SIZE_HINT: 5,
// 表示 Brotli 算法中参数类型为大窗口(与前面大窗口相关设置关联)的常量,值为 6
BROTLI_PARAM_LARGE_WINDOW: 6,
// 表示 Brotli 算法中参数类型为后缀数量(可能在特定数据处理中有相关意义)的常量,值为 7
BROTLI_PARAM_NPOSTFIX: 7,
// 表示 Brotli 算法中参数类型为直接数量(具体含义取决于算法内部逻辑)的常量,值为 8
BROTLI_PARAM_NDIRECT: 8,
// 表示 Brotli 解码器出现错误结果的常量,用于判断解码结果是否为错误情况,值为 0
BROTLI_DECODER_RESULT_ERROR: 0,
// 表示 Brotli 解码器成功的常量,用于判断解码操作是否成功完成,值为 1
BROTLI_DECODER_RESULT_SUCCESS: 1,
// 表示 Brotli 解码器需要更多输入数据才能继续解码的常量,用于反馈解码状态,值为 2
BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT: 2,
// 表示 Brotli 解码器需要更多输出空间(可能是缓冲区等已满,需要更多空间来存放解码后的数据)才能继续解码的常量,值为 3
BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT: 3,
// 表示 Brotli 解码器参数类型为禁用环形缓冲区重新分配(可能涉及内存管理、缓冲区优化相关设置)的常量,值为 0
BROTLI_DECODER_PARAM_DISABLE_RING_BUFFER_REALLOCATION: 0,
// 表示 Brotli 解码器参数类型为大窗口(与前面大窗口相关设置关联)的常量,值为 1
BROTLI_DECODER_PARAM_LARGE_WINDOW: 1,
// 表示 Brotli 解码器没有错误的常量,用于判断解码器当前状态是否无错,值为 0
BROTLI_DECODER_NO_ERROR: 0,
// 表示 Brotli 解码器成功的常量,用于判断解码器操作是否成功,值为 1
BROTLI_DECODER_SUCCESS: 1,
// 表示 Brotli 解码器需要更多输入数据才能继续操作的常量,用于反馈解码器的状态需求,值为 2
BROTLI_DECODER_NEEDS_MORE_INPUT: 2,
// 表示 Brotli 解码器需要更多输出空间(类似前面需要更多输出情况)才能继续操作的常量,值为 3
BROTLI_DECODER_NEEDS_MORE_OUTPUT: 3,
// 表示 Brotli 解码器出现格式错误(具体是过度的半字节相关问题,可能涉及数据格式解析异常)的常量,值为 -1
BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_NIBBLE: -1,
// 表示 Brotli 解码器出现格式错误(涉及保留字段相关问题,可能是数据格式不符合规范)的常量,值为 -2
BROTLI_DECODER_ERROR_FORMAT_RESERVED: -2,
// 表示 Brotli 解码器出现格式错误(过度的元数据半字节相关问题,可能在处理元数据时格式异常)的常量,值为 -3
BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_META_NIBBLE: -3,
// 表示 Brotli 解码器出现格式错误(简单哈夫曼字母表相关问题,可能是哈夫曼编码相关数据格式不符合要求)的常量,值为 -4
BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_ALPHABET: -4,
// 表示 Brotli 解码器出现格式错误(简单哈夫曼相同相关问题,可能是哈夫曼编码重复等格式异常情况)的常量,值为 -5
BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_SAME: -5,
// 表示 Brotli 解码器出现格式错误(上下文映射空间相关问题,可能是数据结构中上下文映射部分格式不符合要求)的常量,值为 -6
BROTLI_DECODER_ERROR_FORMAT_CL_SPACE: -6,
// 表示 Brotli 解码器出现格式错误(哈夫曼空间相关问题,可能是哈夫曼编码相关数据结构格式不符合要求)的常量,值为 -7
BROTLI_DECODER_ERROR_FORMAT_HUFFMAN_SPACE: -7,
// 表示 Brot
// 表示Brotli解码器出现格式错误具体是上下文映射重复相关问题可能是在处理数据时上下文映射部分出现不符合规范的重复情况的常量值为 -8
BROTLI_DECODER_ERROR_FORMAT_CONTEXT_MAP_REPEAT: -8,
// 表示Brotli解码器出现格式错误与数据块长度相关的第一种错误情况具体错误原因需结合Brotli解码器对块长度的格式要求来确定的常量值为 -9
BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_1: -9,
// 表示Brotli解码器出现格式错误与数据块长度相关的第二种错误情况同样需依据具体的块长度格式规范来判断错误缘由的常量值为 -10
BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_2: -10,
// 表示Brotli解码器出现格式错误与转换相关的问题可能是在对数据进行某种转换操作时数据格式不符合要求等情况的常量值为 -11
BROTLI_DECODER_ERROR_FORMAT_TRANSFORM: -11,
// 表示Brotli解码器出现格式错误与字典相关的问题比如字典数据格式不符合要求或者字典使用方面出现异常等情况的常量值为 -12
BROTLI_DECODER_ERROR_FORMAT_DICTIONARY: -12,
// 表示Brotli解码器出现格式错误与窗口位数相关的问题可能是传入的窗口位数参数不符合要求或者数据中体现的窗口位数信息有错误等情况的常量值为 -13
BROTLI_DECODER_ERROR_FORMAT_WINDOW_BITS: -13,
// 表示Brotli解码器出现格式错误与填充相关的第一种错误情况具体的填充格式不符合Brotli解码器的要求等情况的常量值为 -14
BROTLI_DECODER_ERROR_FORMAT_PADDING_1: -14,
// 表示Brotli解码器出现格式错误与填充相关的第二种错误情况类似第一种填充错误只是具体错误细节有所不同的常量值为 -15
BROTLI_DECODER_ERROR_FORMAT_PADDING_2: -15,
// 表示Brotli解码器出现格式错误与距离相关的问题比如在数据处理中涉及到的距离参数、指针距离等不符合格式要求等情况的常量值为 -16
BROTLI_DECODER_ERROR_FORMAT_DISTANCE: -16,
// 表示Brotli解码器出现字典未设置的错误可能在需要字典辅助解码但却没有正确设置字典的情况下出现该错误的常量值为 -19
BROTLI_DECODER_ERROR_DICTIONARY_NOT_SET: -19,
// 表示Brotli解码器出现参数无效的错误即传入的参数不符合解码器对参数的合法性要求比如参数类型、范围等不正确的常量值为 -20
BROTLI_DECODER_ERROR_INVALID_ARGUMENTS: -20,
// 表示Brotli解码器出现分配上下文模式相关内存失败的错误可能是在为上下文模式相关的数据结构分配内存时出现内存不足等问题的常量值为 -21
BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MODES: -21,
// 表示Brotli解码器出现分配树组相关内存失败的错误在为树组相关的数据结构分配内存时遇到内存相关的问题导致无法正常分配的常量值为 -22
BROTLI_DECODER_ERROR_ALLOC_TREE_GROUPS: -22,
// 表示Brotli解码器出现分配上下文映射相关内存失败的错误涉及到上下文映射的数据结构在内存分配环节出现问题无法成功分配内存的常量值为 -25
BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MAP: -25,
// 表示Brotli解码器出现分配环形缓冲区相关内存失败的第一种错误情况可能是第一次尝试分配环形缓冲区内存时遇到问题比如内存不足等原因的常量值为 -26
BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_1: -26,
// 表示Brotli解码器出现分配环形缓冲区相关内存失败的第二种错误情况与第一种类似但可能是后续再次分配或者另一种相关的内存分配问题导致的错误的常量值为 -27
BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_2: -27,
// 表示Brotli解码器出现分配块类型树相关内存失败的错误在为块类型树相关的数据结构分配内存时出现了内存方面的异常情况的常量值为 -30
BROTLI_DECODER_ERROR_ALLOC_BLOCK_TYPE_TREES: -30,
// 表示Brotli解码器出现不可达可能是代码执行流程进入到了本不应到达的逻辑部分意味着程序出现了逻辑错误或者异常情况的错误的常量值为 -31
BROTLI_DECODER_ERROR_UNREACHABLE: -31,
}, realZlibConstants))

439
node_modules/minizlib/index.js generated vendored

@ -1,320 +1,421 @@
'use strict'
const assert = require('assert')
const Buffer = require('buffer').Buffer
const realZlib = require('zlib')
const constants = exports.constants = require('./constants.js')
const Minipass = require('minipass')
const OriginalBufferConcat = Buffer.concat
// 引入Node.js的内置断言模块用于编写测试用例时进行各种断言检查确保代码符合预期的行为
const assert = require('assert');
// 引入Node.js的Buffer模块用于处理二进制数据如创建、操作字节缓冲区等
const Buffer = require('buffer').Buffer;
// 引入Node.js的zlib模块用于进行数据的压缩和解压缩操作
const realZlib = require('zlib');
// 引入自定义的常量模块(./constants.js并将其赋值给当前模块的exports.constants方便其他模块使用这些常量
const constants = exports.constants = require('./constants.js');
// 引入Minipass模块Minipass可能是一个实现了流相关功能的基础类用于构建自定义的流对象此处为推测具体功能依赖其自身实现
const Minipass = require('minipass');
// 保存原始的Buffer.concat方法后续代码中会对Buffer.concat进行临时修改这里先保存以便恢复
const OriginalBufferConcat = Buffer.concat;
// 自定义的错误类ZlibError继承自Error类用于包装zlib相关操作出现的错误提供更详细和统一的错误信息格式
class ZlibError extends Error {
constructor (err) {
super('zlib: ' + err.message)
this.code = err.code
this.errno = err.errno
// 调用父类Error的构造函数传入格式化后的错误消息消息前缀为 'zlib: ',后面跟上原始错误的消息内容
super('zlib: ' + err.message);
// 将原始错误的错误码赋值给当前错误对象的code属性方便外部根据错误码判断具体错误类型
this.code = err.code;
// 将原始错误的系统错误号errno赋值给当前错误对象的errno属性用于更底层的错误追踪和处理如果适用
this.errno = err.errno;
/* istanbul ignore if */
// 以下代码块在测试覆盖时可能会被忽略(通常是一些特殊情况或者难以触发的逻辑),
// 如果当前错误对象没有设置错误码code属性为空则将错误码默认设置为 'ZLIB_ERROR'
if (!this.code)
this.code = 'ZLIB_ERROR'
this.code = 'ZLIB_ERROR';
this.message = 'zlib: ' + err.message
Error.captureStackTrace(this, this.constructor)
// 再次设置错误消息,确保消息格式符合预期,这里与构造函数开头设置的消息内容一致,可能是为了代码的清晰性和一致性
this.message = 'zlib: ' + err.message;
// 捕获当前错误对象的堆栈信息,方便在调试时查看错误发生的调用栈情况,第二个参数指定了构造函数作为起始位置
Error.captureStackTrace(this, this.constructor);
}
// 重写name属性的访问器返回自定义的错误名称 'ZlibError',用于更清晰地标识错误类型
get name () {
return 'ZlibError'
return 'ZlibError';
}
}
// the Zlib class they all inherit from
// This thing manages the queue of requests, and returns
// true or false if there is anything in the queue when
// you call the .write() method.
const _opts = Symbol('opts')
const _flushFlag = Symbol('flushFlag')
const _finishFlushFlag = Symbol('finishFlushFlag')
const _fullFlushFlag = Symbol('fullFlushFlag')
const _handle = Symbol('handle')
const _onError = Symbol('onError')
const _sawError = Symbol('sawError')
const _level = Symbol('level')
const _strategy = Symbol('strategy')
const _ended = Symbol('ended')
const _defaultFullFlush = Symbol('_defaultFullFlush')
// 以下定义了一系列Symbol类型的私有属性名用于在ZlibBase类中标记一些内部使用的属性
// 通过Symbol可以创建唯一的标识符避免属性名冲突实现一定程度的封装和数据隐藏
const _opts = Symbol('opts');
const _flushFlag = Symbol('flushFlag');
const _finishFlushFlag = Symbol('finishFlushFlag');
const _fullFlushFlag = Symbol('fullFlushFlag');
const _handle = Symbol('handle');
const _onError = Symbol('onError');
const _sawError = Symbol('sawError');
const _level = Symbol('level');
const _strategy = Symbol('strategy');
const _ended = Symbol('ended');
const _defaultFullFlush = Symbol('_defaultFullFlush');
// ZlibBase类继承自Minipass类作为其他与zlib相关的类的基类用于管理压缩/解压操作的请求队列等功能
class ZlibBase extends Minipass {
constructor (opts, mode) {
if (!opts || typeof opts !== 'object')
throw new TypeError('invalid options for ZlibBase constructor')
super(opts)
this[_ended] = false
this[_opts] = opts
this[_flushFlag] = opts.flush
this[_finishFlushFlag] = opts.finishFlush
// this will throw if any options are invalid for the class selected
// 首先检查传入的opts参数如果不存在或者不是对象类型抛出TypeError异常提示传入的ZlibBase构造函数参数无效
if (!opts || typeof opts!== 'object')
throw new TypeError('invalid options for ZlibBase constructor');
// 调用父类Minipass的构造函数传入opts参数完成父类的初始化操作
super(opts);
// 标记当前对象是否已经结束初始化为false表示尚未结束通过私有属性 _ended 来记录
this[_ended] = false;
// 将传入的opts参数保存到私有属性 _opts 中,方便后续在类中使用这些配置选项
this[_opts] = opts;
// 将opts中的flush属性值赋给私有属性 _flushFlag可能用于控制数据的刷新方式具体依赖zlib相关逻辑
this[_flushFlag] = opts.flush;
// 将opts中的finishFlush属性值赋给私有属性 _finishFlushFlag可能与结束时的刷新操作相关同样依赖具体逻辑
this[_finishFlushFlag] = opts.finishFlush;
// 尝试根据传入的mode创建对应的zlib实例通过realZlib[mode]这里假设realZlib对象有根据不同模式创建实例的功能
// 如果创建过程中出现错误捕获异常并抛出一个经过包装的ZlibError错误对象确保错误信息符合自定义的格式和处理逻辑
try {
this[_handle] = new realZlib[mode](opts)
this[_handle] = new realZlib[mode](opts);
} catch (er) {
// make sure that all errors get decorated properly
throw new ZlibError(er)
throw new ZlibError(er);
}
// 定义一个内部的错误处理函数 _onError用于处理zlib实例触发的错误事件
this[_onError] = (err) => {
this[_sawError] = true
// there is no way to cleanly recover.
// continuing only obscures problems.
this.close()
this.emit('error', err)
}
this[_handle].on('error', er => this[_onError](new ZlibError(er)))
this.once('end', () => this.close)
// 标记已经出现错误,通过私有属性 _sawError 记录,后续可以根据此标记进行相应的处理判断
this[_sawError] = true;
// 在出现错误的情况下认为无法进行干净的恢复操作直接关闭相关资源调用close方法
// 继续执行可能会掩盖问题,所以选择关闭并触发 'error' 事件向外传递错误信息
this.close();
this.emit('error', err);
};
// 监听zlib实例的 'error' 事件,当触发时调用内部的 _onError 函数来处理错误将原始错误包装为ZlibError类型后再处理
this[_handle].on('error', er => this[_onError](new ZlibError(er)));
// 监听当前对象继承自Minipass可能是流相关的结束事件的 'end' 事件当触发时调用close方法进行关闭相关操作
this.once('end', () => this.close);
}
// close方法用于关闭与zlib相关的资源可能是释放底层的句柄等操作
close () {
// 如果存在zlib实例的句柄_handle属性不为null则调用其close方法进行关闭操作
// 然后将 _handle 属性设置为null表示已经关闭最后触发 'close' 事件通知外部相关操作已完成
if (this[_handle]) {
this[_handle].close()
this[_handle] = null
this.emit('close')
this[_handle].close();
this[_handle] = null;
this.emit('close');
}
}
// reset方法用于重置zlib相关的状态前提是没有出现过错误通过 _sawError 属性判断),
// 如果没有错误且存在zlib实例的句柄调用句柄的reset方法进行重置操作具体重置的内容依赖zlib底层实现
reset () {
if (!this[_sawError]) {
assert(this[_handle], 'zlib binding closed')
return this[_handle].reset()
assert(this[_handle], 'zlib binding closed');
return this[_handle].reset();
}
}
// flush方法用于执行数据的刷新操作根据传入的参数或默认的刷新标志来决定刷新方式
flush (flushFlag) {
// 如果已经标记为结束状态ended为真则直接返回不进行刷新操作
if (this.ended)
return
return;
if (typeof flushFlag !== 'number')
flushFlag = this[_fullFlushFlag]
this.write(Object.assign(Buffer.alloc(0), { [_flushFlag]: flushFlag }))
// 如果传入的flushFlag参数不是数字类型使用默认的完全刷新标志_fullFlushFlag具体值应在类的其他地方定义或初始化
if (typeof flushFlag!== 'number')
flushFlag = this[_fullFlushFlag];
// 创建一个空的Buffer对象并将刷新标志_flushFlag作为属性添加到该对象上然后调用write方法将其写入流中进行刷新操作
this.write(Object.assign(Buffer.alloc(0), { [_flushFlag]: flushFlag }));
}
// end方法用于标记流的结束操作并进行一些相关的清理和刷新操作
end (chunk, encoding, cb) {
// 如果传入了数据chunk先调用write方法将其写入流中进行相应的编码转换等处理后面的代码会实现
if (chunk)
this.write(chunk, encoding)
this.flush(this[_finishFlushFlag])
this[_ended] = true
return super.end(null, null, cb)
this.write(chunk, encoding);
// 调用flush方法进行结束时的刷新操作使用 _finishFlushFlag 作为刷新标志
this.flush(this[_finishFlushFlag]);
// 标记当前对象已经结束(通过私有属性 _ended 设置为true
this[_ended] = true;
// 调用父类Minipass的end方法传入null表示没有额外的数据要写入结束流操作并传递回调函数cb如果有的话
return super.end(null, null, cb);
}
// ended属性访问器用于获取当前对象是否已经结束的状态返回存储在 _ended 属性中的值
get ended () {
return this[_ended]
return this[_ended];
}
// write方法用于向流中写入数据涉及到对数据的处理、调用zlib实例进行压缩/解压操作以及将结果写入父类流等复杂逻辑
write (chunk, encoding, cb) {
// process the chunk using the sync process
// then super.write() all the outputted chunks
// 如果传入的第二个参数encoding是函数类型将其作为回调函数cb同时将encoding默认设置为 'utf8'
// 这是一种常见的参数处理方式,用于统一参数格式,方便后续对数据进行处理
if (typeof encoding === 'function')
cb = encoding, encoding = 'utf8'
cb = encoding, encoding = 'utf8';
if (typeof chunk === 'string')
chunk = Buffer.from(chunk, encoding)
// 如果传入的第一个参数chunk是字符串类型将其转换为Buffer类型使用指定的encoding进行编码转换
if (typeof chunk ==='string')
chunk = Buffer.from(chunk, encoding);
// 如果已经出现过错误_sawError为真直接返回不再进行写入操作
if (this[_sawError])
return
assert(this[_handle], 'zlib binding closed')
// _processChunk tries to .close() the native handle after it's done, so we
// intercept that by temporarily making it a no-op.
const nativeHandle = this[_handle]._handle
const originalNativeClose = nativeHandle.close
nativeHandle.close = () => {}
const originalClose = this[_handle].close
this[_handle].close = () => {}
// It also calls `Buffer.concat()` at the end, which may be convenient
// for some, but which we are not interested in as it slows us down.
Buffer.concat = (args) => args
let result
return;
// 通过断言确保存在zlib实例的句柄如果不存在则抛出异常提示zlib绑定已关闭无法进行写入操作
assert(this[_handle], 'zlib binding closed');
// 以下代码块对zlib实例的原生句柄_handle._handle进行一些临时操作主要是拦截其close方法使其变为空操作noop
// 目的是避免在处理数据过程中意外关闭句柄同时也保存了原始的close方法方便后续恢复
const nativeHandle = this[_handle]._handle;
const originalNativeClose = nativeHandle.close;
nativeHandle.close = () => {};
const originalClose = this[_handle].close;
this[_handle].close = () => {};
// 临时修改Buffer.concat方法为一个简单返回参数的函数这里修改的目的可能是为了优化性能或者避免一些不必要的操作
// 因为原有的Buffer.concat可能会有一些额外的逻辑如合并缓冲区等而此处不需要这些功能
Buffer.concat = (args) => args;
let result;
try {
// 根据传入的chunk数据是否包含 _flushFlag 属性以及其值来确定刷新标志,如果没有则使用类中保存的 _flushFlag 属性值
const flushFlag = typeof chunk[_flushFlag] === 'number'
? chunk[_flushFlag] : this[_flushFlag]
result = this[_handle]._processChunk(chunk, flushFlag)
// if we don't throw, reset it back how it was
Buffer.concat = OriginalBufferConcat
? chunk[_flushFlag] : this[_flushFlag];
// 调用zlib实例的 _processChunk方法处理数据chunk传入数据和刷新标志获取处理结果可能是经过压缩/解压后的缓冲区数据等)
result = this[_handle]._processChunk(chunk, flushFlag);
// 如果没有抛出异常说明处理成功将Buffer.concat方法恢复为原始的方法之前保存的OriginalBufferConcat
Buffer.concat = OriginalBufferConcat;
} catch (err) {
// or if we do, put Buffer.concat() back before we emit error
// Error events call into user code, which may call Buffer.concat()
Buffer.concat = OriginalBufferConcat
this[_onError](new ZlibError(err))
// 如果在处理过程中抛出异常先将Buffer.concat方法恢复为原始的方法
// 然后调用内部的 _onError 方法处理错误将原始错误包装为ZlibError类型并触发 'error' 事件向外通知错误情况
// 之所以要先恢复Buffer.concat方法是因为后续的错误处理可能会涉及到用户代码调用Buffer.concat方法如果不恢复可能导致错误
Buffer.concat = OriginalBufferConcat;
this[_onError](new ZlibError(err));
} finally {
if (this[_handle]) {
// Core zlib resets `_handle` to null after attempting to close the
// native handle. Our no-op handler prevented actual closure, but we
// need to restore the `._handle` property.
this[_handle]._handle = nativeHandle
nativeHandle.close = originalNativeClose
this[_handle].close = originalClose
// `_processChunk()` adds an 'error' listener. If we don't remove it
// after each call, these handlers start piling up.
this[_handle].removeAllListeners('error')
// 在finally块中确保无论是否出现异常都要进行一些清理和恢复操作
// 将zlib实例的 _handle 属性重新指向原始的原生句柄之前保存的nativeHandle恢复原生句柄的close方法为原始的方法
this[_handle]._handle = nativeHandle;
nativeHandle.close = originalNativeClose;
this[_handle].close = originalClose;
// 移除zlib实例对 'error' 事件的所有监听器,因为 _processChunk方法每次调用可能会添加 'error' 监听器,
// 如果不及时移除,这些监听器会不断累积,导致意外的行为
this[_handle].removeAllListeners('error');
}
}
let writeReturn
let writeReturn;
// 如果有处理结果result进行后续的写入操作
if (result) {
// 如果处理结果是数组且长度大于0说明可能有多个缓冲区数据需要写入
// 先将第一个缓冲区通常是zlib实例内部的输出缓冲区可能会被复用所以需要复制一份通过父类的write方法写入流中
// 然后遍历数组的其余元素依次调用父类的write方法将数据写入流中
if (Array.isArray(result) && result.length > 0) {
// The first buffer is always `handle._outBuffer`, which would be
// re-used for later invocations; so, we always have to copy that one.
writeReturn = super.write(Buffer.from(result[0]))
writeReturn = super.write(Buffer.from(result[0]));
for (let i = 1; i < result.length; i++) {
writeReturn = super.write(result[i])
writeReturn = super.write(result[i]);
}
} else {
writeReturn = super.write(Buffer.from(result))
// 如果结果不是数组或者数组长度为0直接将结果单个缓冲区数据通过父类的write方法写入流中
writeReturn = super.write(Buffer.from(result));
}
}
// 如果有回调函数cb执行回调函数通常用于通知写入操作完成等情况
if (cb)
cb()
return writeReturn
cb();
// 返回写入操作的返回值可能是父类write方法的返回值具体含义依赖父类的实现逻辑
return writeReturn;
}
}
// Zlib类继承自ZlibBase类用于进一步定制基于zlib库的压缩/解压相关操作,添加特定的默认参数设置等功能
class Zlib extends ZlibBase {
constructor (opts, mode) {
opts = opts || {}
opts.flush = opts.flush || constants.Z_NO_FLUSH
opts.finishFlush = opts.finishFlush || constants.Z_FINISH
super(opts, mode)
this[_fullFlushFlag] = constants.Z_FULL_FLUSH
this[_level] = opts.level
this[_strategy] = opts.strategy
// 如果没有传入opts参数则创建一个空对象作为默认值确保后续对opts属性的访问不会出现问题
opts = opts || {};
// 如果opts中没有设置flush属性将其默认设置为 constants.Z_NO_FLUSH从之前引入的常量模块中获取可能表示不进行刷新操作的常量值
opts.flush = opts.flush || constants.Z_NO_FLUSH;
// 如果opts中没有设置finishFlush属性将其默认设置为 constants.Z_FINISH可能表示完成时的刷新操作相关常量值
opts.finishFlush = opts.finishFlush || constants.Z_FINISH;
// 调用父类ZlibBase的构造函数传入处理后的opts参数和mode参数完成父类的初始化以及与zlib底层实例的创建等操作
super(opts, mode);
// 设置完全刷新标志_fullFlushFlag为 constants.Z_FULL_FLUSH具体含义与zlib的刷新机制相关可能是一种较为彻底的刷新方式对应的常量值
this[_fullFlushFlag] = constants.Z_FULL_FLUSH;
// 将opts中的level属性值保存到私有属性 _level 中,可能用于记录当前压缩/解压操作的级别设置具体依赖zlib相关逻辑
this[_level] = opts.level;
// 将opts中的strategy属性值保存到私有属性 _strategy 中,可能用于记录当前采用的压缩/解压策略(同样依赖具体逻辑)
this[_strategy] = opts.strategy;
}
// params方法用于修改当前zlib实例的参数如压缩级别、策略等但需要满足一定条件并进行一些复杂的内部处理
params (level, strategy) {
// 如果已经出现过错误_sawError为真直接返回不进行参数修改操作可能是在出现错误后认为当前状态不适合修改参数
if (this[_sawError])
return
return;
// 如果不存在zlib实例的句柄_handle为null抛出一个错误提示在绑定已关闭的情况下无法切换参数
if (!this[_handle])
throw new Error('cannot switch params when binding is closed')
throw new Error('cannot switch params when binding is closed');
// 以下代码块在测试覆盖时可能会被忽略(通常是一些难以触发或者不适合在常规测试中执行的逻辑),
// 如果当前zlib实例不支持params方法即 _handle.params不存在抛出一个错误提示在当前实现中不支持此操作
// 这里可能是因为不同版本或者不同底层实现对参数修改的支持情况不一致导致的判断
// no way to test this without also not supporting params at all
/* istanbul ignore if */
if (!this[_handle].params)
throw new Error('not supported in this implementation')
if (this[_level] !== level || this[_strategy] !== strategy) {
this.flush(constants.Z_SYNC_FLUSH)
assert(this[_handle], 'zlib binding closed')
// .params() calls .flush(), but the latter is always async in the
// core zlib. We override .flush() temporarily to intercept that and
// flush synchronously.
const origFlush = this[_handle].flush
throw new Error('not supported in this implementation');
// 如果传入的新参数level或strategy与当前保存的参数_level、_strategy不一致进行参数修改操作
if (this[_level]!== level || this[_strategy]!== strategy) {
// 先调用flush方法进行同步刷新操作使用 constants.Z_SYNC_FLUSH 作为刷新标志,确保数据处于合适的状态以便修改参数
this.flush(constants.Z_SYNC_FLUSH);
// 通过断言确保存在zlib实例的句柄如果不存在则抛出异常提示zlib绑定已关闭无法进行参数修改操作
assert(this[_handle], 'zlib binding closed');
// 以下代码是为了处理核心zlib库中.params() 方法调用.flush() 方法且后者是异步的情况,
// 在这里临时重写zlib实例的.flush() 方法使其在内部调用当前类的flush方法实现同步刷新并执行传入的回调函数cb
// 这样可以拦截并改变原本异步的刷新行为,使其符合当前参数修改时的同步需求
const origFlush = this[_handle].flush;
this[_handle].flush = (flushFlag, cb) => {
this.flush(flushFlag)
cb()
}
this.flush(flushFlag);
cb();
};
try {
this[_handle].params(level, strategy)
// 调用zlib实例的.params() 方法传入新的参数level和strategy实际执行参数修改操作具体修改的内容依赖zlib底层实现
this[_handle].params(level, strategy);
} finally {
this[_handle].flush = origFlush
// 在无论是否出现异常的情况下都要将zlib实例的.flush() 方法恢复为原始的方法之前保存的origFlush确保后续操作不受影响
this[_handle].flush = origFlush;
}
/* istanbul ignore else */
// 以下代码块在测试覆盖时可能会被默认忽略(可能是一些正常流程下必然会执行的逻辑),
// 如果zlib实例的句柄仍然存在即没有在参数修改过程中出现意外关闭等情况更新当前对象保存的参数_level和 _strategy为新传入的值
if (this[_handle]) {
this[_level] = level
this[_strategy] = strategy
this[_level] = level;
this[_strategy] = strategy;
}
}
}
}
// minimal 2-byte header
// Deflate类继承自Zlib类代表使用deflate压缩算法的相关操作构造函数中传入opts参数并调用父类Zlib的构造函数指定模式为 'Deflate'
// 它可能会在创建实例时根据Zlib类以及更上层的ZlibBase类的逻辑初始化与deflate算法相关的配置和底层zlib实例等内容
class Deflate extends Zlib {
constructor (opts) {
super(opts, 'Deflate')
super(opts, 'Deflate');
}
}
// Inflate类继承自Zlib类代表使用inflate解压算法的相关操作构造函数中传入opts参数并调用父类Zlib的构造函数指定模式为 'Inflate'
// 用于初始化与inflate算法相关的配置和底层zlib实例等以便后续进行解压相关的操作
class Inflate extends Zlib {
constructor (opts) {
super(opts, 'Inflate')
super(opts, 'Inflate');
}
}
// gzip - bigger header, same deflate compression
// Gzip类继承自Zlib类用于处理gzip格式的压缩/解压相关操作构造函数中传入opts参数并调用父类Zlib的构造函数指定模式为 'Gzip'
// gzip是一种常见的带有特定头部格式的压缩文件格式该类在初始化时会基于Zlib类的基础配置和对应模式来准备相关操作
class Gzip extends Zlib {
constructor (opts) {
super(opts, 'Gzip')
super(opts, 'Gzip');
}
}
// Gunzip类继承自Zlib类主要用于对gzip格式文件进行解压操作构造函数中传入opts参数并调用父类Zlib的构造函数指定模式为 'Gunzip'
class Gunzip extends Zlib {
constructor (opts) {
super(opts, 'Gunzip')
super(opts, 'Gunzip');
}
}
// raw - no header
// DeflateRaw类继承自Zlib类用于使用原始的deflate算法进行操作可能不包含像gzip等格式那样的额外头部信息
// 构造函数传入opts参数并调用父类Zlib的构造函数指定模式为 'DeflateRaw',以便初始化相关配置和底层实例
class DeflateRaw extends Zlib {
constructor (opts) {
super(opts, 'DeflateRaw')
super(opts, 'DeflateRaw');
}
}
// InflateRaw类继承自Zlib类用于使用原始的inflate算法进行解压操作对应前面的DeflateRaw去除格式头部等信息的解压情况
// 构造函数传入opts参数并调用父类Zlib的构造函数指定模式为 'InflateRaw',来初始化相应的配置和底层实例
class InflateRaw extends Zlib {
constructor (opts) {
super(opts, 'InflateRaw')
super(opts, 'InflateRaw');
}
}
// auto-detect header.
// Unzip类继承自Zlib类用于自动检测文件头部并进行相应的解压操作可以处理多种格式通过自动识别头部来确定解压方式
// 构造函数传入opts参数并调用父类Zlib的构造函数指定模式为 'Unzip',以此来初始化相关配置和底层实例
class Unzip extends Zlib {
constructor (opts) {
super(opts, 'Unzip')
super(opts, 'Unzip');
}
}
// Brotli类继承自ZlibBase类用于基于Brotli压缩算法进行相关操作和Zlib类类似不过是针对Brotli算法的特定处理
class Brotli extends ZlibBase {
constructor (opts, mode) {
opts = opts || {}
opts = opts || {};
opts.flush = opts.flush || constants.BROTLI_OPERATION_PROCESS
opts.finishFlush = opts.finishFlush || constants.BROTLI_OPERATION_FINISH
// 如果opts中没有设置flush属性将其默认设置为 constants.BROTLI_OPERATION_PROCESS与Brotli算法的操作类型相关的常量可能表示常规处理阶段的刷新方式
opts.flush = opts.flush || constants.BROTLI_OPERATION_PROCESS;
// 如果opts中没有设置finishFlush属性将其默认设置为 constants.BROTLI_OPERATION_FINISH可能表示Brotli算法完成操作时的刷新方式相关常量值
opts.finishFlush = opts.finishFlush || constants.BROTLI_OPERATION_FINISH;
super(opts, mode)
// 调用父类ZlibBase的构造函数传入处理后的opts参数和mode参数完成父类的初始化以及与Brotli相关的底层实例创建等操作
super(opts, mode);
this[_fullFlushFlag] = constants.BROTLI_OPERATION_FLUSH
// 设置完全刷新标志_fullFlushFlag为 constants.BROTLI_OPERATION_FLUSH与Brotli算法的刷新操作类型相关的常量值
this[_fullFlushFlag] = constants.BROTLI_OPERATION_FLUSH;
}
}
// BrotliCompress类继承自Brotli类专门用于使用Brotli算法进行压缩操作构造函数传入opts参数并调用父类Brotli的构造函数指定模式为 'BrotliCompress'
// 以此来初始化与Brotli压缩相关的配置和底层实例等内容
class BrotliCompress extends Brotli {
constructor (opts) {
super(opts, 'BrotliCompress')
super(opts, 'BrotliCompress');
}
}
// BrotliDecompress类继承自Brotli类专门用于使用Brotli算法进行解压操作构造函数传入opts参数并调用父类Brotli的构造函数指定模式为 'BrotliDecompress'
// 用于初始化与Brotli解压相关的配置和底层实例等以便后续进行解压相关的操作
class BrotliDecompress extends Brotli {
constructor (opts) {
super(opts, 'BrotliDecompress')
super(opts, 'BrotliDecompress');
}
}
exports.Deflate = Deflate
exports.Inflate = Inflate
exports.Gzip = Gzip
exports.Gunzip = Gunzip
exports.DeflateRaw = DeflateRaw
exports.InflateRaw = InflateRaw
exports.Unzip = Unzip
// 将上述定义的各个类作为模块的导出内容,方便其他模块引入并使用这些类来进行相应的压缩、解压等操作
exports.Deflate = Deflate;
exports.Inflate = Inflate;
exports.Gzip = Gzip;
exports.Gunzip = Gunzip;
exports.DeflateRaw = DeflateRaw;
exports.InflateRaw = InflateRaw;
exports.Unzip = Unzip;
/* istanbul ignore else */
// 以下代码块在测试覆盖时可能会被默认忽略可能是根据不同Node.js版本的兼容性判断等情况
// 如果Node.js的 realZlib 模块中存在 BrotliCompress 函数即支持Brotli压缩算法则将 BrotliCompress 和 BrotliDecompress 类作为模块导出内容,
// 否则创建一个在构造函数中抛出错误的类作为它们的导出内容提示在当前版本的Node.js中不支持Brotli算法
if (typeof realZlib.BrotliCompress === 'function') {
exports.BrotliCompress = BrotliCompress
exports.BrotliDecompress = BrotliDecompress
exports.BrotliCompress = BrotliCompress;
exports.BrotliDecompress = BrotliDecompress;
} else {
exports.BrotliCompress = exports.BrotliDecompress = class {
constructor () {
throw new Error('Brotli is not supported in this version of Node.js')
throw new Error('Brotli is not supported in this version of Node.js');
}
}
}
};
}

97
node_modules/ms/index.js generated vendored

@ -1,62 +1,86 @@
/**
* Helpers.
* 辅助变量定义部分
* 这里定义了一系列时间单位换算相关的变量方便后续在时间格式化和解析等操作中使用
*/
// 定义变量 s 表示 1 秒对应的毫秒数,即 1000 毫秒
var s = 1000;
// 定义变量 m 表示 1 分钟对应的毫秒数,通过 1 分钟等于 60 秒来换算,即 60 * 1000 毫秒
var m = s * 60;
// 定义变量 h 表示 1 小时对应的毫秒数,通过 1 小时等于 60 分钟来换算,即 60 * 60 * 1000 毫秒
var h = m * 60;
// 定义变量 d 表示 1 天对应的毫秒数,通过 1 天等于 24 小时来换算,即 24 * 60 * 60 * 1000 毫秒
var d = h * 24;
// 定义变量 y 表示 1 年对应的毫秒数,这里取一年为 365.25 天进行换算,即 365.25 * 24 * 60 * 60 * 1000 毫秒
var y = d * 365.25;
/**
* Parse or format the given `val`.
* 此函数是模块对外暴露的主要接口用于解析给定的 `val` 参数如果是字符串或者格式化给定的 `val` 参数如果是数字
*
* Options:
*
* - `long` verbose formatting [false]
* 可以传入一个可选的 `options` 对象其中 `long` 属性用于控制是否采用详细冗长的格式化方式默认值为 `false`
*
* @param {String|Number} val
* @param {Object} [options]
* @throws {Error} throw an error if val is not a non-empty string or a number
* @return {String|Number}
* @param {String|Number} val 要处理的参数可以是字符串或者数字类型
* @param {Object} [options] 可选的配置对象用于控制格式化等相关行为
* @throws {Error} throw an error if val is not a non-empty string or a number 如果 `val` 既不是非空字符串也不是有效的数字会抛出一个错误
* @return {String|Number} 根据 `val` 的类型以及 `options` 的配置返回相应的解析或格式化后的结果可能是字符串或者数字类型
* @api public
*/
module.exports = function(val, options) {
// 如果没有传入 `options` 参数,则创建一个空对象作为默认值,确保后续对 `options` 属性的访问不会出现问题
options = options || {};
// 获取 `val` 的类型,通过 `typeof` 操作符判断是字符串、数字还是其他类型
var type = typeof val;
if (type === 'string' && val.length > 0) {
// 如果 `val` 是字符串类型且长度大于 0说明需要进行解析操作调用 `parse` 函数(内部私有函数)进行解析,并返回解析结果
if (type ==='string' && val.length > 0) {
return parse(val);
} else if (type === 'number' && isNaN(val) === false) {
return options.long ? fmtLong(val) : fmtShort(val);
// 如果 `val` 是数字类型且不是 `NaN`(即有效数字),根据 `options.long` 的值来决定调用 `fmtLong`(详细格式化)函数还是 `fmtShort`(简短格式化)函数进行格式化,并返回格式化后的结果
return options.long? fmtLong(val) : fmtShort(val);
}
// 如果 `val` 不符合上述两种合法情况(既不是非空字符串也不是有效数字),抛出一个错误,提示 `val` 的值不符合要求,并展示 `val` 的具体内容(通过 `JSON.stringify` 转换为字符串形式)
throw new Error(
'val is not a non-empty string or a valid number. val=' +
'val is not a non-empty string or a valid number. val=' +
JSON.stringify(val)
);
};
/**
* Parse the given `str` and return milliseconds.
* 此函数用于解析给定的字符串 `str`尝试从字符串中提取时间相关的数值和单位信息并将其转换为对应的毫秒数返回
* 如果字符串格式不符合要求或者无法正确解析则返回 `undefined`
*
* @param {String} str
* @return {Number}
* @param {String} str 要解析的字符串期望包含时间数值和对应的时间单位表示 "1h" 表示 1 小时
* @return {Number} 返回解析后的毫秒数如果解析失败则返回 `undefined`
* @api private
*/
function parse(str) {
// 将传入的 `str` 参数强制转换为字符串类型,确保后续字符串操作的一致性
str = String(str);
// 如果字符串长度大于 100可能认为是不合理的输入直接返回不进行后续解析操作这里 100 只是一个人为设定的长度限制阈值)
if (str.length > 100) {
return;
}
// 使用正则表达式来匹配字符串中的时间数值和单位部分,尝试提取相关信息。
// 正则表达式的含义如下:
// ^ 表示匹配字符串的开头
// (?:\d+)?\.?\d+ 表示匹配可选的整数部分(可能没有)、可选的小数点以及必须的小数部分,用于提取时间数值
// * 表示前面的数值部分和后面的单位部分之间可以有零个或多个空格
// (milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)? 表示匹配可选的时间单位部分,支持多种不同的时间单位缩写形式(如 "ms"、"s"、"m"、"h"、"d"、"y" 等),并且单位部分是不区分大小写的(通过 /i 修饰符指定)
// $ 表示匹配字符串的结尾
var match = /^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec(
str
str
);
if (!match) {
return;
}
// 提取匹配到的时间数值部分,并通过 `parseFloat` 转换为浮点数类型,存储在变量 `n` 中
var n = parseFloat(match[1]);
// 提取匹配到的时间单位部分,如果没有匹配到则默认使用 "ms"(毫秒),并将其转换为小写形式,存储在变量 `type` 中
var type = (match[2] || 'ms').toLowerCase();
// 根据提取到的时间单位 `type`,通过 `switch` 语句进行不同情况的处理,将对应的时间数值转换为毫秒数并返回
switch (type) {
case 'years':
case 'year':
@ -99,54 +123,69 @@ function parse(str) {
/**
* Short format for `ms`.
* 此函数用于将给定的毫秒数 `ms` 转换为简短格式的时间表示字符串根据毫秒数的大小选择合适的时间单位进行缩写显示
*
* @param {Number} ms
* @return {String}
* @param {Number} ms 要格式化的毫秒数
* @return {String} 返回简短格式的时间表示字符串 "1h""30m""10s" 等形式
* @api private
*/
function fmtShort(ms) {
// 如果毫秒数大于等于 1 天对应的毫秒数(`d`),则将其除以 `d` 并取整,然后加上时间单位 "d"(天)返回,表示以天为单位的时间格式
if (ms >= d) {
return Math.round(ms / d) + 'd';
}
// 如果毫秒数大于等于 1 小时对应的毫秒数(`h`),则将其除以 `h` 并取整,然后加上时间单位 "h"(小时)返回,表示以小时为单位的时间格式
if (ms >= h) {
return Math.round(ms / h) + 'h';
}
// 如果毫秒数大于等于 1 分钟对应的毫秒数(`m`),则将其除以 `m` 并取整,然后加上时间单位 "m"(分钟)返回,表示以分钟为单位的时间格式
if (ms >= m) {
return Math.round(ms / m) + 'm';
}
// 如果毫秒数大于等于 1 秒对应的毫秒数(`s`),则将其除以 `s` 并取整,然后加上时间单位 "s"(秒)返回,表示以秒为单位的时间格式
if (ms >= s) {
return Math.round(ms / s) + 's';
}
// 如果毫秒数小于 1 秒对应的毫秒数,直接返回原始的毫秒数加上时间单位 "ms"(毫秒),表示以毫秒为单位的时间格式
return ms + 'ms';
}
/**
* Long format for `ms`.
* 此函数用于将给定的毫秒数 `ms` 转换为详细格式的时间表示字符串会根据不同的时间范围使用更详细的表述方式包含复数形式等进行格式化
*
* @param {Number} ms
* @return {String}
* @param {Number} ms 要格式化的毫秒数
* @return {String} 返回详细格式的时间表示字符串 "1 day""2 hours" 等形式更符合自然语言的表述习惯
* @api private
*/
function fmtLong(ms) {
return plural(ms, d, 'day') ||
plural(ms, h, 'hour') ||
plural(ms, m, 'minute') ||
plural(ms, s, 'second') ||
ms + ' ms';
return (
// 调用 `plural` 函数(内部私有函数)尝试按照以天为单位进行格式化,如果满足条件则返回相应的格式化字符串,否则继续后续的格式化判断
plural(ms, d, 'day') ||
// 调用 `plural` 函数尝试按照以小时为单位进行格式化,如果满足条件则返回相应的格式化字符串,否则继续后续的格式化判断
plural(ms, h, 'hour') ||
// 调用 `plural` 函数尝试按照以分钟为单位进行格式化,如果满足条件则返回相应的格式化字符串,否则继续后续的格式化判断
plural(ms, h, 'minute') ||
// 调用 `plural` 函数尝试按照以秒为单位进行格式化,如果满足条件则返回相应的格式化字符串,否则直接返回原始的毫秒数加上 " ms"(注意这里有空格)作为最后的格式化结果
plural(ms, s, 'second') ||
ms +'ms'
);
}
/**
* Pluralization helper.
* 此函数是一个辅助函数用于根据给定的毫秒数 `ms`时间单位对应的毫秒数 `n` `d``h``m``s` 以及时间单位名称 `name`
* 来判断是否需要使用复数形式进行格式化并返回相应的格式化字符串
* 如果毫秒数小于对应的时间单位毫秒数 `n`则直接返回 `undefined`表示不满足格式化条件
*/
function plural(ms, n, name) {
if (ms < n) {
return;
}
// 如果毫秒数小于对应时间单位毫秒数的 1.5 倍,使用 `Math.floor` 向下取整,并按照单数形式(不带 "s")进行格式化,返回如 "1 day" 的格式字符串
if (ms < n * 1.5) {
return Math.floor(ms / n) + ' ' + name;
return Math.floor(ms / n) +' '+ name;
}
return Math.ceil(ms / n) + ' ' + name + 's';
}
// 如果毫秒数大于等于对应时间单位毫秒数的 1.5 倍,使用 `Math.ceil` 向上取整,并按照复数形式(带 "s")进行格式化,返回如 "2 days" 的格式字符串
return Math.ceil(ms / n) +' '+ name +'s';
}

154
node_modules/multibase/src/index.js generated vendored

@ -4,101 +4,128 @@
*/
'use strict'
const { Buffer } = require('buffer')
const constants = require('./constants')
exports = module.exports = multibase
exports.encode = encode
exports.decode = decode
exports.isEncoded = isEncoded
exports.names = Object.freeze(Object.keys(constants.names))
exports.codes = Object.freeze(Object.keys(constants.codes))
const errNotSupported = new Error('Unsupported encoding')
// 从Node.js的 'buffer' 模块中解构出 'Buffer' 对象,用于处理二进制数据,例如创建、操作字节缓冲区等
const { Buffer } = require('buffer');
// 引入自定义的 'constants' 模块推测其中包含了与多基数编码Multibase相关的常量定义比如编码名称、编码代码等信息
const constants = require('./constants');
// 将'multibase' 函数以及其他相关函数('encode'、'decode'、'isEncoded')作为模块的导出内容,方便其他模块引入并使用这些功能。
// 同时,将 'names' 和 'codes' 属性也作为导出内容,分别对应从 'constants' 模块中获取的编码名称和编码代码的键名数组,并使用 'Object.freeze' 冻结,防止其被意外修改。
exports = module.exports = multibase;
exports.encode = encode;
exports.decode = decode;
exports.isEncoded = isEncoded;
exports.names = Object.freeze(Object.keys(constants.names));
exports.codes = Object.freeze(Object.keys(constants.codes));
// 创建一个表示不支持的编码错误的 'Error' 实例,用于在遇到不支持的编码情况时抛出相应错误信息
const errNotSupported = new Error('Unsupported encoding');
/**
* Create a new buffer with the multibase varint+code.
* 此函数用于创建一个带有多基数Multibase变长整数varint和编码代码的新缓冲区
* 它接收一个表示多基数名称或编码代码数字的参数以及一个要添加多基数前缀的数据缓冲区返回处理后的缓冲区
*
* @param {string|number} nameOrCode - The multibase name or code number.
* @param {Buffer} buf - The data to be prefixed with multibase.
* @param {string|number} nameOrCode - The multibase name or code number. 可以是多基数编码的名称字符串形式或者编码代码对应的数字用于确定具体使用的编码方式
* @param {Buffer} buf - The data to be prefixed with multibase. 要添加多基数前缀的二进制数据缓冲区
* @memberof Multibase
* @returns {Buffer}
* @returns {Buffer} 返回一个新的缓冲区包含了多基数编码相关的前缀和原始的数据缓冲区内容拼接后的结果
*/
function multibase (nameOrCode, buf) {
// 如果没有传入要添加前缀的数据缓冲区buf 为假值),则抛出一个错误,提示需要一个已编码的缓冲区作为参数
if (!buf) {
throw new Error('requires an encoded buffer')
throw new Error('requires an encoded buffer');
}
const base = getBase(nameOrCode)
const codeBuf = Buffer.from(base.code)
const name = base.name
validEncode(name, buf)
return Buffer.concat([codeBuf, buf])
// 通过 'getBase' 函数(内部函数,用于根据名称或代码获取对应的编码基础信息)获取具体的编码基础对象,包含编码相关的各种属性和方法
const base = getBase(nameOrCode);
// 根据获取到的编码基础对象中的编码代码创建一个缓冲区,用于后续拼接在数据前面作为多基数前缀的一部分
const codeBuf = Buffer.from(base.code);
const name = base.name;
// 调用 'validEncode' 函数(内部函数,用于验证编码是否有效)验证当前编码名称和数据缓冲区是否匹配、能否正确编码,此处主要进行有效性验证但无返回值(返回值为 undefined
validEncode(name, buf);
// 使用 'Buffer.concat' 方法将编码代码缓冲区和原始数据缓冲区拼接在一起,形成最终带有多基数前缀的新缓冲区,并返回该缓冲区
return Buffer.concat([codeBuf, buf]);
}
/**
* Encode data with the specified base and add the multibase prefix.
* 此函数用于使用指定的编码基础对数据进行编码并添加多基数前缀最终返回编码后带有前缀的缓冲区
*
* @param {string|number} nameOrCode - The multibase name or code number.
* @param {Buffer} buf - The data to be encoded.
* @returns {Buffer}
* @param {string|number} nameOrCode - The multibase name or code number. 多基数编码的名称或编码代码对应的数字用于指定具体的编码方式
* @param {Buffer} buf - The data to be encoded. 要进行编码的二进制数据缓冲区
* @returns {Buffer} 返回经过指定编码方式编码并添加多基数前缀后的缓冲区
* @memberof Multibase
*/
function encode (nameOrCode, buf) {
const base = getBase(nameOrCode)
const name = base.name
// 通过 'getBase' 函数获取对应的编码基础对象,包含编码相关的属性和方法等信息
const base = getBase(nameOrCode);
const name = base.name;
return multibase(name, Buffer.from(base.encode(buf)))
// 调用'multibase' 函数,先使用编码基础对象的 'encode' 方法对数据进行编码(将原始数据按照指定编码方式转换),
// 然后将编码后的结果作为数据添加多基数前缀,最终返回处理后的缓冲区
return multibase(name, Buffer.from(base.encode(buf)));
}
/**
* Takes a buffer or string encoded with multibase header, decodes it and
* returns the decoded buffer
* 此函数用于接收一个带有多基数头部header编码的缓冲区或字符串对其进行解码操作并返回解码后的缓冲区
*
* @param {Buffer|string} bufOrString
* @returns {Buffer}
* @param {Buffer|string} bufOrString 可以是已经编码的缓冲区或者对应的字符串形式包含了多基数编码的相关信息
* @returns {Buffer} 返回解码后的二进制数据缓冲区
* @memberof Multibase
*
*/
function decode (bufOrString) {
// 如果传入的参数是缓冲区类型,将其转换为字符串形式,方便后续按字符串逻辑进行处理(比如截取前缀等操作)
if (Buffer.isBuffer(bufOrString)) {
bufOrString = bufOrString.toString()
bufOrString = bufOrString.toString();
}
const code = bufOrString.substring(0, 1)
bufOrString = bufOrString.substring(1, bufOrString.length)
// 截取输入字符串的第一个字符作为编码代码,用于后续确定使用哪种编码方式进行解码
const code = bufOrString.substring(0, 1);
// 截取输入字符串中除去第一个字符(编码代码部分)后的剩余部分,作为要解码的实际数据内容
bufOrString = bufOrString.substring(1, bufOrString.length);
if (typeof bufOrString === 'string') {
bufOrString = Buffer.from(bufOrString)
// 如果剩余的数据内容仍然是字符串类型,将其转换为缓冲区类型,以便后续使用缓冲区相关的解码方法进行操作
if (typeof bufOrString ==='string') {
bufOrString = Buffer.from(bufOrString);
}
const base = getBase(code)
return Buffer.from(base.decode(bufOrString.toString()))
// 通过 'getBase' 函数根据编码代码获取对应的编码基础对象,包含解码相关的方法等信息
const base = getBase(code);
// 调用编码基础对象的 'decode' 方法对数据进行解码操作,将解码后的结果从字符串形式转换为缓冲区形式并返回
return Buffer.from(base.decode(bufOrString.toString()));
}
/**
* Is the given data multibase encoded?
* 此函数用于判断给定的数据缓冲区或字符串形式是否是经过多基数编码的
*
* @param {Buffer|string} bufOrString
* @returns {boolean}
* @param {Buffer|string} bufOrString 要检查的二进制数据缓冲区或者对应的字符串形式的数据
* @returns {boolean} 如果是经过多基数编码的则返回 true否则返回 false
* @memberof Multibase
*/
function isEncoded (bufOrString) {
// 如果传入的参数是缓冲区类型,将其转换为字符串形式,方便后续按字符串逻辑进行处理(比如截取前缀等操作)
if (Buffer.isBuffer(bufOrString)) {
bufOrString = bufOrString.toString()
bufOrString = bufOrString.toString();
}
// Ensure bufOrString is a string
if (Object.prototype.toString.call(bufOrString) !== '[object String]') {
return false
// 确保经过转换后的数据是字符串类型,如果不是(通过 'Object.prototype.toString.call' 判断类型不符合 '[object String]'),则直接返回 false表示不是多基数编码的数据
if (Object.prototype.toString.call(bufOrString)!== '[object String]') {
return false;
}
const code = bufOrString.substring(0, 1)
// 截取输入字符串的第一个字符作为编码代码,用于尝试获取对应的编码基础对象来判断是否合法编码
const code = bufOrString.substring(0, 1);
try {
const base = getBase(code)
return base.name
// 通过 'getBase' 函数根据编码代码获取对应的编码基础对象,如果能成功获取到(说明编码代码合法),则进一步判断其是否有对应的编码名称(即是否是有效的已实现的编码),返回相应的布尔值结果
const base = getBase(code);
return base.name;
} catch (err) {
return false
// 如果在获取编码基础对象过程中出现错误(比如编码代码不被支持等情况),则返回 false表示不是多基数编码的数据
return false;
}
}
@ -107,26 +134,41 @@ function isEncoded (bufOrString) {
* @param {Buffer} buf
* @private
* @returns {undefined}
* 此函数是一个私有函数用于验证给定编码名称对应的编码方式能否对传入的数据缓冲区进行正确的编码操作
* 它通过调用对应的编码基础对象的 'decode' 方法进行验证如果出现问题可能会抛出异常由调用者处理本身无返回值返回 undefined
*/
function validEncode (name, buf) {
const base = getBase(name)
base.decode(buf.toString())
const base = getBase(name);
base.decode(buf.toString());
}
/**
* 此函数用于根据传入的多基数编码名称或编码代码获取对应的编码基础对象
* 如果传入的名称或代码在 'constants' 模块定义的编码名称或编码代码集合中能找到对应项则返回相应的编码基础对象否则抛出不支持的编码错误
* 同时还会检查获取到的编码基础对象是否已经实现通过 'isImplemented' 方法判断如果未实现则抛出相应的错误信息
*
* @param {string|number} nameOrCode 多基数编码的名称或编码代码对应的数字
* @returns {Object} 返回对应的编码基础对象包含编码相关的各种属性如名称编码代码等和方法如编码解码方法等
*/
function getBase (nameOrCode) {
let base
let base;
// 首先检查传入的名称或代码是否在 'constants' 模块定义的编码名称集合中存在对应项,如果存在则获取对应的编码基础对象
if (constants.names[nameOrCode]) {
base = constants.names[nameOrCode]
base = constants.names[nameOrCode];
} else if (constants.codes[nameOrCode]) {
base = constants.codes[nameOrCode]
// 如果在编码名称集合中不存在,再检查是否在编码代码集合中存在对应项,如果存在则获取对应的编码基础对象
base = constants.codes[nameOrCode];
} else {
throw errNotSupported
// 如果在两个集合中都找不到对应项,抛出表示不支持的编码错误(之前定义的 'errNotSupported' 错误对象)
throw errNotSupported;
}
// 检查获取到的编码基础对象是否已经实现(通过 'isImplemented' 方法判断,具体实现逻辑应该在编码基础对象内部定义),
// 如果未实现,则抛出一个新的错误,提示对应的编码基础对象对应的编码还未实现
if (!base.isImplemented()) {
throw new Error('Base ' + nameOrCode + ' is not implemented yet')
throw new Error('Base'+ nameOrCode +'is not implemented yet');
}
return base
}
return base;
}
Loading…
Cancel
Save