diff --git a/lib/internal/validators.js b/lib/internal/validators.js index 079ab3d2f53c20..1d656c3d65233e 100644 --- a/lib/internal/validators.js +++ b/lib/internal/validators.js @@ -1,6 +1,7 @@ 'use strict'; const { + ArrayIsArray, NumberIsInteger, NumberMAX_SAFE_INTEGER, NumberMIN_SAFE_INTEGER, @@ -123,6 +124,30 @@ function validateNumber(value, name) { throw new ERR_INVALID_ARG_TYPE(name, 'number', value); } +function validateBoolean(value, name) { + if (typeof value !== 'boolean') + throw new ERR_INVALID_ARG_TYPE(name, 'boolean', value); +} + +const validateObject = hideStackFrames( + (value, name, { nullable = false } = {}) => { + if ((!nullable && value === null) || + ArrayIsArray(value) || + typeof value !== 'object') { + throw new ERR_INVALID_ARG_TYPE(name, 'Object', value); + } + }); + +const validateArray = hideStackFrames((value, name, { minLength = 0 } = {}) => { + if (!ArrayIsArray(value)) { + throw new ERR_INVALID_ARG_TYPE(name, 'Array', value); + } + if (value.length < minLength) { + const reason = `must be longer than ${minLength}`; + throw new ERR_INVALID_ARG_VALUE(name, value, reason); + } +}); + function validateSignalName(signal, name = 'signal') { if (typeof signal !== 'string') throw new ERR_INVALID_ARG_TYPE(name, 'string', signal); @@ -159,8 +184,11 @@ module.exports = { isInt32, isUint32, parseMode, + validateArray, + validateBoolean, validateBuffer, validateEncoding, + validateObject, validateInteger, validateInt32, validateUint32, diff --git a/test/parallel/test-validators.js b/test/parallel/test-validators.js index 76b10a9abed13f..1c36cc17ec046b 100644 --- a/test/parallel/test-validators.js +++ b/test/parallel/test-validators.js @@ -1,26 +1,87 @@ // Flags: --expose-internals 'use strict'; + require('../common'); const assert = require('assert'); const { - validateInteger + validateArray, + validateBoolean, + validateInteger, + validateObject, } = require('internal/validators'); const { MAX_SAFE_INTEGER, MIN_SAFE_INTEGER } = Number; const outOfRangeError = { code: 'ERR_OUT_OF_RANGE', - name: 'RangeError' + name: 'RangeError', +}; +const invalidArgTypeError = { + code: 'ERR_INVALID_ARG_TYPE', + name: 'TypeError', }; +const invalidArgValueError = { + code: 'ERR_INVALID_ARG_VALUE', + name: 'TypeError', +}; + +{ + // validateInteger tests. + + // validateInteger() defaults to validating safe integers. + validateInteger(MAX_SAFE_INTEGER, 'foo'); + validateInteger(MIN_SAFE_INTEGER, 'foo'); + assert.throws(() => { + validateInteger(MAX_SAFE_INTEGER + 1, 'foo'); + }, outOfRangeError); + assert.throws(() => { + validateInteger(MIN_SAFE_INTEGER - 1, 'foo'); + }, outOfRangeError); + + // validateInteger() works with unsafe integers. + validateInteger(MAX_SAFE_INTEGER + 1, 'foo', 0, MAX_SAFE_INTEGER + 1); + validateInteger(MIN_SAFE_INTEGER - 1, 'foo', MIN_SAFE_INTEGER - 1); +} + +{ + // validateArray tests. + validateArray([], 'foo'); + validateArray([1, 2, 3], 'foo'); + + [undefined, null, true, false, 0, 0.0, 42, '', 'string', {}] + .forEach((val) => { + assert.throws(() => { + validateArray(val, 'foo'); + }, invalidArgTypeError); + }); + + validateArray([1], 'foo', { minLength: 1 }); + assert.throws(() => { + validateArray([], 'foo', { minLength: 1 }); + }, invalidArgValueError); +} + +{ + // validateBoolean tests. + validateBoolean(true, 'foo'); + validateBoolean(false, 'foo'); + + [undefined, null, 0, 0.0, 42, '', 'string', {}, []].forEach((val) => { + assert.throws(() => { + validateBoolean(val, 'foo'); + }, invalidArgTypeError); + }); +} + +{ + // validateObject tests. + validateObject({}, 'foo'); + validateObject({ a: 42, b: 'foo' }, 'foo'); + + [undefined, null, true, false, 0, 0.0, 42, '', 'string', []] + .forEach((val) => { + assert.throws(() => { + validateObject(val, 'foo'); + }, invalidArgTypeError); + }); -// validateInteger() defaults to validating safe integers. -validateInteger(MAX_SAFE_INTEGER, 'foo'); -validateInteger(MIN_SAFE_INTEGER, 'foo'); -assert.throws(() => { - validateInteger(MAX_SAFE_INTEGER + 1, 'foo'); -}, outOfRangeError); -assert.throws(() => { - validateInteger(MIN_SAFE_INTEGER - 1, 'foo'); -}, outOfRangeError); - -// validateInteger() works with unsafe integers. -validateInteger(MAX_SAFE_INTEGER + 1, 'foo', 0, MAX_SAFE_INTEGER + 1); -validateInteger(MIN_SAFE_INTEGER - 1, 'foo', MIN_SAFE_INTEGER - 1); + validateObject(null, 'foo', { nullable: true }); +}