1
1
/* eslint-disable */
2
-
// Ported from https://github.com/stackblitz/alien-signals/blob/v1.0.4/src/system.ts
2
+
// Ported from https://github.com/stackblitz/alien-signals/blob/v1.0.13/src/system.ts
3
3
import type { ComputedRefImpl as Computed } from './computed.js'
4
4
import type { ReactiveEffect as Effect } from './effect.js'
5
5
@@ -32,9 +32,16 @@ export const enum SubscriberFlags {
32
32
Propagated = Dirty | PendingComputed,
33
33
}
34
34
35
+
interface OneWayLink<T> {
36
+
target: T
37
+
linked: OneWayLink<T> | undefined
38
+
}
39
+
40
+
const notifyBuffer: (Effect | undefined)[] = []
41
+
35
42
let batchDepth = 0
36
-
let queuedEffects: Effect | undefined
37
-
let queuedEffectsTail: Effect | undefined
43
+
let notifyIndex = 0
44
+
let notifyBufferLength = 0
38
45
39
46
export function startBatch(): void {
40
47
++batchDepth
@@ -67,80 +74,81 @@ export function link(dep: Dependency, sub: Subscriber): Link | undefined {
67
74
return linkNewDep(dep, sub, nextDep, currentDep)
68
75
}
69
76
70
-
export function propagate(link: Link): void {
77
+
export function propagate(current: Link): void {
78
+
let next = current.nextSub
79
+
let branchs: OneWayLink<Link | undefined> | undefined
80
+
let branchDepth = 0
71
81
let targetFlag = SubscriberFlags.Dirty
72
-
let subs = link
73
-
let stack = 0
74
82
75
83
top: do {
76
-
const sub = link.sub
84
+
const sub = current.sub
77
85
const subFlags = sub.flags
78
86
87
+
let shouldNotify = false
88
+
79
89
if (
80
-
(!(
90
+
!(
81
91
subFlags &
82
92
(SubscriberFlags.Tracking |
83
93
SubscriberFlags.Recursed |
84
94
SubscriberFlags.Propagated)
85
-
) &&
86
-
((sub.flags = subFlags | targetFlag), true)) ||
87
-
(subFlags & SubscriberFlags.Recursed &&
88
-
!(subFlags & SubscriberFlags.Tracking) &&
89
-
((sub.flags = (subFlags & ~SubscriberFlags.Recursed) | targetFlag),
90
-
true)) ||
91
-
(!(subFlags & SubscriberFlags.Propagated) &&
92
-
isValidLink(link, sub) &&
93
-
((sub.flags = subFlags | SubscriberFlags.Recursed | targetFlag),
94
-
(sub as Dependency).subs !== undefined))
95
+
)
96
+
) {
97
+
sub.flags = subFlags | targetFlag
98
+
shouldNotify = true
99
+
} else if (
100
+
subFlags & SubscriberFlags.Recursed &&
101
+
!(subFlags & SubscriberFlags.Tracking)
95
102
) {
103
+
sub.flags = (subFlags & ~SubscriberFlags.Recursed) | targetFlag
104
+
shouldNotify = true
105
+
} else if (
106
+
!(subFlags & SubscriberFlags.Propagated) &&
107
+
isValidLink(current, sub)
108
+
) {
109
+
sub.flags = subFlags | SubscriberFlags.Recursed | targetFlag
110
+
shouldNotify = (sub as Dependency).subs !== undefined
111
+
}
112
+
113
+
if (shouldNotify) {
96
114
const subSubs = (sub as Dependency).subs
97
115
if (subSubs !== undefined) {
116
+
current = subSubs
98
117
if (subSubs.nextSub !== undefined) {
99
-
subSubs.prevSub = subs
100
-
link = subs = subSubs
101
-
targetFlag = SubscriberFlags.PendingComputed
102
-
++stack
103
-
} else {
104
-
link = subSubs
105
-
targetFlag = SubscriberFlags.PendingComputed
118
+
branchs = { target: next, linked: branchs }
119
+
++branchDepth
120
+
next = current.nextSub
106
121
}
122
+
targetFlag = SubscriberFlags.PendingComputed
107
123
continue
108
124
}
109
125
if (subFlags & SubscriberFlags.Effect) {
110
-
if (queuedEffectsTail !== undefined) {
111
-
queuedEffectsTail.depsTail!.nextDep = sub.deps
112
-
} else {
113
-
queuedEffects = sub as Effect
114
-
}
115
-
queuedEffectsTail = sub as Effect
126
+
notifyBuffer[notifyBufferLength++] = sub as Effect
116
127
}
117
128
} else if (!(subFlags & (SubscriberFlags.Tracking | targetFlag))) {
118
129
sub.flags = subFlags | targetFlag
119
130
} else if (
120
131
!(subFlags & targetFlag) &&
121
132
subFlags & SubscriberFlags.Propagated &&
122
-
isValidLink(link, sub)
133
+
isValidLink(current, sub)
123
134
) {
124
135
sub.flags = subFlags | targetFlag
125
136
}
126
137
127
-
if ((link = subs.nextSub!) !== undefined) {
128
-
subs = link
129
-
targetFlag = stack
138
+
if ((current = next!) !== undefined) {
139
+
next = current.nextSub
140
+
targetFlag = branchDepth
130
141
? SubscriberFlags.PendingComputed
131
142
: SubscriberFlags.Dirty
132
143
continue
133
144
}
134
145
135
-
while (stack) {
136
-
--stack
137
-
const dep = subs.dep
138
-
const depSubs = dep.subs!
139
-
subs = depSubs.prevSub!
140
-
depSubs.prevSub = undefined
141
-
if ((link = subs.nextSub!) !== undefined) {
142
-
subs = link
143
-
targetFlag = stack
146
+
while (branchDepth--) {
147
+
current = branchs!.target!
148
+
branchs = branchs!.linked
149
+
if (current !== undefined) {
150
+
next = current.nextSub
151
+
targetFlag = branchDepth
144
152
? SubscriberFlags.PendingComputed
145
153
: SubscriberFlags.Dirty
146
154
continue top
@@ -194,35 +202,26 @@ export function processComputedUpdate(
194
202
computed: Computed,
195
203
flags: SubscriberFlags,
196
204
): void {
197
-
if (
198
-
flags & SubscriberFlags.Dirty ||
199
-
(checkDirty(computed.deps!)
200
-
? true
201
-
: ((computed.flags = flags & ~SubscriberFlags.PendingComputed), false))
202
-
) {
205
+
if (flags & SubscriberFlags.Dirty || checkDirty(computed.deps!)) {
203
206
if (computed.update()) {
204
207
const subs = computed.subs
205
208
if (subs !== undefined) {
206
209
shallowPropagate(subs)
207
210
}
208
211
}
212
+
} else {
213
+
computed.flags = flags & ~SubscriberFlags.PendingComputed
209
214
}
210
215
}
211
216
212
217
export function processEffectNotifications(): void {
213
-
while (queuedEffects !== undefined) {
214
-
const effect = queuedEffects
215
-
const depsTail = effect.depsTail!
216
-
const queuedNext = depsTail.nextDep
217
-
if (queuedNext !== undefined) {
218
-
depsTail.nextDep = undefined
219
-
queuedEffects = queuedNext.sub as Effect
220
-
} else {
221
-
queuedEffects = undefined
222
-
queuedEffectsTail = undefined
223
-
}
218
+
while (notifyIndex < notifyBufferLength) {
219
+
const effect = notifyBuffer[notifyIndex]!
220
+
notifyBuffer[notifyIndex++] = undefined
224
221
effect.notify()
225
222
}
223
+
notifyIndex = 0
224
+
notifyBufferLength = 0
226
225
}
227
226
228
227
function linkNewDep(
@@ -259,15 +258,18 @@ function linkNewDep(
259
258
return newLink
260
259
}
261
260
262
-
function checkDirty(link: Link): boolean {
263
-
let stack = 0
261
+
function checkDirty(current: Link): boolean {
262
+
let prevLinks: OneWayLink<Link> | undefined
263
+
let checkDepth = 0
264
264
let dirty: boolean
265
265
266
266
top: do {
267
267
dirty = false
268
-
const dep = link.dep
268
+
const dep = current.dep
269
269
270
-
if ('flags' in dep) {
270
+
if (current.sub.flags & SubscriberFlags.Dirty) {
271
+
dirty = true
272
+
} else if ('flags' in dep) {
271
273
const depFlags = dep.flags
272
274
if (
273
275
(depFlags & (SubscriberFlags.Computed | SubscriberFlags.Dirty)) ===
@@ -285,58 +287,49 @@ function checkDirty(link: Link): boolean {
285
287
(SubscriberFlags.Computed | SubscriberFlags.PendingComputed)) ===
286
288
(SubscriberFlags.Computed | SubscriberFlags.PendingComputed)
287
289
) {
288
-
const depSubs = dep.subs!
289
-
if (depSubs.nextSub !== undefined) {
290
-
depSubs.prevSub = link
290
+
if (current.nextSub !== undefined || current.prevSub !== undefined) {
291
+
prevLinks = { target: current, linked: prevLinks }
291
292
}
292
-
link = dep.deps!
293
-
++stack
293
+
current = dep.deps!
294
+
++checkDepth
294
295
continue
295
296
}
296
297
}
297
298
298
-
if (!dirty && link.nextDep !== undefined) {
299
-
link = link.nextDep
299
+
if (!dirty && current.nextDep !== undefined) {
300
+
current = current.nextDep
300
301
continue
301
302
}
302
303
303
-
if (stack) {
304
-
let sub = link.sub as Computed
305
-
do {
306
-
--stack
307
-
const subSubs = sub.subs!
308
-
309
-
if (dirty) {
310
-
if (sub.update()) {
311
-
if ((link = subSubs.prevSub!) !== undefined) {
312
-
subSubs.prevSub = undefined
313
-
shallowPropagate(subSubs)
314
-
sub = link.sub as Computed
315
-
} else {
316
-
sub = subSubs.sub as Computed
317
-
}
318
-
continue
319
-
}
320
-
} else {
321
-
sub.flags &= ~SubscriberFlags.PendingComputed
322
-
}
323
-
324
-
if ((link = subSubs.prevSub!) !== undefined) {
325
-
subSubs.prevSub = undefined
326
-
if (link.nextDep !== undefined) {
327
-
link = link.nextDep
328
-
continue top
329
-
}
330
-
sub = link.sub as Computed
331
-
} else {
332
-
if ((link = subSubs.nextDep!) !== undefined) {
333
-
continue top
304
+
while (checkDepth) {
305
+
--checkDepth
306
+
const sub = current.sub as Computed
307
+
const firstSub = sub.subs!
308
+
if (dirty) {
309
+
if (sub.update()) {
310
+
if (firstSub.nextSub !== undefined) {
311
+
current = prevLinks!.target
312
+
prevLinks = prevLinks!.linked
313
+
shallowPropagate(firstSub)
314
+
} else {
315
+
current = firstSub
334
316
}
335
-
sub = subSubs.sub as Computed
317
+
continue
336
318
}
337
-
338
-
dirty = false
339
-
} while (stack)
319
+
} else {
320
+
sub.flags &= ~SubscriberFlags.PendingComputed
321
+
}
322
+
if (firstSub.nextSub !== undefined) {
323
+
current = prevLinks!.target
324
+
prevLinks = prevLinks!.linked
325
+
} else {
326
+
current = firstSub
327
+
}
328
+
if (current.nextDep !== undefined) {
329
+
current = current.nextDep
330
+
continue top
331
+
}
332
+
dirty = false
340
333
}
341
334
342
335
return dirty
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