checkDirty method

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

Checks if a node is dirty by examining its dependencies.

Traverses sub's dependencies starting from link to determine if any have changed. If a dependency is dirty or pending, recursively checks its dependencies.

This pull-based checking ensures values are only recomputed when actually needed, avoiding unnecessary calculations.

Returns true if any dependency has changed, requiring sub to update, or false if all dependencies are clean.

Implementation

@pragma('vm:align-loops')
bool checkDirty(Link link, ReactiveNode sub) {
  Stack<Link>? stack;
  int checkDepth = 0;
  bool dirty = false;

  top:
  do {
    final dep = link.dep, flags = dep.flags;

    if ((sub.flags & ReactiveFlags.dirty) != ReactiveFlags.none) {
      dirty = true;
    } else if ((flags &
            17 /*(ReactiveFlags.mutable | ReactiveFlags.dirty)*/) ==
        17 /*(ReactiveFlags.mutable | ReactiveFlags.dirty)*/) {
      if (update(dep)) {
        final subs = dep.subs!;
        if (subs.nextSub != null) {
          shallowPropagate(subs);
        }
        dirty = true;
      }
    } else if ((flags &
            33 /*(ReactiveFlags.mutable | ReactiveFlags.pending)*/) ==
        33 /*(ReactiveFlags.mutable | ReactiveFlags.pending)*/) {
      if (link.nextSub != null || link.prevSub != null) {
        stack = Stack(value: link, prev: stack);
      }
      link = dep.deps!;
      sub = dep;
      ++checkDepth;
      continue;
    }

    if (!dirty) {
      final nextDep = link.nextDep;
      if (nextDep != null) {
        link = nextDep;
        continue;
      }
    }

    while ((checkDepth--) > 0) {
      final firstSub = sub.subs!, hasMultipleSubs = firstSub.nextSub != null;

      if (hasMultipleSubs) {
        link = stack!.value;
        stack = stack.prev;
      } else {
        link = firstSub;
      }
      if (dirty) {
        if (update(sub)) {
          if (hasMultipleSubs) {
            shallowPropagate(firstSub);
          }
          sub = link.sub;
          continue;
        }
        dirty = false;
      } else {
        sub.flags &= -33 /*~ReactiveFlags.pending*/;
      }
      sub = link.sub;
      final nextDep = link.nextDep;
      if (nextDep != null) {
        link = nextDep;
        continue top;
      }
    }

    return dirty;
  } while (true);
}