Repository: facebook/react
File: compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Program.ts (TypeScript)

Code before:
  fn: BabelFn;
  fnType: ReactFunctionType;
};
/**
 * Find all React components and hooks that need to be compiled
 *
 * @returns An array of React functions from @param program to transform
 */
function findFunctionsToCompile(
  program: NodePath<t.Program>,
  pass: CompilerPass,
  programContext: ProgramContext,
): Array<CompileSource> {
  const queue: Array<CompileSource> = [];
  const traverseFunction = (fn: BabelFn, pass: CompilerPass): void => {
    // In 'all' mode, compile only top level functions
    if (
      pass.opts.compilationMode === 'all' &&
      fn.scope.getProgramParent() !== fn.scope.parent
    ) {
      return;
    }

    const fnType = getReactFunctionType(fn, pass);

    if (pass.opts.environment?.validateNoComponentOrHookFactories) {
      if (fnType === null || fnType === 'Other') {
        validateNoNestedComponentsOrHookFactories(fn, pass, programContext);
      }
    }

    if (fnType === null) {
      return;
    }

    if (programContext.alreadyCompiled.has(fn.node)) {
      return;
    }

    /*
     * We may be generating a new FunctionDeclaration node, so we must skip over it or this
     * traversal will loop infinitely.
     * Ensure we avoid visiting the original function again.
     */
    programContext.alreadyCompiled.add(fn.node);
    fn.skip();

    queue.push({kind: 'original', fn, fnType});
  };

  // Main traversal to compile with Forget

Review comment (bug):
`environment` shouldn't be nullable here, right? I'm asking bc if it actually is nullable that's a bug (types say it's not, BabelPlugin.ts checks the environment).

Code after:
  fn: BabelFn;
  fnType: ReactFunctionType;
};
/**
 * Find all React components and hooks that need to be compiled
 *
 * @returns An array of React functions from @param program to transform
 */
function findFunctionsToCompile(
  program: NodePath<t.Program>,
  pass: CompilerPass,
  programContext: ProgramContext,
): Array<CompileSource> {
  const queue: Array<CompileSource> = [];
  const traverseFunction = (fn: BabelFn, pass: CompilerPass): void => {
    // In 'all' mode, compile only top level functions
    if (
      pass.opts.compilationMode === 'all' &&
      fn.scope.getProgramParent() !== fn.scope.parent
    ) {
      return;
    }

    const fnType = getReactFunctionType(fn, pass);

    if (pass.opts.environment.validateNoDynamicallyCreatedComponentsOrHooks) {
      validateNoDynamicallyCreatedComponentsOrHooks(fn, pass, programContext);
    }

    if (fnType === null || programContext.alreadyCompiled.has(fn.node)) {
      return;
    }

    /*
     * We may be generating a new FunctionDeclaration node, so we must skip over it or this
     * traversal will loop infinitely.
     * Ensure we avoid visiting the original function again.
     */
    programContext.alreadyCompiled.add(fn.node);
    fn.skip();

    queue.push({kind: 'original', fn, fnType});
  };

  // Main traversal to compile with Forget
  program.traverse(
    {
      ClassDeclaration(node: NodePath<t.ClassDeclaration>) {
        /*
         * Don't visit functions defined inside classes, because they
         * can reference `this` which is unsafe for compilation