From 235b327c0354c8aad2eeb48b0c027b598e7512cf Mon Sep 17 00:00:00 2001 From: Wil Wilsman Date: Fri, 29 Jul 2022 15:45:13 -0500 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20Explicitly=20handle=20yieldTo=20?= =?UTF-8?q?promise=20resolution=20and=20rejection=20(#1017)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If we allow yieldTo promise errors to bubble, some version of node throws an error. These type of errors can be avoided completely by always explicitly handling promise resolution and rejection. --- packages/core/src/utils.js | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/packages/core/src/utils.js b/packages/core/src/utils.js index 19662df68..722aaca98 100644 --- a/packages/core/src/utils.js +++ b/packages/core/src/utils.js @@ -99,11 +99,19 @@ export class AbortError extends Error { // An async generator that yields after every event loop until the promise settles export async function* yieldTo(subject) { - let pending = typeof subject?.finally === 'function'; - if (pending) subject.then(() => (pending = false), () => (pending = false)); + // yield to any provided generator or return non-promise values + if (isGenerator(subject)) return yield* subject; + if (typeof subject?.then !== 'function') return subject; + + // update local variables with the provided promise + let result, error, pending = !!subject + .then(r => (result = r), e => (error = e)) + .finally(() => (pending = false)); + /* eslint-disable-next-line no-unmodified-loop-condition */ while (pending) yield new Promise(r => setImmediate(r)); - return isGenerator(subject) ? yield* subject : await subject; + if (error) throw error; + return result; } // An async generator that runs provided generators concurrently