import child_process from 'child_process'; import net from "net"; import { RpcMessage, RpcPeer } from "../../rpc"; import { SidebandSocketSerializer } from "../socket-serializer"; import { ChildProcessWorker } from "./child-process-worker"; import { RuntimeWorkerOptions } from "./runtime-worker"; import worker_threads from 'worker_threads'; export class NodeForkWorker extends ChildProcessWorker { constructor(mainFilename: string, pluginId: string, options: RuntimeWorkerOptions) { super(pluginId, options); const { env, pluginDebug } = options; const execArgv: string[] = process.execArgv.slice(); if (pluginDebug) { execArgv.push(`--inspect=0.0.0.0:${pluginDebug.inspectPort}`); } this.worker = child_process.fork(mainFilename, [ worker_threads.isMainThread ? 'child' : 'fork', this.pluginId ], { stdio: ['pipe', 'pipe', 'pipe', 'ipc'], env: Object.assign({}, process.env, env), serialization: 'advanced', execArgv, }); this.setupWorker(); } setupRpcPeer(peer: RpcPeer): void { this.worker.on('message', (message, sendHandle) => { if ((message as any).type && sendHandle) { peer.handleMessage(message as any, { sendHandle, }); } else if (sendHandle) { this.emit('rpc', message, sendHandle); } else { peer.handleMessage(message as any); } }); peer.transportSafeArgumentTypes.add(Buffer.name); peer.transportSafeArgumentTypes.add(Uint8Array.name); peer.addSerializer(net.Socket, net.Socket.name, new SidebandSocketSerializer()); } send(message: RpcMessage, reject?: (e: Error) => void, serializationContext?: any): void { try { if (!this.worker) throw new Error('fork worker has been killed'); this.worker.send(message, serializationContext?.sendHandle, e => { if (e && reject) reject(e); }); } catch (e) { reject?.(e); } } get pid() { return this.worker?.pid; } }