Skip to content

Commit 7108077

Browse files
committed
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
1 parent 263d137 commit 7108077

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
@@ -20,11 +20,7 @@
2020
const {
2121
_setupTraceCategoryState,
2222
_setupNextTick,
23-
_setupPromises, _chdir, _cpuUsage,
24-
_hrtime, _hrtimeBigInt,
25-
_memoryUsage, _rawDebug,
26-
_umask,
27-
_shouldAbortOnUncaughtToggle
23+
_setupPromises
2824
} = bootstrappers;
2925
const { internalBinding, NativeModule } = loaderExports;
3026

@@ -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

@@ -208,9 +234,37 @@ function startup() {
208234
}
209235
}
210236

211-
perf.markMilestone(NODE_PERFORMANCE_MILESTONE_BOOTSTRAP_COMPLETE);
237+
// process.allowedNodeEnvironmentFlags
238+
Object.defineProperty(process, 'allowedNodeEnvironmentFlags', {
239+
get() {
240+
const flags = perThreadSetup.buildAllowedFlags();
241+
process.allowedNodeEnvironmentFlags = flags;
242+
return process.allowedNodeEnvironmentFlags;
243+
},
244+
// If the user tries to set this to another value, override
245+
// this completely to that value.
246+
set(value) {
247+
Object.defineProperty(this, 'allowedNodeEnvironmentFlags', {
248+
value,
249+
configurable: true,
250+
enumerable: true,
251+
writable: true
252+
});
253+
},
254+
enumerable: true,
255+
configurable: true
256+
});
257+
// process.assert
258+
process.assert = deprecate(
259+
perThreadSetup.assert,
260+
'process.assert() is deprecated. Please use the `assert` module instead.',
261+
'DEP0100');
212262

213-
perThreadSetup.setupAllowedFlags();
263+
const perf = internalBinding('performance');
264+
const {
265+
NODE_PERFORMANCE_MILESTONE_BOOTSTRAP_COMPLETE,
266+
} = perf.constants;
267+
perf.markMilestone(NODE_PERFORMANCE_MILESTONE_BOOTSTRAP_COMPLETE);
214268

215269
startExecution();
216270
}

lib/internal/process/main_thread_only.js

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

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

38-
process.umask = function umask(mask) {
37+
function umask(mask) {
3938
if (mask === undefined) {
4039
// Get the mask
41-
return _umask(mask);
40+
return binding.umask(mask);
4241
}
4342
mask = validateMode(mask, 'mask');
44-
return _umask(mask);
43+
return binding.umask(mask);
44+
}
45+
46+
return {
47+
chdir,
48+
umask
4549
};
4650
}
4751

@@ -175,7 +179,7 @@ function setupChildProcessIpcChannel() {
175179

176180
module.exports = {
177181
setupStdio,
178-
setupProcessMethods,
182+
wrapProcessMethods,
179183
setupSignalHandlers,
180184
setupChildProcessIpcChannel,
181185
wrapPosixCredentialSetters

0 commit comments

Comments
 (0)