From 4fa607fc7b689299d468df47df20c90c32bd09ff Mon Sep 17 00:00:00 2001 From: Denys Otrishko Date: Thu, 18 Jun 2020 22:58:42 +0300 Subject: [PATCH 1/2] 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 --- lib/timers.js | 12 ++++++++---- test/parallel/test-timers-promisified.js | 22 ++++++++++++++++++++++ 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/lib/timers.js b/lib/timers.js index fce904019205e9..53e934f3c9ac7c 100644 --- a/lib/timers.js +++ b/lib/timers.js @@ -190,8 +190,10 @@ setTimeout[customPromisify] = function(after, value, options = {}) { insert(timeout, timeout._idleTimeout); if (signal) { signal.addEventListener('abort', () => { - clearTimeout(timeout); - reject(lazyDOMException('AbortError')); + if (!timeout._destroyed) { + clearTimeout(timeout); + reject(lazyDOMException('AbortError')); + } }, { once: true }); } }); @@ -340,8 +342,10 @@ setImmediate[customPromisify] = function(value, options = {}) { const immediate = new Immediate(resolve, [value]); if (signal) { signal.addEventListener('abort', () => { - clearImmediate(immediate); - reject(lazyDOMException('AbortError')); + if (!immediate._destroyed) { + clearImmediate(immediate); + reject(lazyDOMException('AbortError')); + } }, { once: true }); } }); diff --git a/test/parallel/test-timers-promisified.js b/test/parallel/test-timers-promisified.js index d470d2f97c79eb..91385a5369e0fd 100644 --- a/test/parallel/test-timers-promisified.js +++ b/test/parallel/test-timers-promisified.js @@ -10,6 +10,11 @@ const { promisify } = require('util'); const setTimeout = promisify(timers.setTimeout); const setImmediate = promisify(timers.setImmediate); +process.on('multipleResolves', (type, promise, reason) => { + console.error('multipleResolves', type, promise, reason); + throw new Error('multipleResolves'); +}); + { const promise = setTimeout(1); promise.then(common.mustCall((value) => { @@ -66,6 +71,23 @@ const setImmediate = promisify(timers.setImmediate); assert.rejects(setImmediate(10, { signal }), /AbortError/); } +{ + // Check that aborting after resolve will not reject. + const ac = new AbortController(); + const signal = ac.signal; + setTimeout(10, undefined, { signal }).then(() => { + ac.abort(); + }); +} +{ + // Check that aborting after resolve will not reject. + const ac = new AbortController(); + const signal = ac.signal; + setImmediate(10, { signal }).then(() => { + ac.abort(); + }); +} + { Promise.all( [1, '', false, Infinity].map((i) => assert.rejects(setImmediate(10, i)), { From cd586a816a88268350b952d7c5e508f224d0268c Mon Sep 17 00:00:00 2001 From: Denys Otrishko Date: Thu, 18 Jun 2020 23:50:59 +0300 Subject: [PATCH 2/2] fixup! timers: fix multipleResolves in promisified timeouts/immediates --- test/parallel/test-timers-promisified.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/test/parallel/test-timers-promisified.js b/test/parallel/test-timers-promisified.js index 91385a5369e0fd..f46dc3f24d20eb 100644 --- a/test/parallel/test-timers-promisified.js +++ b/test/parallel/test-timers-promisified.js @@ -10,10 +10,7 @@ const { promisify } = require('util'); const setTimeout = promisify(timers.setTimeout); const setImmediate = promisify(timers.setImmediate); -process.on('multipleResolves', (type, promise, reason) => { - console.error('multipleResolves', type, promise, reason); - throw new Error('multipleResolves'); -}); +process.on('multipleResolves', common.mustNotCall()); { const promise = setTimeout(1);