Spaces:
Running
Running
; | |
var _a; | |
Object.defineProperty(exports, "__esModule", { value: true }); | |
exports.unload = exports.load = exports.onExit = exports.signals = void 0; | |
// Note: since nyc uses this module to output coverage, any lines | |
// that are in the direct sync flow of nyc's outputCoverage are | |
// ignored, since we can never get coverage for them. | |
// grab a reference to node's real process object right away | |
const signals_js_1 = require("./signals.js"); | |
Object.defineProperty(exports, "signals", { enumerable: true, get: function () { return signals_js_1.signals; } }); | |
const processOk = (process) => !!process && | |
typeof process === 'object' && | |
typeof process.removeListener === 'function' && | |
typeof process.emit === 'function' && | |
typeof process.reallyExit === 'function' && | |
typeof process.listeners === 'function' && | |
typeof process.kill === 'function' && | |
typeof process.pid === 'number' && | |
typeof process.on === 'function'; | |
const kExitEmitter = Symbol.for('signal-exit emitter'); | |
const global = globalThis; | |
const ObjectDefineProperty = Object.defineProperty.bind(Object); | |
// teeny special purpose ee | |
class Emitter { | |
emitted = { | |
afterExit: false, | |
exit: false, | |
}; | |
listeners = { | |
afterExit: [], | |
exit: [], | |
}; | |
count = 0; | |
id = Math.random(); | |
constructor() { | |
if (global[kExitEmitter]) { | |
return global[kExitEmitter]; | |
} | |
ObjectDefineProperty(global, kExitEmitter, { | |
value: this, | |
writable: false, | |
enumerable: false, | |
configurable: false, | |
}); | |
} | |
on(ev, fn) { | |
this.listeners[ev].push(fn); | |
} | |
removeListener(ev, fn) { | |
const list = this.listeners[ev]; | |
const i = list.indexOf(fn); | |
/* c8 ignore start */ | |
if (i === -1) { | |
return; | |
} | |
/* c8 ignore stop */ | |
if (i === 0 && list.length === 1) { | |
list.length = 0; | |
} | |
else { | |
list.splice(i, 1); | |
} | |
} | |
emit(ev, code, signal) { | |
if (this.emitted[ev]) { | |
return false; | |
} | |
this.emitted[ev] = true; | |
let ret = false; | |
for (const fn of this.listeners[ev]) { | |
ret = fn(code, signal) === true || ret; | |
} | |
if (ev === 'exit') { | |
ret = this.emit('afterExit', code, signal) || ret; | |
} | |
return ret; | |
} | |
} | |
class SignalExitBase { | |
} | |
const signalExitWrap = (handler) => { | |
return { | |
onExit(cb, opts) { | |
return handler.onExit(cb, opts); | |
}, | |
load() { | |
return handler.load(); | |
}, | |
unload() { | |
return handler.unload(); | |
}, | |
}; | |
}; | |
class SignalExitFallback extends SignalExitBase { | |
onExit() { | |
return () => { }; | |
} | |
load() { } | |
unload() { } | |
} | |
class SignalExit extends SignalExitBase { | |
// "SIGHUP" throws an `ENOSYS` error on Windows, | |
// so use a supported signal instead | |
/* c8 ignore start */ | |
#hupSig = process.platform === 'win32' ? 'SIGINT' : 'SIGHUP'; | |
/* c8 ignore stop */ | |
#emitter = new Emitter(); | |
#process; | |
#originalProcessEmit; | |
#originalProcessReallyExit; | |
#sigListeners = {}; | |
#loaded = false; | |
constructor(process) { | |
super(); | |
this.#process = process; | |
// { <signal>: <listener fn>, ... } | |
this.#sigListeners = {}; | |
for (const sig of signals_js_1.signals) { | |
this.#sigListeners[sig] = () => { | |
// If there are no other listeners, an exit is coming! | |
// Simplest way: remove us and then re-send the signal. | |
// We know that this will kill the process, so we can | |
// safely emit now. | |
const listeners = this.#process.listeners(sig); | |
let { count } = this.#emitter; | |
// This is a workaround for the fact that signal-exit v3 and signal | |
// exit v4 are not aware of each other, and each will attempt to let | |
// the other handle it, so neither of them do. To correct this, we | |
// detect if we're the only handler *except* for previous versions | |
// of signal-exit, and increment by the count of listeners it has | |
// created. | |
/* c8 ignore start */ | |
const p = process; | |
if (typeof p.__signal_exit_emitter__ === 'object' && | |
typeof p.__signal_exit_emitter__.count === 'number') { | |
count += p.__signal_exit_emitter__.count; | |
} | |
/* c8 ignore stop */ | |
if (listeners.length === count) { | |
this.unload(); | |
const ret = this.#emitter.emit('exit', null, sig); | |
/* c8 ignore start */ | |
const s = sig === 'SIGHUP' ? this.#hupSig : sig; | |
if (!ret) | |
process.kill(process.pid, s); | |
/* c8 ignore stop */ | |
} | |
}; | |
} | |
this.#originalProcessReallyExit = process.reallyExit; | |
this.#originalProcessEmit = process.emit; | |
} | |
onExit(cb, opts) { | |
/* c8 ignore start */ | |
if (!processOk(this.#process)) { | |
return () => { }; | |
} | |
/* c8 ignore stop */ | |
if (this.#loaded === false) { | |
this.load(); | |
} | |
const ev = opts?.alwaysLast ? 'afterExit' : 'exit'; | |
this.#emitter.on(ev, cb); | |
return () => { | |
this.#emitter.removeListener(ev, cb); | |
if (this.#emitter.listeners['exit'].length === 0 && | |
this.#emitter.listeners['afterExit'].length === 0) { | |
this.unload(); | |
} | |
}; | |
} | |
load() { | |
if (this.#loaded) { | |
return; | |
} | |
this.#loaded = true; | |
// This is the number of onSignalExit's that are in play. | |
// It's important so that we can count the correct number of | |
// listeners on signals, and don't wait for the other one to | |
// handle it instead of us. | |
this.#emitter.count += 1; | |
for (const sig of signals_js_1.signals) { | |
try { | |
const fn = this.#sigListeners[sig]; | |
if (fn) | |
this.#process.on(sig, fn); | |
} | |
catch (_) { } | |
} | |
this.#process.emit = (ev, ...a) => { | |
return this.#processEmit(ev, ...a); | |
}; | |
this.#process.reallyExit = (code) => { | |
return this.#processReallyExit(code); | |
}; | |
} | |
unload() { | |
if (!this.#loaded) { | |
return; | |
} | |
this.#loaded = false; | |
signals_js_1.signals.forEach(sig => { | |
const listener = this.#sigListeners[sig]; | |
/* c8 ignore start */ | |
if (!listener) { | |
throw new Error('Listener not defined for signal: ' + sig); | |
} | |
/* c8 ignore stop */ | |
try { | |
this.#process.removeListener(sig, listener); | |
/* c8 ignore start */ | |
} | |
catch (_) { } | |
/* c8 ignore stop */ | |
}); | |
this.#process.emit = this.#originalProcessEmit; | |
this.#process.reallyExit = this.#originalProcessReallyExit; | |
this.#emitter.count -= 1; | |
} | |
#processReallyExit(code) { | |
/* c8 ignore start */ | |
if (!processOk(this.#process)) { | |
return 0; | |
} | |
this.#process.exitCode = code || 0; | |
/* c8 ignore stop */ | |
this.#emitter.emit('exit', this.#process.exitCode, null); | |
return this.#originalProcessReallyExit.call(this.#process, this.#process.exitCode); | |
} | |
#processEmit(ev, ...args) { | |
const og = this.#originalProcessEmit; | |
if (ev === 'exit' && processOk(this.#process)) { | |
if (typeof args[0] === 'number') { | |
this.#process.exitCode = args[0]; | |
/* c8 ignore start */ | |
} | |
/* c8 ignore start */ | |
const ret = og.call(this.#process, ev, ...args); | |
/* c8 ignore start */ | |
this.#emitter.emit('exit', this.#process.exitCode, null); | |
/* c8 ignore stop */ | |
return ret; | |
} | |
else { | |
return og.call(this.#process, ev, ...args); | |
} | |
} | |
} | |
const process = globalThis.process; | |
// wrap so that we call the method on the actual handler, without | |
// exporting it directly. | |
_a = signalExitWrap(processOk(process) ? new SignalExit(process) : new SignalExitFallback()), | |
/** | |
* Called when the process is exiting, whether via signal, explicit | |
* exit, or running out of stuff to do. | |
* | |
* If the global process object is not suitable for instrumentation, | |
* then this will be a no-op. | |
* | |
* Returns a function that may be used to unload signal-exit. | |
*/ | |
exports.onExit = _a.onExit, | |
/** | |
* Load the listeners. Likely you never need to call this, unless | |
* doing a rather deep integration with signal-exit functionality. | |
* Mostly exposed for the benefit of testing. | |
* | |
* @internal | |
*/ | |
exports.load = _a.load, | |
/** | |
* Unload the listeners. Likely you never need to call this, unless | |
* doing a rather deep integration with signal-exit functionality. | |
* Mostly exposed for the benefit of testing. | |
* | |
* @internal | |
*/ | |
exports.unload = _a.unload; | |
//# sourceMappingURL=index.js.map |