GeezerVison is showing github.com — timers: propagate signal.reason in awaitable timers · nodejs/node@2aae868
File treeExpand file treeCollapse file tree Open diff view settings Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: lib/timers/promises.js +11-8Lines changed: 11 additions & 8 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -44,7 +44,7 @@ const kScheduler = Symbol('kScheduler'); | 44 | 44 | function cancelListenerHandler(clear, reject, signal) { | 45 | 45 | if (!this._destroyed) { | 46 | 46 | clear(this); | 47 | | - reject(new AbortError()); | | 47 | + reject(new AbortError(undefined, { cause: signal?.reason })); | 48 | 48 | } | 49 | 49 | } | 50 | 50 |
| @@ -74,15 +74,15 @@ function setTimeout(after, value, options = kEmptyObject) { | 74 | 74 | // to 12.x, then this can be converted to use optional chaining to | 75 | 75 | // simplify the check. | 76 | 76 | if (signal && signal.aborted) { | 77 | | - return PromiseReject(new AbortError()); | | 77 | + return PromiseReject(new AbortError(undefined, { cause: signal.reason })); | 78 | 78 | } | 79 | 79 | let oncancel; | 80 | 80 | const ret = new Promise((resolve, reject) => { | 81 | 81 | const timeout = new Timeout(resolve, after, args, false, ref); | 82 | 82 | insert(timeout, timeout._idleTimeout); | 83 | 83 | if (signal) { | 84 | 84 | oncancel = FunctionPrototypeBind(cancelListenerHandler, | 85 | | - timeout, clearTimeout, reject); | | 85 | + timeout, clearTimeout, reject, signal); | 86 | 86 | signal.addEventListener('abort', oncancel); | 87 | 87 | } | 88 | 88 | }); | @@ -117,15 +117,16 @@ function setImmediate(value, options = kEmptyObject) { | 117 | 117 | // to 12.x, then this can be converted to use optional chaining to | 118 | 118 | // simplify the check. | 119 | 119 | if (signal && signal.aborted) { | 120 | | - return PromiseReject(new AbortError()); | | 120 | + return PromiseReject(new AbortError(undefined, { cause: signal.reason })); | 121 | 121 | } | 122 | 122 | let oncancel; | 123 | 123 | const ret = new Promise((resolve, reject) => { | 124 | 124 | const immediate = new Immediate(resolve, [value]); | 125 | 125 | if (!ref) immediate.unref(); | 126 | 126 | if (signal) { | 127 | 127 | oncancel = FunctionPrototypeBind(cancelListenerHandler, | 128 | | - immediate, clearImmediate, reject); | | 128 | + immediate, clearImmediate, reject, | | 129 | + signal); | 129 | 130 | signal.addEventListener('abort', oncancel); | 130 | 131 | } | 131 | 132 | }); | @@ -142,7 +143,7 @@ async function* setInterval(after, value, options = kEmptyObject) { | 142 | 143 | validateBoolean(ref, 'options.ref'); | 143 | 144 |
| 144 | 145 | if (signal?.aborted) | 145 | | - throw new AbortError(); | | 146 | + throw new AbortError(undefined, { cause: signal?.reason }); | 146 | 147 |
| 147 | 148 | let onCancel; | 148 | 149 | let interval; | @@ -161,7 +162,9 @@ async function* setInterval(after, value, options = kEmptyObject) { | 161 | 162 | onCancel = () => { | 162 | 163 | clearInterval(interval); | 163 | 164 | if (callback) { | 164 | | - callback(PromiseReject(new AbortError())); | | 165 | + callback( | | 166 | + PromiseReject( | | 167 | + new AbortError(undefined, { cause: signal.reason }))); | 165 | 168 | callback = undefined; | 166 | 169 | } | 167 | 170 | }; | @@ -176,7 +179,7 @@ async function* setInterval(after, value, options = kEmptyObject) { | 176 | 179 | yield value; | 177 | 180 | } | 178 | 181 | } | 179 | | - throw new AbortError(); | | 182 | + throw new AbortError(undefined, { cause: signal?.reason }); | 180 | 183 | } finally { | 181 | 184 | clearInterval(interval); | 182 | 185 | signal?.removeEventListener('abort', onCancel); | |
Collapse file Copy file name to clipboardExpand all lines: test/parallel/test-timers-immediate-promisified.js +7Lines changed: 7 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -97,3 +97,10 @@ process.on('multipleResolves', common.mustNotCall()); | 97 | 97 | assert.strictEqual(stderr, ''); | 98 | 98 | })); | 99 | 99 | } | | 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()); |
Collapse file Copy file name to clipboardExpand all lines: test/parallel/test-timers-interval-promisified.js +12Lines changed: 12 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -246,3 +246,15 @@ process.on('multipleResolves', common.mustNotCall()); | 246 | 246 | setPromiseTimeout(time_unit * 3).then(() => post = true), | 247 | 247 | ]).then(common.mustCall()); | 248 | 248 | } | | 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, no-empty | | 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()); |
Collapse file Copy file name to clipboardExpand all lines: test/parallel/test-timers-timeout-promisified.js +7Lines changed: 7 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -97,3 +97,10 @@ process.on('multipleResolves', common.mustNotCall()); | 97 | 97 | assert.strictEqual(stderr, ''); | 98 | 98 | })); | 99 | 99 | } | | 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()); |
|