repl: keep reference count for `process.on('newListener')` · nodejs/node@2ca42c8
@@ -186,7 +186,35 @@ const domainSet = new SafeWeakSet();
186186const kBufferedCommandSymbol = Symbol('bufferedCommand');
187187const kLoadingSymbol = Symbol('loading');
188188189-let addedNewListener = false;
189+function processNewListener(event, listener) {
190+if (event === 'uncaughtException' &&
191+process.domain &&
192+listener.name !== 'domainUncaughtExceptionClear' &&
193+domainSet.has(process.domain)) {
194+// Throw an error so that the event will not be added and the current
195+// domain takes over. That way the user is notified about the error
196+// and the current code evaluation is stopped, just as any other code
197+// that contains an error.
198+throw new ERR_INVALID_REPL_INPUT(
199+'Listeners for `uncaughtException` cannot be used in the REPL');
200+}
201+}
202+203+let processNewListenerUseCount = 0;
204+function addProcessNewListener() {
205+if (processNewListenerUseCount++ === 0) {
206+// Add this listener only once and use a WeakSet that contains the REPLs
207+// domains. Otherwise we'd have to add a single listener to each REPL
208+// instance and that could trigger the `MaxListenersExceededWarning`.
209+process.prependListener('newListener', processNewListener);
210+}
211+}
212+213+function removeProcessNewListener() {
214+if (--processNewListenerUseCount === 0) {
215+process.removeListener('newListener', processNewListener);
216+}
217+}
190218191219fixReplRequire(module);
192220@@ -327,24 +355,9 @@ function REPLServer(prompt,
327355// It is possible to introspect the running REPL accessing this variable
328356// from inside the REPL. This is useful for anyone working on the REPL.
329357module.exports.repl = this;
330-} else if (!addedNewListener) {
331-// Add this listener only once and use a WeakSet that contains the REPLs
332-// domains. Otherwise we'd have to add a single listener to each REPL
333-// instance and that could trigger the `MaxListenersExceededWarning`.
334-process.prependListener('newListener', (event, listener) => {
335-if (event === 'uncaughtException' &&
336-process.domain &&
337-listener.name !== 'domainUncaughtExceptionClear' &&
338-domainSet.has(process.domain)) {
339-// Throw an error so that the event will not be added and the current
340-// domain takes over. That way the user is notified about the error
341-// and the current code evaluation is stopped, just as any other code
342-// that contains an error.
343-throw new ERR_INVALID_REPL_INPUT(
344-'Listeners for `uncaughtException` cannot be used in the REPL');
345-}
346-});
347-addedNewListener = true;
358+} else {
359+addProcessNewListener();
360+this.once('exit', removeProcessNewListener);
348361}
349362350363domainSet.add(this._domain);