Compute every node's open/blocked/closed status from the graph's gating
edges. Pure: returns a new Graph with re-stamped node statuses; the input is
not mutated. Run on the unfiltered graph so blocked status survives filtering.
Complexity: O(N + E). Two indexes built in one linear pass over edges —
gating edges by their source from, and (only when childOfGates is set)
child-of edges by their target to — then each node looks up its own
relevant edges directly instead of scanning the whole edge list. The
previous implementation was O(N × E), which on a graph with ~1600 nodes
and ~1400 edges meant ~2.2 million inner iterations and noticeable GC
pressure under V8's spread-and-allocate hot path.
Compute every node's
open/blocked/closedstatus from the graph's gating edges. Pure: returns a newGraphwith re-stamped node statuses; the input is not mutated. Run on the unfiltered graph so blocked status survives filtering.Complexity: O(N + E). Two indexes built in one linear pass over edges — gating edges by their source
from, and (only whenchildOfGatesis set)child-ofedges by their targetto— then each node looks up its own relevant edges directly instead of scanning the whole edge list. The previous implementation was O(N × E), which on a graph with ~1600 nodes and ~1400 edges meant ~2.2 million inner iterations and noticeable GC pressure under V8's spread-and-allocate hot path.