checkDirty method

bool checkDirty(
  1. ReactiveLink link,
  2. ReactiveNode sub
)

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);
}