Skip to content

Commit dde7152

Browse files
joyeecheungaddaleax
authored andcommitted
src: move more process methods initialization in bootstrap/node.js
Instead of: - Writing methods onto the process directly in C++ during `SetupProcessObject()` and overwrite with argument checks later - Or, wrapping and writing them in `internal/process/*.js` Do: - Move the C++ implementations in node_process.cc and mark them static wherever possible - Expose the C++ methods through a new `internalBinding('process_methods')` - Wrap the methods in `internal/process/*.js` in a side-effect-free manner and return them back to `internal/bootstrap/node.js` - Centralize the write to the process object based on conditions in `bootstrap/node.js` So it's easier to see what methods are attached to the process object during bootstrap under what condition and in what order. The eventual goal is to figure out the dependency of process methods and the write/read access to the process object during bootstrap, group these access properly and remove the process properties that should not be exposed to users this way. Also correct the NODE_PERFORMANCE_MILESTONE_BOOTSTRAP_COMPLETE milestone which should be marked before code execution. Refs: #24961 PR-URL: #25127 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: James M Snell <jasnell@gmail.com> Backport-PR-URL: #25496
1 parent a4f50a6 commit dde7152

File tree

9 files changed

+322
-317
lines changed

9 files changed

+322
-317
lines changed

lib/internal/bootstrap/node.js

+77-23
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,7 @@
1919

2020
const {
2121
_setupNextTick,
22-
_setupPromises, _chdir, _cpuUsage,
23-
_hrtime, _hrtimeBigInt,
24-
_memoryUsage, _rawDebug,
25-
_umask,
26-
_shouldAbortOnUncaughtToggle
22+
_setupPromises
2723
} = bootstrappers;
2824
const { internalBinding, NativeModule } = loaderExports;
2925

@@ -56,15 +52,57 @@ function startup() {
5652
);
5753
}
5854

59-
perThreadSetup.setupAssert();
60-
perThreadSetup.setupConfig();
55+
// process.config is serialized config.gypi
56+
process.config = JSON.parse(internalBinding('native_module').config);
6157

58+
const rawMethods = internalBinding('process_methods');
59+
// Set up methods and events on the process object for the main thread
6260
if (isMainThread) {
61+
// This depends on process being an event emitter
6362
mainThreadSetup.setupSignalHandlers(internalBinding);
63+
64+
process.abort = rawMethods.abort;
65+
const wrapped = mainThreadSetup.wrapProcessMethods(rawMethods);
66+
process.umask = wrapped.umask;
67+
process.chdir = wrapped.chdir;
68+
69+
// TODO(joyeecheung): deprecate and remove these underscore methods
70+
process._debugProcess = rawMethods._debugProcess;
71+
process._debugEnd = rawMethods._debugEnd;
72+
process._startProfilerIdleNotifier =
73+
rawMethods._startProfilerIdleNotifier;
74+
process._stopProfilerIdleNotifier = rawMethods._stopProfilerIdleNotifier;
6475
}
6576

66-
perThreadSetup.setupUncaughtExceptionCapture(exceptionHandlerState,
67-
_shouldAbortOnUncaughtToggle);
77+
// Set up methods on the process object for all threads
78+
{
79+
process.cwd = rawMethods.cwd;
80+
process.dlopen = rawMethods.dlopen;
81+
process.uptime = rawMethods.uptime;
82+
83+
// TODO(joyeecheung): either remove them or make them public
84+
process._getActiveRequests = rawMethods._getActiveRequests;
85+
process._getActiveHandles = rawMethods._getActiveHandles;
86+
87+
// TODO(joyeecheung): remove these
88+
process.reallyExit = rawMethods.reallyExit;
89+
process._kill = rawMethods._kill;
90+
91+
const wrapped = perThreadSetup.wrapProcessMethods(
92+
rawMethods, exceptionHandlerState
93+
);
94+
process._rawDebug = wrapped._rawDebug;
95+
process.hrtime = wrapped.hrtime;
96+
process.hrtime.bigint = wrapped.hrtimeBigInt;
97+
process.cpuUsage = wrapped.cpuUsage;
98+
process.memoryUsage = wrapped.memoryUsage;
99+
process.kill = wrapped.kill;
100+
process.exit = wrapped.exit;
101+
process.setUncaughtExceptionCaptureCallback =
102+
wrapped.setUncaughtExceptionCaptureCallback;
103+
process.hasUncaughtExceptionCaptureCallback =
104+
wrapped.hasUncaughtExceptionCaptureCallback;
105+
}
68106

