diff --git a/.codesandbox/ci.json b/.codesandbox/ci.json index f644328ad927e..2164efec0c8fa 100644 --- a/.codesandbox/ci.json +++ b/.codesandbox/ci.json @@ -1,7 +1,7 @@ { "packages": ["packages/react", "packages/react-dom", "packages/react-server-dom-webpack", "packages/scheduler"], "buildCommand": "download-build-in-codesandbox-ci", - "node": "18", + "node": "20", "publishDirectory": { "react": "build/oss-experimental/react", "react-dom": "build/oss-experimental/react-dom", diff --git a/compiler/apps/playground/components/Editor/ConfigEditor.tsx b/compiler/apps/playground/components/Editor/ConfigEditor.tsx new file mode 100644 index 0000000000000..d8b99c1dea4e4 --- /dev/null +++ b/compiler/apps/playground/components/Editor/ConfigEditor.tsx @@ -0,0 +1,103 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import MonacoEditor, {loader, type Monaco} from '@monaco-editor/react'; +import {parseConfigPragmaAsString} from 'babel-plugin-react-compiler'; +import type {editor} from 'monaco-editor'; +import * as monaco from 'monaco-editor'; +import parserBabel from 'prettier/plugins/babel'; +import * as prettierPluginEstree from 'prettier/plugins/estree'; +import * as prettier from 'prettier/standalone'; +import {useState, useEffect} from 'react'; +import {Resizable} from 're-resizable'; +import {useStore} from '../StoreContext'; +import {monacoOptions} from './monacoOptions'; + +loader.config({monaco}); + +export default function ConfigEditor(): JSX.Element { + const [, setMonaco] = useState(null); + const store = useStore(); + + // Parse string-based override config from pragma comment and format it + const [configJavaScript, setConfigJavaScript] = useState(''); + + useEffect(() => { + const pragma = store.source.substring(0, store.source.indexOf('\n')); + const configString = `(${parseConfigPragmaAsString(pragma)})`; + + prettier + .format(configString, { + semi: true, + parser: 'babel-ts', + plugins: [parserBabel, prettierPluginEstree], + }) + .then(formatted => { + setConfigJavaScript(formatted); + }) + .catch(error => { + console.error('Error formatting config:', error); + setConfigJavaScript('({})'); // Return empty object if not valid for now + //TODO: Add validation and error handling for config + }); + console.log('Config:', configString); + }, [store.source]); + + const handleChange: (value: string | undefined) => void = value => { + if (!value) return; + + // TODO: Implement sync logic to update pragma comments in the source + console.log('Config changed:', value); + }; + + const handleMount: ( + _: editor.IStandaloneCodeEditor, + monaco: Monaco, + ) => void = (_, monaco) => { + setMonaco(monaco); + + const uri = monaco.Uri.parse(`file:///config.js`); + const model = monaco.editor.getModel(uri); + if (model) { + model.updateOptions({tabSize: 2}); + } + }; + + return ( +
+

+ Config Overrides +

+ + + +
+ ); +} diff --git a/compiler/apps/playground/components/Editor/EditorImpl.tsx b/compiler/apps/playground/components/Editor/EditorImpl.tsx index 2a8697157a3bd..3614bbf0548e3 100644 --- a/compiler/apps/playground/components/Editor/EditorImpl.tsx +++ b/compiler/apps/playground/components/Editor/EditorImpl.tsx @@ -37,6 +37,7 @@ import { type Store, } from '../../lib/stores'; import {useStore, useStoreDispatch} from '../StoreContext'; +import ConfigEditor from './ConfigEditor'; import Input from './Input'; import { CompilerOutput, @@ -46,6 +47,7 @@ import { } from './Output'; import {transformFromAstSync} from '@babel/core'; import {LoggerEvent} from 'babel-plugin-react-compiler/dist/Entrypoint'; +import {useSearchParams} from 'next/navigation'; function parseInput( input: string, @@ -291,7 +293,13 @@ export default function Editor(): JSX.Element { [deferredStore.source], ); + // TODO: Remove this once the config editor is more stable + const searchParams = useSearchParams(); + const search = searchParams.get('showConfig'); + const shouldShowConfig = search === 'true'; + useMountEffect(() => { + // Initialize store let mountStore: Store; try { mountStore = initStoreFromUrlOrLocalStorage(); @@ -328,6 +336,7 @@ export default function Editor(): JSX.Element { return ( <>
+ {shouldShowConfig && }
diff --git a/compiler/packages/babel-plugin-react-compiler/src/CompilerError.ts b/compiler/packages/babel-plugin-react-compiler/src/CompilerError.ts index f3007034c3b7d..e12530a8db56b 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/CompilerError.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/CompilerError.ts @@ -36,6 +36,14 @@ export enum ErrorSeverity { * memoization. */ CannotPreserveMemoization = 'CannotPreserveMemoization', + /** + * An API that is known to be incompatible with the compiler. Generally as a result of + * the library using "interior mutability", ie having a value whose referential identity + * stays the same but which provides access to values that can change. For example a + * function that doesn't change but returns different results, or an object that doesn't + * change identity but whose properties change. + */ + IncompatibleLibrary = 'IncompatibleLibrary', /** * Unhandled syntax that we don't support yet. */ @@ -458,7 +466,8 @@ export class CompilerError extends Error { case ErrorSeverity.InvalidJS: case ErrorSeverity.InvalidReact: case ErrorSeverity.InvalidConfig: - case ErrorSeverity.UnsupportedJS: { + case ErrorSeverity.UnsupportedJS: + case ErrorSeverity.IncompatibleLibrary: { return true; } case ErrorSeverity.CannotPreserveMemoization: @@ -506,8 +515,9 @@ function printErrorSummary(severity: ErrorSeverity, message: string): string { severityCategory = 'Error'; break; } + case ErrorSeverity.IncompatibleLibrary: case ErrorSeverity.CannotPreserveMemoization: { - severityCategory = 'Memoization'; + severityCategory = 'Compilation Skipped'; break; } case ErrorSeverity.Invariant: { @@ -547,6 +557,9 @@ export enum ErrorCategory { // Checks that manual memoization is preserved PreserveManualMemo = 'PreserveManualMemo', + // Checks for known incompatible libraries + IncompatibleLibrary = 'IncompatibleLibrary', + // Checking for no mutations of props, hook arguments, hook return values Immutability = 'Immutability', @@ -870,6 +883,15 @@ function getRuleForCategoryImpl(category: ErrorCategory): LintRule { recommended: true, }; } + case ErrorCategory.IncompatibleLibrary: { + return { + category, + name: 'incompatible-library', + description: + 'Validates against usage of libraries which are incompatible with memoization (manual or automatic)', + recommended: true, + }; + } default: { assertExhaustive(category, `Unsupported category ${category}`); } diff --git a/compiler/packages/babel-plugin-react-compiler/src/HIR/DefaultModuleTypeProvider.ts b/compiler/packages/babel-plugin-react-compiler/src/HIR/DefaultModuleTypeProvider.ts new file mode 100644 index 0000000000000..3b3e120f39076 --- /dev/null +++ b/compiler/packages/babel-plugin-react-compiler/src/HIR/DefaultModuleTypeProvider.ts @@ -0,0 +1,91 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import {Effect, ValueKind} from '..'; +import {TypeConfig} from './TypeSchema'; + +/** + * Libraries developed before we officially documented the [Rules of React](https://react.dev/reference/rules) + * implement APIs which cannot be memoized safely, either via manual or automatic memoization. + * + * Any non-hook API that is designed to be called during render (not events/effects) should be safe to memoize: + * + * ```js + * function Component() { + * const {someFunction} = useLibrary(); + * // it should always be safe to memoize functions like this + * const result = useMemo(() => someFunction(), [someFunction]); + * } + * ``` + * + * However, some APIs implement "interior mutability" — mutating values rather than copying into a new value + * and setting state with the new value. Such functions (`someFunction()` in the example) could return different + * values even though the function itself is the same object. This breaks memoization, since React relies on + * the outer object (or function) changing if part of its value has changed. + * + * Given that we didn't have the Rules of React precisely documented prior to the introduction of React compiler, + * it's understandable that some libraries accidentally shipped APIs that break this rule. However, developers + * can easily run into pitfalls with these APIs. They may manually memoize them, which can break their app. Or + * they may try using React Compiler, and think that the compiler has broken their code. + * + * To help ensure that developers can successfully use the compiler with existing code, this file teaches the + * compiler about specific APIs that are known to be incompatible with memoization. We've tried to be as precise + * as possible. + * + * The React team is open to collaborating with library authors to help develop compatible versions of these APIs, + * and we have already reached out to the teams who own any API listed here to ensure they are aware of the issue. + */ +export function defaultModuleTypeProvider( + moduleName: string, +): TypeConfig | null { + switch (moduleName) { + case 'react-hook-form': { + return { + kind: 'object', + properties: { + useForm: { + kind: 'hook', + returnType: { + kind: 'object', + properties: { + // Only the `watch()` function returned by react-hook-form's `useForm()` API is incompatible + watch: { + kind: 'function', + positionalParams: [], + restParam: Effect.Read, + calleeEffect: Effect.Read, + returnType: {kind: 'type', name: 'Any'}, + returnValueKind: ValueKind.Mutable, + knownIncompatible: `React Hook Form's \`useForm()\` API returns a \`watch()\` function which cannot be memoized safely.`, + }, + }, + }, + }, + }, + }; + } + case '@tanstack/react-table': { + return { + kind: 'object', + properties: { + /* + * Many of the properties of `useReactTable()`'s return value are incompatible, so we mark the entire hook + * as incompatible + */ + useReactTable: { + kind: 'hook', + positionalParams: [], + restParam: Effect.Read, + returnType: {kind: 'type', name: 'Any'}, + knownIncompatible: `TanStack Table's \`useReactTable()\` API returns functions that cannot be memoized safely`, + }, + }, + }; + } + } + return null; +} diff --git a/compiler/packages/babel-plugin-react-compiler/src/HIR/Environment.ts b/compiler/packages/babel-plugin-react-compiler/src/HIR/Environment.ts index d85c6b19c6738..421b204e655c7 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/HIR/Environment.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/HIR/Environment.ts @@ -50,6 +50,7 @@ import { import {Scope as BabelScope, NodePath} from '@babel/traverse'; import {TypeSchema} from './TypeSchema'; import {FlowTypeEnv} from '../Flood/Types'; +import {defaultModuleTypeProvider} from './DefaultModuleTypeProvider'; export const ReactElementSymbolSchema = z.object({ elementSymbol: z.union([ @@ -860,10 +861,16 @@ export class Environment { #resolveModuleType(moduleName: string, loc: SourceLocation): Global | null { let moduleType = this.#moduleTypes.get(moduleName); if (moduleType === undefined) { - if (this.config.moduleTypeProvider == null) { + /* + * NOTE: Zod doesn't work when specifying a function as a default, so we have to + * fallback to the default value here + */ + const moduleTypeProvider = + this.config.moduleTypeProvider ?? defaultModuleTypeProvider; + if (moduleTypeProvider == null) { return null; } - const unparsedModuleConfig = this.config.moduleTypeProvider(moduleName); + const unparsedModuleConfig = moduleTypeProvider(moduleName); if (unparsedModuleConfig != null) { const parsedModuleConfig = TypeSchema.safeParse(unparsedModuleConfig); if (!parsedModuleConfig.success) { diff --git a/compiler/packages/babel-plugin-react-compiler/src/HIR/Globals.ts b/compiler/packages/babel-plugin-react-compiler/src/HIR/Globals.ts index 264174debafc0..561bdab6982d7 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/HIR/Globals.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/HIR/Globals.ts @@ -1001,6 +1001,7 @@ export function installTypeConfig( mutableOnlyIfOperandsAreMutable: typeConfig.mutableOnlyIfOperandsAreMutable === true, aliasing: typeConfig.aliasing, + knownIncompatible: typeConfig.knownIncompatible ?? null, }); } case 'hook': { @@ -1019,6 +1020,7 @@ export function installTypeConfig( returnValueKind: typeConfig.returnValueKind ?? ValueKind.Frozen, noAlias: typeConfig.noAlias === true, aliasing: typeConfig.aliasing, + knownIncompatible: typeConfig.knownIncompatible ?? null, }); } case 'object': { diff --git a/compiler/packages/babel-plugin-react-compiler/src/HIR/ObjectShape.ts b/compiler/packages/babel-plugin-react-compiler/src/HIR/ObjectShape.ts index ced080adcc0c3..2c626243e7075 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/HIR/ObjectShape.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/HIR/ObjectShape.ts @@ -332,6 +332,7 @@ export type FunctionSignature = { mutableOnlyIfOperandsAreMutable?: boolean; impure?: boolean; + knownIncompatible?: string | null | undefined; canonicalName?: string; diff --git a/compiler/packages/babel-plugin-react-compiler/src/HIR/TypeSchema.ts b/compiler/packages/babel-plugin-react-compiler/src/HIR/TypeSchema.ts index e63ef067b20c7..42c7d2d89dce1 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/HIR/TypeSchema.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/HIR/TypeSchema.ts @@ -251,6 +251,7 @@ export type FunctionTypeConfig = { impure?: boolean | null | undefined; canonicalName?: string | null | undefined; aliasing?: AliasingSignatureConfig | null | undefined; + knownIncompatible?: string | null | undefined; }; export const FunctionTypeSchema: z.ZodType = z.object({ kind: z.literal('function'), @@ -264,6 +265,7 @@ export const FunctionTypeSchema: z.ZodType = z.object({ impure: z.boolean().nullable().optional(), canonicalName: z.string().nullable().optional(), aliasing: AliasingSignatureSchema.nullable().optional(), + knownIncompatible: z.string().nullable().optional(), }); export type HookTypeConfig = { @@ -274,6 +276,7 @@ export type HookTypeConfig = { returnValueKind?: ValueKind | null | undefined; noAlias?: boolean | null | undefined; aliasing?: AliasingSignatureConfig | null | undefined; + knownIncompatible?: string | null | undefined; }; export const HookTypeSchema: z.ZodType = z.object({ kind: z.literal('hook'), @@ -283,6 +286,7 @@ export const HookTypeSchema: z.ZodType = z.object({ returnValueKind: ValueKindSchema.nullable().optional(), noAlias: z.boolean().nullable().optional(), aliasing: AliasingSignatureSchema.nullable().optional(), + knownIncompatible: z.string().nullable().optional(), }); export type BuiltInTypeConfig = diff --git a/compiler/packages/babel-plugin-react-compiler/src/Inference/InferMutationAliasingEffects.ts b/compiler/packages/babel-plugin-react-compiler/src/Inference/InferMutationAliasingEffects.ts index 8dd79409ce151..8ef78aa196428 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Inference/InferMutationAliasingEffects.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Inference/InferMutationAliasingEffects.ts @@ -2170,6 +2170,27 @@ function computeEffectsForLegacySignature( }), }); } + if (signature.knownIncompatible != null && state.env.isInferredMemoEnabled) { + const errors = new CompilerError(); + errors.pushDiagnostic( + CompilerDiagnostic.create({ + category: ErrorCategory.IncompatibleLibrary, + severity: ErrorSeverity.IncompatibleLibrary, + reason: 'Use of incompatible library', + description: [ + 'This API returns functions which cannot be memoized without leading to stale UI. ' + + 'To prevent this, by default React Compiler will skip memoizing this component/hook. ' + + 'However, you may see issues if values from this API are passed to other components/hooks that are ' + + 'memoized.', + ].join(''), + }).withDetail({ + kind: 'error', + loc: receiver.loc, + message: signature.knownIncompatible, + }), + ); + throw errors; + } const stores: Array = []; const captures: Array = []; function visit(place: Place, effect: Effect): void { diff --git a/compiler/packages/babel-plugin-react-compiler/src/Utils/TestUtils.ts b/compiler/packages/babel-plugin-react-compiler/src/Utils/TestUtils.ts index 7c1df1ba413b5..29e1da699ec33 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Utils/TestUtils.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Utils/TestUtils.ts @@ -182,6 +182,11 @@ export function parseConfigPragmaForTests( environment?: PartialEnvironmentConfig; }, ): PluginOptions { + const overridePragma = parseConfigPragmaAsString(pragma); + if (overridePragma !== '') { + return parseConfigStringAsJS(overridePragma, defaults); + } + const environment = parseConfigPragmaEnvironmentForTest( pragma, defaults.environment ?? {}, @@ -217,3 +222,104 @@ export function parseConfigPragmaForTests( } return parsePluginOptions(options); } + +export function parseConfigPragmaAsString(pragma: string): string { + // Check if it's in JS override format + for (const {key, value: val} of splitPragma(pragma)) { + if (key === 'OVERRIDE' && val != null) { + return val; + } + } + return ''; +} + +function parseConfigStringAsJS( + configString: string, + defaults: { + compilationMode: CompilationMode; + environment?: PartialEnvironmentConfig; + }, +): PluginOptions { + let parsedConfig: any; + try { + // Parse the JavaScript object literal + parsedConfig = new Function(`return ${configString}`)(); + } catch (error) { + CompilerError.invariant(false, { + reason: 'Failed to parse config pragma as JavaScript object', + description: `Could not parse: ${configString}. Error: ${error}`, + loc: null, + suggestions: null, + }); + } + + console.log('OVERRIDE:', parsedConfig); + + const options: Record = { + ...defaultOptions, + panicThreshold: 'all_errors', + compilationMode: defaults.compilationMode, + environment: defaults.environment ?? defaultOptions.environment, + }; + + // Apply parsed config, merging environment if it exists + if (parsedConfig.environment) { + const mergedEnvironment = { + ...(options.environment as Record), + ...parsedConfig.environment, + }; + + // Apply complex defaults for environment flags that are set to true + const environmentConfig: Partial> = + {}; + for (const [key, value] of Object.entries(mergedEnvironment)) { + if (hasOwnProperty(EnvironmentConfigSchema.shape, key)) { + if (value === true && key in testComplexConfigDefaults) { + environmentConfig[key] = testComplexConfigDefaults[key]; + } else { + environmentConfig[key] = value; + } + } + } + + // Validate environment config + const validatedEnvironment = + EnvironmentConfigSchema.safeParse(environmentConfig); + if (!validatedEnvironment.success) { + CompilerError.invariant(false, { + reason: 'Invalid environment configuration in config pragma', + description: `${fromZodError(validatedEnvironment.error)}`, + loc: null, + suggestions: null, + }); + } + + if (validatedEnvironment.data.enableResetCacheOnSourceFileChanges == null) { + validatedEnvironment.data.enableResetCacheOnSourceFileChanges = false; + } + + options.environment = validatedEnvironment.data; + } + + // Apply other config options + for (const [key, value] of Object.entries(parsedConfig)) { + if (key === 'environment') { + continue; + } + + if (hasOwnProperty(defaultOptions, key)) { + if (value === true && key in testComplexPluginOptionDefaults) { + options[key] = testComplexPluginOptionDefaults[key]; + } else if (key === 'target' && value === 'donotuse_meta_internal') { + options[key] = { + kind: value, + runtimeModule: 'react', + }; + } else { + options[key] = value; + } + } + } + + return parsePluginOptions(options); +} diff --git a/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidatePreservedManualMemoization.ts b/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidatePreservedManualMemoization.ts index 516ca232e9e4b..624cf382b7d49 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidatePreservedManualMemoization.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Validation/ValidatePreservedManualMemoization.ts @@ -284,8 +284,7 @@ function validateInferredDep( CompilerDiagnostic.create({ category: ErrorCategory.PreserveManualMemo, severity: ErrorSeverity.CannotPreserveMemoization, - reason: - 'Compilation skipped because existing memoization could not be preserved', + reason: 'Existing memoization could not be preserved', description: [ 'React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. ', 'The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. ', @@ -539,8 +538,7 @@ class Visitor extends ReactiveFunctionVisitor { CompilerDiagnostic.create({ category: ErrorCategory.PreserveManualMemo, severity: ErrorSeverity.CannotPreserveMemoization, - reason: - 'Compilation skipped because existing memoization could not be preserved', + reason: 'Existing memoization could not be preserved', description: [ 'React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. ', 'This dependency may be mutated later, which could cause the value to change unexpectedly.', @@ -588,8 +586,7 @@ class Visitor extends ReactiveFunctionVisitor { CompilerDiagnostic.create({ category: ErrorCategory.PreserveManualMemo, severity: ErrorSeverity.CannotPreserveMemoization, - reason: - 'Compilation skipped because existing memoization could not be preserved', + reason: 'Existing memoization could not be preserved', description: [ 'React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This value was memoized in source but not in compilation output. ', DEBUG diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.hoist-optional-member-expression-with-conditional-optional.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.hoist-optional-member-expression-with-conditional-optional.expect.md index 39d9aa83bd4c9..7913666aa31b4 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.hoist-optional-member-expression-with-conditional-optional.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.hoist-optional-member-expression-with-conditional-optional.expect.md @@ -26,7 +26,7 @@ function Component(props) { ``` Found 1 error: -Memoization: Compilation skipped because existing memoization could not be preserved +Compilation Skipped: Existing memoization could not be preserved React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `props.items`, but the source dependencies were [props?.items, props.cond]. Inferred different dependency than source. diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.hoist-optional-member-expression-with-conditional.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.hoist-optional-member-expression-with-conditional.expect.md index 5950ff64a62c7..b60a91187552f 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.hoist-optional-member-expression-with-conditional.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.hoist-optional-member-expression-with-conditional.expect.md @@ -26,7 +26,7 @@ function Component(props) { ``` Found 1 error: -Memoization: Compilation skipped because existing memoization could not be preserved +Compilation Skipped: Existing memoization could not be preserved React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `props.items`, but the source dependencies were [props?.items, props.cond]. Inferred different dependency than source. diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-known-incompatible-function.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-known-incompatible-function.expect.md new file mode 100644 index 0000000000000..ef14379f2f4c8 --- /dev/null +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-known-incompatible-function.expect.md @@ -0,0 +1,34 @@ + +## Input + +```javascript +import {knownIncompatible} from 'ReactCompilerKnownIncompatibleTest'; + +function Component() { + const data = knownIncompatible(); + return
Error
; +} + +``` + + +## Error + +``` +Found 1 error: + +Compilation Skipped: Use of incompatible library + +This API returns functions which cannot be memoized without leading to stale UI. To prevent this, by default React Compiler will skip memoizing this component/hook. However, you may see issues if values from this API are passed to other components/hooks that are memoized. + +error.invalid-known-incompatible-function.ts:4:15 + 2 | + 3 | function Component() { +> 4 | const data = knownIncompatible(); + | ^^^^^^^^^^^^^^^^^ useKnownIncompatible is known to be incompatible + 5 | return
Error
; + 6 | } + 7 | +``` + + \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-known-incompatible-function.js b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-known-incompatible-function.js new file mode 100644 index 0000000000000..778b6dd0453f7 --- /dev/null +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-known-incompatible-function.js @@ -0,0 +1,6 @@ +import {knownIncompatible} from 'ReactCompilerKnownIncompatibleTest'; + +function Component() { + const data = knownIncompatible(); + return
Error
; +} diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-known-incompatible-hook-return-property.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-known-incompatible-hook-return-property.expect.md new file mode 100644 index 0000000000000..1336415348028 --- /dev/null +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-known-incompatible-hook-return-property.expect.md @@ -0,0 +1,33 @@ + +## Input + +```javascript +import {useKnownIncompatibleIndirect} from 'ReactCompilerKnownIncompatibleTest'; + +function Component() { + const {incompatible} = useKnownIncompatibleIndirect(); + return
{incompatible()}
; +} + +``` + + +## Error + +``` +Found 1 error: + +Compilation Skipped: Use of incompatible library + +This API returns functions which cannot be memoized without leading to stale UI. To prevent this, by default React Compiler will skip memoizing this component/hook. However, you may see issues if values from this API are passed to other components/hooks that are memoized. + +error.invalid-known-incompatible-hook-return-property.ts:5:15 + 3 | function Component() { + 4 | const {incompatible} = useKnownIncompatibleIndirect(); +> 5 | return
{incompatible()}
; + | ^^^^^^^^^^^^ useKnownIncompatibleIndirect returns an incompatible() function that is known incompatible + 6 | } + 7 | +``` + + \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-known-incompatible-hook-return-property.js b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-known-incompatible-hook-return-property.js new file mode 100644 index 0000000000000..1160ccb4dc6c5 --- /dev/null +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-known-incompatible-hook-return-property.js @@ -0,0 +1,6 @@ +import {useKnownIncompatibleIndirect} from 'ReactCompilerKnownIncompatibleTest'; + +function Component() { + const {incompatible} = useKnownIncompatibleIndirect(); + return
{incompatible()}
; +} diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-known-incompatible-hook.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-known-incompatible-hook.expect.md new file mode 100644 index 0000000000000..dd01727b704f8 --- /dev/null +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-known-incompatible-hook.expect.md @@ -0,0 +1,34 @@ + +## Input + +```javascript +import {useKnownIncompatible} from 'ReactCompilerKnownIncompatibleTest'; + +function Component() { + const data = useKnownIncompatible(); + return
Error
; +} + +``` + + +## Error + +``` +Found 1 error: + +Compilation Skipped: Use of incompatible library + +This API returns functions which cannot be memoized without leading to stale UI. To prevent this, by default React Compiler will skip memoizing this component/hook. However, you may see issues if values from this API are passed to other components/hooks that are memoized. + +error.invalid-known-incompatible-hook.ts:4:15 + 2 | + 3 | function Component() { +> 4 | const data = useKnownIncompatible(); + | ^^^^^^^^^^^^^^^^^^^^ useKnownIncompatible is known to be incompatible + 5 | return
Error
; + 6 | } + 7 | +``` + + \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-known-incompatible-hook.js b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-known-incompatible-hook.js new file mode 100644 index 0000000000000..618516c55c95e --- /dev/null +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-known-incompatible-hook.js @@ -0,0 +1,6 @@ +import {useKnownIncompatible} from 'ReactCompilerKnownIncompatibleTest'; + +function Component() { + const data = useKnownIncompatible(); + return
Error
; +} diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-optional-member-expression-as-memo-dep-non-optional-in-body.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-optional-member-expression-as-memo-dep-non-optional-in-body.expect.md index 2c94e1cf29090..fa5cc6d53f3ef 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-optional-member-expression-as-memo-dep-non-optional-in-body.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-optional-member-expression-as-memo-dep-non-optional-in-body.expect.md @@ -20,7 +20,7 @@ function Component(props) { ``` Found 1 error: -Memoization: Compilation skipped because existing memoization could not be preserved +Compilation Skipped: Existing memoization could not be preserved React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `props.items.edges.nodes`, but the source dependencies were [props.items?.edges?.nodes]. Inferred different dependency than source. diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-useEffect-dep-not-memoized-bc-range-overlaps-hook.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-useEffect-dep-not-memoized-bc-range-overlaps-hook.expect.md index 8f551da3e88df..1e13064b72206 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-useEffect-dep-not-memoized-bc-range-overlaps-hook.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-useEffect-dep-not-memoized-bc-range-overlaps-hook.expect.md @@ -25,7 +25,7 @@ function Component(props) { ``` Found 1 error: -Memoization: React Compiler has skipped optimizing this component because the effect dependencies could not be memoized. Unmemoized effect dependencies can trigger an infinite loop or other unexpected behavior +Compilation Skipped: React Compiler has skipped optimizing this component because the effect dependencies could not be memoized. Unmemoized effect dependencies can trigger an infinite loop or other unexpected behavior error.invalid-useEffect-dep-not-memoized-bc-range-overlaps-hook.ts:9:2 7 | diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-useEffect-dep-not-memoized.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-useEffect-dep-not-memoized.expect.md index f79c9bc4eaf0f..02712424842f4 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-useEffect-dep-not-memoized.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-useEffect-dep-not-memoized.expect.md @@ -22,7 +22,7 @@ function Component(props) { ``` Found 1 error: -Memoization: React Compiler has skipped optimizing this component because the effect dependencies could not be memoized. Unmemoized effect dependencies can trigger an infinite loop or other unexpected behavior +Compilation Skipped: React Compiler has skipped optimizing this component because the effect dependencies could not be memoized. Unmemoized effect dependencies can trigger an infinite loop or other unexpected behavior error.invalid-useEffect-dep-not-memoized.ts:6:2 4 | function Component(props) { diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-useInsertionEffect-dep-not-memoized.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-useInsertionEffect-dep-not-memoized.expect.md index c6e17ff2e05da..9f98a7a2273f2 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-useInsertionEffect-dep-not-memoized.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-useInsertionEffect-dep-not-memoized.expect.md @@ -22,7 +22,7 @@ function Component(props) { ``` Found 1 error: -Memoization: React Compiler has skipped optimizing this component because the effect dependencies could not be memoized. Unmemoized effect dependencies can trigger an infinite loop or other unexpected behavior +Compilation Skipped: React Compiler has skipped optimizing this component because the effect dependencies could not be memoized. Unmemoized effect dependencies can trigger an infinite loop or other unexpected behavior error.invalid-useInsertionEffect-dep-not-memoized.ts:6:2 4 | function Component(props) { diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-useLayoutEffect-dep-not-memoized.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-useLayoutEffect-dep-not-memoized.expect.md index 6641d1fc90f56..55ba0876d761c 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-useLayoutEffect-dep-not-memoized.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-useLayoutEffect-dep-not-memoized.expect.md @@ -22,7 +22,7 @@ function Component(props) { ``` Found 1 error: -Memoization: React Compiler has skipped optimizing this component because the effect dependencies could not be memoized. Unmemoized effect dependencies can trigger an infinite loop or other unexpected behavior +Compilation Skipped: React Compiler has skipped optimizing this component because the effect dependencies could not be memoized. Unmemoized effect dependencies can trigger an infinite loop or other unexpected behavior error.invalid-useLayoutEffect-dep-not-memoized.ts:6:2 4 | function Component(props) { diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.ref-like-name-not-Ref.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.ref-like-name-not-Ref.expect.md index 99475d39905d2..22e2f41f79990 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.ref-like-name-not-Ref.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.ref-like-name-not-Ref.expect.md @@ -33,7 +33,7 @@ export const FIXTURE_ENTRYPOINT = { ``` Found 1 error: -Memoization: Compilation skipped because existing memoization could not be preserved +Compilation Skipped: Existing memoization could not be preserved React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `Ref.current`, but the source dependencies were []. Inferred dependency not present in source. diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.ref-like-name-not-a-ref.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.ref-like-name-not-a-ref.expect.md index 2a306a600cb94..fbde27f77e62d 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.ref-like-name-not-a-ref.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.ref-like-name-not-a-ref.expect.md @@ -33,7 +33,7 @@ export const FIXTURE_ENTRYPOINT = { ``` Found 1 error: -Memoization: Compilation skipped because existing memoization could not be preserved +Compilation Skipped: Existing memoization could not be preserved React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `notaref.current`, but the source dependencies were []. Inferred dependency not present in source. diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-repro-missed-memoization-from-capture-in-invoked-function-inferred-as-mutation.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-repro-missed-memoization-from-capture-in-invoked-function-inferred-as-mutation.expect.md index dfdf7a83004b2..946dd33fcbf60 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-repro-missed-memoization-from-capture-in-invoked-function-inferred-as-mutation.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-repro-missed-memoization-from-capture-in-invoked-function-inferred-as-mutation.expect.md @@ -44,7 +44,7 @@ component Component() { ``` Found 1 error: -Memoization: Compilation skipped because existing memoization could not be preserved +Compilation Skipped: Existing memoization could not be preserved React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This value was memoized in source but not in compilation output. diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-repro-missed-memoization-from-inferred-mutation-in-logger.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-repro-missed-memoization-from-inferred-mutation-in-logger.expect.md index 240af30520f3a..46c473a1b5e7c 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-repro-missed-memoization-from-inferred-mutation-in-logger.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-repro-missed-memoization-from-inferred-mutation-in-logger.expect.md @@ -54,7 +54,7 @@ component Component(id) { ``` Found 3 errors: -Memoization: Compilation skipped because existing memoization could not be preserved +Compilation Skipped: Existing memoization could not be preserved React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This value was memoized in source but not in compilation output. @@ -76,7 +76,7 @@ React Compiler has skipped optimizing this component because the existing manual 18 | const setCurrentIndex = useCallback( 19 | (index: number) => { -Memoization: Compilation skipped because existing memoization could not be preserved +Compilation Skipped: Existing memoization could not be preserved React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This dependency may be mutated later, which could cause the value to change unexpectedly. @@ -88,7 +88,7 @@ React Compiler has skipped optimizing this component because the existing manual 30 | 31 | if (prevId !== id) { -Memoization: Compilation skipped because existing memoization could not be preserved +Compilation Skipped: Existing memoization could not be preserved React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This value was memoized in source but not in compilation output. diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-repro-unmemoized-callback-captured-in-context-variable.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-repro-unmemoized-callback-captured-in-context-variable.expect.md index 429e4eb4db1ce..11ef34621c499 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-repro-unmemoized-callback-captured-in-context-variable.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-repro-unmemoized-callback-captured-in-context-variable.expect.md @@ -52,7 +52,7 @@ export const FIXTURE_ENTRYPOINT = { ``` Found 1 error: -Memoization: Compilation skipped because existing memoization could not be preserved +Compilation Skipped: Existing memoization could not be preserved React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This value was memoized in source but not in compilation output. diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.validate-memoized-effect-deps-invalidated-dep-value.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.validate-memoized-effect-deps-invalidated-dep-value.expect.md index 735decbe5585f..7fdadfbc896b1 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.validate-memoized-effect-deps-invalidated-dep-value.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.validate-memoized-effect-deps-invalidated-dep-value.expect.md @@ -30,7 +30,7 @@ export const FIXTURE_ENTRYPOINT = { ``` Found 1 error: -Memoization: React Compiler has skipped optimizing this component because the effect dependencies could not be memoized. Unmemoized effect dependencies can trigger an infinite loop or other unexpected behavior +Compilation Skipped: React Compiler has skipped optimizing this component because the effect dependencies could not be memoized. Unmemoized effect dependencies can trigger an infinite loop or other unexpected behavior error.validate-memoized-effect-deps-invalidated-dep-value.ts:11:2 9 | const y = [x]; diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.validate-object-entries-mutation.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.validate-object-entries-mutation.expect.md index 09ff6e7214ba3..76b8d466ed4e9 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.validate-object-entries-mutation.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.validate-object-entries-mutation.expect.md @@ -27,7 +27,7 @@ export const FIXTURE_ENTRYPOINT = { ``` Found 2 errors: -Memoization: Compilation skipped because existing memoization could not be preserved +Compilation Skipped: Existing memoization could not be preserved React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This dependency may be mutated later, which could cause the value to change unexpectedly. @@ -40,7 +40,7 @@ error.validate-object-entries-mutation.ts:6:57 8 | value.updated = true; 9 | }); -Memoization: Compilation skipped because existing memoization could not be preserved +Compilation Skipped: Existing memoization could not be preserved React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This value was memoized in source but not in compilation output. diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.validate-object-values-mutation.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.validate-object-values-mutation.expect.md index b791b629278af..fe532231896e3 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.validate-object-values-mutation.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.validate-object-values-mutation.expect.md @@ -27,7 +27,7 @@ export const FIXTURE_ENTRYPOINT = { ``` Found 2 errors: -Memoization: Compilation skipped because existing memoization could not be preserved +Compilation Skipped: Existing memoization could not be preserved React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This dependency may be mutated later, which could cause the value to change unexpectedly. @@ -40,7 +40,7 @@ error.validate-object-values-mutation.ts:6:55 8 | value.updated = true; 9 | }); -Memoization: Compilation skipped because existing memoization could not be preserved +Compilation Skipped: Existing memoization could not be preserved React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This value was memoized in source but not in compilation output. diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/dynamic-gating-bailout-nopanic.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/dynamic-gating-bailout-nopanic.expect.md index 58e85caf84f27..bb0172c56f8a7 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/dynamic-gating-bailout-nopanic.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/dynamic-gating-bailout-nopanic.expect.md @@ -58,7 +58,7 @@ export const FIXTURE_ENTRYPOINT = { ## Logs ``` -{"kind":"CompileError","fnLoc":{"start":{"line":6,"column":0,"index":206},"end":{"line":16,"column":1,"index":433},"filename":"dynamic-gating-bailout-nopanic.ts"},"detail":{"options":{"category":"PreserveManualMemo","severity":"CannotPreserveMemoization","reason":"Compilation skipped because existing memoization could not be preserved","description":"React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `value`, but the source dependencies were []. Inferred dependency not present in source.","suggestions":null,"details":[{"kind":"error","loc":{"start":{"line":9,"column":31,"index":288},"end":{"line":9,"column":52,"index":309},"filename":"dynamic-gating-bailout-nopanic.ts"},"message":"Could not preserve existing manual memoization"}]}}} +{"kind":"CompileError","fnLoc":{"start":{"line":6,"column":0,"index":206},"end":{"line":16,"column":1,"index":433},"filename":"dynamic-gating-bailout-nopanic.ts"},"detail":{"options":{"category":"PreserveManualMemo","severity":"CannotPreserveMemoization","reason":"Existing memoization could not be preserved","description":"React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `value`, but the source dependencies were []. Inferred dependency not present in source.","suggestions":null,"details":[{"kind":"error","loc":{"start":{"line":9,"column":31,"index":288},"end":{"line":9,"column":52,"index":309},"filename":"dynamic-gating-bailout-nopanic.ts"},"message":"Could not preserve existing manual memoization"}]}}} ``` ### Eval output diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/error.invalid-useCallback-captures-reassigned-context.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/error.invalid-useCallback-captures-reassigned-context.expect.md index d4064a6ef20d3..a6d7eb64e10aa 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/error.invalid-useCallback-captures-reassigned-context.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/error.invalid-useCallback-captures-reassigned-context.expect.md @@ -31,7 +31,7 @@ export const FIXTURE_ENTRYPOINT = { ``` Found 2 errors: -Memoization: Compilation skipped because existing memoization could not be preserved +Compilation Skipped: Existing memoization could not be preserved React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This dependency may be mutated later, which could cause the value to change unexpectedly. @@ -44,7 +44,7 @@ error.invalid-useCallback-captures-reassigned-context.ts:11:37 13 | x = makeArray(); 14 | -Memoization: Compilation skipped because existing memoization could not be preserved +Compilation Skipped: Existing memoization could not be preserved React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This value was memoized in source but not in compilation output. diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.false-positive-useMemo-dropped-infer-always-invalidating.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.false-positive-useMemo-dropped-infer-always-invalidating.expect.md index 57c4e43aa78f9..aead04aa95354 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.false-positive-useMemo-dropped-infer-always-invalidating.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.false-positive-useMemo-dropped-infer-always-invalidating.expect.md @@ -32,7 +32,7 @@ export const FIXTURE_ENTRYPOINT = { ``` Found 1 error: -Memoization: Compilation skipped because existing memoization could not be preserved +Compilation Skipped: Existing memoization could not be preserved React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This value was memoized in source but not in compilation output. diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.false-positive-useMemo-infer-mutate-deps.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.false-positive-useMemo-infer-mutate-deps.expect.md index c71c444a4c83e..a30b33d8b648e 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.false-positive-useMemo-infer-mutate-deps.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.false-positive-useMemo-infer-mutate-deps.expect.md @@ -31,7 +31,7 @@ export const FIXTURE_ENTRYPOINT = { ``` Found 1 error: -Memoization: Compilation skipped because existing memoization could not be preserved +Compilation Skipped: Existing memoization could not be preserved React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This dependency may be mutated later, which could cause the value to change unexpectedly. diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.false-positive-useMemo-overlap-scopes.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.false-positive-useMemo-overlap-scopes.expect.md index 9ed81d0f40c7a..f2bd513f57fe1 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.false-positive-useMemo-overlap-scopes.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.false-positive-useMemo-overlap-scopes.expect.md @@ -42,7 +42,7 @@ export const FIXTURE_ENTRYPOINT = { ``` Found 1 error: -Memoization: Compilation skipped because existing memoization could not be preserved +Compilation Skipped: Existing memoization could not be preserved React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This dependency may be mutated later, which could cause the value to change unexpectedly. diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.hoist-useCallback-conditional-access-own-scope.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.hoist-useCallback-conditional-access-own-scope.expect.md index 916d98fcdb298..eafc8f16cffd8 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.hoist-useCallback-conditional-access-own-scope.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.hoist-useCallback-conditional-access-own-scope.expect.md @@ -28,7 +28,7 @@ export const FIXTURE_ENTRYPOINT = { ``` Found 1 error: -Memoization: Compilation skipped because existing memoization could not be preserved +Compilation Skipped: Existing memoization could not be preserved React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `propB`, but the source dependencies were [propA, propB.x.y]. Inferred less specific property than source. diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.hoist-useCallback-infer-conditional-value-block.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.hoist-useCallback-infer-conditional-value-block.expect.md index 409b16232f3ad..6298ab289c142 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.hoist-useCallback-infer-conditional-value-block.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.hoist-useCallback-infer-conditional-value-block.expect.md @@ -31,7 +31,7 @@ export const FIXTURE_ENTRYPOINT = { ``` Found 2 errors: -Memoization: Compilation skipped because existing memoization could not be preserved +Compilation Skipped: Existing memoization could not be preserved React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `propA`, but the source dependencies were [propA.a, propB.x.y]. Inferred less specific property than source. @@ -60,7 +60,7 @@ error.hoist-useCallback-infer-conditional-value-block.ts:6:21 16 | 17 | export const FIXTURE_ENTRYPOINT = { -Memoization: Compilation skipped because existing memoization could not be preserved +Compilation Skipped: Existing memoization could not be preserved React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `propB`, but the source dependencies were [propA.a, propB.x.y]. Inferred less specific property than source. diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.invalid-useCallback-captures-reassigned-context.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.invalid-useCallback-captures-reassigned-context.expect.md index 40ea791adf6e6..082097cbd10f6 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.invalid-useCallback-captures-reassigned-context.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.invalid-useCallback-captures-reassigned-context.expect.md @@ -32,7 +32,7 @@ export const FIXTURE_ENTRYPOINT = { ``` Found 2 errors: -Memoization: Compilation skipped because existing memoization could not be preserved +Compilation Skipped: Existing memoization could not be preserved React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This dependency may be mutated later, which could cause the value to change unexpectedly. @@ -45,7 +45,7 @@ error.invalid-useCallback-captures-reassigned-context.ts:12:37 14 | x = makeArray(); 15 | -Memoization: Compilation skipped because existing memoization could not be preserved +Compilation Skipped: Existing memoization could not be preserved React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This value was memoized in source but not in compilation output. diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.preserve-use-memo-ref-missing-reactive.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.preserve-use-memo-ref-missing-reactive.expect.md index a85b278857557..3eb8e6cb26234 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.preserve-use-memo-ref-missing-reactive.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.preserve-use-memo-ref-missing-reactive.expect.md @@ -30,7 +30,7 @@ export const FIXTURE_ENTRYPOINT = { ``` Found 1 error: -Memoization: Compilation skipped because existing memoization could not be preserved +Compilation Skipped: Existing memoization could not be preserved React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `ref`, but the source dependencies were []. Inferred dependency not present in source. diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.todo-useCallback-captures-invalidating-value.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.todo-useCallback-captures-invalidating-value.expect.md index bd8959eaab979..34f98b8c780fe 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.todo-useCallback-captures-invalidating-value.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.todo-useCallback-captures-invalidating-value.expect.md @@ -30,7 +30,7 @@ export const FIXTURE_ENTRYPOINT = { ``` Found 1 error: -Memoization: Compilation skipped because existing memoization could not be preserved +Compilation Skipped: Existing memoization could not be preserved React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. This value was memoized in source but not in compilation output. diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useCallback-aliased-var.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useCallback-aliased-var.expect.md index 92a43578d5961..f742006ea12be 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useCallback-aliased-var.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useCallback-aliased-var.expect.md @@ -21,7 +21,7 @@ function useHook(x) { ``` Found 1 error: -Memoization: Compilation skipped because existing memoization could not be preserved +Compilation Skipped: Existing memoization could not be preserved React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `aliasedX`, but the source dependencies were [x, aliasedProp]. Inferred different dependency than source. diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useCallback-conditional-access-noAlloc.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useCallback-conditional-access-noAlloc.expect.md index d79cba3f0c879..92b667de08b1a 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useCallback-conditional-access-noAlloc.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useCallback-conditional-access-noAlloc.expect.md @@ -27,7 +27,7 @@ export const FIXTURE_ENTRYPOINT = { ``` Found 1 error: -Memoization: Compilation skipped because existing memoization could not be preserved +Compilation Skipped: Existing memoization could not be preserved React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `propB?.x.y`, but the source dependencies were [propA, propB.x.y]. Inferred different dependency than source. diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useCallback-infer-less-specific-conditional-access.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useCallback-infer-less-specific-conditional-access.expect.md index 4dee95a0246b6..c22a96d629f22 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useCallback-infer-less-specific-conditional-access.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useCallback-infer-less-specific-conditional-access.expect.md @@ -26,7 +26,7 @@ function Component({propA, propB}) { ``` Found 1 error: -Memoization: Compilation skipped because existing memoization could not be preserved +Compilation Skipped: Existing memoization could not be preserved React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `propB`, but the source dependencies were [propA?.a, propB.x.y]. Inferred less specific property than source. diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useCallback-property-call-dep.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useCallback-property-call-dep.expect.md index 29996cb28aa73..506a20792e909 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useCallback-property-call-dep.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useCallback-property-call-dep.expect.md @@ -19,7 +19,7 @@ function Component({propA}) { ``` Found 1 error: -Memoization: Compilation skipped because existing memoization could not be preserved +Compilation Skipped: Existing memoization could not be preserved React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `propA`, but the source dependencies were [propA.x]. Inferred less specific property than source. diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useMemo-aliased-var.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useMemo-aliased-var.expect.md index 6aac32aad7600..11a7de33481a0 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useMemo-aliased-var.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useMemo-aliased-var.expect.md @@ -21,7 +21,7 @@ function useHook(x) { ``` Found 1 error: -Memoization: Compilation skipped because existing memoization could not be preserved +Compilation Skipped: Existing memoization could not be preserved React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `x`, but the source dependencies were [aliasedX, aliasedProp]. Inferred different dependency than source. diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useMemo-infer-less-specific-conditional-access.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useMemo-infer-less-specific-conditional-access.expect.md index be17a49e63cb3..cf24f25926959 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useMemo-infer-less-specific-conditional-access.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useMemo-infer-less-specific-conditional-access.expect.md @@ -26,7 +26,7 @@ function Component({propA, propB}) { ``` Found 1 error: -Memoization: Compilation skipped because existing memoization could not be preserved +Compilation Skipped: Existing memoization could not be preserved React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `propB`, but the source dependencies were [propA?.a, propB.x.y]. Inferred less specific property than source. diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useMemo-infer-less-specific-conditional-value-block.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useMemo-infer-less-specific-conditional-value-block.expect.md index acad841ac25b4..fafaad14e6489 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useMemo-infer-less-specific-conditional-value-block.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useMemo-infer-less-specific-conditional-value-block.expect.md @@ -26,7 +26,7 @@ function Component({propA, propB}) { ``` Found 2 errors: -Memoization: Compilation skipped because existing memoization could not be preserved +Compilation Skipped: Existing memoization could not be preserved React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `propA`, but the source dependencies were [propA.a, propB.x.y]. Inferred less specific property than source. @@ -54,7 +54,7 @@ error.useMemo-infer-less-specific-conditional-value-block.ts:6:17 15 | } 16 | -Memoization: Compilation skipped because existing memoization could not be preserved +Compilation Skipped: Existing memoization could not be preserved React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `propB`, but the source dependencies were [propA.a, propB.x.y]. Inferred less specific property than source. diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useMemo-property-call-chained-object.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useMemo-property-call-chained-object.expect.md index b742a2cba66e3..00cc3fb83958b 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useMemo-property-call-chained-object.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useMemo-property-call-chained-object.expect.md @@ -21,7 +21,7 @@ function Component({propA}) { ``` Found 1 error: -Memoization: Compilation skipped because existing memoization could not be preserved +Compilation Skipped: Existing memoization could not be preserved React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `propA`, but the source dependencies were [propA.x]. Inferred less specific property than source. diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useMemo-property-call-dep.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useMemo-property-call-dep.expect.md index 933056135306c..1c86ef5a927f2 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useMemo-property-call-dep.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useMemo-property-call-dep.expect.md @@ -19,7 +19,7 @@ function Component({propA}) { ``` Found 1 error: -Memoization: Compilation skipped because existing memoization could not be preserved +Compilation Skipped: Existing memoization could not be preserved React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `propA`, but the source dependencies were [propA.x]. Inferred less specific property than source. diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useMemo-unrelated-mutation-in-depslist.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useMemo-unrelated-mutation-in-depslist.expect.md index eedb933c6eaf6..8ed05bcaf4013 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useMemo-unrelated-mutation-in-depslist.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useMemo-unrelated-mutation-in-depslist.expect.md @@ -32,7 +32,7 @@ function useFoo(input1) { ``` Found 1 error: -Memoization: Compilation skipped because existing memoization could not be preserved +Compilation Skipped: Existing memoization could not be preserved React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `input1`, but the source dependencies were [y]. Inferred different dependency than source. diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/error.todo-optional-member-expression-with-conditional-optional.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/error.todo-optional-member-expression-with-conditional-optional.expect.md index c0603c047c939..14ea4e7593875 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/error.todo-optional-member-expression-with-conditional-optional.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/error.todo-optional-member-expression-with-conditional-optional.expect.md @@ -26,7 +26,7 @@ function Component(props) { ``` Found 1 error: -Memoization: Compilation skipped because existing memoization could not be preserved +Compilation Skipped: Existing memoization could not be preserved React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `props.items`, but the source dependencies were [props?.items, props.cond]. Inferred different dependency than source. diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/error.todo-optional-member-expression-with-conditional.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/error.todo-optional-member-expression-with-conditional.expect.md index 625ea3a963ac9..f3fdb07697a85 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/error.todo-optional-member-expression-with-conditional.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/error.todo-optional-member-expression-with-conditional.expect.md @@ -26,7 +26,7 @@ function Component(props) { ``` Found 1 error: -Memoization: Compilation skipped because existing memoization could not be preserved +Compilation Skipped: Existing memoization could not be preserved React Compiler has skipped optimizing this component because the existing manual memoization could not be preserved. The inferred dependencies did not match the manually specified dependencies, which could cause the value to change more or less frequently than expected. The inferred dependency was `props.items`, but the source dependencies were [props?.items, props.cond]. Inferred different dependency than source. diff --git a/compiler/packages/babel-plugin-react-compiler/src/index.ts b/compiler/packages/babel-plugin-react-compiler/src/index.ts index 2830d70d95c8d..d8e3bf21def76 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/index.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/index.ts @@ -48,7 +48,10 @@ export { printReactiveFunction, printReactiveFunctionWithOutlined, } from './ReactiveScopes'; -export {parseConfigPragmaForTests} from './Utils/TestUtils'; +export { + parseConfigPragmaForTests, + parseConfigPragmaAsString, +} from './Utils/TestUtils'; declare global { let __DEV__: boolean | null | undefined; } diff --git a/compiler/packages/snap/src/sprout/shared-runtime-type-provider.ts b/compiler/packages/snap/src/sprout/shared-runtime-type-provider.ts index 58b007c1c7355..b01a204e78b35 100644 --- a/compiler/packages/snap/src/sprout/shared-runtime-type-provider.ts +++ b/compiler/packages/snap/src/sprout/shared-runtime-type-provider.ts @@ -198,6 +198,51 @@ export function makeSharedRuntimeTypeProvider({ }, }, }; + } else if (moduleName === 'ReactCompilerKnownIncompatibleTest') { + /** + * Fake module used for testing validation of known incompatible + * API validation + */ + return { + kind: 'object', + properties: { + useKnownIncompatible: { + kind: 'hook', + positionalParams: [], + restParam: EffectEnum.Read, + returnType: {kind: 'type', name: 'Any'}, + knownIncompatible: `useKnownIncompatible is known to be incompatible`, + }, + useKnownIncompatibleIndirect: { + kind: 'hook', + positionalParams: [], + restParam: EffectEnum.Read, + returnType: { + kind: 'object', + properties: { + incompatible: { + kind: 'function', + positionalParams: [], + restParam: EffectEnum.Read, + calleeEffect: EffectEnum.Read, + returnType: {kind: 'type', name: 'Any'}, + returnValueKind: ValueKindEnum.Mutable, + knownIncompatible: `useKnownIncompatibleIndirect returns an incompatible() function that is known incompatible`, + }, + }, + }, + }, + knownIncompatible: { + kind: 'function', + positionalParams: [], + restParam: EffectEnum.Read, + calleeEffect: EffectEnum.Read, + returnType: {kind: 'type', name: 'Any'}, + returnValueKind: ValueKindEnum.Mutable, + knownIncompatible: `useKnownIncompatible is known to be incompatible`, + }, + }, + }; } else if (moduleName === 'ReactCompilerTest') { /** * Fake module used for testing validation that type providers return hook diff --git a/packages/eslint-plugin-react-hooks/README.md b/packages/eslint-plugin-react-hooks/README.md index 10020afd61038..20d32fe9fd1bc 100644 --- a/packages/eslint-plugin-react-hooks/README.md +++ b/packages/eslint-plugin-react-hooks/README.md @@ -22,15 +22,22 @@ yarn add eslint-plugin-react-hooks --dev #### >= 6.0.0 -For users of 6.0 and beyond, simply add the `recommended` config. +For users of 6.0 and beyond, add the `recommended` config. ```js -import * as reactHooks from 'eslint-plugin-react-hooks'; +// eslint.config.js +import reactHooks from 'eslint-plugin-react-hooks'; +import { defineConfig } from 'eslint/config'; -export default [ - // ... - reactHooks.configs.recommended, -]; +export default defineConfig([ + { + files: ["src/**/*.{js,jsx,ts,tsx}"], + plugins: { + 'react-hooks': reactHooks, + }, + extends: ['react-hooks/recommended'], + }, +]); ``` #### 5.2.0 @@ -38,12 +45,18 @@ export default [ For users of 5.2.0 (the first version with flat config support), add the `recommended-latest` config. ```js -import * as reactHooks from 'eslint-plugin-react-hooks'; +import reactHooks from 'eslint-plugin-react-hooks'; +import { defineConfig } from 'eslint/config'; -export default [ - // ... - reactHooks.configs['recommended-latest'], -]; +export default defineConfig([ + { + files: ["src/**/*.{js,jsx,ts,tsx}"], + plugins: { + 'react-hooks': reactHooks, + }, + extends: ['react-hooks/recommended-latest'], + }, +]); ``` ### Legacy Config (.eslintrc)