File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change 11import {
2+ ref ,
23 reactive ,
34 effect ,
45 stop ,
@@ -801,6 +802,26 @@ describe('reactivity/effect', () => {
801802 expect ( dummy ) . toBe ( 3 )
802803 } )
803804
805+ // #5707
806+ // when an effect completes its run, it should clear the tracking bits of
807+ // its tracked deps. However, if the effect stops itself, the deps list is
808+ // emptied so their bits are never cleared.
809+ it ( 'edge case: self-stopping effect tracking ref' , ( ) => {
810+ const c = ref ( true )
811+ const runner = effect ( ( ) => {
812+ // reference ref
813+ if ( ! c . value ) {
814+ // stop itself while running
815+ stop ( runner )
816+ }
817+ } )
818+ // trigger run
819+ c . value = ! c . value
820+ // should clear bits
821+ expect ( ( c as any ) . dep . w ) . toBe ( 0 )
822+ expect ( ( c as any ) . dep . n ) . toBe ( 0 )
823+ } )
824+
804825 it ( 'events: onStop' , ( ) => {
805826 const onStop = jest . fn ( )
806827 const runner = effect ( ( ) => { } , {
Original file line number Diff line number Diff line change @@ -64,6 +64,10 @@ export class ReactiveEffect<T = any> {
6464 * @internal
6565 */
6666 allowRecurse ?: boolean
67+ /**
68+ * @internal
69+ */
70+ private deferStop ?: boolean
6771
6872 onStop ?: ( ) => void
6973 // dev only
@@ -114,11 +118,18 @@ export class ReactiveEffect<T = any> {
114118 activeEffect = this . parent
115119 shouldTrack = lastShouldTrack
116120 this . parent = undefined
121+
122+ if ( this . deferStop ) {
123+ this . stop ( )
124+ }
117125 }
118126 }
119127
120128 stop ( ) {
121- if ( this . active ) {
129+ // stopped while running itself - defer the cleanup
130+ if ( activeEffect === this ) {
131+ this . deferStop = true
132+ } else if ( this . active ) {
122133 cleanupEffect ( this )
123134 if ( this . onStop ) {
124135 this . onStop ( )
You can’t perform that action at this time.
0 commit comments