/
githubmirror
/
deno
Обзор
Документация
Войти
/
githubmirror
/
deno
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
ext/node/polyfills/internal/validators.mjs
516 строк
13 KB
Bartek Iwańczuk
chore: bump node_compat test suite to Node.js 26.5.1 (#36391)
03 авг 2026, 12:52
Не верифицирован
03 авг 2026, 12:52
bca6182
Код
Авторство
О чём код?
// Copyright 2018-2026 the Deno authors. MIT license. // Copyright Joyent and Node contributors. All rights reserved. MIT license. (function () { const { core, primordials } = __bootstrap; const { ArrayIsArray, ArrayPrototypeIncludes, ArrayPrototypeJoin, ArrayPrototypeMap, NumberIsInteger, NumberIsNaN, NumberMIN_SAFE_INTEGER, NumberMAX_SAFE_INTEGER, NumberParseInt, NumberIsFinite, SafeRegExp, String, StringPrototypeIncludes, StringPrototypeTrim, ReflectHas, RegExpPrototypeTest, } = primordials; const { codes } = core.loadExtScript("ext:deno_node/internal/error_codes.ts"); const { hideStackFrames } = core.loadExtScript( "ext:deno_node/internal/hide_stack_frames.ts", ); const { isArrayBufferView } = core.loadExtScript( "ext:deno_node/internal/util/types.ts", ); /** * @param {number} value * @returns {boolean} */ function isInt32(value) { return typeof value === "number" && value === (value | 0); } /** * @param {unknown} value * @returns {boolean} */ function isUint32(value) { return value === (value >>> 0); } const octalReg = new SafeRegExp(/^[0-7]+$/); const modeDesc = "must be a 32-bit unsigned integer or an octal string"; /** * Parse and validate values that will be converted into mode_t (the S_* * constants). Only valid numbers and octal strings are allowed. They could be * converted to 32-bit unsigned integers or non-negative signed integers in the * C++ land, but any value higher than 0o777 will result in platform-specific * behaviors. * * @param {*} value Values to be validated * @param {string} name Name of the argument * @param {number} [def] If specified, will be returned for invalid values * @returns {number} */ function parseFileMode(value, name, def) { value ??= def; if (typeof value === "string") { if (!RegExpPrototypeTest(octalReg, value)) { throw new codes.ERR_INVALID_ARG_VALUE(name, value, modeDesc); } value = NumberParseInt(value, 8); } validateInt32(value, name, 0, 2 ** 32 - 1); return value; } /** @type {(buffer: unknown, name?: string) => asserts buffer is ArrayBufferView} */ const validateBuffer = hideStackFrames((buffer, name = "buffer") => { if (!isArrayBufferView(buffer)) { throw new codes.ERR_INVALID_ARG_TYPE( name, ["Buffer", "TypedArray", "DataView"], buffer, ); } }); /** @type {ValidateNumber} */ const validateInteger = hideStackFrames( ( value, name, min = NumberMIN_SAFE_INTEGER, max = NumberMAX_SAFE_INTEGER, ) => { if (typeof value !== "number") { throw new codes.ERR_INVALID_ARG_TYPE(name, "number", value); } if (!NumberIsInteger(value)) { throw new codes.ERR_OUT_OF_RANGE(name, "an integer", value); } if (value < min || value > max) { throw new codes.ERR_OUT_OF_RANGE(name, `>= ${min} && <= ${max}`, value); } }, ); /** * @typedef {{ * allowArray?: boolean, * allowFunction?: boolean, * nullable?: boolean, * }} ValidateObjectOptions */ /** @typedef {(value: unknown, name: string, options?: ValidateObjectOptions) => asserts value is object} ValidateObject */ /** @type {ValidateObject} */ const validateObject = hideStackFrames((value, name, options) => { const useDefaultOptions = options == null; const allowArray = useDefaultOptions ? false : options.allowArray; const allowFunction = useDefaultOptions ? false : options.allowFunction; const nullable = useDefaultOptions ? false : options.nullable; if ( (!nullable && value === null) || (!allowArray && ArrayIsArray(value)) || (typeof value !== "object" && ( !allowFunction || typeof value !== "function" )) ) { throw new codes.ERR_INVALID_ARG_TYPE(name, "Object", value); } }); /** @type {ValidateNumber} */ const validateInt32 = hideStackFrames( (value, name, min = -2147483648, max = 2147483647) => { // The defaults for min and max correspond to the limits of 32-bit integers. if (!isInt32(value)) { if (typeof value !== "number") { throw new codes.ERR_INVALID_ARG_TYPE(name, "number", value); } if (!NumberIsInteger(value)) { throw new codes.ERR_OUT_OF_RANGE(name, "an integer", value); } throw new codes.ERR_OUT_OF_RANGE(name, `>= ${min} && <= ${max}`, value); } if (value < min || value > max) { throw new codes.ERR_OUT_OF_RANGE(name, `>= ${min} && <= ${max}`, value); } }, ); /** * @type {(value: unknown, name: string, positive?: boolean) => asserts value is number} */ const validateUint32 = hideStackFrames( (value, name, positive) => { if (!isUint32(value)) { if (typeof value !== "number") { throw new codes.ERR_INVALID_ARG_TYPE(name, "number", value); } if (!NumberIsInteger(value)) { throw new codes.ERR_OUT_OF_RANGE(name, "an integer", value); } const min = positive ? 1 : 0; // 2 ** 32 === 4294967296 throw new codes.ERR_OUT_OF_RANGE( name, `>= ${min} && < 4294967296`, value, ); } if (positive && value === 0) { throw new codes.ERR_OUT_OF_RANGE(name, ">= 1 && < 4294967296", value); } }, ); /** * @param {unknown} value * @param {string} name */ function validateString(value, name) { if (typeof value !== "string") { throw new codes.ERR_INVALID_ARG_TYPE(name, "string", value); } } /** @type {typeof validateString} */ const validateStringWithoutNullBytes = hideStackFrames((value, name) => { validateString(value, name); if (StringPrototypeIncludes(value, "\u0000")) { throw new codes.ERR_INVALID_ARG_VALUE( name, value, "must be a string without null bytes", ); } }); /** @typedef {(value: unknown, name: string, min?: number, max?: number) => asserts value is number} ValidateNumber */ /** @type {ValidateNumber} */ const validateNumber = hideStackFrames((value, name, min = undefined, max) => { if (typeof value !== "number") { throw new codes.ERR_INVALID_ARG_TYPE(name, "number", value); } if ( (min != null && value < min) || (max != null && value > max) || ((min != null || max != null) && NumberIsNaN(value)) ) { throw new codes.ERR_OUT_OF_RANGE( name, `${min != null ? `>= ${min}` : ""}${ min != null && max != null ? " && " : "" }${max != null ? `<= ${max}` : ""}`, value, ); } }); /** * @param {unknown} value * @param {string} name */ function validateBoolean(value, name) { if (typeof value !== "boolean") { throw new codes.ERR_INVALID_ARG_TYPE(name, "boolean", value); } } /** @typedef {<T>(value: unknown, name: string, oneOf: readonly T[]) => asserts value is T} ValidateOneOf */ /** @type {ValidateOneOf} */ const validateOneOf = hideStackFrames((value, name, oneOf) => { if (!ArrayPrototypeIncludes(oneOf, value)) { const allowed = ArrayPrototypeJoin( ArrayPrototypeMap( oneOf, (v) => (typeof v === "string" ? `'${v}'` : String(v)), ), ", ", ); const reason = "must be one of: " + allowed; throw new codes.ERR_INVALID_ARG_VALUE(name, value, reason); } }); function validateEncoding(data, encoding) { const { normalizeEncoding } = core.loadExtScript( "ext:deno_node/internal/normalize_encoding.ts", ); const normalizedEncoding = normalizeEncoding(encoding); const length = data.length; if (normalizedEncoding === "hex" && length % 2 !== 0) { throw new codes.ERR_INVALID_ARG_VALUE( "encoding", encoding, `is invalid for data of length ${length}`, ); } } // Check that the port number is not NaN when coerced to a number, // is an integer and that it falls within the legal range of port numbers. /** * @param {string} name * @returns {number} */ function validatePort(port, name = "Port", allowZero = true) { if ( (typeof port !== "number" && typeof port !== "string") || (typeof port === "string" && StringPrototypeTrim(port).length === 0) || +port !== (+port >>> 0) || port > 0xFFFF || (port === 0 && !allowZero) ) { throw new codes.ERR_SOCKET_BAD_PORT(name, port, allowZero); } return port; } /** * @param {unknown} signal * @param {string} name */ const validateAbortSignal = hideStackFrames( (signal, name) => { if ( signal !== undefined && (signal === null || typeof signal !== "object" || !ReflectHas(signal, "aborted")) ) { throw new codes.ERR_INVALID_ARG_TYPE(name, "AbortSignal", signal); } }, ); /** @type {(value: unknown, name: string) => asserts value is Function} */ const validateFunction = hideStackFrames( (value, name) => { if (typeof value !== "function") { throw new codes.ERR_INVALID_ARG_TYPE(name, "Function", value); } }, ); /** * @param {unknown} value * @param {string} name */ const validateArray = hideStackFrames( (value, name, minLength = 0) => { if (!ArrayIsArray(value)) { throw new codes.ERR_INVALID_ARG_TYPE(name, "Array", value); } if (value.length < minLength) { const reason = `must be longer than ${minLength}`; throw new codes.ERR_INVALID_ARG_VALUE(name, value, reason); } }, ); /** * @callback validateStringArray * @param {*} value * @param {string} name * @returns {asserts value is string[]} */ /** @type {validateStringArray} */ const validateStringArray = hideStackFrames((value, name) => { validateArray(value, name); for (let i = 0; i < value.length; ++i) { // Don't use validateString here for performance reasons, as // we would generate intermediate strings for the name. if (typeof value[i] !== "string") { throw new codes.ERR_INVALID_ARG_TYPE(`${name}[${i}]`, "string", value[i]); } } }); /** * @callback validateBooleanArray * @param {*} value * @param {string} name * @returns {asserts value is boolean[]} */ /** @type {validateBooleanArray} */ const validateBooleanArray = hideStackFrames((value, name) => { validateArray(value, name); for (let i = 0; i < value.length; ++i) { // Don't use validateBoolean here for performance reasons, as // we would generate intermediate strings for the name. if (value[i] !== true && value[i] !== false) { throw new codes.ERR_INVALID_ARG_TYPE( `${name}[${i}]`, "boolean", value[i], ); } } }); function validateUnion(value, name, union) { if (!ArrayPrototypeIncludes(union, value)) { throw new codes.ERR_INVALID_ARG_TYPE( name, `('${ArrayPrototypeJoin(union, "|")}')`, value, ); } } const validateFiniteNumber = hideStackFrames((number, name) => { // Common case if (number === undefined) { return false; } if (NumberIsFinite(number)) { return true; // Is a valid number } if (NumberIsNaN(number)) { return false; } validateNumber(number, name); // Infinite numbers throw new codes.ERR_OUT_OF_RANGE(name, "a finite number", number); }); const checkRangesOrGetDefault = hideStackFrames( (number, name, lower, upper, def) => { if (!validateFiniteNumber(number, name)) { return def; } if (number < lower || number > upper) { throw new codes.ERR_OUT_OF_RANGE( name, `>= ${lower} and <= ${upper}`, number, ); } return number; }, ); const linkValueRegExp = new SafeRegExp("^(?:<[^>]*>)(?:\\s*;\\s*[^;]*)*$"); const validateLinkHeaderFormat = hideStackFrames((value, name) => { if ( typeof value === "undefined" || !RegExpPrototypeTest(linkValueRegExp, value) ) { throw new codes.ERR_INVALID_ARG_VALUE( name, value, 'must be an array or string of format "</styles.css>; rel=preload; as=style"', ); } }); const validateLinkHeaderValue = hideStackFrames((hints) => { if (typeof hints === "string") { validateLinkHeaderFormat(hints, "hints"); return hints; } else if (ArrayIsArray(hints)) { const hintsLength = hints.length; let result = ""; if (hintsLength === 0) { return result; } for (let i = 0; i < hintsLength; i++) { const link = hints[i]; validateLinkHeaderFormat(link, "hints"); result += link; if (i !== hintsLength - 1) { result += ", "; } } return result; } throw new codes.ERR_INVALID_ARG_VALUE( "hints", hints, 'must be an array or string of format "</styles.css>; rel=preload; as=style"', ); }); return { default: { isInt32, isUint32, parseFileMode, validateAbortSignal, validateArray, validateBoolean, validateBooleanArray, validateBuffer, validateFunction, validateInt32, validateInteger, validateNumber, validateObject, validateOneOf, validatePort, validateString, validateStringArray, validateStringWithoutNullBytes, validateUint32, validateUnion, validateFiniteNumber, validateLinkHeaderValue, checkRangesOrGetDefault, }, checkRangesOrGetDefault, isInt32, isUint32, parseFileMode, validateAbortSignal, validateArray, validateBoolean, validateBooleanArray, validateBuffer, validateEncoding, validateFiniteNumber, validateFunction, validateInt32, validateInteger, validateLinkHeaderValue, validateNumber, validateObject, validateOneOf, validatePort, validateString, validateStringArray, validateStringWithoutNullBytes, validateUint32, validateUnion, }; })();