From 6bf64df5383113d71bf6ebc8823c6a3ef412e6d0 Mon Sep 17 00:00:00 2001 From: Sathya Gunsasekaran Date: Tue, 16 Apr 2024 14:41:16 +0100 Subject: [PATCH] [babel] Add a sources option This allows the plugin to be configured to run on an allowlist, rather than compiling all files helping with an incremental rollout plan. The sources option takes both an array of path strings or a function to be flexible. For now I've left this be optional but we can make it required. ghstack-source-id: 282a33dc8d08d47f699894692e0fcc813dff5b77 Pull Request resolved: https://github.com/facebook/react-forget/pull/2855 --- .../src/Entrypoint/Options.ts | 2 + .../src/Entrypoint/Program.ts | 38 +++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/compiler/packages/babel-plugin-react-forget/src/Entrypoint/Options.ts b/compiler/packages/babel-plugin-react-forget/src/Entrypoint/Options.ts index 5989411375..bb3aef26df 100644 --- a/compiler/packages/babel-plugin-react-forget/src/Entrypoint/Options.ts +++ b/compiler/packages/babel-plugin-react-forget/src/Entrypoint/Options.ts @@ -108,6 +108,8 @@ export type PluginOptions = { * Ignore 'use no forget' annotations. Helpful during testing but should not be used in production. */ ignoreUseNoForget: boolean; + + sources?: Array | ((filename: string) => boolean) | null; }; const CompilationModeSchema = z.enum([ diff --git a/compiler/packages/babel-plugin-react-forget/src/Entrypoint/Program.ts b/compiler/packages/babel-plugin-react-forget/src/Entrypoint/Program.ts index 15aec82858..41542c327f 100644 --- a/compiler/packages/babel-plugin-react-forget/src/Entrypoint/Program.ts +++ b/compiler/packages/babel-plugin-react-forget/src/Entrypoint/Program.ts @@ -195,12 +195,50 @@ const DEFAULT_ESLINT_SUPPRESSIONS = [ "react-hooks/rules-of-hooks", ]; +function isFilePartOfSources( + sources: Array | ((filename: string) => boolean), + filename: string +): boolean { + if (typeof sources === "function") { + return sources(filename); + } + + for (const prefix in sources) { + if (filename.indexOf(prefix) !== -1) { + return true; + } + } + + return false; +} + export function compileProgram( program: NodePath, pass: CompilerPass ): void { const options = parsePluginOptions(pass.opts); + if (options.sources) { + if (pass.filename === null) { + const error = new CompilerError(); + error.pushErrorDetail( + new CompilerErrorDetail({ + reason: `Expected a filename but found none.`, + description: + "When the 'sources' config options is specified, the React compiler will only compile files with a name", + severity: ErrorSeverity.InvalidConfig, + loc: null, + }) + ); + handleError(error, pass, null); + return; + } + + if (!isFilePartOfSources(options.sources, pass.filename)) { + return; + } + } + // Top level "use no forget", skip this file entirely if ( findDirectiveDisablingMemoization(program.node.directives, options) != null