From 960706eebf73f08ebc9d5dd853a05def05e2c153 Mon Sep 17 00:00:00 2001 From: Evan You Date: Fri, 20 Sep 2024 23:39:33 +0800 Subject: [PATCH] fix(reactivity): do not remove dep from depsMap when unsubbed by computed follow up of 235ea4772 after discovering regression in vant ecosystem-ci tests --- .../reactivity/__tests__/computed.spec.ts | 20 ++++++++++++++++++- packages/reactivity/src/effect.ts | 6 +++--- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/packages/reactivity/__tests__/computed.spec.ts b/packages/reactivity/__tests__/computed.spec.ts index 543c9c6e770..90987e86720 100644 --- a/packages/reactivity/__tests__/computed.spec.ts +++ b/packages/reactivity/__tests__/computed.spec.ts @@ -1006,9 +1006,27 @@ describe('reactivity/computed', () => { expect(serializeInner(root)).toBe(`

Step 2

`) }) - it('manual trigger computed', () => { + test('manual trigger computed', () => { const cValue = computed(() => 1) triggerRef(cValue) expect(cValue.value).toBe(1) }) + + test('computed should remain live after losing all subscribers', () => { + const toggle = ref(true) + const state = reactive({ + a: 1, + }) + const p = computed(() => state.a + 1) + const pp = computed(() => { + return toggle.value ? p.value : 111 + }) + + const { effect: e } = effect(() => pp.value) + e.stop() + + expect(p.value).toBe(2) + state.a++ + expect(p.value).toBe(3) + }) }) diff --git a/packages/reactivity/src/effect.ts b/packages/reactivity/src/effect.ts index 4428b8df256..d0b7c7bd9fb 100644 --- a/packages/reactivity/src/effect.ts +++ b/packages/reactivity/src/effect.ts @@ -399,7 +399,7 @@ export function refreshComputed(computed: ComputedRefImpl): undefined { } } -function removeSub(link: Link) { +function removeSub(link: Link, fromComputed = false) { const { dep, prevSub, nextSub } = link if (prevSub) { prevSub.nextSub = nextSub @@ -425,9 +425,9 @@ function removeSub(link: Link) { // value can be GCed dep.computed.flags &= ~EffectFlags.TRACKING for (let l = dep.computed.deps; l; l = l.nextDep) { - removeSub(l) + removeSub(l, true) } - } else if (dep.map) { + } else if (dep.map && !fromComputed) { // property dep, remove it from the owner depsMap dep.map.delete(dep.key) if (!dep.map.size) targetMap.delete(dep.target!)