* Safely invoke a user-supplied callback. If the callback throws * synchronously, the owning object is destroyed with the error. If the * callback returns a promise that rejects, the rejection is caught and the * owning object is destroyed. Sync callbacks that do not throw incur no * promise all
(fn, owner, ...args)
| 1174 | * @param {...any} args Arguments forwarded to the callback. |
| 1175 | */ |
| 1176 | function safeCallbackInvoke(fn, owner, ...args) { |
| 1177 | try { |
| 1178 | const result = fn(...args, owner); |
| 1179 | if (isPromise(result)) { |
| 1180 | // Block body - do NOT return the result of `owner.destroy(err)`. |
| 1181 | // For some owners (e.g. `QuicEndpoint`), `destroy(err)` returns the |
| 1182 | // owner's `closed` promise which itself eventually rejects with |
| 1183 | // the same error. If we let that propagate through the `.then()` |
| 1184 | // chain promise, nobody is awaiting that chain and we surface the |
| 1185 | // rejection as unhandled. |
| 1186 | PromisePrototypeThen(result, undefined, (err) => { |
| 1187 | owner.destroy(err); |
| 1188 | }); |
| 1189 | } |
| 1190 | } catch (err) { |
| 1191 | owner.destroy(err); |
| 1192 | } |
| 1193 | } |
| 1194 | |
| 1195 | /** |
| 1196 | * Invoke an onerror callback. If the callback itself throws synchronously |
no test coverage detected
searching dependent graphs…