]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(runtime-core): handle error in async setup (#2881)
authoredison <daiwei521@126.com>
Fri, 26 Mar 2021 14:26:30 +0000 (22:26 +0800)
committerGitHub <noreply@github.com>
Fri, 26 Mar 2021 14:26:30 +0000 (10:26 -0400)
packages/runtime-core/src/component.ts
packages/server-renderer/__tests__/render.spec.ts
packages/server-renderer/__tests__/ssrSuspense.spec.ts

index 51147ccc8f404b16a44b6bb9396625bb9705911b..fe81efedfaf2f3b060fcb4ac6f47fbdb4b297bea 100644 (file)
@@ -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,
index 85d537621b8d714769dd47d2c4640cf08896c5ab..e537d9d78d506cc2f5bc1e15a38bb09de03b96f5 100644 (file)
@@ -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 = () => {}
index a7d1078783328527724bf078e63158db4169ae78..3cdd81373703e967ff3ed489eacbd9c0f6f914f5 100644 (file)
@@ -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()
   })
 })