events: optimize EventTarget.addEventListener

PR-URL: https://github.com/nodejs/node/pull/55312
Fixes: https://github.com/nodejs/node/issues/55311
Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
Reviewed-By: Vinícius Lourenço Claro Cardoso <contact@viniciusl.com.br>
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
This commit is contained in:
Robert Nagy 2024-10-14 12:24:32 +02:00 committed by GitHub
parent f97865fab4
commit 488ce99d76
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 61 additions and 25 deletions

View File

@ -0,0 +1,25 @@
'use strict';
const common = require('../common.js');
const bench = common.createBenchmark(main, {
n: [1e5],
nListener: [1, 5, 10],
});
function main({ n, nListener }) {
const target = new EventTarget();
const listeners = [];
for (let k = 0; k < nListener; k += 1)
listeners.push(() => {});
bench.start();
for (let i = 0; i < n; i += 1) {
for (let k = listeners.length; --k >= 0;) {
target.addEventListener('abort', listeners[k]);
}
for (let k = listeners.length; --k >= 0;) {
target.removeEventListener('abort', listeners[k]);
}
}
bench.end(n);
}

View File

@ -2,8 +2,8 @@
const common = require('../common.js'); const common = require('../common.js');
const bench = common.createBenchmark(main, { const bench = common.createBenchmark(main, {
n: [1e6], n: [1e5],
nListener: [5, 10], nListener: [1, 5, 10],
}); });
function main({ n, nListener }) { function main({ n, nListener }) {

View File

@ -597,20 +597,41 @@ class EventTarget {
if (arguments.length < 2) if (arguments.length < 2)
throw new ERR_MISSING_ARGS('type', 'listener'); throw new ERR_MISSING_ARGS('type', 'listener');
let once = false;
let capture = false;
let passive = false;
let isNodeStyleListener = false;
let weak = false;
let resistStopPropagation = false;
if (options !== kEmptyObject) {
// We validateOptions before the validateListener check because the spec // We validateOptions before the validateListener check because the spec
// requires us to hit getters. // requires us to hit getters.
const { options = validateEventListenerOptions(options);
once,
capture, once = options.once;
passive, capture = options.capture;
signal, passive = options.passive;
isNodeStyleListener, isNodeStyleListener = options.isNodeStyleListener;
weak, weak = options.weak;
resistStopPropagation, resistStopPropagation = options.resistStopPropagation;
} = validateEventListenerOptions(options);
const signal = options.signal;
validateAbortSignal(signal, 'options.signal'); validateAbortSignal(signal, 'options.signal');
if (signal) {
if (signal.aborted) {
return;
}
// TODO(benjamingr) make this weak somehow? ideally the signal would
// not prevent the event target from GC.
signal.addEventListener('abort', () => {
this.removeEventListener(type, listener, options);
}, { __proto__: null, once: true, [kWeakHandler]: this, [kResistStopPropagation]: true });
}
}
if (!validateEventListener(listener)) { if (!validateEventListener(listener)) {
// The DOM silently allows passing undefined as a second argument // The DOM silently allows passing undefined as a second argument
// No error code for this since it is a Warning // No error code for this since it is a Warning
@ -623,18 +644,8 @@ class EventTarget {
process.emitWarning(w); process.emitWarning(w);
return; return;
} }
type = webidl.converters.DOMString(type);
if (signal) { type = webidl.converters.DOMString(type);
if (signal.aborted) {
return;
}
// TODO(benjamingr) make this weak somehow? ideally the signal would
// not prevent the event target from GC.
signal.addEventListener('abort', () => {
this.removeEventListener(type, listener, options);
}, { __proto__: null, once: true, [kWeakHandler]: this, [kResistStopPropagation]: true });
}
let root = this[kEvents].get(type); let root = this[kEvents].get(type);