diff options
author | await-ovo <13152410380@163.com> | 2023-07-03 03:11:34 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-07-02 19:11:34 +0000 |
commit | 0f4051a37ad23377091043206e64126003caa480 (patch) | |
tree | 3fbe98a9c78ee716665dcadaa962ea132eb9bfea /ext/node/polyfills/internal/timers.mjs | |
parent | 01f0d03ae82c422c1f9551f3bfbb57daac769ddc (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.mjs | 30 |
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; }; |