#53537: refactor: run the init bundles from Node's embedder start callback
Description of Change
Each Electron process runs an init bundle (lib/browser/init.ts, lib/renderer/init.ts, ...) inside Node before any app code. Until now we got Node to run it by pretending it was the user's script: we inserted electron/js2c/<type>_init as argv[1], Node's normal "run the main module" path picked it up, two Node patches stopped Node from treating that fake path as a file on disk, and each bundle then removed itself from process.argv again.
Node has a real hook for this: an embedder can pass LoadEnvironment() a callback that runs its own entry code. NodeBindings::LoadEnvironment() now does that and runs the bundle the same way node_init is already run, so argv is never touched and the two patches are no longer needed.
- Removes
chore_allow_the_node_entrypoint_to_be_a_builtin_module.patchand therun_main.jspart offix_do_not_resolve_electron_entrypoints.patch(its remaining hunk is aboutrequire('electron')from ESM and stays). - The init bundles stop splicing
process.argv;utility/init.tsgetsinternalBindingfrom Node's loader instead of a wrapper argument. - The bundles are compiled with the same
(process, require)parameters asnode_init, and the build-time code cache generator is updated to match;spec/api-js2c-code-cache-spec.tschecks the cache is still used in every process type. - The bundle is called without a
v8::TryCatch, asrunMaindid, so an app whose main script throws while loading still reachesprocess.on('uncaughtException')(or Electron's error dialog) instead of the error being logged and swallowed. - With an embedder callback Node would pause for
--inspect-brkon the first line of our bundle instead of the app's entry, so the flag is masked while the bundle starts and, only when it was set, Node's cached options are refreshed before the bundle runs; the pause still lands on the app's first line (checked with a CDP client).
Startup cost, measured on the linux-x64 CI builds of this branch and main with a packaged one-window app over 60 interleaved launches (performance.nodeTiming): Environment creation to bootstrap-complete 20.0 vs 20.0 ms, bootstrap-complete to the first line of the app's main.js 17.0 vs 17.0 ms, main.js to ready 60 vs 60 ms; getJs2cCodeCacheStatus() reports the same accepted set on both (browser_init, node_init, with internal/main/embedding in place of internal/main/run_main_module).
process.argv, process.type, require.main, process.execArgv and -r preloads were compared against main in the browser, renderer, worker and utility processes and are unchanged.
Checklist
- I have built and tested this change
- I have filled out the PR description
- I have reviewed and verified the changes
-
npm testpasses
Release Notes
Notes: none
Backports
Semver Impact
Semantic Versioning helps users understand the impact of updates:
- Major (X.y.z): Breaking changes that may require code modifications
- Minor (x.Y.z): New features that maintain backward compatibility
- Patch (x.y.Z): Bug fixes that don't change the API
- None: Changes that don't affect using facing parts of Electron