diff --git a/compiler/packages/babel-plugin-react-forget/src/Validation/ValidateNoCapitalizedCalls.ts b/compiler/packages/babel-plugin-react-forget/src/Validation/ValidateNoCapitalizedCalls.ts index 13d49c5be5..5b3a67c8a6 100644 --- a/compiler/packages/babel-plugin-react-forget/src/Validation/ValidateNoCapitalizedCalls.ts +++ b/compiler/packages/babel-plugin-react-forget/src/Validation/ValidateNoCapitalizedCalls.ts @@ -27,6 +27,7 @@ export function validateNoCapitalizedCalls(fn: HIRFunction): void { }; const capitalLoadGlobals = new Map(); + const capitalizedProperties = new Map(); for (const [, block] of fn.body.blocks) { for (const { lvalue, value } of block.instructions) { switch (value.kind) { @@ -54,6 +55,27 @@ export function validateNoCapitalizedCalls(fn: HIRFunction): void { suggestions: null, }); } + break; + } + case "PropertyLoad": { + // Start conservative and disallow all capitalized method calls + if (/^[A-Z]/.test(value.property)) { + capitalizedProperties.set(lvalue.identifier.id, value.property); + } + break; + } + case "MethodCall": { + const propertyIdentifier = value.property.identifier.id; + const propertyName = capitalizedProperties.get(propertyIdentifier); + if (propertyName != null) { + CompilerError.throwInvalidReact({ + reason: `Capitalized method calls may be calling components that use hooks, which make them dangerous to memoize. Ensure there are no hook calls in the function and rename it to begin with a lowercase letter to fix this error`, + description: `${propertyName} may be a component.`, + loc: value.loc, + suggestions: null, + }); + } + break; } } } diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.capitalized-method-call.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.capitalized-method-call.expect.md new file mode 100644 index 0000000000..813c6dab5e --- /dev/null +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.capitalized-method-call.expect.md @@ -0,0 +1,27 @@ + +## Input + +```javascript +// @validateNoCapitalizedCalls +function Component() { + const x = someGlobal.SomeFunc(); + + return x; +} + +``` + + +## Error + +``` + 1 | // @validateNoCapitalizedCalls + 2 | function Component() { +> 3 | const x = someGlobal.SomeFunc(); + | ^^^^^^^^^^^^^^^^^^^^^ InvalidReact: Capitalized method calls may be calling components that use hooks, which make them dangerous to memoize. Ensure there are no hook calls in the function and rename it to begin with a lowercase letter to fix this error. SomeFunc may be a component. (3:3) + 4 | + 5 | return x; + 6 | } +``` + + \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.capitalized-method-call.js b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.capitalized-method-call.js new file mode 100644 index 0000000000..5f829e2cf0 --- /dev/null +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.capitalized-method-call.js @@ -0,0 +1,6 @@ +// @validateNoCapitalizedCalls +function Component() { + const x = someGlobal.SomeFunc(); + + return x; +}