Skip to content

Commit

Permalink
events: extract addAbortListener for safe internal use
Browse files Browse the repository at this point in the history
Refs: #48596
PR-URL: #52081
Reviewed-By: Moshe Atlow <[email protected]>
Reviewed-By: Benjamin Gruenbaum <[email protected]>
Reviewed-By: Antoine du Hamel <[email protected]>
Reviewed-By: Luigi Pinca <[email protected]>
  • Loading branch information
atlowChemi authored and marco-ippolito committed May 3, 2024
1 parent 93bddb5 commit 5e69673
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 29 deletions.
30 changes: 1 addition & 29 deletions lib/events.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ const {
validateNumber,
validateString,
} = require('internal/validators');
const { addAbortListener } = require('internal/events/abort_listener');

const kCapture = Symbol('kCapture');
const kErrorMonitor = Symbol('events.errorMonitor');
Expand Down Expand Up @@ -1219,32 +1220,3 @@ function listenersController() {
},
};
}

let queueMicrotask;

function addAbortListener(signal, listener) {
if (signal === undefined) {
throw new ERR_INVALID_ARG_TYPE('signal', 'AbortSignal', signal);
}
validateAbortSignal(signal, 'signal');
validateFunction(listener, 'listener');

let removeEventListener;
if (signal.aborted) {
queueMicrotask ??= require('internal/process/task_queues').queueMicrotask;
queueMicrotask(() => listener());
} else {
kResistStopPropagation ??= require('internal/event_target').kResistStopPropagation;
// TODO(atlowChemi) add { subscription: true } and return directly
signal.addEventListener('abort', listener, { __proto__: null, once: true, [kResistStopPropagation]: true });
removeEventListener = () => {
signal.removeEventListener('abort', listener);
};
}
return {
__proto__: null,
[SymbolDispose]() {
removeEventListener?.();
},
};
}
54 changes: 54 additions & 0 deletions lib/internal/events/abort_listener.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
'use strict';

const {
SymbolDispose,
} = primordials;
const {
validateAbortSignal,
validateFunction,
} = require('internal/validators');
const {
codes: {
ERR_INVALID_ARG_TYPE,
},
} = require('internal/errors');

let queueMicrotask;
let kResistStopPropagation;

/**
* @param {AbortSignal} signal
* @param {EventListener} listener
* @returns {Disposable}
*/
function addAbortListener(signal, listener) {
if (signal === undefined) {
throw new ERR_INVALID_ARG_TYPE('signal', 'AbortSignal', signal);
}
validateAbortSignal(signal, 'signal');
validateFunction(listener, 'listener');

let removeEventListener;
if (signal.aborted) {
queueMicrotask ??= require('internal/process/task_queues').queueMicrotask;
queueMicrotask(() => listener());
} else {
kResistStopPropagation ??= require('internal/event_target').kResistStopPropagation;
// TODO(atlowChemi) add { subscription: true } and return directly
signal.addEventListener('abort', listener, { __proto__: null, once: true, [kResistStopPropagation]: true });
removeEventListener = () => {
signal.removeEventListener('abort', listener);
};
}
return {
__proto__: null,
[SymbolDispose]() {
removeEventListener?.();
},
};
}

module.exports = {
__proto__: null,
addAbortListener,
};
1 change: 1 addition & 0 deletions test/parallel/test-bootstrap-modules.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ expected.beforePreExec = new Set([
'Internal Binding module_wrap',
'NativeModule internal/modules/cjs/loader',
'Internal Binding wasm_web_api',
'NativeModule internal/events/abort_listener',
]);

expected.atRunTime = new Set([
Expand Down

0 comments on commit 5e69673

Please sign in to comment.