fix(hmr): avoid infinite recursion when reloading hmr components (#6936)
close #6930
This commit is contained in:
parent
f1cc478819
commit
36bd9b0a1f
|
@ -6,6 +6,7 @@ import {
|
||||||
h,
|
h,
|
||||||
nextTick,
|
nextTick,
|
||||||
nodeOps,
|
nodeOps,
|
||||||
|
ref,
|
||||||
render,
|
render,
|
||||||
serializeInner,
|
serializeInner,
|
||||||
triggerEvent,
|
triggerEvent,
|
||||||
|
@ -415,6 +416,53 @@ describe('hot module replacement', () => {
|
||||||
expect(mountSpy).toHaveBeenCalledTimes(1)
|
expect(mountSpy).toHaveBeenCalledTimes(1)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// #6930
|
||||||
|
test('reload: avoid infinite recursion', async () => {
|
||||||
|
const root = nodeOps.createElement('div')
|
||||||
|
const childId = 'test-child-6930'
|
||||||
|
const unmountSpy = vi.fn()
|
||||||
|
const mountSpy = vi.fn()
|
||||||
|
|
||||||
|
const Child: ComponentOptions = {
|
||||||
|
__hmrId: childId,
|
||||||
|
data() {
|
||||||
|
return { count: 0 }
|
||||||
|
},
|
||||||
|
expose: ['count'],
|
||||||
|
unmounted: unmountSpy,
|
||||||
|
render: compileToFunction(`<div @click="count++">{{ count }}</div>`),
|
||||||
|
}
|
||||||
|
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(`<div>0</div>0`)
|
||||||
|
|
||||||
|
reload(childId, {
|
||||||
|
__hmrId: childId,
|
||||||
|
data() {
|
||||||
|
return { count: 1 }
|
||||||
|
},
|
||||||
|
mounted: mountSpy,
|
||||||
|
render: compileToFunction(`<div @click="count++">{{ count }}</div>`),
|
||||||
|
})
|
||||||
|
await nextTick()
|
||||||
|
expect(serializeInner(root)).toBe(`<div>1</div>1`)
|
||||||
|
expect(unmountSpy).toHaveBeenCalledTimes(1)
|
||||||
|
expect(mountSpy).toHaveBeenCalledTimes(1)
|
||||||
|
})
|
||||||
|
|
||||||
// #1156 - static nodes should retain DOM element reference across updates
|
// #1156 - static nodes should retain DOM element reference across updates
|
||||||
// when HMR is active
|
// when HMR is active
|
||||||
test('static el reference', async () => {
|
test('static el reference', async () => {
|
||||||
|
|
|
@ -139,7 +139,11 @@ function reload(id: string, newComp: HMRComponent) {
|
||||||
// components to be unmounted and re-mounted. Queue the update so that we
|
// 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.
|
// don't end up forcing the same parent to re-render multiple times.
|
||||||
instance.parent.effect.dirty = true
|
instance.parent.effect.dirty = true
|
||||||
queueJob(instance.parent.update)
|
queueJob(() => {
|
||||||
|
instance.parent!.update()
|
||||||
|
// #6930 avoid infinite recursion
|
||||||
|
hmrDirtyComponents.delete(oldComp)
|
||||||
|
})
|
||||||
} else if (instance.appContext.reload) {
|
} else if (instance.appContext.reload) {
|
||||||
// root instance mounted via createApp() has a reload method
|
// root instance mounted via createApp() has a reload method
|
||||||
instance.appContext.reload()
|
instance.appContext.reload()
|
||||||
|
|
Loading…
Reference in New Issue