diff --git a/compiler/forget/src/CompilerOptions.ts b/compiler/forget/src/CompilerOptions.ts index ce634aec04..0ad6423d67 100644 --- a/compiler/forget/src/CompilerOptions.ts +++ b/compiler/forget/src/CompilerOptions.ts @@ -6,15 +6,15 @@ */ import { PluginOptions } from "@babel/core"; +import { hasOwnProperty } from "./Common/utils"; import { - createCompilerFlags, CompilerFlags, + createCompilerFlags, parseCompilerFlags, } from "./CompilerFlags"; import { isOutputKind, OutputKind } from "./CompilerOutputs"; import { Logger, noopLogger } from "./Logger"; import { PassName } from "./Pass"; -import { hasOwnProperty } from "./Common/utils"; export type CompilerOptions = { outputKinds: OutputKind[]; @@ -38,6 +38,11 @@ export type CompilerOptions = { * By default, logs are disabled. */ logger: Logger; + + /** + * Capitalized identifier names that can be used in call expressions. + */ + allowedCapitalizedUserFunctions: Set; }; /** @@ -98,6 +103,17 @@ export function parseCompilerOptions( } resOpts.logger = logger; } + if (hasOwnProperty(inputOpts, "allowedCapitalizedUserFunctions")) { + const allowedCapitalizedUserFunctions = + inputOpts.allowedCapitalizedUserFunctions; + if ( + typeof allowedCapitalizedUserFunctions !== "object" || + !(allowedCapitalizedUserFunctions instanceof Set) + ) { + throw `Invalid value for 'allowedCapitalizedUserFunctions': ${allowedCapitalizedUserFunctions}`; + } + resOpts.allowedCapitalizedUserFunctions = allowedCapitalizedUserFunctions; + } return resOpts; } @@ -111,5 +127,6 @@ export function createCompilerOptions(): CompilerOptions { stopPass: PassName.JSGen, optIn: false, logger: noopLogger, + allowedCapitalizedUserFunctions: new Set(), }; } diff --git a/compiler/forget/src/MiddleEnd/SketchyCodeCheck.ts b/compiler/forget/src/MiddleEnd/SketchyCodeCheck.ts index 8801d60145..904e3e676d 100644 --- a/compiler/forget/src/MiddleEnd/SketchyCodeCheck.ts +++ b/compiler/forget/src/MiddleEnd/SketchyCodeCheck.ts @@ -23,7 +23,7 @@ export default { run, }; -const ALLOWED_CAPITALIZED_FUNCTIONS = new Set([ +const ALLOWED_CAPITALIZED_STDLIB_FUNCTIONS = new Set([ "AggregateError", "Array", "BigInt", @@ -58,7 +58,10 @@ export function run( const callee = path.get("callee"); if (t.isIdentifier(callee.node)) { const name = callee.node.name; - if (ALLOWED_CAPITALIZED_FUNCTIONS.has(name)) { + if ( + ALLOWED_CAPITALIZED_STDLIB_FUNCTIONS.has(name) || + context.opts.allowedCapitalizedUserFunctions.has(name) + ) { return; } // Allow `Module().method()`; diff --git a/compiler/forget/src/__tests__/CompilerOptions-test.ts b/compiler/forget/src/__tests__/CompilerOptions-test.ts index 9a2dc859ec..fdcde972ce 100644 --- a/compiler/forget/src/__tests__/CompilerOptions-test.ts +++ b/compiler/forget/src/__tests__/CompilerOptions-test.ts @@ -64,6 +64,7 @@ describe("CompilerOptions", () => { optIn: true, stopPass: PassName.JSGen, logger: noopLogger, + allowedCapitalizedUserFunctions: new Set(), }; expect(parseCompilerOptions(fullInput)).toEqual(fullInput); }); diff --git a/compiler/forget/src/__tests__/transform-test.ts b/compiler/forget/src/__tests__/transform-test.ts index 06d2132a3f..33608b5caa 100644 --- a/compiler/forget/src/__tests__/transform-test.ts +++ b/compiler/forget/src/__tests__/transform-test.ts @@ -116,6 +116,9 @@ describe("React Forget", () => { stopPass, flags, logger: createArrayLogger(logs), + allowedCapitalizedUserFunctions: new Set([ + "ReactForgetSecretInternals", + ]), }, compileOptions );