Skip to content

Commit

Permalink
fix node:timers abort callback reset (#3380)
Browse files Browse the repository at this point in the history
  • Loading branch information
anonrig authored Jan 21, 2025
1 parent 9cea433 commit 6dd8a1a
Show file tree
Hide file tree
Showing 2 changed files with 363 additions and 15 deletions.
35 changes: 21 additions & 14 deletions src/node/internal/internal_timers_promises.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ import {

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

type OnCancelCallback = (() => void) | undefined;

export async function setTimeout<T = void>(
delay: number | undefined,
value?: T,
Expand Down Expand Up @@ -62,17 +64,21 @@ export async function setTimeout<T = void>(
}

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

const timer = timers.setTimeout(() => {
resolve(value as T);
}, delay ?? 0);
if (onCancel) {
signal?.removeEventListener('abort', onCancel);
}
}, delay ?? 1);

if (signal) {
function onCancel(): void {
onCancel = (): void => {
timers.clearTimeout(timer);
reject(new AbortError(undefined, { cause: signal?.reason }));
}
signal.addEventListener('abort', onCancel);
reject(new AbortError(undefined, { cause: signal.reason }));
};
signal.addEventListener('abort', onCancel, { once: true });
}

return promise;
Expand Down Expand Up @@ -101,18 +107,21 @@ export async function setImmediate<T>(
}

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

const timer = timers.setImmediate(() => {
resolve(value as T);
if (onCancel) {
signal?.removeEventListener('abort', onCancel);
}
});

if (signal) {
function onCancel(): void {
onCancel = (): void => {
timers.clearImmediate(timer);
signal?.removeEventListener('abort', onCancel);
reject(new AbortError(undefined, { cause: signal?.reason }));
}
signal.addEventListener('abort', onCancel);
reject(new AbortError(undefined, { cause: signal.reason }));
};
signal.addEventListener('abort', onCancel, { once: true });
}

return promise;
Expand Down Expand Up @@ -144,7 +153,7 @@ export async function* setInterval<T = void>(
throw new AbortError(undefined, { cause: signal.reason });
}

let onCancel: (() => void) | undefined;
let onCancel: OnCancelCallback;
let interval: timers.Timeout;
try {
let notYielded = 0;
Expand All @@ -164,14 +173,12 @@ export async function* setInterval<T = void>(
if (signal) {
onCancel = (): void => {
timers.clearInterval(interval);
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
signal.removeEventListener('abort', onCancel!);
callback?.(
Promise.reject(new AbortError(undefined, { cause: signal.reason }))
);
callback = undefined;
};
signal.addEventListener('abort', onCancel);
signal.addEventListener('abort', onCancel, { once: true });
}

while (!signal?.aborted) {
Expand Down
Loading

0 comments on commit 6dd8a1a

Please sign in to comment.