Skip to content

Commit 82a3438

Browse files
committed
events: fix addAbortListener for aborted signals
Signed-off-by: Lazizbek Ergashev <lazerg2@gmail.com>
1 parent 2f469df commit 82a3438

3 files changed

Lines changed: 37 additions & 1 deletion

File tree

‎lib/internal/event_target.js‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1243,6 +1243,7 @@ module.exports = {
12431243
kTrustEvent,
12441244
kRemoveListener,
12451245
kEvents,
1246+
kTarget,
12461247
kWeakHandler,
12471248
kResistStopPropagation,
12481249
isEventTarget,

‎lib/internal/events/abort_listener.js‎

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ const {
1717
let queueMicrotask;
1818
let kResistStopPropagation;
1919
let abortListenerOptions;
20+
let Event;
21+
let kTarget;
22+
let kTrustEvent;
2023

2124
/**
2225
* @param {AbortSignal} signal
@@ -33,7 +36,19 @@ function addAbortListener(signal, listener) {
3336
let removeEventListener;
3437
if (signal.aborted) {
3538
queueMicrotask ??= require('internal/process/task_queues').queueMicrotask;
36-
queueMicrotask(() => listener());
39+
if (Event === undefined) {
40+
({ Event, kTarget, kTrustEvent } = require('internal/event_target'));
41+
}
42+
let disposed = false;
43+
queueMicrotask(() => {
44+
if (disposed) return;
45+
const event = new Event('abort', { [kTrustEvent]: true });
46+
event[kTarget] = signal;
47+
listener(event);
48+
});
49+
removeEventListener = () => {
50+
disposed = true;
51+
};
3752
} else {
3853
kResistStopPropagation ??= require('internal/event_target').kResistStopPropagation;
3954
abortListenerOptions ??= ObjectFreeze({ __proto__: null, once: true, [kResistStopPropagation]: true });

‎test/parallel/test-events-add-abort-listener.mjs‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,26 @@ describe('events.addAbortListener', () => {
3333
assert.strictEqual(typeof disposable[Symbol.dispose], 'function');
3434
});
3535

36+
it('should pass an abort event to the listener for aborted runners', async () => {
37+
const signal = AbortSignal.abort();
38+
events.addAbortListener(
39+
signal,
40+
common.mustCall((e) => {
41+
assert.strictEqual(e.type, 'abort');
42+
assert.strictEqual(e.target, signal);
43+
}),
44+
);
45+
46+
await new Promise(queueMicrotask);
47+
});
48+
49+
it('should not execute the listener for aborted runners when disposed', async () => {
50+
const disposable = events.addAbortListener(AbortSignal.abort(), common.mustNotCall());
51+
disposable[Symbol.dispose]();
52+
53+
await new Promise(queueMicrotask);
54+
});
55+
3656
it('should execute the listener even when event propagation stopped', () => {
3757
const controller = new AbortController();
3858
const { signal } = controller;

0 commit comments

Comments
 (0)