Skip to content

Commit e795547

Browse files
jasnelldanielleadams
authored andcommitted
timers: propagate signal.reason in awaitable timers
Signed-off-by: James M Snell <[email protected]> PR-URL: #41008 Reviewed-By: Ruben Bridgewater <[email protected]> Reviewed-By: Robert Nagy <[email protected]> Reviewed-By: Benjamin Gruenbaum <[email protected]>
1 parent 12023df commit e795547

4 files changed

+38
-9
lines changed

lib/timers/promises.js

+12-9
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,10 @@ const {
2424
validateObject,
2525
} = require('internal/validators');
2626

27-
function cancelListenerHandler(clear, reject) {
27+
function cancelListenerHandler(clear, reject, signal) {
2828
if (!this._destroyed) {
2929
clear(this);
30-
reject(new AbortError());
30+
reject(new AbortError(undefined, { cause: signal?.reason }));
3131
}
3232
}
3333

@@ -57,7 +57,7 @@ function setTimeout(after, value, options = {}) {
5757
// to 12.x, then this can be converted to use optional chaining to
5858
// simplify the check.
5959
if (signal && signal.aborted) {
60-
return PromiseReject(new AbortError());
60+
return PromiseReject(new AbortError(undefined, { cause: signal.reason }));
6161
}
6262
let oncancel;
6363
const ret = new Promise((resolve, reject) => {
@@ -66,7 +66,7 @@ function setTimeout(after, value, options = {}) {
6666
if (signal) {
6767
oncancel = FunctionPrototypeBind(cancelListenerHandler,
6868
// eslint-disable-next-line no-undef
69-
timeout, clearTimeout, reject);
69+
timeout, clearTimeout, reject, signal);
7070
signal.addEventListener('abort', oncancel);
7171
}
7272
});
@@ -101,7 +101,7 @@ function setImmediate(value, options = {}) {
101101
// to 12.x, then this can be converted to use optional chaining to
102102
// simplify the check.
103103
if (signal && signal.aborted) {
104-
return PromiseReject(new AbortError());
104+
return PromiseReject(new AbortError(undefined, { cause: signal.reason }));
105105
}
106106
let oncancel;
107107
const ret = new Promise((resolve, reject) => {
@@ -110,7 +110,8 @@ function setImmediate(value, options = {}) {
110110
if (signal) {
111111
oncancel = FunctionPrototypeBind(cancelListenerHandler,
112112
// eslint-disable-next-line no-undef
113-
immediate, clearImmediate, reject);
113+
immediate, clearImmediate, reject,
114+
signal);
114115
signal.addEventListener('abort', oncancel);
115116
}
116117
});
@@ -127,7 +128,7 @@ async function* setInterval(after, value, options = {}) {
127128
validateBoolean(ref, 'options.ref');
128129

129130
if (signal?.aborted)
130-
throw new AbortError();
131+
throw new AbortError(undefined, { cause: signal?.reason });
131132

132133
let onCancel;
133134
let interval;
@@ -147,7 +148,9 @@ async function* setInterval(after, value, options = {}) {
147148
// eslint-disable-next-line no-undef
148149
clearInterval(interval);
149150
if (callback) {
150-
callback(PromiseReject(new AbortError()));
151+
callback(
152+
PromiseReject(
153+
new AbortError(undefined, { cause: signal.reason })));
151154
callback = undefined;
152155
}
153156
};
@@ -162,7 +165,7 @@ async function* setInterval(after, value, options = {}) {
162165
yield value;
163166
}
164167
}
165-
throw new AbortError();
168+
throw new AbortError(undefined, { cause: signal?.reason });
166169
} finally {
167170
// eslint-disable-next-line no-undef
168171
clearInterval(interval);

test/parallel/test-timers-immediate-promisified.js

+7
Original file line numberDiff line numberDiff line change
@@ -97,3 +97,10 @@ process.on('multipleResolves', common.mustNotCall());
9797
assert.strictEqual(stderr, '');
9898
}));
9999
}
100+
101+
(async () => {
102+
const signal = AbortSignal.abort('boom');
103+
await assert.rejects(timerPromises.setImmediate(undefined, { signal }), {
104+
cause: 'boom',
105+
});
106+
})().then(common.mustCall());

test/parallel/test-timers-interval-promisified.js

+12
Original file line numberDiff line numberDiff line change
@@ -246,3 +246,15 @@ process.on('multipleResolves', common.mustNotCall());
246246
setPromiseTimeout(time_unit * 3).then(() => post = true),
247247
]).then(common.mustCall());
248248
}
249+
250+
(async () => {
251+
const signal = AbortSignal.abort('boom');
252+
try {
253+
const iterable = timerPromises.setInterval(2, undefined, { signal });
254+
// eslint-disable-next-line no-unused-vars
255+
for await (const _ of iterable) {}
256+
assert.fail('should have failed');
257+
} catch (err) {
258+
assert.strictEqual(err.cause, 'boom');
259+
}
260+
})().then(common.mustCall());

test/parallel/test-timers-timeout-promisified.js

+7
Original file line numberDiff line numberDiff line change
@@ -97,3 +97,10 @@ process.on('multipleResolves', common.mustNotCall());
9797
assert.strictEqual(stderr, '');
9898
}));
9999
}
100+
101+
(async () => {
102+
const signal = AbortSignal.abort('boom');
103+
await assert.rejects(timerPromises.setTimeout(1, undefined, { signal }), {
104+
cause: 'boom',
105+
});
106+
})().then(common.mustCall());

0 commit comments

Comments
 (0)