fix(ssr): ensure async setup error handling work with suspense during ssr
This commit is contained in:
parent
d668d48e9e
commit
2e71f07bc1
@ -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) => {
|
||||
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.
|
||||
|
@ -811,8 +811,6 @@ 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
|
||||
|
@ -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(
|
||||
`<div><div>async</div><!----></div>`
|
||||
)
|
||||
expect('Uncaught error in async setup').toHaveBeenWarned()
|
||||
expect(
|
||||
'Unhandled error during execution of setup function'
|
||||
).toHaveBeenWarned()
|
||||
|
||||
expect(Comp.errorCaptured).toHaveBeenCalledTimes(1)
|
||||
expect('missing template or render function').toHaveBeenWarned()
|
||||
})
|
||||
|
||||
test('failing suspense in passing suspense', async () => {
|
||||
const Comp = {
|
||||
errorCaptured: jest.fn(() => false),
|
||||
render() {
|
||||
return h(Suspense, null, {
|
||||
default: h('div', [
|
||||
@ -99,15 +98,14 @@ describe('SSR Suspense', () => {
|
||||
expect(await renderToString(createApp(Comp))).toBe(
|
||||
`<div><div>async</div><div><!----></div></div>`
|
||||
)
|
||||
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()
|
||||
})
|
||||
|
||||
test('passing suspense in failing suspense', async () => {
|
||||
const Comp = {
|
||||
errorCaptured: jest.fn(() => false),
|
||||
render() {
|
||||
return h(Suspense, null, {
|
||||
default: h('div', [
|
||||
@ -125,10 +123,7 @@ describe('SSR Suspense', () => {
|
||||
expect(await renderToString(createApp(Comp))).toBe(
|
||||
`<div><!----><div><div>async</div></div></div>`
|
||||
)
|
||||
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()
|
||||
})
|
||||
})
|
||||
|
@ -89,11 +89,7 @@ export function renderComponentVNode(
|
||||
const hasAsyncSetup = isPromise(res)
|
||||
const prefetch = (vnode.type as ComponentOptions).serverPrefetch
|
||||
if (hasAsyncSetup || prefetch) {
|
||||
let p = hasAsyncSetup
|
||||
? (res as Promise<void>).catch(err => {
|
||||
warn(`[@vue/server-renderer]: Uncaught error in async setup:\n`, err)
|
||||
})
|
||||
: Promise.resolve()
|
||||
let p = hasAsyncSetup ? (res as Promise<void>) : Promise.resolve()
|
||||
if (prefetch) {
|
||||
p = p.then(() => prefetch.call(instance.proxy)).catch(err => {
|
||||
warn(`[@vue/server-renderer]: Uncaught error in serverPrefetch:\n`, err)
|
||||
|
Loading…
Reference in New Issue
Block a user