fix(reactivity): ensure watch(Effect) can run independent of unmounted instance if created in a detatched effectScope (fix #7319) (#7330)

* fix(reactivity): ensure watch(Effect) can run independent of unmounted instance if created in a detatched effectScope

* test: use separate counters for each watcher to make test more robust
This commit is contained in:
Thorsten Lünborg 2023-01-09 15:20:21 +01:00 committed by GitHub
parent 8731852919
commit cd7c887b75
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 44 additions and 2 deletions

View File

@ -1150,4 +1150,44 @@ describe('api: watch', () => {
// own update effect
expect(instance!.scope.effects.length).toBe(1)
})
test('watchEffect should keep running if created in a detatched scope', async () => {
const trigger = ref(0)
let countWE = 0
let countW = 0
const Comp = {
setup() {
effectScope(true).run(() => {
watchEffect(
() => {
trigger.value
countWE++
},
)
watch(
trigger,
() => countW++
)
})
return () => ''
}
}
const root = nodeOps.createElement('div')
render(h(Comp), root)
// only watchEffect as ran so far
expect(countWE).toBe(1)
expect(countW).toBe(0)
trigger.value++
await nextTick()
// both watchers run while component is mounted
expect(countWE).toBe(2)
expect(countW).toBe(1)
render(null, root) // unmount
await nextTick()
trigger.value++
await nextTick()
// both watchers run again event though component has been unmounted
expect(countWE).toBe(3)
expect(countW).toBe(2)
})
})

View File

@ -7,7 +7,8 @@ import {
isReactive,
ReactiveFlags,
EffectScheduler,
DebuggerOptions
DebuggerOptions,
getCurrentScope,
} from '@vue/reactivity'
import { SchedulerJob, queueJob } from './scheduler'
import {
@ -197,7 +198,8 @@ function doWatch(
)
}
const instance = currentInstance
const instance = getCurrentScope() === currentInstance?.scope ? currentInstance : null
// const instance = currentInstance
let getter: () => any
let forceTrigger = false
let isMultiSource = false