관리-도구
편집 파일: index.js
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.foregroundChild = exports.normalizeFgArgs = void 0; const child_process_1 = require("child_process"); const cross_spawn_1 = __importDefault(require("cross-spawn")); const signal_exit_1 = require("signal-exit"); const all_signals_js_1 = require("./all-signals.js"); const watchdog_js_1 = require("./watchdog.js"); /* c8 ignore start */ const spawn = process?.platform === 'win32' ? cross_spawn_1.default : child_process_1.spawn; /** * Normalizes the arguments passed to `foregroundChild`. * * Exposed for testing. * * @internal */ const normalizeFgArgs = (fgArgs) => { let [program, args = [], spawnOpts = {}, cleanup = () => { }] = fgArgs; if (typeof args === 'function') { cleanup = args; spawnOpts = {}; args = []; } else if (!!args && typeof args === 'object' && !Array.isArray(args)) { if (typeof spawnOpts === 'function') cleanup = spawnOpts; spawnOpts = args; args = []; } else if (typeof spawnOpts === 'function') { cleanup = spawnOpts; spawnOpts = {}; } if (Array.isArray(program)) { const [pp, ...pa] = program; program = pp; args = pa; } return [program, args, { ...spawnOpts }, cleanup]; }; exports.normalizeFgArgs = normalizeFgArgs; function foregroundChild(...fgArgs) { const [program, args, spawnOpts, cleanup] = (0, exports.normalizeFgArgs)(fgArgs); spawnOpts.stdio = [0, 1, 2]; if (process.send) { spawnOpts.stdio.push('ipc'); } const child = spawn(program, args, spawnOpts); const unproxySignals = proxySignals(child); const childHangup = () => { try { child.kill('SIGHUP'); /* c8 ignore start */ } catch (_) { // SIGHUP is weird on windows child.kill('SIGTERM'); } /* c8 ignore stop */ }; const removeOnExit = (0, signal_exit_1.onExit)(childHangup); const dog = (0, watchdog_js_1.watchdog)(child); let done = false; child.on('close', async (code, signal) => { dog.kill('SIGKILL'); /* c8 ignore start */ if (done) { return; } /* c8 ignore stop */ done = true; const result = cleanup(code, signal); const res = isPromise(result) ? await result : result; removeOnExit(); unproxySignals(); if (res === false) return; else if (typeof res === 'string') { signal = res; code = null; } else if (typeof res === 'number') { code = res; signal = null; } if (signal) { // If there is nothing else keeping the event loop alive, // then there's a race between a graceful exit and getting // the signal to this process. Put this timeout here to // make sure we're still alive to get the signal, and thus // exit with the intended signal code. /* istanbul ignore next */ setTimeout(() => { }, 2000); try { process.kill(process.pid, signal); /* c8 ignore start */ } catch (_) { process.kill(process.pid, 'SIGTERM'); } /* c8 ignore stop */ } else { process.exit(code || 0); } }); if (process.send) { process.removeAllListeners('message'); child.on('message', (message, sendHandle) => { process.send?.(message, sendHandle); }); process.on('message', (message, sendHandle) => { child.send(message, sendHandle); }); } return child; } exports.foregroundChild = foregroundChild; /** * Starts forwarding signals to `child` through `parent`. */ const proxySignals = (child) => { const listeners = new Map(); for (const sig of all_signals_js_1.allSignals) { const listener = () => { // some signals can only be received, not sent try { child.kill(sig); /* c8 ignore start */ } catch (_) { } /* c8 ignore stop */ }; try { // if it's a signal this system doesn't recognize, skip it process.on(sig, listener); listeners.set(sig, listener); /* c8 ignore start */ } catch (_) { } /* c8 ignore stop */ } return () => { for (const [sig, listener] of listeners) { process.removeListener(sig, listener); } }; }; const isPromise = (o) => !!o && typeof o === 'object' && typeof o.then === 'function'; //# sourceMappingURL=index.js.map