瀏覽代碼

fix(runtime-core): handle error in async setup (#2881)

edison 5 年之前
父節點
當前提交
d668d48e9e

+ 2 - 2
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, callWithErrorHandling } from './errorHandling'
+import { ErrorCodes, callWithAsyncErrorHandling } 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 = callWithErrorHandling(
+    const setupResult = callWithAsyncErrorHandling(
       setup,
       instance,
       ErrorCodes.SETUP_FUNCTION,

+ 38 - 0
packages/server-renderer/__tests__/render.spec.ts

@@ -777,6 +777,44 @@ function testRender(type: string, render: typeof renderToString) {
       expect(html).toBe(`<div>hello</div>`)
     })
 
+    // #2763
+    test('error handling w/ async setup', async () => {
+      const fn = jest.fn()
+      const fn2 = jest.fn()
+
+      const asyncChildren = defineComponent({
+        async setup() {
+          return Promise.reject('async child error')
+        },
+        template: `<div>asyncChildren</div>`
+      })
+      const app = createApp({
+        name: 'App',
+        components: {
+          asyncChildren
+        },
+        template: `<div class="app"><async-children /></div>`,
+        errorCaptured(error) {
+          fn(error)
+        }
+      })
+
+      app.config.errorHandler = error => {
+        fn2(error)
+      }
+
+      const html = await renderToString(app)
+      expect(html).toBe(`<div class="app"><div>asyncChildren</div></div>`)
+
+      expect(fn).toHaveBeenCalledTimes(1)
+      expect(fn).toBeCalledWith('async child error')
+
+      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 = () => {}

+ 12 - 0
packages/server-renderer/__tests__/ssrSuspense.spec.ts

@@ -39,6 +39,9 @@ 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('missing template').toHaveBeenWarned()
   })
 
@@ -71,6 +74,9 @@ describe('SSR Suspense', () => {
       `<div><div>async</div><!----></div>`
     )
     expect('Uncaught error in async setup').toHaveBeenWarned()
+    expect(
+      'Unhandled error during execution of setup function'
+    ).toHaveBeenWarned()
     expect('missing template or render function').toHaveBeenWarned()
   })
 
@@ -94,6 +100,9 @@ describe('SSR Suspense', () => {
       `<div><div>async</div><div><!----></div></div>`
     )
     expect('Uncaught error in async setup').toHaveBeenWarned()
+    expect(
+      'Unhandled error during execution of setup function'
+    ).toHaveBeenWarned()
     expect('missing template').toHaveBeenWarned()
   })
 
@@ -117,6 +126,9 @@ describe('SSR Suspense', () => {
       `<div><!----><div><div>async</div></div></div>`
     )
     expect('Uncaught error in async setup').toHaveBeenWarned()
+    expect(
+      'Unhandled error during execution of setup function'
+    ).toHaveBeenWarned()
     expect('missing template').toHaveBeenWarned()
   })
 })