Repository: nodejs/node
Pull request: lib: use validators for argument validation

This refactors internal validation helpers in `child_process` to use the common validators in `lib/internal/validators.js` where possible.

This improves code consistency and maintainability.

<!--
Before submitting a pull request, please read:

- the CONTRIBUTING guide at https://github.com/nodejs/node/blob/HEAD/CONTRIBUTING.md
- the commit message formatting guidelines at
  https://github.com/nodejs/node/blob/HEAD/doc/contributing/pull-requests.md#commit-message-guidelines

For code changes:
1. Include tests for any bug fixes or new features.
2. Update documentation if relevant.
3. Ensure that `make -j4 test` (UNIX), or `vcbuild test` (Windows) passes.

If you believe this PR should be highlighted in the Node.js CHANGELOG
please add the `notable-change` label.

Developer's Certificate of Origin 1.1

By making a contribution to this project, I certify that:

(a) The contribution was created in whole or in part by me and I
    have the right to submit it under the open source license
    indicated in the file; or

(b) The contribution is based upon previous work that, to the best
    of my knowledge, is covered under an appropriate open source
    license and I have the right under that license to submit that
    work with modifications, whether created in whole or in part
    by me, under the same open source license (unless I am
    permitted to submit under a different license), as indicated
    in the file; or

(c) The contribution was provided directly to me by some other
    person who certified (a), (b) or (c) and I have not modified
    it.

(d) I understand and agree that this project and the contribution
    are public and that a record of the contribution (including all
    personal information I submit with it, including my sign-off) is
    maintained indefinitely and may be redistributed consistent with
    this project or the open source license(s) involved.
-->


Changed files:
filename: lib/child_process.js
patch: @@ -33,7 +33,6 @@ const {
   ArrayPrototypeSort,
   ArrayPrototypeSplice,
   ArrayPrototypeUnshift,
-  NumberIsInteger,
   ObjectAssign,
   ObjectDefineProperty,
   ObjectPrototypeHasOwnProperty,
@@ -70,18 +69,19 @@ const {
     ERR_CHILD_PROCESS_STDIO_MAXBUFFER,
     ERR_INVALID_ARG_TYPE,
     ERR_INVALID_ARG_VALUE,
-    ERR_OUT_OF_RANGE,
   },
   genericNodeError,
 } = require('internal/errors');
 const { clearTimeout, setTimeout } = require('timers');
 const { getValidatedPath } = require('internal/fs/utils');
 const {
-  isInt32,
   validateAbortSignal,
   validateArray,
   validateBoolean,
   validateFunction,
+  validateInteger,
+  validateInt32,
+  validateNumber,
   validateObject,
   validateString,
 } = require('internal/validators');
@@ -603,13 +603,13 @@ function normalizeSpawnArguments(file, args, options) {
   }
 
   // Validate the uid, if present.
-  if (options.uid != null && !isInt32(options.uid)) {
-    throw new ERR_INVALID_ARG_TYPE('options.uid', 'int32', options.uid);
+  if (options.uid != null) {
+    validateInt32(options.uid, 'options.uid');
   }
 
   // Validate the gid, if present.
-  if (options.gid != null && !isInt32(options.gid)) {
-    throw new ERR_INVALID_ARG_TYPE('options.gid', 'int32', options.gid);
+  if (options.gid != null) {
+    validateInt32(options.gid, 'options.gid');
   }
 
   // Validate the shell, if present.
@@ -1018,17 +1018,15 @@ function validateArgumentsNullCheck(args, propName) {
 
 
 function validateTimeout(timeout) {
-  if (timeout != null && !(NumberIsInteger(timeout) && timeout >= 0)) {
-    throw new ERR_OUT_OF_RANGE('timeout', 'an unsigned integer', timeout);
+  if (timeout != null) {
+    validateInteger(timeout, 'timeout', 0);
   }
 }
 
 
 function validateMaxBuffer(maxBuffer) {
-  if (maxBuffer != null && !(typeof maxBuffer === 'number' && maxBuffer >= 0)) {
-    throw new ERR_OUT_OF_RANGE('options.maxBuffer',
-                               'a positive number',
-                               maxBuffer);
+  if (maxBuffer != null) {
+    validateNumber(maxBuffer, 'options.maxBuffer', 0);
   }
 }
 

filename: test/parallel/test-child-process-fork-timeout-kill-signal.js
patch: @@ -27,11 +27,11 @@ const { getEventListeners } = require('events');
   // Verify timeout verification
   throws(() => fork(fixtures.path('child-process-stay-alive-forever.js'), {
     timeout: 'badValue',
-  }), /ERR_OUT_OF_RANGE/);
+  }), /ERR_INVALID_ARG_TYPE/);
 
   throws(() => fork(fixtures.path('child-process-stay-alive-forever.js'), {
     timeout: {},
-  }), /ERR_OUT_OF_RANGE/);
+  }), /ERR_INVALID_ARG_TYPE/);
 }
 
 {

filename: test/parallel/test-child-process-spawn-timeout-kill-signal.js
patch: @@ -28,11 +28,11 @@ const aliveForeverFile = 'child-process-stay-alive-forever.js';
   // Verify timeout verification
   throws(() => spawn(process.execPath, [fixtures.path(aliveForeverFile)], {
     timeout: 'badValue',
-  }), /ERR_OUT_OF_RANGE/);
+  }), /ERR_INVALID_ARG_TYPE/);
 
   throws(() => spawn(process.execPath, [fixtures.path(aliveForeverFile)], {
     timeout: {},
-  }), /ERR_OUT_OF_RANGE/);
+  }), /ERR_INVALID_ARG_TYPE/);
 }
 
 {

filename: test/parallel/test-child-process-spawn-typeerror.js
patch: @@ -39,6 +39,8 @@ const invalidArgTypeError = {
   name: 'TypeError'
 };
 
+const invalidRangeError = { code: 'ERR_OUT_OF_RANGE', name: 'RangeError' };
+
 assert.throws(function() {
   spawn(invalidcmd, 'this is not an array');
 }, invalidArgTypeError);
@@ -77,11 +79,11 @@ assert.throws(function() {
 
 assert.throws(function() {
   spawn(cmd, [], { uid: 2 ** 63 });
-}, invalidArgTypeError);
+}, invalidRangeError);
 
 assert.throws(function() {
   spawn(cmd, [], { gid: 2 ** 63 });
-}, invalidArgTypeError);
+}, invalidRangeError);
 
 // Argument types for combinatorics.
 const a = [];

