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,
|
||||
nextTick,
|
||||
nodeOps,
|
||||
ref,
|
||||
render,
|
||||
serializeInner,
|
||||
triggerEvent,
|
||||
|
@ -415,6 +416,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 = 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
|
||||
// when HMR is active
|
||||
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
|
||||
// don't end up forcing the same parent to re-render multiple times.
|
||||
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) {
|
||||
// root instance mounted via createApp() has a reload method
|
||||
instance.appContext.reload()
|
||||
|
|
Loading…
Reference in New Issue