Skip to content

Commit

Permalink
fix(reactivity): avoid cross-component dependency leaks in setup()
Browse files Browse the repository at this point in the history
  • Loading branch information
yyx990803 committed Feb 18, 2020
1 parent 202532c commit d9d63f2
Show file tree
Hide file tree
Showing 5 changed files with 27 additions and 7 deletions.
12 changes: 11 additions & 1 deletion packages/reactivity/src/effect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,11 +95,13 @@ function run(effect: ReactiveEffect, fn: Function, args: unknown[]): unknown {
if (!effectStack.includes(effect)) {
cleanup(effect)
try {
enableTracking()
effectStack.push(effect)
activeEffect = effect
return fn(...args)
} finally {
effectStack.pop()
resetTracking()
activeEffect = effectStack[effectStack.length - 1]
}
}
Expand All @@ -116,15 +118,23 @@ function cleanup(effect: ReactiveEffect) {
}

let shouldTrack = true
const trackStack: boolean[] = []

export function pauseTracking() {
trackStack.push(shouldTrack)
shouldTrack = false
}

export function resumeTracking() {
export function enableTracking() {
trackStack.push(shouldTrack)
shouldTrack = true
}

export function resetTracking() {
const last = trackStack.pop()
shouldTrack = last === undefined ? true : last
}

export function track(target: object, type: TrackOpTypes, key: unknown) {
if (!shouldTrack || activeEffect === undefined) {
return
Expand Down
5 changes: 4 additions & 1 deletion packages/reactivity/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,11 @@ export {
export {
effect,
stop,
trigger,
track,
enableTracking,
pauseTracking,
resumeTracking,
resetTracking,
ITERATE_KEY,
ReactiveEffect,
ReactiveEffectOptions,
Expand Down
4 changes: 2 additions & 2 deletions packages/runtime-core/src/apiLifecycle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { ComponentPublicInstance } from './componentProxy'
import { callWithAsyncErrorHandling, ErrorTypeStrings } from './errorHandling'
import { warn } from './warning'
import { capitalize } from '@vue/shared'
import { pauseTracking, resumeTracking, DebuggerEvent } from '@vue/reactivity'
import { pauseTracking, resetTracking, DebuggerEvent } from '@vue/reactivity'

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

Expand Down Expand Up @@ -39,7 +39,7 @@ export function injectHook(
setCurrentInstance(target)
const res = callWithAsyncErrorHandling(hook, target, type, args)
setCurrentInstance(null)
resumeTracking()
resetTracking()
return res
})
if (prepend) {
Expand Down
9 changes: 8 additions & 1 deletion packages/runtime-core/src/component.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import { VNode, VNodeChild, isVNode } from './vnode'
import { ReactiveEffect, shallowReadonly } from '@vue/reactivity'
import {
ReactiveEffect,
shallowReadonly,
pauseTracking,
resetTracking
} from '@vue/reactivity'
import {
PublicInstanceProxyHandlers,
ComponentPublicInstance,
Expand Down Expand Up @@ -341,12 +346,14 @@ function setupStatefulComponent(

currentInstance = instance
currentSuspense = parentSuspense
pauseTracking()
const setupResult = callWithErrorHandling(
setup,
instance,
ErrorCodes.SETUP_FUNCTION,
[propsProxy, setupContext]
)
resetTracking()
currentInstance = null
currentSuspense = null

Expand Down
4 changes: 2 additions & 2 deletions packages/runtime-core/src/warning.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { VNode } from './vnode'
import { Data, ComponentInternalInstance, Component } from './component'
import { isString, isFunction } from '@vue/shared'
import { toRaw, isRef, pauseTracking, resumeTracking } from '@vue/reactivity'
import { toRaw, isRef, pauseTracking, resetTracking } from '@vue/reactivity'
import { callWithErrorHandling, ErrorCodes } from './errorHandling'

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

resumeTracking()
resetTracking()
}

function getComponentTrace(): ComponentTraceStack {
Expand Down

0 comments on commit d9d63f2

Please sign in to comment.