From ffbe87e7a3bda9666245e7e5b1565cd35b9cc5ea Mon Sep 17 00:00:00 2001 From: daiwei Date: Tue, 31 Dec 2024 16:11:41 +0800 Subject: [PATCH 1/2] fix(runtime-core): prevent updating instance if it's already the current instance --- packages/runtime-core/src/component.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/runtime-core/src/component.ts b/packages/runtime-core/src/component.ts index 3ed42ed0b55..cf8a17e9d2b 100644 --- a/packages/runtime-core/src/component.ts +++ b/packages/runtime-core/src/component.ts @@ -760,7 +760,10 @@ if (__SSR__) { } } -export const setCurrentInstance = (instance: ComponentInternalInstance) => { +export const setCurrentInstance = ( + instance: ComponentInternalInstance, +): (() => void) => { + if (currentInstance === instance) return NOOP const prev = currentInstance internalSetCurrentInstance(instance) instance.scope.on() From acb325c13cd393472e0d2561ce220953e5af939d Mon Sep 17 00:00:00 2001 From: daiwei Date: Tue, 31 Dec 2024 16:20:18 +0800 Subject: [PATCH 2/2] test: add test case --- .../runtime-core/__tests__/apiWatch.spec.ts | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/packages/runtime-core/__tests__/apiWatch.spec.ts b/packages/runtime-core/__tests__/apiWatch.spec.ts index 7d2a1e73c08..40b45922375 100644 --- a/packages/runtime-core/__tests__/apiWatch.spec.ts +++ b/packages/runtime-core/__tests__/apiWatch.spec.ts @@ -6,6 +6,7 @@ import { getCurrentInstance, nextTick, onErrorCaptured, + onScopeDispose, onWatcherCleanup, reactive, ref, @@ -1362,6 +1363,32 @@ describe('api: watch', () => { expect(source.mock.calls.some(args => args.includes(instance))) }) + test('this.$watch w/ onScopeDispose', () => { + const onCleanup = vi.fn() + const toggle = ref(true) + + const Comp = defineComponent({ + render() {}, + created(this: any) { + this.$watch( + () => 1, + function () {}, + ) + onScopeDispose(onCleanup) + }, + }) + + const App = defineComponent({ + render() { + return toggle.value ? h(Comp) : null + }, + }) + + const root = nodeOps.createElement('div') + createApp(App).mount(root) + expect(onCleanup).toBeCalledTimes(0) + }) + test('should not leak `this.proxy` to setup()', () => { const source = vi.fn()