Skip to content

Commit

Permalink
fix(jsx): await all promises at once to avoid race condition (#3274)
Browse files Browse the repository at this point in the history
  • Loading branch information
usualoma authored Aug 15, 2024
1 parent 986db29 commit a5b2382
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 3 deletions.
33 changes: 33 additions & 0 deletions src/jsx/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,39 @@ describe('JSX middleware', () => {
expect(res.headers.get('Content-Type')).toBe('text/html; charset=UTF-8')
expect(await res.text()).toBe('<html><body><h1>Hello from async component</h1></body></html>')
})

it('Should handle async component error', async () => {
const componentError = new Error('Error from async error component')

const AsyncComponent = async () => {
await new Promise((resolve) => setTimeout(resolve, 10))
return <h1>Hello from async component</h1>
}
const AsyncErrorComponent = async () => {
await new Promise((resolve) => setTimeout(resolve, 0))
throw componentError
}

let raisedError: any
app.onError((e, c) => {
raisedError = e
return c.html('<html><body><h1>Error from onError</h1></body></html>', 500)
})
app.get('/', (c) => {
return c.html(
<>
<AsyncComponent />
<AsyncErrorComponent />
</>
)
})

const res = await app.request('http://localhost/')
expect(res.status).toBe(500)
expect(res.headers.get('Content-Type')).toBe('text/html; charset=UTF-8')
expect(await res.text()).toBe('<html><body><h1>Error from onError</h1></body></html>')
expect(raisedError).toBe(componentError)
})
})

describe('render to string', () => {
Expand Down
7 changes: 4 additions & 3 deletions src/utils/html.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,15 @@ export const stringBufferToString = async (
): Promise<HtmlEscapedString> => {
let str = ''
callbacks ||= []
for (let i = buffer.length - 1; ; i--) {
str += buffer[i]
const resolvedBuffer = await Promise.all(buffer)
for (let i = resolvedBuffer.length - 1; ; i--) {
str += resolvedBuffer[i]
i--
if (i < 0) {
break
}

let r = await buffer[i]
let r = resolvedBuffer[i]
if (typeof r === 'object') {
callbacks.push(...((r as HtmlEscapedString).callbacks || []))
}
Expand Down

0 comments on commit a5b2382

Please sign in to comment.