filename: test/parallel/test-child-process-spawnsync-validation-errors.js
patch: @@ -64,10 +64,10 @@ if (!common.isWindows) {
       fail('uid', [], invalidArgTypeError);
       fail('uid', {}, invalidArgTypeError);
       fail('uid', common.mustNotCall(), invalidArgTypeError);
-      fail('uid', NaN, invalidArgTypeError);
-      fail('uid', Infinity, invalidArgTypeError);
-      fail('uid', 3.1, invalidArgTypeError);
-      fail('uid', -3.1, invalidArgTypeError);
+      fail('uid', NaN, invalidRangeError);
+      fail('uid', Infinity, invalidRangeError);
+      fail('uid', 3.1, invalidRangeError);
+      fail('uid', -3.1, invalidRangeError);
     }
   }
 
@@ -83,10 +83,10 @@ if (!common.isWindows) {
       fail('gid', [], invalidArgTypeError);
       fail('gid', {}, invalidArgTypeError);
       fail('gid', common.mustNotCall(), invalidArgTypeError);
-      fail('gid', NaN, invalidArgTypeError);
-      fail('gid', Infinity, invalidArgTypeError);
-      fail('gid', 3.1, invalidArgTypeError);
-      fail('gid', -3.1, invalidArgTypeError);
+      fail('gid', NaN, invalidRangeError);
+      fail('gid', Infinity, invalidRangeError);
+      fail('gid', 3.1, invalidRangeError);
+      fail('gid', -3.1, invalidRangeError);
     }
   }
 }
@@ -152,12 +152,12 @@ if (!common.isWindows) {
   pass('timeout', 1);
   pass('timeout', 0);
   fail('timeout', -1, invalidRangeError);
-  fail('timeout', true, invalidRangeError);
-  fail('timeout', false, invalidRangeError);
-  fail('timeout', __dirname, invalidRangeError);
-  fail('timeout', [], invalidRangeError);
-  fail('timeout', {}, invalidRangeError);
-  fail('timeout', common.mustNotCall(), invalidRangeError);
+  fail('timeout', true, invalidArgTypeError);
+  fail('timeout', false, invalidArgTypeError);
+  fail('timeout', __dirname, invalidArgTypeError);
+  fail('timeout', [], invalidArgTypeError);
+  fail('timeout', {}, invalidArgTypeError);
+  fail('timeout', common.mustNotCall(), invalidArgTypeError);
   fail('timeout', NaN, invalidRangeError);
   fail('timeout', Infinity, invalidRangeError);
   fail('timeout', 3.1, invalidRangeError);
@@ -175,12 +175,12 @@ if (!common.isWindows) {
   fail('maxBuffer', -1, invalidRangeError);
   fail('maxBuffer', NaN, invalidRangeError);
   fail('maxBuffer', -Infinity, invalidRangeError);
-  fail('maxBuffer', true, invalidRangeError);
-  fail('maxBuffer', false, invalidRangeError);
-  fail('maxBuffer', __dirname, invalidRangeError);
-  fail('maxBuffer', [], invalidRangeError);
-  fail('maxBuffer', {}, invalidRangeError);
-  fail('maxBuffer', common.mustNotCall(), invalidRangeError);
+  fail('maxBuffer', true, invalidArgTypeError);
+  fail('maxBuffer', false, invalidArgTypeError);
+  fail('maxBuffer', __dirname, invalidArgTypeError);
+  fail('maxBuffer', [], invalidArgTypeError);
+  fail('maxBuffer', {}, invalidArgTypeError);
+  fail('maxBuffer', common.mustNotCall(), invalidArgTypeError);
 }
 
 {