diff --git a/lib/effectScope.ts b/lib/effectScope.ts index 9341110..831f079 100644 --- a/lib/effectScope.ts +++ b/lib/effectScope.ts @@ -1,4 +1,4 @@ -import { DirtyLevels, IEffect, Link, Subscriber } from './system.js'; +import { DirtyLevels, IEffect, Subscriber } from './system.js'; export function effectScope() { return new EffectScope(); @@ -28,9 +28,9 @@ export class EffectScope implements IEffect, Subscriber { stop() { if (this.deps !== undefined) { - Link.releaseDeps(this.deps); - Link.release(this.deps); + Subscriber.clearTrack(this.deps); this.deps = undefined; + this.depsTail = undefined; } this.versionOrDirtyLevel = DirtyLevels.None; } diff --git a/lib/system.ts b/lib/system.ts index c485f46..2db7dab 100644 --- a/lib/system.ts +++ b/lib/system.ts @@ -73,7 +73,7 @@ export namespace System { export namespace Link { - let pool: Link | undefined = undefined; + export let pool: Link | undefined = undefined; export function get(dep: Dependency, sub: Subscriber): Link { if (pool !== undefined) { @@ -94,57 +94,6 @@ export namespace Link { }; } } - - export function releaseDeps(toBreak: Link) { - let nextDep = toBreak.nextDep; - while (nextDep !== undefined) { - toBreak.nextDep = undefined; - const nextNext = nextDep.nextDep; - Link.release(nextDep); - toBreak = nextDep; - nextDep = nextNext; - } - } - - export function release(link: Link) { - const dep = link.dep as Dependency & ({} | Subscriber); - const nextSub = link.nextSub; - const prevSub = link.prevSubOrUpdate; - - if (nextSub !== undefined) { - nextSub.prevSubOrUpdate = prevSub; - } - if (prevSub !== undefined) { - prevSub.nextSub = nextSub; - } - - if (nextSub === undefined) { - link.dep.subsTail = prevSub; - } - if (prevSub === undefined) { - link.dep.subs = nextSub; - } - - // @ts-ignore - link.dep = undefined; - // @ts-ignore - link.sub = undefined; - link.prevSubOrUpdate = undefined; - link.nextSub = undefined; - link.nextDep = undefined; - - link.queuedPropagateOrNextReleased = pool; - pool = link; - - if (dep.subs === undefined && 'deps' in dep) { - if (dep.deps !== undefined) { - Link.releaseDeps(dep.deps); - Link.release(dep.deps); - dep.deps = undefined; - } - dep.versionOrDirtyLevel = DirtyLevels.Released; - } - } } export namespace Dependency { @@ -466,16 +415,65 @@ export namespace Subscriber { system.activeDepsSubsDepth--; system.activeDepsSub = prevSub; - if (sub.depsTail !== undefined) { - Link.releaseDeps(sub.depsTail); + const depsTail = sub.depsTail; + if (depsTail !== undefined) { + if (depsTail.nextDep !== undefined) { + clearTrack(depsTail.nextDep); + depsTail.nextDep = undefined; + } } else if (sub.deps !== undefined) { - Link.releaseDeps(sub.deps); - Link.release(sub.deps); + clearTrack(sub.deps); sub.deps = undefined; } sub.versionOrDirtyLevel = DirtyLevels.None; } + export function clearTrack(link: Link | undefined) { + while (link !== undefined) { + + const nextDep = link.nextDep; + const dep = link.dep as Dependency & Subscriber; + const nextSub = link.nextSub; + const prevSub = link.prevSubOrUpdate; + + if (nextSub !== undefined) { + nextSub.prevSubOrUpdate = prevSub; + } + if (prevSub !== undefined) { + prevSub.nextSub = nextSub; + } + + if (nextSub === undefined) { + link.dep.subsTail = prevSub; + } + if (prevSub === undefined) { + link.dep.subs = nextSub; + } + + // @ts-ignore + link.dep = undefined; + // @ts-ignore + link.sub = undefined; + link.prevSubOrUpdate = undefined; + link.nextSub = undefined; + link.nextDep = undefined; + + link.queuedPropagateOrNextReleased = Link.pool; + Link.pool = link; + + if (dep.subs === undefined && dep.deps !== undefined) { + link = dep.deps; + dep.depsTail!.nextDep = nextDep; + dep.deps = undefined; + dep.depsTail = undefined; + dep.versionOrDirtyLevel = DirtyLevels.Released; + continue; + } + + link = nextDep; + } + } + export function startTrackEffects(sub: Subscriber) { const prevSub = system.activeEffectsSub; system.activeEffectsSub = sub; @@ -491,11 +489,14 @@ export namespace Subscriber { system.activeEffectsSubsDepth--; system.activeEffectsSub = prevSub; - if (sub.depsTail !== undefined) { - Link.releaseDeps(sub.depsTail); + const depsTail = sub.depsTail; + if (depsTail !== undefined) { + if (depsTail.nextDep !== undefined) { + clearTrack(depsTail.nextDep); + depsTail.nextDep = undefined; + } } else if (sub.deps !== undefined) { - Link.releaseDeps(sub.deps); - Link.release(sub.deps); + clearTrack(sub.deps); sub.deps = undefined; } sub.versionOrDirtyLevel = DirtyLevels.None; diff --git a/unstable/vue.ts b/unstable/vue.ts index 4c1dea0..482df5b 100644 --- a/unstable/vue.ts +++ b/unstable/vue.ts @@ -4,7 +4,6 @@ import { DirtyLevels, Effect, EffectScope, - Link, Signal, Subscriber, System, @@ -99,9 +98,9 @@ export class ReactiveEffect extends Effect { stop() { if (this.deps !== undefined) { - Link.releaseDeps(this.deps); - Link.release(this.deps); + Subscriber.clearTrack(this.deps); this.deps = undefined; + this.depsTail = undefined; } this.versionOrDirtyLevel = DirtyLevels.None; }