Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lib: improve hideStackFrames intellisense #44181

Merged
merged 11 commits into from
Aug 17, 2022
5 changes: 3 additions & 2 deletions lib/internal/errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -392,8 +392,9 @@ function makeNodeErrorWithCode(Base, key) {

/**
* This function removes unnecessary frames from Node.js core errors.
* @template {(...args: any[]) => any} T
* @type {(fn: T) => T}
* @template {(...args: unknown[]) => unknown} T
* @param {T} fn
* @returns {T}
*/
function hideStackFrames(fn) {
// We rename the functions that will be hidden to cut off the stacktrace
Expand Down
154 changes: 149 additions & 5 deletions lib/internal/validators.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,18 @@ const {
} = require('internal/util/types');
const { signals } = internalBinding('constants').os;

/**
* @param {number} value
anonrig marked this conversation as resolved.
Show resolved Hide resolved
* @returns {boolean}
anonrig marked this conversation as resolved.
Show resolved Hide resolved
*/
aduh95 marked this conversation as resolved.
Show resolved Hide resolved
function isInt32(value) {
return value === (value | 0);
}

/**
* @param {number} value
* @returns {boolean}
anonrig marked this conversation as resolved.
Show resolved Hide resolved
*/
aduh95 marked this conversation as resolved.
Show resolved Hide resolved
function isUint32(value) {
return value === (value >>> 0);
}
Expand Down Expand Up @@ -70,6 +78,16 @@ function parseFileMode(value, name, def) {
return value;
}

/**
* @callback validateInteger
* @param {*} value
* @param {string} name
* @param {number} [min]
* @param {number} [max]
* @returns {asserts value is number}
*/

/** @type {validateInteger} */
const validateInteger = hideStackFrames(
(value, name, min = NumberMIN_SAFE_INTEGER, max = NumberMAX_SAFE_INTEGER) => {
if (typeof value !== 'number')
Expand All @@ -81,6 +99,16 @@ const validateInteger = hideStackFrames(
}
);

/**
* @callback validateInt32
* @param {*} value
* @param {string} name
* @param {number} [min]
* @param {number} [max]
* @returns {asserts value is number}
*/

/** @type {validateInt32} */
const validateInt32 = hideStackFrames(
(value, name, min = -2147483648, max = 2147483647) => {
// The defaults for min and max correspond to the limits of 32-bit integers.
Expand All @@ -96,7 +124,16 @@ const validateInt32 = hideStackFrames(
}
);

const validateUint32 = hideStackFrames((value, name, positive) => {
/**
* @callback validateUint32
* @param {*} value
* @param {string} name
* @param {number|boolean} [positive=false]
* @returns {asserts value is number}
*/

/** @type {validateUint32} */
const validateUint32 = hideStackFrames((value, name, positive = false) => {
if (typeof value !== 'number') {
throw new ERR_INVALID_ARG_TYPE(name, 'number', value);
}
Expand All @@ -111,11 +148,29 @@ const validateUint32 = hideStackFrames((value, name, positive) => {
}
});

/**
* @callback validateString
* @param {*} value
* @param {string} name
* @returns {asserts value is string}
*/

/** @type {validateString} */
function validateString(value, name) {
if (typeof value !== 'string')
throw new ERR_INVALID_ARG_TYPE(name, 'string', value);
}

/**
* @callback validateNumber
* @param {*} value
* @param {string} name
* @param {number} [min]
* @param {number} [max]
* @returns {asserts value is number}
*/

/** @type {validateNumber} */
function validateNumber(value, name, min = undefined, max) {
if (typeof value !== 'number')
throw new ERR_INVALID_ARG_TYPE(name, 'number', value);
Expand All @@ -129,6 +184,15 @@ function validateNumber(value, name, min = undefined, max) {
}
}

/**
* @callback validateOneOf
* @template T
* @param {T} value
* @param {string} name
* @param {T[]} oneOf
*/

/** @type {validateOneOf} */
const validateOneOf = hideStackFrames((value, name, oneOf) => {
if (!ArrayPrototypeIncludes(oneOf, value)) {
const allowed = ArrayPrototypeJoin(
Expand All @@ -140,6 +204,14 @@ const validateOneOf = hideStackFrames((value, name, oneOf) => {
}
});

/**
* @callback validateBoolean
* @param {*} value
* @param {string} name
* @returns {asserts value is boolean}
*/

/** @type {validateBoolean} */
function validateBoolean(value, name) {
if (typeof value !== 'boolean')
throw new ERR_INVALID_ARG_TYPE(name, 'boolean', value);
Expand All @@ -152,16 +224,19 @@ function getOwnPropertyValueOrDefault(options, key, defaultValue) {
}

/**
* @param {unknown} value
* @callback validateObject
* @param {*} value
* @param {string} name
* @param {{
* allowArray?: boolean,
* allowFunction?: boolean,
* nullable?: boolean
* }} [options]
*/

/** @type {validateObject} */
const validateObject = hideStackFrames(
(value, name, options) => {
(value, name, options = null) => {
const allowArray = getOwnPropertyValueOrDefault(options, 'allowArray', false);
const allowFunction = getOwnPropertyValueOrDefault(options, 'allowFunction', false);
const nullable = getOwnPropertyValueOrDefault(options, 'nullable', false);
Expand All @@ -174,6 +249,15 @@ const validateObject = hideStackFrames(
}
});

/**
* @callback validateArray
* @param {*} value
* @param {string} name
* @param {number} [minLength]
* @returns {asserts value is any[]}
*/

/** @type {validateArray} */
const validateArray = hideStackFrames((value, name, minLength = 0) => {
if (!ArrayIsArray(value)) {
throw new ERR_INVALID_ARG_TYPE(name, 'Array', value);
Expand All @@ -184,6 +268,12 @@ const validateArray = hideStackFrames((value, name, minLength = 0) => {
}
});

// eslint-disable-next-line jsdoc/require-returns-check
/**
* @param {*} signal
* @param {string} [name='signal']
* @returns {asserts signal is keyof signals}
*/
function validateSignalName(signal, name = 'signal') {
validateString(signal, name);

Expand All @@ -197,6 +287,13 @@ function validateSignalName(signal, name = 'signal') {
}
}

/**
* @callback validateBuffer
* @param {*} buffer
* @param {string} [name='buffer']
anonrig marked this conversation as resolved.
Show resolved Hide resolved
*/

/** @type {validateBuffer} */
const validateBuffer = hideStackFrames((buffer, name = 'buffer') => {
if (!isArrayBufferView(buffer)) {
throw new ERR_INVALID_ARG_TYPE(name,
Expand All @@ -205,6 +302,10 @@ const validateBuffer = hideStackFrames((buffer, name = 'buffer') => {
}
});

/**
* @param {string} data
* @param {string} encoding
*/
function validateEncoding(data, encoding) {
const normalizedEncoding = normalizeEncoding(encoding);
const length = data.length;
Expand All @@ -215,8 +316,14 @@ function validateEncoding(data, encoding) {
}
}

// 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.
/**
* 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 {*} port
* @param {string} [name='Port']
* @param {boolean} [allowZero=true]
* @returns {number}
*/
aduh95 marked this conversation as resolved.
Show resolved Hide resolved
function validatePort(port, name = 'Port', allowZero = true) {
if ((typeof port !== 'number' && typeof port !== 'string') ||
(typeof port === 'string' && StringPrototypeTrim(port).length === 0) ||
Expand All @@ -228,6 +335,13 @@ function validatePort(port, name = 'Port', allowZero = true) {
return port | 0;
}

/**
* @callback validateAbortSignal
* @param {*} signal
* @param {string} name
*/
anonrig marked this conversation as resolved.
Show resolved Hide resolved

/** @type {validateAbortSignal} */
const validateAbortSignal = hideStackFrames((signal, name) => {
if (signal !== undefined &&
(signal === null ||
Expand All @@ -237,21 +351,51 @@ const validateAbortSignal = hideStackFrames((signal, name) => {
}
});

/**
* @callback validateFunction
* @param {*} value
* @param {string} name
* @returns {asserts value is Function}
*/

/** @type {validateFunction} */
const validateFunction = hideStackFrames((value, name) => {
if (typeof value !== 'function')
throw new ERR_INVALID_ARG_TYPE(name, 'Function', value);
});

/**
* @callback validatePlainFunction
* @param {*} value
* @param {string} name
* @returns {asserts value is Function}
*/

/** @type {validatePlainFunction} */
const validatePlainFunction = hideStackFrames((value, name) => {
if (typeof value !== 'function' || isAsyncFunction(value))
throw new ERR_INVALID_ARG_TYPE(name, 'Function', value);
});

/**
* @callback validateUndefined
* @param {*} value
* @param {string} name
* @returns {asserts value is undefined}
*/

/** @type {validateUndefined} */
const validateUndefined = hideStackFrames((value, name) => {
if (value !== undefined)
throw new ERR_INVALID_ARG_TYPE(name, 'undefined', value);
});

/**
* @template T
* @param {T} value
* @param {string} name
* @param {T[]} union
*/
function validateUnion(value, name, union) {
if (!ArrayPrototypeIncludes(union, value)) {
throw new ERR_INVALID_ARG_TYPE(name, `('${ArrayPrototypeJoin(union, '|')}')`, value);
Expand Down