From ab59bedae4e5e40b28804d88a51305b236d4a873 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=B6=E8=BF=9C=E6=96=B9?= Date: Tue, 19 Mar 2024 20:47:52 +0800 Subject: [PATCH] fix(runtime-core): fix errorHandler causes an infinite loop during execution (#9575) Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Haoqun Jiang --- .../__tests__/errorHandling.spec.ts | 26 +++++++++++++++++++ packages/runtime-core/src/errorHandling.ts | 3 +++ 2 files changed, 29 insertions(+) diff --git a/packages/runtime-core/__tests__/errorHandling.spec.ts b/packages/runtime-core/__tests__/errorHandling.spec.ts index d995c5fa057..085127677ba 100644 --- a/packages/runtime-core/__tests__/errorHandling.spec.ts +++ b/packages/runtime-core/__tests__/errorHandling.spec.ts @@ -583,5 +583,31 @@ describe('error handling', () => { expect(handler).toHaveBeenCalledTimes(4) }) + // #9574 + test('should pause tracking in error handler', async () => { + const error = new Error('error') + const x = ref(Math.random()) + + const handler = vi.fn(() => { + x.value + x.value = Math.random() + }) + + const app = createApp({ + setup() { + return () => { + throw error + } + }, + }) + + app.config.errorHandler = handler + app.mount(nodeOps.createElement('div')) + + await nextTick() + expect(handler).toHaveBeenCalledWith(error, {}, 'render function') + expect(handler).toHaveBeenCalledTimes(1) + }) + // native event handler handling should be tested in respective renderers }) diff --git a/packages/runtime-core/src/errorHandling.ts b/packages/runtime-core/src/errorHandling.ts index 041eb123938..dda6480385b 100644 --- a/packages/runtime-core/src/errorHandling.ts +++ b/packages/runtime-core/src/errorHandling.ts @@ -1,3 +1,4 @@ +import { pauseTracking, resetTracking } from '@vue/reactivity' import type { VNode } from './vnode' import type { ComponentInternalInstance } from './component' import { popWarningContext, pushWarningContext, warn } from './warning' @@ -127,12 +128,14 @@ export function handleError( // app-level handling const appErrorHandler = instance.appContext.config.errorHandler if (appErrorHandler) { + pauseTracking() callWithErrorHandling( appErrorHandler, null, ErrorCodes.APP_ERROR_HANDLER, [err, exposedInstance, errorInfo], ) + resetTracking() return } }