Skip to content

Commit 235ea47

Browse files
committedSep 20, 2024··
fix(reactivity): fix memory leak from dep instances of garbage collected objects
close #11979 close #11971
1 parent 5c8b76e commit 235ea47

File tree

2 files changed

+25
-8
lines changed

2 files changed

+25
-8
lines changed
 

‎packages/reactivity/src/dep.ts

+12-1
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,13 @@ export class Dep {
8282
*/
8383
subsHead?: Link
8484

85+
/**
86+
* For object property deps cleanup
87+
*/
88+
target?: unknown = undefined
89+
map?: KeyToDepMap = undefined
90+
key?: unknown = undefined
91+
8592
constructor(public computed?: ComputedRefImpl | undefined) {
8693
if (__DEV__) {
8794
this.subsHead = undefined
@@ -218,7 +225,8 @@ function addSub(link: Link) {
218225
// which maintains a Set of subscribers, but we simply store them as
219226
// raw Maps to reduce memory overhead.
220227
type KeyToDepMap = Map<any, Dep>
221-
const targetMap = new WeakMap<object, KeyToDepMap>()
228+
229+
export const targetMap: WeakMap<object, KeyToDepMap> = new WeakMap()
222230

223231
export const ITERATE_KEY: unique symbol = Symbol(
224232
__DEV__ ? 'Object iterate' : '',
@@ -249,6 +257,9 @@ export function track(target: object, type: TrackOpTypes, key: unknown): void {
249257
let dep = depsMap.get(key)
250258
if (!dep) {
251259
depsMap.set(key, (dep = new Dep()))
260+
dep.target = target
261+
dep.map = depsMap
262+
dep.key = key
252263
}
253264
if (__DEV__) {
254265
dep.track({

‎packages/reactivity/src/effect.ts

+13-7
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { extend, hasChanged } from '@vue/shared'
22
import type { ComputedRefImpl } from './computed'
33
import type { TrackOpTypes, TriggerOpTypes } from './constants'
4-
import { type Link, globalVersion } from './dep'
4+
import { type Link, globalVersion, targetMap } from './dep'
55
import { activeEffectScope } from './effectScope'
66
import { warn } from './warning'
77

@@ -418,13 +418,19 @@ function removeSub(link: Link) {
418418
dep.subsHead = nextSub
419419
}
420420

421-
if (!dep.subs && dep.computed) {
421+
if (!dep.subs) {
422422
// last subscriber removed
423-
// if computed, unsubscribe it from all its deps so this computed and its
424-
// value can be GCed
425-
dep.computed.flags &= ~EffectFlags.TRACKING
426-
for (let l = dep.computed.deps; l; l = l.nextDep) {
427-
removeSub(l)
423+
if (dep.computed) {
424+
// if computed, unsubscribe it from all its deps so this computed and its
425+
// value can be GCed
426+
dep.computed.flags &= ~EffectFlags.TRACKING
427+
for (let l = dep.computed.deps; l; l = l.nextDep) {
428+
removeSub(l)
429+
}
430+
} else if (dep.map) {
431+
// property dep, remove it from the owner depsMap
432+
dep.map.delete(dep.key)
433+
if (!dep.map.size) targetMap.delete(dep.target!)
428434
}
429435
}
430436
}

0 commit comments

Comments
 (0)
Please sign in to comment.