1
-
import { isFunction } from '@vue/shared'
1
+
import { hasChanged, isFunction } from '@vue/shared'
2
+
import { ReactiveFlags, TrackOpTypes } from './constants'
3
+
import { onTrack, setupFlagsHandler } from './debug'
2
4
import {
3
5
type DebuggerEvent,
4
6
type DebuggerOptions,
5
-
EffectFlags,
6
-
type Subscriber,
7
7
activeSub,
8
-
batch,
9
-
refreshComputed,
8
+
activeTrackId,
9
+
nextTrackId,
10
+
setActiveSub,
10
11
} from './effect'
12
+
import { activeEffectScope } from './effectScope'
11
13
import type { Ref } from './ref'
14
+
import {
15
+
type Dependency,
16
+
type IComputed,
17
+
type Link,
18
+
SubscriberFlags,
19
+
checkDirty,
20
+
endTrack,
21
+
link,
22
+
startTrack,
23
+
} from './system'
12
24
import { warn } from './warning'
13
-
import { Dep, type Link, globalVersion } from './dep'
14
-
import { ReactiveFlags, TrackOpTypes } from './constants'
15
25
16
26
declare const ComputedRefSymbol: unique symbol
17
27
declare const WritableComputedRefSymbol: unique symbol
@@ -44,15 +54,23 @@ export interface WritableComputedOptions<T, S = T> {
44
54
* @private exported by @vue/reactivity for Vue core use, but not exported from
45
55
* the main vue package
46
56
*/
47
-
export class ComputedRefImpl<T = any> implements Subscriber {
57
+
export class ComputedRefImpl<T = any> implements IComputed {
48
58
/**
49
59
* @internal
50
60
*/
51
-
_value: any = undefined
52
-
/**
53
-
* @internal
54
-
*/
55
-
readonly dep: Dep = new Dep(this)
61
+
_value: T | undefined = undefined
62
+
version = 0
63
+
64
+
// Dependency
65
+
subs: Link | undefined = undefined
66
+
subsTail: Link | undefined = undefined
67
+
lastTrackedId = 0
68
+
69
+
// Subscriber
70
+
deps: Link | undefined = undefined
71
+
depsTail: Link | undefined = undefined
72
+
flags: SubscriberFlags = SubscriberFlags.Dirty
73
+
56
74
/**
57
75
* @internal
58
76
*/
@@ -63,34 +81,39 @@ export class ComputedRefImpl<T = any> implements Subscriber {
63
81
*/
64
82
readonly __v_isReadonly: boolean
65
83
// TODO isolatedDeclarations ReactiveFlags.IS_READONLY
66
-
// A computed is also a subscriber that tracks other deps
67
-
/**
68
-
* @internal
69
-
*/
70
-
deps?: Link = undefined
71
-
/**
72
-
* @internal
73
-
*/
74
-
depsTail?: Link = undefined
75
-
/**
76
-
* @internal
77
-
*/
78
-
flags: EffectFlags = EffectFlags.DIRTY
79
-
/**
80
-
* @internal
81
-
*/
82
-
globalVersion: number = globalVersion - 1
83
-
/**
84
-
* @internal
85
-
*/
86
-
isSSR: boolean
87
-
/**
88
-
* @internal
89
-
*/
90
-
next?: Subscriber = undefined
91
84
92
85
// for backwards compat
93
-
effect: this = this
86
+
get effect(): this {
87
+
return this
88
+
}
89
+
// for backwards compat
90
+
get dep(): Dependency {
91
+
return this
92
+
}
93
+
// for backwards compat
94
+
get _dirty(): boolean {
95
+
const flags = this.flags
96
+
if (flags & SubscriberFlags.Dirty) {
97
+
return true
98
+
} else if (flags & SubscriberFlags.ToCheckDirty) {
99
+
if (checkDirty(this.deps!)) {
100
+
this.flags |= SubscriberFlags.Dirty
101
+
return true
102
+
} else {
103
+
this.flags &= ~SubscriberFlags.ToCheckDirty
104
+
return false
105
+
}
106
+
}
107
+
return false
108
+
}
109
+
set _dirty(v: boolean) {
110
+
if (v) {
111
+
this.flags |= SubscriberFlags.Dirty
112
+
} else {
113
+
this.flags &= ~SubscriberFlags.Dirtys
114
+
}
115
+
}
116
+
94
117
// dev only
95
118
onTrack?: (event: DebuggerEvent) => void
96
119
// dev only
@@ -105,43 +128,34 @@ export class ComputedRefImpl<T = any> implements Subscriber {
105
128
constructor(
106
129
public fn: ComputedGetter<T>,
107
130
private readonly setter: ComputedSetter<T> | undefined,
108
-
isSSR: boolean,
109
131
) {
110
132
this[ReactiveFlags.IS_READONLY] = !setter
111
-
this.isSSR = isSSR
112
-
}
113
-
114
-
/**
115
-
* @internal
116
-
*/
117
-
notify(): true | void {
118
-
this.flags |= EffectFlags.DIRTY
119
-
if (
120
-
!(this.flags & EffectFlags.NOTIFIED) &&
121
-
// avoid infinite self recursion
122
-
activeSub !== this
123
-
) {
124
-
batch(this, true)
125
-
return true
126
-
} else if (__DEV__) {
127
-
// TODO warn
133
+
if (__DEV__) {
134
+
setupFlagsHandler(this)
128
135
}
129
136
}
130
137
131
138
get value(): T {
132
-
const link = __DEV__
133
-
? this.dep.track({
139
+
if (this._dirty) {
140
+
this.update()
141
+
}
142
+
if (activeTrackId !== 0 && this.lastTrackedId !== activeTrackId) {
143
+
if (__DEV__) {
144
+
onTrack(activeSub!, {
134
145
target: this,
135
146
type: TrackOpTypes.GET,
136
147
key: 'value',
137
148
})
138
-
: this.dep.track()
139
-
refreshComputed(this)
140
-
// sync version after evaluation
141
-
if (link) {
142
-
link.version = this.dep.version
149
+
}
150
+
this.lastTrackedId = activeTrackId
151
+
link(this, activeSub!).version = this.version
152
+
} else if (
153
+
activeEffectScope !== undefined &&
154
+
this.lastTrackedId !== activeEffectScope.trackId
155
+
) {
156
+
link(this, activeEffectScope)
143
157
}
144
-
return this._value
158
+
return this._value!
145
159
}
146
160
147
161
set value(newValue) {
@@ -151,6 +165,27 @@ export class ComputedRefImpl<T = any> implements Subscriber {
151
165
warn('Write operation failed: computed value is readonly')
152
166
}
153
167
}
168
+
169
+
update(): boolean {
170
+
const prevSub = activeSub
171
+
const prevTrackId = activeTrackId
172
+
setActiveSub(this, nextTrackId())
173
+
startTrack(this)
174
+
const oldValue = this._value
175
+
let newValue: T
176
+
try {
177
+
newValue = this.fn(oldValue)
178
+
} finally {
179
+
setActiveSub(prevSub, prevTrackId)
180
+
endTrack(this)
181
+
}
182
+
if (hasChanged(oldValue, newValue)) {
183
+
this._value = newValue
184
+
this.version++
185
+
return true
186
+
}
187
+
return false
188
+
}
154
189
}
155
190
156
191
/**
@@ -209,7 +244,7 @@ export function computed<T>(
209
244
setter = getterOrOptions.set
210
245
}
211
246
212
-
const cRef = new ComputedRefImpl(getter, setter, isSSR)
247
+
const cRef = new ComputedRefImpl(getter, setter)
213
248
214
249
if (__DEV__ && debugOptions && !isSSR) {
215
250
cRef.onTrack = debugOptions.onTrack
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4