Skip to content

Commit

Permalink
fix(reactivity): ensure multiple effectScope on() and off() calls mai…
Browse files Browse the repository at this point in the history
…ntains correct active scope

close #12631
close #12632

This is a combination of changes from both 8dec243 and #12641
  • Loading branch information
yyx990803 committed Jan 8, 2025
1 parent e8e8422 commit 22dcbf3
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 2 deletions.
15 changes: 13 additions & 2 deletions packages/reactivity/src/effectScope.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ export class EffectScope {
* @internal
*/
private _active = true
/**
* @internal track `on` calls, allow `on` call multiple times
*/
private _on = 0
/**
* @internal
*/
Expand Down Expand Up @@ -99,20 +103,27 @@ export class EffectScope {
}
}

prevScope: EffectScope | undefined
/**
* This should only be called on non-detached scopes
* @internal
*/
on(): void {
activeEffectScope = this
if (++this._on === 1) {
this.prevScope = activeEffectScope
activeEffectScope = this
}
}

/**
* This should only be called on non-detached scopes
* @internal
*/
off(): void {
activeEffectScope = this.parent
if (this._on > 0 && --this._on === 0) {
activeEffectScope = this.prevScope
this.prevScope = undefined
}
}

stop(fromParent?: boolean): void {
Expand Down
28 changes: 28 additions & 0 deletions packages/runtime-core/__tests__/apiWatch.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import {
TrackOpTypes,
TriggerOpTypes,
effectScope,
onScopeDispose,
shallowReactive,
shallowRef,
toRef,
Expand Down Expand Up @@ -1982,4 +1983,31 @@ describe('api: watch', () => {
expect(spy1).toHaveBeenCalled()
expect(spy2).toHaveBeenCalled()
})

// #12631
test('this.$watch w/ onScopeDispose', () => {
const onCleanup = vi.fn()
const toggle = ref(true)

const Comp = defineComponent({
render() {},
created(this: any) {
this.$watch(
() => 1,
function () {},
)
onScopeDispose(onCleanup)
},
})

const App = defineComponent({
render() {
return toggle.value ? h(Comp) : null
},
})

const root = nodeOps.createElement('div')
createApp(App).mount(root)
expect(onCleanup).toBeCalledTimes(0)
})
})

0 comments on commit 22dcbf3

Please sign in to comment.