*/
subsHead?: Link
+ /**
+ * For object property deps cleanup
+ */
+ target?: unknown = undefined
+ map?: KeyToDepMap = undefined
+ key?: unknown = undefined
+
constructor(public computed?: ComputedRefImpl | undefined) {
if (__DEV__) {
this.subsHead = undefined
// which maintains a Set of subscribers, but we simply store them as
// raw Maps to reduce memory overhead.
type KeyToDepMap = Map<any, Dep>
-const targetMap = new WeakMap<object, KeyToDepMap>()
+
+export const targetMap: WeakMap<object, KeyToDepMap> = new WeakMap()
export const ITERATE_KEY: unique symbol = Symbol(
__DEV__ ? 'Object iterate' : '',
let dep = depsMap.get(key)
if (!dep) {
depsMap.set(key, (dep = new Dep()))
+ dep.target = target
+ dep.map = depsMap
+ dep.key = key
}
if (__DEV__) {
dep.track({
import { extend, hasChanged } from '@vue/shared'
import type { ComputedRefImpl } from './computed'
import type { TrackOpTypes, TriggerOpTypes } from './constants'
-import { type Link, globalVersion } from './dep'
+import { type Link, globalVersion, targetMap } from './dep'
import { activeEffectScope } from './effectScope'
import { warn } from './warning'
dep.subsHead = nextSub
}
- if (!dep.subs && dep.computed) {
+ if (!dep.subs) {
// last subscriber removed
- // if computed, unsubscribe it from all its deps so this computed and its
- // value can be GCed
- dep.computed.flags &= ~EffectFlags.TRACKING
- for (let l = dep.computed.deps; l; l = l.nextDep) {
- removeSub(l)
+ if (dep.computed) {
+ // if computed, unsubscribe it from all its deps so this computed and its
+ // value can be GCed
+ dep.computed.flags &= ~EffectFlags.TRACKING
+ for (let l = dep.computed.deps; l; l = l.nextDep) {
+ removeSub(l)
+ }
+ } else if (dep.map) {
+ // property dep, remove it from the owner depsMap
+ dep.map.delete(dep.key)
+ if (!dep.map.size) targetMap.delete(dep.target!)
}
}
}