Skip to content

Commit 64d22c3

Browse files
lundibundironag
authored andcommitted
timers: fix multipleResolves in promisified timeouts/immediates
After successful timer finish the abort event callback would still reject (already resolved promise) upon calling abortController.abort(). Signed-off-by: Denys Otrishko <shishugi@gmail.com> PR-URL: #33949 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net>
1 parent 51a2df4 commit 64d22c3

File tree

2 files changed

+27
-4
lines changed

2 files changed

+27
-4
lines changed

lib/timers.js

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -190,8 +190,10 @@ setTimeout[customPromisify] = function(after, value, options = {}) {
190190
insert(timeout, timeout._idleTimeout);
191191
if (signal) {
192192
signal.addEventListener('abort', () => {
193-
clearTimeout(timeout);
194-
reject(lazyDOMException('AbortError'));
193+
if (!timeout._destroyed) {
194+
clearTimeout(timeout);
195+
reject(lazyDOMException('AbortError'));
196+
}
195197
}, { once: true });
196198
}
197199
});
@@ -340,8 +342,10 @@ setImmediate[customPromisify] = function(value, options = {}) {
340342
const immediate = new Immediate(resolve, [value]);
341343
if (signal) {
342344
signal.addEventListener('abort', () => {
343-
clearImmediate(immediate);
344-
reject(lazyDOMException('AbortError'));
345+
if (!immediate._destroyed) {
346+
clearImmediate(immediate);
347+
reject(lazyDOMException('AbortError'));
348+
}
345349
}, { once: true });
346350
}
347351
});

test/parallel/test-timers-promisified.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ const { promisify } = require('util');
1010
const setTimeout = promisify(timers.setTimeout);
1111
const setImmediate = promisify(timers.setImmediate);
1212

13+
process.on('multipleResolves', common.mustNotCall());
14+
1315
{
1416
const promise = setTimeout(1);
1517
promise.then(common.mustCall((value) => {
@@ -66,6 +68,23 @@ const setImmediate = promisify(timers.setImmediate);
6668
assert.rejects(setImmediate(10, { signal }), /AbortError/);
6769
}
6870

71+
{
72+
// Check that aborting after resolve will not reject.
73+
const ac = new AbortController();
74+
const signal = ac.signal;
75+
setTimeout(10, undefined, { signal }).then(() => {
76+
ac.abort();
77+
});
78+
}
79+
{
80+
// Check that aborting after resolve will not reject.
81+
const ac = new AbortController();
82+
const signal = ac.signal;
83+
setImmediate(10, { signal }).then(() => {
84+
ac.abort();
85+
});
86+
}
87+
6988
{
7089
Promise.all(
7190
[1, '', false, Infinity].map((i) => assert.rejects(setImmediate(10, i)), {

0 commit comments

Comments
 (0)