123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150 |
- import { EventEmitter } from 'events';
- import { Duplex, PassThrough } from 'stream';
- import { Socket } from 'net';
- import { MessagePortMain } from '@electron/internal/browser/message-port-main';
- const { _fork } = process._linkedBinding('electron_browser_utility_process');
- class ForkUtilityProcess extends EventEmitter {
- #handle: ElectronInternal.UtilityProcessWrapper | null;
- #stdout: Duplex | null = null;
- #stderr: Duplex | null = null;
- constructor (modulePath: string, args?: string[], options?: Electron.ForkOptions) {
- super();
- if (!modulePath) {
- throw new Error('Missing UtilityProcess entry script.');
- }
- if (args == null) {
- args = [];
- } else if (typeof args === 'object' && !Array.isArray(args)) {
- options = args;
- args = [];
- }
- if (options == null) {
- options = {};
- } else {
- options = { ...options };
- }
- if (!options) {
- throw new Error('Options cannot be undefined.');
- }
- if (options.execArgv != null) {
- if (!Array.isArray(options.execArgv)) {
- throw new TypeError('execArgv must be an array of strings.');
- }
- }
- if (options.serviceName != null) {
- if (typeof options.serviceName !== 'string') {
- throw new TypeError('serviceName must be a string.');
- }
- }
- if (options.cwd != null) {
- if (typeof options.cwd !== 'string') {
- throw new TypeError('cwd path must be a string.');
- }
- }
- if (typeof options.stdio === 'string') {
- const stdio : Array<'pipe' | 'ignore' | 'inherit'> = [];
- switch (options.stdio) {
- case 'inherit':
- case 'ignore':
- stdio.push('ignore', options.stdio, options.stdio);
- break;
- case 'pipe':
- this.#stderr = new PassThrough();
- this.#stdout = new PassThrough();
- stdio.push('ignore', options.stdio, options.stdio);
- break;
- default:
- throw new Error('stdio must be of the following values: inherit, pipe, ignore');
- }
- options.stdio = stdio;
- } else if (Array.isArray(options.stdio)) {
- if (options.stdio.length >= 3) {
- if (options.stdio[0] !== 'ignore') {
- throw new Error('stdin value other than ignore is not supported.');
- }
- if (options.stdio[1] === 'pipe') {
- this.#stdout = new PassThrough();
- } else if (options.stdio[1] !== 'ignore' && options.stdio[1] !== 'inherit') {
- throw new Error('stdout configuration must be of the following values: inherit, pipe, ignore');
- }
- if (options.stdio[2] === 'pipe') {
- this.#stderr = new PassThrough();
- } else if (options.stdio[2] !== 'ignore' && options.stdio[2] !== 'inherit') {
- throw new Error('stderr configuration must be of the following values: inherit, pipe, ignore');
- }
- } else {
- throw new Error('configuration missing for stdin, stdout or stderr.');
- }
- }
- this.#handle = _fork({ options, modulePath, args });
- this.#handle!.emit = (channel: string | symbol, ...args: any[]) => {
- if (channel === 'exit') {
- try {
- this.emit('exit', ...args);
- } finally {
- this.#handle = null;
- if (this.#stdout) {
- this.#stdout.removeAllListeners();
- this.#stdout = null;
- }
- if (this.#stderr) {
- this.#stderr.removeAllListeners();
- this.#stderr = null;
- }
- }
- return false;
- } else if (channel === 'stdout' && this.#stdout) {
- new Socket({ fd: args[0], readable: true }).pipe(this.#stdout);
- return true;
- } else if (channel === 'stderr' && this.#stderr) {
- new Socket({ fd: args[0], readable: true }).pipe(this.#stderr);
- return true;
- } else {
- return this.emit(channel, ...args);
- }
- };
- }
- get pid () {
- return this.#handle?.pid;
- }
- get stdout () {
- return this.#stdout;
- }
- get stderr () {
- return this.#stderr;
- }
- postMessage (message: any, transfer?: MessagePortMain[]) {
- if (Array.isArray(transfer)) {
- transfer = transfer.map((o: any) => o instanceof MessagePortMain ? o._internalPort : o);
- return this.#handle?.postMessage(message, transfer);
- }
- return this.#handle?.postMessage(message);
- }
- kill () : boolean {
- if (this.#handle === null) {
- return false;
- }
- return this.#handle.kill();
- }
- }
- export function fork (modulePath: string, args?: string[], options?: Electron.ForkOptions) {
- return new ForkUtilityProcess(modulePath, args, options);
- }
|