repl: keep reference count for `process.on('newListener')` · nodejs/node@999bf22
@@ -183,7 +183,35 @@ const domainSet = new SafeWeakSet();
183183const kBufferedCommandSymbol = Symbol('bufferedCommand');
184184const kLoadingSymbol = Symbol('loading');
185185186-let addedNewListener = false;
186+function processNewListener(event, listener) {
187+if (event === 'uncaughtException' &&
188+process.domain &&
189+listener.name !== 'domainUncaughtExceptionClear' &&
190+domainSet.has(process.domain)) {
191+// Throw an error so that the event will not be added and the current
192+// domain takes over. That way the user is notified about the error
193+// and the current code evaluation is stopped, just as any other code
194+// that contains an error.
195+throw new ERR_INVALID_REPL_INPUT(
196+'Listeners for `uncaughtException` cannot be used in the REPL');
197+}
198+}
199+200+let processNewListenerUseCount = 0;
201+function addProcessNewListener() {
202+if (processNewListenerUseCount++ === 0) {
203+// Add this listener only once and use a WeakSet that contains the REPLs
204+// domains. Otherwise we'd have to add a single listener to each REPL
205+// instance and that could trigger the `MaxListenersExceededWarning`.
206+process.prependListener('newListener', processNewListener);
207+}
208+}
209+210+function removeProcessNewListener() {
211+if (--processNewListenerUseCount === 0) {
212+process.removeListener('newListener', processNewListener);
213+}
214+}
187215188216fixReplRequire(module);
189217@@ -337,24 +365,9 @@ class REPLServer extends Interface {
337365// It is possible to introspect the running REPL accessing this variable
338366// from inside the REPL. This is useful for anyone working on the REPL.
339367module.exports.repl = this;
340-} else if (!addedNewListener) {
341-// Add this listener only once and use a WeakSet that contains the REPLs
342-// domains. Otherwise we'd have to add a single listener to each REPL
343-// instance and that could trigger the `MaxListenersExceededWarning`.
344-process.prependListener('newListener', (event, listener) => {
345-if (event === 'uncaughtException' &&
346-process.domain &&
347-listener.name !== 'domainUncaughtExceptionClear' &&
348-domainSet.has(process.domain)) {
349-// Throw an error so that the event will not be added and the current
350-// domain takes over. That way the user is notified about the error
351-// and the current code evaluation is stopped, just as any other code
352-// that contains an error.
353-throw new ERR_INVALID_REPL_INPUT(
354-'Listeners for `uncaughtException` cannot be used in the REPL');
355-}
356-});
357-addedNewListener = true;
368+} else {
369+addProcessNewListener();
370+this.once('exit', removeProcessNewListener);
358371}
359372360373domainSet.add(this._domain);