Skip to content

Commit 790032a

Browse files
committed
fix node:timers abort callback reset
1 parent b982f8b commit 790032a

File tree

1 file changed

+26
-10
lines changed

1 file changed

+26
-10
lines changed

src/node/internal/internal_timers_promises.ts

+26-10
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ import {
3434

3535
const kScheduler = Symbol.for('kScheduler');
3636

37+
type OnCancelCallback = (() => void) | undefined;
38+
3739
export async function setTimeout<T = void>(
3840
delay: number | undefined,
3941
value?: T,
@@ -62,16 +64,23 @@ export async function setTimeout<T = void>(
6264
}
6365

6466
const { promise, resolve, reject } = Promise.withResolvers<T>();
67+
let onCancel: OnCancelCallback;
6568

6669
const timer = timers.setTimeout(() => {
6770
resolve(value as T);
71+
if (onCancel) {
72+
signal?.removeEventListener('abort', onCancel);
73+
}
6874
}, delay ?? 0);
6975

7076
if (signal) {
71-
function onCancel(): void {
77+
onCancel = (): void => {
7278
timers.clearTimeout(timer);
73-
reject(new AbortError(undefined, { cause: signal?.reason }));
74-
}
79+
if (onCancel) {
80+
signal.removeEventListener('abort', onCancel);
81+
}
82+
reject(new AbortError(undefined, { cause: signal.reason }));
83+
};
7584
signal.addEventListener('abort', onCancel);
7685
}
7786

@@ -101,17 +110,23 @@ export async function setImmediate<T>(
101110
}
102111

103112
const { promise, resolve, reject } = Promise.withResolvers<T>();
113+
let onCancel: OnCancelCallback;
104114

105115
const timer = globalThis.setImmediate(() => {
106116
resolve(value as T);
117+
if (onCancel) {
118+
signal?.removeEventListener('abort', onCancel);
119+
}
107120
});
108121

109122
if (signal) {
110-
function onCancel(): void {
123+
onCancel = (): void => {
111124
globalThis.clearImmediate(timer);
112-
signal?.removeEventListener('abort', onCancel);
113-
reject(new AbortError(undefined, { cause: signal?.reason }));
114-
}
125+
if (onCancel) {
126+
signal.removeEventListener('abort', onCancel);
127+
}
128+
reject(new AbortError(undefined, { cause: signal.reason }));
129+
};
115130
signal.addEventListener('abort', onCancel);
116131
}
117132

@@ -144,7 +159,7 @@ export async function* setInterval<T = void>(
144159
throw new AbortError(undefined, { cause: signal.reason });
145160
}
146161

147-
let onCancel: (() => void) | undefined;
162+
let onCancel: OnCancelCallback;
148163
let interval: timers.Timeout;
149164
try {
150165
let notYielded = 0;
@@ -164,8 +179,9 @@ export async function* setInterval<T = void>(
164179
if (signal) {
165180
onCancel = (): void => {
166181
timers.clearInterval(interval);
167-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
168-
signal.removeEventListener('abort', onCancel!);
182+
if (onCancel) {
183+
signal.removeEventListener('abort', onCancel);
184+
}
169185
callback?.(
170186
Promise.reject(new AbortError(undefined, { cause: signal.reason }))
171187
);

0 commit comments

Comments
 (0)