From 07125309b25eebc592412786450d5783450e47fa Mon Sep 17 00:00:00 2001 From: Taku Amano Date: Sat, 31 Aug 2024 16:46:32 +0900 Subject: [PATCH] fix(jsx): race condition in ErrorBoundary with event loop (#3343) Fixes #3333 --- src/jsx/components.test.tsx | 28 ++++++++++++++++++++++++++++ src/jsx/components.ts | 10 ++++++++-- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/jsx/components.test.tsx b/src/jsx/components.test.tsx index 43696d599..9f64eec19 100644 --- a/src/jsx/components.test.tsx +++ b/src/jsx/components.test.tsx @@ -191,6 +191,34 @@ describe('ErrorBoundary', () => { }) }) + describe('async : setTimeout', async () => { + const TimeoutSuccessComponent = async () => { + await new Promise((resolve) => setTimeout(resolve, 10)) + return
OK
+ } + const TimeoutErrorComponent = async () => { + await new Promise((resolve) => setTimeout(resolve, 0)) + throw new Error('Error') + } + + it('fallback', async () => { + const html = ( + <> + + }> + + + + ).toString() + + expect((await resolveCallback(await html)).toString()).toEqual( + '
OK
Out Of Service
' + ) + + suspenseCounter-- + }) + }) + describe('streaming', async () => { const Component = async ({ error }: { error?: boolean }) => { await new Promise((resolve) => setTimeout(resolve, 10)) diff --git a/src/jsx/components.ts b/src/jsx/components.ts index 846b1fd49..060d67c88 100644 --- a/src/jsx/components.ts +++ b/src/jsx/components.ts @@ -93,13 +93,19 @@ d.replaceWith(c.content) })(document) ` } + + let error: unknown + const promiseAll = Promise.all(resArray).catch((e) => (error = e)) return raw(``, [ ({ phase, buffer, context }) => { if (phase === HtmlEscapedCallbackPhase.BeforeStream) { return } - return Promise.all(resArray) - .then(async (htmlArray) => { + return promiseAll + .then(async (htmlArray: HtmlEscapedString[]) => { + if (error) { + throw error + } htmlArray = htmlArray.flat() const content = htmlArray.join('') let html = buffer