Skip to content

Commit c6558b0

Browse files
committed
timers: runtime-deprecate Timeout.prototype[Symbol.dispose]
Emit a DEP0208 deprecation warning when Timeout.prototype[Symbol.dispose] is called. The web platform setTimeout()/setInterval() APIs return a number, which cannot implement Symbol.dispose. Prefer clearTimeout() instead. Immediate.prototype[Symbol.dispose] is left unchanged. Fixes: #58689 Signed-off-by: Matteo Collina <hello@matteocollina.com>
1 parent fb5d01f commit c6558b0

5 files changed

Lines changed: 37 additions & 4 deletions

File tree

doc/api/deprecations.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4646,6 +4646,23 @@ underlying stream are emitted from `req`. On the write-side you can use
46464646
`res.writableFinished` to confirm whether the response was written
46474647
successfully before the response closed.
46484648
4649+
### DEP0208: `Timeout.prototype[Symbol.dispose]()`
4650+
4651+
<!-- YAML
4652+
changes:
4653+
- version: REPLACEME
4654+
pr-url: https://github.com/nodejs/node/pull/64615
4655+
description: Runtime deprecation.
4656+
-->
4657+
4658+
Type: Runtime
4659+
4660+
Calling `timeout[Symbol.dispose]()` is deprecated. The web platform
4661+
[`setTimeout()`][] and [`setInterval()`][] APIs return a number, which cannot
4662+
implement `Symbol.dispose`. Prefer [`clearTimeout()`][] instead to cancel a
4663+
timeout. This deprecation does not apply to [`Immediate`][] objects returned by
4664+
[`setImmediate()`][].
4665+
46494666
[DEP0142]: #dep0142-repl_builtinlibs
46504667
[DEP0156]: #dep0156-aborted-property-and-abort-aborted-event-in-http
46514668
[NIST SP 800-38D]: https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf
@@ -4668,6 +4685,7 @@ successfully before the response closed.
46684685
[`Decipheriv`]: crypto.md#class-decipheriv
46694686
[`Duplex.toWeb()`]: stream.md#streamduplextowebstreamduplex-options
46704687
[`Error.isError`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/isError
4688+
[`Immediate`]: timers.md#class-immediate
46714689
[`KeyObject.from()`]: crypto.md#static-method-keyobjectfromkey
46724690
[`REPLServer.clearBufferedCommand()`]: repl.md#replserverclearbufferedcommand
46734691
[`ReadStream.open()`]: fs.md#class-fsreadstream
@@ -4763,6 +4781,7 @@ successfully before the response closed.
47634781
[`response.writableEnded`]: http.md#responsewritableended
47644782
[`response.writableFinished`]: http.md#responsewritablefinished
47654783
[`script.createCachedData()`]: vm.md#scriptcreatecacheddata
4784+
[`setImmediate()`]: timers.md#setimmediatecallback-args
47664785
[`setInterval()`]: timers.md#setintervalcallback-delay-args
47674786
[`setTimeout()`]: timers.md#settimeoutcallback-delay-args
47684787
[`socket.bufferSize`]: net.md#socketbuffersize

doc/api/timers.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,12 +177,18 @@ thread. This allows enhanced compatibility with browser
177177
added:
178178
- v20.5.0
179179
- v18.18.0
180+
deprecated: REPLACEME
180181
changes:
182+
- version: REPLACEME
183+
pr-url: https://github.com/nodejs/node/pull/64615
184+
description: Runtime deprecation.
181185
- version: v24.2.0
182186
pr-url: https://github.com/nodejs/node/pull/58467
183187
description: No longer experimental.
184188
-->
185189

190+
> Stability: 0 - Deprecated: Use [`clearTimeout()`][] instead.
191+
186192
Cancels the timeout.
187193

188194
## Scheduling timers

lib/timers.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ const {
5252
knownTimersById,
5353
} = require('internal/timers');
5454
const {
55+
deprecate,
5556
promisify: { custom: customPromisify },
5657
} = require('internal/util');
5758
let debug = require('internal/util/debuglog').debuglog('timer', (fn) => {
@@ -180,9 +181,9 @@ Timeout.prototype.close = function() {
180181
return this;
181182
};
182183

183-
Timeout.prototype[SymbolDispose] = function() {
184+
Timeout.prototype[SymbolDispose] = deprecate(function() {
184185
clearTimeout(this);
185-
};
186+
}, 'Timeout.prototype[Symbol.dispose] is deprecated. Use clearTimeout instead.', 'DEP0208');
186187

187188
/**
188189
* Coerces a `Timeout` to a primitive.

test/doctool/test-doc-api-json.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,5 +159,5 @@ for await (const dirent of await fs.opendir(new URL('../../out/doc/api/', import
159159
assert.partialDeepStrictEqual(allExpectedKeys, findAllKeys(json));
160160
}
161161

162-
assert.strictEqual(numberOfDeprecatedSections, 45); // Increase this number every time a new API is deprecated.
162+
assert.strictEqual(numberOfDeprecatedSections, 46); // Increase this number every time a new API is deprecated.
163163
assert.strictEqual(numberOfRemovedAPIs, 46); // Increase this number every time a section is marked as removed.

test/parallel/test-timers-dispose.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,22 @@
22
const common = require('../common');
33
const assert = require('assert');
44

5+
common.expectWarning({
6+
DeprecationWarning: {
7+
DEP0208: 'Timeout.prototype[Symbol.dispose] is deprecated. Use clearTimeout instead.',
8+
},
9+
});
10+
511
const timer = setTimeout(common.mustNotCall(), 10);
612
const interval = setInterval(common.mustNotCall(), 10);
713
const immediate = setImmediate(common.mustNotCall());
814

915
timer[Symbol.dispose]();
16+
// Second call should not emit another warning (codes are warned once).
1017
interval[Symbol.dispose]();
18+
// Immediate is not deprecated.
1119
immediate[Symbol.dispose]();
1220

13-
1421
process.on('exit', () => {
1522
assert.strictEqual(timer._destroyed, true);
1623
assert.strictEqual(interval._destroyed, true);

0 commit comments

Comments
 (0)