checkDirty method
Pull phase: walks sub's dependencies starting at link and confirms
whether anything upstream actually changed, calling update on stale
mutable dependencies along the way (deepest first, iteratively).
Returns true if sub must recompute. This is what makes pending
cheap: a maybe-stale node only does real work when someone pulls it.
Fase pull: percorre as dependências de sub a partir de link e
confirma se algo acima realmente mudou, chamando update nas
dependências mutáveis obsoletas pelo caminho (mais profundas primeiro,
iterativamente). Retorna true se sub precisa recomputar. É isso
que torna pending barato: um nó talvez-obsoleto só faz trabalho real
quando alguém o puxa.
Implementation
@pragma('vm:align-loops')
bool checkDirty(ReactiveLink link, ReactiveNode sub) {
EngineStack<ReactiveLink>? stack;
int checkDepth = 0;
bool dirty = false;
top:
do {
final ReactiveNode dep = link.dep;
final ReactiveFlags flags = dep.flags;
if (sub.flags.hasAny(ReactiveFlags.dirty)) {
dirty = true;
} else if (flags.hasAll(ReactiveFlags.mutableDirty)) {
final ReactiveLink? subs = dep.subs;
if (update(dep)) {
if (subs!.nextSub != null) {
shallowPropagate(subs);
}
dirty = true;
}
} else if (flags.hasAll(ReactiveFlags.mutablePending)) {
stack = EngineStack<ReactiveLink>(value: link, prev: stack);
link = dep.deps!;
sub = dep;
++checkDepth;
continue;
}
if (!dirty) {
final ReactiveLink? nextDep = link.nextDep;
if (nextDep != null) {
link = nextDep;
continue;
}
}
while ((checkDepth--) > 0) {
link = stack!.value;
stack = stack.prev;
if (dirty) {
final ReactiveLink? subs = sub.subs;
if (update(sub)) {
if (subs!.nextSub != null) {
shallowPropagate(subs);
}
sub = link.sub;
continue;
}
dirty = false;
} else {
sub.flags = sub.flags & ~ReactiveFlags.pending;
}
sub = link.sub;
final ReactiveLink? nextDep = link.nextDep;
if (nextDep != null) {
link = nextDep;
continue top;
}
}
return dirty && sub.flags != ReactiveFlags.none;
} while (true);
}