@tanstack/store 0.8.1 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/alien.cjs +345 -0
- package/dist/cjs/alien.cjs.map +1 -0
- package/dist/cjs/alien.d.cts +57 -0
- package/dist/cjs/atom.cjs +222 -0
- package/dist/cjs/atom.cjs.map +1 -0
- package/dist/cjs/atom.d.cts +16 -0
- package/dist/cjs/batch.cjs +15 -0
- package/dist/cjs/batch.cjs.map +1 -0
- package/dist/cjs/batch.d.cts +1 -0
- package/dist/cjs/index.cjs +8 -12
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +3 -4
- package/dist/cjs/store.cjs +22 -29
- package/dist/cjs/store.cjs.map +1 -1
- package/dist/cjs/store.d.cts +11 -30
- package/dist/cjs/types.d.cts +47 -20
- package/dist/esm/alien.d.ts +57 -0
- package/dist/esm/alien.js +345 -0
- package/dist/esm/alien.js.map +1 -0
- package/dist/esm/atom.d.ts +16 -0
- package/dist/esm/atom.js +222 -0
- package/dist/esm/atom.js.map +1 -0
- package/dist/esm/batch.d.ts +1 -0
- package/dist/esm/batch.js +15 -0
- package/dist/esm/batch.js.map +1 -0
- package/dist/esm/index.d.ts +3 -4
- package/dist/esm/index.js +8 -12
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/store.d.ts +11 -30
- package/dist/esm/store.js +23 -30
- package/dist/esm/store.js.map +1 -1
- package/dist/esm/types.d.ts +47 -20
- package/package.json +6 -7
- package/src/alien.ts +654 -0
- package/src/atom.ts +298 -0
- package/src/batch.ts +12 -0
- package/src/index.ts +3 -4
- package/src/store.ts +33 -72
- package/src/types.ts +60 -24
- package/dist/cjs/derived.cjs +0 -117
- package/dist/cjs/derived.cjs.map +0 -1
- package/dist/cjs/derived.d.cts +0 -50
- package/dist/cjs/effect.cjs +0 -24
- package/dist/cjs/effect.cjs.map +0 -1
- package/dist/cjs/effect.d.cts +0 -18
- package/dist/cjs/scheduler.cjs +0 -109
- package/dist/cjs/scheduler.cjs.map +0 -1
- package/dist/cjs/scheduler.d.cts +0 -27
- package/dist/cjs/types.cjs +0 -7
- package/dist/cjs/types.cjs.map +0 -1
- package/dist/esm/derived.d.ts +0 -50
- package/dist/esm/derived.js +0 -117
- package/dist/esm/derived.js.map +0 -1
- package/dist/esm/effect.d.ts +0 -18
- package/dist/esm/effect.js +0 -24
- package/dist/esm/effect.js.map +0 -1
- package/dist/esm/scheduler.d.ts +0 -27
- package/dist/esm/scheduler.js +0 -109
- package/dist/esm/scheduler.js.map +0 -1
- package/dist/esm/types.js +0 -7
- package/dist/esm/types.js.map +0 -1
- package/src/derived.ts +0 -203
- package/src/effect.ts +0 -42
- package/src/scheduler.ts +0 -155
package/src/alien.ts
ADDED
|
@@ -0,0 +1,654 @@
|
|
|
1
|
+
/* eslint-disable */
|
|
2
|
+
// Adapted from Alien Signals
|
|
3
|
+
// https://github.com/stackblitz/alien-signals/
|
|
4
|
+
|
|
5
|
+
export interface ReactiveNode {
|
|
6
|
+
deps?: Link
|
|
7
|
+
depsTail?: Link
|
|
8
|
+
subs?: Link
|
|
9
|
+
subsTail?: Link
|
|
10
|
+
flags: ReactiveFlags
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface Link {
|
|
14
|
+
version: number
|
|
15
|
+
dep: ReactiveNode
|
|
16
|
+
sub: ReactiveNode
|
|
17
|
+
prevSub: Link | undefined
|
|
18
|
+
nextSub: Link | undefined
|
|
19
|
+
prevDep: Link | undefined
|
|
20
|
+
nextDep: Link | undefined
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
interface Stack<T> {
|
|
24
|
+
value: T
|
|
25
|
+
prev: Stack<T> | undefined
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export const enum ReactiveFlags {
|
|
29
|
+
None = 0,
|
|
30
|
+
Mutable = 1,
|
|
31
|
+
Watching = 2,
|
|
32
|
+
RecursedCheck = 4,
|
|
33
|
+
Recursed = 8,
|
|
34
|
+
Dirty = 16,
|
|
35
|
+
Pending = 32,
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function createReactiveSystem({
|
|
39
|
+
update,
|
|
40
|
+
notify,
|
|
41
|
+
unwatched,
|
|
42
|
+
}: {
|
|
43
|
+
update(sub: ReactiveNode): boolean
|
|
44
|
+
notify(sub: ReactiveNode): void
|
|
45
|
+
unwatched(sub: ReactiveNode): void
|
|
46
|
+
}) {
|
|
47
|
+
return {
|
|
48
|
+
link,
|
|
49
|
+
unlink,
|
|
50
|
+
propagate,
|
|
51
|
+
checkDirty,
|
|
52
|
+
shallowPropagate,
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function link(dep: ReactiveNode, sub: ReactiveNode, version: number): void {
|
|
56
|
+
const prevDep = sub.depsTail
|
|
57
|
+
if (prevDep !== undefined && prevDep.dep === dep) {
|
|
58
|
+
return
|
|
59
|
+
}
|
|
60
|
+
const nextDep = prevDep !== undefined ? prevDep.nextDep : sub.deps
|
|
61
|
+
if (nextDep !== undefined && nextDep.dep === dep) {
|
|
62
|
+
nextDep.version = version
|
|
63
|
+
sub.depsTail = nextDep
|
|
64
|
+
return
|
|
65
|
+
}
|
|
66
|
+
const prevSub = dep.subsTail
|
|
67
|
+
if (
|
|
68
|
+
prevSub !== undefined &&
|
|
69
|
+
prevSub.version === version &&
|
|
70
|
+
prevSub.sub === sub
|
|
71
|
+
) {
|
|
72
|
+
return
|
|
73
|
+
}
|
|
74
|
+
const newLink =
|
|
75
|
+
(sub.depsTail =
|
|
76
|
+
dep.subsTail =
|
|
77
|
+
{
|
|
78
|
+
version,
|
|
79
|
+
dep,
|
|
80
|
+
sub,
|
|
81
|
+
prevDep,
|
|
82
|
+
nextDep,
|
|
83
|
+
prevSub,
|
|
84
|
+
nextSub: undefined,
|
|
85
|
+
})
|
|
86
|
+
if (nextDep !== undefined) {
|
|
87
|
+
nextDep.prevDep = newLink
|
|
88
|
+
}
|
|
89
|
+
if (prevDep !== undefined) {
|
|
90
|
+
prevDep.nextDep = newLink
|
|
91
|
+
} else {
|
|
92
|
+
sub.deps = newLink
|
|
93
|
+
}
|
|
94
|
+
if (prevSub !== undefined) {
|
|
95
|
+
prevSub.nextSub = newLink
|
|
96
|
+
} else {
|
|
97
|
+
dep.subs = newLink
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function unlink(link: Link, sub = link.sub): Link | undefined {
|
|
102
|
+
const dep = link.dep
|
|
103
|
+
const prevDep = link.prevDep
|
|
104
|
+
const nextDep = link.nextDep
|
|
105
|
+
const nextSub = link.nextSub
|
|
106
|
+
const prevSub = link.prevSub
|
|
107
|
+
if (nextDep !== undefined) {
|
|
108
|
+
nextDep.prevDep = prevDep
|
|
109
|
+
} else {
|
|
110
|
+
sub.depsTail = prevDep
|
|
111
|
+
}
|
|
112
|
+
if (prevDep !== undefined) {
|
|
113
|
+
prevDep.nextDep = nextDep
|
|
114
|
+
} else {
|
|
115
|
+
sub.deps = nextDep
|
|
116
|
+
}
|
|
117
|
+
if (nextSub !== undefined) {
|
|
118
|
+
nextSub.prevSub = prevSub
|
|
119
|
+
} else {
|
|
120
|
+
dep.subsTail = prevSub
|
|
121
|
+
}
|
|
122
|
+
if (prevSub !== undefined) {
|
|
123
|
+
prevSub.nextSub = nextSub
|
|
124
|
+
} else if ((dep.subs = nextSub) === undefined) {
|
|
125
|
+
unwatched(dep)
|
|
126
|
+
}
|
|
127
|
+
return nextDep
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function propagate(link: Link): void {
|
|
131
|
+
let next = link.nextSub
|
|
132
|
+
let stack: Stack<Link | undefined> | undefined
|
|
133
|
+
|
|
134
|
+
top: do {
|
|
135
|
+
const sub = link.sub
|
|
136
|
+
let flags = sub.flags
|
|
137
|
+
|
|
138
|
+
if (
|
|
139
|
+
!(
|
|
140
|
+
flags &
|
|
141
|
+
(ReactiveFlags.RecursedCheck |
|
|
142
|
+
ReactiveFlags.Recursed |
|
|
143
|
+
ReactiveFlags.Dirty |
|
|
144
|
+
ReactiveFlags.Pending)
|
|
145
|
+
)
|
|
146
|
+
) {
|
|
147
|
+
sub.flags = flags | ReactiveFlags.Pending
|
|
148
|
+
} else if (
|
|
149
|
+
!(flags & (ReactiveFlags.RecursedCheck | ReactiveFlags.Recursed))
|
|
150
|
+
) {
|
|
151
|
+
flags = ReactiveFlags.None
|
|
152
|
+
} else if (!(flags & ReactiveFlags.RecursedCheck)) {
|
|
153
|
+
sub.flags = (flags & ~ReactiveFlags.Recursed) | ReactiveFlags.Pending
|
|
154
|
+
} else if (
|
|
155
|
+
!(flags & (ReactiveFlags.Dirty | ReactiveFlags.Pending)) &&
|
|
156
|
+
isValidLink(link, sub)
|
|
157
|
+
) {
|
|
158
|
+
sub.flags = flags | (ReactiveFlags.Recursed | ReactiveFlags.Pending)
|
|
159
|
+
flags &= ReactiveFlags.Mutable
|
|
160
|
+
} else {
|
|
161
|
+
flags = ReactiveFlags.None
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
if (flags & ReactiveFlags.Watching) {
|
|
165
|
+
notify(sub)
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
if (flags & ReactiveFlags.Mutable) {
|
|
169
|
+
const subSubs = sub.subs
|
|
170
|
+
if (subSubs !== undefined) {
|
|
171
|
+
const nextSub = (link = subSubs).nextSub
|
|
172
|
+
if (nextSub !== undefined) {
|
|
173
|
+
stack = { value: next, prev: stack }
|
|
174
|
+
next = nextSub
|
|
175
|
+
}
|
|
176
|
+
continue
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
if ((link = next!) !== undefined) {
|
|
181
|
+
next = link.nextSub
|
|
182
|
+
continue
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
while (stack !== undefined) {
|
|
186
|
+
link = stack.value!
|
|
187
|
+
stack = stack.prev
|
|
188
|
+
if (link !== undefined) {
|
|
189
|
+
next = link.nextSub
|
|
190
|
+
continue top
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
break
|
|
195
|
+
} while (true)
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function checkDirty(link: Link, sub: ReactiveNode): boolean {
|
|
199
|
+
let stack: Stack<Link> | undefined
|
|
200
|
+
let checkDepth = 0
|
|
201
|
+
let dirty = false
|
|
202
|
+
|
|
203
|
+
top: do {
|
|
204
|
+
const dep = link.dep
|
|
205
|
+
const flags = dep.flags
|
|
206
|
+
|
|
207
|
+
if (sub.flags & ReactiveFlags.Dirty) {
|
|
208
|
+
dirty = true
|
|
209
|
+
} else if (
|
|
210
|
+
(flags & (ReactiveFlags.Mutable | ReactiveFlags.Dirty)) ===
|
|
211
|
+
(ReactiveFlags.Mutable | ReactiveFlags.Dirty)
|
|
212
|
+
) {
|
|
213
|
+
if (update(dep)) {
|
|
214
|
+
const subs = dep.subs!
|
|
215
|
+
if (subs.nextSub !== undefined) {
|
|
216
|
+
shallowPropagate(subs)
|
|
217
|
+
}
|
|
218
|
+
dirty = true
|
|
219
|
+
}
|
|
220
|
+
} else if (
|
|
221
|
+
(flags & (ReactiveFlags.Mutable | ReactiveFlags.Pending)) ===
|
|
222
|
+
(ReactiveFlags.Mutable | ReactiveFlags.Pending)
|
|
223
|
+
) {
|
|
224
|
+
if (link.nextSub !== undefined || link.prevSub !== undefined) {
|
|
225
|
+
stack = { value: link, prev: stack }
|
|
226
|
+
}
|
|
227
|
+
link = dep.deps!
|
|
228
|
+
sub = dep
|
|
229
|
+
++checkDepth
|
|
230
|
+
continue
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
if (!dirty) {
|
|
234
|
+
const nextDep = link.nextDep
|
|
235
|
+
if (nextDep !== undefined) {
|
|
236
|
+
link = nextDep
|
|
237
|
+
continue
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
while (checkDepth--) {
|
|
242
|
+
const firstSub = sub.subs!
|
|
243
|
+
const hasMultipleSubs = firstSub.nextSub !== undefined
|
|
244
|
+
if (hasMultipleSubs) {
|
|
245
|
+
link = stack!.value
|
|
246
|
+
stack = stack!.prev
|
|
247
|
+
} else {
|
|
248
|
+
link = firstSub
|
|
249
|
+
}
|
|
250
|
+
if (dirty) {
|
|
251
|
+
if (update(sub)) {
|
|
252
|
+
if (hasMultipleSubs) {
|
|
253
|
+
shallowPropagate(firstSub)
|
|
254
|
+
}
|
|
255
|
+
sub = link.sub
|
|
256
|
+
continue
|
|
257
|
+
}
|
|
258
|
+
dirty = false
|
|
259
|
+
} else {
|
|
260
|
+
sub.flags &= ~ReactiveFlags.Pending
|
|
261
|
+
}
|
|
262
|
+
sub = link.sub
|
|
263
|
+
const nextDep = link.nextDep
|
|
264
|
+
if (nextDep !== undefined) {
|
|
265
|
+
link = nextDep
|
|
266
|
+
continue top
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
return dirty
|
|
271
|
+
} while (true)
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
function shallowPropagate(link: Link): void {
|
|
275
|
+
do {
|
|
276
|
+
const sub = link.sub
|
|
277
|
+
const flags = sub.flags
|
|
278
|
+
if (
|
|
279
|
+
(flags & (ReactiveFlags.Pending | ReactiveFlags.Dirty)) ===
|
|
280
|
+
ReactiveFlags.Pending
|
|
281
|
+
) {
|
|
282
|
+
sub.flags = flags | ReactiveFlags.Dirty
|
|
283
|
+
if (
|
|
284
|
+
(flags & (ReactiveFlags.Watching | ReactiveFlags.RecursedCheck)) ===
|
|
285
|
+
ReactiveFlags.Watching
|
|
286
|
+
) {
|
|
287
|
+
notify(sub)
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
} while ((link = link.nextSub!) !== undefined)
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
function isValidLink(checkLink: Link, sub: ReactiveNode): boolean {
|
|
294
|
+
let link = sub.depsTail
|
|
295
|
+
while (link !== undefined) {
|
|
296
|
+
if (link === checkLink) {
|
|
297
|
+
return true
|
|
298
|
+
}
|
|
299
|
+
link = link.prevDep
|
|
300
|
+
}
|
|
301
|
+
return false
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
interface EffectNode extends ReactiveNode {
|
|
306
|
+
fn(): void
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
interface ComputedNode<T = any> extends ReactiveNode {
|
|
310
|
+
value: T | undefined
|
|
311
|
+
getter: (previousValue?: T) => T
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
interface SignalNode<T = any> extends ReactiveNode {
|
|
315
|
+
currentValue: T
|
|
316
|
+
pendingValue: T
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
let cycle = 0
|
|
320
|
+
let batchDepth = 0
|
|
321
|
+
let notifyIndex = 0
|
|
322
|
+
let queuedLength = 0
|
|
323
|
+
let activeSub: ReactiveNode | undefined
|
|
324
|
+
|
|
325
|
+
const queued: (EffectNode | undefined)[] = []
|
|
326
|
+
const { link, unlink, propagate, checkDirty, shallowPropagate } =
|
|
327
|
+
createReactiveSystem({
|
|
328
|
+
update(node: SignalNode | ComputedNode): boolean {
|
|
329
|
+
if (node.depsTail !== undefined) {
|
|
330
|
+
return updateComputed(node as ComputedNode)
|
|
331
|
+
} else {
|
|
332
|
+
return updateSignal(node as SignalNode)
|
|
333
|
+
}
|
|
334
|
+
},
|
|
335
|
+
notify(effect: EffectNode) {
|
|
336
|
+
let insertIndex = queuedLength
|
|
337
|
+
let firstInsertedIndex = insertIndex
|
|
338
|
+
|
|
339
|
+
do {
|
|
340
|
+
queued[insertIndex++] = effect
|
|
341
|
+
effect.flags &= ~ReactiveFlags.Watching
|
|
342
|
+
effect = effect.subs?.sub as EffectNode
|
|
343
|
+
if (effect === undefined || !(effect.flags & ReactiveFlags.Watching)) {
|
|
344
|
+
break
|
|
345
|
+
}
|
|
346
|
+
} while (true)
|
|
347
|
+
|
|
348
|
+
queuedLength = insertIndex
|
|
349
|
+
|
|
350
|
+
while (firstInsertedIndex < --insertIndex) {
|
|
351
|
+
const left = queued[firstInsertedIndex]
|
|
352
|
+
queued[firstInsertedIndex++] = queued[insertIndex]
|
|
353
|
+
queued[insertIndex] = left
|
|
354
|
+
}
|
|
355
|
+
},
|
|
356
|
+
unwatched(node) {
|
|
357
|
+
if (!(node.flags & ReactiveFlags.Mutable)) {
|
|
358
|
+
effectScopeOper.call(node)
|
|
359
|
+
} else if (node.depsTail !== undefined) {
|
|
360
|
+
node.depsTail = undefined
|
|
361
|
+
node.flags = ReactiveFlags.Mutable | ReactiveFlags.Dirty
|
|
362
|
+
purgeDeps(node)
|
|
363
|
+
}
|
|
364
|
+
},
|
|
365
|
+
})
|
|
366
|
+
|
|
367
|
+
export function getActiveSub(): ReactiveNode | undefined {
|
|
368
|
+
return activeSub
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
export function setActiveSub(sub?: ReactiveNode) {
|
|
372
|
+
const prevSub = activeSub
|
|
373
|
+
activeSub = sub
|
|
374
|
+
return prevSub
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
export function getBatchDepth(): number {
|
|
378
|
+
return batchDepth
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
export function startBatch() {
|
|
382
|
+
++batchDepth
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
export function endBatch() {
|
|
386
|
+
if (!--batchDepth) {
|
|
387
|
+
flush()
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
export function isSignal(fn: () => void): boolean {
|
|
392
|
+
return fn.name === 'bound ' + signalOper.name
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
export function isComputed(fn: () => void): boolean {
|
|
396
|
+
return fn.name === 'bound ' + computedOper.name
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
export function isEffect(fn: () => void): boolean {
|
|
400
|
+
return fn.name === 'bound ' + effectOper.name
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
export function isEffectScope(fn: () => void): boolean {
|
|
404
|
+
return fn.name === 'bound ' + effectScopeOper.name
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
export function signal<T>(): {
|
|
408
|
+
(): T | undefined
|
|
409
|
+
(value: T | undefined): void
|
|
410
|
+
}
|
|
411
|
+
export function signal<T>(initialValue: T): {
|
|
412
|
+
(): T
|
|
413
|
+
(value: T): void
|
|
414
|
+
}
|
|
415
|
+
export function signal<T>(initialValue?: T): {
|
|
416
|
+
(): T | undefined
|
|
417
|
+
(value: T | undefined): void
|
|
418
|
+
} {
|
|
419
|
+
return signalOper.bind({
|
|
420
|
+
currentValue: initialValue,
|
|
421
|
+
pendingValue: initialValue,
|
|
422
|
+
subs: undefined,
|
|
423
|
+
subsTail: undefined,
|
|
424
|
+
flags: ReactiveFlags.Mutable,
|
|
425
|
+
}) as () => T | undefined
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
export function computed<T>(getter: (previousValue?: T) => T): () => T {
|
|
429
|
+
return computedOper.bind({
|
|
430
|
+
value: undefined,
|
|
431
|
+
subs: undefined,
|
|
432
|
+
subsTail: undefined,
|
|
433
|
+
deps: undefined,
|
|
434
|
+
depsTail: undefined,
|
|
435
|
+
flags: ReactiveFlags.None,
|
|
436
|
+
getter: getter as (previousValue?: unknown) => unknown,
|
|
437
|
+
}) as () => T
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
export function effect(fn: () => void): () => void {
|
|
441
|
+
const e: EffectNode = {
|
|
442
|
+
fn,
|
|
443
|
+
subs: undefined,
|
|
444
|
+
subsTail: undefined,
|
|
445
|
+
deps: undefined,
|
|
446
|
+
depsTail: undefined,
|
|
447
|
+
flags: ReactiveFlags.Watching | ReactiveFlags.RecursedCheck,
|
|
448
|
+
}
|
|
449
|
+
const prevSub = setActiveSub(e)
|
|
450
|
+
if (prevSub !== undefined) {
|
|
451
|
+
link(e, prevSub, 0)
|
|
452
|
+
}
|
|
453
|
+
try {
|
|
454
|
+
e.fn()
|
|
455
|
+
} finally {
|
|
456
|
+
activeSub = prevSub
|
|
457
|
+
e.flags &= ~ReactiveFlags.RecursedCheck
|
|
458
|
+
}
|
|
459
|
+
return effectOper.bind(e)
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
export function effectScope(fn: () => void): () => void {
|
|
463
|
+
const e: ReactiveNode = {
|
|
464
|
+
deps: undefined,
|
|
465
|
+
depsTail: undefined,
|
|
466
|
+
subs: undefined,
|
|
467
|
+
subsTail: undefined,
|
|
468
|
+
flags: ReactiveFlags.None,
|
|
469
|
+
}
|
|
470
|
+
const prevSub = setActiveSub(e)
|
|
471
|
+
if (prevSub !== undefined) {
|
|
472
|
+
link(e, prevSub, 0)
|
|
473
|
+
}
|
|
474
|
+
try {
|
|
475
|
+
fn()
|
|
476
|
+
} finally {
|
|
477
|
+
activeSub = prevSub
|
|
478
|
+
}
|
|
479
|
+
return effectScopeOper.bind(e)
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
export function trigger(fn: () => void) {
|
|
483
|
+
const sub: ReactiveNode = {
|
|
484
|
+
deps: undefined,
|
|
485
|
+
depsTail: undefined,
|
|
486
|
+
flags: ReactiveFlags.Watching,
|
|
487
|
+
}
|
|
488
|
+
const prevSub = setActiveSub(sub)
|
|
489
|
+
try {
|
|
490
|
+
fn()
|
|
491
|
+
} finally {
|
|
492
|
+
activeSub = prevSub
|
|
493
|
+
let link = sub.deps
|
|
494
|
+
while (link !== undefined) {
|
|
495
|
+
const dep = link.dep
|
|
496
|
+
link = unlink(link, sub)
|
|
497
|
+
const subs = dep.subs
|
|
498
|
+
if (subs !== undefined) {
|
|
499
|
+
sub.flags = ReactiveFlags.None
|
|
500
|
+
propagate(subs)
|
|
501
|
+
shallowPropagate(subs)
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
if (!batchDepth) {
|
|
505
|
+
flush()
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
function updateComputed(c: ComputedNode): boolean {
|
|
511
|
+
++cycle
|
|
512
|
+
c.depsTail = undefined
|
|
513
|
+
c.flags = ReactiveFlags.Mutable | ReactiveFlags.RecursedCheck
|
|
514
|
+
const prevSub = setActiveSub(c)
|
|
515
|
+
try {
|
|
516
|
+
const oldValue = c.value
|
|
517
|
+
return oldValue !== (c.value = c.getter(oldValue))
|
|
518
|
+
} finally {
|
|
519
|
+
activeSub = prevSub
|
|
520
|
+
c.flags &= ~ReactiveFlags.RecursedCheck
|
|
521
|
+
purgeDeps(c)
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
function updateSignal(s: SignalNode): boolean {
|
|
526
|
+
s.flags = ReactiveFlags.Mutable
|
|
527
|
+
return s.currentValue !== (s.currentValue = s.pendingValue)
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
function run(e: EffectNode): void {
|
|
531
|
+
const flags = e.flags
|
|
532
|
+
if (
|
|
533
|
+
flags & ReactiveFlags.Dirty ||
|
|
534
|
+
(flags & ReactiveFlags.Pending && checkDirty(e.deps!, e))
|
|
535
|
+
) {
|
|
536
|
+
++cycle
|
|
537
|
+
e.depsTail = undefined
|
|
538
|
+
e.flags = ReactiveFlags.Watching | ReactiveFlags.RecursedCheck
|
|
539
|
+
const prevSub = setActiveSub(e)
|
|
540
|
+
try {
|
|
541
|
+
;(e as EffectNode).fn()
|
|
542
|
+
} finally {
|
|
543
|
+
activeSub = prevSub
|
|
544
|
+
e.flags &= ~ReactiveFlags.RecursedCheck
|
|
545
|
+
purgeDeps(e)
|
|
546
|
+
}
|
|
547
|
+
} else {
|
|
548
|
+
e.flags = ReactiveFlags.Watching
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
function flush(): void {
|
|
553
|
+
try {
|
|
554
|
+
while (notifyIndex < queuedLength) {
|
|
555
|
+
const effect = queued[notifyIndex]!
|
|
556
|
+
queued[notifyIndex++] = undefined
|
|
557
|
+
run(effect)
|
|
558
|
+
}
|
|
559
|
+
} finally {
|
|
560
|
+
while (notifyIndex < queuedLength) {
|
|
561
|
+
const effect = queued[notifyIndex]!
|
|
562
|
+
queued[notifyIndex++] = undefined
|
|
563
|
+
effect.flags |= ReactiveFlags.Watching | ReactiveFlags.Recursed
|
|
564
|
+
}
|
|
565
|
+
notifyIndex = 0
|
|
566
|
+
queuedLength = 0
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
function computedOper<T>(this: ComputedNode<T>): T {
|
|
571
|
+
const flags = this.flags
|
|
572
|
+
if (
|
|
573
|
+
flags & ReactiveFlags.Dirty ||
|
|
574
|
+
(flags & ReactiveFlags.Pending &&
|
|
575
|
+
(checkDirty(this.deps!, this) ||
|
|
576
|
+
((this.flags = flags & ~ReactiveFlags.Pending), false)))
|
|
577
|
+
) {
|
|
578
|
+
if (updateComputed(this)) {
|
|
579
|
+
const subs = this.subs
|
|
580
|
+
if (subs !== undefined) {
|
|
581
|
+
shallowPropagate(subs)
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
} else if (!flags) {
|
|
585
|
+
this.flags = ReactiveFlags.Mutable | ReactiveFlags.RecursedCheck
|
|
586
|
+
const prevSub = setActiveSub(this)
|
|
587
|
+
try {
|
|
588
|
+
this.value = this.getter()
|
|
589
|
+
} finally {
|
|
590
|
+
activeSub = prevSub
|
|
591
|
+
this.flags &= ~ReactiveFlags.RecursedCheck
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
const sub = activeSub
|
|
595
|
+
if (sub !== undefined) {
|
|
596
|
+
link(this, sub, cycle)
|
|
597
|
+
}
|
|
598
|
+
return this.value!
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
function signalOper<T>(this: SignalNode<T>, ...value: [T]): T | void {
|
|
602
|
+
if (value.length) {
|
|
603
|
+
if (this.pendingValue !== (this.pendingValue = value[0])) {
|
|
604
|
+
this.flags = ReactiveFlags.Mutable | ReactiveFlags.Dirty
|
|
605
|
+
const subs = this.subs
|
|
606
|
+
if (subs !== undefined) {
|
|
607
|
+
propagate(subs)
|
|
608
|
+
if (!batchDepth) {
|
|
609
|
+
flush()
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
} else {
|
|
614
|
+
if (this.flags & ReactiveFlags.Dirty) {
|
|
615
|
+
if (updateSignal(this)) {
|
|
616
|
+
const subs = this.subs
|
|
617
|
+
if (subs !== undefined) {
|
|
618
|
+
shallowPropagate(subs)
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
let sub = activeSub
|
|
623
|
+
while (sub !== undefined) {
|
|
624
|
+
if (sub.flags & (ReactiveFlags.Mutable | ReactiveFlags.Watching)) {
|
|
625
|
+
link(this, sub, cycle)
|
|
626
|
+
break
|
|
627
|
+
}
|
|
628
|
+
sub = sub.subs?.sub
|
|
629
|
+
}
|
|
630
|
+
return this.currentValue
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
function effectOper(this: EffectNode): void {
|
|
635
|
+
effectScopeOper.call(this)
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
function effectScopeOper(this: ReactiveNode): void {
|
|
639
|
+
this.depsTail = undefined
|
|
640
|
+
this.flags = ReactiveFlags.None
|
|
641
|
+
purgeDeps(this)
|
|
642
|
+
const sub = this.subs
|
|
643
|
+
if (sub !== undefined) {
|
|
644
|
+
unlink(sub)
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
function purgeDeps(sub: ReactiveNode) {
|
|
649
|
+
const depsTail = sub.depsTail
|
|
650
|
+
let dep = depsTail !== undefined ? depsTail.nextDep : sub.deps
|
|
651
|
+
while (dep !== undefined) {
|
|
652
|
+
dep = unlink(dep, sub)
|
|
653
|
+
}
|
|
654
|
+
}
|