diff --git a/doc/api/events.md b/doc/api/events.md index 30985b1ce0c12f..be9de5d9aca0a2 100644 --- a/doc/api/events.md +++ b/doc/api/events.md @@ -1171,6 +1171,10 @@ that a "possible EventEmitter memory leak" has been detected. For any single `EventEmitter`, the `emitter.getMaxListeners()` and `emitter.setMaxListeners()` methods can be used to temporarily avoid this warning: +`defaultMaxListeners` has no effect on `AbortSignal` instances. While it is +still possible to use [`emitter.setMaxListeners(n)`][] to set a warning limit +for individual `AbortSignal` instances, per default `AbortSignal` instances will not warn. + ```mjs import { EventEmitter } from 'node:events'; const emitter = new EventEmitter(); diff --git a/lib/internal/abort_controller.js b/lib/internal/abort_controller.js index b812f588c23e99..6dd40cb00e9950 100644 --- a/lib/internal/abort_controller.js +++ b/lib/internal/abort_controller.js @@ -28,6 +28,7 @@ const { kResistStopPropagation, kWeakHandler, } = require('internal/event_target'); +const { kMaxEventTargetListeners } = require('events'); const { customInspectSymbol, kEmptyObject, @@ -164,6 +165,7 @@ class AbortSignal extends EventTarget { } super(); + this[kMaxEventTargetListeners] = 0; const { aborted = false, reason = undefined, diff --git a/test/parallel/test-eventtarget-memoryleakwarning.js b/test/parallel/test-eventtarget-memoryleakwarning.js index b2da553ab4cacb..2c907165d865d9 100644 --- a/test/parallel/test-eventtarget-memoryleakwarning.js +++ b/test/parallel/test-eventtarget-memoryleakwarning.js @@ -12,22 +12,22 @@ const { setTimeout } = require('timers/promises'); common.expectWarning({ MaxListenersExceededWarning: [ ['Possible EventTarget memory leak detected. 3 foo listeners added to ' + - 'EventTarget. MaxListeners is 2. Use events.setMaxListeners() ' + + 'EventTarget. MaxListeners is 2. Use events.setMaxListeners() ' + 'to increase limit'], ['Possible EventTarget memory leak detected. 3 foo listeners added to ' + - '[MessagePort [EventTarget]]. ' + - 'MaxListeners is 2. ' + - 'Use events.setMaxListeners() to increase ' + + '[MessagePort [EventTarget]]. ' + + 'MaxListeners is 2. ' + + 'Use events.setMaxListeners() to increase ' + 'limit'], ['Possible EventTarget memory leak detected. 3 foo listeners added to ' + - '[MessagePort [EventTarget]]. ' + - 'MaxListeners is 2. ' + - 'Use events.setMaxListeners() to increase ' + + '[MessagePort [EventTarget]]. ' + + 'MaxListeners is 2. ' + + 'Use events.setMaxListeners() to increase ' + 'limit'], - ['Possible EventTarget memory leak detected. 3 foo listeners added to ' + - '[AbortSignal]. ' + - 'MaxListeners is 2. ' + - 'Use events.setMaxListeners() to increase ' + + ['Possible EventTarget memory leak detected. 2 foo listeners added to ' + + '[AbortSignal]. ' + + 'MaxListeners is 1. ' + + 'Use events.setMaxListeners() to increase ' + 'limit'], ], }); @@ -65,13 +65,25 @@ common.expectWarning({ mc.port1.addEventListener('foo', () => {}); mc.port1.addEventListener('foo', () => {}); mc.port1.addEventListener('foo', () => {}); +} +{ + // No warning emitted because AbortController ignores `EventEmitter.defaultMaxListeners` + setMaxListeners(2); const ac = new AbortController(); ac.signal.addEventListener('foo', () => {}); ac.signal.addEventListener('foo', () => {}); ac.signal.addEventListener('foo', () => {}); } +{ + // Will still warn as `setMaxListeners` can still manually set a limit + const ac = new AbortController(); + setMaxListeners(1, ac.signal); + ac.signal.addEventListener('foo', () => {}); + ac.signal.addEventListener('foo', () => {}); +} + { // It works for EventEmitters also const ee = new EventEmitter();