From ddeeaa26d420e0fc7ffe67bda33c2f39568a8428 Mon Sep 17 00:00:00 2001 From: Evan You Date: Fri, 14 Oct 2022 10:53:23 +0800 Subject: [PATCH] fix(effectScope): calling off() of a detached scope should not break currentScope --- packages/reactivity/__tests__/effectScope.spec.ts | 11 +++++++++++ packages/reactivity/src/effectScope.ts | 7 ++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/packages/reactivity/__tests__/effectScope.spec.ts b/packages/reactivity/__tests__/effectScope.spec.ts index af92c97f94c..28579fef028 100644 --- a/packages/reactivity/__tests__/effectScope.spec.ts +++ b/packages/reactivity/__tests__/effectScope.spec.ts @@ -277,4 +277,15 @@ describe('reactivity/effect/scope', () => { expect(getCurrentScope()).toBe(currentScope) }) }) + + it('calling .off() of a detached scope inside an active scope should not break currentScope', () => { + const parentScope = new EffectScope() + + parentScope.run(() => { + const childScope = new EffectScope(true) + childScope.on() + childScope.off() + expect(getCurrentScope()).toBe(parentScope) + }) + }) }) diff --git a/packages/reactivity/src/effectScope.ts b/packages/reactivity/src/effectScope.ts index f4396e8f3ab..557a1379492 100644 --- a/packages/reactivity/src/effectScope.ts +++ b/packages/reactivity/src/effectScope.ts @@ -34,9 +34,9 @@ export class EffectScope { */ private index: number | undefined - constructor(detached = false) { + constructor(public detached = false) { + this.parent = activeEffectScope if (!detached && activeEffectScope) { - this.parent = activeEffectScope this.index = (activeEffectScope.scopes || (activeEffectScope.scopes = [])).push( this @@ -89,7 +89,7 @@ export class EffectScope { } } // nested scope, dereference from parent to avoid memory leaks - if (this.parent && !fromParent) { + if (!this.detached && this.parent && !fromParent) { // optimized O(1) removal const last = this.parent.scopes!.pop() if (last && last !== this) { @@ -97,6 +97,7 @@ export class EffectScope { last.index = this.index! } } + this.parent = undefined this.active = false } }