From b3d78d89f81f92a2b1467bec72107f8632e4eac9 Mon Sep 17 00:00:00 2001 From: avivkeller Date: Mon, 27 Jul 2026 23:36:56 -0700 Subject: [PATCH 1/3] process: add `process.entrypoint` Signed-off-by: avivkeller --- doc/api/process.md | 11 ++ lib/internal/main/worker_thread.js | 7 +- lib/internal/modules/esm/hooks.js | 1 + lib/internal/process/pre_execution.js | 22 ++++ test/fixtures/entrypoint/check-commonjs.cjs | 5 + test/fixtures/entrypoint/check-module.mjs | 4 + test/fixtures/entrypoint/commonjs.cjs | 1 + test/fixtures/entrypoint/loader.mjs | 4 + test/fixtures/entrypoint/module.mjs | 1 + test/parallel/test-process-entrypoint.js | 105 ++++++++++++++++++++ 10 files changed, 160 insertions(+), 1 deletion(-) create mode 100644 test/fixtures/entrypoint/check-commonjs.cjs create mode 100644 test/fixtures/entrypoint/check-module.mjs create mode 100644 test/fixtures/entrypoint/commonjs.cjs create mode 100644 test/fixtures/entrypoint/loader.mjs create mode 100644 test/fixtures/entrypoint/module.mjs create mode 100644 test/parallel/test-process-entrypoint.js diff --git a/doc/api/process.md b/doc/api/process.md index 0a7f85700ae8..d006aea7fb3f 100644 --- a/doc/api/process.md +++ b/doc/api/process.md @@ -1513,6 +1513,17 @@ emitMyWarning(); // Emits nothing ``` +## `process.entrypoint` + + + +* Type: {URL | undefined} + +The entrypoint that node was instantiated with, or {undefined} if node +was instantiated without one (e.g., in the REPL). + ## `process.env` -* Type: {URL | undefined} +* Type: {string | undefined} -The entry point that Node.js was started with. Worker threads inherit this -value. If Node.js was started without an entry point, such as in the REPL, the -value is {undefined}. +The URL of the entry point that Node.js was started with, such as +`'file:///path/to/app.js'`. Worker threads inherit this value. If Node.js was +started without an entry point, such as in the REPL, the value is {undefined}. ## `process.env` diff --git a/lib/internal/main/worker_thread.js b/lib/internal/main/worker_thread.js index 42bf1ee805fe..25be1f4fb7f4 100644 --- a/lib/internal/main/worker_thread.js +++ b/lib/internal/main/worker_thread.js @@ -105,9 +105,7 @@ port.on('message', (message) => { mainThreadPort, } = message; - const { URL } = require('internal/url'); - defineEntrypoint(entrypoint === undefined ? - undefined : new URL(entrypoint)); + defineEntrypoint(() => entrypoint); if (doEval !== 'internal') { if (argv !== undefined) { diff --git a/lib/internal/process/pre_execution.js b/lib/internal/process/pre_execution.js index b09ff3d3169e..010d83b18054 100644 --- a/lib/internal/process/pre_execution.js +++ b/lib/internal/process/pre_execution.js @@ -255,13 +255,22 @@ function refreshRuntimeOptions() { refreshOptions(); } -function defineEntrypoint(entrypoint) { +function defineEntrypoint(computeEntrypoint) { + let entrypoint; + let computed = false; + ObjectDefineProperty(process, 'entrypoint', { __proto__: null, - writable: false, enumerable: true, configurable: true, - value: entrypoint, + get() { + if (!computed) { + entrypoint = computeEntrypoint(); + computed = true; + } + return entrypoint; + }, + set: undefined, }); } @@ -305,15 +314,18 @@ function patchProcessObject(expandArgv1) { } } - let entrypoint; - if (mainEntry !== undefined) { - const { pathToFileURL } = require('internal/url'); - entrypoint = pathToFileURL(mainEntry); - } else if (getOptionValue('--entry-url') && process.argv[1]) { - const { URL } = require('internal/url'); - entrypoint = new URL(process.argv[1], getCWDURL()); - } - defineEntrypoint(entrypoint); + const entryArg = process.argv[1]; + defineEntrypoint(() => { + if (mainEntry !== undefined) { + const { pathToFileURL } = require('internal/url'); + return pathToFileURL(mainEntry).href; + } + if (entryArg && getOptionValue('--entry-url')) { + const { URL } = require('internal/url'); + return new URL(entryArg, getCWDURL()).href; + } + return undefined; + }); // We need to initialize the global console here again with process.stdout // and friends for snapshot deserialization. diff --git a/lib/internal/worker.js b/lib/internal/worker.js index d7bd9feb5e7a..295e2526ecca 100644 --- a/lib/internal/worker.js +++ b/lib/internal/worker.js @@ -362,7 +362,7 @@ class Worker extends EventEmitter { this[kPort].postMessage({ argv, - entrypoint: process.entrypoint?.href, + entrypoint: process.entrypoint, type: messageTypes.LOAD_SCRIPT, filename, doEval, diff --git a/test/fixtures/entrypoint/check-commonjs.cjs b/test/fixtures/entrypoint/check-commonjs.cjs index 9e11d41631d7..0adc9959c004 100644 --- a/test/fixtures/entrypoint/check-commonjs.cjs +++ b/test/fixtures/entrypoint/check-commonjs.cjs @@ -2,4 +2,4 @@ const assert = require('node:assert'); -assert.strictEqual(process.entrypoint.href, process.env.NODE_TEST_ENTRYPOINT); +assert.strictEqual(process.entrypoint, process.env.NODE_TEST_ENTRYPOINT); diff --git a/test/fixtures/entrypoint/check-module.mjs b/test/fixtures/entrypoint/check-module.mjs index 07f18768647c..79781382a58b 100644 --- a/test/fixtures/entrypoint/check-module.mjs +++ b/test/fixtures/entrypoint/check-module.mjs @@ -1,4 +1,4 @@ import assert from 'node:assert'; import { entrypoint } from 'node:process'; -assert.strictEqual(entrypoint.href, process.env.NODE_TEST_ENTRYPOINT); +assert.strictEqual(entrypoint, process.env.NODE_TEST_ENTRYPOINT); diff --git a/test/fixtures/entrypoint/commonjs.cjs b/test/fixtures/entrypoint/commonjs.cjs index f1c28fad08ae..891f9a3475de 100644 --- a/test/fixtures/entrypoint/commonjs.cjs +++ b/test/fixtures/entrypoint/commonjs.cjs @@ -1 +1 @@ -console.log(process.entrypoint.href); +console.log(process.entrypoint); diff --git a/test/fixtures/entrypoint/loader.mjs b/test/fixtures/entrypoint/loader.mjs index 07f18768647c..79781382a58b 100644 --- a/test/fixtures/entrypoint/loader.mjs +++ b/test/fixtures/entrypoint/loader.mjs @@ -1,4 +1,4 @@ import assert from 'node:assert'; import { entrypoint } from 'node:process'; -assert.strictEqual(entrypoint.href, process.env.NODE_TEST_ENTRYPOINT); +assert.strictEqual(entrypoint, process.env.NODE_TEST_ENTRYPOINT); diff --git a/test/fixtures/entrypoint/module.mjs b/test/fixtures/entrypoint/module.mjs index f1c28fad08ae..891f9a3475de 100644 --- a/test/fixtures/entrypoint/module.mjs +++ b/test/fixtures/entrypoint/module.mjs @@ -1 +1 @@ -console.log(process.entrypoint.href); +console.log(process.entrypoint); diff --git a/test/fixtures/entrypoint/worker.cjs b/test/fixtures/entrypoint/worker.cjs index 9ace1cf2a8d8..1c3492afa5ba 100644 --- a/test/fixtures/entrypoint/worker.cjs +++ b/test/fixtures/entrypoint/worker.cjs @@ -5,5 +5,5 @@ const { isMainThread, workerData, Worker } = require('node:worker_threads'); if (isMainThread || workerData === 'nested') { new Worker(__filename, { workerData: isMainThread ? 'nested' : 'leaf' }); } else { - console.log(process.entrypoint.href); + console.log(process.entrypoint); } diff --git a/test/parallel/test-process-entrypoint.js b/test/parallel/test-process-entrypoint.js index ed054ac50898..8d1dfdf23c14 100644 --- a/test/parallel/test-process-entrypoint.js +++ b/test/parallel/test-process-entrypoint.js @@ -20,7 +20,7 @@ const cjsPreload = fixtures.path('entrypoint', 'check-commonjs.cjs'); const esmPreload = fixtures.fileURL('entrypoint', 'check-module.mjs').href; const loader = fixtures.fileURL('entrypoint', 'loader.mjs').href; -const printEntrypoint = 'console.log(process.entrypoint?.href)'; +const printEntrypoint = 'console.log(process.entrypoint)'; async function getEntrypoint(args, options, expected) { const { code, signal, stderr, stdout } = await spawnPromisified(