Skip to content

Commit

Permalink
timers: propagate signal.reason in awaitable timers
Browse files Browse the repository at this point in the history
Signed-off-by: James M Snell <jasnell@gmail.com>

PR-URL: #41008
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: Robert Nagy <ronagy@icloud.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
  • Loading branch information
jasnell authored and targos committed Aug 1, 2022
1 parent 0074cb6 commit b411248
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 8 deletions.
19 changes: 11 additions & 8 deletions lib/timers/promises.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ const kScheduler = Symbol('kScheduler');
function cancelListenerHandler(clear, reject, signal) {
if (!this._destroyed) {
clear(this);
reject(new AbortError());
reject(new AbortError(undefined, { cause: signal?.reason }));
}
}

Expand Down Expand Up @@ -74,15 +74,15 @@ function setTimeout(after, value, options = kEmptyObject) {
// to 12.x, then this can be converted to use optional chaining to
// simplify the check.
if (signal && signal.aborted) {
return PromiseReject(new AbortError());
return PromiseReject(new AbortError(undefined, { cause: signal.reason }));
}
let oncancel;
const ret = new Promise((resolve, reject) => {
const timeout = new Timeout(resolve, after, args, false, ref);
insert(timeout, timeout._idleTimeout);
if (signal) {
oncancel = FunctionPrototypeBind(cancelListenerHandler,
timeout, clearTimeout, reject);
timeout, clearTimeout, reject, signal);
signal.addEventListener('abort', oncancel);
}
});
Expand Down Expand Up @@ -117,15 +117,16 @@ function setImmediate(value, options = kEmptyObject) {
// to 12.x, then this can be converted to use optional chaining to
// simplify the check.
if (signal && signal.aborted) {
return PromiseReject(new AbortError());
return PromiseReject(new AbortError(undefined, { cause: signal.reason }));
}
let oncancel;
const ret = new Promise((resolve, reject) => {
const immediate = new Immediate(resolve, [value]);
if (!ref) immediate.unref();
if (signal) {
oncancel = FunctionPrototypeBind(cancelListenerHandler,
immediate, clearImmediate, reject);
immediate, clearImmediate, reject,
signal);
signal.addEventListener('abort', oncancel);
}
});
Expand All @@ -142,7 +143,7 @@ async function* setInterval(after, value, options = kEmptyObject) {
validateBoolean(ref, 'options.ref');

if (signal?.aborted)
throw new AbortError();
throw new AbortError(undefined, { cause: signal?.reason });

let onCancel;
let interval;
Expand All @@ -161,7 +162,9 @@ async function* setInterval(after, value, options = kEmptyObject) {
onCancel = () => {
clearInterval(interval);
if (callback) {
callback(PromiseReject(new AbortError()));
callback(
PromiseReject(
new AbortError(undefined, { cause: signal.reason })));
callback = undefined;
}
};
Expand All @@ -176,7 +179,7 @@ async function* setInterval(after, value, options = kEmptyObject) {
yield value;
}
}
throw new AbortError();
throw new AbortError(undefined, { cause: signal?.reason });
} finally {
clearInterval(interval);
signal?.removeEventListener('abort', onCancel);
Expand Down
7 changes: 7 additions & 0 deletions test/parallel/test-timers-immediate-promisified.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,3 +97,10 @@ process.on('multipleResolves', common.mustNotCall());
assert.strictEqual(stderr, '');
}));
}

(async () => {
const signal = AbortSignal.abort('boom');
await assert.rejects(timerPromises.setImmediate(undefined, { signal }), {
cause: 'boom',
});
})().then(common.mustCall());
12 changes: 12 additions & 0 deletions test/parallel/test-timers-interval-promisified.js
Original file line number Diff line number Diff line change
Expand Up @@ -246,3 +246,15 @@ process.on('multipleResolves', common.mustNotCall());
setPromiseTimeout(time_unit * 3).then(() => post = true),
]).then(common.mustCall());
}

(async () => {
const signal = AbortSignal.abort('boom');
try {
const iterable = timerPromises.setInterval(2, undefined, { signal });
// eslint-disable-next-line no-unused-vars, no-empty
for await (const _ of iterable) { }
assert.fail('should have failed');
} catch (err) {
assert.strictEqual(err.cause, 'boom');
}
})().then(common.mustCall());
7 changes: 7 additions & 0 deletions test/parallel/test-timers-timeout-promisified.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,3 +97,10 @@ process.on('multipleResolves', common.mustNotCall());
assert.strictEqual(stderr, '');
}));
}

(async () => {
const signal = AbortSignal.abort('boom');
await assert.rejects(timerPromises.setTimeout(1, undefined, { signal }), {
cause: 'boom',
});
})().then(common.mustCall());

0 comments on commit b411248

Please sign in to comment.