mirror of
https://github.com/nodejs/node.git
synced 2025-04-30 15:41:06 +00:00
process: remove process.exit()
, process.exitCode
coercion to integer
This removes the deprecation, `DEP0164` and validates the exit code for both `process.exit([code])` and `process.exitCode`. Signed-off-by: Daeyeon Jeong <daeyeon.dev@gmail.com> PR-URL: https://github.com/nodejs/node/pull/43716 Refs: https://github.com/nodejs/node/pull/43738 Refs: https://github.com/nodejs/node/pull/44714 Refs: https://github.com/nodejs/node/pull/44711 Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: Darshan Sen <raisinten@gmail.com>
This commit is contained in:
parent
19f3973828
commit
2d0d99733b
@ -3178,6 +3178,9 @@ thing instead.
|
||||
|
||||
<!-- YAML
|
||||
changes:
|
||||
- version: REPLACEME
|
||||
pr-url: https://github.com/nodejs/node/pull/43716
|
||||
description: End-of-Life.
|
||||
- version: v19.0.0
|
||||
pr-url: https://github.com/nodejs/node/pull/44711
|
||||
description: Runtime deprecation.
|
||||
@ -3195,7 +3198,7 @@ changes:
|
||||
coercion.
|
||||
-->
|
||||
|
||||
Type: Runtime
|
||||
Type: End-of-Life
|
||||
|
||||
Values other than `undefined`, `null`, integer numbers, and integer strings
|
||||
(e.g., `'1'`) are deprecated as value for the `code` parameter in
|
||||
|
@ -1708,9 +1708,15 @@ that started the Node.js process. Symbolic links, if any, are resolved.
|
||||
|
||||
<!-- YAML
|
||||
added: v0.1.13
|
||||
changes:
|
||||
- version: REPLACEME
|
||||
pr-url: https://github.com/nodejs/node/pull/43716
|
||||
description: Only accepts a code of type number, or of type string if it
|
||||
represents an integer.
|
||||
-->
|
||||
|
||||
* `code` {integer} The exit code. **Default:** `0`.
|
||||
* `code` {integer|string|null|undefined} The exit code. For string type, only
|
||||
integer strings (e.g.,'1') are allowed. **Default:** `0`.
|
||||
|
||||
The `process.exit()` method instructs Node.js to terminate the process
|
||||
synchronously with an exit status of `code`. If `code` is omitted, exit uses
|
||||
@ -1810,9 +1816,15 @@ than the current process.
|
||||
|
||||
<!-- YAML
|
||||
added: v0.11.8
|
||||
changes:
|
||||
- version: REPLACEME
|
||||
pr-url: https://github.com/nodejs/node/pull/43716
|
||||
description: Only accepts a code of type number, or of type string if it
|
||||
represents an integer.
|
||||
-->
|
||||
|
||||
* {integer}
|
||||
* {integer|string|null|undefined} The exit code. For string type, only
|
||||
integer strings (e.g.,'1') are allowed. **Default:** `undefined`.
|
||||
|
||||
A number which will be the process exit code, when the process either
|
||||
exits gracefully, or is exited via [`process.exit()`][] without specifying
|
||||
|
@ -60,6 +60,8 @@ const {
|
||||
ArrayPrototypeFill,
|
||||
FunctionPrototypeCall,
|
||||
JSONParse,
|
||||
Number,
|
||||
NumberIsNaN,
|
||||
ObjectDefineProperty,
|
||||
ObjectGetPrototypeOf,
|
||||
ObjectSetPrototypeOf,
|
||||
@ -74,6 +76,9 @@ const {
|
||||
deprecate,
|
||||
exposeInterface,
|
||||
} = require('internal/util');
|
||||
const {
|
||||
validateInteger,
|
||||
} = require('internal/validators');
|
||||
const {
|
||||
exiting_aliased_Uint32Array,
|
||||
getHiddenValue,
|
||||
@ -103,12 +108,6 @@ process.domain = null;
|
||||
process._exiting = false;
|
||||
|
||||
{
|
||||
const warnIntegerCoercionDeprecation = deprecate(
|
||||
() => {},
|
||||
'Implicit coercion to integer for exit code is deprecated.',
|
||||
'DEP0164'
|
||||
);
|
||||
|
||||
let exitCode;
|
||||
|
||||
ObjectDefineProperty(process, 'exitCode', {
|
||||
@ -117,8 +116,13 @@ process._exiting = false;
|
||||
return exitCode;
|
||||
},
|
||||
set(code) {
|
||||
if (perThreadSetup.isDeprecatedExitCode(code)) {
|
||||
warnIntegerCoercionDeprecation();
|
||||
if (code !== null && code !== undefined) {
|
||||
let value = code;
|
||||
if (typeof code === 'string' && code !== '' &&
|
||||
NumberIsNaN((value = Number(code)))) {
|
||||
value = code;
|
||||
}
|
||||
validateInteger(value, 'code');
|
||||
}
|
||||
exitCode = code;
|
||||
},
|
||||
|
@ -13,10 +13,7 @@ const {
|
||||
ArrayPrototypeSplice,
|
||||
BigUint64Array,
|
||||
Float64Array,
|
||||
Number,
|
||||
NumberIsInteger,
|
||||
NumberMAX_SAFE_INTEGER,
|
||||
NumberMIN_SAFE_INTEGER,
|
||||
ObjectFreeze,
|
||||
ObjectDefineProperty,
|
||||
ReflectApply,
|
||||
@ -183,25 +180,12 @@ function wrapProcessMethods(binding) {
|
||||
|
||||
memoryUsage.rss = rss;
|
||||
|
||||
const { deprecate } = require('internal/util');
|
||||
const warnIntegerCoercionDeprecationSync = deprecate(
|
||||
() => {},
|
||||
'Implicit coercion to integer for exit code is deprecated.',
|
||||
'DEP0164',
|
||||
true
|
||||
);
|
||||
|
||||
function exit(code) {
|
||||
process.off('exit', handleProcessExit);
|
||||
|
||||
if (isDeprecatedExitCode(code)) {
|
||||
// Emit the deprecation warning synchronously since deprecation warning is
|
||||
// generally emitted in a next tick but we have no next tick timing here.
|
||||
warnIntegerCoercionDeprecationSync();
|
||||
}
|
||||
|
||||
if (code || code === 0)
|
||||
if (arguments.length !== 0) {
|
||||
process.exitCode = code;
|
||||
}
|
||||
|
||||
if (!process._exiting) {
|
||||
process._exiting = true;
|
||||
@ -424,23 +408,6 @@ function toggleTraceCategoryState(asyncHooksEnabled) {
|
||||
}
|
||||
}
|
||||
|
||||
function isDeprecatedExitCode(code) {
|
||||
if (code !== null && code !== undefined) {
|
||||
const value =
|
||||
typeof code === 'string' && code !== '' ? Number(code) : code;
|
||||
// Check if the value is an integer.
|
||||
if (
|
||||
typeof value !== 'number' ||
|
||||
!NumberIsInteger(value) ||
|
||||
value < NumberMIN_SAFE_INTEGER ||
|
||||
value > NumberMAX_SAFE_INTEGER
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
toggleTraceCategoryState,
|
||||
assert,
|
||||
@ -449,5 +416,4 @@ module.exports = {
|
||||
hrtime,
|
||||
hrtimeBigInt,
|
||||
refreshHrtimeBuffer,
|
||||
isDeprecatedExitCode,
|
||||
};
|
||||
|
@ -1,100 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
require('../common');
|
||||
|
||||
const deprecated = [
|
||||
{
|
||||
code: '',
|
||||
expected: 0,
|
||||
},
|
||||
{
|
||||
code: '1 one',
|
||||
expected: 0,
|
||||
},
|
||||
{
|
||||
code: 'two',
|
||||
expected: 0,
|
||||
},
|
||||
{
|
||||
code: {},
|
||||
expected: 0,
|
||||
},
|
||||
{
|
||||
code: [],
|
||||
expected: 0,
|
||||
},
|
||||
{
|
||||
code: true,
|
||||
expected: 1,
|
||||
},
|
||||
{
|
||||
code: false,
|
||||
expected: 0,
|
||||
},
|
||||
{
|
||||
code: 2n,
|
||||
expected: 0,
|
||||
expected_useProcessExitCode: 1,
|
||||
},
|
||||
{
|
||||
code: 2.1,
|
||||
expected: 2,
|
||||
},
|
||||
{
|
||||
code: Infinity,
|
||||
expected: 0,
|
||||
},
|
||||
{
|
||||
code: NaN,
|
||||
expected: 0,
|
||||
},
|
||||
];
|
||||
const args = deprecated;
|
||||
|
||||
if (process.argv[2] === undefined) {
|
||||
const { spawnSync } = require('node:child_process');
|
||||
const { inspect, debuglog } = require('node:util');
|
||||
const { strictEqual } = require('node:assert');
|
||||
|
||||
const debug = debuglog('test');
|
||||
const node = process.execPath;
|
||||
const test = (index, useProcessExitCode) => {
|
||||
const { status: code, stderr } = spawnSync(node, [
|
||||
__filename,
|
||||
index,
|
||||
useProcessExitCode,
|
||||
]);
|
||||
debug(`actual: ${code}, ${inspect(args[index])} ${!!useProcessExitCode}`);
|
||||
debug(`${stderr}`);
|
||||
|
||||
const expected =
|
||||
useProcessExitCode && args[index].expected_useProcessExitCode ?
|
||||
args[index].expected_useProcessExitCode :
|
||||
args[index].expected;
|
||||
|
||||
strictEqual(code, expected, `actual: ${code}, ${inspect(args[index])}`);
|
||||
strictEqual(
|
||||
['[DEP0164]'].some((pattern) => stderr.includes(pattern)),
|
||||
true
|
||||
);
|
||||
};
|
||||
|
||||
for (const index of args.keys()) {
|
||||
// Check `process.exit([code])`
|
||||
test(index);
|
||||
// Check exit with `process.exitCode`
|
||||
test(index, true);
|
||||
}
|
||||
} else {
|
||||
const index = parseInt(process.argv[2]);
|
||||
const useProcessExitCode = process.argv[3] !== 'undefined';
|
||||
if (Number.isNaN(index)) {
|
||||
return process.exit(100);
|
||||
}
|
||||
|
||||
if (useProcessExitCode) {
|
||||
process.exitCode = args[index].code;
|
||||
} else {
|
||||
process.exit(args[index].code);
|
||||
}
|
||||
}
|
143
test/parallel/test-process-exit-code-validation.js
Normal file
143
test/parallel/test-process-exit-code-validation.js
Normal file
@ -0,0 +1,143 @@
|
||||
'use strict';
|
||||
|
||||
require('../common');
|
||||
|
||||
const invalids = [
|
||||
{
|
||||
code: '',
|
||||
expected: 1,
|
||||
pattern: "Received type string \\(''\\)$",
|
||||
},
|
||||
{
|
||||
code: '1 one',
|
||||
expected: 1,
|
||||
pattern: "Received type string \\('1 one'\\)$",
|
||||
},
|
||||
{
|
||||
code: 'two',
|
||||
expected: 1,
|
||||
pattern: "Received type string \\('two'\\)$",
|
||||
},
|
||||
{
|
||||
code: {},
|
||||
expected: 1,
|
||||
pattern: 'Received an instance of Object$',
|
||||
},
|
||||
{
|
||||
code: [],
|
||||
expected: 1,
|
||||
pattern: 'Received an instance of Array$',
|
||||
},
|
||||
{
|
||||
code: true,
|
||||
expected: 1,
|
||||
pattern: 'Received type boolean \\(true\\)$',
|
||||
},
|
||||
{
|
||||
code: false,
|
||||
expected: 1,
|
||||
pattern: 'Received type boolean \\(false\\)$',
|
||||
},
|
||||
{
|
||||
code: 2n,
|
||||
expected: 1,
|
||||
pattern: 'Received type bigint \\(2n\\)$',
|
||||
},
|
||||
{
|
||||
code: 2.1,
|
||||
expected: 1,
|
||||
pattern: 'Received 2.1$',
|
||||
},
|
||||
{
|
||||
code: Infinity,
|
||||
expected: 1,
|
||||
pattern: 'Received Infinity$',
|
||||
},
|
||||
{
|
||||
code: NaN,
|
||||
expected: 1,
|
||||
pattern: 'Received NaN$',
|
||||
},
|
||||
];
|
||||
const valids = [
|
||||
{
|
||||
code: 1,
|
||||
expected: 1,
|
||||
},
|
||||
{
|
||||
code: '2',
|
||||
expected: 2,
|
||||
},
|
||||
{
|
||||
code: undefined,
|
||||
expected: 0,
|
||||
},
|
||||
{
|
||||
code: null,
|
||||
expected: 0,
|
||||
},
|
||||
{
|
||||
code: 0,
|
||||
expected: 0,
|
||||
},
|
||||
{
|
||||
code: '0',
|
||||
expected: 0,
|
||||
},
|
||||
];
|
||||
const args = [...invalids, ...valids];
|
||||
|
||||
if (process.argv[2] === undefined) {
|
||||
const { spawnSync } = require('node:child_process');
|
||||
const { inspect, debuglog } = require('node:util');
|
||||
const { throws, strictEqual } = require('node:assert');
|
||||
|
||||
const debug = debuglog('test');
|
||||
const node = process.execPath;
|
||||
const test = (index, useProcessExitCode) => {
|
||||
const { status: code } = spawnSync(node, [
|
||||
__filename,
|
||||
index,
|
||||
useProcessExitCode,
|
||||
]);
|
||||
debug(`actual: ${code}, ${inspect(args[index])} ${!!useProcessExitCode}`);
|
||||
strictEqual(
|
||||
code,
|
||||
args[index].expected,
|
||||
`actual: ${code}, ${inspect(args[index])}`
|
||||
);
|
||||
};
|
||||
|
||||
// Check process.exitCode
|
||||
for (const arg of invalids) {
|
||||
debug(`invaild code: ${inspect(arg.code)}`);
|
||||
throws(() => (process.exitCode = arg.code), new RegExp(arg.pattern));
|
||||
}
|
||||
for (const arg of valids) {
|
||||
debug(`vaild code: ${inspect(arg.code)}`);
|
||||
process.exitCode = arg.code;
|
||||
}
|
||||
|
||||
throws(() => {
|
||||
delete process.exitCode;
|
||||
}, /Cannot delete property 'exitCode' of #<process>/);
|
||||
process.exitCode = 0;
|
||||
|
||||
// Check process.exit([code])
|
||||
for (const index of args.keys()) {
|
||||
test(index);
|
||||
test(index, true);
|
||||
}
|
||||
} else {
|
||||
const index = parseInt(process.argv[2]);
|
||||
const useProcessExitCode = process.argv[3] !== 'undefined';
|
||||
if (Number.isNaN(index)) {
|
||||
return process.exit(100);
|
||||
}
|
||||
|
||||
if (useProcessExitCode) {
|
||||
process.exitCode = args[index].code;
|
||||
} else {
|
||||
process.exit(args[index].code);
|
||||
}
|
||||
}
|
@ -33,7 +33,7 @@ if (isMainThread) {
|
||||
assert.strictEqual(headers[':status'], 200);
|
||||
}));
|
||||
|
||||
req.on('data', common.mustCall(process.exit));
|
||||
req.on('data', common.mustCall(() => process.exit()));
|
||||
req.on('end', common.mustNotCall());
|
||||
req.end();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user