From 0a301d4dabd667526cbcd96e88b50741b519a812 Mon Sep 17 00:00:00 2001 From: Wei Date: Tue, 12 Apr 2022 15:51:05 +0800 Subject: [PATCH] fix(reactivity): fix currentScope loss when running detached effect scope (#5575) --- .../reactivity/__tests__/effectScope.spec.ts | 16 +++++++++++++++- packages/reactivity/src/effectScope.ts | 9 ++++++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/packages/reactivity/__tests__/effectScope.spec.ts b/packages/reactivity/__tests__/effectScope.spec.ts index 3ce8affe..6adda3d8 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', () => { @@ -263,4 +264,17 @@ describe('reactivity/effect/scope', () => { expect(watchSpy).toHaveBeenCalledTimes(1) 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) + }) + }) }) diff --git a/packages/reactivity/src/effectScope.ts b/packages/reactivity/src/effectScope.ts index fcacab6e..01499c5a 100644 --- a/packages/reactivity/src/effectScope.ts +++ b/packages/reactivity/src/effectScope.ts @@ -8,7 +8,13 @@ export class EffectScope { effects: ReactiveEffect[] = [] cleanups: (() => void)[] = [] + /** + * only assinged by undetached scope + */ parent: EffectScope | undefined + /** + * record undetached scopes + */ scopes: EffectScope[] | undefined /** * track a child scope's index in its parent's scopes array for optimized @@ -28,11 +34,12 @@ export class EffectScope { run(fn: () => T): T | undefined { if (this.active) { + const currentEffectScope = activeEffectScope try { activeEffectScope = this return fn() } finally { - activeEffectScope = this.parent + activeEffectScope = currentEffectScope } } else if (__DEV__) { warn(`cannot run an inactive effect scope.`)