Skip to content

Commit

Permalink
events: optimize EventTarget.addEventListener
Browse files Browse the repository at this point in the history
PR-URL: #55312
Fixes: #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>
  • Loading branch information
ronag authored and aduh95 committed Oct 19, 2024
1 parent a490bb8 commit 8ceefeb
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 26 deletions.
25 changes: 25 additions & 0 deletions benchmark/events/eventtarget-add-remove-abort.js
Original file line number Diff line number Diff line change
@@ -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);
}
4 changes: 2 additions & 2 deletions benchmark/events/eventtarget-add-remove.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
const common = require('../common.js');

const bench = common.createBenchmark(main, {
n: [1e6],
nListener: [5, 10],
n: [1e5],
nListener: [1, 5, 10],
});

function main({ n, nListener }) {
Expand Down
59 changes: 35 additions & 24 deletions lib/internal/event_target.js
Original file line number Diff line number Diff line change
Expand Up @@ -597,19 +597,40 @@ class EventTarget {
if (arguments.length < 2)
throw new ERR_MISSING_ARGS('type', 'listener');

// We validateOptions before the validateListener check because the spec
// requires us to hit getters.
const {
once,
capture,
passive,
signal,
isNodeStyleListener,
weak,
resistStopPropagation,
} = validateEventListenerOptions(options);

validateAbortSignal(signal, 'options.signal');
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
// requires us to hit getters.
options = validateEventListenerOptions(options);

once = options.once;
capture = options.capture;
passive = options.passive;
isNodeStyleListener = options.isNodeStyleListener;
weak = options.weak;
resistStopPropagation = options.resistStopPropagation;

const 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)) {
// The DOM silently allows passing undefined as a second argument
Expand All @@ -623,18 +644,8 @@ class EventTarget {
process.emitWarning(w);
return;
}
type = webidl.converters.DOMString(type);

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 });
}
type = webidl.converters.DOMString(type);

let root = this[kEvents].get(type);

Expand Down

0 comments on commit 8ceefeb

Please sign in to comment.