1
- import { remove } from '@vue/shared'
2
1
import { ReactiveEffect } from './effect'
3
2
import { warn } from './warning'
4
3
@@ -7,17 +6,23 @@ const effectScopeStack: EffectScope[] = []
7
6
8
7
export class EffectScope {
9
8
active = true
10
- effects : ( ReactiveEffect | EffectScope ) [ ] = [ ]
9
+ effects : ReactiveEffect [ ] = [ ]
11
10
cleanups : ( ( ) => void ) [ ] = [ ]
12
11
parent : EffectScope | undefined
12
+ private children : EffectScope [ ] | undefined
13
+ private parentIndex : number | undefined
13
14
14
15
constructor ( detached = false ) {
15
16
if ( ! detached ) {
16
- recordEffectScope ( this )
17
- this . parent = activeEffectScope
17
+ this . recordEffectScope ( )
18
18
}
19
19
}
20
20
21
+ get scopes ( ) : EffectScope [ ] {
22
+ if ( ! this . children ) this . children = [ ]
23
+ return this . children
24
+ }
25
+
21
26
run < T > ( fn : ( ) => T ) : T | undefined {
22
27
if ( this . active ) {
23
28
try {
@@ -45,14 +50,31 @@ export class EffectScope {
45
50
}
46
51
}
47
52
48
- stop ( fromParent = false ) {
53
+ stop ( ) {
49
54
if ( this . active ) {
50
- this . effects . forEach ( e => e . stop ( true ) )
55
+ this . effects . forEach ( e => e . stop ( ) )
56
+ this . children ?. forEach ( e => e . stop ( ) )
51
57
this . cleanups . forEach ( cleanup => cleanup ( ) )
58
+ this . parent ?. derefChildScope ( this )
52
59
this . active = false
53
- if ( ! fromParent && this . parent ) {
54
- remove ( this . parent . effects , this )
55
- }
60
+ }
61
+ }
62
+
63
+ private recordEffectScope ( ) {
64
+ const parent = activeEffectScope
65
+ if ( parent && parent . active ) {
66
+ this . parent = parent
67
+ this . parentIndex = parent . scopes . push ( this ) - 1
68
+ }
69
+ }
70
+
71
+ private derefChildScope ( scope : EffectScope ) {
72
+ // reuse the freed index by moving the last array entry
73
+ const last = this . scopes . pop ( )
74
+ if ( last && last !== scope ) {
75
+ const childIndex = scope . parentIndex !
76
+ this . scopes [ childIndex ] = last
77
+ last . parentIndex = childIndex
56
78
}
57
79
}
58
80
}
@@ -62,7 +84,7 @@ export function effectScope(detached?: boolean) {
62
84
}
63
85
64
86
export function recordEffectScope (
65
- effect : ReactiveEffect | EffectScope ,
87
+ effect : ReactiveEffect ,
66
88
scope ?: EffectScope | null
67
89
) {
68
90
scope = scope || activeEffectScope
0 commit comments