diff --git a/packages/reactivity/src/dep.ts b/packages/reactivity/src/dep.ts index c24f123ded4..6c051590cb9 100644 --- a/packages/reactivity/src/dep.ts +++ b/packages/reactivity/src/dep.ts @@ -82,6 +82,11 @@ export class Dep { */ subsHead?: Link + /** + * Delete itself from depsMap + */ + cleanup?: () => void + constructor(public computed?: ComputedRefImpl | undefined) { if (__DEV__) { this.subsHead = undefined @@ -249,6 +254,7 @@ export function track(target: object, type: TrackOpTypes, key: unknown): void { let dep = depsMap.get(key) if (!dep) { depsMap.set(key, (dep = new Dep())) + dep.cleanup = () => depsMap.delete(key) } if (__DEV__) { dep.track({ diff --git a/packages/reactivity/src/effect.ts b/packages/reactivity/src/effect.ts index b8dd62a0f6e..9cef2b4890a 100644 --- a/packages/reactivity/src/effect.ts +++ b/packages/reactivity/src/effect.ts @@ -414,14 +414,22 @@ function removeSub(link: Link) { dep.subs = prevSub } - 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) { + dep.computed.flags &= ~EffectFlags.TRACKING + for (let l = dep.computed.deps; l; l = l.nextDep) { + removeSub(l) + } } + + // cleanup subsHead + if (__DEV__ && prevSub === undefined) dep.subsHead = undefined + + // remove the dep from depsMap + if (dep.cleanup) dep.cleanup() } }