Repository: facebook/react
File: packages/react-client/src/ReactFlightClient.js (JavaScript)

Code before:
    case INITIALIZED:
      wakeChunk(resolveListeners, chunk.value, chunk);
      break;
    case BLOCKED:
      // It is possible that we're blocked on our own chunk if it's a cycle.
      // Before adding back the listeners to the chunk, let's check if it would
      // result in a cycle.
      for (let i = 0; i < resolveListeners.length; i++) {
        const listener = resolveListeners[i];
        if (typeof listener !== 'function') {
          const reference: InitializationReference = listener;
          const cyclicHandler = resolveBlockedCycle(chunk, reference);
          if (cyclicHandler !== null) {
            // This reference points back to this chunk. We can resolve the cycle by
            // using the value from that handler.
            fulfillReference(reference, cyclicHandler.value, chunk);
            resolveListeners.splice(i, 1);
            i--;
            if (rejectListeners !== null) {
              const rejectionIdx = rejectListeners.indexOf(reference);
              if (rejectionIdx !== -1) {
                rejectListeners.splice(rejectionIdx, 1);
              }
            }
            // The status might have changed after fulfilling the reference.
            return wakeChunkIfInitialized(
              chunk,
              resolveListeners,
              rejectListeners,
            );
          }
        }
      }
    // Fallthrough
    case PENDING:
      if (chunk.value) {
        for (let i = 0; i < resolveListeners.length; i++) {
          chunk.value.push(resolveListeners[i]);
        }
      } else {
        chunk.value = resolveListeners;
      }

      if (chunk.reason) {
        if (rejectListeners) {
          for (let i = 0; i < rejectListeners.length; i++) {
            chunk.reason.push(rejectListeners[i]);
          }
        }
      } else {
        chunk.reason = rejectListeners;

Review comment (bug):
We should try to avoid recursion when not necessary. For example, a pattern we typically use is check if something is resolved first and then initialize and then check if something is initialized instead of a single switch.

In this case, there can also be a lot of listeners when there's a lot of references to the same thing so in theory you can actually stack overflow because of this recursion.

Instead, you should check if the status has changed to initialized or errored here and if so call `wakeChunk` or `rejectChunk` respectively.

Code after:
    case INITIALIZED:
      wakeChunk(resolveListeners, chunk.value, chunk);
      break;
    case BLOCKED:
      // It is possible that we're blocked on our own chunk if it's a cycle.
      // Before adding back the listeners to the chunk, let's check if it would
      // result in a cycle.
      for (let i = 0; i < resolveListeners.length; i++) {
        const listener = resolveListeners[i];
        if (typeof listener !== 'function') {
          const reference: InitializationReference = listener;
          const cyclicHandler = resolveBlockedCycle(chunk, reference);
          if (cyclicHandler !== null) {
            // This reference points back to this chunk. We can resolve the cycle by
            // using the value from that handler.
            fulfillReference(reference, cyclicHandler.value, chunk);
            resolveListeners.splice(i, 1);
            i--;
            if (rejectListeners !== null) {
              const rejectionIdx = rejectListeners.indexOf(reference);
              if (rejectionIdx !== -1) {
                rejectListeners.splice(rejectionIdx, 1);
              }
            }
            // The status might have changed after fulfilling the reference.
            switch ((chunk: SomeChunk<T>).status) {
              case INITIALIZED:
                const initializedChunk: InitializedChunk<T> = (chunk: any);
                wakeChunk(
                  resolveListeners,
                  initializedChunk.value,
                  initializedChunk,
                );
                return;
              case ERRORED:
                if (rejectListeners !== null) {
                  rejectChunk(rejectListeners, chunk.reason);
                }
                return;
            }
          }
        }
      }
    // Fallthrough
    case PENDING:
      if (chunk.value) {
        for (let i = 0; i < resolveListeners.length; i++) {
          chunk.value.push(resolveListeners[i]);
        }
      } else {
        chunk.value = resolveListeners;