From: edison Date: Wed, 8 Jan 2025 10:03:40 +0000 (+0800) Subject: fix(reactivity): ensure multiple effectScope `on()` and `off()` calls maintains corre... X-Git-Tag: v3.6.0-alpha.1~16^2~138 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=679cbdf4806cf8c325098f2b579abab60fffb1bb;p=thirdparty%2Fvuejs%2Fcore.git fix(reactivity): ensure multiple effectScope `on()` and `off()` calls maintains correct active scope (#12641) --- diff --git a/packages/reactivity/__tests__/effectScope.spec.ts b/packages/reactivity/__tests__/effectScope.spec.ts index debbdafb1e..84310b985f 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 80f42db648..9ca24c0885 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 _on = 0 /** * @internal */ @@ -105,8 +109,10 @@ export class EffectScope { * @internal */ on(): void { - this.prevScope = activeEffectScope - activeEffectScope = this + if (++this._on === 1) { + this.prevScope = activeEffectScope + activeEffectScope = this + } } /** @@ -114,7 +120,10 @@ export class EffectScope { * @internal */ off(): void { - activeEffectScope = this.prevScope + if (this._on > 0 && --this._on === 0) { + activeEffectScope = this.prevScope + this.prevScope = undefined + } } stop(fromParent?: boolean): void {