Repository: denoland/deno
Pull request: fix(ext/node): add events `getMaxListeners`

Enables `parallel/test-events-getmaxlisteners.js`

Towards #29595 

Changed files:
filename: ext/node/polyfills/_events.mjs
patch: @@ -76,6 +76,7 @@ EventEmitter.on = on;
 EventEmitter.once = once;
 EventEmitter.getEventListeners = getEventListeners;
 EventEmitter.setMaxListeners = setMaxListeners;
+EventEmitter.getMaxListeners = getMaxListeners;
 EventEmitter.listenerCount = listenerCount;
 // Backwards-compat with node 0.10.x
 EventEmitter.EventEmitter = EventEmitter;
@@ -251,6 +252,33 @@ EventEmitter.prototype.setMaxListeners = function setMaxListeners(n) {
   return this;
 };
 
+/**
+ * Returns the max listeners set.
+ * @param {EventEmitter | EventTarget} emitterOrTarget
+ * @returns {number}
+ */
+export function getMaxListeners(emitterOrTarget) {
+  if (typeof emitterOrTarget?.getMaxListeners === "function") {
+    return _getMaxListeners(emitterOrTarget);
+  } else if (
+    typeof emitterOrTarget?.[kMaxEventTargetListeners] === "number"
+  ) {
+    return emitterOrTarget[kMaxEventTargetListeners] ?? defaultMaxListeners;
+  } else if (emitterOrTarget instanceof AbortSignal) {
+    return 0; // default for AbortController if not set by EventTarget prototype.
+  } else if (
+    emitterOrTarget instanceof EventTarget
+  ) {
+    return defaultMaxListeners;
+  }
+
+  throw new ERR_INVALID_ARG_TYPE(
+    "emitter",
+    ["EventEmitter", "EventTarget"],
+    emitterOrTarget,
+  );
+}
+
 function _getMaxListeners(that) {
   if (that._maxListeners === undefined) {
     return EventEmitter.defaultMaxListeners;

filename: ext/node/polyfills/events.ts
patch: @@ -9,6 +9,7 @@ export {
   EventEmitter,
   EventEmitterAsyncResource,
   getEventListeners,
+  getMaxListeners,
   listenerCount,
   on,
   once,

filename: tests/node_compat/config.jsonc
patch: @@ -533,6 +533,7 @@
       "test-event-emitter-subclass.js",
       "test-event-emitter-symbols.js",
       "test-events-add-abort-listener.mjs",
+      "test-events-getmaxlisteners.js",
       "test-events-list.js",
       "test-events-on-async-iterator.js",
       "test-events-once.js",

filename: tests/node_compat/runner/TODO.md
patch: @@ -748,7 +748,6 @@ NOTE: This file should not be manually edited. Please edit `tests/node_compat/co
 - [parallel/test-event-target.js](https://github.com/nodejs/node/tree/v23.9.0/test/parallel/test-event-target.js)
 - [parallel/test-eventemitter-asyncresource.js](https://github.com/nodejs/node/tree/v23.9.0/test/parallel/test-eventemitter-asyncresource.js)
 - [parallel/test-events-customevent.js](https://github.com/nodejs/node/tree/v23.9.0/test/parallel/test-events-customevent.js)
-- [parallel/test-events-getmaxlisteners.js](https://github.com/nodejs/node/tree/v23.9.0/test/parallel/test-events-getmaxlisteners.js)
 - [parallel/test-events-listener-count-with-listener.js](https://github.com/nodejs/node/tree/v23.9.0/test/parallel/test-events-listener-count-with-listener.js)
 - [parallel/test-events-static-geteventlisteners.js](https://github.com/nodejs/node/tree/v23.9.0/test/parallel/test-events-static-geteventlisteners.js)
 - [parallel/test-eventsource-disabled.js](https://github.com/nodejs/node/tree/v23.9.0/test/parallel/test-eventsource-disabled.js)

filename: tests/node_compat/test/parallel/test-events-getmaxlisteners.js
patch: @@ -0,0 +1,31 @@
+// deno-fmt-ignore-file
+// deno-lint-ignore-file
+
+// Copyright Joyent and Node contributors. All rights reserved. MIT license.
+// Taken from Node 23.9.0
+// This file is automatically generated by `tests/node_compat/runner/setup.ts`. Do not modify this file manually.
+
+'use strict';
+
+require('../common');
+const assert = require('node:assert');
+const { getMaxListeners, EventEmitter, defaultMaxListeners, setMaxListeners } = require('node:events');
+
+{
+  const ee = new EventEmitter();
+  assert.strictEqual(getMaxListeners(ee), defaultMaxListeners);
+  setMaxListeners(101, ee);
+  assert.strictEqual(getMaxListeners(ee), 101);
+}
+
+{
+  const et = new EventTarget();
+  assert.strictEqual(getMaxListeners(et), defaultMaxListeners);
+  setMaxListeners(101, et);
+  assert.strictEqual(getMaxListeners(et), 101);
+}
+
+{
+  const ac = new AbortController();
+  assert.strictEqual(getMaxListeners(ac.signal), 0);
+}