index.js 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. "use strict";
  2. var __importDefault = (this && this.__importDefault) || function (mod) {
  3. return (mod && mod.__esModule) ? mod : { "default": mod };
  4. };
  5. Object.defineProperty(exports, "__esModule", { value: true });
  6. exports.foregroundChild = exports.normalizeFgArgs = void 0;
  7. const child_process_1 = require("child_process");
  8. const cross_spawn_1 = __importDefault(require("cross-spawn"));
  9. const signal_exit_1 = require("signal-exit");
  10. const proxy_signals_js_1 = require("./proxy-signals.js");
  11. const watchdog_js_1 = require("./watchdog.js");
  12. /* c8 ignore start */
  13. const spawn = process?.platform === 'win32' ? cross_spawn_1.default : child_process_1.spawn;
  14. /**
  15. * Normalizes the arguments passed to `foregroundChild`.
  16. *
  17. * Exposed for testing.
  18. *
  19. * @internal
  20. */
  21. const normalizeFgArgs = (fgArgs) => {
  22. let [program, args = [], spawnOpts = {}, cleanup = () => { }] = fgArgs;
  23. if (typeof args === 'function') {
  24. cleanup = args;
  25. spawnOpts = {};
  26. args = [];
  27. }
  28. else if (!!args && typeof args === 'object' && !Array.isArray(args)) {
  29. if (typeof spawnOpts === 'function')
  30. cleanup = spawnOpts;
  31. spawnOpts = args;
  32. args = [];
  33. }
  34. else if (typeof spawnOpts === 'function') {
  35. cleanup = spawnOpts;
  36. spawnOpts = {};
  37. }
  38. if (Array.isArray(program)) {
  39. const [pp, ...pa] = program;
  40. program = pp;
  41. args = pa;
  42. }
  43. return [program, args, { ...spawnOpts }, cleanup];
  44. };
  45. exports.normalizeFgArgs = normalizeFgArgs;
  46. function foregroundChild(...fgArgs) {
  47. const [program, args, spawnOpts, cleanup] = (0, exports.normalizeFgArgs)(fgArgs);
  48. spawnOpts.stdio = [0, 1, 2];
  49. if (process.send) {
  50. spawnOpts.stdio.push('ipc');
  51. }
  52. const child = spawn(program, args, spawnOpts);
  53. const childHangup = () => {
  54. try {
  55. child.kill('SIGHUP');
  56. /* c8 ignore start */
  57. }
  58. catch (_) {
  59. // SIGHUP is weird on windows
  60. child.kill('SIGTERM');
  61. }
  62. /* c8 ignore stop */
  63. };
  64. const removeOnExit = (0, signal_exit_1.onExit)(childHangup);
  65. (0, proxy_signals_js_1.proxySignals)(child);
  66. const dog = (0, watchdog_js_1.watchdog)(child);
  67. let done = false;
  68. child.on('close', async (code, signal) => {
  69. /* c8 ignore start */
  70. if (done)
  71. return;
  72. /* c8 ignore stop */
  73. done = true;
  74. const result = cleanup(code, signal, {
  75. watchdogPid: dog.pid,
  76. });
  77. const res = isPromise(result) ? await result : result;
  78. removeOnExit();
  79. if (res === false)
  80. return;
  81. else if (typeof res === 'string') {
  82. signal = res;
  83. code = null;
  84. }
  85. else if (typeof res === 'number') {
  86. code = res;
  87. signal = null;
  88. }
  89. if (signal) {
  90. // If there is nothing else keeping the event loop alive,
  91. // then there's a race between a graceful exit and getting
  92. // the signal to this process. Put this timeout here to
  93. // make sure we're still alive to get the signal, and thus
  94. // exit with the intended signal code.
  95. /* istanbul ignore next */
  96. setTimeout(() => { }, 2000);
  97. try {
  98. process.kill(process.pid, signal);
  99. /* c8 ignore start */
  100. }
  101. catch (_) {
  102. process.kill(process.pid, 'SIGTERM');
  103. }
  104. /* c8 ignore stop */
  105. }
  106. else {
  107. process.exit(code || 0);
  108. }
  109. });
  110. if (process.send) {
  111. process.removeAllListeners('message');
  112. child.on('message', (message, sendHandle) => {
  113. process.send?.(message, sendHandle);
  114. });
  115. process.on('message', (message, sendHandle) => {
  116. child.send(message, sendHandle);
  117. });
  118. }
  119. return child;
  120. }
  121. exports.foregroundChild = foregroundChild;
  122. const isPromise = (o) => !!o && typeof o === 'object' && typeof o.then === 'function';
  123. //# sourceMappingURL=index.js.map