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)) {
|
||||
cleanup(effect)
|
||||
try {
|
||||
enableTracking()
|
||||
effectStack.push(effect)
|
||||
activeEffect = effect
|
||||
return fn(...args)
|
||||
} finally {
|
||||
effectStack.pop()
|
||||
resetTracking()
|
||||
activeEffect = effectStack[effectStack.length - 1]
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
|
@ -21,8 +21,11 @@ export {
|
||||
export {
|
||||
effect,
|
||||
stop,
|
||||
trigger,
|
||||
track,
|
||||
enableTracking,
|
||||
pauseTracking,
|
||||
resumeTracking,
|
||||
resetTracking,
|
||||
ITERATE_KEY,
|
||||
ReactiveEffect,
|
||||
ReactiveEffectOptions,
|
||||
|
@ -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'
|
||||
|
||||
@ -39,7 +39,7 @@ export function injectHook(
|
||||
setCurrentInstance(target)
|
||||
const res = callWithAsyncErrorHandling(hook, target, type, args)
|
||||
setCurrentInstance(null)
|
||||
resumeTracking()
|
||||
resetTracking()
|
||||
return res
|
||||
})
|
||||
if (prepend) {
|
||||
|
@ -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,
|
||||
@ -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
|
||||
|
||||
|
@ -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 & {
|
||||
@ -60,7 +60,7 @@ export function warn(msg: string, ...args: any[]) {
|
||||
console.warn(...warnArgs)
|
||||
}
|
||||
|
||||
resumeTracking()
|
||||
resetTracking()
|
||||
}
|
||||
|
||||
function getComponentTrace(): ComponentTraceStack {
|
||||
|
Loading…
Reference in New Issue
Block a user