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