Skip to content

Commit d9d63f2

Browse files
committed
fix(reactivity): avoid cross-component dependency leaks in setup()
1 parent 202532c commit d9d63f2

File tree

5 files changed

+27
-7
lines changed

5 files changed

+27
-7
lines changed

packages/reactivity/src/effect.ts

+11-1
Original file line numberDiff line numberDiff line change
@@ -95,11 +95,13 @@ function run(effect: ReactiveEffect, fn: Function, args: unknown[]): unknown {
9595
if (!effectStack.includes(effect)) {
9696
cleanup(effect)
9797
try {
98+
enableTracking()
9899
effectStack.push(effect)
99100
activeEffect = effect
100101
return fn(...args)
101102
} finally {
102103
effectStack.pop()
104+
resetTracking()
103105
activeEffect = effectStack[effectStack.length - 1]
104106
}
105107
}
@@ -116,15 +118,23 @@ function cleanup(effect: ReactiveEffect) {
116118
}
117119

118120
let shouldTrack = true
121+
const trackStack: boolean[] = []
119122

120123
export function pauseTracking() {
124+
trackStack.push(shouldTrack)
121125
shouldTrack = false
122126
}
123127

124-
export function resumeTracking() {
128+
export function enableTracking() {
129+
trackStack.push(shouldTrack)
125130
shouldTrack = true
126131
}
127132

133+
export function resetTracking() {
134+
const last = trackStack.pop()
135+
shouldTrack = last === undefined ? true : last
136+
}
137+
128138
export function track(target: object, type: TrackOpTypes, key: unknown) {
129139
if (!shouldTrack || activeEffect === undefined) {
130140
return

packages/reactivity/src/index.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,11 @@ export {
2121
export {
2222
effect,
2323
stop,
24+
trigger,
25+
track,
26+
enableTracking,
2427
pauseTracking,
25-
resumeTracking,
28+
resetTracking,
2629
ITERATE_KEY,
2730
ReactiveEffect,
2831
ReactiveEffectOptions,

packages/runtime-core/src/apiLifecycle.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { ComponentPublicInstance } from './componentProxy'
99
import { callWithAsyncErrorHandling, ErrorTypeStrings } from './errorHandling'
1010
import { warn } from './warning'
1111
import { capitalize } from '@vue/shared'
12-
import { pauseTracking, resumeTracking, DebuggerEvent } from '@vue/reactivity'
12+
import { pauseTracking, resetTracking, DebuggerEvent } from '@vue/reactivity'
1313

1414
export { onActivated, onDeactivated } from './components/KeepAlive'
1515

@@ -39,7 +39,7 @@ export function injectHook(
3939
setCurrentInstance(target)
4040
const res = callWithAsyncErrorHandling(hook, target, type, args)
4141
setCurrentInstance(null)
42-
resumeTracking()
42+
resetTracking()
4343
return res
4444
})
4545
if (prepend) {

packages/runtime-core/src/component.ts

+8-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
import { VNode, VNodeChild, isVNode } from './vnode'
2-
import { ReactiveEffect, shallowReadonly } from '@vue/reactivity'
2+
import {
3+
ReactiveEffect,
4+
shallowReadonly,
5+
pauseTracking,
6+
resetTracking
7+
} from '@vue/reactivity'
38
import {
49
PublicInstanceProxyHandlers,
510
ComponentPublicInstance,
@@ -341,12 +346,14 @@ function setupStatefulComponent(
341346

342347
currentInstance = instance
343348
currentSuspense = parentSuspense
349+
pauseTracking()
344350
const setupResult = callWithErrorHandling(
345351
setup,
346352
instance,
347353
ErrorCodes.SETUP_FUNCTION,
348354
[propsProxy, setupContext]
349355
)
356+
resetTracking()
350357
currentInstance = null
351358
currentSuspense = null
352359

packages/runtime-core/src/warning.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { VNode } from './vnode'
22
import { Data, ComponentInternalInstance, Component } from './component'
33
import { isString, isFunction } from '@vue/shared'
4-
import { toRaw, isRef, pauseTracking, resumeTracking } from '@vue/reactivity'
4+
import { toRaw, isRef, pauseTracking, resetTracking } from '@vue/reactivity'
55
import { callWithErrorHandling, ErrorCodes } from './errorHandling'
66

77
type ComponentVNode = VNode & {
@@ -60,7 +60,7 @@ export function warn(msg: string, ...args: any[]) {
6060
console.warn(...warnArgs)
6161
}
6262

63-
resumeTracking()
63+
resetTracking()
6464
}
6565

6666
function getComponentTrace(): ComponentTraceStack {

0 commit comments

Comments
 (0)