Skip to content
File

Blob: src/node/internal/public_process.ts

typescript816 lines
1// Copyright (c) 2017-2022 Cloudflare, Inc.
2// Licensed under the Apache 2.0 license found in the LICENSE file or at:
3// https://opensource.org/licenses/Apache-2.0
4//
5 
6// Process is implemented under node-internal: so that we can have node:process
7// resolve to node-internal:public_process OR node-internal:legacy_process depending
8// on whether the enable_nodejs_process_v2 compat flag is set.
9 
10import { default as EventEmitter } from 'node-internal:events';
11import {
12 ERR_EPERM,
13 ERR_INVALID_ARG_TYPE,
14 ERR_INVALID_ARG_VALUE,
15 ERR_OUT_OF_RANGE,
16 ERR_METHOD_NOT_IMPLEMENTED,
17} from 'node-internal:internal_errors';
18import processImpl from 'node-internal:process';
19import { Buffer } from 'node-internal:internal_buffer';
20import { parseEnv } from 'node-internal:internal_utils';
21import { Writable } from 'node-internal:streams_writable';
22import { writeSync } from 'node-internal:internal_fs_sync';
23import { ReadStream } from 'node-internal:internal_fs_streams';
24import {
25 platform,
26 nextTick,
27 emitWarning,
28 env,
29 features,
30 config,
31 _setEventsProcess,
32} from 'node-internal:internal_process';
33import { validateString } from 'node-internal:validators';
34import internalAssert from 'node-internal:internal_assert';
35import type { Readable } from 'node-internal:streams_readable';
36import type * as NodeFS from 'node:fs';
37 
38export { platform, nextTick, emitWarning, env, features, config };
39 
40// For stdin, we emulate `node foo.js < /dev/null`
41// In Node.js, process.stdin is a net.Socket (Duplex) with both readable and writable properties.
42// We use 'any' cast to assign socket-like properties without type conflicts.
43export const stdin = new ReadStream(null, {
44 fd: 0,
45 autoClose: false,
46}) as Readable & { fd: number };
47stdin.fd = 0;
48// In Node.js, process.stdin is a net.Socket (Duplex) with socket-like properties.
49// We add socket-like stub properties for compatibility, but avoid setting writable-related
50// properties that would cause the streams internals to treat this ReadStream as writable
51// (which would trigger calls to .end() that don't exist on ReadStream).
52/* eslint-disable @typescript-eslint/no-unsafe-assignment,
53 @typescript-eslint/no-unsafe-member-access,
54 @typescript-eslint/no-explicit-any */
55const stdinAny = stdin as any;
56stdinAny.allowHalfOpen = false;
57stdinAny.bufferSize = 0;
58stdinAny.connecting = false;
59stdinAny.readyState = 'open';
60/* eslint-enable @typescript-eslint/no-unsafe-assignment,
61 @typescript-eslint/no-unsafe-member-access,
62 @typescript-eslint/no-explicit-any */
63 
64function chunkToBuffer(
65 chunk: Buffer | ArrayBufferView | DataView | string,
66 encoding: BufferEncoding
67): Buffer {
68 if (Buffer.isBuffer(chunk)) {
69 return chunk;
70 }
71 if (typeof chunk === 'string') {
72 return Buffer.from(chunk, encoding);
73 }
74 return Buffer.from(chunk.buffer, chunk.byteOffset, chunk.byteLength);
75}
76 
77// For stdout, we emulate `nohup node foo.js`
78class SyncWriteStream extends Writable {
79 fd: number;
80 override readable: boolean = false;
81 _type = 'fs';
82 _isStdio = true;
83 constructor(fd: number) {
84 super({ autoDestroy: true });
85 this.fd = fd;
86 }
87 override _write(
88 chunk: string | Buffer | ArrayBufferView | DataView,
89 encoding: BufferEncoding,
90 cb: (error?: Error | null) => void
91 ): void {
92 try {
93 writeSync(this.fd, chunkToBuffer(chunk, encoding));
94 } catch (e: unknown) {
95 cb(e as Error);
96 return;
97 }
98 cb();
99 }
100}
101 
102// In Node.js, process.stdout/stderr are net.Socket (TTY) instances with Duplex stream properties.
103// We assign socket-like stub properties for compatibility.
104/* eslint-disable @typescript-eslint/no-unsafe-assignment,
105 @typescript-eslint/no-unsafe-member-access,
106 @typescript-eslint/no-explicit-any */
107function addSocketProperties(stream: SyncWriteStream): void {
108 const s = stream as any;
109 s.allowHalfOpen = false;
110 s.bufferSize = 0;
111 s.bytesRead = 0;
112 s.bytesWritten = 0;
113 s.connecting = false;
114 s.pending = false;
115 s.readableAborted = false;
116 s.readableDidRead = false;
117 s.readableEnded = false;
118 s.readableHighWaterMark = 16384;
119 s.readableLength = 0;
120 s.readableObjectMode = false;
121 s.readyState = 'open';
122}
123/* eslint-enable @typescript-eslint/no-unsafe-assignment,
124 @typescript-eslint/no-unsafe-member-access,
125 @typescript-eslint/no-explicit-any */
126 
127export const stdout = new SyncWriteStream(1);
128addSocketProperties(stdout);
129export const stderr = new SyncWriteStream(2);
130addSocketProperties(stderr);
131 
132export function chdir(path: string | Buffer | URL): void {
133 validateString(path, 'directory');
134 processImpl.setCwd(path);
135}
136 
137export const cwd = processImpl.getCwd.bind(processImpl);
138 
139// We do not support setting the umask as we do not have a fine-grained
140// permissions on the VFS. Instead we only support validation of input
141// and then ignoring it.
142export function umask(mask: number | string | undefined): number {
143 if (mask !== undefined) {
144 if (typeof mask === 'string') {
145 if (!/^[0-7]+$/.test(mask)) {
146 throw new ERR_INVALID_ARG_VALUE(
147 'mask',
148 mask,
149 'must be a 32-bit unsigned integer or an octal string'
150 );
151 }
152 mask = parseInt(mask, 8);
153 } else if (typeof mask !== 'number') {
154 throw new ERR_INVALID_ARG_TYPE('mask', 'number', mask);
155 }
156 if (mask < 0 || mask > 0xffffffff || !Number.isInteger(mask)) {
157 throw new ERR_INVALID_ARG_VALUE(
158 'mask',
159 mask,
160 'must be a 32-bit unsigned integer or an octal string'
161 );
162 }
163 }
164 // just return Node.js default of 18
165 return 18;
166}
167 
168export const versions = processImpl.versions;
169 
170export const version = `v${processImpl.versions.node}`;
171 
172export const title = 'workerd';
173 
174export const argv = ['workerd'];
175 
176export const argv0 = 'workerd';
177 
178export const execArgv = [];
179 
180export const arch = 'x64';
181 
182// For simplicity and polyfill expectations, we assign pid 1 to the process and pid 0 to the "parent".
183export const pid = 1;
184export const ppid = 0;
185 
186export const allowedNodeEnvironmentFlags = new Set();
187 
188export function setSourceMapsEnabled(
189 _enabled: boolean,
190 _options?: { nodeModules: boolean; generatedCode: boolean }
191): void {
192 // no-op since we do not support disabling source maps
193}
194 
195export function getSourceMapsSupport(): {
196 enabled: boolean;
197 nodeModules: boolean;
198 generatedCode: boolean;
199} {
200 return {
201 enabled: false,
202 nodeModules: false,
203 generatedCode: false,
204 };
205}
206 
207export const hrtime = Object.assign(
208 function hrtime(time?: [number, number]): [number, number] {
209 if (time !== undefined) {
210 if (!Array.isArray(time))
211 throw new ERR_INVALID_ARG_TYPE('time', 'tuple of integers', time);
212 else if ((time as number[]).length !== 2)
213 throw new ERR_OUT_OF_RANGE('time', '2', time);
214 }
215 const nanoTime = BigInt(Date.now()) * 1_000_000n;
216 const nanosBigint = nanoTime % 1_000_000_000n;
217 let seconds = Number((nanoTime - nanosBigint) / 1_000_000_000n);
218 let nanos = Number(nanosBigint);
219 if (time) {
220 const [prevSeconds, prevNanos] = time;
221 seconds -= prevSeconds;
222 nanos -= prevNanos;
223 // We don't have nanosecond-level precision, but if we
224 // did (say with the introduction of randomness), this
225 // is how we would handle nanosecond underflow
226 if (nanos < 0) {
227 seconds -= 1;
228 nanos += 1e9;
229 }
230 }
231 return [seconds, nanos];
232 },
233 {
234 bigint: function (): bigint {
235 return BigInt(Date.now()) * 1_000_000n;
236 },
237 }
238);
239 
240export function ref(): void {
241 // no-op
242}
243 
244export function unref(): void {
245 // no-op
246}
247 
248export function setUncaughtExceptionCaptureCallback(
249 _fn?: (...args: unknown[]) => void
250): void {
251 throw new ERR_METHOD_NOT_IMPLEMENTED(
252 'process.setUncaughtExceptionCaptureCallback'
253 );
254}
255 
256export function hasUncaughtExceptionCaptureCallback(): boolean {
257 throw new ERR_METHOD_NOT_IMPLEMENTED(
258 'process.hasUncaughtExceptionCaptureCallback'
259 );
260}
261 
262export function kill(_pid: number, _signal?: string | number): boolean {
263 throw new ERR_METHOD_NOT_IMPLEMENTED('process.kill');
264}
265 
266export function binding(_name: string): unknown {
267 throw new ERR_METHOD_NOT_IMPLEMENTED('process.binding');
268}
269 
270export function dlopen(
271 _module: unknown,
272 _filename: string,
273 _flags?: number
274): void {
275 throw new ERR_METHOD_NOT_IMPLEMENTED('process.dlopen');
276}
277 
278export const exitCode: number | undefined = undefined;
279 
280export function getActiveResourcesInfo(): string[] {
281 throw new ERR_METHOD_NOT_IMPLEMENTED('process.getActiveResourcesInfo');
282}
283 
284export function memoryUsage(): {
285 rss: number;
286 heapTotal: number;
287 heapUsed: number;
288 external: number;
289 arrayBuffers: number;
290} {
291 return {
292 rss: 0,
293 heapTotal: 0,
294 heapUsed: 0,
295 external: 0,
296 arrayBuffers: 0,
297 };
298}
299 
300export function resourceUsage(): {
301 userCPUTime: number;
302 systemCPUTime: number;
303 maxRSS: number;
304 sharedMemorySize: number;
305 unsharedDataSize: number;
306 unsharedStackSize: number;
307 minorPageFault: number;
308 majorPageFault: number;
309 swappedOut: number;
310 fsRead: number;
311 fsWrite: number;
312 ipcSent: number;
313 ipcReceived: number;
314 signalsCount: number;
315 voluntaryContextSwitches: number;
316 involuntaryContextSwitches: number;
317} {
318 return {
319 userCPUTime: 0,
320 systemCPUTime: 0,
321 maxRSS: 0,
322 sharedMemorySize: 0,
323 unsharedDataSize: 0,
324 unsharedStackSize: 0,
325 minorPageFault: 0,
326 majorPageFault: 0,
327 swappedOut: 0,
328 fsRead: 0,
329 fsWrite: 0,
330 ipcSent: 0,
331 ipcReceived: 0,
332 signalsCount: 0,
333 voluntaryContextSwitches: 0,
334 involuntaryContextSwitches: 0,
335 };
336}
337 
338export function threadCpuUsage(): {
339 user: number;
340 system: number;
341} {
342 throw new ERR_METHOD_NOT_IMPLEMENTED('process.threadCpuUsage');
343}
344 
345export function cpuUsage(_previousValue?: { user: number; system: number }): {
346 user: number;
347 system: number;
348} {
349 throw new ERR_METHOD_NOT_IMPLEMENTED('process.cpuUsage');
350}
351 
352// Properties and constants
353export const channel = null;
354export const connected = false;
355export const debugPort = 0; // may be implemented to align with inspector in future
356export const noDeprecation = false;
357export const traceDeprecation = false;
358export const throwDeprecation = false;
359export const sourceMapsEnabled = false;
360export const execPath = '';
361 
362export const permission = {
363 has: (): boolean => {
364 throw new ERR_METHOD_NOT_IMPLEMENTED('process.permission.has');
365 },
366};
367 
368export const release = {
369 name: 'node',
370 lts: true,
371 sourceUrl: '',
372 headersUrl: '',
373};
374 
375export const report = {
376 compact: false,
377 directory: '',
378 filename: '',
379 getReport: (): Record<string, unknown> => {
380 // We do not intend to implement process.report in workerd, but there
381 // are some modules in the ecosystem that call it expecting it to exist and
382 // not throw. Returning an empty object for now to satisfy that use case.
383 return {};
384 },
385 reportOnFatalError: false,
386 reportOnSignal: false,
387 reportOnUncaughtException: false,
388 excludeNetwork: false,
389 excludeEnv: false,
390 signal: 'SIGUSR2',
391 writeReport: (): string => {
392 // In this case, there's an expectation that the function will produce
393 // a report on disk and return the filename. Since we do not intend
394 // to implement this API in workerd, we throw to indicate that.
395 throw new ERR_METHOD_NOT_IMPLEMENTED('process.report.writeReport');
396 },
397};
398 
399export const finalization = {
400 register: (): void => {
401 throw new ERR_METHOD_NOT_IMPLEMENTED('process.finalization.register');
402 },
403 registerBeforeExit: (): void => {
404 throw new ERR_METHOD_NOT_IMPLEMENTED(
405 'process.finalization.registerBeforeExit'
406 );
407 },
408 unregister: (): void => {
409 throw new ERR_METHOD_NOT_IMPLEMENTED('process.finalization.unregister');
410 },
411};
412 
413// Additional undocumented APIs
414export function _rawDebug(...args: unknown[]): void {
415 console.log(...args);
416}
417 
418export const moduleLoadList: string[] = [];
419export const _preload_modules: string[] = [];
420 
421export function _linkedBinding(_name: string): unknown {
422 throw new ERR_METHOD_NOT_IMPLEMENTED('process._linkedBinding');
423}
424 
425export const domain = null;
426export const _exiting = false;
427 
428export function _getActiveRequests(): unknown[] {
429 return [];
430}
431 
432export function _getActiveHandles(): unknown[] {
433 return [];
434}
435 
436export function reallyExit(code?: number): void {
437 processImpl.exitImpl(code || 0);
438}
439 
440export function _kill(_pid: number, _signal: number): boolean {
441 throw new ERR_METHOD_NOT_IMPLEMENTED('process._kill');
442}
443 
444export function constrainedMemory(): number {
445 return 0;
446}
447 
448export function availableMemory(): number {
449 // This may be implemented in future, for now this matches unenv
450 return 0;
451}
452 
453export function execve(
454 _file: string,
455 _args: string[],
456 _env: Record<string, string>
457): never {
458 throw new ERR_METHOD_NOT_IMPLEMENTED('process.execve');
459}
460 
461export function openStdin(): typeof stdin {
462 return stdin;
463}
464 
465export function _fatalException(_err: Error): boolean {
466 return false;
467}
468 
469export function _tickCallback(): void {
470 // no-op
471}
472 
473export function _debugProcess(_pid: number): void {
474 // no-op
475}
476 
477export function _debugEnd(): void {
478 // no-op
479}
480 
481export function _startProfilerIdleNotifier(): void {
482 // no-op
483}
484 
485export function _stopProfilerIdleNotifier(): void {
486 // no-op
487}
488 
489export function send(_message: unknown, _sendHandle?: unknown): boolean {
490 return false;
491}
492 
493export function getBuiltinModule(id: string): object {
494 return processImpl.getBuiltinModule(id);
495}
496 
497export function exit(code: number): void {
498 processImpl.exitImpl(code);
499}
500 
501export function abort(): void {
502 exit(1);
503}
504 
505// In future we may return accurate uptime information here, but returning
506// zero at least allows code paths to work correctly in most cases, and is
507// not a completely unreasonable interpretation of Cloudflare's execution
508// model assumptions.
509export function uptime(): number {
510 return 0;
511}
512 
513export function loadEnvFile(path: string | URL | Buffer = '.env'): void {
514 const { readFileSync } = process.getBuiltinModule('fs') as typeof NodeFS;
515 const parsed = parseEnv(
516 readFileSync(path instanceof URL ? path : path.toString(), 'utf8')
517 );
518 Object.assign(process.env, parsed);
519}
520 
521// On the virtual filesystem, we only support group 0
522export function getegid(): number {
523 return 0;
524}
525 
526export function getgid(): number {
527 return 0;
528}
529 
530export function getgroups(): number[] {
531 return [0];
532}
533 
534// On the virtual filesystem, we only support user 0
535export function geteuid(): number {
536 return 0;
537}
538 
539export function getuid(): number {
540 return 0;
541}
542 
543// We support group 0 but no others, with the virtual filesystem.
544export function setegid(id: number | string): void {
545 if (id !== 0) throw new ERR_EPERM({ syscall: 'setegid' });
546}
547 
548// We support group 0 but no others, with the virtual filesystem.
549export function setgid(id: number | string): void {
550 if (id !== 0) throw new ERR_EPERM({ syscall: 'setgid' });
551}
552 
553// We support group 0 but no others, with the virtual filesystem.
554export function seteuid(id: number | string): void {
555 if (id !== 0) throw new ERR_EPERM({ syscall: 'seteuid' });
556}
557 
558// We support group 0 but no others, with the virtual filesystem.
559export function setuid(id: number | string): void {
560 if (id !== 0) throw new ERR_EPERM({ syscall: 'setuid' });
561}
562 
563// We don't support setting or initializing arbitrary groups on the virtual filesystem.
564export function setgroups(_groups: number[]): void {
565 throw new ERR_EPERM({ syscall: 'setgroups' });
566}
567 
568export function initgroups(
569 _user: number | string,
570 _extractGroup: number | string
571): void {
572 throw new ERR_EPERM({ syscall: 'initgroups' });
573}
574 
575interface Process extends EventEmitter {
576 version: typeof version;
577 versions: typeof versions;
578 title: typeof title;
579 argv: typeof argv;
580 argv0: typeof argv0;
581 execArgv: typeof execArgv;
582 arch: typeof arch;
583 platform: typeof platform;
584 config: typeof config;
585 pid: typeof pid;
586 ppid: typeof ppid;
587 getegid: typeof getegid;
588 getgid: typeof getgid;
589 getgroups: typeof getgroups;
590 geteuid: typeof geteuid;
591 getuid: typeof getuid;
592 setegid: typeof setegid;
593 setgid: typeof setgid;
594 setgroups: typeof setgroups;
595 seteuid: typeof seteuid;
596 setuid: typeof setuid;
597 initgroups: typeof initgroups;
598 setSourceMapsEnabled: typeof setSourceMapsEnabled;
599 getSourceMapsSupport: typeof getSourceMapsSupport;
600 nextTick: typeof nextTick;
601 emitWarning: typeof emitWarning;
602 env: typeof env;
603 exit: typeof exit;
604 abort: typeof abort;
605 getBuiltinModule: typeof getBuiltinModule;
606 features: typeof features;
607 allowedNodeEnvironmentFlags: typeof allowedNodeEnvironmentFlags;
608 kill: typeof kill;
609 ref: typeof ref;
610 unref: typeof unref;
611 chdir: typeof chdir;
612 cwd: typeof cwd;
613 umask: typeof umask;
614 hrtime: typeof hrtime;
615 uptime: typeof uptime;
616 loadEnvFile: typeof loadEnvFile;
617 exitCode: typeof exitCode;
618 channel: typeof channel;
619 connected: typeof connected;
620 binding: typeof binding;
621 debugPort: typeof debugPort;
622 dlopen: typeof dlopen;
623 finalization: typeof finalization;
624 getActiveResourcesInfo: typeof getActiveResourcesInfo;
625 setUncaughtExceptionCaptureCallback: typeof setUncaughtExceptionCaptureCallback;
626 hasUncaughtExceptionCaptureCallback: typeof hasUncaughtExceptionCaptureCallback;
627 memoryUsage: typeof memoryUsage;
628 noDeprecation: typeof noDeprecation;
629 permission: typeof permission;
630 release: typeof release;
631 report: typeof report;
632 resourceUsage: typeof resourceUsage;
633 send: typeof send;
634 traceDeprecation: typeof traceDeprecation;
635 throwDeprecation: typeof throwDeprecation;
636 sourceMapsEnabled: typeof sourceMapsEnabled;
637 stdin: typeof stdin;
638 stdout: typeof stdout;
639 stderr: typeof stderr;
640 threadCpuUsage: typeof threadCpuUsage;
641 cpuUsage: typeof cpuUsage;
642 execPath: typeof execPath;
643 constrainedMemory: typeof constrainedMemory;
644 availableMemory: typeof availableMemory;
645 execve: typeof execve;
646 openStdin: typeof openStdin;
647 _rawDebug: typeof _rawDebug;
648 moduleLoadList: typeof moduleLoadList;
649 _linkedBinding: typeof _linkedBinding;
650 domain: typeof domain;
651 _exiting: typeof _exiting;
652 _getActiveRequests: typeof _getActiveRequests;
653 _getActiveHandles: typeof _getActiveHandles;
654 reallyExit: typeof reallyExit;
655 _kill: typeof _kill;
656 _fatalException: typeof _fatalException;
657 _tickCallback: typeof _tickCallback;
658 _debugProcess: typeof _debugProcess;
659 _debugEnd: typeof _debugEnd;
660 _startProfilerIdleNotifier: typeof _startProfilerIdleNotifier;
661 _stopProfilerIdleNotifier: typeof _stopProfilerIdleNotifier;
662 _preload_modules: typeof _preload_modules;
663}
664 
665export const _disconnect = undefined,
666 _handleQueue = undefined,
667 _pendingMessage = undefined,
668 _channel = undefined,
669 _send = undefined;
670 
671export let assert: typeof internalAssert.ok | undefined = undefined;
672 
673if (!Cloudflare.compatibilityFlags.remove_nodejs_compat_eol_v23) {
674 assert = internalAssert.ok.bind(internalAssert);
675}
676 
677const _process = {
678 assert,
679 version,
680 versions,
681 title,
682 argv,
683 argv0,
684 execArgv,
685 arch,
686 platform,
687 config,
688 pid,
689 ppid,
690 getegid,
691 getgid,
692 getgroups,
693 geteuid,
694 getuid,
695 setegid,
696 setgid,
697 setgroups,
698 seteuid,
699 setuid,
700 initgroups,
701 setSourceMapsEnabled,
702 getSourceMapsSupport,
703 nextTick,
704 emitWarning,
705 env,
706 exit,
707 abort,
708 getBuiltinModule,
709 features,
710 allowedNodeEnvironmentFlags,
711 kill,
712 ref,
713 unref,
714 chdir,
715 cwd,
716 umask,
717 hrtime,
718 uptime,
719 loadEnvFile,
720 exitCode,
721 channel,
722 connected,
723 binding,
724 debugPort,
725 dlopen,
726 finalization,
727 getActiveResourcesInfo,
728 setUncaughtExceptionCaptureCallback,
729 hasUncaughtExceptionCaptureCallback,
730 memoryUsage,
731 noDeprecation,
732 permission,
733 release,
734 report,
735 resourceUsage,
736 send,
737 traceDeprecation,
738 throwDeprecation,
739 sourceMapsEnabled,
740 stdin,
741 stdout,
742 stderr,
743 threadCpuUsage,
744 cpuUsage,
745 execPath,
746 constrainedMemory,
747 availableMemory,
748 execve,
749 openStdin,
750 _rawDebug,
751 moduleLoadList,
752 _linkedBinding,
753 domain,
754 _exiting,
755 _getActiveRequests,
756 _getActiveHandles,
757 reallyExit,
758 _kill,
759 _fatalException,
760 _tickCallback,
761 _debugProcess,
762 _debugEnd,
763 _startProfilerIdleNotifier,
764 _stopProfilerIdleNotifier,
765 _preload_modules,
766 _disconnect,
767 _handleQueue,
768 _pendingMessage,
769 _channel,
770 _send,
771};
772 
773const process: Process = Object.setPrototypeOf(
774 _process,
775 EventEmitter.prototype as object
776) as Process;
777EventEmitter.call(process);
778 
779Object.defineProperty(process, Symbol.toStringTag, {
780 value: 'process',
781 configurable: true,
782});
783 
784// We lazily attach unhandled rejection and rejection handled listeners
785// to ensure performance optimizations remain in the no listener case
786let addedUnhandledRejection = false,
787 addedRejectionHandled = false;
788process.on('newListener', (name) => {
789 if (name === 'unhandledRejection' && !addedUnhandledRejection) {
790 addEventListener(
791 'unhandledrejection',
792 function (evt: Event & { reason: unknown; promise: Promise<unknown> }) {
793 process.emit('unhandledRejection', evt.reason, evt.promise);
794 }
795 );
796 addedUnhandledRejection = true;
797 }
798 if (name === 'rejectionHandled' && !addedRejectionHandled) {
799 addEventListener(
800 'rejectionhandled',
801 function (evt: Event & { reason: unknown; promise: Promise<unknown> }) {
802 process.emit('rejectionHandled', evt.promise);
803 }
804 );
805 addedRejectionHandled = true;
806 }
807});
808 
809_setEventsProcess(process);
810 
811export const _events = process._events,
812 _eventsCount = process._eventsCount,
813 _maxListeners = process._maxListeners;
814 
815export default process;