function findReleasableNodesInner()

in packages/recoil/core/Recoil_Retention.js [76:139]


  function findReleasableNodesInner(searchFromNodes: Set<NodeKey>): void {
    const releasableNodesFoundThisIteration = new Set();

    const downstreams = getDownstreamNodesInTopologicalOrder(
      store,
      treeState,
      searchFromNodes,
      releasableNodes, // don't descend into these
      nonReleasableNodes, // don't descend into these
    );

    // Find which of the downstream nodes are releasable and which are not:
    for (const node of downstreams) {
      // Not releasable if configured to be retained forever:
      if (getNode(node).retainedBy === 'recoilRoot') {
        nonReleasableNodes.add(node);
        continue;
      }

      // Not releasable if retained directly by a component:
      if ((storeState.retention.referenceCounts.get(node) ?? 0) > 0) {
        nonReleasableNodes.add(node);
        continue;
      }

      // Not releasable if retained by a zone:
      if (
        zonesThatCouldRetainNode(node).some(z =>
          storeState.retention.referenceCounts.get(z),
        )
      ) {
        nonReleasableNodes.add(node);
        continue;
      }

      // Not releasable if it has a non-releasable child (which will already be in
      // nonReleasableNodes because we are going in topological order):
      const nodeChildren = graph.nodeToNodeSubscriptions.get(node);
      if (
        nodeChildren &&
        someSet(nodeChildren, child => nonReleasableNodes.has(child))
      ) {
        nonReleasableNodes.add(node);
        continue;
      }

      releasableNodes.add(node);
      releasableNodesFoundThisIteration.add(node);
    }

    // If we found any releasable nodes, we need to walk UP from those nodes to
    // find whether their parents can now be released as well:
    const parents = new Set();
    for (const node of releasableNodesFoundThisIteration) {
      for (const parent of graph.nodeDeps.get(node) ?? emptySet) {
        if (!releasableNodes.has(parent)) {
          parents.add(parent);
        }
      }
    }
    if (parents.size) {
      findReleasableNodesInner(parents);
    }
  }