From 2571c08f998b75fc5e971a358c823746e5ba7eb2 Mon Sep 17 00:00:00 2001 From: Gang Chen Date: Mon, 3 Jan 2022 23:54:03 +0800 Subject: [PATCH] module: `process.exit()` should result in exit code 0 --- .../modules/esm/handle_process_exit.js | 10 ++++++++++ lib/internal/modules/run_main.js | 9 +++------ lib/internal/process/per_thread.js | 4 ++++ test/es-module/test-esm-tla-unfinished.mjs | 19 +++++++++++++++++++ test/fixtures/es-modules/tla/process-exit.mjs | 1 + .../unresolved-with-worker-process-exit.mjs | 10 ++++++++++ 6 files changed, 47 insertions(+), 6 deletions(-) create mode 100644 lib/internal/modules/esm/handle_process_exit.js create mode 100644 test/fixtures/es-modules/tla/process-exit.mjs create mode 100644 test/fixtures/es-modules/tla/unresolved-with-worker-process-exit.mjs diff --git a/lib/internal/modules/esm/handle_process_exit.js b/lib/internal/modules/esm/handle_process_exit.js new file mode 100644 index 00000000000000..f64f0128fa66f3 --- /dev/null +++ b/lib/internal/modules/esm/handle_process_exit.js @@ -0,0 +1,10 @@ +'use strict'; + +function handleProcessExit() { + if (process.exitCode === undefined) + process.exitCode = 13; +} + +module.exports = { + handleProcessExit, +} \ No newline at end of file diff --git a/lib/internal/modules/run_main.js b/lib/internal/modules/run_main.js index 9a0263024144fb..4dda238a731e12 100644 --- a/lib/internal/modules/run_main.js +++ b/lib/internal/modules/run_main.js @@ -8,6 +8,7 @@ const CJSLoader = require('internal/modules/cjs/loader'); const { Module, toRealPath, readPackageScope } = CJSLoader; const { getOptionValue } = require('internal/options'); const path = require('path'); +const { handleProcessExit } = require('internal/modules/esm/handle_process_exit'); function resolveMainPath(main) { // Note extension resolution for the main entry point can be deprecated in a @@ -56,15 +57,11 @@ async function handleMainPromise(promise) { // Handle a Promise from running code that potentially does Top-Level Await. // In that case, it makes sense to set the exit code to a specific non-zero // value if the main code never finishes running. - function handler() { - if (process.exitCode === undefined) - process.exitCode = 13; - } - process.on('exit', handler); + process.on('exit', handleProcessExit); try { return await promise; } finally { - process.off('exit', handler); + process.off('exit', handleProcessExit); } } diff --git a/lib/internal/process/per_thread.js b/lib/internal/process/per_thread.js index a63217d9b3955a..9f8f233bc8b44d 100644 --- a/lib/internal/process/per_thread.js +++ b/lib/internal/process/per_thread.js @@ -48,6 +48,8 @@ const { } = require('internal/validators'); const constants = internalBinding('constants').os.signals; +const { handleProcessExit } = require('internal/modules/esm/handle_process_exit'); + const kInternal = Symbol('internal properties'); function assert(x, msg) { @@ -175,6 +177,8 @@ function wrapProcessMethods(binding) { memoryUsage.rss = rss; function exit(code) { + process.off('exit', handleProcessExit); + if (code || code === 0) process.exitCode = code; diff --git a/test/es-module/test-esm-tla-unfinished.mjs b/test/es-module/test-esm-tla-unfinished.mjs index 7d35c86285ac81..84ed3ed7d6b56c 100644 --- a/test/es-module/test-esm-tla-unfinished.mjs +++ b/test/es-module/test-esm-tla-unfinished.mjs @@ -80,3 +80,22 @@ import fixtures from '../common/fixtures.js'; assert.deepStrictEqual([status, stdout], [1, '']); assert.match(stderr, /Error: Xyz/); } + +{ + // calling process.exit() in .mjs should return status 0 + const { status, stdout, stderr } = child_process.spawnSync( + process.execPath, + [fixtures.path('es-modules/tla/process-exit.mjs')], + { encoding: 'utf8' }); + assert.deepStrictEqual([status, stdout, stderr], [0, '', '']); +} + +{ + // calling process.exit() in .mjs should return status 0 + const { status, stdout, stderr } = child_process.spawnSync( + process.execPath, + [fixtures.path('es-modules/tla/unresolved-with-worker-process-exit.mjs')], + { encoding: 'utf8' }); + assert.deepStrictEqual([status, stdout, stderr], [13, '', '']); +} + diff --git a/test/fixtures/es-modules/tla/process-exit.mjs b/test/fixtures/es-modules/tla/process-exit.mjs new file mode 100644 index 00000000000000..37dd593a2b4aae --- /dev/null +++ b/test/fixtures/es-modules/tla/process-exit.mjs @@ -0,0 +1 @@ +process.exit(); \ No newline at end of file diff --git a/test/fixtures/es-modules/tla/unresolved-with-worker-process-exit.mjs b/test/fixtures/es-modules/tla/unresolved-with-worker-process-exit.mjs new file mode 100644 index 00000000000000..3c0bc75167423a --- /dev/null +++ b/test/fixtures/es-modules/tla/unresolved-with-worker-process-exit.mjs @@ -0,0 +1,10 @@ +import { Worker } from 'worker_threads'; + +// Do not use isMainThread so that this test itself can be run inside a Worker. +if (!process.env.HAS_STARTED_WORKER) { + process.env.HAS_STARTED_WORKER = 1; + new Worker(import.meta.url.slice('file://'.length)); + await new Promise(() => {}); +} else { + process.exit() +}