diff --git a/packages/reactivity/src/debug.ts b/packages/reactivity/src/debug.ts index 9963777fd17..41908a0d124 100644 --- a/packages/reactivity/src/debug.ts +++ b/packages/reactivity/src/debug.ts @@ -1,6 +1,6 @@ import { extend } from '@vue/shared' import type { DebuggerEventExtraInfo, ReactiveEffectOptions } from './effect' -import type { Link, Subscriber } from './system' +import { type Link, type Subscriber, SubscriberFlags } from './system' export const triggerEventInfos: DebuggerEventExtraInfo[] = [] @@ -58,8 +58,11 @@ export function setupFlagsHandler(target: Subscriber): void { return target._flags }, set(value) { - // @ts-expect-error - if (!(target._flags >> 2) && !!(value >> 2)) { + if ( + // @ts-expect-error + !(target._flags >> SubscriberFlags.DirtyFlagsIndex) && + !!(value >> SubscriberFlags.DirtyFlagsIndex) + ) { onTrigger(this) } // @ts-expect-error diff --git a/packages/reactivity/src/effect.ts b/packages/reactivity/src/effect.ts index 1ef15eee52f..6ad693c26c6 100644 --- a/packages/reactivity/src/effect.ts +++ b/packages/reactivity/src/effect.ts @@ -13,6 +13,10 @@ import { } from './system' import { warn } from './warning' +export enum EffectFlags { + ALLOW_RECURSE = 1 << 2, +} + export type EffectScheduler = (...args: any[]) => any export type DebuggerEvent = { @@ -35,7 +39,6 @@ export interface DebuggerOptions { export interface ReactiveEffectOptions extends DebuggerOptions { scheduler?: EffectScheduler - allowRecurse?: boolean onStop?: () => void } @@ -57,10 +60,9 @@ export class ReactiveEffect implements IEffect, ReactiveEffectOptions { // Subscriber deps: Link | undefined = undefined depsTail: Link | undefined = undefined - flags: SubscriberFlags = SubscriberFlags.Dirty + flags: number = SubscriberFlags.Dirty pauseLevel: PauseLevels = PauseLevels.None - allowRecurse = false /** * @internal @@ -139,7 +141,10 @@ export class ReactiveEffect implements IEffect, ReactiveEffectOptions { } setActiveSub(prevSub, prevTrackId) endTrack(this) - if (this.allowRecurse && this.flags & SubscriberFlags.CanPropagate) { + if ( + this.flags & SubscriberFlags.CanPropagate && + this.flags & EffectFlags.ALLOW_RECURSE + ) { this.flags &= ~SubscriberFlags.CanPropagate this.notify() } diff --git a/packages/reactivity/src/index.ts b/packages/reactivity/src/index.ts index d335c27c122..f0445e87da0 100644 --- a/packages/reactivity/src/index.ts +++ b/packages/reactivity/src/index.ts @@ -57,6 +57,7 @@ export { resetTracking, onEffectCleanup, ReactiveEffect, + EffectFlags, type ReactiveEffectRunner, type ReactiveEffectOptions, type EffectScheduler, diff --git a/packages/reactivity/src/system.ts b/packages/reactivity/src/system.ts index 7841fa689d4..69c1bb20157 100644 --- a/packages/reactivity/src/system.ts +++ b/packages/reactivity/src/system.ts @@ -42,6 +42,11 @@ export enum SubscriberFlags { ToCheckDirty = 1 << 3, Dirty = 1 << 4, Dirtys = SubscriberFlags.ToCheckDirty | SubscriberFlags.Dirty, + All = SubscriberFlags.Tracking | + SubscriberFlags.CanPropagate | + SubscriberFlags.Dirtys, + + DirtyFlagsIndex = 3, } let batchDepth = 0 @@ -141,7 +146,7 @@ export function propagate(subs: Link): void { const subFlags = sub.flags if (!(subFlags & SubscriberFlags.Tracking)) { - let canPropagate = !(subFlags >> 2) + let canPropagate = !(subFlags >> SubscriberFlags.DirtyFlagsIndex) if (!canPropagate && subFlags & SubscriberFlags.CanPropagate) { sub.flags &= ~SubscriberFlags.CanPropagate canPropagate = true @@ -171,7 +176,7 @@ export function propagate(subs: Link): void { sub.flags |= targetFlag } } else if (isValidLink(link, sub)) { - if (!(subFlags >> 2)) { + if (!(subFlags >> SubscriberFlags.DirtyFlagsIndex)) { sub.flags |= targetFlag | SubscriberFlags.CanPropagate const subSubs = (sub as Dependency).subs if (subSubs !== undefined) { @@ -293,7 +298,7 @@ export function checkDirty(deps: Link): boolean { export function startTrack(sub: Subscriber): void { sub.depsTail = undefined - sub.flags = SubscriberFlags.Tracking + sub.flags = (sub.flags & ~SubscriberFlags.All) | SubscriberFlags.Tracking } export function endTrack(sub: Subscriber): void { @@ -343,7 +348,7 @@ function clearTrack(link: Link): void { if (dep.subs === undefined && 'deps' in dep) { if ('notify' in dep) { - dep.flags = SubscriberFlags.None + dep.flags &= ~SubscriberFlags.Dirtys } else { dep.flags |= SubscriberFlags.Dirty } diff --git a/packages/runtime-core/src/renderer.ts b/packages/runtime-core/src/renderer.ts index 5e38888c09e..55492a1bd5b 100644 --- a/packages/runtime-core/src/renderer.ts +++ b/packages/runtime-core/src/renderer.ts @@ -48,7 +48,12 @@ import { queueJob, queuePostFlushCb, } from './scheduler' -import { ReactiveEffect, pauseTracking, resetTracking } from '@vue/reactivity' +import { + EffectFlags, + ReactiveEffect, + pauseTracking, + resetTracking, +} from '@vue/reactivity' import { updateProps } from './componentProps' import { updateSlots } from './componentSlots' import { popWarningContext, pushWarningContext, warn } from './warning' @@ -2419,10 +2424,10 @@ function toggleRecurse( allowed: boolean, ) { if (allowed) { - effect.allowRecurse = true + effect.flags |= EffectFlags.ALLOW_RECURSE job.flags! |= SchedulerJobFlags.ALLOW_RECURSE } else { - effect.allowRecurse = false + effect.flags &= ~EffectFlags.ALLOW_RECURSE job.flags! &= ~SchedulerJobFlags.ALLOW_RECURSE } }