From 043eb35be6baf3d3f512b6634b56b25f86d19d7a Mon Sep 17 00:00:00 2001 From: daiwei Date: Fri, 3 Jan 2025 09:17:19 +0800 Subject: [PATCH 1/3] feat(effectScope): allow multiple calls by tracking call count --- .../reactivity/__tests__/effectScope.spec.ts | 13 +++++++++++++ packages/reactivity/src/effectScope.ts | 16 +++++++++++++--- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/packages/reactivity/__tests__/effectScope.spec.ts b/packages/reactivity/__tests__/effectScope.spec.ts index debbdafb1e7..84310b985f2 100644 --- a/packages/reactivity/__tests__/effectScope.spec.ts +++ b/packages/reactivity/__tests__/effectScope.spec.ts @@ -296,6 +296,19 @@ describe('reactivity/effect/scope', () => { }) }) + it('calling on() and off() multiple times inside an active scope should not break currentScope', () => { + const parentScope = effectScope() + parentScope.run(() => { + const childScope = effectScope(true) + childScope.on() + childScope.on() + childScope.off() + childScope.off() + childScope.off() + expect(getCurrentScope()).toBe(parentScope) + }) + }) + it('should pause/resume EffectScope', async () => { const counter = reactive({ num: 0 }) const fnSpy = vi.fn(() => counter.num) diff --git a/packages/reactivity/src/effectScope.ts b/packages/reactivity/src/effectScope.ts index 80f42db6484..cca0b113149 100644 --- a/packages/reactivity/src/effectScope.ts +++ b/packages/reactivity/src/effectScope.ts @@ -8,6 +8,10 @@ export class EffectScope { * @internal */ private _active = true + /** + * @internal track `on` calls, allow `on` call multiple times + */ + private _onCallCount = 0 /** * @internal */ @@ -105,8 +109,11 @@ export class EffectScope { * @internal */ on(): void { - this.prevScope = activeEffectScope - activeEffectScope = this + this._onCallCount++ + if (this._onCallCount === 1) { + this.prevScope = activeEffectScope + activeEffectScope = this + } } /** @@ -114,7 +121,10 @@ export class EffectScope { * @internal */ off(): void { - activeEffectScope = this.prevScope + this._onCallCount = Math.max(0, this._onCallCount - 1) + if (this._onCallCount === 0) { + activeEffectScope = this.prevScope + } } stop(fromParent?: boolean): void { From d92c37a8ec5be193283516533617ad5241cd596d Mon Sep 17 00:00:00 2001 From: Evan You Date: Wed, 8 Jan 2025 18:00:49 +0800 Subject: [PATCH 2/3] refactor: simplify implementation --- packages/reactivity/src/effectScope.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/packages/reactivity/src/effectScope.ts b/packages/reactivity/src/effectScope.ts index cca0b113149..4079e2a9d61 100644 --- a/packages/reactivity/src/effectScope.ts +++ b/packages/reactivity/src/effectScope.ts @@ -11,7 +11,7 @@ export class EffectScope { /** * @internal track `on` calls, allow `on` call multiple times */ - private _onCallCount = 0 + private _on = 0 /** * @internal */ @@ -109,8 +109,7 @@ export class EffectScope { * @internal */ on(): void { - this._onCallCount++ - if (this._onCallCount === 1) { + if (++this._on === 1) { this.prevScope = activeEffectScope activeEffectScope = this } @@ -121,8 +120,7 @@ export class EffectScope { * @internal */ off(): void { - this._onCallCount = Math.max(0, this._onCallCount - 1) - if (this._onCallCount === 0) { + if (this._on > 0 && --this._on === 0) { activeEffectScope = this.prevScope } } From 499af49d51214b86626927c328873bab787c7006 Mon Sep 17 00:00:00 2001 From: Evan You Date: Wed, 8 Jan 2025 18:02:11 +0800 Subject: [PATCH 3/3] chore: also unset prevScope on off --- packages/reactivity/src/effectScope.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/reactivity/src/effectScope.ts b/packages/reactivity/src/effectScope.ts index 4079e2a9d61..9ca24c08857 100644 --- a/packages/reactivity/src/effectScope.ts +++ b/packages/reactivity/src/effectScope.ts @@ -122,6 +122,7 @@ export class EffectScope { off(): void { if (this._on > 0 && --this._on === 0) { activeEffectScope = this.prevScope + this.prevScope = undefined } }