async function normalizeSnapshot()

in packages-ext/recoil-devtools/src/pages/Page/PageScript.js [30:90]


async function normalizeSnapshot(
  snapshot: ?RecoilSnapshot,
  onlyDirty: boolean,
  props: DevToolsConnnectProps,
): Promise<{modifiedValues?: {[string]: mixed}}> {
  if (snapshot == null) {
    return {modifiedValues: undefined};
  }
  const modifiedValues = {};
  const release = snapshot.retain();
  try {
    const dirtyNodes = snapshot.getNodes_UNSTABLE({isModified: onlyDirty});
    const customSerialize = props.serializeFn ?? DefaultCustomSerialize;
    const subscribers = new Set();

    // We wrap this loop into a promise to defer the execution
    // of the second (subscribers) loop, so selector
    // can settle before we check their values
    await new Promise(resolve => {
      for (const node of dirtyNodes) {
        const info = snapshot.getInfo_UNSTABLE(node);
        // We only accumulate subscribers if we are looking at only dirty nodes
        if (onlyDirty) {
          subscribers.add(...Array.from(info.subscribers.nodes));
        }
        modifiedValues[node.key] = {
          content: serialize(
            customSerialize(info.loadable?.contents, node.key),
            props.maxDepth,
            props.maxItems,
          ),
          nodeType: info.type,
          deps: Array.from(info.deps).map(n => n.key),
        };
      }
      resolve();
    });

    for (const node of subscribers) {
      if (node != null) {
        const info = snapshot.getInfo_UNSTABLE(node);
        modifiedValues[node.key] = {
          content: serialize(
            customSerialize(info.loadable?.contents, node.key),
            props.maxDepth,
            props.maxItems,
          ),
          nodeType: info.type,
          isSubscriber: true,
          deps: Array.from(info.deps).map(n => n.key),
        };
      }
    }
  } finally {
    release();
  }

  return {
    modifiedValues,
  };
}