Skip to content

Commit 679cbdf

Browse files
authored
fix(reactivity): ensure multiple effectScope on() and off() calls maintains correct active scope (#12641)
1 parent 20cd429 commit 679cbdf

File tree

2 files changed

+25
-3
lines changed

2 files changed

+25
-3
lines changed

packages/reactivity/__tests__/effectScope.spec.ts

+13
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,19 @@ describe('reactivity/effect/scope', () => {
296296
})
297297
})
298298

299+
it('calling on() and off() multiple times inside an active scope should not break currentScope', () => {
300+
const parentScope = effectScope()
301+
parentScope.run(() => {
302+
const childScope = effectScope(true)
303+
childScope.on()
304+
childScope.on()
305+
childScope.off()
306+
childScope.off()
307+
childScope.off()
308+
expect(getCurrentScope()).toBe(parentScope)
309+
})
310+
})
311+
299312
it('should pause/resume EffectScope', async () => {
300313
const counter = reactive({ num: 0 })
301314
const fnSpy = vi.fn(() => counter.num)

packages/reactivity/src/effectScope.ts

+12-3
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ export class EffectScope {
88
* @internal
99
*/
1010
private _active = true
11+
/**
12+
* @internal track `on` calls, allow `on` call multiple times
13+
*/
14+
private _on = 0
1115
/**
1216
* @internal
1317
*/
@@ -105,16 +109,21 @@ export class EffectScope {
105109
* @internal
106110
*/
107111
on(): void {
108-
this.prevScope = activeEffectScope
109-
activeEffectScope = this
112+
if (++this._on === 1) {
113+
this.prevScope = activeEffectScope
114+
activeEffectScope = this
115+
}
110116
}
111117

112118
/**
113119
* This should only be called on non-detached scopes
114120
* @internal
115121
*/
116122
off(): void {
117-
activeEffectScope = this.prevScope
123+
if (this._on > 0 && --this._on === 0) {
124+
activeEffectScope = this.prevScope
125+
this.prevScope = undefined
126+
}
118127
}
119128

120129
stop(fromParent?: boolean): void {

0 commit comments

Comments
 (0)