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`)