diff --git a/packages/server-renderer/__tests__/render.spec.ts b/packages/server-renderer/__tests__/render.spec.ts index d0a5223b2ff..5083a983016 100644 --- a/packages/server-renderer/__tests__/render.spec.ts +++ b/packages/server-renderer/__tests__/render.spec.ts @@ -12,6 +12,7 @@ import { defineComponent, getCurrentInstance, h, + nextTick, onErrorCaptured, onServerPrefetch, reactive, @@ -819,6 +820,9 @@ function testRender(type: string, render: typeof renderToString) { ) } catch {} expect(getCurrentInstance()).toBe(prev) + expect( + '[Vue warn]: Unhandled error during execution of render function', + ).toHaveBeenWarned() }) // #7733 @@ -1188,6 +1192,42 @@ function testRender(type: string, render: typeof renderToString) { expect((capturedError as unknown as Error).message).toBe('An error') }) + test('async setup throwing error', async () => { + let capturedError: string[] = [] + + const Child = { + async setup() { + await nextTick() + throw new Error('An error') + return { foo: { bar: 1 } } + }, + template: `{{ foo.bar }}`, + } + + const app = createApp({ + components: { Child }, + setup() { + onErrorCaptured(e => { + capturedError.push(e.message) + return false + }) + }, + template: ``, + }) + + try { + await render(app) + } catch (e: any) {} + expect(capturedError.length).toBe(2) + expect(capturedError).toStrictEqual([ + 'An error', + "Cannot read properties of undefined (reading 'bar')", + ]) + expect( + '[Vue warn]: Property "foo" was accessed during render but is not defined on instance', + ).toHaveBeenWarned() + }) + test('computed reactivity during SSR with onServerPrefetch', async () => { const store = { // initial state could be hydrated diff --git a/packages/server-renderer/src/render.ts b/packages/server-renderer/src/render.ts index f04080b9c31..cb2a88028d6 100644 --- a/packages/server-renderer/src/render.ts +++ b/packages/server-renderer/src/render.ts @@ -3,6 +3,7 @@ import { type Component, type ComponentInternalInstance, type DirectiveBinding, + ErrorCodes, Fragment, type FunctionalComponent, Static, @@ -10,6 +11,7 @@ import { type VNode, type VNodeArrayChildren, type VNodeProps, + handleError, mergeProps, ssrUtils, warn, @@ -200,6 +202,8 @@ function renderComponentSubTree( instance.data, instance.ctx, ) + } catch (err) { + handleError(err, instance, ErrorCodes.RENDER_FUNCTION) } finally { setCurrentRenderingInstance(prev) }