fix(reactivity): avoid cross-component dependency leaks in setup()
This commit is contained in:
parent
202532c301
commit
d9d63f21b1
@ -95,11 +95,13 @@ function run(effect: ReactiveEffect, fn: Function, args: unknown[]): unknown {
|
|||||||
if (!effectStack.includes(effect)) {
|
if (!effectStack.includes(effect)) {
|
||||||
cleanup(effect)
|
cleanup(effect)
|
||||||
try {
|
try {
|
||||||
|
enableTracking()
|
||||||
effectStack.push(effect)
|
effectStack.push(effect)
|
||||||
activeEffect = effect
|
activeEffect = effect
|
||||||
return fn(...args)
|
return fn(...args)
|
||||||
} finally {
|
} finally {
|
||||||
effectStack.pop()
|
effectStack.pop()
|
||||||
|
resetTracking()
|
||||||
activeEffect = effectStack[effectStack.length - 1]
|
activeEffect = effectStack[effectStack.length - 1]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -116,15 +118,23 @@ function cleanup(effect: ReactiveEffect) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let shouldTrack = true
|
let shouldTrack = true
|
||||||
|
const trackStack: boolean[] = []
|
||||||
|
|
||||||
export function pauseTracking() {
|
export function pauseTracking() {
|
||||||
|
trackStack.push(shouldTrack)
|
||||||
shouldTrack = false
|
shouldTrack = false
|
||||||
}
|
}
|
||||||
|
|
||||||
export function resumeTracking() {
|
export function enableTracking() {
|
||||||
|
trackStack.push(shouldTrack)
|
||||||
shouldTrack = true
|
shouldTrack = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function resetTracking() {
|
||||||
|
const last = trackStack.pop()
|
||||||
|
shouldTrack = last === undefined ? true : last
|
||||||
|
}
|
||||||
|
|
||||||
export function track(target: object, type: TrackOpTypes, key: unknown) {
|
export function track(target: object, type: TrackOpTypes, key: unknown) {
|
||||||
if (!shouldTrack || activeEffect === undefined) {
|
if (!shouldTrack || activeEffect === undefined) {
|
||||||
return
|
return
|
||||||
|
@ -21,8 +21,11 @@ export {
|
|||||||
export {
|
export {
|
||||||
effect,
|
effect,
|
||||||
stop,
|
stop,
|
||||||
|
trigger,
|
||||||
|
track,
|
||||||
|
enableTracking,
|
||||||
pauseTracking,
|
pauseTracking,
|
||||||
resumeTracking,
|
resetTracking,
|
||||||
ITERATE_KEY,
|
ITERATE_KEY,
|
||||||
ReactiveEffect,
|
ReactiveEffect,
|
||||||
ReactiveEffectOptions,
|
ReactiveEffectOptions,
|
||||||
|
@ -9,7 +9,7 @@ import { ComponentPublicInstance } from './componentProxy'
|
|||||||
import { callWithAsyncErrorHandling, ErrorTypeStrings } from './errorHandling'
|
import { callWithAsyncErrorHandling, ErrorTypeStrings } from './errorHandling'
|
||||||
import { warn } from './warning'
|
import { warn } from './warning'
|
||||||
import { capitalize } from '@vue/shared'
|
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'
|
export { onActivated, onDeactivated } from './components/KeepAlive'
|
||||||
|
|
||||||
@ -39,7 +39,7 @@ export function injectHook(
|
|||||||
setCurrentInstance(target)
|
setCurrentInstance(target)
|
||||||
const res = callWithAsyncErrorHandling(hook, target, type, args)
|
const res = callWithAsyncErrorHandling(hook, target, type, args)
|
||||||
setCurrentInstance(null)
|
setCurrentInstance(null)
|
||||||
resumeTracking()
|
resetTracking()
|
||||||
return res
|
return res
|
||||||
})
|
})
|
||||||
if (prepend) {
|
if (prepend) {
|
||||||
|
@ -1,5 +1,10 @@
|
|||||||
import { VNode, VNodeChild, isVNode } from './vnode'
|
import { VNode, VNodeChild, isVNode } from './vnode'
|
||||||
import { ReactiveEffect, shallowReadonly } from '@vue/reactivity'
|
import {
|
||||||
|
ReactiveEffect,
|
||||||
|
shallowReadonly,
|
||||||
|
pauseTracking,
|
||||||
|
resetTracking
|
||||||
|
} from '@vue/reactivity'
|
||||||
import {
|
import {
|
||||||
PublicInstanceProxyHandlers,
|
PublicInstanceProxyHandlers,
|
||||||
ComponentPublicInstance,
|
ComponentPublicInstance,
|
||||||
@ -341,12 +346,14 @@ function setupStatefulComponent(
|
|||||||
|
|
||||||
currentInstance = instance
|
currentInstance = instance
|
||||||
currentSuspense = parentSuspense
|
currentSuspense = parentSuspense
|
||||||
|
pauseTracking()
|
||||||
const setupResult = callWithErrorHandling(
|
const setupResult = callWithErrorHandling(
|
||||||
setup,
|
setup,
|
||||||
instance,
|
instance,
|
||||||
ErrorCodes.SETUP_FUNCTION,
|
ErrorCodes.SETUP_FUNCTION,
|
||||||
[propsProxy, setupContext]
|
[propsProxy, setupContext]
|
||||||
)
|
)
|
||||||
|
resetTracking()
|
||||||
currentInstance = null
|
currentInstance = null
|
||||||
currentSuspense = null
|
currentSuspense = null
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { VNode } from './vnode'
|
import { VNode } from './vnode'
|
||||||
import { Data, ComponentInternalInstance, Component } from './component'
|
import { Data, ComponentInternalInstance, Component } from './component'
|
||||||
import { isString, isFunction } from '@vue/shared'
|
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'
|
import { callWithErrorHandling, ErrorCodes } from './errorHandling'
|
||||||
|
|
||||||
type ComponentVNode = VNode & {
|
type ComponentVNode = VNode & {
|
||||||
@ -60,7 +60,7 @@ export function warn(msg: string, ...args: any[]) {
|
|||||||
console.warn(...warnArgs)
|
console.warn(...warnArgs)
|
||||||
}
|
}
|
||||||
|
|
||||||
resumeTracking()
|
resetTracking()
|
||||||
}
|
}
|
||||||
|
|
||||||
function getComponentTrace(): ComponentTraceStack {
|
function getComponentTrace(): ComponentTraceStack {
|
||||||
|
Loading…
Reference in New Issue
Block a user