summaryrefslogtreecommitdiff
path: root/ext/node/polyfills/internal/timers.mjs
diff options
context:
space:
mode:
authorawait-ovo <13152410380@163.com>2023-07-03 03:11:34 +0800
committerGitHub <noreply@github.com>2023-07-02 19:11:34 +0000
commit0f4051a37ad23377091043206e64126003caa480 (patch)
tree3fbe98a9c78ee716665dcadaa962ea132eb9bfea /ext/node/polyfills/internal/timers.mjs
parent01f0d03ae82c422c1f9551f3bfbb57daac769ddc (diff)
fix(ext/node): ignore cancelled timer when node timer refresh (#19637)
For timers that have already executed clearTimeout, there is no need to recreate a new timer when refresh is executed again.
Diffstat (limited to 'ext/node/polyfills/internal/timers.mjs')
-rw-r--r--ext/node/polyfills/internal/timers.mjs30
1 files changed, 27 insertions, 3 deletions
diff --git a/ext/node/polyfills/internal/timers.mjs b/ext/node/polyfills/internal/timers.mjs
index d7c986917..c2e8c00e9 100644
--- a/ext/node/polyfills/internal/timers.mjs
+++ b/ext/node/polyfills/internal/timers.mjs
@@ -4,6 +4,13 @@
// TODO(petamoriken): enable prefer-primordials for node polyfills
// deno-lint-ignore-file prefer-primordials
+const primordials = globalThis.__bootstrap.primordials;
+const {
+ MapPrototypeDelete,
+ MapPrototypeSet,
+ SafeMap,
+} = primordials;
+
import { inspect } from "ext:deno_node/internal/util/inspect.mjs";
import { validateFunction, validateNumber } from "ext:deno_node/internal/validators.mjs";
import { ERR_OUT_OF_RANGE } from "ext:deno_node/internal/errors.ts";
@@ -22,6 +29,14 @@ export const kTimeout = Symbol("timeout");
const kRefed = Symbol("refed");
const createTimer = Symbol("createTimer");
+/**
+ * The keys in this map correspond to the key ID's in the spec's map of active
+ * timers. The values are the timeout's status.
+ *
+ * @type {Map<number, Timeout>}
+ */
+export const activeTimers = new SafeMap();
+
// Timer constructor function.
export function Timeout(callback, after, args, isRepeat, isRefed) {
if (typeof after === "number" && after > TIMEOUT_MAX) {
@@ -31,19 +46,26 @@ export function Timeout(callback, after, args, isRepeat, isRefed) {
this._onTimeout = callback;
this._timerArgs = args;
this._isRepeat = isRepeat;
+ this._destroyed = false;
this[kRefed] = isRefed;
this[kTimerId] = this[createTimer]();
}
Timeout.prototype[createTimer] = function () {
const callback = this._onTimeout;
- const cb = (...args) => callback.bind(this)(...args);
+ const cb = (...args) => {
+ if (!this._isRepeat) {
+ MapPrototypeDelete(activeTimers, this[kTimerId])
+ }
+ return callback.bind(this)(...args);
+ }
const id = this._isRepeat
? setInterval_(cb, this._idleTimeout, ...this._timerArgs)
: setTimeout_(cb, this._idleTimeout, ...this._timerArgs);
if (!this[kRefed]) {
Deno.unrefTimer(id);
}
+ MapPrototypeSet(activeTimers, id, this);
return id;
};
@@ -59,8 +81,10 @@ Timeout.prototype[inspect.custom] = function (_, options) {
};
Timeout.prototype.refresh = function () {
- clearTimeout_(this[kTimerId]);
- this[kTimerId] = this[createTimer]();
+ if (!this._destroyed) {
+ clearTimeout_(this[kTimerId]);
+ this[kTimerId] = this[createTimer]();
+ }
return this;
};