From 26a65548e1215dcd74b7a55a93f6f26ac2085130 Mon Sep 17 00:00:00 2001 From: Rairn <958414905@qq.com> Date: Mon, 24 Oct 2022 17:55:14 +0800 Subject: [PATCH 1/3] fix(hmr): avoid infinite recursion when reloading hmr components (#6930) --- packages/runtime-core/__tests__/hmr.spec.ts | 50 ++++++++++++++++++++- packages/runtime-core/src/hmr.ts | 8 +++- 2 files changed, 56 insertions(+), 2 deletions(-) diff --git a/packages/runtime-core/__tests__/hmr.spec.ts b/packages/runtime-core/__tests__/hmr.spec.ts index b81a8b3af63..8128d458804 100644 --- a/packages/runtime-core/__tests__/hmr.spec.ts +++ b/packages/runtime-core/__tests__/hmr.spec.ts @@ -9,7 +9,8 @@ import { serializeInner, triggerEvent, TestElement, - nextTick + nextTick, + ref } from '@vue/runtime-test' import * as runtimeTest from '@vue/runtime-test' import { registerRuntimeCompiler, createApp } from '@vue/runtime-test' @@ -262,6 +263,53 @@ describe('hot module replacement', () => { expect(mountSpy).toHaveBeenCalledTimes(1) }) + // #6930 + test('reload: avoid infinite recursion', async () => { + const root = nodeOps.createElement('div') + const childId = 'test-child-6930' + const unmountSpy = jest.fn() + const mountSpy = jest.fn() + + const Child: ComponentOptions = { + __hmrId: childId, + data() { + return { count: 0 } + }, + expose: ['count'], + unmounted: unmountSpy, + render: compileToFunction(`
{{ count }}
`) + } + createRecord(childId, Child) + + const Parent: ComponentOptions = { + setup() { + const com = ref() + const changeRef = (value: any) => { + com.value = value + } + + return () => [h(Child, { ref: changeRef }), com.value?.count] + } + } + + render(h(Parent), root) + await nextTick() + expect(serializeInner(root)).toBe(`
0
0`) + + reload(childId, { + __hmrId: childId, + data() { + return { count: 1 } + }, + mounted: mountSpy, + render: compileToFunction(`
{{ count }}
`) + }) + await nextTick() + expect(serializeInner(root)).toBe(`
1
1`) + expect(unmountSpy).toHaveBeenCalledTimes(1) + expect(mountSpy).toHaveBeenCalledTimes(1) + }) + // #1156 - static nodes should retain DOM element reference across updates // when HMR is active test('static el reference', async () => { diff --git a/packages/runtime-core/src/hmr.ts b/packages/runtime-core/src/hmr.ts index fe8ca132bc8..91f776025d2 100644 --- a/packages/runtime-core/src/hmr.ts +++ b/packages/runtime-core/src/hmr.ts @@ -137,7 +137,13 @@ function reload(id: string, newComp: HMRComponent) { // 4. Force the parent instance to re-render. This will cause all updated // components to be unmounted and re-mounted. Queue the update so that we // don't end up forcing the same parent to re-render multiple times. - queueJob(instance.parent.update) + queueJob(() => { + if (instance.parent) { + instance.parent.update() + // #6930 avoid infinite recursion + hmrDirtyComponents.delete(oldComp) + } + }) } else if (instance.appContext.reload) { // root instance mounted via createApp() has a reload method instance.appContext.reload() From 9f5e2a6f91ffa91cdf9c67b60d621b31b2c9cf9e Mon Sep 17 00:00:00 2001 From: Rairn <958414905@qq.com> Date: Sat, 4 Feb 2023 15:18:08 +0800 Subject: [PATCH 2/3] chore: fix test --- packages/runtime-core/__tests__/hmr.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/runtime-core/__tests__/hmr.spec.ts b/packages/runtime-core/__tests__/hmr.spec.ts index 8128d458804..badf7718889 100644 --- a/packages/runtime-core/__tests__/hmr.spec.ts +++ b/packages/runtime-core/__tests__/hmr.spec.ts @@ -267,8 +267,8 @@ describe('hot module replacement', () => { test('reload: avoid infinite recursion', async () => { const root = nodeOps.createElement('div') const childId = 'test-child-6930' - const unmountSpy = jest.fn() - const mountSpy = jest.fn() + const unmountSpy = vi.fn() + const mountSpy = vi.fn() const Child: ComponentOptions = { __hmrId: childId, From 351a20178123459129e9644a5b59159b1c59d83e Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Fri, 31 May 2024 15:39:29 +0000 Subject: [PATCH 3/3] [autofix.ci] apply automated fixes --- packages/runtime-core/__tests__/hmr.spec.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/runtime-core/__tests__/hmr.spec.ts b/packages/runtime-core/__tests__/hmr.spec.ts index 510a0d2af34..39aece16a5a 100644 --- a/packages/runtime-core/__tests__/hmr.spec.ts +++ b/packages/runtime-core/__tests__/hmr.spec.ts @@ -430,7 +430,7 @@ describe('hot module replacement', () => { }, expose: ['count'], unmounted: unmountSpy, - render: compileToFunction(`
{{ count }}
`) + render: compileToFunction(`
{{ count }}
`), } createRecord(childId, Child) @@ -442,7 +442,7 @@ describe('hot module replacement', () => { } return () => [h(Child, { ref: changeRef }), com.value?.count] - } + }, } render(h(Parent), root) @@ -455,7 +455,7 @@ describe('hot module replacement', () => { return { count: 1 } }, mounted: mountSpy, - render: compileToFunction(`
{{ count }}
`) + render: compileToFunction(`
{{ count }}
`), }) await nextTick() expect(serializeInner(root)).toBe(`
1
1`)