diff --git a/packages/runtime-core/src/component.ts b/packages/runtime-core/src/component.ts index fe81efedf..1295b7593 100644 --- a/packages/runtime-core/src/component.ts +++ b/packages/runtime-core/src/component.ts @@ -23,7 +23,7 @@ import { } from './componentProps' import { Slots, initSlots, InternalSlots } from './componentSlots' import { warn } from './warning' -import { ErrorCodes, callWithAsyncErrorHandling } from './errorHandling' +import { ErrorCodes, callWithErrorHandling, handleError } from './errorHandling' import { AppContext, createAppContext, AppConfig } from './apiCreateApp' import { Directive, validateDirectiveName } from './directives' import { @@ -579,7 +579,7 @@ function setupStatefulComponent( currentInstance = instance pauseTracking() - const setupResult = callWithAsyncErrorHandling( + const setupResult = callWithErrorHandling( setup, instance, ErrorCodes.SETUP_FUNCTION, @@ -591,9 +591,13 @@ function setupStatefulComponent( if (isPromise(setupResult)) { if (isSSR) { // return the promise so server-renderer can wait on it - return setupResult.then((resolvedResult: unknown) => { - handleSetupResult(instance, resolvedResult, isSSR) - }) + return setupResult + .then((resolvedResult: unknown) => { + handleSetupResult(instance, resolvedResult, isSSR) + }) + .catch(e => { + handleError(e, instance, ErrorCodes.SETUP_FUNCTION) + }) } else if (__FEATURE_SUSPENSE__) { // async setup returned Promise. // bail here and wait for re-entry. diff --git a/packages/server-renderer/__tests__/render.spec.ts b/packages/server-renderer/__tests__/render.spec.ts index e537d9d78..bb7009f87 100644 --- a/packages/server-renderer/__tests__/render.spec.ts +++ b/packages/server-renderer/__tests__/render.spec.ts @@ -811,10 +811,8 @@ function testRender(type: string, render: typeof renderToString) { expect(fn2).toHaveBeenCalledTimes(1) expect(fn2).toBeCalledWith('async child error') - - expect('Uncaught error in async setup').toHaveBeenWarned() }) - + // https://github.com/vuejs/vue-next/issues/3322 test('effect onInvalidate does not error', async () => { const noop = () => {} diff --git a/packages/server-renderer/__tests__/ssrSuspense.spec.ts b/packages/server-renderer/__tests__/ssrSuspense.spec.ts index 3cdd81373..4da4ce4b9 100644 --- a/packages/server-renderer/__tests__/ssrSuspense.spec.ts +++ b/packages/server-renderer/__tests__/ssrSuspense.spec.ts @@ -29,6 +29,7 @@ describe('SSR Suspense', () => { test('reject', async () => { const Comp = { + errorCaptured: jest.fn(() => false), render() { return h(Suspense, null, { default: h(RejectingAsync), @@ -38,10 +39,8 @@ describe('SSR Suspense', () => { } expect(await renderToString(createApp(Comp))).toBe(``) - expect('Uncaught error in async setup').toHaveBeenWarned() - expect( - 'Unhandled error during execution of setup function' - ).toHaveBeenWarned() + + expect(Comp.errorCaptured).toHaveBeenCalledTimes(1) expect('missing template').toHaveBeenWarned() }) @@ -62,6 +61,7 @@ describe('SSR Suspense', () => { test('resolving component + rejecting component', async () => { const Comp = { + errorCaptured: jest.fn(() => false), render() { return h(Suspense, null, { default: h('div', [h(ResolvingAsync), h(RejectingAsync)]), @@ -73,15 +73,14 @@ describe('SSR Suspense', () => { expect(await renderToString(createApp(Comp))).toBe( `