Skip to content

Commit ef3192d

Browse files
authored
fix(node/timers): ensure active timers entry is deleted on Timeout.prototype.refresh (#31436)
Closes #31435
1 parent 4876b41 commit ef3192d

File tree

2 files changed

+21
-14
lines changed

2 files changed

+21
-14
lines changed

ext/node/polyfills/internal/timers.mjs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { primordials } from "ext:core/mod.js";
55
const {
66
FunctionPrototypeBind,
77
MapPrototypeDelete,
8+
MapPrototypeGet,
89
MapPrototypeSet,
910
NumberIsFinite,
1011
SafeArrayIterator,
@@ -33,6 +34,7 @@ export { kTimerId } from "ext:deno_web/02_timers.js";
3334
// Timeout values > TIMEOUT_MAX are set to 1.
3435
export const TIMEOUT_MAX = 2 ** 31 - 1;
3536

37+
export const kDestroy = Symbol("destroy");
3638
export const kTimeout = Symbol("timeout");
3739
const kRefed = Symbol("refed");
3840
const createTimer = Symbol("createTimer");
@@ -43,7 +45,15 @@ const createTimer = Symbol("createTimer");
4345
*
4446
* @type {Map<number, Timeout>}
4547
*/
46-
export const activeTimers = new SafeMap();
48+
const activeTimers = new SafeMap();
49+
50+
/**
51+
* @param {number} id
52+
* @returns {Timeout | undefined}
53+
*/
54+
export function getActiveTimer(id) {
55+
return MapPrototypeGet(activeTimers, id);
56+
}
4757

4858
// Timer constructor function.
4959
export function Timeout(callback, after, args, isRepeat, isRefed) {
@@ -87,6 +97,11 @@ Timeout.prototype[createTimer] = function () {
8797
return id;
8898
};
8999

100+
Timeout.prototype[kDestroy] = function () {
101+
this._destroyed = true;
102+
MapPrototypeDelete(activeTimers, this[kTimerId]);
103+
};
104+
90105
// Make sure the linked list only shows the minimal necessary information.
91106
Timeout.prototype[inspect.custom] = function (_, options) {
92107
return inspect(this, {
@@ -101,6 +116,7 @@ Timeout.prototype[inspect.custom] = function (_, options) {
101116
Timeout.prototype.refresh = function () {
102117
if (!this._destroyed) {
103118
clearTimeout_(this[kTimerId]);
119+
MapPrototypeDelete(activeTimers, this[kTimerId]);
104120
this[kTimerId] = this[createTimer]();
105121
}
106122
return this;

ext/node/polyfills/timers.ts

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
import { primordials } from "ext:core/mod.js";
44
const {
55
FunctionPrototypeBind,
6-
MapPrototypeGet,
7-
MapPrototypeDelete,
86
ObjectDefineProperty,
97
Promise,
108
PromiseReject,
@@ -14,8 +12,9 @@ const {
1412
} = primordials;
1513

1614
import {
17-
activeTimers,
15+
getActiveTimer,
1816
Immediate,
17+
kDestroy,
1918
setUnrefTimeout,
2019
Timeout,
2120
} from "ext:deno_node/internal/timers.mjs";
@@ -128,11 +127,7 @@ export function clearTimeout(timeout?: Timeout | number) {
128127
return;
129128
}
130129
const id = +timeout;
131-
const timer = MapPrototypeGet(activeTimers, id);
132-
if (timer) {
133-
timer._destroyed = true;
134-
MapPrototypeDelete(activeTimers, id);
135-
}
130+
getActiveTimer(id)?.[kDestroy]();
136131
clearTimeout_(id);
137132
}
138133
export function setInterval(
@@ -148,11 +143,7 @@ export function clearInterval(timeout?: Timeout | number | string) {
148143
return;
149144
}
150145
const id = +timeout;
151-
const timer = MapPrototypeGet(activeTimers, id);
152-
if (timer) {
153-
timer._destroyed = true;
154-
MapPrototypeDelete(activeTimers, id);
155-
}
146+
getActiveTimer(id)?.[kDestroy]();
156147
clearInterval_(id);
157148
}
158149
export function setImmediate(

0 commit comments

Comments
 (0)