diff --git a/packages/runtime-core/__tests__/vnode.spec.ts b/packages/runtime-core/__tests__/vnode.spec.ts index fdd23797b10..54cdc725b4d 100644 --- a/packages/runtime-core/__tests__/vnode.spec.ts +++ b/packages/runtime-core/__tests__/vnode.spec.ts @@ -8,11 +8,12 @@ import { cloneVNode, mergeProps, normalizeVNode, - transformVNodeArgs + transformVNodeArgs, + isBlockTreeEnabled } from '../src/vnode' import { Data } from '../src/component' import { ShapeFlags, PatchFlags } from '@vue/shared' -import { h, reactive, isReactive, setBlockTracking, ref } from '../src' +import { h, reactive, isReactive, setBlockTracking, ref, withCtx } from '../src' import { createApp, nodeOps, serializeInner } from '@vue/runtime-test' import { setCurrentRenderingInstance } from '../src/componentRenderContext' @@ -614,6 +615,29 @@ describe('vnode', () => { ])) expect(vnode.dynamicChildren).toStrictEqual([]) }) + // #5657 + test('error of slot function execution should not affect block tracking', () => { + expect(isBlockTreeEnabled).toStrictEqual(1) + const slotFn = withCtx( + () => { + throw new Error('slot execution error') + }, + { type: {}, appContext: {} } as any + ) + const Parent = { + setup(_: any, { slots }: any) { + return () => { + try { + slots.default() + } catch (e) {} + } + } + } + const vnode = + (openBlock(), createBlock(Parent, null, { default: slotFn })) + createApp(vnode).mount(nodeOps.createElement('div')) + expect(isBlockTreeEnabled).toStrictEqual(1) + }) }) describe('transformVNodeArgs', () => { diff --git a/packages/runtime-core/src/componentRenderContext.ts b/packages/runtime-core/src/componentRenderContext.ts index 8f49ec251d5..8097dc5fe2b 100644 --- a/packages/runtime-core/src/componentRenderContext.ts +++ b/packages/runtime-core/src/componentRenderContext.ts @@ -89,10 +89,14 @@ export function withCtx( setBlockTracking(-1) } const prevInstance = setCurrentRenderingInstance(ctx) - const res = fn(...args) - setCurrentRenderingInstance(prevInstance) - if (renderFnWithContext._d) { - setBlockTracking(1) + let res + try { + res = fn(...args) + } finally { + setCurrentRenderingInstance(prevInstance) + if (renderFnWithContext._d) { + setBlockTracking(1) + } } if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) {