From a901c60a1ee61fae820e78e76d04a6f545090345 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BD=A0=E6=89=8B=E6=8D=A7=E9=B2=9C=E8=8A=B1?= <157215725@qq.com> Date: Tue, 5 Apr 2022 16:56:57 +0800 Subject: [PATCH] refactor(effectScope): restore parent scope after detached scope run / off --- .../reactivity/__tests__/effectScope.spec.ts | 29 ++++++++++++++++++- packages/reactivity/src/effectScope.ts | 8 ++--- 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/packages/reactivity/__tests__/effectScope.spec.ts b/packages/reactivity/__tests__/effectScope.spec.ts index 3ce8affe78c..14e75575408 100644 --- a/packages/reactivity/__tests__/effectScope.spec.ts +++ b/packages/reactivity/__tests__/effectScope.spec.ts @@ -6,7 +6,8 @@ import { onScopeDispose, computed, ref, - ComputedRef + ComputedRef, + getCurrentScope } from '../src' describe('reactivity/effect/scope', () => { @@ -264,3 +265,29 @@ describe('reactivity/effect/scope', () => { expect(watchEffectSpy).toHaveBeenCalledTimes(2) }) }) + +it('getCurrentScope() stays valid when running a detached nested EffectScope', () => { + const parentScope = new EffectScope() + + parentScope.run(() => { + const currentScope = getCurrentScope() + expect(currentScope).toBeDefined() + const detachedScope = new EffectScope(true) + detachedScope.run(() => {}) + + expect(getCurrentScope()).toBe(currentScope) + }) +}) + +it('getCurrentScope() stays valid when offed a detached nested EffectScope', () => { + const parentScope = new EffectScope() + + parentScope.run(() => { + const currentScope = getCurrentScope() + expect(currentScope).toBeDefined() + const detachedScope = new EffectScope(true) + detachedScope.off() + + expect(getCurrentScope()).toBe(currentScope) + }) +}) \ No newline at end of file diff --git a/packages/reactivity/src/effectScope.ts b/packages/reactivity/src/effectScope.ts index fcacab6e381..1b307369d25 100644 --- a/packages/reactivity/src/effectScope.ts +++ b/packages/reactivity/src/effectScope.ts @@ -17,8 +17,8 @@ export class EffectScope { private index: number | undefined constructor(detached = false) { + this.parent = activeEffectScope if (!detached && activeEffectScope) { - this.parent = activeEffectScope this.index = (activeEffectScope.scopes || (activeEffectScope.scopes = [])).push( this @@ -62,12 +62,12 @@ export class EffectScope { } } // nested scope, dereference from parent to avoid memory leaks - if (this.parent && !fromParent) { + if (this.index !== undefined && this.parent && !fromParent) { // optimized O(1) removal const last = this.parent.scopes!.pop() if (last && last !== this) { - this.parent.scopes![this.index!] = last - last.index = this.index! + this.parent.scopes![this.index] = last + last.index = this.index } } this.active = false