Skip to content

process: add process.entrypoint - #64800

Open
avivkeller wants to merge 4 commits into
nodejs:mainfrom
avivkeller:process.entrypoint
Open

avivkeller wants to merge 4 commits into
nodejs:mainfrom
avivkeller:process.entrypoint

Conversation

@avivkeller

@avivkeller avivkeller commented Jul 28, 2026 •

Copy link
Copy Markdown
Member

Ref: #51840

Adds a process.entrypoint non-configurable property to the process object during bootstrap. This property reflects the executable's main entrypoint (i.e. not --require or --import-ed files, the main file).

Additionally, this entrypoint is passed to workers, so it reflects the entrypoint of the process that created the worker, not the entrypoint of the worker itself.

Signed-off-by: avivkeller <me@aviv.sh>
@nodejs-github-bot

Copy link
Copy Markdown
Collaborator

Review requested:

  • @nodejs/loaders

@nodejs-github-bot nodejs-github-bot added esm Issues and PRs related to the ECMAScript Modules implementation. needs-ci PRs that need a full CI run. process Issues and PRs related to the process subsystem. labels Jul 28, 2026
@avivkeller

Copy link
Copy Markdown
Member Author

@nodejs/process

@mcollina

Copy link
Copy Markdown
Member

in worker threadsx this is set to the entrypoint of the worker?

@codecov

codecov Bot commented Jul 28, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 90.12%. Comparing base (6a3d80f) to head (4878c1f).
⚠️ Report is 376 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #64800      +/-   ##
==========================================
- Coverage   90.16%   90.12%   -0.05%     
==========================================
  Files         744      752       +8     
  Lines      242518   251602    +9084     
  Branches    45705    47278    +1573     
==========================================
+ Hits       218670   226757    +8087     
- Misses      15357    16211     +854     
- Partials     8491     8634     +143     
Files with missing lines Coverage Δ
lib/internal/main/worker_thread.js 94.97% <100.00%> (+0.61%) ⬆️
lib/internal/process/pre_execution.js 97.35% <100.00%> (-0.61%) ⬇️
lib/internal/worker.js 96.76% <100.00%> (+0.02%) ⬆️

... and 264 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@avivkeller

avivkeller commented Jul 28, 2026 •

Copy link
Copy Markdown
Member Author

in worker threadsx this is set to the entrypoint of the worker?

This is set to the entrypoint of the process that created the worker, not the worker itself. So if /my/path/index.js creates /my/worker/index.js, entrypoint will a URL of /my/path/index.js.

@mcollina

Copy link
Copy Markdown
Member

in worker threadsx this is set to the entrypoint of the worker?

This is set to the entrypoint of the process that created the worker, not the worker itself. So if /my/path/index.js creates /my/worker/index.js, entrypoint will a URL of /my/path/index.js.

this is behaviorally different from the old "require.main".

Can we have the same?

@avivkeller

Copy link
Copy Markdown
Member Author

IMO it makes more sense to show the entrypoint of the process, not the worker

@mcollina

Copy link
Copy Markdown
Member

I'm saying this is not identical to require.main, or what import.main is defined.

The issue linked refers to require.main.

@avivkeller

Copy link
Copy Markdown
Member Author

Okay, I've changed Fixes to Ref, since I feel that it makes more sense to show it this way

@mcollina

mcollina commented Aug 1, 2026

Copy link
Copy Markdown
Member

Opened #64903 with the thread-scoped counterpart (module.entrypoint in node:module), matching require.main semantics.

@avivkeller

Copy link
Copy Markdown
Member Author

Awesome! Aside from that, is this good to go?

Comment thread lib/internal/process/pre_execution.js Resolved
mcollina added a commit to mcollina/node that referenced this pull request Aug 3, 2026
Add `module.entrypoint`, a property exposing the resolved URL of the
entry point of the current thread. Unlike `require.main`, it works
regardless of whether the entry point is a CommonJS or an ECMAScript
module, and inside worker threads it reflects the entry point of the
worker itself, matching the semantics of `require.main` and
`import.meta.main`.

Refs: nodejs#51840
Refs: nodejs#64800
Signed-off-by: Matteo Collina <hello@matteocollina.com>
@avivkeller
avivkeller requested a review from mcollina August 4, 2026 17:26
@avivkeller

Copy link
Copy Markdown
Member Author

bump @nodejs/process

Comment thread lib/internal/process/pre_execution.js Resolved
@avivkeller
avivkeller requested a review from jsumners-nr August 15, 2026 21:19
@avivkeller

Copy link
Copy Markdown
Member Author

Bump @mcollina!

@avivkeller

Copy link
Copy Markdown
Member Author

Bump!

mcollina added a commit to mcollina/node that referenced this pull request Nov 6, 2026
Add `module.entrypoint`, a property exposing the resolved URL of the
entry point of the current thread. Unlike `require.main`, it works
regardless of whether the entry point is a CommonJS or an ECMAScript
module, and inside worker threads it reflects the entry point of the
worker itself, matching the semantics of `require.main` and
`import.meta.main`.

Refs: nodejs#51840
Refs: nodejs#64800
Signed-off-by: Matteo Collina <hello@matteocollina.com>

@marcastben-hash marcastben-hash left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I read this at 4878c1f. I did not build the branch; point 1 I checked on a released Node (v24.15.0) using the same computation the PR uses, the rest is from reading.

  1. The value is not the URL the entry module is actually loaded under when the path goes through a link. mainEntry is path.resolve(process.argv[1]), with no realpath, while the CJS and ESM loaders resolve symlinks for the main module (unless --preserve-symlinks-main). Running a script through a directory junction on Windows:

    > node link/app.mjs
    import.meta.url                      file:///.../symtest/real/app.mjs
    pathToFileURL(resolve(argv[1])).href file:///.../symtest/link/app.mjs
    

    So process.entrypoint === import.meta.url is false in that case, and I would expect the same for node_modules/.bin symlinks on POSIX. Since "am I the main module?" is the use case in #51840, this is likely to be the first thing people try. Either resolve it the same way the loader does, or document that the value is the path as given on the command line, made absolute, and not necessarily equal to import.meta.url.

  2. Description and code disagree on configurability. The description says the property is non-configurable; defineEntrypoint() uses configurable: true (which the worker path needs in order to redefine it after patchProcessObject()). As written, user code can delete or redefine process.entrypoint. If that is not intended, the worker could be given the value before the first definition, or the final definition could be made non-configurable.

  3. With a relative --entry-url, the result depends on the cwd at first access. The getter is lazy and calls getCWDURL() when first read, and getCWDURL() follows process.cwd(). node --entry-url ./app.mjs followed by process.chdir() before the first read of process.entrypoint resolves against the new directory. Capturing the cwd at startup, or resolving eagerly in the --entry-url case only, would avoid that.

  4. Docs: it would help to state what the value is for node - (stdin), --test, --watch and single executable applications, since process.argv[1] means something different in some of those. None of them are covered by the tests either.

Disclosure: this review was prepared with AI assistance (Claude).

@JakobJingleheimer JakobJingleheimer left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: I think it's more efficient for the getter to overwrite itself upon execution, switching from a get to a value (then there is no scope to maintain).

Comment thread doc/api/process.md

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: To avoid ambiguity (URL instance vs a string). As it was written, I would expect an instance.

Suggested change
The file URL string of the entry point that Node.js was started with, such as

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

esm Issues and PRs related to the ECMAScript Modules implementation. needs-ci PRs that need a full CI run. process Issues and PRs related to the process subsystem. review wanted PRs that need review.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants