Skip to content

Commit 32df57c

Browse files
committed
refactor: remove processComputedUpdate and expose checkDirty
1 parent d681ca2 commit 32df57c

File tree

2 files changed

+115
-134
lines changed

2 files changed

+115
-134
lines changed

src/index.ts

+30-27
Original file line numberDiff line numberDiff line change
@@ -33,28 +33,10 @@ const {
3333
endTracking,
3434
startTracking,
3535
processEffectNotifications,
36-
processComputedUpdate,
3736
processPendingInnerEffects,
3837
} = createReactiveSystem({
3938
computed: {
40-
update(computed: Computed) {
41-
const prevSub = activeSub;
42-
activeSub = computed;
43-
startTracking(computed);
44-
try {
45-
const oldValue = computed.currentValue;
46-
const newValue = computed.getter(oldValue);
47-
if (oldValue !== newValue) {
48-
computed.currentValue = newValue;
49-
computed.version++;
50-
return true;
51-
}
52-
return false;
53-
} finally {
54-
activeSub = prevSub;
55-
endTracking(computed);
56-
}
57-
},
39+
update: updateComputed,
5840
onUnwatched(computed) {
5941
cooling(computed);
6042
},
@@ -156,6 +138,25 @@ export function effectScope<T>(fn: () => T): () => void {
156138
//#endregion
157139

158140
//#region Internal functions
141+
function updateComputed(computed: Computed) {
142+
const prevSub = activeSub;
143+
activeSub = computed;
144+
startTracking(computed);
145+
try {
146+
const oldValue = computed.currentValue;
147+
const newValue = computed.getter(oldValue);
148+
if (oldValue !== newValue) {
149+
computed.currentValue = newValue;
150+
computed.version++;
151+
return true;
152+
}
153+
return false;
154+
} finally {
155+
activeSub = prevSub;
156+
endTracking(computed);
157+
}
158+
}
159+
159160
function runEffect(e: Effect): void {
160161
const prevSub = activeSub;
161162
activeSub = e;
@@ -182,9 +183,7 @@ function runEffectScope(e: EffectScope, fn: () => void): void {
182183

183184
function notifyEffect(e: Effect) {
184185
const flags = e.flags;
185-
if (flags & SubscriberFlags.Dirty) {
186-
runEffect(e);
187-
} else if (checkDirty(e.deps!)) {
186+
if (flags & SubscriberFlags.Dirty || checkDirty(e.deps!)) {
188187
runEffect(e);
189188
} else {
190189
e.flags = flags & ~SubscriberFlags.Pending;
@@ -204,11 +203,15 @@ function notifyEffectScope(e: EffectScope) {
204203
//#region Bound functions
205204
function computedGetter<T>(this: Computed<T>): T {
206205
let flags = this.flags;
207-
if (flags & SubscriberFlags.Cold) {
208-
warming(this);
209-
processComputedUpdate(this, this.flags);
210-
} else if (flags & (SubscriberFlags.Dirty | SubscriberFlags.Pending)) {
211-
processComputedUpdate(this, flags);
206+
if (flags & (SubscriberFlags.Dirty | SubscriberFlags.Pending | SubscriberFlags.Cold)) {
207+
if (flags & SubscriberFlags.Cold) {
208+
warming(this);
209+
}
210+
if (flags & SubscriberFlags.Dirty || checkDirty(this.deps!)) {
211+
updateComputed(this);
212+
} else {
213+
this.flags &= ~SubscriberFlags.Pending;
214+
}
212215
}
213216
if (activeSub !== undefined) {
214217
link(this, activeSub);

src/system.ts

+85-107
Original file line numberDiff line numberDiff line change
@@ -247,25 +247,88 @@ export function createReactiveSystem({
247247
}
248248
sub.flags &= ~SubscriberFlags.Tracking;
249249
},
250-
checkDirty,
251250
/**
252-
* Updates the computed subscriber if necessary before its value is accessed.
251+
* Recursively checks and updates all computed subscribers marked as pending.
253252
*
254-
* If the subscriber is marked Dirty or PendingComputed, this function runs
255-
* the provided updateComputed logic and triggers a shallowPropagate for any
256-
* downstream subscribers if an actual update occurs.
253+
* It traverses the linked structure using a stack mechanism. For each computed
254+
* subscriber in a pending state, updateComputed is called and shallowPropagate
255+
* is triggered if a value changes. Returns whether any updates occurred.
257256
*
258-
* @param computed - The computed subscriber to update.
259-
* @param flags - The current flag set for this subscriber.
257+
* @param link - The starting link representing a sequence of pending computeds.
258+
* @returns `true` if a computed was updated, otherwise `false`.
260259
*/
261-
processComputedUpdate(computed: Dependency & Subscriber, flags: SubscriberFlags): void {
262-
if (flags & SubscriberFlags.Dirty) {
263-
updateComputed(computed);
264-
} else if (checkDirty(computed.deps!)) {
265-
updateComputed(computed);
266-
} else {
267-
computed.flags = flags & ~SubscriberFlags.Pending;
268-
}
260+
checkDirty(link: Link): boolean {
261+
let stack = 0;
262+
let dirty: boolean;
263+
264+
top: do {
265+
dirty = false;
266+
const dep = link.dep;
267+
268+
if (dep.version !== link.version) {
269+
dirty = true;
270+
} else if ('flags' in dep) {
271+
const depFlags = dep.flags;
272+
if ((depFlags & (SubscriberFlags.Computed | SubscriberFlags.Dirty)) === (SubscriberFlags.Computed | SubscriberFlags.Dirty)) {
273+
if (updateComputed(dep)) {
274+
dirty = true;
275+
}
276+
} else if ((depFlags & (SubscriberFlags.Computed | SubscriberFlags.Pending)) === (SubscriberFlags.Computed | SubscriberFlags.Pending)) {
277+
const depSubs = dep.subs!;
278+
if (depSubs.nextSub !== undefined) {
279+
depSubs.prevSub = link;
280+
}
281+
link = dep.deps!;
282+
++stack;
283+
continue;
284+
}
285+
}
286+
287+
if (!dirty && link.nextDep !== undefined) {
288+
link = link.nextDep;
289+
continue;
290+
}
291+
292+
if (stack) {
293+
let sub = link.sub as Dependency & Subscriber;
294+
do {
295+
--stack;
296+
const subSubs = sub.subs!;
297+
298+
if (dirty) {
299+
if (updateComputed(sub)) {
300+
if ((link = subSubs.prevSub!) !== undefined) {
301+
subSubs.prevSub = undefined;
302+
sub = link.sub as Dependency & Subscriber;
303+
} else {
304+
sub = subSubs.sub as Dependency & Subscriber;
305+
}
306+
continue;
307+
}
308+
} else {
309+
sub.flags &= ~SubscriberFlags.Pending;
310+
}
311+
312+
if ((link = subSubs.prevSub!) !== undefined) {
313+
subSubs.prevSub = undefined;
314+
if (link.nextDep !== undefined) {
315+
link = link.nextDep;
316+
continue top;
317+
}
318+
sub = link.sub as Dependency & Subscriber;
319+
} else {
320+
if ((link = subSubs.nextDep!) !== undefined) {
321+
continue top;
322+
}
323+
sub = subSubs.sub as Dependency & Subscriber;
324+
}
325+
326+
dirty = false;
327+
} while (stack);
328+
}
329+
330+
return dirty;
331+
} while (true);
269332
},
270333
/**
271334
* Ensures all pending internal effects for the given subscriber are processed.
@@ -371,90 +434,6 @@ export function createReactiveSystem({
371434
return newLink;
372435
}
373436

374-
/**
375-
* Recursively checks and updates all computed subscribers marked as pending.
376-
*
377-
* It traverses the linked structure using a stack mechanism. For each computed
378-
* subscriber in a pending state, updateComputed is called and shallowPropagate
379-
* is triggered if a value changes. Returns whether any updates occurred.
380-
*
381-
* @param link - The starting link representing a sequence of pending computeds.
382-
* @returns `true` if a computed was updated, otherwise `false`.
383-
*/
384-
function checkDirty(link: Link): boolean {
385-
let stack = 0;
386-
let dirty: boolean;
387-
388-
top: do {
389-
dirty = false;
390-
const dep = link.dep;
391-
392-
if (dep.version !== link.version) {
393-
dirty = true;
394-
} else if ('flags' in dep) {
395-
const depFlags = dep.flags;
396-
if ((depFlags & (SubscriberFlags.Computed | SubscriberFlags.Dirty)) === (SubscriberFlags.Computed | SubscriberFlags.Dirty)) {
397-
if (updateComputed(dep)) {
398-
dirty = true;
399-
}
400-
} else if ((depFlags & (SubscriberFlags.Computed | SubscriberFlags.Pending)) === (SubscriberFlags.Computed | SubscriberFlags.Pending)) {
401-
const depSubs = dep.subs!;
402-
if (depSubs.nextSub !== undefined) {
403-
depSubs.prevSub = link;
404-
}
405-
link = dep.deps!;
406-
++stack;
407-
continue;
408-
}
409-
}
410-
411-
if (!dirty && link.nextDep !== undefined) {
412-
link = link.nextDep;
413-
continue;
414-
}
415-
416-
if (stack) {
417-
let sub = link.sub as Dependency & Subscriber;
418-
do {
419-
--stack;
420-
const subSubs = sub.subs!;
421-
422-
if (dirty) {
423-
if (updateComputed(sub)) {
424-
if ((link = subSubs.prevSub!) !== undefined) {
425-
subSubs.prevSub = undefined;
426-
sub = link.sub as Dependency & Subscriber;
427-
} else {
428-
sub = subSubs.sub as Dependency & Subscriber;
429-
}
430-
continue;
431-
}
432-
} else {
433-
sub.flags &= ~SubscriberFlags.Pending;
434-
}
435-
436-
if ((link = subSubs.prevSub!) !== undefined) {
437-
subSubs.prevSub = undefined;
438-
if (link.nextDep !== undefined) {
439-
link = link.nextDep;
440-
continue top;
441-
}
442-
sub = link.sub as Dependency & Subscriber;
443-
} else {
444-
if ((link = subSubs.nextDep!) !== undefined) {
445-
continue top;
446-
}
447-
sub = subSubs.sub as Dependency & Subscriber;
448-
}
449-
450-
dirty = false;
451-
} while (stack);
452-
}
453-
454-
return dirty;
455-
} while (true);
456-
}
457-
458437
/**
459438
* Verifies whether the given link is valid for the specified subscriber.
460439
*
@@ -526,8 +505,8 @@ export function createReactiveSystem({
526505

527506
function warming(sub: Subscriber & Dependency) {
528507
sub.flags &= ~SubscriberFlags.Cold;
529-
let link = sub.deps;
530-
while (link !== undefined) {
508+
let link = sub.deps!;
509+
do {
531510
const dep = link.dep as Dependency | Dependency & Subscriber;
532511
if (dep.subs === undefined) {
533512
dep.subs = link;
@@ -545,14 +524,13 @@ export function createReactiveSystem({
545524
warming(dep);
546525
}
547526
}
548-
link = link.nextDep;
549-
}
527+
} while ((link = link.nextDep!) !== undefined);
550528
}
551529

552530
function cooling(sub: Subscriber & Dependency) {
553531
sub.flags |= SubscriberFlags.Cold;
554-
let link = sub.deps;
555-
while (link !== undefined) {
532+
let link = sub.deps!;
533+
do {
556534
const dep = link.dep;
557535
const nextSub = link.nextSub;
558536
const prevSub = link.prevSub;
@@ -576,10 +554,10 @@ export function createReactiveSystem({
576554
dep.subs === undefined
577555
&& 'flags' in dep
578556
&& dep.flags & SubscriberFlags.Computed
557+
&& dep.deps !== undefined
579558
) {
580559
cooling(dep);
581560
}
582-
link = link.nextDep;
583-
}
561+
} while ((link = link.nextDep!) !== undefined);
584562
}
585563
}

0 commit comments

Comments
 (0)