From 46c53932242b6393cf76c6dba3f42aa1d8692eab Mon Sep 17 00:00:00 2001 From: Evan You Date: Fri, 13 Dec 2019 23:06:55 -0500 Subject: [PATCH] perf(reactivity): optimize effect stack --- packages/reactivity/src/computed.ts | 11 +++++------ packages/reactivity/src/effect.ts | 20 +++++++++++--------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/packages/reactivity/src/computed.ts b/packages/reactivity/src/computed.ts index 2788f890..1f1d8ea4 100644 --- a/packages/reactivity/src/computed.ts +++ b/packages/reactivity/src/computed.ts @@ -1,4 +1,4 @@ -import { effect, ReactiveEffect, effectStack } from './effect' +import { effect, ReactiveEffect, activeEffect } from './effect' import { Ref, UnwrapRef } from './ref' import { isFunction, NOOP } from '@vue/shared' @@ -73,15 +73,14 @@ export function computed( } function trackChildRun(childRunner: ReactiveEffect) { - if (effectStack.length === 0) { + if (activeEffect === undefined) { return } - const parentRunner = effectStack[effectStack.length - 1] for (let i = 0; i < childRunner.deps.length; i++) { const dep = childRunner.deps[i] - if (!dep.has(parentRunner)) { - dep.add(parentRunner) - parentRunner.deps.push(dep) + if (!dep.has(activeEffect)) { + dep.add(activeEffect) + activeEffect.deps.push(dep) } } } diff --git a/packages/reactivity/src/effect.ts b/packages/reactivity/src/effect.ts index 6dbf99cd..46969d3c 100644 --- a/packages/reactivity/src/effect.ts +++ b/packages/reactivity/src/effect.ts @@ -40,7 +40,8 @@ export interface DebuggerEventExtraInfo { oldTarget?: Map | Set } -export const effectStack: ReactiveEffect[] = [] +const effectStack: ReactiveEffect[] = [] +export let activeEffect: ReactiveEffect | undefined export const ITERATE_KEY = Symbol('iterate') @@ -95,9 +96,11 @@ function run(effect: ReactiveEffect, fn: Function, args: unknown[]): unknown { cleanup(effect) try { effectStack.push(effect) + activeEffect = effect return fn(...args) } finally { effectStack.pop() + activeEffect = effectStack[effectStack.length - 1] } } } @@ -123,10 +126,9 @@ export function resumeTracking() { } export function track(target: object, type: TrackOpTypes, key: unknown) { - if (!shouldTrack || effectStack.length === 0) { + if (!shouldTrack || activeEffect === undefined) { return } - const effect = effectStack[effectStack.length - 1] let depsMap = targetMap.get(target) if (depsMap === void 0) { targetMap.set(target, (depsMap = new Map())) @@ -135,12 +137,12 @@ export function track(target: object, type: TrackOpTypes, key: unknown) { if (dep === void 0) { depsMap.set(key, (dep = new Set())) } - if (!dep.has(effect)) { - dep.add(effect) - effect.deps.push(dep) - if (__DEV__ && effect.options.onTrack) { - effect.options.onTrack({ - effect, + if (!dep.has(activeEffect)) { + dep.add(activeEffect) + activeEffect.deps.push(dep) + if (__DEV__ && activeEffect.options.onTrack) { + activeEffect.options.onTrack({ + effect: activeEffect, target, type, key