From 83b463b83300ad4fbc013cdbdf3f0e11e8314628 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BC=BC=E6=B0=B4=E5=BE=AE=E5=AF=92?= Date: Wed, 6 Apr 2022 15:57:26 +0800 Subject: [PATCH 1/3] fix(runtime-core):#5657 --- packages/runtime-core/__tests__/vnode.spec.ts | 25 ++++++++++++++++++- .../src/componentRenderContext.ts | 15 ++++++++--- packages/runtime-core/src/errorHandling.ts | 6 +++-- 3 files changed, 39 insertions(+), 7 deletions(-) diff --git a/packages/runtime-core/__tests__/vnode.spec.ts b/packages/runtime-core/__tests__/vnode.spec.ts index fdd23797b10..8c31f9b316f 100644 --- a/packages/runtime-core/__tests__/vnode.spec.ts +++ b/packages/runtime-core/__tests__/vnode.spec.ts @@ -12,7 +12,7 @@ import { } 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 +614,29 @@ describe('vnode', () => { ])) expect(vnode.dynamicChildren).toStrictEqual([]) }) + // #5657 + test('error of slot function execution should not affect block tracking', () => { + const error = new Error('slot execution error') + let caughtError + const slot = withCtx( + () => { + throw error + }, + { type: {}, appContext: {} } as any + ) + try { + slot() + } catch (e) { + caughtError = e + } + expect(caughtError).toBe(error) + expect( + `[Vue warn]: Unhandled error during execution of slot function` + ).toHaveBeenWarned() + + const vnode = (openBlock(), createBlock('div')) + expect(vnode.dynamicChildren).toStrictEqual([]) + }) }) describe('transformVNodeArgs', () => { diff --git a/packages/runtime-core/src/componentRenderContext.ts b/packages/runtime-core/src/componentRenderContext.ts index 8f49ec251d5..3965218b205 100644 --- a/packages/runtime-core/src/componentRenderContext.ts +++ b/packages/runtime-core/src/componentRenderContext.ts @@ -1,6 +1,7 @@ import { ComponentInternalInstance } from './component' import { devtoolsComponentUpdated } from './devtools' import { setBlockTracking } from './vnode' +import { handleError, ErrorCodes } from './errorHandling' /** * mark the current rendering instance for asset resolution (e.g. @@ -89,10 +90,16 @@ 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) + } catch (e) { + handleError(e, prevInstance, ErrorCodes.SLOT_FUNCTION) + } finally { + setCurrentRenderingInstance(prevInstance) + if (renderFnWithContext._d) { + setBlockTracking(1) + } } if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) { diff --git a/packages/runtime-core/src/errorHandling.ts b/packages/runtime-core/src/errorHandling.ts index d190b993d43..8a3f96ecf57 100644 --- a/packages/runtime-core/src/errorHandling.ts +++ b/packages/runtime-core/src/errorHandling.ts @@ -20,7 +20,8 @@ export const enum ErrorCodes { APP_WARN_HANDLER, FUNCTION_REF, ASYNC_COMPONENT_LOADER, - SCHEDULER + SCHEDULER, + SLOT_FUNCTION } export const ErrorTypeStrings: Record = { @@ -54,7 +55,8 @@ export const ErrorTypeStrings: Record = { [ErrorCodes.ASYNC_COMPONENT_LOADER]: 'async component loader', [ErrorCodes.SCHEDULER]: 'scheduler flush. This is likely a Vue internals bug. ' + - 'Please open an issue at https://new-issue.vuejs.org/?repo=vuejs/core' + 'Please open an issue at https://new-issue.vuejs.org/?repo=vuejs/core', + [ErrorCodes.SLOT_FUNCTION]: 'slot function' } export type ErrorTypes = LifecycleHooks | ErrorCodes From e49e322dbe35b2ea4dce5ed596ab1d34c6d79e1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BC=BC=E6=B0=B4=E5=BE=AE=E5=AF=92?= Date: Sat, 18 Jun 2022 10:42:10 +0800 Subject: [PATCH 2/3] fix(runtime-core): update test --- packages/runtime-core/__tests__/vnode.spec.ts | 33 ++++++++++--------- .../src/componentRenderContext.ts | 3 -- 2 files changed, 17 insertions(+), 19 deletions(-) diff --git a/packages/runtime-core/__tests__/vnode.spec.ts b/packages/runtime-core/__tests__/vnode.spec.ts index 8c31f9b316f..54cdc725b4d 100644 --- a/packages/runtime-core/__tests__/vnode.spec.ts +++ b/packages/runtime-core/__tests__/vnode.spec.ts @@ -8,7 +8,8 @@ import { cloneVNode, mergeProps, normalizeVNode, - transformVNodeArgs + transformVNodeArgs, + isBlockTreeEnabled } from '../src/vnode' import { Data } from '../src/component' import { ShapeFlags, PatchFlags } from '@vue/shared' @@ -616,26 +617,26 @@ describe('vnode', () => { }) // #5657 test('error of slot function execution should not affect block tracking', () => { - const error = new Error('slot execution error') - let caughtError - const slot = withCtx( + expect(isBlockTreeEnabled).toStrictEqual(1) + const slotFn = withCtx( () => { - throw error + throw new Error('slot execution error') }, { type: {}, appContext: {} } as any ) - try { - slot() - } catch (e) { - caughtError = e + const Parent = { + setup(_: any, { slots }: any) { + return () => { + try { + slots.default() + } catch (e) {} + } + } } - expect(caughtError).toBe(error) - expect( - `[Vue warn]: Unhandled error during execution of slot function` - ).toHaveBeenWarned() - - const vnode = (openBlock(), createBlock('div')) - expect(vnode.dynamicChildren).toStrictEqual([]) + const vnode = + (openBlock(), createBlock(Parent, null, { default: slotFn })) + createApp(vnode).mount(nodeOps.createElement('div')) + expect(isBlockTreeEnabled).toStrictEqual(1) }) }) diff --git a/packages/runtime-core/src/componentRenderContext.ts b/packages/runtime-core/src/componentRenderContext.ts index 3965218b205..8097dc5fe2b 100644 --- a/packages/runtime-core/src/componentRenderContext.ts +++ b/packages/runtime-core/src/componentRenderContext.ts @@ -1,7 +1,6 @@ import { ComponentInternalInstance } from './component' import { devtoolsComponentUpdated } from './devtools' import { setBlockTracking } from './vnode' -import { handleError, ErrorCodes } from './errorHandling' /** * mark the current rendering instance for asset resolution (e.g. @@ -93,8 +92,6 @@ export function withCtx( let res try { res = fn(...args) - } catch (e) { - handleError(e, prevInstance, ErrorCodes.SLOT_FUNCTION) } finally { setCurrentRenderingInstance(prevInstance) if (renderFnWithContext._d) { From 1e6c0b41912765a7c4a136552c479ff258d763c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BC=BC=E6=B0=B4=E5=BE=AE=E5=AF=92?= Date: Sat, 18 Jun 2022 10:45:48 +0800 Subject: [PATCH 3/3] fix(runtime-core): update test --- packages/runtime-core/src/errorHandling.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/runtime-core/src/errorHandling.ts b/packages/runtime-core/src/errorHandling.ts index 8a3f96ecf57..d190b993d43 100644 --- a/packages/runtime-core/src/errorHandling.ts +++ b/packages/runtime-core/src/errorHandling.ts @@ -20,8 +20,7 @@ export const enum ErrorCodes { APP_WARN_HANDLER, FUNCTION_REF, ASYNC_COMPONENT_LOADER, - SCHEDULER, - SLOT_FUNCTION + SCHEDULER } export const ErrorTypeStrings: Record = { @@ -55,8 +54,7 @@ export const ErrorTypeStrings: Record = { [ErrorCodes.ASYNC_COMPONENT_LOADER]: 'async component loader', [ErrorCodes.SCHEDULER]: 'scheduler flush. This is likely a Vue internals bug. ' + - 'Please open an issue at https://new-issue.vuejs.org/?repo=vuejs/core', - [ErrorCodes.SLOT_FUNCTION]: 'slot function' + 'Please open an issue at https://new-issue.vuejs.org/?repo=vuejs/core' } export type ErrorTypes = LifecycleHooks | ErrorCodes