69107
NativeModule.require('internal/process/warning').setup();
70108
NativeModule.require('internal/process/next_tick').setup(_setupNextTick,
@@ -90,22 +128,10 @@ function startup() {
90128

91129
if (isMainThread) {
92130
mainThreadSetup.setupStdio();
93-
mainThreadSetup.setupProcessMethods(_chdir, _umask);
94131
} else {
95132
workerThreadSetup.setupStdio();
96133
}
97134

98-
const perf = internalBinding('performance');
99-
const {
100-
NODE_PERFORMANCE_MILESTONE_BOOTSTRAP_COMPLETE,
101-
} = perf.constants;
102-
103-
perThreadSetup.setupRawDebug(_rawDebug);
104-
perThreadSetup.setupHrtime(_hrtime, _hrtimeBigInt);
105-
perThreadSetup.setupCpuUsage(_cpuUsage);
106-
perThreadSetup.setupMemoryUsage(_memoryUsage);
107-
perThreadSetup.setupKillAndExit();
108-
109135
if (global.__coverage__)
110136
NativeModule.require('internal/process/write-coverage').setup();
111137

@@ -237,9 +263,37 @@ function startup() {
237263
}
238264
}
239265

240-
perf.markMilestone(NODE_PERFORMANCE_MILESTONE_BOOTSTRAP_COMPLETE);
266+
// process.allowedNodeEnvironmentFlags
267+
Object.defineProperty(process, 'allowedNodeEnvironmentFlags', {
268+
get() {
269+
const flags = perThreadSetup.buildAllowedFlags();
270+
process.allowedNodeEnvironmentFlags = flags;
271+
return process.allowedNodeEnvironmentFlags;
272+
},
273+
// If the user tries to set this to another value, override
274+
// this completely to that value.
275+
set(value) {
276+
Object.defineProperty(this, 'allowedNodeEnvironmentFlags', {
277+
value,
278+
configurable: true,
279+
enumerable: true,
280+
writable: true
281+
});
282+
},
283+
enumerable: true,
284+
configurable: true
285+
});
286+
// process.assert
287+
process.assert = deprecate(
288+
perThreadSetup.assert,
289+
'process.assert() is deprecated. Please use the `assert` module instead.',
290+
'DEP0100');
241291

242-
perThreadSetup.setupAllowedFlags();
292+
const perf = internalBinding('performance');
293+
const {
294+
NODE_PERFORMANCE_MILESTONE_BOOTSTRAP_COMPLETE,
295+
} = perf.constants;
296+
perf.markMilestone(NODE_PERFORMANCE_MILESTONE_BOOTSTRAP_COMPLETE);
243297

244298
startExecution();
245299
}

lib/internal/process/main_thread_only.js

+14-10
Original file line numberDiff line numberDiff line change
@@ -25,21 +25,25 @@ function setupStdio() {
2525
setupProcessStdio(getMainThreadStdio());
2626
}
2727

28-
// Non-POSIX platforms like Windows don't have certain methods.
29-
// Workers also lack these methods since they change process-global state.
30-
function setupProcessMethods(_chdir, _umask) {
31-
process.chdir = function chdir(directory) {
28+
// The execution of this function itself should not cause any side effects.
29+
function wrapProcessMethods(binding) {
30+
function chdir(directory) {
3231
validateString(directory, 'directory');
33-
return _chdir(directory);
34-
};
32+
return binding.chdir(directory);
33+
}
3534

36-
process.umask = function umask(mask) {
35+
function umask(mask) {
3736
if (mask === undefined) {
3837
// Get the mask
39-
return _umask(mask);
38+
return binding.umask(mask);
4039
}
4140
mask = validateMode(mask, 'mask');
42-
return _umask(mask);
41+
return binding.umask(mask);
42+
}
43+
44+
return {
45+
chdir,
46+
umask
4347
};
4448
}
4549

@@ -171,7 +175,7 @@ function setupChildProcessIpcChannel() {
171175

172176
module.exports = {
173177
setupStdio,
174-
setupProcessMethods,
178+
wrapProcessMethods,
175179
setupSignalHandlers,
176180
setupChildProcessIpcChannel,
177181
wrapPosixCredentialSetters

0 commit comments

Comments
 (0)