@fast-china/utils 2.1.9 → 2.1.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +29 -0
- package/README.md +5 -2
- package/README.zh.md +5 -2
- package/dist/array/index.mjs +21 -21
- package/dist/array/index.mjs.map +1 -1
- package/dist/async/index.mjs +32 -32
- package/dist/async/index.mjs.map +1 -1
- package/dist/base64/index.mjs +44 -51
- package/dist/base64/index.mjs.map +1 -1
- package/dist/color/index.mjs +33 -33
- package/dist/color/index.mjs.map +1 -1
- package/dist/crypto/index.mjs +153 -155
- package/dist/crypto/index.mjs.map +1 -1
- package/dist/date/index.mjs +79 -46
- package/dist/date/index.mjs.map +1 -1
- package/dist/dom/style.mjs +7 -7
- package/dist/dom/style.mjs.map +1 -1
- package/dist/env/index.mjs +9 -14
- package/dist/env/index.mjs.map +1 -1
- package/dist/function/index.mjs +4 -4
- package/dist/function/index.mjs.map +1 -1
- package/dist/identity/index.mjs +7 -7
- package/dist/identity/index.mjs.map +1 -1
- package/dist/index.d.mts +393 -366
- package/dist/index.global.min.js +2 -2
- package/dist/index.global.min.js.map +1 -1
- package/dist/index.mjs +2 -1
- package/dist/internal/text.mjs +70 -26
- package/dist/internal/text.mjs.map +1 -1
- package/dist/logger/index.mjs +12 -13
- package/dist/logger/index.mjs.map +1 -1
- package/dist/number/index.mjs +63 -42
- package/dist/number/index.mjs.map +1 -1
- package/dist/object/index.mjs +32 -31
- package/dist/object/index.mjs.map +1 -1
- package/dist/storage/index.mjs +58 -63
- package/dist/storage/index.mjs.map +1 -1
- package/dist/string/index.mjs +60 -64
- package/dist/string/index.mjs.map +1 -1
- package/dist/vue/breakpoints.mjs +14 -10
- package/dist/vue/breakpoints.mjs.map +1 -1
- package/dist/vue/element-size.mjs +4 -4
- package/dist/vue/element-size.mjs.map +1 -1
- package/dist/vue/emits.mjs +7 -7
- package/dist/vue/emits.mjs.map +1 -1
- package/dist/vue/event-listener.mjs +5 -5
- package/dist/vue/event-listener.mjs.map +1 -1
- package/dist/vue/expose.mjs +3 -3
- package/dist/vue/expose.mjs.map +1 -1
- package/dist/vue/func.mjs +2 -2
- package/dist/vue/func.mjs.map +1 -1
- package/dist/vue/index.mjs +2 -1
- package/dist/vue/install.mjs +24 -24
- package/dist/vue/install.mjs.map +1 -1
- package/dist/vue/now.mjs +4 -5
- package/dist/vue/now.mjs.map +1 -1
- package/dist/vue/props.mjs +5 -5
- package/dist/vue/props.mjs.map +1 -1
- package/dist/vue/render.mjs +2 -2
- package/dist/vue/render.mjs.map +1 -1
- package/dist/vue/resize-observer.mjs +4 -6
- package/dist/vue/resize-observer.mjs.map +1 -1
- package/dist/vue/slots.mjs.map +1 -1
- package/dist/vue/transition.mjs +58 -0
- package/dist/vue/transition.mjs.map +1 -0
- package/dist/vue/window-size.mjs +2 -4
- package/dist/vue/window-size.mjs.map +1 -1
- package/dist/vue/with.mjs +1 -1
- package/dist/vue/with.mjs.map +1 -1
- package/package.json +2 -1
- package/dist/internal/runtime.mjs +0 -32
- package/dist/internal/runtime.mjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/number/index.ts"],"sourcesContent":["import { runtimeGlobals } from \"../internal/runtime\";\n\nconst byteUnits = [\"B\", \"kB\", \"MB\", \"GB\", \"TB\", \"PB\", \"EB\", \"ZB\", \"YB\"];\nconst binaryByteUnits = [\"B\", \"KiB\", \"MiB\", \"GiB\", \"TiB\", \"PiB\", \"EiB\", \"ZiB\", \"YiB\"];\n\n/** {@link formatBytes} 的格式化选项。 */\nexport interface FormatBytesOptions {\n\t/** 计量基数。`1000` 生成 SI 单位,`1024` 生成 IEC 单位;默认 `1024`。 */\n\tbase?: 1000 | 1024;\n\t/** 小数位数,范围 0 至 20;默认 `2`。 */\n\tdecimals?: number;\n\t/** `Intl.NumberFormat` 使用的语言;默认固定为 `en-US` 以保证输出稳定。 */\n\tlocale?: string | readonly string[];\n}\n\n/**\n * 拒绝 NaN,同时允许具体 API 自行决定是否接受 Infinity。\n *\n * @param value - 待校验数值。\n * @param name - 用于错误消息的参数名称。\n * @throws `RangeError` 当值为 NaN。\n */\nconst assertNotNaN = (value: number, name: string): void => {\n\tif (Number.isNaN(value)) throw new RangeError(`\\`${name}\\` 不能是 NaN。`);\n};\n\n/**\n * 校验有限数值。\n *\n * @param value - 待校验数值。\n * @param name - 用于错误消息的参数名称。\n * @throws `RangeError` 当值为 NaN 或无穷大。\n */\nconst assertFinite = (value: number, name: string): void => {\n\tif (!Number.isFinite(value)) throw new RangeError(`\\`${name}\\` 必须是有限数。`);\n};\n\n/**\n * 使用科学计数法移动十进制位。\n *\n * @remarks 该方式用于 `roundTo`,可减少直接乘除十次幂造成的额外二进制舍入误差。\n * @param value - 原始数值。\n * @param exponent - 十进制移动位数;正数向右移动。\n * @returns 移动后的数值。\n */\nconst shiftDecimal = (value: number, exponent: number): number => {\n\tif (Object.is(value, -0)) return -0;\n\tconst [coefficient = \"0\", currentExponent = \"0\"] = value.toString().split(\"e\");\n\treturn Number(`${coefficient}e${Number(currentExponent) + exponent}`);\n};\n\n/**\n * 把数字限制在闭区间内。\n *\n * @param value - 需要限制的数字。\n * @param minimum - 闭区间下界。\n * @param maximum - 闭区间上界。\n * @returns `minimum <= result <= maximum` 的值。\n * @throws `RangeError` 当参数为 `NaN` 或下界大于上界。\n */\nexport function clamp(value: number, minimum: number, maximum: number): number {\n\tassertNotNaN(value, \"value\");\n\tassertNotNaN(minimum, \"minimum\");\n\tassertNotNaN(maximum, \"maximum\");\n\tif (minimum > maximum) throw new RangeError(\"`minimum` 不能大于 `maximum`。\");\n\treturn Math.min(Math.max(value, minimum), maximum);\n}\n\n/**\n * 判断数字是否位于指定区间。\n *\n * @param value - 待检查数字。\n * @param minimum - 包含的下界。\n * @param maximum - 上界。\n * @param includeMaximum - 是否包含上界;默认使用半开区间 `[minimum, maximum)`。\n * @returns 数字满足区间边界时返回 `true`。\n * @throws `RangeError` 当参数为 `NaN` 或下界大于上界。\n */\nexport function inRange(value: number, minimum: number, maximum: number, includeMaximum = false): boolean {\n\tassertNotNaN(value, \"value\");\n\tassertNotNaN(minimum, \"minimum\");\n\tassertNotNaN(maximum, \"maximum\");\n\tif (minimum > maximum) throw new RangeError(\"`minimum` 不能大于 `maximum`。\");\n\treturn value >= minimum && (includeMaximum ? value <= maximum : value < maximum);\n}\n\n/**\n * 按十进制位数四舍五入。\n *\n * @remarks IEEE-754 浮点数仍可能存在不可表示误差;财务金额应使用十进制定点方案。\n * @param value - 有限数字。\n * @param digits - 小数位数;负数表示十位、百位等,范围 -15 至 15。\n * @returns 按 `Math.round` 语义舍入后的数字。\n * @throws `RangeError` 当值非有限或位数超出范围。\n */\nexport function roundTo(value: number, digits = 0): number {\n\tassertFinite(value, \"value\");\n\tif (!Number.isSafeInteger(digits) || digits < -15 || digits > 15) {\n\t\tthrow new RangeError(\"`digits` 必须是 -15 到 15 之间的安全整数。\");\n\t}\n\tconst shifted = shiftDecimal(value, digits);\n\t// 对已经没有可表示小数的大数,乘以 10^digits 可能溢出;此时舍入不会改变值。\n\tif (!Number.isFinite(shifted)) return value;\n\treturn shiftDecimal(Math.round(shifted), -digits);\n}\n\n/**\n * 对有限数字求和。\n *\n * @param values - 不会被修改的数字数组。\n * @returns 算术和;空数组返回 `0`。\n * @throws `RangeError` 当任一值非有限或累计结果溢出。\n */\nexport function sum(values: readonly number[]): number {\n\tlet total = 0;\n\tlet compensation = 0;\n\tvalues.forEach((value) => {\n\t\tassertFinite(value, \"value\");\n\t\t// Kahan 补偿保存上一次浮点加法丢失的低位,减少大量小数累计误差。\n\t\tconst adjusted = value - compensation;\n\t\tconst next = total + adjusted;\n\t\tif (!Number.isFinite(next)) throw new RangeError(\"总和超出有限数范围。\");\n\t\tcompensation = next - total - adjusted;\n\t\ttotal = next;\n\t});\n\treturn total;\n}\n\n/**\n * 计算有限数字的算术平均值。\n *\n * @param values - 不会被修改的数字数组。\n * @returns 空数组或只有稀疏空位的数组返回 `undefined`;空位不参与分母。\n * @throws `RangeError` 当任一值非有限。\n */\nexport function average(values: readonly number[]): number | undefined {\n\tlet count = 0;\n\tlet mean = 0;\n\tvalues.forEach((value) => {\n\t\tassertFinite(value, \"value\");\n\t\tcount += 1;\n\t\t// 加权增量形式避免先求和导致 MAX_VALUE + MAX_VALUE 溢出。\n\t\tmean = mean * ((count - 1) / count) + value / count;\n\t});\n\treturn count === 0 ? undefined : mean;\n}\n\n/**\n * 在两个数字间做线性插值。\n *\n * @remarks `amount` 不限制在 0 至 1;区间外的值会执行线性外推。\n * @param start - `amount = 0` 时的起点。\n * @param end - `amount = 1` 时的终点。\n * @param amount - 插值或外推比例。\n * @returns 线性计算结果。\n * @throws `RangeError` 当任一参数非有限或结果超出有限数字范围。\n */\nexport function lerp(start: number, end: number, amount: number): number {\n\tassertFinite(start, \"start\");\n\tassertFinite(end, \"end\");\n\tassertFinite(amount, \"amount\");\n\tconst result = start * (1 - amount) + end * amount;\n\tif (!Number.isFinite(result)) throw new RangeError(\"插值结果超出有限数范围。\");\n\treturn result;\n}\n\n/**\n * 将非负字节数格式化为 SI 或 IEC 单位。\n *\n * @param bytes - 非负有限字节数。\n * @param options - 基数、小数位和语言选项。\n * @returns 例如 `1.5 KiB`。\n * @throws `RangeError` 当字节数为负或非有限、基数不是 1000/1024、小数位非法,或 Locale 无效。\n */\nexport function formatBytes(bytes: number, options: FormatBytesOptions = {}): string {\n\tassertFinite(bytes, \"bytes\");\n\tif (bytes < 0) throw new RangeError(\"`bytes` 不能为负数。\");\n\tconst requestedBase: unknown = options.base ?? 1024;\n\tif (requestedBase !== 1000 && requestedBase !== 1024) throw new RangeError(\"`base` 必须是 1000 或 1024。\");\n\tconst base = requestedBase;\n\tconst decimals = options.decimals ?? 2;\n\tif (!Number.isSafeInteger(decimals) || decimals < 0 || decimals > 20) {\n\t\tthrow new RangeError(\"`decimals` 必须是 0 到 20 之间的安全整数。\");\n\t}\n\tif (bytes === 0) return \"0 B\";\n\n\tconst units = base === 1024 ? binaryByteUnits : byteUnits;\n\t// 小于 1 的合法字节数仍使用 B,不能产生负下标并回退到最大单位。\n\tconst exponent = Math.max(0, Math.min(Math.floor(Math.log(bytes) / Math.log(base)), units.length - 1));\n\tconst value = bytes / base ** exponent;\n\tconst formatted = new Intl.NumberFormat(options.locale ?? \"en-US\", {\n\t\tmaximumFractionDigits: decimals,\n\t\tminimumFractionDigits: 0,\n\t\tuseGrouping: false,\n\t}).format(value);\n\treturn `${formatted} ${units[exponent] ?? units.at(-1)}`;\n}\n\n/**\n * 在半开区间内生成随机整数。\n *\n * @remarks 优先使用 Web Crypto;平台缺少安全随机能力时回退到 `Math.random()`。\n * @param minimum - 包含的安全整数下界。\n * @param maximumExclusive - 不包含的安全整数上界;区间宽度最大为 2^32。\n * @returns 位于 `[minimum, maximumExclusive)` 的随机整数。\n * @throws 参数非法时抛出 `RangeError`。\n */\nexport function randomInt(minimum: number, maximumExclusive: number): number {\n\tif (!Number.isSafeInteger(minimum) || !Number.isSafeInteger(maximumExclusive)) {\n\t\tthrow new RangeError(\"`minimum` 和 `maximumExclusive` 必须是安全整数。\");\n\t}\n\tconst range = maximumExclusive - minimum;\n\tconst uint32Range = 0x1_0000_0000;\n\tif (range <= 0 || range > uint32Range) {\n\t\tthrow new RangeError(\"区间不能为空且宽度不能超过 2^32。\");\n\t}\n\tconst crypto = runtimeGlobals.crypto;\n\tconst getRandomValues = crypto?.getRandomValues?.bind(crypto);\n\n\t// 只接受可以被区间宽度整除的最大 2^32 前缀,消除取模偏差。\n\tconst limit = Math.floor(uint32Range / range) * range;\n\tconst values = new Uint32Array(1);\n\tlet sample: number;\n\tdo {\n\t\tif (getRandomValues !== undefined) getRandomValues(values);\n\t\telse values[0] = Math.floor(Math.random() * uint32Range);\n\t\tsample = values[0] ?? uint32Range;\n\t} while (sample >= limit);\n\treturn minimum + (sample % range);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/number/index.ts"],"sourcesContent":["const byteUnits = [\"B\", \"kB\", \"MB\", \"GB\", \"TB\", \"PB\", \"EB\", \"ZB\", \"YB\"];\nconst binaryByteUnits = [\"B\", \"KiB\", \"MiB\", \"GiB\", \"TiB\", \"PiB\", \"EiB\", \"ZiB\", \"YiB\"];\n\n/** {@link formatBytes} 的格式化选项 */\nexport interface FormatBytesOptions {\n\t/** 计量基数。`1000` 生成 SI 单位,`1024` 生成 IEC 单位;默认 `1024`。 */\n\tbase?: 1000 | 1024;\n\t/** 小数位数,范围 0 至 20;默认 `2` */\n\tdecimals?: number;\n\t/** 显式语言交给 Intl.NumberFormat;省略时内部按 en-US 数字格式输出。 */\n\tlocale?: string | readonly string[];\n}\n\n/**\n * 拒绝 NaN,同时允许具体 API 自行决定是否接受 Infinity。\n *\n * @param value - 待校验数值\n * @param name - 用于错误消息的参数名称\n * @throws `RangeError` 当值为 NaN。\n */\nconst assertNotNaN = (value: number, name: string): void => {\n\tif (Number.isNaN(value)) throw new RangeError(`\\`${name}\\` must not be NaN.`);\n};\n\n/**\n * 校验有限数值。\n *\n * @param value - 待校验数值\n * @param name - 用于错误消息的参数名称\n * @throws `RangeError` 当值为 NaN 或无穷大。\n */\nconst assertFinite = (value: number, name: string): void => {\n\tif (!Number.isFinite(value)) throw new RangeError(`\\`${name}\\` must be a finite number.`);\n};\n\n/**\n * 使用科学计数法移动十进制位。\n *\n * @remarks 该方式用于 `roundTo`,可减少直接乘除十次幂造成的额外二进制舍入误差。\n * @param value - 原始数值\n * @param exponent - 十进制移动位数;正数向右移动。\n * @returns 移动后的数值\n */\nconst shiftDecimal = (value: number, exponent: number): number => {\n\tif (Object.is(value, -0)) return -0;\n\tconst [coefficient = \"0\", currentExponent = \"0\"] = value.toString().split(\"e\");\n\treturn Number(`${coefficient}e${Number(currentExponent) + exponent}`);\n};\n\n/**\n * 把数字限制在闭区间内。\n *\n * @param value - 需要限制的数字\n * @param minimum - 闭区间下界\n * @param maximum - 闭区间上界\n * @returns `minimum <= result <= maximum` 的值。\n * @throws `RangeError` 当参数为 `NaN` 或下界大于上界。\n */\nexport function clamp(value: number, minimum: number, maximum: number): number {\n\tassertNotNaN(value, \"value\");\n\tassertNotNaN(minimum, \"minimum\");\n\tassertNotNaN(maximum, \"maximum\");\n\tif (minimum > maximum) throw new RangeError(\"`minimum` must not exceed `maximum`.\");\n\treturn Math.min(Math.max(value, minimum), maximum);\n}\n\n/**\n * 判断数字是否位于指定区间。\n *\n * @param value - 待检查数字\n * @param minimum - 包含的下界\n * @param maximum - 上界\n * @param includeMaximum - 是否包含上界;默认使用半开区间 `[minimum, maximum)`。\n * @returns 数字满足区间边界时返回 `true`。\n * @throws `RangeError` 当参数为 `NaN` 或下界大于上界。\n */\nexport function inRange(value: number, minimum: number, maximum: number, includeMaximum = false): boolean {\n\tassertNotNaN(value, \"value\");\n\tassertNotNaN(minimum, \"minimum\");\n\tassertNotNaN(maximum, \"maximum\");\n\tif (minimum > maximum) throw new RangeError(\"`minimum` must not exceed `maximum`.\");\n\treturn value >= minimum && (includeMaximum ? value <= maximum : value < maximum);\n}\n\n/**\n * 按十进制位数四舍五入。\n *\n * @remarks IEEE-754 浮点数仍可能存在不可表示误差;财务金额应使用十进制定点方案。\n * @param value - 有限数字\n * @param digits - 小数位数;负数表示十位、百位等,范围 -15 至 15。\n * @returns 按 `Math.round` 语义舍入后的数字\n * @throws `RangeError` 当值非有限或位数超出范围。\n */\nexport function roundTo(value: number, digits = 0): number {\n\tassertFinite(value, \"value\");\n\tif (!Number.isSafeInteger(digits) || digits < -15 || digits > 15) {\n\t\tthrow new RangeError(\"`digits` must be a safe integer between -15 and 15.\");\n\t}\n\tconst shifted = shiftDecimal(value, digits);\n\t// 对已经没有可表示小数的大数,乘以 10^digits 可能溢出;此时舍入不会改变值。\n\tif (!Number.isFinite(shifted)) return value;\n\treturn shiftDecimal(Math.round(shifted), -digits);\n}\n\n/**\n * 对有限数字求和。\n *\n * @param values - 不会被修改的数字数组\n * @returns 算术和;空数组返回 `0`。\n * @throws `RangeError` 当任一值非有限或累计结果溢出。\n */\nexport function sum(values: readonly number[]): number {\n\tlet total = 0;\n\tlet compensation = 0;\n\tvalues.forEach((value) => {\n\t\tassertFinite(value, \"value\");\n\t\t// Kahan 补偿保存上一次浮点加法丢失的低位,减少大量小数累计误差。\n\t\tconst adjusted = value - compensation;\n\t\tconst next = total + adjusted;\n\t\tif (!Number.isFinite(next)) throw new RangeError(\"The sum exceeds the finite number range.\");\n\t\tcompensation = next - total - adjusted;\n\t\ttotal = next;\n\t});\n\treturn total;\n}\n\n/**\n * 计算有限数字的算术平均值。\n *\n * @param values - 不会被修改的数字数组\n * @returns 空数组或只有稀疏空位的数组返回 `undefined`;空位不参与分母。\n * @throws `RangeError` 当任一值非有限。\n */\nexport function average(values: readonly number[]): number | undefined {\n\tlet count = 0;\n\tlet mean = 0;\n\tvalues.forEach((value) => {\n\t\tassertFinite(value, \"value\");\n\t\tcount += 1;\n\t\t// 加权增量形式避免先求和导致 MAX_VALUE + MAX_VALUE 溢出。\n\t\tmean = mean * ((count - 1) / count) + value / count;\n\t});\n\treturn count === 0 ? undefined : mean;\n}\n\n/**\n * 在两个数字间做线性插值。\n *\n * @remarks `amount` 不限制在 0 至 1;区间外的值会执行线性外推。\n * @param start - `amount = 0` 时的起点\n * @param end - `amount = 1` 时的终点\n * @param amount - 插值或外推比例\n * @returns 线性计算结果\n * @throws `RangeError` 当任一参数非有限或结果超出有限数字范围。\n */\nexport function lerp(start: number, end: number, amount: number): number {\n\tassertFinite(start, \"start\");\n\tassertFinite(end, \"end\");\n\tassertFinite(amount, \"amount\");\n\tconst result = start * (1 - amount) + end * amount;\n\tif (!Number.isFinite(result)) throw new RangeError(\"The interpolated result exceeds the finite number range.\");\n\treturn result;\n}\n\n/** 按十进制表示四舍五入,避免 toFixed 的二进制舍入差异,并展开科学计数法。 */\nconst formatByteAmount = (value: number, decimals: number): string => {\n\tconst [coefficient = \"0\", exponent = \"0\"] = value.toString().split(\"e\");\n\tconst [whole = \"0\", fraction = \"\"] = coefficient.split(\".\");\n\tconst digits = whole + fraction;\n\tconst point = whole.length + Number(exponent);\n\tconst integer = point <= 0 ? \"0\" : digits.slice(0, point).padEnd(point, \"0\");\n\tconst fractional = point < 0 ? \"0\".repeat(-point) + digits : digits.slice(Math.max(0, point));\n\tlet rounded = integer + fractional.slice(0, decimals);\n\tif (Number(fractional[decimals] ?? \"0\") >= 5) {\n\t\tlet index = rounded.length - 1;\n\t\twhile (index >= 0 && rounded[index] === \"9\") index -= 1;\n\t\trounded =\n\t\t\tindex < 0\n\t\t\t\t? `1${\"0\".repeat(rounded.length)}`\n\t\t\t\t: rounded.slice(0, index) + String(Number(rounded[index]) + 1) + \"0\".repeat(rounded.length - index - 1);\n\t}\n\tconst keptDecimals = Math.min(decimals, fractional.length);\n\tif (keptDecimals === 0) return rounded;\n\tconst end = rounded.length - keptDecimals;\n\tconst tail = rounded.slice(end).replace(/0+$/u, \"\");\n\treturn tail === \"\" ? rounded.slice(0, end) : `${rounded.slice(0, end)}.${tail}`;\n};\n\n/**\n * 将非负字节数格式化为 SI 或 IEC 单位。\n *\n * @param bytes - 非负有限字节数\n * @param options - 基数、小数位和语言选项\n * @returns 例如 `1.5 KiB`\n * @remarks 默认数字格式使用内部实现;显式指定语言时使用 Intl.NumberFormat。\n * @throws `Error` 当显式指定语言且环境不支持 `Intl.NumberFormat`。\n * @throws `RangeError` 当字节数为负或非有限、基数不是 1000/1024、小数位非法,或 Locale 无效。\n */\nexport function formatBytes(bytes: number, options: FormatBytesOptions = {}): string {\n\tassertFinite(bytes, \"bytes\");\n\tif (bytes < 0) throw new RangeError(\"`bytes` must not be negative.\");\n\tconst requestedBase: unknown = options.base ?? 1024;\n\tif (requestedBase !== 1000 && requestedBase !== 1024) throw new RangeError(\"`base` must be 1000 or 1024.\");\n\tconst base = requestedBase;\n\tconst decimals = options.decimals ?? 2;\n\tif (!Number.isSafeInteger(decimals) || decimals < 0 || decimals > 20) {\n\t\tthrow new RangeError(\"`decimals` must be a safe integer between 0 and 20.\");\n\t}\n\tif (bytes === 0) return \"0 B\";\n\n\tconst units = base === 1024 ? binaryByteUnits : byteUnits;\n\t// 小于 1 的合法字节数仍使用 B,不能产生负下标并回退到最大单位。\n\tconst exponent = Math.max(0, Math.min(Math.floor(Math.log(bytes) / Math.log(base)), units.length - 1));\n\tconst value = bytes / base ** exponent;\n\tif (options.locale === undefined) return `${formatByteAmount(value, decimals)} ${units[exponent]}`;\n\tif (typeof Intl === \"undefined\" || typeof Intl.NumberFormat !== \"function\") {\n\t\tthrow new Error(\"The current runtime does not support Intl.NumberFormat.\");\n\t}\n\tconst formatted = new Intl.NumberFormat(options.locale ?? \"en-US\", {\n\t\tmaximumFractionDigits: decimals,\n\t\tminimumFractionDigits: 0,\n\t\tuseGrouping: false,\n\t}).format(value);\n\treturn `${formatted} ${units[exponent] ?? units[units.length - 1]}`;\n}\n\n/**\n * 在半开区间内生成随机整数。\n *\n * @remarks 优先使用 Web Crypto;平台缺少安全随机能力时回退到 `Math.random()`。\n * @param minimum - 包含的安全整数下界\n * @param maximumExclusive - 不包含的安全整数上界;区间宽度最大为 2^32。\n * @returns 位于 `[minimum, maximumExclusive)` 的随机整数\n * @throws 参数非法时抛出 `RangeError`。\n */\nexport function randomInt(minimum: number, maximumExclusive: number): number {\n\tif (!Number.isSafeInteger(minimum) || !Number.isSafeInteger(maximumExclusive)) {\n\t\tthrow new RangeError(\"`minimum` and `maximumExclusive` must be safe integers.\");\n\t}\n\tconst range = maximumExclusive - minimum;\n\tconst uint32Range = 0x1_0000_0000;\n\tif (range <= 0 || range > uint32Range) {\n\t\tthrow new RangeError(\"The interval must not be empty and its width must not exceed 2^32.\");\n\t}\n\n\t// 只接受可以被区间宽度整除的最大 2^32 前缀,消除取模偏差。\n\tconst limit = Math.floor(uint32Range / range) * range;\n\tconst values = new Uint32Array(1);\n\tlet sample: number;\n\tdo {\n\t\tif (typeof crypto !== \"undefined\" && typeof crypto?.getRandomValues === \"function\") crypto.getRandomValues(values);\n\t\telse values[0] = Math.floor(Math.random() * uint32Range);\n\t\tsample = values[0] ?? uint32Range;\n\t} while (sample >= limit);\n\treturn minimum + (sample % range);\n}\n"],"mappings":"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"}
|
package/dist/object/index.mjs
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* 判断 Query Value 是否为重复参数数组。
|
|
4
4
|
*
|
|
5
|
-
* @param value - 单值或数组形式的 Query Value
|
|
5
|
+
* @param value - 单值或数组形式的 Query Value
|
|
6
6
|
* @returns 是只读原始值数组时返回 `true`。
|
|
7
7
|
*/
|
|
8
8
|
const isQueryPrimitiveArray = (value) => Array.isArray(value);
|
|
@@ -10,9 +10,9 @@ const isQueryPrimitiveArray = (value) => Array.isArray(value);
|
|
|
10
10
|
* 安全写入结果对象的自有可枚举属性。
|
|
11
11
|
*
|
|
12
12
|
* @remarks 使用 `defineProperty` 避免 `__proto__` 触发 Setter,并统一创建可写、可配置的自有可枚举数据属性。
|
|
13
|
-
* @param target -
|
|
14
|
-
* @param key -
|
|
15
|
-
* @param value -
|
|
13
|
+
* @param target - 要写入的结果对象
|
|
14
|
+
* @param key - 自有属性键
|
|
15
|
+
* @param value - 属性值
|
|
16
16
|
*/
|
|
17
17
|
const defineEnumerableProperty = (target, key, value) => {
|
|
18
18
|
Object.defineProperty(target, key, {
|
|
@@ -198,7 +198,7 @@ const equalObjects = (left, right, state) => {
|
|
|
198
198
|
const leftKeys = getEnumerableOwnKeys(left);
|
|
199
199
|
const rightKeys = getEnumerableOwnKeys(right);
|
|
200
200
|
if (leftKeys.length !== rightKeys.length) return false;
|
|
201
|
-
for (const key of leftKeys) if (!Object.
|
|
201
|
+
for (const key of leftKeys) if (!Object.prototype.hasOwnProperty.call(right, key)) return false;
|
|
202
202
|
return compareTrackedPair(left, right, state, () => {
|
|
203
203
|
let compareConstructors = true;
|
|
204
204
|
for (const key of leftKeys) {
|
|
@@ -246,7 +246,7 @@ function isEqualValue(left, right, state) {
|
|
|
246
246
|
/**
|
|
247
247
|
* 判断值是否是普通对象。
|
|
248
248
|
*
|
|
249
|
-
* @param value -
|
|
249
|
+
* @param value - 任意待检查值
|
|
250
250
|
* @returns 原型为 `Object.prototype` 或 `null` 时返回 `true`。
|
|
251
251
|
*/
|
|
252
252
|
function isPlainObject(value) {
|
|
@@ -258,19 +258,19 @@ function isPlainObject(value) {
|
|
|
258
258
|
* 安全判断对象是否拥有自己的属性。
|
|
259
259
|
*
|
|
260
260
|
* @remarks 不调用可能被对象覆盖的 `hasOwnProperty`。
|
|
261
|
-
* @param value -
|
|
262
|
-
* @param key - 字符串、数字或 Symbol
|
|
261
|
+
* @param value - 待检查对象
|
|
262
|
+
* @param key - 字符串、数字或 Symbol 属性键
|
|
263
263
|
* @returns 属性为对象自有属性时返回 `true`,并收窄键类型。
|
|
264
264
|
*/
|
|
265
265
|
function hasOwn(value, key) {
|
|
266
|
-
return Object.
|
|
266
|
+
return Object.prototype.hasOwnProperty.call(value, key);
|
|
267
267
|
}
|
|
268
268
|
/**
|
|
269
269
|
* 递归创建值的深层副本。
|
|
270
270
|
*
|
|
271
271
|
* @remarks 支持循环引用、共享引用、Symbol 键、对象原型、ArrayBuffer、DataView、Date、Map、RegExp、Set 和 TypedArray。
|
|
272
272
|
* Map 的键保持原引用,函数及其他不可克隆值在嵌套位置保持原引用;只复制自有可枚举属性。
|
|
273
|
-
* @param value -
|
|
273
|
+
* @param value - 需要深复制的任意值
|
|
274
274
|
* @returns 与输入类型一致且不共享可克隆嵌套值的新值;原始类型直接返回自身。
|
|
275
275
|
*/
|
|
276
276
|
function cloneDeep(value) {
|
|
@@ -281,8 +281,8 @@ function cloneDeep(value) {
|
|
|
281
281
|
*
|
|
282
282
|
* @remarks 原始值使用 SameValueZero 语义;支持循环引用、数组、对象、ArrayBuffer、DataView、Date、Error、Map、RegExp、Set、Symbol 和 TypedArray。
|
|
283
283
|
* 对象只比较自有可枚举字符串与 Symbol 属性,函数及其他不支持的宿主对象仅在引用相同时相等。
|
|
284
|
-
* @param left -
|
|
285
|
-
* @param right -
|
|
284
|
+
* @param left - 第一待比较值
|
|
285
|
+
* @param right - 第二待比较值
|
|
286
286
|
* @returns 两个值深度等价时返回 `true`。
|
|
287
287
|
*/
|
|
288
288
|
function isEqual(left, right) {
|
|
@@ -304,9 +304,9 @@ function omit(source, keys) {
|
|
|
304
304
|
/**
|
|
305
305
|
* 按条件排除对象的自有可枚举属性。
|
|
306
306
|
*
|
|
307
|
-
* @param source -
|
|
307
|
+
* @param source - 不会被修改的源对象
|
|
308
308
|
* @param predicate - 接收属性值、键和源对象;返回真值时排除该属性。
|
|
309
|
-
* @returns
|
|
309
|
+
* @returns 由未匹配属性组成的新对象
|
|
310
310
|
*/
|
|
311
311
|
function omitBy(source, predicate) {
|
|
312
312
|
const result = {};
|
|
@@ -316,9 +316,9 @@ function omitBy(source, predicate) {
|
|
|
316
316
|
/**
|
|
317
317
|
* 按条件选择对象的自有可枚举属性。
|
|
318
318
|
*
|
|
319
|
-
* @param source -
|
|
319
|
+
* @param source - 不会被修改的源对象
|
|
320
320
|
* @param predicate - 接收属性值、键和源对象;返回真值时保留该属性。
|
|
321
|
-
* @returns
|
|
321
|
+
* @returns 由匹配属性组成的新对象
|
|
322
322
|
*/
|
|
323
323
|
function pickBy(source, predicate) {
|
|
324
324
|
const result = {};
|
|
@@ -328,9 +328,9 @@ function pickBy(source, predicate) {
|
|
|
328
328
|
/**
|
|
329
329
|
* 映射对象的自有可枚举属性值。
|
|
330
330
|
*
|
|
331
|
-
* @param source -
|
|
332
|
-
* @param mapper -
|
|
333
|
-
* @returns
|
|
331
|
+
* @param source - 不会被修改的源对象
|
|
332
|
+
* @param mapper - 接收值、键和源对象的映射函数
|
|
333
|
+
* @returns 保留原键的新对象
|
|
334
334
|
*/
|
|
335
335
|
function mapValues(source, mapper) {
|
|
336
336
|
const result = {};
|
|
@@ -341,8 +341,8 @@ function mapValues(source, mapper) {
|
|
|
341
341
|
* 对自有可枚举属性执行 SameValue 浅比较。
|
|
342
342
|
*
|
|
343
343
|
* @remarks 嵌套对象只比较引用;`NaN` 相等,`0` 与 `-0` 不相等。
|
|
344
|
-
* @param left -
|
|
345
|
-
* @param right -
|
|
344
|
+
* @param left - 第一对象
|
|
345
|
+
* @param right - 第二对象
|
|
346
346
|
* @returns 自有可枚举键集合与对应值均满足 SameValue 时返回 `true`。
|
|
347
347
|
*/
|
|
348
348
|
function shallowEqual(left, right) {
|
|
@@ -350,38 +350,39 @@ function shallowEqual(left, right) {
|
|
|
350
350
|
const leftKeys = Reflect.ownKeys(left).filter((key) => Object.prototype.propertyIsEnumerable.call(left, key));
|
|
351
351
|
const rightKeys = Reflect.ownKeys(right).filter((key) => Object.prototype.propertyIsEnumerable.call(right, key));
|
|
352
352
|
if (leftKeys.length !== rightKeys.length) return false;
|
|
353
|
-
return leftKeys.every((key) => Object.
|
|
353
|
+
return leftKeys.every((key) => Object.prototype.hasOwnProperty.call(right, key) && Object.is(Reflect.get(left, key), Reflect.get(right, key)));
|
|
354
354
|
}
|
|
355
355
|
/**
|
|
356
356
|
* 把 Query 原始值规范化为文本。
|
|
357
357
|
*
|
|
358
|
-
* @param value - 已排除空值的字符串、数字、布尔值或 BigInt
|
|
359
|
-
* @returns 与 URLSearchParams
|
|
358
|
+
* @param value - 已排除空值的字符串、数字、布尔值或 BigInt
|
|
359
|
+
* @returns 与 URLSearchParams 兼容的文本值
|
|
360
360
|
* @throws `RangeError` 当数字不是有限值。
|
|
361
361
|
*/
|
|
362
362
|
const serializeQueryValue = (value) => {
|
|
363
|
-
if (typeof value === "number" && !Number.isFinite(value)) throw new RangeError("
|
|
363
|
+
if (typeof value === "number" && !Number.isFinite(value)) throw new RangeError("Query parameter numbers must be finite.");
|
|
364
364
|
return String(value);
|
|
365
365
|
};
|
|
366
366
|
/**
|
|
367
367
|
* 将对象序列化为标准 URL 查询字符串。
|
|
368
368
|
*
|
|
369
369
|
* @remarks `null` 与 `undefined` 被跳过;数组使用重复键;返回值不会修改输入。
|
|
370
|
-
* @param value -
|
|
371
|
-
* @param options -
|
|
370
|
+
* @param value - 查询参数对象
|
|
371
|
+
* @param options - 排序、空格和问号前缀选项
|
|
372
372
|
* @returns URL 编码后的查询字符串;没有参数时始终返回空字符串。
|
|
373
373
|
* @throws `RangeError` 当参数包含 `NaN` 或无穷数字。
|
|
374
|
+
* @throws `URIError` 当键或值包含孤立的 UTF-16 代理项。
|
|
374
375
|
*/
|
|
375
376
|
function toQueryString(value, options = {}) {
|
|
376
377
|
const entries = Object.entries(value);
|
|
377
378
|
if (options.sort) entries.sort(([left], [right]) => left < right ? -1 : left > right ? 1 : 0);
|
|
378
|
-
const parameters =
|
|
379
|
+
const parameters = [];
|
|
379
380
|
for (const [key, rawValue] of entries) {
|
|
380
381
|
const values = isQueryPrimitiveArray(rawValue) ? rawValue : [rawValue];
|
|
381
|
-
for (const item of values) if (item !== null && item !== void 0) parameters.
|
|
382
|
+
for (const item of values) if (item !== null && item !== void 0) parameters.push(`${encodeURIComponent(key)}=${encodeURIComponent(serializeQueryValue(item))}`);
|
|
382
383
|
}
|
|
383
|
-
let result = parameters.toString();
|
|
384
|
-
if (options.space
|
|
384
|
+
let result = parameters.join("&").replace(/[!'()~]/gu, (character) => `%${character.charCodeAt(0).toString(16).toUpperCase()}`);
|
|
385
|
+
if (options.space !== "percent") result = result.replace(/%20/gu, "+");
|
|
385
386
|
return result && options.prefixQuestionMark ? `?${result}` : result;
|
|
386
387
|
}
|
|
387
388
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/object/index.ts"],"sourcesContent":["/** URL 查询参数支持的单值类型。 */\nexport type QueryPrimitive = bigint | boolean | number | string | null | undefined;\n\n/** URL 查询参数值;数组使用重复键表示。 */\nexport type QueryValue = QueryPrimitive | readonly QueryPrimitive[];\n\n/**\n * 判断 Query Value 是否为重复参数数组。\n *\n * @param value - 单值或数组形式的 Query Value。\n * @returns 是只读原始值数组时返回 `true`。\n */\nconst isQueryPrimitiveArray = (value: QueryValue): value is readonly QueryPrimitive[] => Array.isArray(value);\n\n/** {@link toQueryString} 的序列化选项。 */\nexport interface QueryStringOptions {\n\t/** 返回非空结果时是否添加 `?`;默认 `false`。 */\n\tprefixQuestionMark?: boolean;\n\t/** 是否按键的 UTF-16 码元顺序稳定排序;默认保留对象枚举顺序。 */\n\tsort?: boolean;\n\t/** 空格编码方式;默认遵循表单编码并输出 `+`。 */\n\tspace?: \"percent\" | \"plus\";\n}\n\n/**\n * 安全写入结果对象的自有可枚举属性。\n *\n * @remarks 使用 `defineProperty` 避免 `__proto__` 触发 Setter,并统一创建可写、可配置的自有可枚举数据属性。\n * @param target - 要写入的结果对象。\n * @param key - 自有属性键。\n * @param value - 属性值。\n */\nconst defineEnumerableProperty = (target: object, key: PropertyKey, value: unknown): void => {\n\tObject.defineProperty(target, key, { configurable: true, enumerable: true, value, writable: true });\n};\n\nconst typedArrayTags = new Set([\n\t\"[object BigInt64Array]\",\n\t\"[object BigUint64Array]\",\n\t\"[object Float32Array]\",\n\t\"[object Float64Array]\",\n\t\"[object Int8Array]\",\n\t\"[object Int16Array]\",\n\t\"[object Int32Array]\",\n\t\"[object Uint8Array]\",\n\t\"[object Uint8ClampedArray]\",\n\t\"[object Uint16Array]\",\n\t\"[object Uint32Array]\",\n]);\n\n/** 使用源值的构造器创建同类空实例。 */\nconst createUsingConstructor = (value: object, arguments_: readonly unknown[]): object => {\n\tconst constructor: unknown = Reflect.get(value, \"constructor\");\n\treturn typeof constructor === \"function\" ? (Reflect.construct(constructor, arguments_) as object) : {};\n};\n\n/** 复制 ArrayBufferLike 的当前字节,不与源值共享底层内存。 */\nconst cloneArrayBuffer = (value: ArrayBufferLike): ArrayBufferLike => {\n\tconst result = createUsingConstructor(value, [value.byteLength]) as ArrayBufferLike;\n\tnew Uint8Array(result).set(new Uint8Array(value));\n\treturn result;\n};\n\n/** 递归复制值,并记录已复制对象以还原循环引用和共享引用。 */\nconst cloneDeepValue = (value: unknown, clones: WeakMap<object, object>, isRoot: boolean): unknown => {\n\tif ((typeof value !== \"object\" && typeof value !== \"function\") || value === null) return value;\n\n\tconst source = value;\n\tconst existing = clones.get(source);\n\tif (existing !== undefined) return existing;\n\tif (typeof source === \"function\" && !isRoot) return source;\n\n\tconst tag = Object.prototype.toString.call(source);\n\tlet result: object;\n\tlet pendingBuffer: { source: ArrayBufferLike; result: ArrayBufferLike } | undefined;\n\t// 先登记底层缓冲区,视图登记后再复制其附加属性,避免缓冲区与视图相互引用时重复构造。\n\tconst getBufferClone = (buffer: ArrayBufferLike): ArrayBufferLike => {\n\t\tconst existingBuffer = clones.get(buffer);\n\t\tif (existingBuffer !== undefined) return existingBuffer as ArrayBufferLike;\n\t\tconst clonedBuffer = cloneArrayBuffer(buffer);\n\t\tclones.set(buffer, clonedBuffer);\n\t\tpendingBuffer = { source: buffer, result: clonedBuffer };\n\t\treturn clonedBuffer;\n\t};\n\tif (Array.isArray(source)) {\n\t\t// 只复制实际存在的自有可枚举键,保留空洞、附加字符串属性和 Symbol 属性。\n\t\tresult = createUsingConstructor(source, [source.length]);\n\t} else if (typeof source === \"function\") {\n\t\tresult = {};\n\t} else {\n\t\tswitch (tag) {\n\t\t\tcase \"[object Arguments]\":\n\t\t\t\tresult = {};\n\t\t\t\tbreak;\n\t\t\tcase \"[object ArrayBuffer]\":\n\t\t\tcase \"[object SharedArrayBuffer]\":\n\t\t\t\tresult = cloneArrayBuffer(source as ArrayBufferLike);\n\t\t\t\tbreak;\n\t\t\tcase \"[object Boolean]\":\n\t\t\t\tresult = createUsingConstructor(source, [(source as { valueOf: () => boolean }).valueOf()]);\n\t\t\t\tbreak;\n\t\t\tcase \"[object DataView]\": {\n\t\t\t\tconst view = source as DataView;\n\t\t\t\tresult = createUsingConstructor(source, [getBufferClone(view.buffer), view.byteOffset, view.byteLength]);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"[object Date]\":\n\t\t\t\tresult = createUsingConstructor(source, [(source as Date).getTime()]);\n\t\t\t\tbreak;\n\t\t\tcase \"[object Map]\":\n\t\t\tcase \"[object Set]\":\n\t\t\t\tresult = createUsingConstructor(source, []);\n\t\t\t\tbreak;\n\t\t\tcase \"[object Number]\":\n\t\t\t\tresult = createUsingConstructor(source, [(source as { valueOf: () => number }).valueOf()]);\n\t\t\t\tbreak;\n\t\t\tcase \"[object Object]\": {\n\t\t\t\tconst prototype = Object.getPrototypeOf(source) as object | null;\n\t\t\t\tresult = Object.create(prototype) as object;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"[object RegExp]\": {\n\t\t\t\tconst expression = source as RegExp;\n\t\t\t\tconst clonedExpression = new RegExp(expression.source, expression.flags);\n\t\t\t\tclonedExpression.lastIndex = expression.lastIndex;\n\t\t\t\tresult = clonedExpression;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"[object String]\":\n\t\t\t\tresult = createUsingConstructor(source, [(source as { valueOf: () => string }).valueOf()]);\n\t\t\t\tbreak;\n\t\t\tcase \"[object Symbol]\":\n\t\t\t\tresult = Object((source as { valueOf: () => symbol }).valueOf()) as object;\n\t\t\t\tbreak;\n\t\t\tdefault: {\n\t\t\t\tif (!typedArrayTags.has(tag)) return isRoot ? {} : source;\n\t\t\t\tconst view = source as ArrayBufferView & { readonly length: number };\n\t\t\t\tresult = createUsingConstructor(source, [getBufferClone(view.buffer), view.byteOffset, view.length]);\n\t\t\t}\n\t\t}\n\t}\n\n\tclones.set(source, result);\n\tif (pendingBuffer !== undefined) {\n\t\tcopyCloneProperties(pendingBuffer.source, pendingBuffer.result, clones);\n\t}\n\tif (tag === \"[object Map]\") {\n\t\tfor (const [key, item] of source as Map<unknown, unknown>) {\n\t\t\t(result as Map<unknown, unknown>).set(key, cloneDeepValue(item, clones, false));\n\t\t}\n\t} else if (tag === \"[object Set]\") {\n\t\tfor (const item of source as Set<unknown>) {\n\t\t\t(result as Set<unknown>).add(cloneDeepValue(item, clones, false));\n\t\t}\n\t}\n\n\tcopyCloneProperties(source, result, clones);\n\treturn result;\n};\n\n/** 复制自有可枚举属性,不触发结果原型上的 setter。 */\nfunction copyCloneProperties(source: object, result: object, clones: WeakMap<object, object>): void {\n\tfor (const key of Reflect.ownKeys(source)) {\n\t\tif (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;\n\t\tconst descriptor = Object.getOwnPropertyDescriptor(result, key);\n\t\t// String 包装对象的字符索引由构造器建立,不能重新定义。\n\t\tif (descriptor?.configurable === false && descriptor.writable === false) continue;\n\t\tdefineEnumerableProperty(result, key, cloneDeepValue(Reflect.get(source, key), clones, false));\n\t}\n}\n\n/** 深度比较过程中用于识别循环引用的双向对象映射。 */\ninterface EqualityState {\n\treadonly leftObjects: WeakMap<object, object>;\n\treadonly rightObjects: WeakMap<object, object>;\n}\n\n/** 判断两个值是否满足 SameValueZero 相等。 */\nconst sameValueZero = (left: unknown, right: unknown): boolean =>\n\tleft === right || (typeof left === \"number\" && typeof right === \"number\" && Number.isNaN(left) && Number.isNaN(right));\n\n/** 返回对象的自有可枚举字符串与 Symbol 键。 */\nconst getEnumerableOwnKeys = (value: object): PropertyKey[] =>\n\tReflect.ownKeys(value).filter((key) => Object.prototype.propertyIsEnumerable.call(value, key));\n\n/** 在一次递归分支内记录对象对应关系。 */\nconst compareTrackedPair = (left: object, right: object, state: EqualityState, compare: () => boolean): boolean => {\n\tconst existingRight = state.leftObjects.get(left);\n\tconst existingLeft = state.rightObjects.get(right);\n\tif (existingRight !== undefined || existingLeft !== undefined) return existingRight === right && existingLeft === left;\n\tstate.leftObjects.set(left, right);\n\tstate.rightObjects.set(right, left);\n\ttry {\n\t\treturn compare();\n\t} finally {\n\t\tstate.leftObjects.delete(left);\n\t\tstate.rightObjects.delete(right);\n\t}\n};\n\n/** 按字节比较两个 ArrayBufferLike。 */\nconst equalArrayBuffers = (left: ArrayBufferLike, right: ArrayBufferLike): boolean => {\n\tif (left.byteLength !== right.byteLength) return false;\n\tconst leftBytes = new Uint8Array(left);\n\tconst rightBytes = new Uint8Array(right);\n\tfor (let index = 0; index < leftBytes.length; index += 1) {\n\t\tif (leftBytes[index] !== rightBytes[index]) return false;\n\t}\n\treturn true;\n};\n\n/** 按顺序比较数组或 TypedArray 的元素。 */\nconst equalIndexedValues = (\n\tleft: { readonly [index: number]: unknown; readonly length: number },\n\tright: { readonly [index: number]: unknown; readonly length: number },\n\tstate: EqualityState\n): boolean => {\n\tif (left.length !== right.length) return false;\n\treturn compareTrackedPair(left, right, state, () => {\n\t\tfor (let index = 0; index < left.length; index += 1) {\n\t\t\tif (!isEqualValue(left[index], right[index], state)) return false;\n\t\t}\n\t\treturn true;\n\t});\n};\n\n/** 无序比较 Map 条目或 Set 元素。 */\nconst equalUnorderedValues = (left: readonly unknown[], right: readonly unknown[], state: EqualityState): boolean => {\n\tif (left.length !== right.length) return false;\n\tconst matchedIndexes = new Set<number>();\n\tfor (const leftValue of left) {\n\t\tlet matchedIndex = -1;\n\t\tfor (let index = 0; index < right.length; index += 1) {\n\t\t\tif (matchedIndexes.has(index) || !isEqualValue(leftValue, right[index], state)) continue;\n\t\t\tmatchedIndex = index;\n\t\t\tbreak;\n\t\t}\n\t\tif (matchedIndex < 0) return false;\n\t\tmatchedIndexes.add(matchedIndex);\n\t}\n\treturn true;\n};\n\n/** 比较普通对象或 Arguments 的自有可枚举属性与构造器。 */\nconst equalObjects = (left: object, right: object, state: EqualityState): boolean => {\n\tconst leftKeys = getEnumerableOwnKeys(left);\n\tconst rightKeys = getEnumerableOwnKeys(right);\n\tif (leftKeys.length !== rightKeys.length) return false;\n\tfor (const key of leftKeys) {\n\t\tif (!Object.hasOwn(right, key)) return false;\n\t}\n\n\treturn compareTrackedPair(left, right, state, () => {\n\t\tlet compareConstructors = true;\n\t\tfor (const key of leftKeys) {\n\t\t\tif (!isEqualValue(Reflect.get(left, key), Reflect.get(right, key), state)) return false;\n\t\t\tif (key === \"constructor\") compareConstructors = false;\n\t\t}\n\t\tif (!compareConstructors) return true;\n\t\tconst leftConstructor: unknown = Reflect.get(left, \"constructor\");\n\t\tconst rightConstructor: unknown = Reflect.get(right, \"constructor\");\n\t\tif (leftConstructor === rightConstructor || !(\"constructor\" in left && \"constructor\" in right)) return true;\n\t\treturn (\n\t\t\ttypeof leftConstructor === \"function\" &&\n\t\t\ttypeof rightConstructor === \"function\" &&\n\t\t\tleftConstructor instanceof leftConstructor &&\n\t\t\trightConstructor instanceof rightConstructor\n\t\t);\n\t});\n};\n\n/** 递归比较两个值。 */\nfunction isEqualValue(left: unknown, right: unknown, state: EqualityState): boolean {\n\tif (sameValueZero(left, right)) return true;\n\tif (left === null || left === undefined || right === null || right === undefined) return false;\n\n\tconst leftTag = Object.prototype.toString.call(left);\n\tconst rightTag = Object.prototype.toString.call(right);\n\tconst normalizedLeftTag = leftTag === \"[object Arguments]\" ? \"[object Object]\" : leftTag;\n\tconst normalizedRightTag = rightTag === \"[object Arguments]\" ? \"[object Object]\" : rightTag;\n\tif (normalizedLeftTag !== normalizedRightTag) return false;\n\n\tswitch (normalizedLeftTag) {\n\t\tcase \"[object Boolean]\":\n\t\tcase \"[object Date]\":\n\t\tcase \"[object Number]\":\n\t\t\treturn sameValueZero(Number(left), Number(right));\n\t\tcase \"[object Error]\":\n\t\t\treturn (left as Error).name === (right as Error).name && (left as Error).message === (right as Error).message;\n\t\tcase \"[object RegExp]\":\n\t\t\treturn RegExp.prototype.toString.call(left) === RegExp.prototype.toString.call(right);\n\t\tcase \"[object String]\":\n\t\t\treturn String.prototype.valueOf.call(left) === String.prototype.valueOf.call(right);\n\t\tcase \"[object Symbol]\":\n\t\t\treturn Symbol.prototype.valueOf.call(left) === Symbol.prototype.valueOf.call(right);\n\t}\n\n\tif (typeof left !== \"object\" || typeof right !== \"object\") return false;\n\tif (Array.isArray(left) && Array.isArray(right)) return equalIndexedValues(left, right, state);\n\tif (normalizedLeftTag === \"[object ArrayBuffer]\" || normalizedLeftTag === \"[object SharedArrayBuffer]\") {\n\t\treturn equalArrayBuffers(left as ArrayBufferLike, right as ArrayBufferLike);\n\t}\n\tif (normalizedLeftTag === \"[object DataView]\") {\n\t\tconst leftView = left as DataView;\n\t\tconst rightView = right as DataView;\n\t\treturn (\n\t\t\tleftView.byteLength === rightView.byteLength &&\n\t\t\tleftView.byteOffset === rightView.byteOffset &&\n\t\t\tequalArrayBuffers(leftView.buffer, rightView.buffer)\n\t\t);\n\t}\n\tif (typedArrayTags.has(normalizedLeftTag)) {\n\t\treturn equalIndexedValues(\n\t\t\tleft as ArrayBufferView & { readonly [index: number]: unknown; readonly length: number },\n\t\t\tright as ArrayBufferView & { readonly [index: number]: unknown; readonly length: number },\n\t\t\tstate\n\t\t);\n\t}\n\tif (normalizedLeftTag === \"[object Map]\") {\n\t\treturn compareTrackedPair(left, right, state, () =>\n\t\t\tequalUnorderedValues([...(left as Map<unknown, unknown>)], [...(right as Map<unknown, unknown>)], state)\n\t\t);\n\t}\n\tif (normalizedLeftTag === \"[object Set]\") {\n\t\treturn compareTrackedPair(left, right, state, () => equalUnorderedValues([...(left as Set<unknown>)], [...(right as Set<unknown>)], state));\n\t}\n\tif (normalizedLeftTag === \"[object Object]\") return equalObjects(left, right, state);\n\treturn false;\n}\n\n/**\n * 判断值是否是普通对象。\n *\n * @param value - 任意待检查值。\n * @returns 原型为 `Object.prototype` 或 `null` 时返回 `true`。\n */\nexport function isPlainObject(value: unknown): value is Record<PropertyKey, unknown> {\n\tif (typeof value !== \"object\" || value === null) return false;\n\tconst prototype = Object.getPrototypeOf(value) as object | null;\n\treturn prototype === null || prototype === Object.prototype;\n}\n\n/**\n * 安全判断对象是否拥有自己的属性。\n *\n * @remarks 不调用可能被对象覆盖的 `hasOwnProperty`。\n * @param value - 待检查对象。\n * @param key - 字符串、数字或 Symbol 属性键。\n * @returns 属性为对象自有属性时返回 `true`,并收窄键类型。\n */\nexport function hasOwn<ObjectType extends object, Key extends PropertyKey>(value: ObjectType, key: Key): key is Key & keyof ObjectType {\n\treturn Object.hasOwn(value, key);\n}\n\n/**\n * 递归创建值的深层副本。\n *\n * @remarks 支持循环引用、共享引用、Symbol 键、对象原型、ArrayBuffer、DataView、Date、Map、RegExp、Set 和 TypedArray。\n * Map 的键保持原引用,函数及其他不可克隆值在嵌套位置保持原引用;只复制自有可枚举属性。\n * @param value - 需要深复制的任意值。\n * @returns 与输入类型一致且不共享可克隆嵌套值的新值;原始类型直接返回自身。\n */\nexport function cloneDeep<Value>(value: Value): Value {\n\treturn cloneDeepValue(value, new WeakMap(), true) as Value;\n}\n\n/**\n * 深度比较两个值是否等价。\n *\n * @remarks 原始值使用 SameValueZero 语义;支持循环引用、数组、对象、ArrayBuffer、DataView、Date、Error、Map、RegExp、Set、Symbol 和 TypedArray。\n * 对象只比较自有可枚举字符串与 Symbol 属性,函数及其他不支持的宿主对象仅在引用相同时相等。\n * @param left - 第一待比较值。\n * @param right - 第二待比较值。\n * @returns 两个值深度等价时返回 `true`。\n */\nexport function isEqual(left: unknown, right: unknown): boolean {\n\treturn isEqualValue(left, right, { leftObjects: new WeakMap(), rightObjects: new WeakMap() });\n}\n\n/**\n * 从对象中选择指定自有可枚举属性。\n *\n * @remarks 固定键元组保留精确返回类型;动态数组中可能被选择或排除的键在返回类型中保持可选。\n * @param source - 不会被修改的源对象。\n * @param keys - 需要保留的键;不存在的键被忽略。\n * @returns 新对象,保持 `keys` 的遍历顺序。\n */\nexport function pick<Source extends object, const Keys extends readonly (keyof Source)[]>(\n\tsource: Source,\n\tkeys: Keys\n): number extends Keys[\"length\"] ? Partial<Pick<Source, Keys[number]>> : Pick<Source, Keys[number]>;\nexport function pick<Source extends object>(source: Source, keys: readonly PropertyKey[]): Partial<Source>;\nexport function pick<Source extends object>(source: Source, keys: readonly PropertyKey[]): Partial<Source> {\n\tconst result: Partial<Source> = {};\n\tfor (const key of keys) {\n\t\tif (Object.prototype.propertyIsEnumerable.call(source, key)) defineEnumerableProperty(result, key, Reflect.get(source, key));\n\t}\n\treturn result;\n}\n\n/**\n * 浅复制对象并删除指定属性。\n *\n * @remarks 固定键元组保留精确返回类型;动态数组中可能被选择或排除的键在返回类型中保持可选。\n * @param source - 不会被修改的源对象。\n * @param keys - 需要排除的键。\n * @returns 包含其余自有可枚举字符串与 Symbol 属性的新对象。\n */\nexport function omit<Source extends object, const Keys extends readonly (keyof Source)[]>(\n\tsource: Source,\n\tkeys: Keys\n): number extends Keys[\"length\"] ? Omit<Source, Keys[number]> & Partial<Pick<Source, Keys[number]>> : Omit<Source, Keys[number]>;\nexport function omit<Source extends object>(source: Source, keys: readonly PropertyKey[]): Partial<Source>;\nexport function omit<Source extends object>(source: Source, keys: readonly PropertyKey[]): Partial<Source> {\n\tconst result = { ...source };\n\tfor (const key of keys) Reflect.deleteProperty(result, key);\n\treturn result;\n}\n\n/**\n * 按条件排除对象的自有可枚举属性。\n *\n * @param source - 不会被修改的源对象。\n * @param predicate - 接收属性值、键和源对象;返回真值时排除该属性。\n * @returns 由未匹配属性组成的新对象。\n */\nexport function omitBy<Source extends object>(\n\tsource: Source,\n\tpredicate: (value: Source[keyof Source], key: keyof Source, source: Source) => unknown\n): Partial<Source> {\n\tconst result: Partial<Source> = {};\n\tfor (const key of getEnumerableOwnKeys(source) as (keyof Source)[]) {\n\t\tif (!predicate(source[key], key, source)) defineEnumerableProperty(result, key, source[key]);\n\t}\n\treturn result;\n}\n\n/**\n * 按条件选择对象的自有可枚举属性。\n *\n * @param source - 不会被修改的源对象。\n * @param predicate - 接收属性值、键和源对象;返回真值时保留该属性。\n * @returns 由匹配属性组成的新对象。\n */\nexport function pickBy<Source extends object>(\n\tsource: Source,\n\tpredicate: (value: Source[keyof Source], key: keyof Source, source: Source) => unknown\n): Partial<Source> {\n\tconst result: Partial<Source> = {};\n\tfor (const key of getEnumerableOwnKeys(source) as (keyof Source)[]) {\n\t\tif (predicate(source[key], key, source)) defineEnumerableProperty(result, key, source[key]);\n\t}\n\treturn result;\n}\n\n/**\n * 映射对象的自有可枚举属性值。\n *\n * @param source - 不会被修改的源对象。\n * @param mapper - 接收值、键和源对象的映射函数。\n * @returns 保留原键的新对象。\n */\nexport function mapValues<Source extends object, Result>(\n\tsource: Source,\n\tmapper: (value: Source[keyof Source], key: keyof Source, source: Source) => Result\n): { [Key in keyof Source]: Result } {\n\tconst result = {} as { [Key in keyof Source]: Result };\n\tfor (const key of Reflect.ownKeys(source) as (keyof Source)[]) {\n\t\tif (Object.prototype.propertyIsEnumerable.call(source, key)) defineEnumerableProperty(result, key, mapper(source[key], key, source));\n\t}\n\treturn result;\n}\n\n/**\n * 对自有可枚举属性执行 SameValue 浅比较。\n *\n * @remarks 嵌套对象只比较引用;`NaN` 相等,`0` 与 `-0` 不相等。\n * @param left - 第一对象。\n * @param right - 第二对象。\n * @returns 自有可枚举键集合与对应值均满足 SameValue 时返回 `true`。\n */\nexport function shallowEqual(left: object, right: object): boolean {\n\tif (Object.is(left, right)) return true;\n\tconst leftKeys = Reflect.ownKeys(left).filter((key) => Object.prototype.propertyIsEnumerable.call(left, key));\n\tconst rightKeys = Reflect.ownKeys(right).filter((key) => Object.prototype.propertyIsEnumerable.call(right, key));\n\tif (leftKeys.length !== rightKeys.length) return false;\n\treturn leftKeys.every((key) => Object.hasOwn(right, key) && Object.is(Reflect.get(left, key), Reflect.get(right, key)));\n}\n\n/**\n * 把 Query 原始值规范化为文本。\n *\n * @param value - 已排除空值的字符串、数字、布尔值或 BigInt。\n * @returns 与 URLSearchParams 兼容的文本值。\n * @throws `RangeError` 当数字不是有限值。\n */\nconst serializeQueryValue = (value: Exclude<QueryPrimitive, null | undefined>): string => {\n\tif (typeof value === \"number\" && !Number.isFinite(value)) {\n\t\tthrow new RangeError(\"查询参数中的数字必须是有限数。\");\n\t}\n\treturn String(value);\n};\n\n/**\n * 将对象序列化为标准 URL 查询字符串。\n *\n * @remarks `null` 与 `undefined` 被跳过;数组使用重复键;返回值不会修改输入。\n * @param value - 查询参数对象。\n * @param options - 排序、空格和问号前缀选项。\n * @returns URL 编码后的查询字符串;没有参数时始终返回空字符串。\n * @throws `RangeError` 当参数包含 `NaN` 或无穷数字。\n */\nexport function toQueryString(value: Readonly<Record<string, QueryValue>>, options: QueryStringOptions = {}): string {\n\tconst entries = Object.entries(value);\n\tif (options.sort) entries.sort(([left], [right]) => (left < right ? -1 : left > right ? 1 : 0));\n\tconst parameters = new URLSearchParams();\n\tfor (const [key, rawValue] of entries) {\n\t\tconst values = isQueryPrimitiveArray(rawValue) ? rawValue : [rawValue];\n\t\tfor (const item of values) {\n\t\t\tif (item !== null && item !== undefined) parameters.append(key, serializeQueryValue(item));\n\t\t}\n\t}\n\tlet result = parameters.toString();\n\tif (options.space === \"percent\") result = result.replace(/\\+/gu, \"%20\");\n\treturn result && options.prefixQuestionMark ? `?${result}` : result;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/object/index.ts"],"sourcesContent":["/** URL 查询参数支持的单值类型。 */\nexport type QueryPrimitive = bigint | boolean | number | string | null | undefined;\n\n/** URL 查询参数值;数组使用重复键表示。 */\nexport type QueryValue = QueryPrimitive | readonly QueryPrimitive[];\n\n/**\n * 判断 Query Value 是否为重复参数数组。\n *\n * @param value - 单值或数组形式的 Query Value\n * @returns 是只读原始值数组时返回 `true`。\n */\nconst isQueryPrimitiveArray = (value: QueryValue): value is readonly QueryPrimitive[] => Array.isArray(value);\n\n/** {@link toQueryString} 的序列化选项 */\nexport interface QueryStringOptions {\n\t/** 返回非空结果时是否添加 `?`;默认 `false`。 */\n\tprefixQuestionMark?: boolean;\n\t/** 是否按键的 UTF-16 码元顺序稳定排序;默认保留对象枚举顺序。 */\n\tsort?: boolean;\n\t/** 空格编码方式;默认遵循表单编码并输出 `+`。 */\n\tspace?: \"percent\" | \"plus\";\n}\n\n/**\n * 安全写入结果对象的自有可枚举属性。\n *\n * @remarks 使用 `defineProperty` 避免 `__proto__` 触发 Setter,并统一创建可写、可配置的自有可枚举数据属性。\n * @param target - 要写入的结果对象\n * @param key - 自有属性键\n * @param value - 属性值\n */\nconst defineEnumerableProperty = (target: object, key: PropertyKey, value: unknown): void => {\n\tObject.defineProperty(target, key, { configurable: true, enumerable: true, value, writable: true });\n};\n\nconst typedArrayTags = new Set([\n\t\"[object BigInt64Array]\",\n\t\"[object BigUint64Array]\",\n\t\"[object Float32Array]\",\n\t\"[object Float64Array]\",\n\t\"[object Int8Array]\",\n\t\"[object Int16Array]\",\n\t\"[object Int32Array]\",\n\t\"[object Uint8Array]\",\n\t\"[object Uint8ClampedArray]\",\n\t\"[object Uint16Array]\",\n\t\"[object Uint32Array]\",\n]);\n\n/** 使用源值的构造器创建同类空实例。 */\nconst createUsingConstructor = (value: object, arguments_: readonly unknown[]): object => {\n\tconst constructor: unknown = Reflect.get(value, \"constructor\");\n\treturn typeof constructor === \"function\" ? (Reflect.construct(constructor, arguments_) as object) : {};\n};\n\n/** 复制 ArrayBufferLike 的当前字节,不与源值共享底层内存。 */\nconst cloneArrayBuffer = (value: ArrayBufferLike): ArrayBufferLike => {\n\tconst result = createUsingConstructor(value, [value.byteLength]) as ArrayBufferLike;\n\tnew Uint8Array(result).set(new Uint8Array(value));\n\treturn result;\n};\n\n/** 递归复制值,并记录已复制对象以还原循环引用和共享引用。 */\nconst cloneDeepValue = (value: unknown, clones: WeakMap<object, object>, isRoot: boolean): unknown => {\n\tif ((typeof value !== \"object\" && typeof value !== \"function\") || value === null) return value;\n\n\tconst source = value;\n\tconst existing = clones.get(source);\n\tif (existing !== undefined) return existing;\n\tif (typeof source === \"function\" && !isRoot) return source;\n\n\tconst tag = Object.prototype.toString.call(source);\n\tlet result: object;\n\tlet pendingBuffer: { source: ArrayBufferLike; result: ArrayBufferLike } | undefined;\n\t// 先登记底层缓冲区,视图登记后再复制其附加属性,避免缓冲区与视图相互引用时重复构造。\n\tconst getBufferClone = (buffer: ArrayBufferLike): ArrayBufferLike => {\n\t\tconst existingBuffer = clones.get(buffer);\n\t\tif (existingBuffer !== undefined) return existingBuffer as ArrayBufferLike;\n\t\tconst clonedBuffer = cloneArrayBuffer(buffer);\n\t\tclones.set(buffer, clonedBuffer);\n\t\tpendingBuffer = { source: buffer, result: clonedBuffer };\n\t\treturn clonedBuffer;\n\t};\n\tif (Array.isArray(source)) {\n\t\t// 只复制实际存在的自有可枚举键,保留空洞、附加字符串属性和 Symbol 属性。\n\t\tresult = createUsingConstructor(source, [source.length]);\n\t} else if (typeof source === \"function\") {\n\t\tresult = {};\n\t} else {\n\t\tswitch (tag) {\n\t\t\tcase \"[object Arguments]\":\n\t\t\t\tresult = {};\n\t\t\t\tbreak;\n\t\t\tcase \"[object ArrayBuffer]\":\n\t\t\tcase \"[object SharedArrayBuffer]\":\n\t\t\t\tresult = cloneArrayBuffer(source as ArrayBufferLike);\n\t\t\t\tbreak;\n\t\t\tcase \"[object Boolean]\":\n\t\t\t\tresult = createUsingConstructor(source, [(source as { valueOf: () => boolean }).valueOf()]);\n\t\t\t\tbreak;\n\t\t\tcase \"[object DataView]\": {\n\t\t\t\tconst view = source as DataView;\n\t\t\t\tresult = createUsingConstructor(source, [getBufferClone(view.buffer), view.byteOffset, view.byteLength]);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"[object Date]\":\n\t\t\t\tresult = createUsingConstructor(source, [(source as Date).getTime()]);\n\t\t\t\tbreak;\n\t\t\tcase \"[object Map]\":\n\t\t\tcase \"[object Set]\":\n\t\t\t\tresult = createUsingConstructor(source, []);\n\t\t\t\tbreak;\n\t\t\tcase \"[object Number]\":\n\t\t\t\tresult = createUsingConstructor(source, [(source as { valueOf: () => number }).valueOf()]);\n\t\t\t\tbreak;\n\t\t\tcase \"[object Object]\": {\n\t\t\t\tconst prototype = Object.getPrototypeOf(source) as object | null;\n\t\t\t\tresult = Object.create(prototype) as object;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"[object RegExp]\": {\n\t\t\t\tconst expression = source as RegExp;\n\t\t\t\tconst clonedExpression = new RegExp(expression.source, expression.flags);\n\t\t\t\tclonedExpression.lastIndex = expression.lastIndex;\n\t\t\t\tresult = clonedExpression;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"[object String]\":\n\t\t\t\tresult = createUsingConstructor(source, [(source as { valueOf: () => string }).valueOf()]);\n\t\t\t\tbreak;\n\t\t\tcase \"[object Symbol]\":\n\t\t\t\tresult = Object((source as { valueOf: () => symbol }).valueOf()) as object;\n\t\t\t\tbreak;\n\t\t\tdefault: {\n\t\t\t\tif (!typedArrayTags.has(tag)) return isRoot ? {} : source;\n\t\t\t\tconst view = source as ArrayBufferView & { readonly length: number };\n\t\t\t\tresult = createUsingConstructor(source, [getBufferClone(view.buffer), view.byteOffset, view.length]);\n\t\t\t}\n\t\t}\n\t}\n\n\tclones.set(source, result);\n\tif (pendingBuffer !== undefined) {\n\t\tcopyCloneProperties(pendingBuffer.source, pendingBuffer.result, clones);\n\t}\n\tif (tag === \"[object Map]\") {\n\t\tfor (const [key, item] of source as Map<unknown, unknown>) {\n\t\t\t(result as Map<unknown, unknown>).set(key, cloneDeepValue(item, clones, false));\n\t\t}\n\t} else if (tag === \"[object Set]\") {\n\t\tfor (const item of source as Set<unknown>) {\n\t\t\t(result as Set<unknown>).add(cloneDeepValue(item, clones, false));\n\t\t}\n\t}\n\n\tcopyCloneProperties(source, result, clones);\n\treturn result;\n};\n\n/** 复制自有可枚举属性,不触发结果原型上的 setter。 */\nfunction copyCloneProperties(source: object, result: object, clones: WeakMap<object, object>): void {\n\tfor (const key of Reflect.ownKeys(source)) {\n\t\tif (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;\n\t\tconst descriptor = Object.getOwnPropertyDescriptor(result, key);\n\t\t// String 包装对象的字符索引由构造器建立,不能重新定义。\n\t\tif (descriptor?.configurable === false && descriptor.writable === false) continue;\n\t\tdefineEnumerableProperty(result, key, cloneDeepValue(Reflect.get(source, key), clones, false));\n\t}\n}\n\n/** 深度比较过程中用于识别循环引用的双向对象映射 */\ninterface EqualityState {\n\treadonly leftObjects: WeakMap<object, object>;\n\treadonly rightObjects: WeakMap<object, object>;\n}\n\n/** 判断两个值是否满足 SameValueZero 相等。 */\nconst sameValueZero = (left: unknown, right: unknown): boolean =>\n\tleft === right || (typeof left === \"number\" && typeof right === \"number\" && Number.isNaN(left) && Number.isNaN(right));\n\n/** 返回对象的自有可枚举字符串与 Symbol 键。 */\nconst getEnumerableOwnKeys = (value: object): PropertyKey[] =>\n\tReflect.ownKeys(value).filter((key) => Object.prototype.propertyIsEnumerable.call(value, key));\n\n/** 在一次递归分支内记录对象对应关系。 */\nconst compareTrackedPair = (left: object, right: object, state: EqualityState, compare: () => boolean): boolean => {\n\tconst existingRight = state.leftObjects.get(left);\n\tconst existingLeft = state.rightObjects.get(right);\n\tif (existingRight !== undefined || existingLeft !== undefined) return existingRight === right && existingLeft === left;\n\tstate.leftObjects.set(left, right);\n\tstate.rightObjects.set(right, left);\n\ttry {\n\t\treturn compare();\n\t} finally {\n\t\tstate.leftObjects.delete(left);\n\t\tstate.rightObjects.delete(right);\n\t}\n};\n\n/** 按字节比较两个 ArrayBufferLike。 */\nconst equalArrayBuffers = (left: ArrayBufferLike, right: ArrayBufferLike): boolean => {\n\tif (left.byteLength !== right.byteLength) return false;\n\tconst leftBytes = new Uint8Array(left);\n\tconst rightBytes = new Uint8Array(right);\n\tfor (let index = 0; index < leftBytes.length; index += 1) {\n\t\tif (leftBytes[index] !== rightBytes[index]) return false;\n\t}\n\treturn true;\n};\n\n/** 按顺序比较数组或 TypedArray 的元素。 */\nconst equalIndexedValues = (\n\tleft: { readonly [index: number]: unknown; readonly length: number },\n\tright: { readonly [index: number]: unknown; readonly length: number },\n\tstate: EqualityState\n): boolean => {\n\tif (left.length !== right.length) return false;\n\treturn compareTrackedPair(left, right, state, () => {\n\t\tfor (let index = 0; index < left.length; index += 1) {\n\t\t\tif (!isEqualValue(left[index], right[index], state)) return false;\n\t\t}\n\t\treturn true;\n\t});\n};\n\n/** 无序比较 Map 条目或 Set 元素。 */\nconst equalUnorderedValues = (left: readonly unknown[], right: readonly unknown[], state: EqualityState): boolean => {\n\tif (left.length !== right.length) return false;\n\tconst matchedIndexes = new Set<number>();\n\tfor (const leftValue of left) {\n\t\tlet matchedIndex = -1;\n\t\tfor (let index = 0; index < right.length; index += 1) {\n\t\t\tif (matchedIndexes.has(index) || !isEqualValue(leftValue, right[index], state)) continue;\n\t\t\tmatchedIndex = index;\n\t\t\tbreak;\n\t\t}\n\t\tif (matchedIndex < 0) return false;\n\t\tmatchedIndexes.add(matchedIndex);\n\t}\n\treturn true;\n};\n\n/** 比较普通对象或 Arguments 的自有可枚举属性与构造器。 */\nconst equalObjects = (left: object, right: object, state: EqualityState): boolean => {\n\tconst leftKeys = getEnumerableOwnKeys(left);\n\tconst rightKeys = getEnumerableOwnKeys(right);\n\tif (leftKeys.length !== rightKeys.length) return false;\n\tfor (const key of leftKeys) {\n\t\tif (!Object.prototype.hasOwnProperty.call(right, key)) return false;\n\t}\n\n\treturn compareTrackedPair(left, right, state, () => {\n\t\tlet compareConstructors = true;\n\t\tfor (const key of leftKeys) {\n\t\t\tif (!isEqualValue(Reflect.get(left, key), Reflect.get(right, key), state)) return false;\n\t\t\tif (key === \"constructor\") compareConstructors = false;\n\t\t}\n\t\tif (!compareConstructors) return true;\n\t\tconst leftConstructor: unknown = Reflect.get(left, \"constructor\");\n\t\tconst rightConstructor: unknown = Reflect.get(right, \"constructor\");\n\t\tif (leftConstructor === rightConstructor || !(\"constructor\" in left && \"constructor\" in right)) return true;\n\t\treturn (\n\t\t\ttypeof leftConstructor === \"function\" &&\n\t\t\ttypeof rightConstructor === \"function\" &&\n\t\t\tleftConstructor instanceof leftConstructor &&\n\t\t\trightConstructor instanceof rightConstructor\n\t\t);\n\t});\n};\n\n/** 递归比较两个值。 */\nfunction isEqualValue(left: unknown, right: unknown, state: EqualityState): boolean {\n\tif (sameValueZero(left, right)) return true;\n\tif (left === null || left === undefined || right === null || right === undefined) return false;\n\n\tconst leftTag = Object.prototype.toString.call(left);\n\tconst rightTag = Object.prototype.toString.call(right);\n\tconst normalizedLeftTag = leftTag === \"[object Arguments]\" ? \"[object Object]\" : leftTag;\n\tconst normalizedRightTag = rightTag === \"[object Arguments]\" ? \"[object Object]\" : rightTag;\n\tif (normalizedLeftTag !== normalizedRightTag) return false;\n\n\tswitch (normalizedLeftTag) {\n\t\tcase \"[object Boolean]\":\n\t\tcase \"[object Date]\":\n\t\tcase \"[object Number]\":\n\t\t\treturn sameValueZero(Number(left), Number(right));\n\t\tcase \"[object Error]\":\n\t\t\treturn (left as Error).name === (right as Error).name && (left as Error).message === (right as Error).message;\n\t\tcase \"[object RegExp]\":\n\t\t\treturn RegExp.prototype.toString.call(left) === RegExp.prototype.toString.call(right);\n\t\tcase \"[object String]\":\n\t\t\treturn String.prototype.valueOf.call(left) === String.prototype.valueOf.call(right);\n\t\tcase \"[object Symbol]\":\n\t\t\treturn Symbol.prototype.valueOf.call(left) === Symbol.prototype.valueOf.call(right);\n\t}\n\n\tif (typeof left !== \"object\" || typeof right !== \"object\") return false;\n\tif (Array.isArray(left) && Array.isArray(right)) return equalIndexedValues(left, right, state);\n\tif (normalizedLeftTag === \"[object ArrayBuffer]\" || normalizedLeftTag === \"[object SharedArrayBuffer]\") {\n\t\treturn equalArrayBuffers(left as ArrayBufferLike, right as ArrayBufferLike);\n\t}\n\tif (normalizedLeftTag === \"[object DataView]\") {\n\t\tconst leftView = left as DataView;\n\t\tconst rightView = right as DataView;\n\t\treturn (\n\t\t\tleftView.byteLength === rightView.byteLength &&\n\t\t\tleftView.byteOffset === rightView.byteOffset &&\n\t\t\tequalArrayBuffers(leftView.buffer, rightView.buffer)\n\t\t);\n\t}\n\tif (typedArrayTags.has(normalizedLeftTag)) {\n\t\treturn equalIndexedValues(\n\t\t\tleft as ArrayBufferView & { readonly [index: number]: unknown; readonly length: number },\n\t\t\tright as ArrayBufferView & { readonly [index: number]: unknown; readonly length: number },\n\t\t\tstate\n\t\t);\n\t}\n\tif (normalizedLeftTag === \"[object Map]\") {\n\t\treturn compareTrackedPair(left, right, state, () =>\n\t\t\tequalUnorderedValues([...(left as Map<unknown, unknown>)], [...(right as Map<unknown, unknown>)], state)\n\t\t);\n\t}\n\tif (normalizedLeftTag === \"[object Set]\") {\n\t\treturn compareTrackedPair(left, right, state, () => equalUnorderedValues([...(left as Set<unknown>)], [...(right as Set<unknown>)], state));\n\t}\n\tif (normalizedLeftTag === \"[object Object]\") return equalObjects(left, right, state);\n\treturn false;\n}\n\n/**\n * 判断值是否是普通对象。\n *\n * @param value - 任意待检查值\n * @returns 原型为 `Object.prototype` 或 `null` 时返回 `true`。\n */\nexport function isPlainObject(value: unknown): value is Record<PropertyKey, unknown> {\n\tif (typeof value !== \"object\" || value === null) return false;\n\tconst prototype = Object.getPrototypeOf(value) as object | null;\n\treturn prototype === null || prototype === Object.prototype;\n}\n\n/**\n * 安全判断对象是否拥有自己的属性。\n *\n * @remarks 不调用可能被对象覆盖的 `hasOwnProperty`。\n * @param value - 待检查对象\n * @param key - 字符串、数字或 Symbol 属性键\n * @returns 属性为对象自有属性时返回 `true`,并收窄键类型。\n */\nexport function hasOwn<ObjectType extends object, Key extends PropertyKey>(value: ObjectType, key: Key): key is Key & keyof ObjectType {\n\treturn Object.prototype.hasOwnProperty.call(value, key);\n}\n\n/**\n * 递归创建值的深层副本。\n *\n * @remarks 支持循环引用、共享引用、Symbol 键、对象原型、ArrayBuffer、DataView、Date、Map、RegExp、Set 和 TypedArray。\n * Map 的键保持原引用,函数及其他不可克隆值在嵌套位置保持原引用;只复制自有可枚举属性。\n * @param value - 需要深复制的任意值\n * @returns 与输入类型一致且不共享可克隆嵌套值的新值;原始类型直接返回自身。\n */\nexport function cloneDeep<Value>(value: Value): Value {\n\treturn cloneDeepValue(value, new WeakMap(), true) as Value;\n}\n\n/**\n * 深度比较两个值是否等价。\n *\n * @remarks 原始值使用 SameValueZero 语义;支持循环引用、数组、对象、ArrayBuffer、DataView、Date、Error、Map、RegExp、Set、Symbol 和 TypedArray。\n * 对象只比较自有可枚举字符串与 Symbol 属性,函数及其他不支持的宿主对象仅在引用相同时相等。\n * @param left - 第一待比较值\n * @param right - 第二待比较值\n * @returns 两个值深度等价时返回 `true`。\n */\nexport function isEqual(left: unknown, right: unknown): boolean {\n\treturn isEqualValue(left, right, { leftObjects: new WeakMap(), rightObjects: new WeakMap() });\n}\n\n/**\n * 从对象中选择指定自有可枚举属性。\n *\n * @remarks 固定键元组保留精确返回类型;动态数组中可能被选择或排除的键在返回类型中保持可选。\n * @param source - 不会被修改的源对象\n * @param keys - 需要保留的键;不存在的键被忽略。\n * @returns 新对象,保持 `keys` 的遍历顺序。\n */\nexport function pick<Source extends object, const Keys extends readonly (keyof Source)[]>(\n\tsource: Source,\n\tkeys: Keys\n): number extends Keys[\"length\"] ? Partial<Pick<Source, Keys[number]>> : Pick<Source, Keys[number]>;\nexport function pick<Source extends object>(source: Source, keys: readonly PropertyKey[]): Partial<Source>;\nexport function pick<Source extends object>(source: Source, keys: readonly PropertyKey[]): Partial<Source> {\n\tconst result: Partial<Source> = {};\n\tfor (const key of keys) {\n\t\tif (Object.prototype.propertyIsEnumerable.call(source, key)) defineEnumerableProperty(result, key, Reflect.get(source, key));\n\t}\n\treturn result;\n}\n\n/**\n * 浅复制对象并删除指定属性。\n *\n * @remarks 固定键元组保留精确返回类型;动态数组中可能被选择或排除的键在返回类型中保持可选。\n * @param source - 不会被修改的源对象\n * @param keys - 需要排除的键\n * @returns 包含其余自有可枚举字符串与 Symbol 属性的新对象\n */\nexport function omit<Source extends object, const Keys extends readonly (keyof Source)[]>(\n\tsource: Source,\n\tkeys: Keys\n): number extends Keys[\"length\"] ? Omit<Source, Keys[number]> & Partial<Pick<Source, Keys[number]>> : Omit<Source, Keys[number]>;\nexport function omit<Source extends object>(source: Source, keys: readonly PropertyKey[]): Partial<Source>;\nexport function omit<Source extends object>(source: Source, keys: readonly PropertyKey[]): Partial<Source> {\n\tconst result = { ...source };\n\tfor (const key of keys) Reflect.deleteProperty(result, key);\n\treturn result;\n}\n\n/**\n * 按条件排除对象的自有可枚举属性。\n *\n * @param source - 不会被修改的源对象\n * @param predicate - 接收属性值、键和源对象;返回真值时排除该属性。\n * @returns 由未匹配属性组成的新对象\n */\nexport function omitBy<Source extends object>(\n\tsource: Source,\n\tpredicate: (value: Source[keyof Source], key: keyof Source, source: Source) => unknown\n): Partial<Source> {\n\tconst result: Partial<Source> = {};\n\tfor (const key of getEnumerableOwnKeys(source) as (keyof Source)[]) {\n\t\tif (!predicate(source[key], key, source)) defineEnumerableProperty(result, key, source[key]);\n\t}\n\treturn result;\n}\n\n/**\n * 按条件选择对象的自有可枚举属性。\n *\n * @param source - 不会被修改的源对象\n * @param predicate - 接收属性值、键和源对象;返回真值时保留该属性。\n * @returns 由匹配属性组成的新对象\n */\nexport function pickBy<Source extends object>(\n\tsource: Source,\n\tpredicate: (value: Source[keyof Source], key: keyof Source, source: Source) => unknown\n): Partial<Source> {\n\tconst result: Partial<Source> = {};\n\tfor (const key of getEnumerableOwnKeys(source) as (keyof Source)[]) {\n\t\tif (predicate(source[key], key, source)) defineEnumerableProperty(result, key, source[key]);\n\t}\n\treturn result;\n}\n\n/**\n * 映射对象的自有可枚举属性值。\n *\n * @param source - 不会被修改的源对象\n * @param mapper - 接收值、键和源对象的映射函数\n * @returns 保留原键的新对象\n */\nexport function mapValues<Source extends object, Result>(\n\tsource: Source,\n\tmapper: (value: Source[keyof Source], key: keyof Source, source: Source) => Result\n): { [Key in keyof Source]: Result } {\n\tconst result = {} as { [Key in keyof Source]: Result };\n\tfor (const key of Reflect.ownKeys(source) as (keyof Source)[]) {\n\t\tif (Object.prototype.propertyIsEnumerable.call(source, key)) defineEnumerableProperty(result, key, mapper(source[key], key, source));\n\t}\n\treturn result;\n}\n\n/**\n * 对自有可枚举属性执行 SameValue 浅比较。\n *\n * @remarks 嵌套对象只比较引用;`NaN` 相等,`0` 与 `-0` 不相等。\n * @param left - 第一对象\n * @param right - 第二对象\n * @returns 自有可枚举键集合与对应值均满足 SameValue 时返回 `true`。\n */\nexport function shallowEqual(left: object, right: object): boolean {\n\tif (Object.is(left, right)) return true;\n\tconst leftKeys = Reflect.ownKeys(left).filter((key) => Object.prototype.propertyIsEnumerable.call(left, key));\n\tconst rightKeys = Reflect.ownKeys(right).filter((key) => Object.prototype.propertyIsEnumerable.call(right, key));\n\tif (leftKeys.length !== rightKeys.length) return false;\n\treturn leftKeys.every((key) => Object.prototype.hasOwnProperty.call(right, key) && Object.is(Reflect.get(left, key), Reflect.get(right, key)));\n}\n\n/**\n * 把 Query 原始值规范化为文本。\n *\n * @param value - 已排除空值的字符串、数字、布尔值或 BigInt\n * @returns 与 URLSearchParams 兼容的文本值\n * @throws `RangeError` 当数字不是有限值。\n */\nconst serializeQueryValue = (value: Exclude<QueryPrimitive, null | undefined>): string => {\n\tif (typeof value === \"number\" && !Number.isFinite(value)) {\n\t\tthrow new RangeError(\"Query parameter numbers must be finite.\");\n\t}\n\treturn String(value);\n};\n\n/**\n * 将对象序列化为标准 URL 查询字符串。\n *\n * @remarks `null` 与 `undefined` 被跳过;数组使用重复键;返回值不会修改输入。\n * @param value - 查询参数对象\n * @param options - 排序、空格和问号前缀选项\n * @returns URL 编码后的查询字符串;没有参数时始终返回空字符串。\n * @throws `RangeError` 当参数包含 `NaN` 或无穷数字。\n * @throws `URIError` 当键或值包含孤立的 UTF-16 代理项。\n */\nexport function toQueryString(value: Readonly<Record<string, QueryValue>>, options: QueryStringOptions = {}): string {\n\tconst entries = Object.entries(value);\n\tif (options.sort) entries.sort(([left], [right]) => (left < right ? -1 : left > right ? 1 : 0));\n\tconst parameters: string[] = [];\n\tfor (const [key, rawValue] of entries) {\n\t\tconst values = isQueryPrimitiveArray(rawValue) ? rawValue : [rawValue];\n\t\tfor (const item of values) {\n\t\t\tif (item !== null && item !== undefined) {\n\t\t\t\tparameters.push(`${encodeURIComponent(key)}=${encodeURIComponent(serializeQueryValue(item))}`);\n\t\t\t}\n\t\t}\n\t}\n\t// 补齐表单编码字符集,保留已有查询字符串的输出格式。\n\tlet result = parameters.join(\"&\").replace(/[!'()~]/gu, (character) => `%${character.charCodeAt(0).toString(16).toUpperCase()}`);\n\tif (options.space !== \"percent\") result = result.replace(/%20/gu, \"+\");\n\treturn result && options.prefixQuestionMark ? `?${result}` : result;\n}\n"],"mappings":"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"}
|