@samitouri / QOS-React / commits / 707e321f8f

[compiler][wip] Improve diagnostic infra (#33751)

Work in progress, i'm experimenting with revamping our diagnostic infra. Starting with a better format for representing errors, with an ability to point ot multiple locations, along with better printing of errors. Of course, Babel still controls the printing in the majority case so this still needs more work. --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/facebook/react/pull/33751). * #33981 * #33777 * #33767 * #33765 * #33760 * #33759 * #33758 * __->__ #33751 * #33752 * #33753

Joseph Savona committed Jul 24, 2025 at 15:37 UTC 707e321f8f1ba3f69d27df861caf630fe48aade6
317 files changed +3560 -626
compiler/packages/babel-plugin-react-compiler/src/Babel/BabelPlugin.ts
+52 -44
@@ -12,6 +12,7 @@ import {
12 pipelineUsesReanimatedPlugin,
13 } from '../Entrypoint/Reanimated';
14 import validateNoUntransformedReferences from '../Entrypoint/ValidateNoUntransformedReferences';
15 +import {CompilerError} from '..';
16
17 const ENABLE_REACT_COMPILER_TIMINGS =
18 process.env['ENABLE_REACT_COMPILER_TIMINGS'] === '1';
@@ -34,51 +35,58 @@ export default function BabelPluginReactCompiler(
35 */
36 Program: {
37 enter(prog, pass): void {
37 - const filename = pass.filename ?? 'unknown';
38 - if (ENABLE_REACT_COMPILER_TIMINGS === true) {
39 - performance.mark(`${filename}:start`, {
40 - detail: 'BabelPlugin:Program:start',
41 - });
42 - }
43 - let opts = parsePluginOptions(pass.opts);
44 - const isDev =
45 - (typeof __DEV__ !== 'undefined' && __DEV__ === true) ||
46 - process.env['NODE_ENV'] === 'development';
47 - if (
48 - opts.enableReanimatedCheck === true &&
49 - pipelineUsesReanimatedPlugin(pass.file.opts.plugins)
50 - ) {
51 - opts = injectReanimatedFlag(opts);
52 - }
53 - if (
54 - opts.environment.enableResetCacheOnSourceFileChanges !== false &&
55 - isDev
56 - ) {
57 - opts = {
58 - ...opts,
59 - environment: {
60 - ...opts.environment,
61 - enableResetCacheOnSourceFileChanges: true,
62 - },
63 - };
64 - }
65 - const result = compileProgram(prog, {
66 - opts,
67 - filename: pass.filename ?? null,
68 - comments: pass.file.ast.comments ?? [],
69 - code: pass.file.code,
70 - });
71 - validateNoUntransformedReferences(
72 - prog,
73 - pass.filename ?? null,
74 - opts.logger,
75 - opts.environment,
76 - result,
77 - );
78 - if (ENABLE_REACT_COMPILER_TIMINGS === true) {
79 - performance.mark(`${filename}:end`, {
80 - detail: 'BabelPlugin:Program:end',
38 + try {
39 + const filename = pass.filename ?? 'unknown';
40 + if (ENABLE_REACT_COMPILER_TIMINGS === true) {
41 + performance.mark(`${filename}:start`, {
42 + detail: 'BabelPlugin:Program:start',
43 + });
44 + }
45 + let opts = parsePluginOptions(pass.opts);
46 + const isDev =
47 + (typeof __DEV__ !== 'undefined' && __DEV__ === true) ||
48 + process.env['NODE_ENV'] === 'development';
49 + if (
50 + opts.enableReanimatedCheck === true &&
51 + pipelineUsesReanimatedPlugin(pass.file.opts.plugins)
52 + ) {
53 + opts = injectReanimatedFlag(opts);
54 + }
55 + if (
56 + opts.environment.enableResetCacheOnSourceFileChanges !== false &&
57 + isDev
58 + ) {
59 + opts = {
60 + ...opts,
61 + environment: {
62 + ...opts.environment,
63 + enableResetCacheOnSourceFileChanges: true,
64 + },
65 + };
66 + }
67 + const result = compileProgram(prog, {
68 + opts,
69 + filename: pass.filename ?? null,
70 + comments: pass.file.ast.comments ?? [],
71 + code: pass.file.code,
72 });
73 + validateNoUntransformedReferences(
74 + prog,
75 + pass.filename ?? null,
76 + opts.logger,
77 + opts.environment,
78 + result,
79 + );
80 + if (ENABLE_REACT_COMPILER_TIMINGS === true) {
81 + performance.mark(`${filename}:end`, {
82 + detail: 'BabelPlugin:Program:end',
83 + });
84 + }
85 + } catch (e) {
86 + if (e instanceof CompilerError) {
87 + throw new Error(e.printErrorMessage(pass.file.code));
88 + }
89 + throw e;
90 }
91 },
92 exit(_, pass): void {
compiler/packages/babel-plugin-react-compiler/src/CompilerError.ts
+202 -7
@@ -5,6 +5,7 @@
5 * LICENSE file in the root directory of this source tree.
6 */
7
8 +import {codeFrameColumns} from '@babel/code-frame';
9 import type {SourceLocation} from './HIR';
10 import {Err, Ok, Result} from './Utils/Result';
11 import {assertExhaustive} from './Utils/utils';
@@ -44,6 +45,24 @@ export enum ErrorSeverity {
45 Invariant = 'Invariant',
46 }
47
48 +export type CompilerDiagnosticOptions = {
49 + severity: ErrorSeverity;
50 + category: string;
51 + description: string;
52 + details: Array<CompilerDiagnosticDetail>;
53 + suggestions?: Array<CompilerSuggestion> | null | undefined;
54 +};
55 +
56 +export type CompilerDiagnosticDetail =
57 + /**
58 + * A/the source of the error
59 + */
60 + {
61 + kind: 'error';
62 + loc: SourceLocation;
63 + message: string;
64 + };
65 +
66 export enum CompilerSuggestionOperation {
67 InsertBefore,
68 InsertAfter,
@@ -74,6 +93,94 @@ export type CompilerErrorDetailOptions = {
93 suggestions?: Array<CompilerSuggestion> | null | undefined;
94 };
95
96 +export class CompilerDiagnostic {
97 + options: CompilerDiagnosticOptions;
98 +
99 + constructor(options: CompilerDiagnosticOptions) {
100 + this.options = options;
101 + }
102 +
103 + get category(): CompilerDiagnosticOptions['category'] {
104 + return this.options.category;
105 + }
106 + get description(): CompilerDiagnosticOptions['description'] {
107 + return this.options.description;
108 + }
109 + get severity(): CompilerDiagnosticOptions['severity'] {
110 + return this.options.severity;
111 + }
112 + get suggestions(): CompilerDiagnosticOptions['suggestions'] {
113 + return this.options.suggestions;
114 + }
115 +
116 + primaryLocation(): SourceLocation | null {
117 + return this.options.details.filter(d => d.kind === 'error')[0]?.loc ?? null;
118 + }
119 +
120 + printErrorMessage(source: string): string {
121 + const buffer = [
122 + printErrorSummary(this.severity, this.category),
123 + '\n\n',
124 + this.description,
125 + ];
126 + for (const detail of this.options.details) {
127 + switch (detail.kind) {
128 + case 'error': {
129 + const loc = detail.loc;
130 + if (typeof loc === 'symbol') {
131 + continue;
132 + }
133 + let codeFrame: string;
134 + try {
135 + codeFrame = codeFrameColumns(
136 + source,
137 + {
138 + start: {
139 + line: loc.start.line,
140 + column: loc.start.column + 1,
141 + },
142 + end: {
143 + line: loc.end.line,
144 + column: loc.end.column + 1,
145 + },
146 + },
147 + {
148 + message: detail.message,
149 + },
150 + );
151 + } catch (e) {
152 + codeFrame = detail.message;
153 + }
154 + buffer.push(
155 + `\n\n${loc.filename}:${loc.start.line}:${loc.start.column}\n`,
156 + );
157 + buffer.push(codeFrame);
158 + break;
159 + }
160 + default: {
161 + assertExhaustive(
162 + detail.kind,
163 + `Unexpected detail kind ${(detail as any).kind}`,
164 + );
165 + }
166 + }
167 + }
168 + return buffer.join('');
169 + }
170 +
171 + toString(): string {
172 + const buffer = [printErrorSummary(this.severity, this.category)];
173 + if (this.description != null) {
174 + buffer.push(`. ${this.description}.`);
175 + }
176 + const loc = this.primaryLocation();
177 + if (loc != null && typeof loc !== 'symbol') {
178 + buffer.push(` (${loc.start.line}:${loc.start.column})`);
179 + }
180 + return buffer.join('');
181 + }
182 +}
183 +
184 /*
185 * Each bailout or invariant in HIR lowering creates an {@link CompilerErrorDetail}, which is then
186 * aggregated into a single {@link CompilerError} later.
@@ -101,24 +208,62 @@ export class CompilerErrorDetail {
208 return this.options.suggestions;
209 }
210
104 - printErrorMessage(): string {
105 - const buffer = [`${this.severity}: ${this.reason}`];
211 + primaryLocation(): SourceLocation | null {
212 + return this.loc;
213 + }
214 +
215 + printErrorMessage(source: string): string {
216 + const buffer = [printErrorSummary(this.severity, this.reason)];
217 if (this.description != null) {
107 - buffer.push(`. ${this.description}`);
218 + buffer.push(`\n\n${this.description}.`);
219 }
109 - if (this.loc != null && typeof this.loc !== 'symbol') {
110 - buffer.push(` (${this.loc.start.line}:${this.loc.end.line})`);
220 + const loc = this.loc;
221 + if (loc != null && typeof loc !== 'symbol') {
222 + let codeFrame: string;
223 + try {
224 + codeFrame = codeFrameColumns(
225 + source,
226 + {
227 + start: {
228 + line: loc.start.line,
229 + column: loc.start.column + 1,
230 + },
231 + end: {
232 + line: loc.end.line,
233 + column: loc.end.column + 1,
234 + },
235 + },
236 + {
237 + message: this.reason,
238 + },
239 + );
240 + } catch (e) {
241 + codeFrame = '';
242 + }
243 + buffer.push(
244 + `\n\n${loc.filename}:${loc.start.line}:${loc.start.column}\n`,
245 + );
246 + buffer.push(codeFrame);
247 + buffer.push('\n\n');
248 }
249 return buffer.join('');
250 }
251
252 toString(): string {
116 - return this.printErrorMessage();
253 + const buffer = [printErrorSummary(this.severity, this.reason)];
254 + if (this.description != null) {
255 + buffer.push(`. ${this.description}.`);
256 + }
257 + const loc = this.loc;
258 + if (loc != null && typeof loc !== 'symbol') {
259 + buffer.push(` (${loc.start.line}:${loc.start.column})`);
260 + }
261 + return buffer.join('');
262 }
263 }
264
265 export class CompilerError extends Error {
121 - details: Array<CompilerErrorDetail> = [];
266 + details: Array<CompilerErrorDetail | CompilerDiagnostic> = [];
267
268 static invariant(
269 condition: unknown,
@@ -136,6 +281,12 @@ export class CompilerError extends Error {
281 }
282 }
283
284 + static throwDiagnostic(options: CompilerDiagnosticOptions): never {
285 + const errors = new CompilerError();
286 + errors.pushDiagnostic(new CompilerDiagnostic(options));
287 + throw errors;
288 + }
289 +
290 static throwTodo(
291 options: Omit<CompilerErrorDetailOptions, 'severity'>,
292 ): never {
@@ -210,6 +361,21 @@ export class CompilerError extends Error {
361 return this.name;
362 }
363
364 + printErrorMessage(source: string): string {
365 + return (
366 + `Found ${this.details.length} error${this.details.length === 1 ? '' : 's'}:\n` +
367 + this.details.map(detail => detail.printErrorMessage(source)).join('\n')
368 + );
369 + }
370 +
371 + merge(other: CompilerError): void {
372 + this.details.push(...other.details);
373 + }
374 +
375 + pushDiagnostic(diagnostic: CompilerDiagnostic): void {
376 + this.details.push(diagnostic);
377 + }
378 +
379 push(options: CompilerErrorDetailOptions): CompilerErrorDetail {
380 const detail = new CompilerErrorDetail({
381 reason: options.reason,
@@ -260,3 +426,32 @@ export class CompilerError extends Error {
426 });
427 }
428 }
429 +
430 +function printErrorSummary(severity: ErrorSeverity, message: string): string {
431 + let severityCategory: string;
432 + switch (severity) {
433 + case ErrorSeverity.InvalidConfig:
434 + case ErrorSeverity.InvalidJS:
435 + case ErrorSeverity.InvalidReact:
436 + case ErrorSeverity.UnsupportedJS: {
437 + severityCategory = 'Error';
438 + break;
439 + }
440 + case ErrorSeverity.CannotPreserveMemoization: {
441 + severityCategory = 'Memoization';
442 + break;
443 + }
444 + case ErrorSeverity.Invariant: {
445 + severityCategory = 'Invariant';
446 + break;
447 + }
448 + case ErrorSeverity.Todo: {
449 + severityCategory = 'Todo';
450 + break;
451 + }
452 + default: {
453 + assertExhaustive(severity, `Unexpected severity '${severity}'`);
454 + }
455 + }
456 + return `${severityCategory}: ${message}`;
457 +}
compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Options.ts
+7 -2
@@ -7,7 +7,12 @@
7
8 import * as t from '@babel/types';
9 import {z} from 'zod';
10 -import {CompilerError, CompilerErrorDetailOptions} from '../CompilerError';
10 +import {
11 + CompilerDiagnostic,
12 + CompilerError,
13 + CompilerErrorDetail,
14 + CompilerErrorDetailOptions,
15 +} from '../CompilerError';
16 import {
17 EnvironmentConfig,
18 ExternalFunction,
@@ -224,7 +229,7 @@ export type LoggerEvent =
229 export type CompileErrorEvent = {
230 kind: 'CompileError';
231 fnLoc: t.SourceLocation | null;
227 - detail: CompilerErrorDetailOptions;
232 + detail: CompilerErrorDetail | CompilerDiagnostic;
233 };
234 export type CompileDiagnosticEvent = {
235 kind: 'CompileDiagnostic';
compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Program.ts
+1 -1
@@ -181,7 +181,7 @@ function logError(
181 context.opts.logger.logEvent(context.filename, {
182 kind: 'CompileError',
183 fnLoc,
184 - detail: detail.options,
184 + detail,
185 });
186 }
187 } else {
compiler/packages/babel-plugin-react-compiler/src/Entrypoint/ValidateNoUntransformedReferences.ts
+34 -28
@@ -8,32 +8,27 @@
8 import {NodePath} from '@babel/core';
9 import * as t from '@babel/types';
10
11 -import {
12 - CompilerError,
13 - CompilerErrorDetailOptions,
14 - EnvironmentConfig,
15 - ErrorSeverity,
16 - Logger,
17 -} from '..';
11 +import {CompilerError, EnvironmentConfig, ErrorSeverity, Logger} from '..';
12 import {getOrInsertWith} from '../Utils/utils';
19 -import {Environment} from '../HIR';
13 +import {Environment, GeneratedSource} from '../HIR';
14 import {DEFAULT_EXPORT} from '../HIR/Environment';
15 import {CompileProgramMetadata} from './Program';
16 +import {CompilerDiagnostic, CompilerDiagnosticOptions} from '../CompilerError';
17
18 function throwInvalidReact(
24 - options: Omit<CompilerErrorDetailOptions, 'severity'>,
19 + options: Omit<CompilerDiagnosticOptions, 'severity'>,
20 {logger, filename}: TraversalState,
21 ): never {
27 - const detail: CompilerErrorDetailOptions = {
28 - ...options,
22 + const detail: CompilerDiagnosticOptions = {
23 severity: ErrorSeverity.InvalidReact,
24 + ...options,
25 };
26 logger?.logEvent(filename, {
27 kind: 'CompileError',
28 fnLoc: null,
34 - detail,
29 + detail: new CompilerDiagnostic(detail),
30 });
36 - CompilerError.throw(detail);
31 + CompilerError.throwDiagnostic(detail);
32 }
33
34 function isAutodepsSigil(
@@ -97,14 +92,18 @@ function assertValidEffectImportReference(
92 */
93 throwInvalidReact(
94 {
100 - reason:
101 - '[InferEffectDependencies] React Compiler is unable to infer dependencies of this effect. ' +
102 - 'This will break your build! ' +
103 - 'To resolve, either pass your own dependency array or fix reported compiler bailout diagnostics.',
104 - description: maybeErrorDiagnostic
105 - ? `(Bailout reason: ${maybeErrorDiagnostic})`
106 - : null,
107 - loc: parent.node.loc ?? null,
95 + category:
96 + 'Cannot infer dependencies of this effect. This will break your build!',
97 + description:
98 + 'To resolve, either pass a dependency array or fix reported compiler bailout diagnostics.' +
99 + (maybeErrorDiagnostic ? ` ${maybeErrorDiagnostic}` : ''),
100 + details: [
101 + {
102 + kind: 'error',
103 + message: 'Cannot infer dependencies',
104 + loc: parent.node.loc ?? GeneratedSource,
105 + },
106 + ],
107 },
108 context,
109 );
@@ -124,13 +123,20 @@ function assertValidFireImportReference(
123 );
124 throwInvalidReact(
125 {
127 - reason:
128 - '[Fire] Untransformed reference to compiler-required feature. ' +
129 - 'Either remove this `fire` call or ensure it is successfully transformed by the compiler',
130 - description: maybeErrorDiagnostic
131 - ? `(Bailout reason: ${maybeErrorDiagnostic})`
132 - : null,
133 - loc: paths[0].node.loc ?? null,
126 + category:
127 + '[Fire] Untransformed reference to compiler-required feature.',
128 + description:
129 + 'Either remove this `fire` call or ensure it is successfully transformed by the compiler' +
130 + maybeErrorDiagnostic
131 + ? ` ${maybeErrorDiagnostic}`
132 + : '',
133 + details: [
134 + {
135 + kind: 'error',
136 + message: 'Untransformed `fire` call',
137 + loc: paths[0].node.loc ?? GeneratedSource,
138 + },
139 + ],
140 },
141 context,
142 );
compiler/packages/babel-plugin-react-compiler/src/HIR/BuildHIR.ts
+13 -8
@@ -2271,11 +2271,17 @@ function lowerExpression(
2271 });
2272 for (const [name, locations] of Object.entries(fbtLocations)) {
2273 if (locations.length > 1) {
2274 - CompilerError.throwTodo({
2275 - reason: `Support <${tagName}> tags with multiple <${tagName}:${name}> values`,
2276 - loc: locations.at(-1) ?? GeneratedSource,
2277 - description: null,
2278 - suggestions: null,
2274 + CompilerError.throwDiagnostic({
2275 + severity: ErrorSeverity.Todo,
2276 + category: 'Support duplicate fbt tags',
2277 + description: `Support \`<${tagName}>\` tags with multiple \`<${tagName}:${name}>\` values`,
2278 + details: locations.map(loc => {
2279 + return {
2280 + kind: 'error',
2281 + message: `Multiple \`<${tagName}:${name}>\` tags found`,
2282 + loc,
2283 + };
2284 + }),
2285 });
2286 }
2287 }
@@ -3503,9 +3509,8 @@ function lowerFunction(
3509 );
3510 let loweredFunc: HIRFunction;
3511 if (lowering.isErr()) {
3506 - lowering
3507 - .unwrapErr()
3508 - .details.forEach(detail => builder.errors.pushErrorDetail(detail));
3512 + const functionErrors = lowering.unwrapErr();
3513 + builder.errors.merge(functionErrors);
3514 return null;
3515 }
3516 loweredFunc = lowering.unwrap();
compiler/packages/babel-plugin-react-compiler/src/HIR/HIRBuilder.ts
+13 -4
@@ -7,7 +7,7 @@
7
8 import {Binding, NodePath} from '@babel/traverse';
9 import * as t from '@babel/types';
10 -import {CompilerError} from '../CompilerError';
10 +import {CompilerError, ErrorSeverity} from '../CompilerError';
11 import {Environment} from './Environment';
12 import {
13 BasicBlock,
@@ -308,9 +308,18 @@ export default class HIRBuilder {
308
309 resolveBinding(node: t.Identifier): Identifier {
310 if (node.name === 'fbt') {
311 - CompilerError.throwTodo({
312 - reason: 'Support local variables named "fbt"',
313 - loc: node.loc ?? null,
311 + CompilerError.throwDiagnostic({
312 + severity: ErrorSeverity.Todo,
313 + category: 'Support local variables named `fbt`',
314 + description:
315 + 'Local variables named `fbt` may conflict with the fbt plugin and are not yet supported',
316 + details: [
317 + {
318 + kind: 'error',
319 + message: 'Rename to avoid conflict with fbt plugin',
320 + loc: node.loc ?? GeneratedSource,
321 + },
322 + ],
323 });
324 }
325 const originalName = node.name;
compiler/packages/babel-plugin-react-compiler/src/__tests__/envConfig-test.ts
+2 -2
@@ -20,7 +20,7 @@ describe('parseConfigPragma()', () => {
20 validateHooksUsage: 1,
21 } as any);
22 }).toThrowErrorMatchingInlineSnapshot(
23 - `"InvalidConfig: Could not validate environment config. Update React Compiler config to fix the error. Validation error: Expected boolean, received number at "validateHooksUsage""`,
23 + `"Error: Could not validate environment config. Update React Compiler config to fix the error. Validation error: Expected boolean, received number at "validateHooksUsage"."`,
24 );
25 });
26
@@ -38,7 +38,7 @@ describe('parseConfigPragma()', () => {
38 ],
39 } as any);
40 }).toThrowErrorMatchingInlineSnapshot(
41 - `"InvalidConfig: Could not validate environment config. Update React Compiler config to fix the error. Validation error: autodepsIndex must be > 0 at "inferEffectDependencies[0].autodepsIndex""`,
41 + `"Error: Could not validate environment config. Update React Compiler config to fix the error. Validation error: autodepsIndex must be > 0 at "inferEffectDependencies[0].autodepsIndex"."`,
42 );
43 });
44
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error._todo.computed-lval-in-destructure.expect.md
+7 -1
@@ -15,13 +15,19 @@ function Component(props) {
15 ## Error
16
17 ```
18 +Found 1 error:
19 +Todo: (BuildHIR::lowerAssignment) Handle computed properties in ObjectPattern
20 +
21 +error._todo.computed-lval-in-destructure.ts:3:9
22 1 | function Component(props) {
23 2 | const computedKey = props.key;
24 > 3 | const {[computedKey]: x} = props.val;
21 - | ^^^^^^^^^^^^^^^^ Todo: (BuildHIR::lowerAssignment) Handle computed properties in ObjectPattern (3:3)
25 + | ^^^^^^^^^^^^^^^^ (BuildHIR::lowerAssignment) Handle computed properties in ObjectPattern
26 4 |
27 5 | return x;
28 6 | }
29 +
30 +
31 ```
32
33
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.assign-global-in-component-tag-function.expect.md
+7 -1
@@ -15,13 +15,19 @@ function Component() {
15 ## Error
16
17 ```
18 +Found 1 error:
19 +Error: Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render)
20 +
21 +error.assign-global-in-component-tag-function.ts:3:4
22 1 | function Component() {
23 2 | const Foo = () => {
24 > 3 | someGlobal = true;
21 - | ^^^^^^^^^^ InvalidReact: Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render) (3:3)
25 + | ^^^^^^^^^^ Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render)
26 4 | };
27 5 | return <Foo />;
28 6 | }
29 +
30 +
31 ```
32
33
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.assign-global-in-jsx-children.expect.md
+7 -1
@@ -18,13 +18,19 @@ function Component() {
18 ## Error
19
20 ```
21 +Found 1 error:
22 +Error: Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render)
23 +
24 +error.assign-global-in-jsx-children.ts:3:4
25 1 | function Component() {
26 2 | const foo = () => {
27 > 3 | someGlobal = true;
24 - | ^^^^^^^^^^ InvalidReact: Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render) (3:3)
28 + | ^^^^^^^^^^ Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render)
29 4 | };
30 5 | // Children are generally access/called during render, so
31 6 | // modifying a global in a children function is almost
32 +
33 +
34 ```
35
36
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.assign-global-in-jsx-spread-attribute.expect.md
+7 -1
@@ -16,13 +16,19 @@ function Component() {
16 ## Error
17
18 ```
19 +Found 1 error:
20 +Error: Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render)
21 +
22 +error.assign-global-in-jsx-spread-attribute.ts:4:4
23 2 | function Component() {
24 3 | const foo = () => {
25 > 4 | someGlobal = true;
22 - | ^^^^^^^^^^ InvalidReact: Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render) (4:4)
26 + | ^^^^^^^^^^ Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render)
27 5 | };
28 6 | return <div {...foo} />;
29 7 | }
30 +
31 +
32 ```
33
34
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.bailout-on-flow-suppression.expect.md
+9 -1
@@ -16,13 +16,21 @@ function Foo(props) {
16 ## Error
17
18 ```
19 +Found 1 error:
20 +Error: React Compiler has skipped optimizing this component because one or more React rule violations were reported by Flow. React Compiler only works when your components follow all the rules of React, disabling them may result in unexpected or incorrect behavior
21 +
22 +$FlowFixMe[react-rule-hook].
23 +
24 +error.bailout-on-flow-suppression.ts:4:2
25 2 |
26 3 | function Foo(props) {
27 > 4 | // $FlowFixMe[react-rule-hook]
22 - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ InvalidReact: React Compiler has skipped optimizing this component because one or more React rule violations were reported by Flow. React Compiler only works when your components follow all the rules of React, disabling them may result in unexpected or incorrect behavior. $FlowFixMe[react-rule-hook] (4:4)
28 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ React Compiler has skipped optimizing this component because one or more React rule violations were reported by Flow. React Compiler only works when your components follow all the rules of React, disabling them may result in unexpected or incorrect behavior
29 5 | useX();
30 6 | return null;
31 7 | }
32 +
33 +
34 ```
35
36
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.bailout-on-suppression-of-custom-rule.expect.md
+23 -3
@@ -19,15 +19,35 @@ function lowercasecomponent() {
19 ## Error
20
21 ```
22 +Found 2 errors:
23 +Error: React Compiler has skipped optimizing this component because one or more React ESLint rules were disabled. React Compiler only works when your components follow all the rules of React, disabling them may result in unexpected or incorrect behavior
24 +
25 +eslint-disable my-app/react-rule.
26 +
27 +error.bailout-on-suppression-of-custom-rule.ts:3:0
28 1 | // @eslintSuppressionRules:["my-app","react-rule"]
29 2 |
30 > 3 | /* eslint-disable my-app/react-rule */
25 - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ InvalidReact: React Compiler has skipped optimizing this component because one or more React ESLint rules were disabled. React Compiler only works when your components follow all the rules of React, disabling them may result in unexpected or incorrect behavior. eslint-disable my-app/react-rule (3:3)
26 -
27 -InvalidReact: React Compiler has skipped optimizing this component because one or more React ESLint rules were disabled. React Compiler only works when your components follow all the rules of React, disabling them may result in unexpected or incorrect behavior. eslint-disable-next-line my-app/react-rule (7:7)
31 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ React Compiler has skipped optimizing this component because one or more React ESLint rules were disabled. React Compiler only works when your components follow all the rules of React, disabling them may result in unexpected or incorrect behavior
32 4 | function lowercasecomponent() {
33 5 | 'use forget';
34 6 | const x = [];
35 +
36 +
37 +Error: React Compiler has skipped optimizing this component because one or more React ESLint rules were disabled. React Compiler only works when your components follow all the rules of React, disabling them may result in unexpected or incorrect behavior
38 +
39 +eslint-disable-next-line my-app/react-rule.
40 +
41 +error.bailout-on-suppression-of-custom-rule.ts:7:2
42 + 5 | 'use forget';
43 + 6 | const x = [];
44 +> 7 | // eslint-disable-next-line my-app/react-rule
45 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ React Compiler has skipped optimizing this component because one or more React ESLint rules were disabled. React Compiler only works when your components follow all the rules of React, disabling them may result in unexpected or incorrect behavior
46 + 8 | return <div>{x}</div>;
47 + 9 | }
48 + 10 | /* eslint-enable my-app/react-rule */
49 +
50 +
51 ```
52
53
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.bug-old-inference-false-positive-ref-validation-in-use-effect.expect.md
+19 -3
@@ -36,6 +36,10 @@ function Component() {
36 ## Error
37
38 ```
39 +Found 2 errors:
40 +Error: This argument is a function which may reassign or mutate local variables after render, which can cause inconsistent behavior on subsequent renders. Consider using state instead
41 +
42 +error.bug-old-inference-false-positive-ref-validation-in-use-effect.ts:20:12
43 18 | );
44 19 | const ref = useRef(null);
45 > 20 | useEffect(() => {
@@ -47,12 +51,24 @@ function Component() {
51 > 23 | }
52 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
53 > 24 | }, [update]);
50 - | ^^^^ InvalidReact: This argument is a function which may reassign or mutate local variables after render, which can cause inconsistent behavior on subsequent renders. Consider using state instead (20:24)
51 -
52 -InvalidReact: The function modifies a local variable here (14:14)
54 + | ^^^^ This argument is a function which may reassign or mutate local variables after render, which can cause inconsistent behavior on subsequent renders. Consider using state instead
55 25 |
56 26 | return 'ok';
57 27 | }
58 +
59 +
60 +Error: The function modifies a local variable here
61 +
62 +error.bug-old-inference-false-positive-ref-validation-in-use-effect.ts:14:6
63 + 12 | ...partialParams,
64 + 13 | };
65 +> 14 | nextParams.param = 'value';
66 + | ^^^^^^^^^^ The function modifies a local variable here
67 + 15 | console.log(nextParams);
68 + 16 | },
69 + 17 | [params]
70 +
71 +
72 ```
73
74
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.call-args-destructuring-asignment-complex.expect.md
+7 -1
@@ -14,13 +14,19 @@ function Component(props) {
14 ## Error
15
16 ```
17 +Found 1 error:
18 +Invariant: Const declaration cannot be referenced as an expression
19 +
20 +error.call-args-destructuring-asignment-complex.ts:3:9
21 1 | function Component(props) {
22 2 | let x = makeObject();
23 > 3 | x.foo(([[x]] = makeObject()));
20 - | ^^^^^ Invariant: Const declaration cannot be referenced as an expression (3:3)
24 + | ^^^^^ Const declaration cannot be referenced as an expression
25 4 | return x;
26 5 | }
27 6 |
28 +
29 +
30 ```
31
32
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.capitalized-function-call-aliased.expect.md
+9 -1
@@ -14,12 +14,20 @@ function Foo() {
14 ## Error
15
16 ```
17 +Found 1 error:
18 +Error: Capitalized functions are reserved for components, which must be invoked with JSX. If this is a component, render it with JSX. Otherwise, ensure that it has no hook calls and rename it to begin with a lowercase letter. Alternatively, if you know for a fact that this function is not a component, you can allowlist it via the compiler config
19 +
20 +Bar may be a component..
21 +
22 +error.capitalized-function-call-aliased.ts:4:2
23 2 | function Foo() {
24 3 | let x = Bar;
25 > 4 | x(); // ERROR
20 - | ^^^ InvalidReact: Capitalized functions are reserved for components, which must be invoked with JSX. If this is a component, render it with JSX. Otherwise, ensure that it has no hook calls and rename it to begin with a lowercase letter. Alternatively, if you know for a fact that this function is not a component, you can allowlist it via the compiler config. Bar may be a component. (4:4)
26 + | ^^^ Capitalized functions are reserved for components, which must be invoked with JSX. If this is a component, render it with JSX. Otherwise, ensure that it has no hook calls and rename it to begin with a lowercase letter. Alternatively, if you know for a fact that this function is not a component, you can allowlist it via the compiler config
27 5 | }
28 6 |
29 +
30 +
31 ```
32
33
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.capitalized-function-call.expect.md
+9 -1
@@ -15,13 +15,21 @@ function Component() {
15 ## Error
16
17 ```
18 +Found 1 error:
19 +Error: Capitalized functions are reserved for components, which must be invoked with JSX. If this is a component, render it with JSX. Otherwise, ensure that it has no hook calls and rename it to begin with a lowercase letter. Alternatively, if you know for a fact that this function is not a component, you can allowlist it via the compiler config
20 +
21 +SomeFunc may be a component..
22 +
23 +error.capitalized-function-call.ts:3:12
24 1 | // @validateNoCapitalizedCalls
25 2 | function Component() {
26 > 3 | const x = SomeFunc();
21 - | ^^^^^^^^^^ InvalidReact: Capitalized functions are reserved for components, which must be invoked with JSX. If this is a component, render it with JSX. Otherwise, ensure that it has no hook calls and rename it to begin with a lowercase letter. Alternatively, if you know for a fact that this function is not a component, you can allowlist it via the compiler config. SomeFunc may be a component. (3:3)
27 + | ^^^^^^^^^^ Capitalized functions are reserved for components, which must be invoked with JSX. If this is a component, render it with JSX. Otherwise, ensure that it has no hook calls and rename it to begin with a lowercase letter. Alternatively, if you know for a fact that this function is not a component, you can allowlist it via the compiler config
28 4 |
29 5 | return x;
30 6 | }
31 +
32 +
33 ```
34
35
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.capitalized-method-call.expect.md
+9 -1
@@ -15,13 +15,21 @@ function Component() {
15 ## Error
16
17 ```
18 +Found 1 error:
19 +Error: Capitalized functions are reserved for components, which must be invoked with JSX. If this is a component, render it with JSX. Otherwise, ensure that it has no hook calls and rename it to begin with a lowercase letter. Alternatively, if you know for a fact that this function is not a component, you can allowlist it via the compiler config
20 +
21 +SomeFunc may be a component..
22 +
23 +error.capitalized-method-call.ts:3:12
24 1 | // @validateNoCapitalizedCalls
25 2 | function Component() {
26 > 3 | const x = someGlobal.SomeFunc();
21 - | ^^^^^^^^^^^^^^^^^^^^^ InvalidReact: Capitalized functions are reserved for components, which must be invoked with JSX. If this is a component, render it with JSX. Otherwise, ensure that it has no hook calls and rename it to begin with a lowercase letter. Alternatively, if you know for a fact that this function is not a component, you can allowlist it via the compiler config. SomeFunc may be a component. (3:3)
27 + | ^^^^^^^^^^^^^^^^^^^^^ Capitalized functions are reserved for components, which must be invoked with JSX. If this is a component, render it with JSX. Otherwise, ensure that it has no hook calls and rename it to begin with a lowercase letter. Alternatively, if you know for a fact that this function is not a component, you can allowlist it via the compiler config
28 4 |
29 5 | return x;
30 6 | }
31 +
32 +
33 ```
34
35
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.capture-ref-for-mutation.expect.md
+40 -4
@@ -32,19 +32,55 @@ export const FIXTURE_ENTRYPOINT = {
32 ## Error
33
34 ```
35 +Found 4 errors:
36 +Error: This function accesses a ref value (the `current` property), which may not be accessed during render. (https://react.dev/reference/react/useRef)
37 +
38 +error.capture-ref-for-mutation.ts:12:13
39 10 | };
40 11 | const moveLeft = {
41 > 12 | handler: handleKey('left')(),
38 - | ^^^^^^^^^^^^^^^^^ InvalidReact: This function accesses a ref value (the `current` property), which may not be accessed during render. (https://react.dev/reference/react/useRef) (12:12)
42 + | ^^^^^^^^^^^^^^^^^ This function accesses a ref value (the `current` property), which may not be accessed during render. (https://react.dev/reference/react/useRef)
43 + 13 | };
44 + 14 | const moveRight = {
45 + 15 | handler: handleKey('right')(),
46
40 -InvalidReact: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef) (12:12)
47
42 -InvalidReact: This function accesses a ref value (the `current` property), which may not be accessed during render. (https://react.dev/reference/react/useRef) (15:15)
48 +Error: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
49
44 -InvalidReact: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef) (15:15)
50 +error.capture-ref-for-mutation.ts:12:13
51 + 10 | };
52 + 11 | const moveLeft = {
53 +> 12 | handler: handleKey('left')(),
54 + | ^^^^^^^^^^^^^^^^^ Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
55 13 | };
56 14 | const moveRight = {
57 15 | handler: handleKey('right')(),
58 +
59 +
60 +Error: This function accesses a ref value (the `current` property), which may not be accessed during render. (https://react.dev/reference/react/useRef)
61 +
62 +error.capture-ref-for-mutation.ts:15:13
63 + 13 | };
64 + 14 | const moveRight = {
65 +> 15 | handler: handleKey('right')(),
66 + | ^^^^^^^^^^^^^^^^^^ This function accesses a ref value (the `current` property), which may not be accessed during render. (https://react.dev/reference/react/useRef)
67 + 16 | };
68 + 17 | return [moveLeft, moveRight];
69 + 18 | }
70 +
71 +
72 +Error: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
73 +
74 +error.capture-ref-for-mutation.ts:15:13
75 + 13 | };
76 + 14 | const moveRight = {
77 +> 15 | handler: handleKey('right')(),
78 + | ^^^^^^^^^^^^^^^^^^ Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
79 + 16 | };
80 + 17 | return [moveLeft, moveRight];
81 + 18 | }
82 +
83 +
84 ```
85
86
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.conditional-hook-unknown-hook-react-namespace.expect.md
+7 -1
@@ -16,13 +16,19 @@ function Component(props) {
16 ## Error
17
18 ```
19 +Found 1 error:
20 +Error: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
21 +
22 +error.conditional-hook-unknown-hook-react-namespace.ts:4:8
23 2 | let x = null;
24 3 | if (props.cond) {
25 > 4 | x = React.useNonexistentHook();
22 - | ^^^^^^^^^^^^^^^^^^^^^^^^ InvalidReact: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning) (4:4)
26 + | ^^^^^^^^^^^^^^^^^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
27 5 | }
28 6 | return x;
29 7 | }
30 +
31 +
32 ```
33
34
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.conditional-hooks-as-method-call.expect.md
+7 -1
@@ -16,13 +16,19 @@ function Component(props) {
16 ## Error
17
18 ```
19 +Found 1 error:
20 +Error: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
21 +
22 +error.conditional-hooks-as-method-call.ts:4:8
23 2 | let x = null;
24 3 | if (props.cond) {
25 > 4 | x = Foo.useFoo();
22 - | ^^^^^^^^^^ InvalidReact: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning) (4:4)
26 + | ^^^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
27 5 | }
28 6 | return x;
29 7 | }
30 +
31 +
32 ```
33
34
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.context-variable-only-chained-assign.expect.md
+9 -1
@@ -28,13 +28,21 @@ export const FIXTURE_ENTRYPOINT = {
28 ## Error
29
30 ```
31 +Found 1 error:
32 +Error: Reassigning a variable after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead
33 +
34 +Variable `x` cannot be reassigned after render.
35 +
36 +error.context-variable-only-chained-assign.ts:10:19
37 8 | };
38 9 | const fn2 = () => {
39 > 10 | const copy2 = (x = 4);
34 - | ^ InvalidReact: Reassigning a variable after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead. Variable `x` cannot be reassigned after render (10:10)
40 + | ^ Reassigning a variable after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead
41 11 | return [invoke(fn1), copy2, identity(copy2)];
42 12 | };
43 13 | return invoke(fn2);
44 +
45 +
46 ```
47
48
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.declare-reassign-variable-in-function-declaration.expect.md
+9 -1
@@ -17,13 +17,21 @@ function Component() {
17 ## Error
18
19 ```
20 +Found 1 error:
21 +Error: Reassigning a variable after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead
22 +
23 +Variable `x` cannot be reassigned after render.
24 +
25 +error.declare-reassign-variable-in-function-declaration.ts:4:4
26 2 | let x = null;
27 3 | function foo() {
28 > 4 | x = 9;
23 - | ^ InvalidReact: Reassigning a variable after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead. Variable `x` cannot be reassigned after render (4:4)
29 + | ^ Reassigning a variable after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead
30 5 | }
31 6 | const y = bar(foo);
32 7 | return <Child y={y} />;
33 +
34 +
35 ```
36
37
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.default-param-accesses-local.expect.md
+7 -1
@@ -22,6 +22,10 @@ export const FIXTURE_ENTRYPOINT = {
22 ## Error
23
24 ```
25 +Found 1 error:
26 +Todo: (BuildHIR::node.lowerReorderableExpression) Expression type `ArrowFunctionExpression` cannot be safely reordered
27 +
28 +error.default-param-accesses-local.ts:3:6
29 1 | function Component(
30 2 | x,
31 > 3 | y = () => {
@@ -29,10 +33,12 @@ export const FIXTURE_ENTRYPOINT = {
33 > 4 | return x;
34 | ^^^^^^^^^^^^^
35 > 5 | }
32 - | ^^^^ Todo: (BuildHIR::node.lowerReorderableExpression) Expression type `ArrowFunctionExpression` cannot be safely reordered (3:5)
36 + | ^^^^ (BuildHIR::node.lowerReorderableExpression) Expression type `ArrowFunctionExpression` cannot be safely reordered
37 6 | ) {
38 7 | return y();
39 8 | }
40 +
41 +
42 ```
43
44
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.dont-hoist-inline-reference.expect.md
+9 -1
@@ -19,13 +19,21 @@ export const FIXTURE_ENTRYPOINT = {
19 ## Error
20
21 ```
22 +Found 1 error:
23 +Todo: [hoisting] EnterSSA: Expected identifier to be defined before being used
24 +
25 +Identifier x$1 is undefined.
26 +
27 +error.dont-hoist-inline-reference.ts:3:2
28 1 | import {identity} from 'shared-runtime';
29 2 | function useInvalid() {
30 > 3 | const x = identity(x);
25 - | ^^^^^^^^^^^^^^^^^^^^^^ Todo: [hoisting] EnterSSA: Expected identifier to be defined before being used. Identifier x$1 is undefined (3:3)
31 + | ^^^^^^^^^^^^^^^^^^^^^^ [hoisting] EnterSSA: Expected identifier to be defined before being used
32 4 | return x;
33 5 | }
34 6 |
35 +
36 +
37 ```
38
39
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.emit-freeze-conflicting-global.expect.md
+9 -1
@@ -15,13 +15,21 @@ function useFoo(props) {
15 ## Error
16
17 ```
18 +Found 1 error:
19 +Todo: Encountered conflicting global in generated program
20 +
21 +Conflict from local binding __DEV__.
22 +
23 +error.emit-freeze-conflicting-global.ts:3:8
24 1 | // @enableEmitFreeze @instrumentForget
25 2 | function useFoo(props) {
26 > 3 | const __DEV__ = 'conflicting global';
21 - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Todo: Encountered conflicting global in generated program. Conflict from local binding __DEV__ (3:3)
27 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Encountered conflicting global in generated program
28 4 | console.log(__DEV__);
29 5 | return foo(props.x);
30 6 | }
31 +
32 +
33 ```
34
35
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.function-expression-references-variable-its-assigned-to.expect.md
+9 -1
@@ -15,13 +15,21 @@ function Component() {
15 ## Error
16
17 ```
18 +Found 1 error:
19 +Error: Reassigning a variable after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead
20 +
21 +Variable `callback` cannot be reassigned after render.
22 +
23 +error.function-expression-references-variable-its-assigned-to.ts:3:4
24 1 | function Component() {
25 2 | let callback = () => {
26 > 3 | callback = null;
21 - | ^^^^^^^^ InvalidReact: Reassigning a variable after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead. Variable `callback` cannot be reassigned after render (3:3)
27 + | ^^^^^^^^ Reassigning a variable after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead
28 4 | };
29 5 | return <div onClick={callback} />;
30 6 | }
31 +
32 +
33 ```
34
35
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.hoist-optional-member-expression-with-conditional-optional.expect.md
+9 -1
@@ -24,6 +24,12 @@ function Component(props) {
24 ## Error
25
26 ```
27 +Found 1 error:
28 +Memoization: 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
29 +
30 +The inferred dependency was `props.items`, but the source dependencies were [props?.items, props.cond]. Inferred different dependency than source.
31 +
32 +error.hoist-optional-member-expression-with-conditional-optional.ts:4:23
33 2 | import {ValidateMemoization} from 'shared-runtime';
34 3 | function Component(props) {
35 > 4 | const data = useMemo(() => {
@@ -41,10 +47,12 @@ function Component(props) {
47 > 10 | return x;
48 | ^^^^^^^^^^^^^^^^^
49 > 11 | }, [props?.items, props.cond]);
44 - | ^^^^ CannotPreserveMemoization: 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 (4:11)
50 + | ^^^^ 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
51 12 | return (
52 13 | <ValidateMemoization inputs={[props?.items, props.cond]} output={data} />
53 14 | );
54 +
55 +
56 ```
57
58
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.hoist-optional-member-expression-with-conditional.expect.md
+9 -1
@@ -24,6 +24,12 @@ function Component(props) {
24 ## Error
25
26 ```
27 +Found 1 error:
28 +Memoization: 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
29 +
30 +The inferred dependency was `props.items`, but the source dependencies were [props?.items, props.cond]. Inferred different dependency than source.
31 +
32 +error.hoist-optional-member-expression-with-conditional.ts:4:23
33 2 | import {ValidateMemoization} from 'shared-runtime';
34 3 | function Component(props) {
35 > 4 | const data = useMemo(() => {
@@ -41,10 +47,12 @@ function Component(props) {
47 > 10 | return x;
48 | ^^^^^^^^^^^^^^^^^
49 > 11 | }, [props?.items, props.cond]);
44 - | ^^^^ CannotPreserveMemoization: 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 (4:11)
50 + | ^^^^ 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
51 12 | return (
52 13 | <ValidateMemoization inputs={[props?.items, props.cond]} output={data} />
53 14 | );
54 +
55 +
56 ```
57
58
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.hoisting-simple-function-declaration.expect.md
+7 -1
@@ -24,6 +24,10 @@ export const FIXTURE_ENTRYPOINT = {
24 ## Error
25
26 ```
27 +Found 1 error:
28 +Todo: Support functions with unreachable code that may contain hoisted declarations
29 +
30 +error.hoisting-simple-function-declaration.ts:6:2
31 4 | }
32 5 | return baz(); // OK: FuncDecls are HoistableDeclarations that have both declaration and value hoisting
33 > 6 | function baz() {
@@ -31,10 +35,12 @@ export const FIXTURE_ENTRYPOINT = {
35 > 7 | return bar();
36 | ^^^^^^^^^^^^^^^^^
37 > 8 | }
34 - | ^^^^ Todo: Support functions with unreachable code that may contain hoisted declarations (6:8)
38 + | ^^^^ Support functions with unreachable code that may contain hoisted declarations
39 9 | }
40 10 |
41 11 | export const FIXTURE_ENTRYPOINT = {
42 +
43 +
44 ```
45
46
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.hook-call-freezes-captured-identifier.expect.md
+7 -1
@@ -29,13 +29,19 @@ export const FIXTURE_ENTRYPOINT = {
29 ## Error
30
31 ```
32 +Found 1 error:
33 +Error: Updating a value previously passed as an argument to a hook is not allowed. Consider moving the mutation before calling the hook
34 +
35 +error.hook-call-freezes-captured-identifier.ts:13:2
36 11 | });
37 12 |
38 > 13 | x.value += count;
35 - | ^ InvalidReact: Updating a value previously passed as an argument to a hook is not allowed. Consider moving the mutation before calling the hook (13:13)
39 + | ^ Updating a value previously passed as an argument to a hook is not allowed. Consider moving the mutation before calling the hook
40 14 | return <Stringify x={x} cb={cb} />;
41 15 | }
42 16 |
43 +
44 +
45 ```
46
47
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.hook-call-freezes-captured-memberexpr.expect.md
+7 -1
@@ -29,13 +29,19 @@ export const FIXTURE_ENTRYPOINT = {
29 ## Error
30
31 ```
32 +Found 1 error:
33 +Error: Updating a value previously passed as an argument to a hook is not allowed. Consider moving the mutation before calling the hook
34 +
35 +error.hook-call-freezes-captured-memberexpr.ts:13:2
36 11 | });
37 12 |
38 > 13 | x.value += count;
35 - | ^ InvalidReact: Updating a value previously passed as an argument to a hook is not allowed. Consider moving the mutation before calling the hook (13:13)
39 + | ^ Updating a value previously passed as an argument to a hook is not allowed. Consider moving the mutation before calling the hook
40 14 | return <Stringify x={x} cb={cb} />;
41 15 | }
42 16 |
43 +
44 +
45 ```
46
47
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.hook-property-load-local-hook.expect.md
+19 -3
@@ -23,15 +23,31 @@ export const FIXTURE_ENTRYPOINT = {
23 ## Error
24
25 ```
26 +Found 2 errors:
27 +Error: Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values
28 +
29 +error.hook-property-load-local-hook.ts:7:12
30 5 |
31 6 | function Foo() {
32 > 7 | let bar = useFoo.useBar;
29 - | ^^^^^^^^^^^^^ InvalidReact: Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values (7:7)
30 -
31 -InvalidReact: Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values (8:8)
33 + | ^^^^^^^^^^^^^ Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values
34 8 | return bar();
35 9 | }
36 10 |
37 +
38 +
39 +Error: Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values
40 +
41 +error.hook-property-load-local-hook.ts:8:9
42 + 6 | function Foo() {
43 + 7 | let bar = useFoo.useBar;
44 +> 8 | return bar();
45 + | ^^^ Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values
46 + 9 | }
47 + 10 |
48 + 11 | export const FIXTURE_ENTRYPOINT = {
49 +
50 +
51 ```
52
53
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.hook-ref-value.expect.md
+18 -2
@@ -20,15 +20,31 @@ export const FIXTURE_ENTRYPOINT = {
20 ## Error
21
22 ```
23 +Found 2 errors:
24 +Error: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
25 +
26 +error.hook-ref-value.ts:5:23
27 3 | function Component(props) {
28 4 | const ref = useRef();
29 > 5 | useEffect(() => {}, [ref.current]);
26 - | ^^^^^^^^^^^ InvalidReact: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef) (5:5)
30 + | ^^^^^^^^^^^ Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
31 + 6 | }
32 + 7 |
33 + 8 | export const FIXTURE_ENTRYPOINT = {
34 +
35 +
36 +Error: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
37
28 -InvalidReact: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef) (5:5)
38 +error.hook-ref-value.ts:5:23
39 + 3 | function Component(props) {
40 + 4 | const ref = useRef();
41 +> 5 | useEffect(() => {}, [ref.current]);
42 + | ^^^^^^^^^^^ Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
43 6 | }
44 7 |
45 8 | export const FIXTURE_ENTRYPOINT = {
46 +
47 +
48 ```
49
50
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-ReactUseMemo-async-callback.expect.md
+7 -1
@@ -15,16 +15,22 @@ function component(a, b) {
15 ## Error
16
17 ```
18 +Found 1 error:
19 +Error: useMemo callbacks may not be async or generator functions
20 +
21 +error.invalid-ReactUseMemo-async-callback.ts:2:24
22 1 | function component(a, b) {
23 > 2 | let x = React.useMemo(async () => {
24 | ^^^^^^^^^^^^^
25 > 3 | await a;
26 | ^^^^^^^^^^^^
27 > 4 | }, []);
24 - | ^^^^ InvalidReact: useMemo callbacks may not be async or generator functions (2:4)
28 + | ^^^^ useMemo callbacks may not be async or generator functions
29 5 | return x;
30 6 | }
31 7 |
32 +
33 +
34 ```
35
36
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-access-ref-during-render.expect.md
+7 -1
@@ -15,13 +15,19 @@ function Component(props) {
15 ## Error
16
17 ```
18 +Found 1 error:
19 +Error: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
20 +
21 +error.invalid-access-ref-during-render.ts:4:16
22 2 | function Component(props) {
23 3 | const ref = useRef(null);
24 > 4 | const value = ref.current;
21 - | ^^^^^^^^^^^ InvalidReact: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef) (4:4)
25 + | ^^^^^^^^^^^ Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
26 5 | return value;
27 6 | }
28 7 |
29 +
30 +
31 ```
32
33
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-aliased-ref-in-callback-invoked-during-render-.expect.md
+7 -1
@@ -19,12 +19,18 @@ function Component(props) {
19 ## Error
20
21 ```
22 +Found 1 error:
23 +Error: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
24 +
25 +error.invalid-aliased-ref-in-callback-invoked-during-render-.ts:9:33
26 7 | return <Foo item={item} current={current} />;
27 8 | };
28 > 9 | return <Items>{props.items.map(item => renderItem(item))}</Items>;
25 - | ^^^^^^^^^^^^^^^^^^^^^^^^ InvalidReact: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef) (9:9)
29 + | ^^^^^^^^^^^^^^^^^^^^^^^^ Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
30 10 | }
31 11 |
32 +
33 +
34 ```
35
36
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-array-push-frozen.expect.md
+7 -1
@@ -15,13 +15,19 @@ function Component(props) {
15 ## Error
16
17 ```
18 +Found 1 error:
19 +Error: Updating a value used previously in JSX is not allowed. Consider moving the mutation before the JSX
20 +
21 +error.invalid-array-push-frozen.ts:4:2
22 2 | const x = [];
23 3 | <div>{x}</div>;
24 > 4 | x.push(props.value);
21 - | ^ InvalidReact: Updating a value used previously in JSX is not allowed. Consider moving the mutation before the JSX (4:4)
25 + | ^ Updating a value used previously in JSX is not allowed. Consider moving the mutation before the JSX
26 5 | return x;
27 6 | }
28 7 |
29 +
30 +
31 ```
32
33
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-assign-hook-to-local.expect.md
+7 -1
@@ -14,12 +14,18 @@ function Component(props) {
14 ## Error
15
16 ```
17 +Found 1 error:
18 +Error: Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values
19 +
20 +error.invalid-assign-hook-to-local.ts:2:12
21 1 | function Component(props) {
22 > 2 | const x = useState;
19 - | ^^^^^^^^ InvalidReact: Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values (2:2)
23 + | ^^^^^^^^ Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values
24 3 | const state = x(null);
25 4 | return state[0];
26 5 | }
27 +
28 +
29 ```
30
31
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-computed-store-to-frozen-value.expect.md
+7 -1
@@ -16,13 +16,19 @@ function Component(props) {
16 ## Error
17
18 ```
19 +Found 1 error:
20 +Error: Updating a value used previously in JSX is not allowed. Consider moving the mutation before the JSX
21 +
22 +error.invalid-computed-store-to-frozen-value.ts:5:2
23 3 | // freeze
24 4 | <div>{x}</div>;
25 > 5 | x[0] = true;
22 - | ^ InvalidReact: Updating a value used previously in JSX is not allowed. Consider moving the mutation before the JSX (5:5)
26 + | ^ Updating a value used previously in JSX is not allowed. Consider moving the mutation before the JSX
27 6 | return x;
28 7 | }
29 8 |
30 +
31 +
32 ```
33
34
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-conditional-call-aliased-hook-import.expect.md
+7 -1
@@ -18,13 +18,19 @@ function Component(props) {
18 ## Error
19
20 ```
21 +Found 1 error:
22 +Error: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
23 +
24 +error.invalid-conditional-call-aliased-hook-import.ts:6:11
25 4 | let data;
26 5 | if (props.cond) {
27 > 6 | data = readFragment();
24 - | ^^^^^^^^^^^^ InvalidReact: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning) (6:6)
28 + | ^^^^^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
29 7 | }
30 8 | return data;
31 9 | }
32 +
33 +
34 ```
35
36
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-conditional-call-aliased-react-hook.expect.md
+7 -1
@@ -18,13 +18,19 @@ function Component(props) {
18 ## Error
19
20 ```
21 +Found 1 error:
22 +Error: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
23 +
24 +error.invalid-conditional-call-aliased-react-hook.ts:6:10
25 4 | let s;
26 5 | if (props.cond) {
27 > 6 | [s] = state();
24 - | ^^^^^ InvalidReact: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning) (6:6)
28 + | ^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
29 7 | }
30 8 | return s;
31 9 | }
32 +
33 +
34 ```
35
36
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-conditional-call-non-hook-imported-as-hook.expect.md
+7 -1
@@ -18,13 +18,19 @@ function Component(props) {
18 ## Error
19
20 ```
21 +Found 1 error:
22 +Error: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
23 +
24 +error.invalid-conditional-call-non-hook-imported-as-hook.ts:6:11
25 4 | let data;
26 5 | if (props.cond) {
27 > 6 | data = useArray();
24 - | ^^^^^^^^ InvalidReact: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning) (6:6)
28 + | ^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
29 7 | }
30 8 | return data;
31 9 | }
32 +
33 +
34 ```
35
36
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-conditional-setState-in-useMemo.expect.md
+19 -3
@@ -22,15 +22,31 @@ function Component({item, cond}) {
22 ## Error
23
24 ```
25 +Found 2 errors:
26 +Error: Calling setState from useMemo may trigger an infinite loop. (https://react.dev/reference/react/useState)
27 +
28 +error.invalid-conditional-setState-in-useMemo.ts:7:6
29 5 | useMemo(() => {
30 6 | if (cond) {
31 > 7 | setPrevItem(item);
28 - | ^^^^^^^^^^^ InvalidReact: Calling setState from useMemo may trigger an infinite loop. (https://react.dev/reference/react/useState) (7:7)
29 -
30 -InvalidReact: Calling setState from useMemo may trigger an infinite loop. (https://react.dev/reference/react/useState) (8:8)
32 + | ^^^^^^^^^^^ Calling setState from useMemo may trigger an infinite loop. (https://react.dev/reference/react/useState)
33 8 | setState(0);
34 9 | }
35 10 | }, [cond, key, init]);
36 +
37 +
38 +Error: Calling setState from useMemo may trigger an infinite loop. (https://react.dev/reference/react/useState)
39 +
40 +error.invalid-conditional-setState-in-useMemo.ts:8:6
41 + 6 | if (cond) {
42 + 7 | setPrevItem(item);
43 +> 8 | setState(0);
44 + | ^^^^^^^^ Calling setState from useMemo may trigger an infinite loop. (https://react.dev/reference/react/useState)
45 + 9 | }
46 + 10 | }, [cond, key, init]);
47 + 11 |
48 +
49 +
50 ```
51
52
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-delete-computed-property-of-frozen-value.expect.md
+7 -1
@@ -16,13 +16,19 @@ function Component(props) {
16 ## Error
17
18 ```
19 +Found 1 error:
20 +Error: Updating a value used previously in JSX is not allowed. Consider moving the mutation before the JSX
21 +
22 +error.invalid-delete-computed-property-of-frozen-value.ts:5:9
23 3 | // freeze
24 4 | <div>{x}</div>;
25 > 5 | delete x[y];
22 - | ^ InvalidReact: Updating a value used previously in JSX is not allowed. Consider moving the mutation before the JSX (5:5)
26 + | ^ Updating a value used previously in JSX is not allowed. Consider moving the mutation before the JSX
27 6 | return x;
28 7 | }
29 8 |
30 +
31 +
32 ```
33
34
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-delete-property-of-frozen-value.expect.md
+7 -1
@@ -16,13 +16,19 @@ function Component(props) {
16 ## Error
17
18 ```
19 +Found 1 error:
20 +Error: Updating a value used previously in JSX is not allowed. Consider moving the mutation before the JSX
21 +
22 +error.invalid-delete-property-of-frozen-value.ts:5:9
23 3 | // freeze
24 4 | <div>{x}</div>;
25 > 5 | delete x.y;
22 - | ^ InvalidReact: Updating a value used previously in JSX is not allowed. Consider moving the mutation before the JSX (5:5)
26 + | ^ Updating a value used previously in JSX is not allowed. Consider moving the mutation before the JSX
27 6 | return x;
28 7 | }
29 8 |
30 +
31 +
32 ```
33
34
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-destructure-assignment-to-global.expect.md
+7 -1
@@ -13,12 +13,18 @@ function useFoo(props) {
13 ## Error
14
15 ```
16 +Found 1 error:
17 +Error: Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render)
18 +
19 +error.invalid-destructure-assignment-to-global.ts:2:3
20 1 | function useFoo(props) {
21 > 2 | [x] = props;
18 - | ^ InvalidReact: Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render) (2:2)
22 + | ^ Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render)
23 3 | return {x};
24 4 | }
25 5 |
26 +
27 +
28 ```
29
30
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-destructure-to-local-global-variables.expect.md
+7 -1
@@ -15,13 +15,19 @@ function Component(props) {
15 ## Error
16
17 ```
18 +Found 1 error:
19 +Error: Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render)
20 +
21 +error.invalid-destructure-to-local-global-variables.ts:3:6
22 1 | function Component(props) {
23 2 | let a;
24 > 3 | [a, b] = props.value;
21 - | ^ InvalidReact: Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render) (3:3)
25 + | ^ Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render)
26 4 |
27 5 | return [a, b];
28 6 | }
29 +
30 +
31 ```
32
33
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-disallow-mutating-ref-in-render.expect.md
+7 -1
@@ -16,13 +16,19 @@ function Component() {
16 ## Error
17
18 ```
19 +Found 1 error:
20 +Error: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
21 +
22 +error.invalid-disallow-mutating-ref-in-render.ts:4:2
23 2 | function Component() {
24 3 | const ref = useRef(null);
25 > 4 | ref.current = false;
22 - | ^^^^^^^^^^^ InvalidReact: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef) (4:4)
26 + | ^^^^^^^^^^^ Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
27 5 |
28 6 | return <button ref={ref} />;
29 7 | }
30 +
31 +
32 ```
33
34
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-disallow-mutating-refs-in-render-transitive.expect.md
+18 -2
@@ -21,15 +21,31 @@ function Component() {
21 ## Error
22
23 ```
24 +Found 2 errors:
25 +Error: This function accesses a ref value (the `current` property), which may not be accessed during render. (https://react.dev/reference/react/useRef)
26 +
27 +error.invalid-disallow-mutating-refs-in-render-transitive.ts:9:2
28 7 | };
29 8 | const changeRef = setRef;
30 > 9 | changeRef();
27 - | ^^^^^^^^^ InvalidReact: This function accesses a ref value (the `current` property), which may not be accessed during render. (https://react.dev/reference/react/useRef) (9:9)
31 + | ^^^^^^^^^ This function accesses a ref value (the `current` property), which may not be accessed during render. (https://react.dev/reference/react/useRef)
32 + 10 |
33 + 11 | return <button ref={ref} />;
34 + 12 | }
35 +
36 +
37 +Error: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
38
29 -InvalidReact: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef) (9:9)
39 +error.invalid-disallow-mutating-refs-in-render-transitive.ts:9:2
40 + 7 | };
41 + 8 | const changeRef = setRef;
42 +> 9 | changeRef();
43 + | ^^^^^^^^^ Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
44 10 |
45 11 | return <button ref={ref} />;
46 12 | }
47 +
48 +
49 ```
50
51
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-eval-unsupported.expect.md
+9 -1
@@ -13,12 +13,20 @@ function Component(props) {
13 ## Error
14
15 ```
16 +Found 1 error:
17 +Error: The 'eval' function is not supported
18 +
19 +Eval is an anti-pattern in JavaScript, and the code executed cannot be evaluated by React Compiler.
20 +
21 +error.invalid-eval-unsupported.ts:2:2
22 1 | function Component(props) {
23 > 2 | eval('props.x = true');
18 - | ^^^^ UnsupportedJS: The 'eval' function is not supported. Eval is an anti-pattern in JavaScript, and the code executed cannot be evaluated by React Compiler (2:2)
24 + | ^^^^ The 'eval' function is not supported
25 3 | return <div />;
26 4 | }
27 5 |
28 +
29 +
30 ```
31
32
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-function-expression-mutates-immutable-value.expect.md
+9 -1
@@ -18,13 +18,21 @@ function Component(props) {
18 ## Error
19
20 ```
21 +Found 1 error:
22 +Error: Mutating a value returned from 'useState()', which should not be mutated. Use the setter function to update instead
23 +
24 +Found mutation of `x`.
25 +
26 +error.invalid-function-expression-mutates-immutable-value.ts:5:4
27 3 | const onChange = e => {
28 4 | // INVALID! should use copy-on-write and pass the new value
29 > 5 | x.value = e.target.value;
24 - | ^ InvalidReact: Mutating a value returned from 'useState()', which should not be mutated. Use the setter function to update instead. Found mutation of `x` (5:5)
30 + | ^ Mutating a value returned from 'useState()', which should not be mutated. Use the setter function to update instead
31 6 | setX(x);
32 7 | };
33 8 | return <input value={x.value} onChange={onChange} />;
34 +
35 +
36 ```
37
38
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-global-reassignment-indirect.expect.md
+7 -1
@@ -35,13 +35,19 @@ export const FIXTURE_ENTRYPOINT = {
35 ## Error
36
37 ```
38 +Found 1 error:
39 +Error: Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render)
40 +
41 +error.invalid-global-reassignment-indirect.ts:9:4
42 7 |
43 8 | const setGlobal = () => {
44 > 9 | someGlobal = true;
41 - | ^^^^^^^^^^ InvalidReact: Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render) (9:9)
45 + | ^^^^^^^^^^ Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render)
46 10 | };
47 11 | const indirectSetGlobal = () => {
48 12 | setGlobal();
49 +
50 +
51 ```
52
53
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-hoisting-setstate.expect.md
+23 -3
@@ -38,15 +38,35 @@ export const FIXTURE_ENTRYPOINT = {
38 ## Error
39
40 ```
41 +Found 2 errors:
42 +Error: This variable is accessed before it is declared, which may prevent it from updating as the assigned value changes over time
43 +
44 +Variable `setState` is accessed before it is declared.
45 +
46 +error.invalid-hoisting-setstate.ts:19:18
47 17 | * $2 = Function context=setState
48 18 | */
49 > 19 | useEffect(() => setState(2), []);
44 - | ^^^^^^^^ InvalidReact: This variable is accessed before it is declared, which may prevent it from updating as the assigned value changes over time. Variable `setState` is accessed before it is declared (19:19)
45 -
46 -InvalidReact: This variable is accessed before it is declared, which prevents the earlier access from updating when this value changes over time. Variable `setState` is accessed before it is declared (21:21)
50 + | ^^^^^^^^ This variable is accessed before it is declared, which may prevent it from updating as the assigned value changes over time
51 20 |
52 21 | const [state, setState] = useState(0);
53 22 | return <Stringify state={state} />;
54 +
55 +
56 +Error: This variable is accessed before it is declared, which prevents the earlier access from updating when this value changes over time
57 +
58 +Variable `setState` is accessed before it is declared.
59 +
60 +error.invalid-hoisting-setstate.ts:21:16
61 + 19 | useEffect(() => setState(2), []);
62 + 20 |
63 +> 21 | const [state, setState] = useState(0);
64 + | ^^^^^^^^ This variable is accessed before it is declared, which prevents the earlier access from updating when this value changes over time
65 + 22 | return <Stringify state={state} />;
66 + 23 | }
67 + 24 |
68 +
69 +
70 ```
71
72
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-hook-function-argument-mutates-local-variable.expect.md
+18 -2
@@ -17,6 +17,10 @@ function useFoo() {
17 ## Error
18
19 ```
20 +Found 2 errors:
21 +Error: This argument is a function which may reassign or mutate local variables after render, which can cause inconsistent behavior on subsequent renders. Consider using state instead
22 +
23 +error.invalid-hook-function-argument-mutates-local-variable.ts:5:10
24 3 | function useFoo() {
25 4 | const cache = new Map();
26 > 5 | useHook(() => {
@@ -24,11 +28,23 @@ function useFoo() {
28 > 6 | cache.set('key', 'value');
29 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
30 > 7 | });
27 - | ^^^^ InvalidReact: This argument is a function which may reassign or mutate local variables after render, which can cause inconsistent behavior on subsequent renders. Consider using state instead (5:7)
31 + | ^^^^ This argument is a function which may reassign or mutate local variables after render, which can cause inconsistent behavior on subsequent renders. Consider using state instead
32 + 8 | }
33 + 9 |
34 +
35 +
36 +Error: The function modifies a local variable here
37
29 -InvalidReact: The function modifies a local variable here (6:6)
38 +error.invalid-hook-function-argument-mutates-local-variable.ts:6:4
39 + 4 | const cache = new Map();
40 + 5 | useHook(() => {
41 +> 6 | cache.set('key', 'value');
42 + | ^^^^^ The function modifies a local variable here
43 + 7 | });
44 8 | }
45 9 |
46 +
47 +
48 ```
49
50
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-impure-functions-in-render.expect.md
+36 -4
@@ -17,17 +17,49 @@ function Component() {
17 ## Error
18
19 ```
20 +Found 3 errors:
21 +Error: Calling an impure function can produce unstable results. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#components-and-hooks-must-be-idempotent)
22 +
23 +`Date.now` is an impure function whose results may change on every call.
24 +
25 +error.invalid-impure-functions-in-render.ts:4:15
26 2 |
27 3 | function Component() {
28 > 4 | const date = Date.now();
23 - | ^^^^^^^^^^ InvalidReact: Calling an impure function can produce unstable results. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#components-and-hooks-must-be-idempotent). `Date.now` is an impure function whose results may change on every call (4:4)
29 + | ^^^^^^^^^^ Calling an impure function can produce unstable results. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#components-and-hooks-must-be-idempotent)
30 + 5 | const now = performance.now();
31 + 6 | const rand = Math.random();
32 + 7 | return <Foo date={date} now={now} rand={rand} />;
33
25 -InvalidReact: Calling an impure function can produce unstable results. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#components-and-hooks-must-be-idempotent). `performance.now` is an impure function whose results may change on every call (5:5)
34
27 -InvalidReact: Calling an impure function can produce unstable results. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#components-and-hooks-must-be-idempotent). `Math.random` is an impure function whose results may change on every call (6:6)
28 - 5 | const now = performance.now();
35 +Error: Calling an impure function can produce unstable results. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#components-and-hooks-must-be-idempotent)
36 +
37 +`performance.now` is an impure function whose results may change on every call.
38 +
39 +error.invalid-impure-functions-in-render.ts:5:14
40 + 3 | function Component() {
41 + 4 | const date = Date.now();
42 +> 5 | const now = performance.now();
43 + | ^^^^^^^^^^^^^^^^^ Calling an impure function can produce unstable results. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#components-and-hooks-must-be-idempotent)
44 6 | const rand = Math.random();
45 7 | return <Foo date={date} now={now} rand={rand} />;
46 + 8 | }
47 +
48 +
49 +Error: Calling an impure function can produce unstable results. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#components-and-hooks-must-be-idempotent)
50 +
51 +`Math.random` is an impure function whose results may change on every call.
52 +
53 +error.invalid-impure-functions-in-render.ts:6:15
54 + 4 | const date = Date.now();
55 + 5 | const now = performance.now();
56 +> 6 | const rand = Math.random();
57 + | ^^^^^^^^^^^^^ Calling an impure function can produce unstable results. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#components-and-hooks-must-be-idempotent)
58 + 7 | return <Foo date={date} now={now} rand={rand} />;
59 + 8 | }
60 + 9 |
61 +
62 +
63 ```
64
65
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-jsx-captures-context-variable.expect.md
+9 -1
@@ -50,13 +50,21 @@ export const FIXTURE_ENTRYPOINT = {
50 ## Error
51
52 ```
53 +Found 1 error:
54 +Error: Updating a value used previously in JSX is not allowed. Consider moving the mutation before the JSX
55 +
56 +Found mutation of `i`.
57 +
58 +error.invalid-jsx-captures-context-variable.ts:22:2
59 20 | />
60 21 | );
61 > 22 | i = i + 1;
56 - | ^ InvalidReact: Updating a value used previously in JSX is not allowed. Consider moving the mutation before the JSX. Found mutation of `i` (22:22)
62 + | ^ Updating a value used previously in JSX is not allowed. Consider moving the mutation before the JSX
63 23 | items.push(
64 24 | <Stringify
65 25 | key={i}
66 +
67 +
68 ```
69
70
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-mutate-after-aliased-freeze.expect.md
+7 -1
@@ -25,13 +25,19 @@ function Component(props) {
25 ## Error
26
27 ```
28 +Found 1 error:
29 +Error: Updating a value used previously in JSX is not allowed. Consider moving the mutation before the JSX
30 +
31 +error.invalid-mutate-after-aliased-freeze.ts:13:2
32 11 | // y is MaybeFrozen at this point, since it may alias to x
33 12 | // (which is the above line freezes)
34 > 13 | y.push(props.p2);
31 - | ^ InvalidReact: Updating a value used previously in JSX is not allowed. Consider moving the mutation before the JSX (13:13)
35 + | ^ Updating a value used previously in JSX is not allowed. Consider moving the mutation before the JSX
36 14 |
37 15 | return <Component x={x} y={y} />;
38 16 | }
39 +
40 +
41 ```
42
43
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-mutate-after-freeze.expect.md
+7 -1
@@ -19,13 +19,19 @@ function Component(props) {
19 ## Error
20
21 ```
22 +Found 1 error:
23 +Error: Updating a value used previously in JSX is not allowed. Consider moving the mutation before the JSX
24 +
25 +error.invalid-mutate-after-freeze.ts:7:2
26 5 |
27 6 | // x is Frozen at this point
28 > 7 | x.push(props.p2);
25 - | ^ InvalidReact: Updating a value used previously in JSX is not allowed. Consider moving the mutation before the JSX (7:7)
29 + | ^ Updating a value used previously in JSX is not allowed. Consider moving the mutation before the JSX
30 8 |
31 9 | return <div>{_}</div>;
32 10 | }
33 +
34 +
35 ```
36
37
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-mutate-context-in-callback.expect.md
+9 -1
@@ -24,13 +24,21 @@ function Component(props) {
24 ## Error
25
26 ```
27 +Found 1 error:
28 +Error: Mutating a value returned from 'useContext()', which should not be mutated
29 +
30 +Found mutation of `FooContext`.
31 +
32 +error.invalid-mutate-context-in-callback.ts:12:4
33 10 | // independently
34 11 | const onClick = () => {
35 > 12 | FooContext.current = true;
30 - | ^^^^^^^^^^ InvalidReact: Mutating a value returned from 'useContext()', which should not be mutated. Found mutation of `FooContext` (12:12)
36 + | ^^^^^^^^^^ Mutating a value returned from 'useContext()', which should not be mutated
37 13 | };
38 14 | return <div onClick={onClick} />;
39 15 | }
40 +
41 +
42 ```
43
44
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-mutate-context.expect.md
+7 -1
@@ -14,13 +14,19 @@ function Component(props) {
14 ## Error
15
16 ```
17 +Found 1 error:
18 +Error: Mutating a value returned from 'useContext()', which should not be mutated
19 +
20 +error.invalid-mutate-context.ts:3:2
21 1 | function Component(props) {
22 2 | const context = useContext(FooContext);
23 > 3 | context.value = props.value;
20 - | ^^^^^^^ InvalidReact: Mutating a value returned from 'useContext()', which should not be mutated (3:3)
24 + | ^^^^^^^ Mutating a value returned from 'useContext()', which should not be mutated
25 4 | return context.value;
26 5 | }
27 6 |
28 +
29 +
30 ```
31
32
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-mutate-props-in-effect-fixpoint.expect.md
+9 -1
@@ -25,13 +25,21 @@ function Component(props) {
25 ## Error
26
27 ```
28 +Found 1 error:
29 +Error: Mutating component props or hook arguments is not allowed. Consider using a local variable instead
30 +
31 +Found mutation of `y`.
32 +
33 +error.invalid-mutate-props-in-effect-fixpoint.ts:10:4
34 8 | let y = x;
35 9 | let mutateProps = () => {
36 > 10 | y.foo = true;
31 - | ^ InvalidReact: Mutating component props or hook arguments is not allowed. Consider using a local variable instead. Found mutation of `y` (10:10)
37 + | ^ Mutating component props or hook arguments is not allowed. Consider using a local variable instead
38 11 | };
39 12 | let mutatePropsIndirect = () => {
40 13 | mutateProps();
41 +
42 +
43 ```
44
45
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-mutate-props-via-for-of-iterator.expect.md
+7 -1
@@ -17,13 +17,19 @@ function Component(props) {
17 ## Error
18
19 ```
20 +Found 1 error:
21 +Error: Mutating component props or hook arguments is not allowed. Consider using a local variable instead
22 +
23 +error.invalid-mutate-props-via-for-of-iterator.ts:4:4
24 2 | const items = [];
25 3 | for (const x of props.items) {
26 > 4 | x.modified = true;
23 - | ^ InvalidReact: Mutating component props or hook arguments is not allowed. Consider using a local variable instead (4:4)
27 + | ^ Mutating component props or hook arguments is not allowed. Consider using a local variable instead
28 5 | items.push(x);
29 6 | }
30 7 | return items;
31 +
32 +
33 ```
34
35
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-mutation-in-closure.expect.md
+9 -1
@@ -16,13 +16,21 @@ function useInvalidMutation(options) {
16 ## Error
17
18 ```
19 +Found 1 error:
20 +Error: Mutating component props or hook arguments is not allowed. Consider using a local variable instead
21 +
22 +Found mutation of `options`.
23 +
24 +error.invalid-mutation-in-closure.ts:4:4
25 2 | function test() {
26 3 | foo(options.foo); // error should not point on this line
27 > 4 | options.foo = 'bar';
22 - | ^^^^^^^ InvalidReact: Mutating component props or hook arguments is not allowed. Consider using a local variable instead. Found mutation of `options` (4:4)
28 + | ^^^^^^^ Mutating component props or hook arguments is not allowed. Consider using a local variable instead
29 5 | }
30 6 | return test;
31 7 | }
32 +
33 +
34 ```
35
36
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-mutation-of-possible-props-phi-indirect.expect.md
+9 -1
@@ -19,13 +19,21 @@ function Component(props) {
19 ## Error
20
21 ```
22 +Found 1 error:
23 +Error: Writing to a variable defined outside a component or hook is not allowed. Consider using an effect
24 +
25 +Found mutation of `x`.
26 +
27 +error.invalid-mutation-of-possible-props-phi-indirect.ts:4:4
28 2 | let x = cond ? someGlobal : props.foo;
29 3 | const mutatePhiThatCouldBeProps = () => {
30 > 4 | x.y = true;
25 - | ^ InvalidReact: Writing to a variable defined outside a component or hook is not allowed. Consider using an effect. Found mutation of `x` (4:4)
31 + | ^ Writing to a variable defined outside a component or hook is not allowed. Consider using an effect
32 5 | };
33 6 | const indirectMutateProps = () => {
34 7 | mutatePhiThatCouldBeProps();
35 +
36 +
37 ```
38
39
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-nested-function-reassign-local-variable-in-effect.expect.md
+9 -1
@@ -46,13 +46,21 @@ function Component() {
46 ## Error
47
48 ```
49 +Found 1 error:
50 +Error: Reassigning a variable after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead
51 +
52 +Variable `local` cannot be reassigned after render.
53 +
54 +error.invalid-nested-function-reassign-local-variable-in-effect.ts:7:6
55 5 | // Create the reassignment function inside another function, then return it
56 6 | const reassignLocal = newValue => {
57 > 7 | local = newValue;
52 - | ^^^^^ InvalidReact: Reassigning a variable after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead. Variable `local` cannot be reassigned after render (7:7)
58 + | ^^^^^ Reassigning a variable after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead
59 8 | };
60 9 | return reassignLocal;
61 10 | };
62 +
63 +
64 ```
65
66
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-non-imported-reanimated-shared-value-writes.expect.md
+9 -1
@@ -24,13 +24,21 @@ function SomeComponent() {
24 ## Error
25
26 ```
27 +Found 1 error:
28 +Error: Updating a value returned from a hook is not allowed. Consider moving the mutation into the hook where the value is constructed
29 +
30 +Found mutation of `sharedVal`.
31 +
32 +error.invalid-non-imported-reanimated-shared-value-writes.ts:11:22
33 9 | return (
34 10 | <Button
35 > 11 | onPress={() => (sharedVal.value = Math.random())}
30 - | ^^^^^^^^^ InvalidReact: Updating a value returned from a hook is not allowed. Consider moving the mutation into the hook where the value is constructed. Found mutation of `sharedVal` (11:11)
36 + | ^^^^^^^^^ Updating a value returned from a hook is not allowed. Consider moving the mutation into the hook where the value is constructed
37 12 | title="Randomize"
38 13 | />
39 14 | );
40 +
41 +
42 ```
43
44
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-optional-member-expression-as-memo-dep-non-optional-in-body.expect.md
+9 -1
@@ -18,6 +18,12 @@ function Component(props) {
18 ## Error
19
20 ```
21 +Found 1 error:
22 +Memoization: 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
23 +
24 +The inferred dependency was `props.items.edges.nodes`, but the source dependencies were [props.items?.edges?.nodes]. Inferred different dependency than source.
25 +
26 +error.invalid-optional-member-expression-as-memo-dep-non-optional-in-body.ts:3:23
27 1 | // @validatePreserveExistingMemoizationGuarantees
28 2 | function Component(props) {
29 > 3 | const data = useMemo(() => {
@@ -29,10 +35,12 @@ function Component(props) {
35 > 6 | // deps are optional
36 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
37 > 7 | }, [props.items?.edges?.nodes]);
32 - | ^^^^ CannotPreserveMemoization: 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 (3:7)
38 + | ^^^^ 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
39 8 | return <Foo data={data} />;
40 9 | }
41 10 |
42 +
43 +
44 ```
45
46
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-pass-hook-as-call-arg.expect.md
+7 -1
@@ -12,11 +12,17 @@ function Component(props) {
12 ## Error
13
14 ```
15 +Found 1 error:
16 +Error: Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values
17 +
18 +error.invalid-pass-hook-as-call-arg.ts:2:13
19 1 | function Component(props) {
20 > 2 | return foo(useFoo);
17 - | ^^^^^^ InvalidReact: Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values (2:2)
21 + | ^^^^^^ Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values
22 3 | }
23 4 |
24 +
25 +
26 ```
27
28
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-pass-hook-as-prop.expect.md
+7 -1
@@ -12,11 +12,17 @@ function Component(props) {
12 ## Error
13
14 ```
15 +Found 1 error:
16 +Error: Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values
17 +
18 +error.invalid-pass-hook-as-prop.ts:2:21
19 1 | function Component(props) {
20 > 2 | return <Child foo={useFoo} />;
17 - | ^^^^^^ InvalidReact: Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values (2:2)
21 + | ^^^^^^ Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values
22 3 | }
23 4 |
24 +
25 +
26 ```
27
28
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-pass-mutable-function-as-prop.expect.md
+19 -3
@@ -17,14 +17,30 @@ function Component() {
17 ## Error
18
19 ```
20 +Found 2 errors:
21 +Error: This argument is a function which may reassign or mutate local variables after render, which can cause inconsistent behavior on subsequent renders. Consider using state instead
22 +
23 +error.invalid-pass-mutable-function-as-prop.ts:7:18
24 5 | cache.set('key', 'value');
25 6 | };
26 > 7 | return <Foo fn={fn} />;
23 - | ^^ InvalidReact: This argument is a function which may reassign or mutate local variables after render, which can cause inconsistent behavior on subsequent renders. Consider using state instead (7:7)
24 -
25 -InvalidReact: The function modifies a local variable here (5:5)
27 + | ^^ This argument is a function which may reassign or mutate local variables after render, which can cause inconsistent behavior on subsequent renders. Consider using state instead
28 8 | }
29 9 |
30 +
31 +
32 +Error: The function modifies a local variable here
33 +
34 +error.invalid-pass-mutable-function-as-prop.ts:5:4
35 + 3 | const cache = new Map();
36 + 4 | const fn = () => {
37 +> 5 | cache.set('key', 'value');
38 + | ^^^^^ The function modifies a local variable here
39 + 6 | };
40 + 7 | return <Foo fn={fn} />;
41 + 8 | }
42 +
43 +
44 ```
45
46
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-pass-ref-to-function.expect.md
+7 -1
@@ -15,13 +15,19 @@ function Component(props) {
15 ## Error
16
17 ```
18 +Found 1 error:
19 +Error: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
20 +
21 +error.invalid-pass-ref-to-function.ts:4:16
22 2 | function Component(props) {
23 3 | const ref = useRef(null);
24 > 4 | const x = foo(ref);
21 - | ^^^ InvalidReact: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef) (4:4)
25 + | ^^^ Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
26 5 | return x.current;
27 6 | }
28 7 |
29 +
30 +
31 ```
32
33
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-prop-mutation-indirect.expect.md
+9 -1
@@ -18,13 +18,21 @@ function Component(props) {
18 ## Error
19
20 ```
21 +Found 1 error:
22 +Error: Mutating component props or hook arguments is not allowed. Consider using a local variable instead
23 +
24 +Found mutation of `props`.
25 +
26 +error.invalid-prop-mutation-indirect.ts:3:4
27 1 | function Component(props) {
28 2 | const f = () => {
29 > 3 | props.value = true;
24 - | ^^^^^ InvalidReact: Mutating component props or hook arguments is not allowed. Consider using a local variable instead. Found mutation of `props` (3:3)
30 + | ^^^^^ Mutating component props or hook arguments is not allowed. Consider using a local variable instead
31 4 | };
32 5 | const g = () => {
33 6 | f();
34 +
35 +
36 ```
37
38
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-property-store-to-frozen-value.expect.md
+7 -1
@@ -16,13 +16,19 @@ function Component(props) {
16 ## Error
17
18 ```
19 +Found 1 error:
20 +Error: Updating a value used previously in JSX is not allowed. Consider moving the mutation before the JSX
21 +
22 +error.invalid-property-store-to-frozen-value.ts:5:2
23 3 | // freeze
24 4 | <div>{x}</div>;
25 > 5 | x.y = true;
22 - | ^ InvalidReact: Updating a value used previously in JSX is not allowed. Consider moving the mutation before the JSX (5:5)
26 + | ^ Updating a value used previously in JSX is not allowed. Consider moving the mutation before the JSX
27 6 | return x;
28 7 | }
29 8 |
30 +
31 +
32 ```
33
34
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-props-mutation-in-effect-indirect.expect.md
+9 -1
@@ -18,13 +18,21 @@ function Component(props) {
18 ## Error
19
20 ```
21 +Found 1 error:
22 +Error: Mutating component props or hook arguments is not allowed. Consider using a local variable instead
23 +
24 +Found mutation of `props`.
25 +
26 +error.invalid-props-mutation-in-effect-indirect.ts:3:4
27 1 | function Component(props) {
28 2 | const mutateProps = () => {
29 > 3 | props.value = true;
24 - | ^^^^^ InvalidReact: Mutating component props or hook arguments is not allowed. Consider using a local variable instead. Found mutation of `props` (3:3)
30 + | ^^^^^ Mutating component props or hook arguments is not allowed. Consider using a local variable instead
31 4 | };
32 5 | const indirectMutateProps = () => {
33 6 | mutateProps();
34 +
35 +
36 ```
37
38
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-read-ref-prop-in-render-destructure.expect.md
+7 -1
@@ -14,13 +14,19 @@ function Component({ref}) {
14 ## Error
15
16 ```
17 +Found 1 error:
18 +Error: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
19 +
20 +error.invalid-read-ref-prop-in-render-destructure.ts:3:16
21 1 | // @validateRefAccessDuringRender @compilationMode:"infer"
22 2 | function Component({ref}) {
23 > 3 | const value = ref.current;
20 - | ^^^^^^^^^^^ InvalidReact: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef) (3:3)
24 + | ^^^^^^^^^^^ Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
25 4 | return <div>{value}</div>;
26 5 | }
27 6 |
28 +
29 +
30 ```
31
32
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-read-ref-prop-in-render-property-load.expect.md
+7 -1
@@ -14,13 +14,19 @@ function Component(props) {
14 ## Error
15
16 ```
17 +Found 1 error:
18 +Error: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
19 +
20 +error.invalid-read-ref-prop-in-render-property-load.ts:3:16
21 1 | // @validateRefAccessDuringRender @compilationMode:"infer"
22 2 | function Component(props) {
23 > 3 | const value = props.ref.current;
20 - | ^^^^^^^^^^^^^^^^^ InvalidReact: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef) (3:3)
24 + | ^^^^^^^^^^^^^^^^^ Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
25 4 | return <div>{value}</div>;
26 5 | }
27 6 |
28 +
29 +
30 ```
31
32
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-reassign-const.expect.md
+9 -1
@@ -13,12 +13,20 @@ function Component() {
13 ## Error
14
15 ```
16 +Found 1 error:
17 +Error: Cannot reassign a `const` variable
18 +
19 +`x` is declared as const.
20 +
21 +error.invalid-reassign-const.ts:3:2
22 1 | function Component() {
23 2 | const x = 0;
24 > 3 | x = 1;
19 - | ^ InvalidJS: Cannot reassign a `const` variable. `x` is declared as const (3:3)
25 + | ^ Cannot reassign a `const` variable
26 4 | }
27 5 |
28 +
29 +
30 ```
31
32
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-reassign-local-in-hook-return-value.expect.md
+9 -1
@@ -15,13 +15,21 @@ function useFoo() {
15 ## Error
16
17 ```
18 +Found 1 error:
19 +Error: Reassigning a variable after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead
20 +
21 +Variable `x` cannot be reassigned after render.
22 +
23 +error.invalid-reassign-local-in-hook-return-value.ts:4:4
24 2 | let x = 0;
25 3 | return value => {
26 > 4 | x = value;
21 - | ^ InvalidReact: Reassigning a variable after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead. Variable `x` cannot be reassigned after render (4:4)
27 + | ^ Reassigning a variable after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead
28 5 | };
29 6 | }
30 7 |
31 +
32 +
33 ```
34
35
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-reassign-local-variable-in-async-callback.expect.md
+9 -1
@@ -25,13 +25,21 @@ function Component() {
25 ## Error
26
27 ```
28 +Found 1 error:
29 +Error: Reassigning a variable in an async function can cause inconsistent behavior on subsequent renders. Consider using state instead
30 +
31 +Variable `value` cannot be reassigned after render.
32 +
33 +error.invalid-reassign-local-variable-in-async-callback.ts:8:6
34 6 | // after render, so this should error regardless of where this ends up
35 7 | // getting called
36 > 8 | value = result;
31 - | ^^^^^ InvalidReact: Reassigning a variable in an async function can cause inconsistent behavior on subsequent renders. Consider using state instead. Variable `value` cannot be reassigned after render (8:8)
37 + | ^^^^^ Reassigning a variable in an async function can cause inconsistent behavior on subsequent renders. Consider using state instead
38 9 | });
39 10 | };
40 11 |
41 +
42 +
43 ```
44
45
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-reassign-local-variable-in-effect.expect.md
+9 -1
@@ -47,13 +47,21 @@ function Component() {
47 ## Error
48
49 ```
50 +Found 1 error:
51 +Error: Reassigning a variable after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead
52 +
53 +Variable `local` cannot be reassigned after render.
54 +
55 +error.invalid-reassign-local-variable-in-effect.ts:7:4
56 5 |
57 6 | const reassignLocal = newValue => {
58 > 7 | local = newValue;
53 - | ^^^^^ InvalidReact: Reassigning a variable after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead. Variable `local` cannot be reassigned after render (7:7)
59 + | ^^^^^ Reassigning a variable after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead
60 8 | };
61 9 |
62 10 | const onMount = newValue => {
63 +
64 +
65 ```
66
67
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-reassign-local-variable-in-hook-argument.expect.md
+9 -1
@@ -48,13 +48,21 @@ function Component() {
48 ## Error
49
50 ```
51 +Found 1 error:
52 +Error: Reassigning a variable after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead
53 +
54 +Variable `local` cannot be reassigned after render.
55 +
56 +error.invalid-reassign-local-variable-in-hook-argument.ts:8:4
57 6 |
58 7 | const reassignLocal = newValue => {
59 > 8 | local = newValue;
54 - | ^^^^^ InvalidReact: Reassigning a variable after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead. Variable `local` cannot be reassigned after render (8:8)
60 + | ^^^^^ Reassigning a variable after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead
61 9 | };
62 10 |
63 11 | const callback = newValue => {
64 +
65 +
66 ```
67
68
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-reassign-local-variable-in-jsx-callback.expect.md
+9 -1
@@ -41,13 +41,21 @@ function Component() {
41 ## Error
42
43 ```
44 +Found 1 error:
45 +Error: Reassigning a variable after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead
46 +
47 +Variable `local` cannot be reassigned after render.
48 +
49 +error.invalid-reassign-local-variable-in-jsx-callback.ts:5:4
50 3 |
51 4 | const reassignLocal = newValue => {
52 > 5 | local = newValue;
47 - | ^^^^^ InvalidReact: Reassigning a variable after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead. Variable `local` cannot be reassigned after render (5:5)
53 + | ^^^^^ Reassigning a variable after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead
54 6 | };
55 7 |
56 8 | const onClick = newValue => {
57 +
58 +
59 ```
60
61
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-ref-in-callback-invoked-during-render.expect.md
+7 -1
@@ -18,12 +18,18 @@ function Component(props) {
18 ## Error
19
20 ```
21 +Found 1 error:
22 +Error: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
23 +
24 +error.invalid-ref-in-callback-invoked-during-render.ts:8:33
25 6 | return <Foo item={item} current={current} />;
26 7 | };
27 > 8 | return <Items>{props.items.map(item => renderItem(item))}</Items>;
24 - | ^^^^^^^^^^^^^^^^^^^^^^^^ InvalidReact: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef) (8:8)
28 + | ^^^^^^^^^^^^^^^^^^^^^^^^ Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
29 9 | }
30 10 |
31 +
32 +
33 ```
34
35
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-ref-value-as-props.expect.md
+7 -1
@@ -14,12 +14,18 @@ function Component(props) {
14 ## Error
15
16 ```
17 +Found 1 error:
18 +Error: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
19 +
20 +error.invalid-ref-value-as-props.ts:4:19
21 2 | function Component(props) {
22 3 | const ref = useRef(null);
23 > 4 | return <Foo ref={ref.current} />;
20 - | ^^^^^^^^^^^ InvalidReact: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef) (4:4)
24 + | ^^^^^^^^^^^ Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
25 5 | }
26 6 |
27 +
28 +
29 ```
30
31
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-return-mutable-function-from-hook.expect.md
+18 -2
@@ -19,6 +19,10 @@ function useFoo() {
19 ## Error
20
21 ```
22 +Found 2 errors:
23 +Error: This argument is a function which may reassign or mutate local variables after render, which can cause inconsistent behavior on subsequent renders. Consider using state instead
24 +
25 +error.invalid-return-mutable-function-from-hook.ts:7:9
26 5 | useHook(); // for inference to kick in
27 6 | const cache = new Map();
28 > 7 | return () => {
@@ -26,11 +30,23 @@ function useFoo() {
30 > 8 | cache.set('key', 'value');
31 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
32 > 9 | };
29 - | ^^^^ InvalidReact: This argument is a function which may reassign or mutate local variables after render, which can cause inconsistent behavior on subsequent renders. Consider using state instead (7:9)
33 + | ^^^^ This argument is a function which may reassign or mutate local variables after render, which can cause inconsistent behavior on subsequent renders. Consider using state instead
34 + 10 | }
35 + 11 |
36 +
37 +
38 +Error: The function modifies a local variable here
39
31 -InvalidReact: The function modifies a local variable here (8:8)
40 +error.invalid-return-mutable-function-from-hook.ts:8:4
41 + 6 | const cache = new Map();
42 + 7 | return () => {
43 +> 8 | cache.set('key', 'value');
44 + | ^^^^^ The function modifies a local variable here
45 + 9 | };
46 10 | }
47 11 |
48 +
49 +
50 ```
51
52
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-set-and-read-ref-during-render.expect.md
+18 -3
@@ -15,15 +15,30 @@ function Component(props) {
15 ## Error
16
17 ```
18 +Found 2 errors:
19 +Error: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
20 +
21 +error.invalid-set-and-read-ref-during-render.ts:4:2
22 2 | function Component(props) {
23 3 | const ref = useRef(null);
24 > 4 | ref.current = props.value;
21 - | ^^^^^^^^^^^ InvalidReact: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef) (4:4)
22 -
23 -InvalidReact: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef) (5:5)
25 + | ^^^^^^^^^^^ Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
26 5 | return ref.current;
27 6 | }
28 7 |
29 +
30 +
31 +Error: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
32 +
33 +error.invalid-set-and-read-ref-during-render.ts:5:9
34 + 3 | const ref = useRef(null);
35 + 4 | ref.current = props.value;
36 +> 5 | return ref.current;
37 + | ^^^^^^^^^^^ Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
38 + 6 | }
39 + 7 |
40 +
41 +
42 ```
43
44
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-set-and-read-ref-nested-property-during-render.expect.md
+18 -3
@@ -15,15 +15,30 @@ function Component(props) {
15 ## Error
16
17 ```
18 +Found 2 errors:
19 +Error: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
20 +
21 +error.invalid-set-and-read-ref-nested-property-during-render.ts:4:2
22 2 | function Component(props) {
23 3 | const ref = useRef({inner: null});
24 > 4 | ref.current.inner = props.value;
21 - | ^^^^^^^^^^^ InvalidReact: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef) (4:4)
22 -
23 -InvalidReact: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef) (5:5)
25 + | ^^^^^^^^^^^ Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
26 5 | return ref.current.inner;
27 6 | }
28 7 |
29 +
30 +
31 +Error: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
32 +
33 +error.invalid-set-and-read-ref-nested-property-during-render.ts:5:9
34 + 3 | const ref = useRef({inner: null});
35 + 4 | ref.current.inner = props.value;
36 +> 5 | return ref.current.inner;
37 + | ^^^^^^^^^^^^^^^^^ Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
38 + 6 | }
39 + 7 |
40 +
41 +
42 ```
43
44
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-setState-in-useMemo-indirect-useCallback.expect.md
+7 -1
@@ -26,13 +26,19 @@ function useKeyedState({key, init}) {
26 ## Error
27
28 ```
29 +Found 1 error:
30 +Error: Calling setState from useMemo may trigger an infinite loop. (https://react.dev/reference/react/useState)
31 +
32 +error.invalid-setState-in-useMemo-indirect-useCallback.ts:13:4
33 11 |
34 12 | useMemo(() => {
35 > 13 | fn();
32 - | ^^ InvalidReact: Calling setState from useMemo may trigger an infinite loop. (https://react.dev/reference/react/useState) (13:13)
36 + | ^^ Calling setState from useMemo may trigger an infinite loop. (https://react.dev/reference/react/useState)
37 14 | }, [key, init]);
38 15 |
39 16 | return state;
40 +
41 +
42 ```
43
44
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-setState-in-useMemo.expect.md
+19 -3
@@ -20,15 +20,31 @@ function useKeyedState({key, init}) {
20 ## Error
21
22 ```
23 +Found 2 errors:
24 +Error: Calling setState from useMemo may trigger an infinite loop. (https://react.dev/reference/react/useState)
25 +
26 +error.invalid-setState-in-useMemo.ts:6:4
27 4 |
28 5 | useMemo(() => {
29 > 6 | setPrevKey(key);
26 - | ^^^^^^^^^^ InvalidReact: Calling setState from useMemo may trigger an infinite loop. (https://react.dev/reference/react/useState) (6:6)
27 -
28 -InvalidReact: Calling setState from useMemo may trigger an infinite loop. (https://react.dev/reference/react/useState) (7:7)
30 + | ^^^^^^^^^^ Calling setState from useMemo may trigger an infinite loop. (https://react.dev/reference/react/useState)
31 7 | setState(init);
32 8 | }, [key, init]);
33 9 |
34 +
35 +
36 +Error: Calling setState from useMemo may trigger an infinite loop. (https://react.dev/reference/react/useState)
37 +
38 +error.invalid-setState-in-useMemo.ts:7:4
39 + 5 | useMemo(() => {
40 + 6 | setPrevKey(key);
41 +> 7 | setState(init);
42 + | ^^^^^^^^ Calling setState from useMemo may trigger an infinite loop. (https://react.dev/reference/react/useState)
43 + 8 | }, [key, init]);
44 + 9 |
45 + 10 | return state;
46 +
47 +
48 ```
49
50
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-sketchy-code-use-forget.expect.md
+23 -3
@@ -17,13 +17,33 @@ function lowercasecomponent() {
17 ## Error
18
19 ```
20 -> 1 | /* eslint-disable react-hooks/rules-of-hooks */
21 - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ InvalidReact: React Compiler has skipped optimizing this component because one or more React ESLint rules were disabled. React Compiler only works when your components follow all the rules of React, disabling them may result in unexpected or incorrect behavior. eslint-disable react-hooks/rules-of-hooks (1:1)
20 +Found 2 errors:
21 +Error: React Compiler has skipped optimizing this component because one or more React ESLint rules were disabled. React Compiler only works when your components follow all the rules of React, disabling them may result in unexpected or incorrect behavior
22 +
23 +eslint-disable react-hooks/rules-of-hooks.
24
23 -InvalidReact: React Compiler has skipped optimizing this component because one or more React ESLint rules were disabled. React Compiler only works when your components follow all the rules of React, disabling them may result in unexpected or incorrect behavior. eslint-disable-next-line react-hooks/rules-of-hooks (5:5)
25 +error.invalid-sketchy-code-use-forget.ts:1:0
26 +> 1 | /* eslint-disable react-hooks/rules-of-hooks */
27 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ React Compiler has skipped optimizing this component because one or more React ESLint rules were disabled. React Compiler only works when your components follow all the rules of React, disabling them may result in unexpected or incorrect behavior
28 2 | function lowercasecomponent() {
29 3 | 'use forget';
30 4 | const x = [];
31 +
32 +
33 +Error: React Compiler has skipped optimizing this component because one or more React ESLint rules were disabled. React Compiler only works when your components follow all the rules of React, disabling them may result in unexpected or incorrect behavior
34 +
35 +eslint-disable-next-line react-hooks/rules-of-hooks.
36 +
37 +error.invalid-sketchy-code-use-forget.ts:5:2
38 + 3 | 'use forget';
39 + 4 | const x = [];
40 +> 5 | // eslint-disable-next-line react-hooks/rules-of-hooks
41 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ React Compiler has skipped optimizing this component because one or more React ESLint rules were disabled. React Compiler only works when your components follow all the rules of React, disabling them may result in unexpected or incorrect behavior
42 + 6 | return <div>{x}</div>;
43 + 7 | }
44 + 8 | /* eslint-enable react-hooks/rules-of-hooks */
45 +
46 +
47 ```
48
49
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-ternary-with-hook-values.expect.md
+37 -4
@@ -13,18 +13,51 @@ function Component(props) {
13 ## Error
14
15 ```
16 +Found 4 errors:
17 +Error: Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values
18 +
19 +error.invalid-ternary-with-hook-values.ts:2:25
20 1 | function Component(props) {
21 > 2 | const x = props.cond ? useA : useB;
18 - | ^^^^ InvalidReact: Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values (2:2)
22 + | ^^^^ Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values
23 + 3 | return x();
24 + 4 | }
25 + 5 |
26 +
27 +
28 +Error: Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values
29 +
30 +error.invalid-ternary-with-hook-values.ts:2:32
31 + 1 | function Component(props) {
32 +> 2 | const x = props.cond ? useA : useB;
33 + | ^^^^ Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values
34 + 3 | return x();
35 + 4 | }
36 + 5 |
37
20 -InvalidReact: Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values (2:2)
38
22 -InvalidReact: Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values (2:2)
39 +Error: Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values
40
24 -InvalidReact: Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values (3:3)
41 +error.invalid-ternary-with-hook-values.ts:2:12
42 + 1 | function Component(props) {
43 +> 2 | const x = props.cond ? useA : useB;
44 + | ^^^^^^^^^^^^^^^^^^^^^^^^ Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values
45 3 | return x();
46 4 | }
47 5 |
48 +
49 +
50 +Error: Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values
51 +
52 +error.invalid-ternary-with-hook-values.ts:3:9
53 + 1 | function Component(props) {
54 + 2 | const x = props.cond ? useA : useB;
55 +> 3 | return x();
56 + | ^ Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values
57 + 4 | }
58 + 5 |
59 +
60 +
61 ```
62
63
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-type-provider-hook-name-not-typed-as-hook-namespace.expect.md
+9 -1
@@ -14,12 +14,20 @@ function Component() {
14 ## Error
15
16 ```
17 +Found 1 error:
18 +Error: Invalid type configuration for module
19 +
20 +Expected type for object property 'useHookNotTypedAsHook' from module 'ReactCompilerTest' to be a hook based on the property name.
21 +
22 +error.invalid-type-provider-hook-name-not-typed-as-hook-namespace.ts:4:9
23 2 |
24 3 | function Component() {
25 > 4 | return ReactCompilerTest.useHookNotTypedAsHook();
20 - | ^^^^^^^^^^^^^^^^^ InvalidConfig: Invalid type configuration for module. Expected type for object property 'useHookNotTypedAsHook' from module 'ReactCompilerTest' to be a hook based on the property name (4:4)
26 + | ^^^^^^^^^^^^^^^^^ Invalid type configuration for module
27 5 | }
28 6 |
29 +
30 +
31 ```
32
33
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-type-provider-hook-name-not-typed-as-hook.expect.md
+9 -1
@@ -14,12 +14,20 @@ function Component() {
14 ## Error
15
16 ```
17 +Found 1 error:
18 +Error: Invalid type configuration for module
19 +
20 +Expected type for object property 'useHookNotTypedAsHook' from module 'ReactCompilerTest' to be a hook based on the property name.
21 +
22 +error.invalid-type-provider-hook-name-not-typed-as-hook.ts:4:9
23 2 |
24 3 | function Component() {
25 > 4 | return useHookNotTypedAsHook();
20 - | ^^^^^^^^^^^^^^^^^^^^^ InvalidConfig: Invalid type configuration for module. Expected type for object property 'useHookNotTypedAsHook' from module 'ReactCompilerTest' to be a hook based on the property name (4:4)
26 + | ^^^^^^^^^^^^^^^^^^^^^ Invalid type configuration for module
27 5 | }
28 6 |
29 +
30 +
31 ```
32
33
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-type-provider-hooklike-module-default-not-hook.expect.md
+9 -1
@@ -14,12 +14,20 @@ function Component() {
14 ## Error
15
16 ```
17 +Found 1 error:
18 +Error: Invalid type configuration for module
19 +
20 +Expected type for `import ... from 'useDefaultExportNotTypedAsHook'` to be a hook based on the module name.
21 +
22 +error.invalid-type-provider-hooklike-module-default-not-hook.ts:4:15
23 2 |
24 3 | function Component() {
25 > 4 | return <div>{foo()}</div>;
20 - | ^^^ InvalidConfig: Invalid type configuration for module. Expected type for `import ... from 'useDefaultExportNotTypedAsHook'` to be a hook based on the module name (4:4)
26 + | ^^^ Invalid type configuration for module
27 5 | }
28 6 |
29 +
30 +
31 ```
32
33
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-type-provider-nonhook-name-typed-as-hook.expect.md
+9 -1
@@ -14,12 +14,20 @@ function Component() {
14 ## Error
15
16 ```
17 +Found 1 error:
18 +Error: Invalid type configuration for module
19 +
20 +Expected type for object property 'useHookNotTypedAsHook' from module 'ReactCompilerTest' to be a hook based on the property name.
21 +
22 +error.invalid-type-provider-nonhook-name-typed-as-hook.ts:4:15
23 2 |
24 3 | function Component() {
25 > 4 | return <div>{notAhookTypedAsHook()}</div>;
20 - | ^^^^^^^^^^^^^^^^^^^ InvalidConfig: Invalid type configuration for module. Expected type for object property 'useHookNotTypedAsHook' from module 'ReactCompilerTest' to be a hook based on the property name (4:4)
26 + | ^^^^^^^^^^^^^^^^^^^ Invalid type configuration for module
27 5 | }
28 6 |
29 +
30 +
31 ```
32
33
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-uncalled-function-capturing-mutable-values-memoizes-with-captures-values.expect.md
+19 -3
@@ -47,6 +47,10 @@ hook useMemoMap<TInput: interface {}, TOutput>(
47 ## Error
48
49 ```
50 +Found 2 errors:
51 +Error: This argument is a function which may reassign or mutate local variables after render, which can cause inconsistent behavior on subsequent renders. Consider using state instead
52 +
53 +undefined:21:9
54 19 | map: TInput => TOutput
55 20 | ): TInput => TOutput {
56 > 21 | return useMemo(() => {
@@ -82,11 +86,23 @@ hook useMemoMap<TInput: interface {}, TOutput>(
86 > 36 | };
87 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
88 > 37 | }, [map]);
85 - | ^^^^^^^^^^^^ InvalidReact: This argument is a function which may reassign or mutate local variables after render, which can cause inconsistent behavior on subsequent renders. Consider using state instead (21:37)
86 -
87 -InvalidReact: The function modifies a local variable here (33:33)
89 + | ^^^^^^^^^^^^ This argument is a function which may reassign or mutate local variables after render, which can cause inconsistent behavior on subsequent renders. Consider using state instead
90 38 | }
91 39 |
92 +
93 +
94 +Error: The function modifies a local variable here
95 +
96 +undefined:33:8
97 + 31 | if (output == null) {
98 + 32 | output = map(input);
99 +> 33 | cache.set(input, output);
100 + | ^^^^^ The function modifies a local variable here
101 + 34 | }
102 + 35 | return output;
103 + 36 | };
104 +
105 +
106 ```
107
108
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-unclosed-eslint-suppression.expect.md
+9 -1
@@ -36,12 +36,20 @@ function CrimesAgainstReact() {
36 ## Error
37
38 ```
39 +Found 1 error:
40 +Error: React Compiler has skipped optimizing this component because one or more React ESLint rules were disabled. React Compiler only works when your components follow all the rules of React, disabling them may result in unexpected or incorrect behavior
41 +
42 +eslint-disable react-hooks/rules-of-hooks.
43 +
44 +error.invalid-unclosed-eslint-suppression.ts:2:0
45 1 | // Note: Everything below this is sketchy
46 > 2 | /* eslint-disable react-hooks/rules-of-hooks */
41 - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ InvalidReact: React Compiler has skipped optimizing this component because one or more React ESLint rules were disabled. React Compiler only works when your components follow all the rules of React, disabling them may result in unexpected or incorrect behavior. eslint-disable react-hooks/rules-of-hooks (2:2)
47 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ React Compiler has skipped optimizing this component because one or more React ESLint rules were disabled. React Compiler only works when your components follow all the rules of React, disabling them may result in unexpected or incorrect behavior
48 3 | function lowercasecomponent() {
49 4 | 'use forget';
50 5 | const x = [];
51 +
52 +
53 ```
54
55
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-unconditional-set-state-in-render.expect.md
+19 -3
@@ -19,15 +19,31 @@ function Component(props) {
19 ## Error
20
21 ```
22 +Found 2 errors:
23 +Error: This is an unconditional set state during render, which will trigger an infinite loop. (https://react.dev/reference/react/useState)
24 +
25 +error.invalid-unconditional-set-state-in-render.ts:6:2
26 4 | const aliased = setX;
27 5 |
28 > 6 | setX(1);
25 - | ^^^^ InvalidReact: This is an unconditional set state during render, which will trigger an infinite loop. (https://react.dev/reference/react/useState) (6:6)
26 -
27 -InvalidReact: This is an unconditional set state during render, which will trigger an infinite loop. (https://react.dev/reference/react/useState) (7:7)
29 + | ^^^^ This is an unconditional set state during render, which will trigger an infinite loop. (https://react.dev/reference/react/useState)
30 7 | aliased(2);
31 8 |
32 9 | return x;
33 +
34 +
35 +Error: This is an unconditional set state during render, which will trigger an infinite loop. (https://react.dev/reference/react/useState)
36 +
37 +error.invalid-unconditional-set-state-in-render.ts:7:2
38 + 5 |
39 + 6 | setX(1);
40 +> 7 | aliased(2);
41 + | ^^^^^^^ This is an unconditional set state during render, which will trigger an infinite loop. (https://react.dev/reference/react/useState)
42 + 8 |
43 + 9 | return x;
44 + 10 | }
45 +
46 +
47 ```
48
49
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-use-ref-added-to-dep-without-type-info.expect.md
+18 -2
@@ -22,15 +22,31 @@ function Foo({a}) {
22 ## Error
23
24 ```
25 +Found 2 errors:
26 +Error: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
27 +
28 +error.invalid-use-ref-added-to-dep-without-type-info.ts:10:21
29 8 | // however, this is an instance of accessing a ref during render and is disallowed
30 9 | // under React's rules, so we reject this input
31 > 10 | const x = {a, val: val.ref.current};
28 - | ^^^^^^^^^^^^^^^ InvalidReact: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef) (10:10)
32 + | ^^^^^^^^^^^^^^^ Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
33 + 11 |
34 + 12 | return <VideoList videos={x} />;
35 + 13 | }
36 +
37 +
38 +Error: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
39
30 -InvalidReact: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef) (10:10)
40 +error.invalid-use-ref-added-to-dep-without-type-info.ts:10:21
41 + 8 | // however, this is an instance of accessing a ref during render and is disallowed
42 + 9 | // under React's rules, so we reject this input
43 +> 10 | const x = {a, val: val.ref.current};
44 + | ^^^^^^^^^^^^^^^ Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
45 11 |
46 12 | return <VideoList videos={x} />;
47 13 | }
48 +
49 +
50 ```
51
52
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-useEffect-dep-not-memoized-bc-range-overlaps-hook.expect.md
+7 -1
@@ -23,6 +23,10 @@ function Component(props) {
23 ## Error
24
25 ```
26 +Found 1 error:
27 +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
28 +
29 +error.invalid-useEffect-dep-not-memoized-bc-range-overlaps-hook.ts:9:2
30 7 |
31 8 | // Items is no longer mutable here, but it hasn't been memoized
32 > 9 | useEffect(() => {
@@ -30,10 +34,12 @@ function Component(props) {
34 > 10 | console.log(items);
35 | ^^^^^^^^^^^^^^^^^^^^^^^
36 > 11 | }, [items]);
33 - | ^^^^^^^^^^^^^^ CannotPreserveMemoization: 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 (9:11)
37 + | ^^^^^^^^^^^^^^ 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
38 12 |
39 13 | return [items, state];
40 14 | }
41 +
42 +
43 ```
44
45
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-useEffect-dep-not-memoized.expect.md
+7 -1
@@ -20,6 +20,10 @@ function Component(props) {
20 ## Error
21
22 ```
23 +Found 1 error:
24 +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
25 +
26 +error.invalid-useEffect-dep-not-memoized.ts:6:2
27 4 | function Component(props) {
28 5 | const data = {};
29 > 6 | useEffect(() => {
@@ -27,10 +31,12 @@ function Component(props) {
31 > 7 | console.log(props.value);
32 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
33 > 8 | }, [data]);
30 - | ^^^^^^^^^^^^^ CannotPreserveMemoization: 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 (6:8)
34 + | ^^^^^^^^^^^^^ 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
35 9 | mutate(data);
36 10 | return data;
37 11 | }
38 +
39 +
40 ```
41
42
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-useInsertionEffect-dep-not-memoized.expect.md
+7 -1
@@ -20,6 +20,10 @@ function Component(props) {
20 ## Error
21
22 ```
23 +Found 1 error:
24 +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
25 +
26 +error.invalid-useInsertionEffect-dep-not-memoized.ts:6:2
27 4 | function Component(props) {
28 5 | const data = {};
29 > 6 | useInsertionEffect(() => {
@@ -27,10 +31,12 @@ function Component(props) {
31 > 7 | console.log(props.value);
32 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
33 > 8 | }, [data]);
30 - | ^^^^^^^^^^^^^ CannotPreserveMemoization: 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 (6:8)
34 + | ^^^^^^^^^^^^^ 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
35 9 | mutate(data);
36 10 | return data;
37 11 | }
38 +
39 +
40 ```
41
42
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-useLayoutEffect-dep-not-memoized.expect.md
+7 -1
@@ -20,6 +20,10 @@ function Component(props) {
20 ## Error
21
22 ```
23 +Found 1 error:
24 +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
25 +
26 +error.invalid-useLayoutEffect-dep-not-memoized.ts:6:2
27 4 | function Component(props) {
28 5 | const data = {};
29 > 6 | useLayoutEffect(() => {
@@ -27,10 +31,12 @@ function Component(props) {
31 > 7 | console.log(props.value);
32 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
33 > 8 | }, [data]);
30 - | ^^^^^^^^^^^^^ CannotPreserveMemoization: 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 (6:8)
34 + | ^^^^^^^^^^^^^ 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
35 9 | mutate(data);
36 10 | return data;
37 11 | }
38 +
39 +
40 ```
41
42
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-useMemo-async-callback.expect.md
+7 -1
@@ -15,16 +15,22 @@ function component(a, b) {
15 ## Error
16
17 ```
18 +Found 1 error:
19 +Error: useMemo callbacks may not be async or generator functions
20 +
21 +error.invalid-useMemo-async-callback.ts:2:18
22 1 | function component(a, b) {
23 > 2 | let x = useMemo(async () => {
24 | ^^^^^^^^^^^^^
25 > 3 | await a;
26 | ^^^^^^^^^^^^
27 > 4 | }, []);
24 - | ^^^^ InvalidReact: useMemo callbacks may not be async or generator functions (2:4)
28 + | ^^^^ useMemo callbacks may not be async or generator functions
29 5 | return x;
30 6 | }
31 7 |
32 +
33 +
34 ```
35
36
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-useMemo-callback-args.expect.md
+7 -1
@@ -13,12 +13,18 @@ function component(a, b) {
13 ## Error
14
15 ```
16 +Found 1 error:
17 +Error: useMemo callbacks may not accept any arguments
18 +
19 +error.invalid-useMemo-callback-args.ts:2:18
20 1 | function component(a, b) {
21 > 2 | let x = useMemo(c => a, []);
18 - | ^^^^^^ InvalidReact: useMemo callbacks may not accept any arguments (2:2)
22 + | ^^^^^^ useMemo callbacks may not accept any arguments
23 3 | return x;
24 4 | }
25 5 |
26 +
27 +
28 ```
29
30
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-write-but-dont-read-ref-in-render.expect.md
+7 -1
@@ -17,13 +17,19 @@ function useHook({value}) {
17 ## Error
18
19 ```
20 +Found 1 error:
21 +Error: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
22 +
23 +error.invalid-write-but-dont-read-ref-in-render.ts:5:2
24 3 | const ref = useRef(null);
25 4 | // Writing to a ref in render is against the rules:
26 > 5 | ref.current = value;
23 - | ^^^^^^^^^^^ InvalidReact: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef) (5:5)
27 + | ^^^^^^^^^^^ Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
28 6 | // returning a ref is allowed, so this alone doesn't trigger an error:
29 7 | return ref;
30 8 | }
31 +
32 +
33 ```
34
35
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-write-ref-prop-in-render.expect.md
+7 -1
@@ -15,13 +15,19 @@ function Component(props) {
15 ## Error
16
17 ```
18 +Found 1 error:
19 +Error: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
20 +
21 +error.invalid-write-ref-prop-in-render.ts:4:2
22 2 | function Component(props) {
23 3 | const ref = props.ref;
24 > 4 | ref.current = true;
21 - | ^^^^^^^^^^^ InvalidReact: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef) (4:4)
25 + | ^^^^^^^^^^^ Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
26 5 | return <div>{value}</div>;
27 6 | }
28 7 |
29 +
30 +
31 ```
32
33
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.modify-state-2.expect.md
+7 -1
@@ -17,13 +17,19 @@ function Foo() {
17 ## Error
18
19 ```
20 +Found 1 error:
21 +Error: Mutating a value returned from 'useState()', which should not be mutated. Use the setter function to update instead
22 +
23 +error.modify-state-2.ts:6:2
24 4 | const [state, setState] = useState({foo: {bar: 3}});
25 5 | const foo = state.foo;
26 > 6 | foo.bar = 1;
23 - | ^^^ InvalidReact: Mutating a value returned from 'useState()', which should not be mutated. Use the setter function to update instead (6:6)
27 + | ^^^ Mutating a value returned from 'useState()', which should not be mutated. Use the setter function to update instead
28 7 | return state;
29 8 | }
30 9 |
31 +
32 +
33 ```
34
35
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.modify-state.expect.md
+7 -1
@@ -16,13 +16,19 @@ function Foo() {
16 ## Error
17
18 ```
19 +Found 1 error:
20 +Error: Mutating a value returned from 'useState()', which should not be mutated. Use the setter function to update instead
21 +
22 +error.modify-state.ts:5:2
23 3 | function Foo() {
24 4 | let [state, setState] = useState({});
25 > 5 | state.foo = 1;
22 - | ^^^^^ InvalidReact: Mutating a value returned from 'useState()', which should not be mutated. Use the setter function to update instead (5:5)
26 + | ^^^^^ Mutating a value returned from 'useState()', which should not be mutated. Use the setter function to update instead
27 6 | return state;
28 7 | }
29 8 |
30 +
31 +
32 ```
33
34
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.modify-useReducer-state.expect.md
+7 -1
@@ -16,13 +16,19 @@ function Foo() {
16 ## Error
17
18 ```
19 +Found 1 error:
20 +Error: Mutating a value returned from 'useReducer()', which should not be mutated. Use the dispatch function to update instead
21 +
22 +error.modify-useReducer-state.ts:5:2
23 3 | function Foo() {
24 4 | let [state, setState] = useReducer({foo: 1});
25 > 5 | state.foo = 1;
22 - | ^^^^^ InvalidReact: Mutating a value returned from 'useReducer()', which should not be mutated. Use the dispatch function to update instead (5:5)
26 + | ^^^^^ Mutating a value returned from 'useReducer()', which should not be mutated. Use the dispatch function to update instead
27 6 | return state;
28 7 | }
29 8 |
30 +
31 +
32 ```
33
34
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.mutable-range-shared-inner-outer-function.expect.md
+9 -1
@@ -32,13 +32,21 @@ export const FIXTURE_ENTRYPOINT = {
32 ## Error
33
34 ```
35 +Found 1 error:
36 +Error: Reassigning a variable after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead
37 +
38 +Variable `a` cannot be reassigned after render.
39 +
40 +error.mutable-range-shared-inner-outer-function.ts:8:6
41 6 | const f = () => {
42 7 | if (cond) {
43 > 8 | a = {};
38 - | ^ InvalidReact: Reassigning a variable after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead. Variable `a` cannot be reassigned after render (8:8)
44 + | ^ Reassigning a variable after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead
45 9 | b = [];
46 10 | } else {
47 11 | a = {};
48 +
49 +
50 ```
51
52
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.mutate-function-property.expect.md
+7 -1
@@ -15,13 +15,19 @@ export function ViewModeSelector(props) {
15 ## Error
16
17 ```
18 +Found 1 error:
19 +Error: This mutates a variable that React considers immutable
20 +
21 +error.mutate-function-property.ts:3:2
22 1 | export function ViewModeSelector(props) {
23 2 | const renderIcon = () => <AcceptIcon />;
24 > 3 | renderIcon.displayName = 'AcceptIcon';
21 - | ^^^^^^^^^^ InvalidReact: This mutates a variable that React considers immutable (3:3)
25 + | ^^^^^^^^^^ This mutates a variable that React considers immutable
26 4 |
27 5 | return <Dropdown checkableIndicator={{children: renderIcon}} />;
28 6 | }
29 +
30 +
31 ```
32
33
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.mutate-global-increment-op-invalid-react.expect.md
+7 -1
@@ -15,13 +15,19 @@ function NoHooks() {
15 ## Error
16
17 ```
18 +Found 1 error:
19 +Todo: (BuildHIR::lowerExpression) Support UpdateExpression where argument is a global
20 +
21 +error.mutate-global-increment-op-invalid-react.ts:4:2
22 2 |
23 3 | function NoHooks() {
24 > 4 | renderCount++;
21 - | ^^^^^^^^^^^^^ Todo: (BuildHIR::lowerExpression) Support UpdateExpression where argument is a global (4:4)
25 + | ^^^^^^^^^^^^^ (BuildHIR::lowerExpression) Support UpdateExpression where argument is a global
26 5 | return <div />;
27 6 | }
28 7 |
29 +
30 +
31 ```
32
33
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.mutate-hook-argument.expect.md
+18 -3
@@ -13,14 +13,29 @@ function useHook(a, b) {
13 ## Error
14
15 ```
16 +Found 2 errors:
17 +Error: Mutating component props or hook arguments is not allowed. Consider using a local variable instead
18 +
19 +error.mutate-hook-argument.ts:2:2
20 1 | function useHook(a, b) {
21 > 2 | b.test = 1;
18 - | ^ InvalidReact: Mutating component props or hook arguments is not allowed. Consider using a local variable instead (2:2)
19 -
20 -InvalidReact: Mutating component props or hook arguments is not allowed. Consider using a local variable instead (3:3)
22 + | ^ Mutating component props or hook arguments is not allowed. Consider using a local variable instead
23 3 | a.test = 2;
24 4 | }
25 5 |
26 +
27 +
28 +Error: Mutating component props or hook arguments is not allowed. Consider using a local variable instead
29 +
30 +error.mutate-hook-argument.ts:3:2
31 + 1 | function useHook(a, b) {
32 + 2 | b.test = 1;
33 +> 3 | a.test = 2;
34 + | ^ Mutating component props or hook arguments is not allowed. Consider using a local variable instead
35 + 4 | }
36 + 5 |
37 +
38 +
39 ```
40
41
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.mutate-property-from-global.expect.md
+7 -1
@@ -15,13 +15,19 @@ function Foo() {
15 ## Error
16
17 ```
18 +Found 1 error:
19 +Error: Writing to a variable defined outside a component or hook is not allowed. Consider using an effect
20 +
21 +error.mutate-property-from-global.ts:4:9
22 2 |
23 3 | function Foo() {
24 > 4 | delete wat.foo;
21 - | ^^^ InvalidReact: Writing to a variable defined outside a component or hook is not allowed. Consider using an effect (4:4)
25 + | ^^^ Writing to a variable defined outside a component or hook is not allowed. Consider using an effect
26 5 | return wat;
27 6 | }
28 7 |
29 +
30 +
31 ```
32
33
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.mutate-props.expect.md
+7 -1
@@ -13,12 +13,18 @@ function Foo(props) {
13 ## Error
14
15 ```
16 +Found 1 error:
17 +Error: Mutating component props or hook arguments is not allowed. Consider using a local variable instead
18 +
19 +error.mutate-props.ts:2:2
20 1 | function Foo(props) {
21 > 2 | props.test = 1;
18 - | ^^^^^ InvalidReact: Mutating component props or hook arguments is not allowed. Consider using a local variable instead (2:2)
22 + | ^^^^^ Mutating component props or hook arguments is not allowed. Consider using a local variable instead
23 3 | return null;
24 4 | }
25 5 |
26 +
27 +
28 ```
29
30
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.nomemo-and-change-detect.expect.md
+2 -1
@@ -11,7 +11,8 @@ function Component(props) {}
11 ## Error
12
13 ```
14 -InvalidConfig: Invalid environment config: the 'disableMemoizationForDebugging' and 'enableChangeDetectionForDebugging' options cannot be used together
14 +Found 1 error:
15 +Error: Invalid environment config: the 'disableMemoizationForDebugging' and 'enableChangeDetectionForDebugging' options cannot be used together
16 ```
17
18
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.not-useEffect-external-mutate.expect.md
+19 -3
@@ -17,15 +17,31 @@ function Component(props) {
17 ## Error
18
19 ```
20 +Found 2 errors:
21 +Error: Writing to a variable defined outside a component or hook is not allowed. Consider using an effect
22 +
23 +error.not-useEffect-external-mutate.ts:5:4
24 3 | function Component(props) {
25 4 | foo(() => {
26 > 5 | x.a = 10;
23 - | ^ InvalidReact: Writing to a variable defined outside a component or hook is not allowed. Consider using an effect (5:5)
24 -
25 -InvalidReact: Writing to a variable defined outside a component or hook is not allowed. Consider using an effect (6:6)
27 + | ^ Writing to a variable defined outside a component or hook is not allowed. Consider using an effect
28 6 | x.a = 20;
29 7 | });
30 8 | }
31 +
32 +
33 +Error: Writing to a variable defined outside a component or hook is not allowed. Consider using an effect
34 +
35 +error.not-useEffect-external-mutate.ts:6:4
36 + 4 | foo(() => {
37 + 5 | x.a = 10;
38 +> 6 | x.a = 20;
39 + | ^ Writing to a variable defined outside a component or hook is not allowed. Consider using an effect
40 + 7 | });
41 + 8 | }
42 + 9 |
43 +
44 +
45 ```
46
47
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.object-capture-global-mutation.expect.md
+7 -1
@@ -22,13 +22,19 @@ export const FIXTURE_ENTRYPOINT = {
22 ## Error
23
24 ```
25 +Found 1 error:
26 +Error: Writing to a variable defined outside a component or hook is not allowed. Consider using an effect
27 +
28 +error.object-capture-global-mutation.ts:4:4
29 2 | function Foo() {
30 3 | const x = () => {
31 > 4 | window.href = 'foo';
28 - | ^^^^^^ InvalidReact: Writing to a variable defined outside a component or hook is not allowed. Consider using an effect (4:4)
32 + | ^^^^^^ Writing to a variable defined outside a component or hook is not allowed. Consider using an effect
33 5 | };
34 6 | const y = {x};
35 7 | return <Bar y={y} />;
36 +
37 +
38 ```
39
40
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.propertyload-hook.expect.md
+18 -3
@@ -13,14 +13,29 @@ function Component() {
13 ## Error
14
15 ```
16 +Found 2 errors:
17 +Error: Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values
18 +
19 +error.propertyload-hook.ts:2:12
20 1 | function Component() {
21 > 2 | const x = Foo.useFoo;
18 - | ^^^^^^^^^^ InvalidReact: Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values (2:2)
19 -
20 -InvalidReact: Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values (3:3)
22 + | ^^^^^^^^^^ Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values
23 3 | return x();
24 4 | }
25 5 |
26 +
27 +
28 +Error: Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values
29 +
30 +error.propertyload-hook.ts:3:9
31 + 1 | function Component() {
32 + 2 | const x = Foo.useFoo;
33 +> 3 | return x();
34 + | ^ Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values
35 + 4 | }
36 + 5 |
37 +
38 +
39 ```
40
41
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.reassign-global-fn-arg.expect.md
+7 -1
@@ -24,13 +24,19 @@ export const FIXTURE_ENTRYPOINT = {
24 ## Error
25
26 ```
27 +Found 1 error:
28 +Error: Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render)
29 +
30 +error.reassign-global-fn-arg.ts:5:4
31 3 | export default function MyApp() {
32 4 | const fn = () => {
33 > 5 | b = 2;
30 - | ^ InvalidReact: Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render) (5:5)
34 + | ^ Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render)
35 6 | };
36 7 | return foo(fn);
37 8 | }
38 +
39 +
40 ```
41
42
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.reassignment-to-global-indirect.expect.md
+19 -3
@@ -17,15 +17,31 @@ function Component() {
17 ## Error
18
19 ```
20 +Found 2 errors:
21 +Error: Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render)
22 +
23 +error.reassignment-to-global-indirect.ts:4:4
24 2 | const foo = () => {
25 3 | // Cannot assign to globals
26 > 4 | someUnknownGlobal = true;
23 - | ^^^^^^^^^^^^^^^^^ InvalidReact: Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render) (4:4)
24 -
25 -InvalidReact: Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render) (5:5)
27 + | ^^^^^^^^^^^^^^^^^ Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render)
28 5 | moduleLocal = true;
29 6 | };
30 7 | foo();
31 +
32 +
33 +Error: Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render)
34 +
35 +error.reassignment-to-global-indirect.ts:5:4
36 + 3 | // Cannot assign to globals
37 + 4 | someUnknownGlobal = true;
38 +> 5 | moduleLocal = true;
39 + | ^^^^^^^^^^^ Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render)
40 + 6 | };
41 + 7 | foo();
42 + 8 | }
43 +
44 +
45 ```
46
47
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.reassignment-to-global.expect.md
+18 -3
@@ -14,15 +14,30 @@ function Component() {
14 ## Error
15
16 ```
17 +Found 2 errors:
18 +Error: Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render)
19 +
20 +error.reassignment-to-global.ts:3:2
21 1 | function Component() {
22 2 | // Cannot assign to globals
23 > 3 | someUnknownGlobal = true;
20 - | ^^^^^^^^^^^^^^^^^ InvalidReact: Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render) (3:3)
21 -
22 -InvalidReact: Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render) (4:4)
24 + | ^^^^^^^^^^^^^^^^^ Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render)
25 4 | moduleLocal = true;
26 5 | }
27 6 |
28 +
29 +
30 +Error: Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render)
31 +
32 +error.reassignment-to-global.ts:4:2
33 + 2 | // Cannot assign to globals
34 + 3 | someUnknownGlobal = true;
35 +> 4 | moduleLocal = true;
36 + | ^^^^^^^^^^^ Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render)
37 + 5 | }
38 + 6 |
39 +
40 +
41 ```
42
43
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.ref-initialization-arbitrary.expect.md
+19 -3
@@ -25,15 +25,31 @@ export const FIXTURE_ENTRYPOINT = {
25 ## Error
26
27 ```
28 +Found 2 errors:
29 +Error: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
30 +
31 +undefined:8:6
32 6 | component C() {
33 7 | const r = useRef(DEFAULT_VALUE);
34 > 8 | if (r.current == DEFAULT_VALUE) {
31 - | ^^^^^^^^^ InvalidReact: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef) (8:8)
32 -
33 -InvalidReact: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef) (9:9)
35 + | ^^^^^^^^^ Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
36 9 | r.current = 1;
37 10 | }
38 11 | }
39 +
40 +
41 +Error: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
42 +
43 +undefined:9:4
44 + 7 | const r = useRef(DEFAULT_VALUE);
45 + 8 | if (r.current == DEFAULT_VALUE) {
46 +> 9 | r.current = 1;
47 + | ^^^^^^^^^ Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
48 + 10 | }
49 + 11 | }
50 + 12 |
51 +
52 +
53 ```
54
55
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.ref-initialization-call-2.expect.md
+7 -1
@@ -23,13 +23,19 @@ export const FIXTURE_ENTRYPOINT = {
23 ## Error
24
25 ```
26 +Found 1 error:
27 +Error: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
28 +
29 +undefined:7:6
30 5 | const r = useRef(null);
31 6 | if (r.current == null) {
32 > 7 | f(r);
29 - | ^ InvalidReact: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef) (7:7)
33 + | ^ Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
34 8 | }
35 9 | }
36 10 |
37 +
38 +
39 ```
40
41
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.ref-initialization-call.expect.md
+7 -1
@@ -23,13 +23,19 @@ export const FIXTURE_ENTRYPOINT = {
23 ## Error
24
25 ```
26 +Found 1 error:
27 +Error: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
28 +
29 +undefined:7:6
30 5 | const r = useRef(null);
31 6 | if (r.current == null) {
32 > 7 | f(r.current);
29 - | ^^^^^^^^^ InvalidReact: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef) (7:7)
33 + | ^^^^^^^^^ Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
34 8 | }
35 9 | }
36 10 |
37 +
38 +
39 ```
40
41
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.ref-initialization-linear.expect.md
+7 -1
@@ -24,13 +24,19 @@ export const FIXTURE_ENTRYPOINT = {
24 ## Error
25
26 ```
27 +Found 1 error:
28 +Error: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
29 +
30 +undefined:8:4
31 6 | if (r.current == null) {
32 7 | r.current = 42;
33 > 8 | r.current = 42;
30 - | ^^^^^^^^^ InvalidReact: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef) (8:8)
34 + | ^^^^^^^^^ Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
35 9 | }
36 10 | }
37 11 |
38 +
39 +
40 ```
41
42
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.ref-initialization-nonif.expect.md
+21 -3
@@ -24,15 +24,33 @@ export const FIXTURE_ENTRYPOINT = {
24 ## Error
25
26 ```
27 +Found 2 errors:
28 +Error: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
29 +
30 +undefined:6:16
31 4 | component C() {
32 5 | const r = useRef(null);
33 > 6 | const guard = r.current == null;
30 - | ^^^^^^^^^^^^^^^^^ InvalidReact: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef) (6:6)
31 -
32 -InvalidReact: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef). Cannot access ref value `guard` (7:7)
34 + | ^^^^^^^^^^^^^^^^^ Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
35 7 | if (guard) {
36 8 | r.current = 1;
37 9 | }
38 +
39 +
40 +Error: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
41 +
42 +Cannot access ref value `guard`.
43 +
44 +undefined:7:6
45 + 5 | const r = useRef(null);
46 + 6 | const guard = r.current == null;
47 +> 7 | if (guard) {
48 + | ^^^^^ Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
49 + 8 | r.current = 1;
50 + 9 | }
51 + 10 | }
52 +
53 +
54 ```
55
56
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.ref-initialization-other.expect.md
+7 -1
@@ -24,13 +24,19 @@ export const FIXTURE_ENTRYPOINT = {
24 ## Error
25
26 ```
27 +Found 1 error:
28 +Error: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
29 +
30 +undefined:8:4
31 6 | const r2 = useRef(null);
32 7 | if (r.current == null) {
33 > 8 | r2.current = 1;
30 - | ^^^^^^^^^^ InvalidReact: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef) (8:8)
34 + | ^^^^^^^^^^ Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
35 9 | }
36 10 | }
37 11 |
38 +
39 +
40 ```
41
42
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.ref-initialization-post-access-2.expect.md
+7 -1
@@ -24,13 +24,19 @@ export const FIXTURE_ENTRYPOINT = {
24 ## Error
25
26 ```
27 +Found 1 error:
28 +Error: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
29 +
30 +undefined:9:4
31 7 | r.current = 1;
32 8 | }
33 > 9 | f(r.current);
30 - | ^^^^^^^^^ InvalidReact: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef) (9:9)
34 + | ^^^^^^^^^ Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
35 10 | }
36 11 |
37 12 | export const FIXTURE_ENTRYPOINT = {
38 +
39 +
40 ```
41
42
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.ref-initialization-post-access.expect.md
+7 -1
@@ -24,13 +24,19 @@ export const FIXTURE_ENTRYPOINT = {
24 ## Error
25
26 ```
27 +Found 1 error:
28 +Error: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
29 +
30 +undefined:9:2
31 7 | r.current = 1;
32 8 | }
33 > 9 | r.current = 1;
30 - | ^^^^^^^^^ InvalidReact: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef) (9:9)
34 + | ^^^^^^^^^ Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
35 10 | }
36 11 |
37 12 | export const FIXTURE_ENTRYPOINT = {
38 +
39 +
40 ```
41
42
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.ref-like-name-not-Ref.expect.md
+9 -1
@@ -31,6 +31,12 @@ export const FIXTURE_ENTRYPOINT = {
31 ## Error
32
33 ```
34 +Found 1 error:
35 +Memoization: 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
36 +
37 +The inferred dependency was `Ref.current`, but the source dependencies were []. Inferred dependency not present in source.
38 +
39 +error.ref-like-name-not-Ref.ts:11:30
40 9 | const Ref = useCustomRef();
41 10 |
42 > 11 | const onClick = useCallback(() => {
@@ -38,10 +44,12 @@ export const FIXTURE_ENTRYPOINT = {
44 > 12 | Ref.current?.click();
45 | ^^^^^^^^^^^^^^^^^^^^^^^^^
46 > 13 | }, []);
41 - | ^^^^ CannotPreserveMemoization: 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 (11:13)
47 + | ^^^^ 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
48 14 |
49 15 | return <button onClick={onClick} />;
50 16 | }
51 +
52 +
53 ```
54
55
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.ref-like-name-not-a-ref.expect.md
+9 -1
@@ -31,6 +31,12 @@ export const FIXTURE_ENTRYPOINT = {
31 ## Error
32
33 ```
34 +Found 1 error:
35 +Memoization: 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
36 +
37 +The inferred dependency was `notaref.current`, but the source dependencies were []. Inferred dependency not present in source.
38 +
39 +error.ref-like-name-not-a-ref.ts:11:30
40 9 | const notaref = useCustomRef();
41 10 |
42 > 11 | const onClick = useCallback(() => {
@@ -38,10 +44,12 @@ export const FIXTURE_ENTRYPOINT = {
44 > 12 | notaref.current?.click();
45 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
46 > 13 | }, []);
41 - | ^^^^ CannotPreserveMemoization: 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 (11:13)
47 + | ^^^^ 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
48 14 |
49 15 | return <button onClick={onClick} />;
50 16 | }
51 +
52 +
53 ```
54
55
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.ref-optional.expect.md
+7 -1
@@ -20,13 +20,19 @@ export const FIXTURE_ENTRYPOINT = {
20 ## Error
21
22 ```
23 +Found 1 error:
24 +Error: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
25 +
26 +error.ref-optional.ts:5:9
27 3 | function Component(props) {
28 4 | const ref = useRef();
29 > 5 | return ref?.current;
26 - | ^^^^^^^^^^^^ InvalidReact: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef) (5:5)
30 + | ^^^^^^^^^^^^ Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
31 6 | }
32 7 |
33 8 | export const FIXTURE_ENTRYPOINT = {
34 +
35 +
36 ```
37
38
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.repro-ref-mutable-range.expect.md
+7 -1
@@ -28,13 +28,19 @@ export const FIXTURE_ENTRYPOINT = {
28 ## Error
29
30 ```
31 +Found 1 error:
32 +Error: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
33 +
34 +error.repro-ref-mutable-range.ts:11:36
35 9 | mutate(value);
36 10 | if (CONST_TRUE) {
37 > 11 | return <Stringify ref={identity(ref)} />;
34 - | ^^^ InvalidReact: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef) (11:11)
38 + | ^^^ Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
39 12 | }
40 13 | return value;
41 14 | }
42 +
43 +
44 ```
45
46
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.sketchy-code-exhaustive-deps.expect.md
+9 -1
@@ -20,13 +20,21 @@ function Component() {
20 ## Error
21
22 ```
23 +Found 1 error:
24 +Error: React Compiler has skipped optimizing this component because one or more React ESLint rules were disabled. React Compiler only works when your components follow all the rules of React, disabling them may result in unexpected or incorrect behavior
25 +
26 +eslint-disable-next-line react-hooks/exhaustive-deps.
27 +
28 +error.sketchy-code-exhaustive-deps.ts:6:7
29 4 | () => {
30 5 | item.push(1);
31 > 6 | }, // eslint-disable-next-line react-hooks/exhaustive-deps
26 - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ InvalidReact: React Compiler has skipped optimizing this component because one or more React ESLint rules were disabled. React Compiler only works when your components follow all the rules of React, disabling them may result in unexpected or incorrect behavior. eslint-disable-next-line react-hooks/exhaustive-deps (6:6)
32 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ React Compiler has skipped optimizing this component because one or more React ESLint rules were disabled. React Compiler only works when your components follow all the rules of React, disabling them may result in unexpected or incorrect behavior
33 7 | []
34 8 | );
35 9 |
36 +
37 +
38 ```
39
40
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.sketchy-code-rules-of-hooks.expect.md
+9 -1
@@ -21,11 +21,19 @@ export const FIXTURE_ENTRYPOINT = {
21 ## Error
22
23 ```
24 +Found 1 error:
25 +Error: React Compiler has skipped optimizing this component because one or more React ESLint rules were disabled. React Compiler only works when your components follow all the rules of React, disabling them may result in unexpected or incorrect behavior
26 +
27 +eslint-disable react-hooks/rules-of-hooks.
28 +
29 +error.sketchy-code-rules-of-hooks.ts:1:0
30 > 1 | /* eslint-disable react-hooks/rules-of-hooks */
25 - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ InvalidReact: React Compiler has skipped optimizing this component because one or more React ESLint rules were disabled. React Compiler only works when your components follow all the rules of React, disabling them may result in unexpected or incorrect behavior. eslint-disable react-hooks/rules-of-hooks (1:1)
31 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ React Compiler has skipped optimizing this component because one or more React ESLint rules were disabled. React Compiler only works when your components follow all the rules of React, disabling them may result in unexpected or incorrect behavior
32 2 | function lowercasecomponent() {
33 3 | const x = [];
34 4 | return <div>{x}</div>;
35 +
36 +
37 ```
38
39
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.store-property-in-global.expect.md
+7 -1
@@ -15,13 +15,19 @@ function Foo() {
15 ## Error
16
17 ```
18 +Found 1 error:
19 +Error: Writing to a variable defined outside a component or hook is not allowed. Consider using an effect
20 +
21 +error.store-property-in-global.ts:4:2
22 2 |
23 3 | function Foo() {
24 > 4 | wat.test = 1;
21 - | ^^^ InvalidReact: Writing to a variable defined outside a component or hook is not allowed. Consider using an effect (4:4)
25 + | ^^^ Writing to a variable defined outside a component or hook is not allowed. Consider using an effect
26 5 | return wat;
27 6 | }
28 7 |
29 +
30 +
31 ```
32
33
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-for-await-loops.expect.md
+7 -1
@@ -16,6 +16,10 @@ async function Component({items}) {
16 ## Error
17
18 ```
19 +Found 1 error:
20 +Todo: (BuildHIR::lowerStatement) Handle for-await loops
21 +
22 +error.todo-for-await-loops.ts:3:2
23 1 | async function Component({items}) {
24 2 | const x = [];
25 > 3 | for await (const item of items) {
@@ -23,10 +27,12 @@ async function Component({items}) {
27 > 4 | x.push(item);
28 | ^^^^^^^^^^^^^^^^^
29 > 5 | }
26 - | ^^^^ Todo: (BuildHIR::lowerStatement) Handle for-await loops (3:5)
30 + | ^^^^ (BuildHIR::lowerStatement) Handle for-await loops
31 6 | return x;
32 7 | }
33 8 |
34 +
35 +
36 ```
37
38
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-for-in-loop-with-context-variable-iterator.expect.md
+7 -1
@@ -31,6 +31,10 @@ export const FIXTURE_ENTRYPOINT = {
31 ## Error
32
33 ```
34 +Found 1 error:
35 +Todo: Support non-trivial for..in inits
36 +
37 +error.todo-for-in-loop-with-context-variable-iterator.ts:8:2
38 6 | // NOTE: `item` is a context variable because it's reassigned and also referenced
39 7 | // within a closure, the `onClick` handler of each item
40 > 8 | for (let key in props.data) {
@@ -48,10 +52,12 @@ export const FIXTURE_ENTRYPOINT = {
52 > 14 | );
53 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
54 > 15 | }
51 - | ^^^^ Todo: Support non-trivial for..in inits (8:15)
55 + | ^^^^ Support non-trivial for..in inits
56 16 | return <div>{items}</div>;
57 17 | }
58 18 |
59 +
60 +
61 ```
62
63
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-for-of-loop-with-context-variable-iterator.expect.md
+7 -1
@@ -31,6 +31,10 @@ export const FIXTURE_ENTRYPOINT = {
31 ## Error
32
33 ```
34 +Found 1 error:
35 +Todo: Support non-trivial for..of inits
36 +
37 +error.todo-for-of-loop-with-context-variable-iterator.ts:8:2
38 6 | // NOTE: `item` is a context variable because it's reassigned and also referenced
39 7 | // within a closure, the `onClick` handler of each item
40 > 8 | for (let item of props.data) {
@@ -48,10 +52,12 @@ export const FIXTURE_ENTRYPOINT = {
52 > 14 | );
53 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
54 > 15 | }
51 - | ^^^^ Todo: Support non-trivial for..of inits (8:15)
55 + | ^^^^ Support non-trivial for..of inits
56 16 | return <div>{items}</div>;
57 17 | }
58 18 |
59 +
60 +
61 ```
62
63
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-function-expression-references-later-variable-declaration.expect.md
+9 -1
@@ -17,13 +17,21 @@ function Component() {
17 ## Error
18
19 ```
20 +Found 1 error:
21 +Error: Reassigning a variable after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead
22 +
23 +Variable `onClick` cannot be reassigned after render.
24 +
25 +error.todo-function-expression-references-later-variable-declaration.ts:3:4
26 1 | function Component() {
27 2 | let callback = () => {
28 > 3 | onClick = () => {};
23 - | ^^^^^^^ InvalidReact: Reassigning a variable after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead. Variable `onClick` cannot be reassigned after render (3:3)
29 + | ^^^^^^^ Reassigning a variable after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead
30 4 | };
31 5 | let onClick;
32 6 |
33 +
34 +
35 ```
36
37
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-functiondecl-hoisting.expect.md
+7 -1
@@ -31,13 +31,19 @@ export const FIXTURE_ENTRYPOINT = {
31 ## Error
32
33 ```
34 +Found 1 error:
35 +Todo: [PruneHoistedContexts] Rewrite hoisted function references
36 +
37 +error.todo-functiondecl-hoisting.ts:12:17
38 10 | */
39 11 | function Foo({value}) {
40 > 12 | const result = bar();
37 - | ^^^ Todo: [PruneHoistedContexts] Rewrite hoisted function references (12:12)
41 + | ^^^ [PruneHoistedContexts] Rewrite hoisted function references
42 13 | function bar() {
43 14 | return {value};
44 15 | }
45 +
46 +
47 ```
48
49
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-handle-update-context-identifiers.expect.md
+7 -1
@@ -22,13 +22,19 @@ export const FIXTURE_ENTRYPOINT = {
22 ## Error
23
24 ```
25 +Found 1 error:
26 +Todo: (BuildHIR::lowerExpression) Handle UpdateExpression to variables captured within lambdas.
27 +
28 +error.todo-handle-update-context-identifiers.ts:4:11
29 2 | let counter = 2;
30 3 | const fn = () => {
31 > 4 | return counter++;
28 - | ^^^^^^^^^ Todo: (BuildHIR::lowerExpression) Handle UpdateExpression to variables captured within lambdas. (4:4)
32 + | ^^^^^^^^^ (BuildHIR::lowerExpression) Handle UpdateExpression to variables captured within lambdas.
33 5 | };
34 6 |
35 7 | return fn();
36 +
37 +
38 ```
39
40
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-hoist-function-decls.expect.md
+7 -1
@@ -15,6 +15,10 @@ function Component() {
15 ## Error
16
17 ```
18 +Found 1 error:
19 +Todo: Support functions with unreachable code that may contain hoisted declarations
20 +
21 +error.todo-hoist-function-decls.ts:3:2
22 1 | function Component() {
23 2 | return get2();
24 > 3 | function get2() {
@@ -22,9 +26,11 @@ function Component() {
26 > 4 | return 2;
27 | ^^^^^^^^^^^^^
28 > 5 | }
25 - | ^^^^ Todo: Support functions with unreachable code that may contain hoisted declarations (3:5)
29 + | ^^^^ Support functions with unreachable code that may contain hoisted declarations
30 6 | }
31 7 |
32 +
33 +
34 ```
35
36
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-hoisted-function-in-unreachable-code.expect.md
+7 -1
@@ -16,12 +16,18 @@ function Component() {
16 ## Error
17
18 ```
19 +Found 1 error:
20 +Todo: Support functions with unreachable code that may contain hoisted declarations
21 +
22 +error.todo-hoisted-function-in-unreachable-code.ts:6:2
23 4 |
24 5 | // This is unreachable from a control-flow perspective, but it gets hoisted
25 > 6 | function Foo() {}
22 - | ^^^^^^^^^^^^^^^^^ Todo: Support functions with unreachable code that may contain hoisted declarations (6:6)
26 + | ^^^^^^^^^^^^^^^^^ Support functions with unreachable code that may contain hoisted declarations
27 7 | }
28 8 |
29 +
30 +
31 ```
32
33
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-hoisting-simple-var-declaration.expect.md
+7 -1
@@ -25,13 +25,19 @@ export const FIXTURE_ENTRYPOINT = {
25 ## Error
26
27 ```
28 +Found 1 error:
29 +Todo: (BuildHIR::lowerStatement) Handle var kinds in VariableDeclaration
30 +
31 +error.todo-hoisting-simple-var-declaration.ts:7:2
32 5 | }
33 6 | const result = addOne(2);
34 > 7 | var a = 1;
31 - | ^^^^^^^^^^ Todo: (BuildHIR::lowerStatement) Handle var kinds in VariableDeclaration (7:7)
35 + | ^^^^^^^^^^ (BuildHIR::lowerStatement) Handle var kinds in VariableDeclaration
36 8 |
37 9 | return result; // OK: returns NaN. The code is semantically wrong but technically correct
38 10 | }
39 +
40 +
41 ```
42
43
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-hook-call-spreads-mutable-iterator.expect.md
+7 -1
@@ -21,13 +21,19 @@ export const FIXTURE_ENTRYPOINT = {
21 ## Error
22
23 ```
24 +Found 1 error:
25 +Todo: Support spread syntax for hook arguments
26 +
27 +error.todo-hook-call-spreads-mutable-iterator.ts:5:24
28 3 | function Component() {
29 4 | const items = makeArray(0, 1, 2, null, 4, false, 6);
30 > 5 | return useIdentity(...items.values());
27 - | ^^^^^^^^^^^^^^ Todo: Support spread syntax for hook arguments (5:5)
31 + | ^^^^^^^^^^^^^^ Support spread syntax for hook arguments
32 6 | }
33 7 |
34 8 | export const FIXTURE_ENTRYPOINT = {
35 +
36 +
37 ```
38
39
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-invalid-jsx-in-catch-in-outer-try-with-finally.expect.md
+7 -1
@@ -26,6 +26,10 @@ function Component(props) {
26 ## Error
27
28 ```
29 +Found 1 error:
30 +Todo: (BuildHIR::lowerStatement) Handle TryStatement without a catch clause
31 +
32 +error.todo-invalid-jsx-in-catch-in-outer-try-with-finally.ts:6:2
33 4 | function Component(props) {
34 5 | let el;
35 > 6 | try {
@@ -47,10 +51,12 @@ function Component(props) {
51 > 14 | console.log(el);
52 | ^^^^^^^^^^^^^^
53 > 15 | }
50 - | ^^^^ Todo: (BuildHIR::lowerStatement) Handle TryStatement without a catch clause (6:15)
54 + | ^^^^ (BuildHIR::lowerStatement) Handle TryStatement without a catch clause
55 16 | return el;
56 17 | }
57 18 |
58 +
59 +
60 ```
61
62
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-invalid-jsx-in-try-with-finally.expect.md
+7 -1
@@ -19,6 +19,10 @@ function Component(props) {
19 ## Error
20
21 ```
22 +Found 1 error:
23 +Todo: (BuildHIR::lowerStatement) Handle TryStatement without a catch clause
24 +
25 +error.todo-invalid-jsx-in-try-with-finally.ts:4:2
26 2 | function Component(props) {
27 3 | let el;
28 > 4 | try {
@@ -30,10 +34,12 @@ function Component(props) {
34 > 7 | console.log(el);
35 | ^^^^^^^^^^^^^^^^^
36 > 8 | }
33 - | ^^^^ Todo: (BuildHIR::lowerStatement) Handle TryStatement without a catch clause (4:8)
37 + | ^^^^ (BuildHIR::lowerStatement) Handle TryStatement without a catch clause
38 9 | return el;
39 10 | }
40 11 |
41 +
42 +
43 ```
44
45
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-kitchensink.expect.md
+146 -18
@@ -79,31 +79,159 @@ let moduleLocal = false;
79 ## Error
80
81 ```
82 +Found 10 errors:
83 +Todo: (BuildHIR::lowerStatement) Handle var kinds in VariableDeclaration
84 +
85 +error.todo-kitchensink.ts:3:2
86 1 | function foo([a, b], {c, d, e = 'e'}, f = 'f', ...args) {
87 2 | let i = 0;
88 > 3 | var x = [];
85 - | ^^^^^^^^^^^ Todo: (BuildHIR::lowerStatement) Handle var kinds in VariableDeclaration (3:3)
86 -
87 -UnsupportedJS: Inline `class` declarations are not supported. Move class declarations outside of components/hooks (5:10)
88 -
89 -Todo: (BuildHIR::lowerStatement) Handle non-variable initialization in ForStatement (20:22)
90 -
91 -Todo: (BuildHIR::lowerStatement) Handle non-variable initialization in ForStatement (23:25)
92 -
93 -Todo: (BuildHIR::lowerStatement) Handle non-variable initialization in ForStatement (26:28)
94 -
95 -Todo: (BuildHIR::lowerStatement) Handle empty test in ForStatement (26:28)
89 + | ^^^^^^^^^^^ (BuildHIR::lowerStatement) Handle var kinds in VariableDeclaration
90 + 4 |
91 + 5 | class Bar {
92 + 6 | #secretSauce = 42;
93
97 -Todo: (BuildHIR::lowerExpression) Handle tagged template with interpolations (30:32)
94
99 -Todo: (BuildHIR::lowerExpression) Handle tagged template where cooked value is different from raw value (34:34)
95 +Error: Inline `class` declarations are not supported
96 +
97 +Move class declarations outside of components/hooks.
98 +
99 +error.todo-kitchensink.ts:5:2
100 + 3 | var x = [];
101 + 4 |
102 +> 5 | class Bar {
103 + | ^^^^^^^^^^^
104 +> 6 | #secretSauce = 42;
105 + | ^^^^^^^^^^^^^^^^^^^^^^
106 +> 7 | constructor() {
107 + | ^^^^^^^^^^^^^^^^^^^^^^
108 +> 8 | console.log(this.#secretSauce);
109 + | ^^^^^^^^^^^^^^^^^^^^^^
110 +> 9 | }
111 + | ^^^^^^^^^^^^^^^^^^^^^^
112 +> 10 | }
113 + | ^^^^ Inline `class` declarations are not supported
114 + 11 |
115 + 12 | const g = {b() {}, c: () => {}};
116 + 13 | const {z, aa = 'aa'} = useCustom();
117 +
118 +
119 +Todo: (BuildHIR::lowerStatement) Handle non-variable initialization in ForStatement
120 +
121 +error.todo-kitchensink.ts:20:2
122 + 18 | const j = function bar([quz, qux], ...args) {};
123 + 19 |
124 +> 20 | for (; i < 3; i += 1) {
125 + | ^^^^^^^^^^^^^^^^^^^^^^^
126 +> 21 | x.push(i);
127 + | ^^^^^^^^^^^^^^
128 +> 22 | }
129 + | ^^^^ (BuildHIR::lowerStatement) Handle non-variable initialization in ForStatement
130 + 23 | for (; i < 3; ) {
131 + 24 | break;
132 + 25 | }
133 +
134 +
135 +Todo: (BuildHIR::lowerStatement) Handle non-variable initialization in ForStatement
136 +
137 +error.todo-kitchensink.ts:23:2
138 + 21 | x.push(i);
139 + 22 | }
140 +> 23 | for (; i < 3; ) {
141 + | ^^^^^^^^^^^^^^^^^
142 +> 24 | break;
143 + | ^^^^^^^^^^
144 +> 25 | }
145 + | ^^^^ (BuildHIR::lowerStatement) Handle non-variable initialization in ForStatement
146 + 26 | for (;;) {
147 + 27 | break;
148 + 28 | }
149 +
150 +
151 +Todo: (BuildHIR::lowerStatement) Handle non-variable initialization in ForStatement
152 +
153 +error.todo-kitchensink.ts:26:2
154 + 24 | break;
155 + 25 | }
156 +> 26 | for (;;) {
157 + | ^^^^^^^^^^
158 +> 27 | break;
159 + | ^^^^^^^^^^
160 +> 28 | }
161 + | ^^^^ (BuildHIR::lowerStatement) Handle non-variable initialization in ForStatement
162 + 29 |
163 + 30 | graphql`
164 + 31 | ${g}
165 +
166 +
167 +Todo: (BuildHIR::lowerStatement) Handle empty test in ForStatement
168 +
169 +error.todo-kitchensink.ts:26:2
170 + 24 | break;
171 + 25 | }
172 +> 26 | for (;;) {
173 + | ^^^^^^^^^^
174 +> 27 | break;
175 + | ^^^^^^^^^^
176 +> 28 | }
177 + | ^^^^ (BuildHIR::lowerStatement) Handle empty test in ForStatement
178 + 29 |
179 + 30 | graphql`
180 + 31 | ${g}
181 +
182 +
183 +Todo: (BuildHIR::lowerExpression) Handle tagged template with interpolations
184 +
185 +error.todo-kitchensink.ts:30:2
186 + 28 | }
187 + 29 |
188 +> 30 | graphql`
189 + | ^^^^^^^^
190 +> 31 | ${g}
191 + | ^^^^^^^^
192 +> 32 | `;
193 + | ^^^^ (BuildHIR::lowerExpression) Handle tagged template with interpolations
194 + 33 |
195 + 34 | graphql`\\t\n`;
196 + 35 |
197 +
198 +
199 +Todo: (BuildHIR::lowerExpression) Handle tagged template where cooked value is different from raw value
200 +
201 +error.todo-kitchensink.ts:34:2
202 + 32 | `;
203 + 33 |
204 +> 34 | graphql`\\t\n`;
205 + | ^^^^^^^^^^^^^^ (BuildHIR::lowerExpression) Handle tagged template where cooked value is different from raw value
206 + 35 |
207 + 36 | for (c of [1, 2]) {
208 + 37 | }
209 +
210 +
211 +Todo: (BuildHIR::node.lowerReorderableExpression) Expression type `MemberExpression` cannot be safely reordered
212 +
213 +error.todo-kitchensink.ts:57:9
214 + 55 | case foo(): {
215 + 56 | }
216 +> 57 | case x.y: {
217 + | ^^^ (BuildHIR::node.lowerReorderableExpression) Expression type `MemberExpression` cannot be safely reordered
218 + 58 | }
219 + 59 | default: {
220 + 60 | }
221 +
222 +
223 +Todo: (BuildHIR::node.lowerReorderableExpression) Expression type `BinaryExpression` cannot be safely reordered
224 +
225 +error.todo-kitchensink.ts:53:9
226 + 51 |
227 + 52 | switch (i) {
228 +> 53 | case 1 + 1: {
229 + | ^^^^^ (BuildHIR::node.lowerReorderableExpression) Expression type `BinaryExpression` cannot be safely reordered
230 + 54 | }
231 + 55 | case foo(): {
232 + 56 | }
233
101 -Todo: (BuildHIR::node.lowerReorderableExpression) Expression type `MemberExpression` cannot be safely reordered (57:57)
234
103 -Todo: (BuildHIR::node.lowerReorderableExpression) Expression type `BinaryExpression` cannot be safely reordered (53:53)
104 - 4 |
105 - 5 | class Bar {
106 - 6 | #secretSauce = 42;
235 ```
236
237
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-logical-expression-within-try-catch.expect.md
+7 -1
@@ -18,13 +18,19 @@ function Component(props) {
18 ## Error
19
20 ```
21 +Found 1 error:
22 +Todo: Support value blocks (conditional, logical, optional chaining, etc) within a try/catch statement
23 +
24 +error.todo-logical-expression-within-try-catch.ts:4:13
25 2 | let result;
26 3 | try {
27 > 4 | result = props.cond && props.foo;
24 - | ^^^^^ Todo: Support value blocks (conditional, logical, optional chaining, etc) within a try/catch statement (4:4)
28 + | ^^^^^ Support value blocks (conditional, logical, optional chaining, etc) within a try/catch statement
29 5 | } catch (e) {
30 6 | console.log(e);
31 7 | }
32 +
33 +
34 ```
35
36
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-nested-method-calls-lower-property-load-into-temporary.expect.md
+7 -1
@@ -22,13 +22,19 @@ export const FIXTURE_ENTRYPOINT = {
22 ## Error
23
24 ```
25 +Found 1 error:
26 +Invariant: [Codegen] Internal error: MethodCall::property must be an unpromoted + unmemoized MemberExpression. Got a `Identifier`
27 +
28 +error.todo-nested-method-calls-lower-property-load-into-temporary.ts:6:14
29 4 | function Component({}) {
30 5 | const items = makeArray(0, 1, 2, null, 4, false, 6);
31 > 6 | const max = Math.max(2, items.push(5), ...other);
28 - | ^^^^^^^^ Invariant: [Codegen] Internal error: MethodCall::property must be an unpromoted + unmemoized MemberExpression. Got a `Identifier` (6:6)
32 + | ^^^^^^^^ [Codegen] Internal error: MethodCall::property must be an unpromoted + unmemoized MemberExpression. Got a `Identifier`
33 7 | return max;
34 8 | }
35 9 |
36 +
37 +
38 ```
39
40
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-new-target-meta-property.expect.md
+7 -1
@@ -15,13 +15,19 @@ function foo() {
15 ## Error
16
17 ```
18 +Found 1 error:
19 +Todo: (BuildHIR::lowerExpression) Handle MetaProperty expressions other than import.meta
20 +
21 +error.todo-new-target-meta-property.ts:4:13
22 2 |
23 3 | function foo() {
24 > 4 | const nt = new.target;
21 - | ^^^^^^^^^^ Todo: (BuildHIR::lowerExpression) Handle MetaProperty expressions other than import.meta (4:4)
25 + | ^^^^^^^^^^ (BuildHIR::lowerExpression) Handle MetaProperty expressions other than import.meta
26 5 | return <Stringify value={nt} />;
27 6 | }
28 7 |
29 +
30 +
31 ```
32
33
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-object-expression-computed-key-modified-during-after-construction-sequence-expr.expect.md
+7 -1
@@ -24,13 +24,19 @@ export const FIXTURE_ENTRYPOINT = {
24 ## Error
25
26 ```
27 +Found 1 error:
28 +Todo: (BuildHIR::lowerExpression) Expected Identifier, got SequenceExpression key in ObjectExpression
29 +
30 +error.todo-object-expression-computed-key-modified-during-after-construction-sequence-expr.ts:6:6
31 4 | const key = {};
32 5 | const context = {
33 > 6 | [(mutate(key), key)]: identity([props.value]),
30 - | ^^^^^^^^^^^^^^^^ Todo: (BuildHIR::lowerExpression) Expected Identifier, got SequenceExpression key in ObjectExpression (6:6)
34 + | ^^^^^^^^^^^^^^^^ (BuildHIR::lowerExpression) Expected Identifier, got SequenceExpression key in ObjectExpression
35 7 | };
36 8 | mutate(key);
37 9 | return context;
38 +
39 +
40 ```
41
42
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-object-expression-computed-key-modified-during-after-construction.expect.md
+7 -1
@@ -24,13 +24,19 @@ export const FIXTURE_ENTRYPOINT = {
24 ## Error
25
26 ```
27 +Found 1 error:
28 +Todo: (BuildHIR::lowerExpression) Expected Identifier, got CallExpression key in ObjectExpression
29 +
30 +error.todo-object-expression-computed-key-modified-during-after-construction.ts:6:5
31 4 | const key = {};
32 5 | const context = {
33 > 6 | [mutateAndReturn(key)]: identity([props.value]),
30 - | ^^^^^^^^^^^^^^^^^^^^ Todo: (BuildHIR::lowerExpression) Expected Identifier, got CallExpression key in ObjectExpression (6:6)
34 + | ^^^^^^^^^^^^^^^^^^^^ (BuildHIR::lowerExpression) Expected Identifier, got CallExpression key in ObjectExpression
35 7 | };
36 8 | mutate(key);
37 9 | return context;
38 +
39 +
40 ```
41
42
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-object-expression-computed-key-mutate-key-while-constructing-object.expect.md
+7 -1
@@ -23,13 +23,19 @@ export const FIXTURE_ENTRYPOINT = {
23 ## Error
24
25 ```
26 +Found 1 error:
27 +Todo: (BuildHIR::lowerExpression) Expected Identifier, got CallExpression key in ObjectExpression
28 +
29 +error.todo-object-expression-computed-key-mutate-key-while-constructing-object.ts:6:5
30 4 | const key = {};
31 5 | const context = {
32 > 6 | [mutateAndReturn(key)]: identity([props.value]),
29 - | ^^^^^^^^^^^^^^^^^^^^ Todo: (BuildHIR::lowerExpression) Expected Identifier, got CallExpression key in ObjectExpression (6:6)
33 + | ^^^^^^^^^^^^^^^^^^^^ (BuildHIR::lowerExpression) Expected Identifier, got CallExpression key in ObjectExpression
34 7 | };
35 8 | return context;
36 9 | }
37 +
38 +
39 ```
40
41
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-object-expression-get-syntax.expect.md
+7 -1
@@ -23,6 +23,10 @@ export const FIXTURE_ENTRYPOINT = {
23 ## Error
24
25 ```
26 +Found 1 error:
27 +Todo: (BuildHIR::lowerExpression) Handle get functions in ObjectExpression
28 +
29 +error.todo-object-expression-get-syntax.ts:3:4
30 1 | function Component({value}) {
31 2 | const object = {
32 > 3 | get value() {
@@ -30,10 +34,12 @@ export const FIXTURE_ENTRYPOINT = {
34 > 4 | return value;
35 | ^^^^^^^^^^^^^^^^^^^
36 > 5 | },
33 - | ^^^^^^ Todo: (BuildHIR::lowerExpression) Handle get functions in ObjectExpression (3:5)
37 + | ^^^^^^ (BuildHIR::lowerExpression) Handle get functions in ObjectExpression
38 6 | };
39 7 | return <div>{object.value}</div>;
40 8 | }
41 +
42 +
43 ```
44
45
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-object-expression-member-expr-call.expect.md
+7 -1
@@ -25,13 +25,19 @@ export const FIXTURE_ENTRYPOINT = {
25 ## Error
26
27 ```
28 +Found 1 error:
29 +Todo: (BuildHIR::lowerExpression) Expected Identifier, got CallExpression key in ObjectExpression
30 +
31 +error.todo-object-expression-member-expr-call.ts:7:5
32 5 | const key = {};
33 6 | const context = {
34 > 7 | [obj.mutateAndReturn(key)]: identity([props.value]),
31 - | ^^^^^^^^^^^^^^^^^^^^^^^^ Todo: (BuildHIR::lowerExpression) Expected Identifier, got CallExpression key in ObjectExpression (7:7)
35 + | ^^^^^^^^^^^^^^^^^^^^^^^^ (BuildHIR::lowerExpression) Expected Identifier, got CallExpression key in ObjectExpression
36 8 | };
37 9 | mutate(key);
38 10 | return context;
39 +
40 +
41 ```
42
43
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-object-expression-set-syntax.expect.md
+7 -1
@@ -25,6 +25,10 @@ export const FIXTURE_ENTRYPOINT = {
25 ## Error
26
27 ```
28 +Found 1 error:
29 +Todo: (BuildHIR::lowerExpression) Handle set functions in ObjectExpression
30 +
31 +error.todo-object-expression-set-syntax.ts:4:4
32 2 | let value;
33 3 | const object = {
34 > 4 | set value(v) {
@@ -32,10 +36,12 @@ export const FIXTURE_ENTRYPOINT = {
36 > 5 | value = v;
37 | ^^^^^^^^^^^^^^^^
38 > 6 | },
35 - | ^^^^^^ Todo: (BuildHIR::lowerExpression) Handle set functions in ObjectExpression (4:6)
39 + | ^^^^^^ (BuildHIR::lowerExpression) Handle set functions in ObjectExpression
40 7 | };
41 8 | object.value = props.value;
42 9 | return <div>{value}</div>;
43 +
44 +
45 ```
46
47
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-optional-call-chain-in-logical-expr.expect.md
+7 -1
@@ -20,13 +20,19 @@ export const FIXTURE_ENTRYPONT = {
20 ## Error
21
22 ```
23 +Found 1 error:
24 +Todo: Unexpected terminal kind `optional` for logical test block
25 +
26 +error.todo-optional-call-chain-in-logical-expr.ts:5:30
27 3 | function useFoo(props: {value: {x: string; y: string} | null}) {
28 4 | const value = props.value;
29 > 5 | return useNoAlias(value?.x, value?.y) ?? {};
26 - | ^^^^^^^^ Todo: Unexpected terminal kind `optional` for logical test block (5:5)
30 + | ^^^^^^^^ Unexpected terminal kind `optional` for logical test block
31 6 | }
32 7 |
33 8 | export const FIXTURE_ENTRYPONT = {
34 +
35 +
36 ```
37
38
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-optional-call-chain-in-optional.expect.md
+7 -1
@@ -22,13 +22,19 @@ export const FIXTURE_ENTRYPONT = {
22 ## Error
23
24 ```
25 +Found 1 error:
26 +Todo: Unexpected terminal kind `optional` for optional fallthrough block
27 +
28 +error.todo-optional-call-chain-in-optional.ts:3:21
29 1 | function useFoo(props: {value: {x: string; y: string} | null}) {
30 2 | const value = props.value;
31 > 3 | return createArray(value?.x, value?.y)?.join(', ');
28 - | ^^^^^^^^ Todo: Unexpected terminal kind `optional` for optional fallthrough block (3:3)
32 + | ^^^^^^^^ Unexpected terminal kind `optional` for optional fallthrough block
33 4 | }
34 5 |
35 6 | function createArray<T>(...args: Array<T>): Array<T> {
36 +
37 +
38 ```
39
40
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-optional-call-chain-in-ternary.expect.md
+7 -1
@@ -20,13 +20,19 @@ export const FIXTURE_ENTRYPONT = {
20 ## Error
21
22 ```
23 +Found 1 error:
24 +Todo: Unexpected terminal kind `optional` for ternary test block
25 +
26 +error.todo-optional-call-chain-in-ternary.ts:5:30
27 3 | function useFoo(props: {value: {x: string; y: string} | null}) {
28 4 | const value = props.value;
29 > 5 | return useNoAlias(value?.x, value?.y) ? {} : null;
26 - | ^^^^^^^^ Todo: Unexpected terminal kind `optional` for ternary test block (5:5)
30 + | ^^^^^^^^ Unexpected terminal kind `optional` for ternary test block
31 6 | }
32 7 |
33 8 | export const FIXTURE_ENTRYPONT = {
34 +
35 +
36 ```
37
38
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-reassign-const.expect.md
+7 -1
@@ -21,13 +21,19 @@ function Component({foo}) {
21 ## Error
22
23 ```
24 +Found 1 error:
25 +Todo: Support destructuring of context variables
26 +
27 +error.todo-reassign-const.ts:3:20
28 1 | import {Stringify} from 'shared-runtime';
29 2 |
30 > 3 | function Component({foo}) {
27 - | ^^^ Todo: Support destructuring of context variables (3:3)
31 + | ^^^ Support destructuring of context variables
32 4 | let bar = foo.bar;
33 5 | return (
34 6 | <Stringify
35 +
36 +
37 ```
38
39
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-repro-declaration-for-all-identifiers.expect.md
+7 -1
@@ -16,13 +16,19 @@ function Foo() {
16 ## Error
17
18 ```
19 +Found 1 error:
20 +Todo: Support value blocks (conditional, logical, optional chaining, etc) within a try/catch statement
21 +
22 +error.todo-repro-declaration-for-all-identifiers.ts:5:20
23 3 | // NOTE: this fixture previously failed during LeaveSSA;
24 4 | // double-check this code when supporting value blocks in try/catch
25 > 5 | for (let i = 0; i < 2; i++) {}
22 - | ^ Todo: Support value blocks (conditional, logical, optional chaining, etc) within a try/catch statement (5:5)
26 + | ^ Support value blocks (conditional, logical, optional chaining, etc) within a try/catch statement
27 6 | } catch {}
28 7 | }
29 8 |
30 +
31 +
32 ```
33
34
\ No newline at end of file
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
+7 -1
@@ -42,13 +42,19 @@ component Component() {
42 ## Error
43
44 ```
45 +Found 1 error:
46 +Memoization: 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.
47 +
48 +undefined:18:20
49 16 | // We infer that getIsEnabled returns a mutable value, such that
50 17 | // isEnabled is mutable
51 > 18 | const isEnabled = useMemo(() => getIsEnabled(), [getIsEnabled]);
48 - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ CannotPreserveMemoization: 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. (18:18)
52 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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.
53 19 |
54 20 | // We then infer getLoggingData as capturing that mutable value,
55 21 | // so any calls to this function are then inferred as extending
56 +
57 +
58 ```
59
60
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-repro-missed-memoization-from-inferred-mutation-in-logger.expect.md
+46 -4
@@ -52,6 +52,10 @@ component Component(id) {
52 ## Error
53
54 ```
55 +Found 3 errors:
56 +Memoization: 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.
57 +
58 +undefined:11:18
59 9 | const [index, setIndex] = useState(0);
60 10 |
61 > 11 | const logData = useMemo(() => {
@@ -65,14 +69,52 @@ component Component(id) {
69 > 15 | };
70 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
71 > 16 | }, [index, items]);
68 - | ^^^^^^^^^^^^^^^^^^^^^ CannotPreserveMemoization: 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. (11:16)
72 + | ^^^^^^^^^^^^^^^^^^^^^ 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.
73 + 17 |
74 + 18 | const setCurrentIndex = useCallback(
75 + 19 | (index: number) => {
76 +
77 +
78 +Memoization: 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
79
70 -CannotPreserveMemoization: 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 (28:28)
80 +undefined:28:12
81 + 26 | setIndex(index);
82 + 27 | },
83 +> 28 | [index, logData, items]
84 + | ^^^^^^^ 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
85 + 29 | );
86 + 30 |
87 + 31 | if (prevId !== id) {
88
72 -CannotPreserveMemoization: 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. (19:27)
89 +
90 +Memoization: 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.
91 +
92 +undefined:19:4
93 17 |
94 18 | const setCurrentIndex = useCallback(
75 - 19 | (index: number) => {
95 +> 19 | (index: number) => {
96 + | ^^^^^^^^^^^^^^^^^^^^
97 +> 20 | const object = {
98 + | ^^^^^^^^^^^^^^^^^^^^^^
99 +> 21 | tracking: logData.key,
100 + | ^^^^^^^^^^^^^^^^^^^^^^
101 +> 22 | };
102 + | ^^^^^^^^^^^^^^^^^^^^^^
103 +> 23 | // We infer that this may mutate `object`, which in turn aliases
104 + | ^^^^^^^^^^^^^^^^^^^^^^
105 +> 24 | // data from `logData`, such that `logData` may be mutated.
106 + | ^^^^^^^^^^^^^^^^^^^^^^
107 +> 25 | LogEvent.log(() => object);
108 + | ^^^^^^^^^^^^^^^^^^^^^^
109 +> 26 | setIndex(index);
110 + | ^^^^^^^^^^^^^^^^^^^^^^
111 +> 27 | },
112 + | ^^^^^^ 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.
113 + 28 | [index, logData, items]
114 + 29 | );
115 + 30 |
116 +
117 +
118 ```
119
120
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-repro-named-function-with-shadowed-local-same-name.expect.md
+9 -1
@@ -19,12 +19,20 @@ function Component(props) {
19 ## Error
20
21 ```
22 +Found 1 error:
23 +Invariant: [InferMutationAliasingEffects] Expected value kind to be initialized
24 +
25 +<unknown> hasErrors_0$15:TFunction.
26 +
27 +error.todo-repro-named-function-with-shadowed-local-same-name.ts:9:9
28 7 | return hasErrors;
29 8 | }
30 > 9 | return hasErrors();
25 - | ^^^^^^^^^ Invariant: [InferMutationAliasingEffects] Expected value kind to be initialized. <unknown> hasErrors_0$15:TFunction (9:9)
31 + | ^^^^^^^^^ [InferMutationAliasingEffects] Expected value kind to be initialized
32 10 | }
33 11 |
34 +
35 +
36 ```
37
38
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-repro-unmemoized-callback-captured-in-context-variable.expect.md
+7 -1
@@ -50,13 +50,19 @@ export const FIXTURE_ENTRYPOINT = {
50 ## Error
51
52 ```
53 +Found 1 error:
54 +Memoization: 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.
55 +
56 +error.todo-repro-unmemoized-callback-captured-in-context-variable.ts:11:12
57 9 | const a = useHook();
58 10 | // Because b is also part of that same mutable range, it can't be memoized either
59 > 11 | const b = useMemo(() => ({}), []);
56 - | ^^^^^^^^^^^^^^^^^^^^^^^ CannotPreserveMemoization: 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. (11:11)
60 + | ^^^^^^^^^^^^^^^^^^^^^^^ 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.
61 12 |
62 13 | // Conditional assignment without a subsequent mutation normally doesn't create a mutable
63 14 | // range, but in this case we're reassigning a context variable
64 +
65 +
66 ```
67
68
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-useCallback-set-ref-nested-property-ref-modified-later-preserve-memoization.expect.md
+7 -1
@@ -31,13 +31,19 @@ export const FIXTURE_ENTRYPOINT = {
31 ## Error
32
33 ```
34 +Found 1 error:
35 +Error: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
36 +
37 +error.todo-useCallback-set-ref-nested-property-ref-modified-later-preserve-memoization.ts:14:2
38 12 |
39 13 | // The ref is modified later, extending its range and preventing memoization of onChange
40 > 14 | ref.current.inner = null;
37 - | ^^^^^^^^^^^ InvalidReact: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef) (14:14)
41 + | ^^^^^^^^^^^ Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
42 15 |
43 16 | return <input onChange={onChange} />;
44 17 | }
45 +
46 +
47 ```
48
49
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo-valid-functiondecl-hoisting.expect.md
+7 -1
@@ -34,13 +34,19 @@ export const FIXTURE_ENTRYPOINT = {
34 ## Error
35
36 ```
37 +Found 1 error:
38 +Todo: [PruneHoistedContexts] Rewrite hoisted function references
39 +
40 +error.todo-valid-functiondecl-hoisting.ts:13:11
41 11 |
42 12 | function foo() {
43 > 13 | return bar();
40 - | ^^^ Todo: [PruneHoistedContexts] Rewrite hoisted function references (13:13)
44 + | ^^^ [PruneHoistedContexts] Rewrite hoisted function references
45 14 | }
46 15 | function bar() {
47 16 | return 42;
48 +
49 +
50 ```
51
52
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.todo.try-catch-with-throw.expect.md
+7 -1
@@ -18,13 +18,19 @@ function Component(props) {
18 ## Error
19
20 ```
21 +Found 1 error:
22 +Todo: (BuildHIR::lowerStatement) Support ThrowStatement inside of try/catch
23 +
24 +error.todo.try-catch-with-throw.ts:4:4
25 2 | let x;
26 3 | try {
27 > 4 | throw [];
24 - | ^^^^^^^^^ Todo: (BuildHIR::lowerStatement) Support ThrowStatement inside of try/catch (4:4)
28 + | ^^^^^^^^^ (BuildHIR::lowerStatement) Support ThrowStatement inside of try/catch
29 5 | } catch (e) {
30 6 | x.push(e);
31 7 | }
32 +
33 +
34 ```
35
36
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.unconditional-set-state-in-render-after-loop-break.expect.md
+7 -1
@@ -22,13 +22,19 @@ function Component(props) {
22 ## Error
23
24 ```
25 +Found 1 error:
26 +Error: This is an unconditional set state during render, which will trigger an infinite loop. (https://react.dev/reference/react/useState)
27 +
28 +error.unconditional-set-state-in-render-after-loop-break.ts:11:2
29 9 | }
30 10 | }
31 > 11 | setState(true);
28 - | ^^^^^^^^ InvalidReact: This is an unconditional set state during render, which will trigger an infinite loop. (https://react.dev/reference/react/useState) (11:11)
32 + | ^^^^^^^^ This is an unconditional set state during render, which will trigger an infinite loop. (https://react.dev/reference/react/useState)
33 12 | return state;
34 13 | }
35 14 |
36 +
37 +
38 ```
39
40
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.unconditional-set-state-in-render-after-loop.expect.md
+7 -1
@@ -17,13 +17,19 @@ function Component(props) {
17 ## Error
18
19 ```
20 +Found 1 error:
21 +Error: This is an unconditional set state during render, which will trigger an infinite loop. (https://react.dev/reference/react/useState)
22 +
23 +error.unconditional-set-state-in-render-after-loop.ts:6:2
24 4 | for (const _ of props) {
25 5 | }
26 > 6 | setState(true);
23 - | ^^^^^^^^ InvalidReact: This is an unconditional set state during render, which will trigger an infinite loop. (https://react.dev/reference/react/useState) (6:6)
27 + | ^^^^^^^^ This is an unconditional set state during render, which will trigger an infinite loop. (https://react.dev/reference/react/useState)
28 7 | return state;
29 8 | }
30 9 |
31 +
32 +
33 ```
34
35
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.unconditional-set-state-in-render-with-loop-throw.expect.md
+7 -1
@@ -22,13 +22,19 @@ function Component(props) {
22 ## Error
23
24 ```
25 +Found 1 error:
26 +Error: This is an unconditional set state during render, which will trigger an infinite loop. (https://react.dev/reference/react/useState)
27 +
28 +error.unconditional-set-state-in-render-with-loop-throw.ts:11:2
29 9 | }
30 10 | }
31 > 11 | setState(true);
28 - | ^^^^^^^^ InvalidReact: This is an unconditional set state during render, which will trigger an infinite loop. (https://react.dev/reference/react/useState) (11:11)
32 + | ^^^^^^^^ This is an unconditional set state during render, which will trigger an infinite loop. (https://react.dev/reference/react/useState)
33 12 | return state;
34 13 | }
35 14 |
36 +
37 +
38 ```
39
40
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.unconditional-set-state-lambda.expect.md
+7 -1
@@ -20,13 +20,19 @@ function Component(props) {
20 ## Error
21
22 ```
23 +Found 1 error:
24 +Error: This is an unconditional set state during render, which will trigger an infinite loop. (https://react.dev/reference/react/useState)
25 +
26 +error.unconditional-set-state-lambda.ts:8:2
27 6 | setX(1);
28 7 | };
29 > 8 | foo();
26 - | ^^^ InvalidReact: This is an unconditional set state during render, which will trigger an infinite loop. (https://react.dev/reference/react/useState) (8:8)
30 + | ^^^ This is an unconditional set state during render, which will trigger an infinite loop. (https://react.dev/reference/react/useState)
31 9 |
32 10 | return [x];
33 11 | }
34 +
35 +
36 ```
37
38
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.unconditional-set-state-nested-function-expressions.expect.md
+7 -1
@@ -28,13 +28,19 @@ function Component(props) {
28 ## Error
29
30 ```
31 +Found 1 error:
32 +Error: This is an unconditional set state during render, which will trigger an infinite loop. (https://react.dev/reference/react/useState)
33 +
34 +error.unconditional-set-state-nested-function-expressions.ts:16:2
35 14 | bar();
36 15 | };
37 > 16 | baz();
34 - | ^^^ InvalidReact: This is an unconditional set state during render, which will trigger an infinite loop. (https://react.dev/reference/react/useState) (16:16)
38 + | ^^^ This is an unconditional set state during render, which will trigger an infinite loop. (https://react.dev/reference/react/useState)
39 17 |
40 18 | return [x];
41 19 | }
42 +
43 +
44 ```
45
46
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.update-global-should-bailout.expect.md
+7 -1
@@ -19,13 +19,19 @@ export const FIXTURE_ENTRYPOINT = {
19 ## Error
20
21 ```
22 +Found 1 error:
23 +Error: Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render)
24 +
25 +error.update-global-should-bailout.ts:3:2
26 1 | let renderCount = 0;
27 2 | function useFoo() {
28 > 3 | renderCount += 1;
25 - | ^^^^^^^^^^^^^^^^ InvalidReact: Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render) (3:3)
29 + | ^^^^^^^^^^^^^^^^ Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render)
30 4 | return renderCount;
31 5 | }
32 6 |
33 +
34 +
35 ```
36
37
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.useCallback-accesses-ref-mutated-later-via-function-preserve-memoization.expect.md
+18 -2
@@ -34,15 +34,31 @@ export const FIXTURE_ENTRYPOINT = {
34 ## Error
35
36 ```
37 +Found 2 errors:
38 +Error: This function accesses a ref value (the `current` property), which may not be accessed during render. (https://react.dev/reference/react/useRef)
39 +
40 +error.useCallback-accesses-ref-mutated-later-via-function-preserve-memoization.ts:17:2
41 15 | ref.current.inner = null;
42 16 | };
43 > 17 | reset();
40 - | ^^^^^ InvalidReact: This function accesses a ref value (the `current` property), which may not be accessed during render. (https://react.dev/reference/react/useRef) (17:17)
44 + | ^^^^^ This function accesses a ref value (the `current` property), which may not be accessed during render. (https://react.dev/reference/react/useRef)
45 + 18 |
46 + 19 | return <input onChange={onChange} />;
47 + 20 | }
48 +
49 +
50 +Error: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
51
42 -InvalidReact: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef) (17:17)
52 +error.useCallback-accesses-ref-mutated-later-via-function-preserve-memoization.ts:17:2
53 + 15 | ref.current.inner = null;
54 + 16 | };
55 +> 17 | reset();
56 + | ^^^^^ Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
57 18 |
58 19 | return <input onChange={onChange} />;
59 20 | }
60 +
61 +
62 ```
63
64
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.useCallback-set-ref-nested-property-dont-preserve-memoization.expect.md
+7 -1
@@ -30,13 +30,19 @@ export const FIXTURE_ENTRYPOINT = {
30 ## Error
31
32 ```
33 +Found 1 error:
34 +Error: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
35 +
36 +error.useCallback-set-ref-nested-property-dont-preserve-memoization.ts:13:2
37 11 | });
38 12 |
39 > 13 | ref.current.inner = null;
36 - | ^^^^^^^^^^^ InvalidReact: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef) (13:13)
40 + | ^^^^^^^^^^^ Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
41 14 |
42 15 | return <input onChange={onChange} />;
43 16 | }
44 +
45 +
46 ```
47
48
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.useMemo-callback-generator.expect.md
+7 -1
@@ -18,13 +18,19 @@ function component(a, b) {
18 ## Error
19
20 ```
21 +Found 1 error:
22 +Todo: (BuildHIR::lowerExpression) Handle YieldExpression expressions
23 +
24 +error.useMemo-callback-generator.ts:6:4
25 4 | // add support for generators in the future.
26 5 | let x = useMemo(function* () {
27 > 6 | yield a;
24 - | ^^^^^^^ Todo: (BuildHIR::lowerExpression) Handle YieldExpression expressions (6:6)
28 + | ^^^^^^^ (BuildHIR::lowerExpression) Handle YieldExpression expressions
29 7 | }, []);
30 8 | return x;
31 9 | }
32 +
33 +
34 ```
35
36
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.useMemo-non-literal-depslist.expect.md
+7 -1
@@ -28,13 +28,19 @@ export const FIXTURE_ENTRYPOINT = {
28 ## Error
29
30 ```
31 +Found 1 error:
32 +Error: Expected the dependency list for useMemo to be an array literal
33 +
34 +error.useMemo-non-literal-depslist.ts:10:4
35 8 | return text.toUpperCase();
36 9 | },
37 > 10 | hasDeps ? null : [text], // should be DCE'd
34 - | ^^^^^^^^^^^^^^^^^^^^^^^ InvalidReact: Expected the dependency list for useMemo to be an array literal (10:10)
38 + | ^^^^^^^^^^^^^^^^^^^^^^^ Expected the dependency list for useMemo to be an array literal
39 11 | );
40 12 | return resolvedText;
41 13 | }
42 +
43 +
44 ```
45
46
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.validate-blocklisted-imports.expect.md
+9 -1
@@ -17,12 +17,20 @@ function useHook() {
17 ## Error
18
19 ```
20 +Found 1 error:
21 +Todo: Bailing out due to blocklisted import
22 +
23 +Import from module DangerousImport.
24 +
25 +error.validate-blocklisted-imports.ts:2:0
26 1 | // @validateBlocklistedImports:["DangerousImport"]
27 > 2 | import {foo} from 'DangerousImport';
22 - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Todo: Bailing out due to blocklisted import. Import from module DangerousImport (2:2)
28 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Bailing out due to blocklisted import
29 3 | import {useIdentity} from 'shared-runtime';
30 4 |
31 5 | function useHook() {
32 +
33 +
34 ```
35
36
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.validate-memoized-effect-deps-invalidated-dep-value.expect.md
+7 -1
@@ -28,6 +28,10 @@ export const FIXTURE_ENTRYPOINT = {
28 ## Error
29
30 ```
31 +Found 1 error:
32 +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
33 +
34 +error.validate-memoized-effect-deps-invalidated-dep-value.ts:11:2
35 9 | const y = [x];
36 10 |
37 > 11 | useEffect(() => {
@@ -35,10 +39,12 @@ export const FIXTURE_ENTRYPOINT = {
39 > 12 | console.log(y);
40 | ^^^^^^^^^^^^^^^^^^^
41 > 13 | }, [y]);
38 - | ^^^^^^^^^^ CannotPreserveMemoization: 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 (11:13)
42 + | ^^^^^^^^^^ 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
43 14 | }
44 15 |
45 16 | export const FIXTURE_ENTRYPOINT = {
46 +
47 +
48 ```
49
50
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.validate-mutate-ref-arg-in-render.expect.md
+7 -1
@@ -20,13 +20,19 @@ export const FIXTURE_ENTRYPOINT = {
20 ## Error
21
22 ```
23 +Found 1 error:
24 +Error: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
25 +
26 +error.validate-mutate-ref-arg-in-render.ts:3:14
27 1 | // @validateRefAccessDuringRender:true
28 2 | function Foo(props, ref) {
29 > 3 | console.log(ref.current);
26 - | ^^^^^^^^^^^ InvalidReact: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef) (3:3)
30 + | ^^^^^^^^^^^ Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
31 4 | return <div>{props.bar}</div>;
32 5 | }
33 6 |
34 +
35 +
36 ```
37
38
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/error.todo-fbt-as-local.expect.md
+7 -1
@@ -50,10 +50,16 @@ export const FIXTURE_ENTRYPOINT = {
50 ## Error
51
52 ```
53 +Found 1 error:
54 +Todo: Support local variables named `fbt`
55 +
56 +Local variables named `fbt` may conflict with the fbt plugin and are not yet supported
57 +
58 +error.todo-fbt-as-local.ts:18:19
59 16 |
60 17 | function Foo(props) {
61 > 18 | const getText1 = fbt =>
56 - | ^^^ Todo: Support local variables named "fbt" (18:18)
62 + | ^^^ Rename to avoid conflict with fbt plugin
63 19 | fbt(
64 20 | `Hello, ${fbt.param('(key) name', identity(props.name))}!`,
65 21 | '(description) Greeting'
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/error.todo-fbt-unknown-enum-value.expect.md
+16 -1
@@ -19,10 +19,25 @@ function Component({a, b}) {
19 ## Error
20
21 ```
22 +Found 1 error:
23 +Todo: Support duplicate fbt tags
24 +
25 +Support `<fbt>` tags with multiple `<fbt:enum>` values
26 +
27 +error.todo-fbt-unknown-enum-value.ts:6:7
28 + 4 | return (
29 + 5 | <fbt desc="Description">
30 +> 6 | <fbt:enum enum-range={['avalue1', 'avalue1']} value={a} />{' '}
31 + | ^^^^^^^^ Multiple `<fbt:enum>` tags found
32 + 7 | <fbt:enum enum-range={['bvalue1', 'bvalue2']} value={b} />
33 + 8 | </fbt>
34 + 9 | );
35 +
36 +error.todo-fbt-unknown-enum-value.ts:7:7
37 5 | <fbt desc="Description">
38 6 | <fbt:enum enum-range={['avalue1', 'avalue1']} value={a} />{' '}
39 > 7 | <fbt:enum enum-range={['bvalue1', 'bvalue2']} value={b} />
25 - | ^^^^^^^^ Todo: Support <fbt> tags with multiple <fbt:enum> values (7:7)
40 + | ^^^^^^^^ Multiple `<fbt:enum>` tags found
41 8 | </fbt>
42 9 | );
43 10 | }
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/error.todo-locally-require-fbt.expect.md
+7 -1
@@ -14,9 +14,15 @@ function Component(props) {
14 ## Error
15
16 ```
17 +Found 1 error:
18 +Todo: Support local variables named `fbt`
19 +
20 +Local variables named `fbt` may conflict with the fbt plugin and are not yet supported
21 +
22 +error.todo-locally-require-fbt.ts:2:8
23 1 | function Component(props) {
24 > 2 | const fbt = require('fbt');
19 - | ^^^ Todo: Support local variables named "fbt" (2:2)
25 + | ^^^ Rename to avoid conflict with fbt plugin
26 3 |
27 4 | return <fbt desc="Description">{'Text'}</fbt>;
28 5 | }
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/error.todo-multiple-fbt-plural.expect.md
+16 -1
@@ -53,10 +53,25 @@ export const FIXTURE_ENTRYPOINT = {
53 ## Error
54
55 ```
56 +Found 1 error:
57 +Todo: Support duplicate fbt tags
58 +
59 +Support `<fbt>` tags with multiple `<fbt:plural>` values
60 +
61 +error.todo-multiple-fbt-plural.ts:29:7
62 + 27 | return (
63 + 28 | <fbt desc="Test fbt description">
64 +> 29 | <fbt:plural count={rewrites} name="number of rewrites" showCount="yes">
65 + | ^^^^^^^^^^ Multiple `<fbt:plural>` tags found
66 + 30 | rewrite
67 + 31 | </fbt:plural>
68 + 32 | to Rust ·
69 +
70 +error.todo-multiple-fbt-plural.ts:33:7
71 31 | </fbt:plural>
72 32 | to Rust ·
73 > 33 | <fbt:plural count={months} name="number of months" showCount="yes">
59 - | ^^^^^^^^^^ Todo: Support <fbt> tags with multiple <fbt:plural> values (33:33)
74 + | ^^^^^^^^^^ Multiple `<fbt:plural>` tags found
75 34 | month
76 35 | </fbt:plural>
77 36 | traveling
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/dynamic-gating-bailout-nopanic.expect.md
+1 -1
@@ -58,7 +58,7 @@ export const FIXTURE_ENTRYPOINT = {
58 ## Logs
59
60 ```
61 -{"kind":"CompileError","fnLoc":{"start":{"line":6,"column":0,"index":206},"end":{"line":16,"column":1,"index":433},"filename":"dynamic-gating-bailout-nopanic.ts"},"detail":{"reason":"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","description":"The inferred dependency was `value`, but the source dependencies were []. Inferred dependency not present in source","severity":"CannotPreserveMemoization","suggestions":null,"loc":{"start":{"line":9,"column":31,"index":288},"end":{"line":9,"column":52,"index":309},"filename":"dynamic-gating-bailout-nopanic.ts"}}}
61 +{"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":{"reason":"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","description":"The inferred dependency was `value`, but the source dependencies were []. Inferred dependency not present in source","severity":"CannotPreserveMemoization","suggestions":null,"loc":{"start":{"line":9,"column":31,"index":288},"end":{"line":9,"column":52,"index":309},"filename":"dynamic-gating-bailout-nopanic.ts"}}}}
62 ```
63
64 ### Eval output
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/dynamic-gating-invalid-multiple.expect.md
+1 -1
@@ -38,7 +38,7 @@ export const FIXTURE_ENTRYPOINT = {
38 ## Logs
39
40 ```
41 -{"kind":"CompileError","fnLoc":{"start":{"line":3,"column":0,"index":86},"end":{"line":7,"column":1,"index":190},"filename":"dynamic-gating-invalid-multiple.ts"},"detail":{"reason":"Multiple dynamic gating directives found","description":"Expected a single directive but found [use memo if(getTrue), use memo if(getFalse)]","severity":"InvalidReact","suggestions":null,"loc":{"start":{"line":4,"column":2,"index":105},"end":{"line":4,"column":25,"index":128},"filename":"dynamic-gating-invalid-multiple.ts"}}}
41 +{"kind":"CompileError","fnLoc":{"start":{"line":3,"column":0,"index":86},"end":{"line":7,"column":1,"index":190},"filename":"dynamic-gating-invalid-multiple.ts"},"detail":{"options":{"reason":"Multiple dynamic gating directives found","description":"Expected a single directive but found [use memo if(getTrue), use memo if(getFalse)]","severity":"InvalidReact","suggestions":null,"loc":{"start":{"line":4,"column":2,"index":105},"end":{"line":4,"column":25,"index":128},"filename":"dynamic-gating-invalid-multiple.ts"}}}}
42 ```
43
44 ### Eval output
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/error.dynamic-gating-invalid-identifier-nopanic-required-feature.expect.md
+7 -1
@@ -23,10 +23,16 @@ export const FIXTURE_ENTRYPOINT = {
23 ## Error
24
25 ```
26 +Found 1 error:
27 +Error: Cannot infer dependencies of this effect. This will break your build!
28 +
29 +To resolve, either pass a dependency array or fix reported compiler bailout diagnostics.
30 +
31 +error.dynamic-gating-invalid-identifier-nopanic-required-feature.ts:8:2
32 6 | 'use memo if(invalid identifier)';
33 7 | const arr = [propVal];
34 > 8 | useEffect(() => print(arr), AUTODEPS);
29 - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ InvalidReact: [InferEffectDependencies] React Compiler is unable to infer dependencies of this effect. This will break your build! To resolve, either pass your own dependency array or fix reported compiler bailout diagnostics. (8:8)
35 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Cannot infer dependencies
36 9 | }
37 10 |
38 11 | export const FIXTURE_ENTRYPOINT = {
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating/error.dynamic-gating-invalid-identifier.expect.md
+9 -1
@@ -20,13 +20,21 @@ export const FIXTURE_ENTRYPOINT = {
20 ## Error
21
22 ```
23 +Found 1 error:
24 +Error: Dynamic gating directive is not a valid JavaScript identifier
25 +
26 +Found 'use memo if(true)'.
27 +
28 +error.dynamic-gating-invalid-identifier.ts:4:2
29 2 |
30 3 | function Foo() {
31 > 4 | 'use memo if(true)';
26 - | ^^^^^^^^^^^^^^^^^^^^ InvalidReact: Dynamic gating directive is not a valid JavaScript identifier. Found 'use memo if(true)' (4:4)
32 + | ^^^^^^^^^^^^^^^^^^^^ Dynamic gating directive is not a valid JavaScript identifier
33 5 | return <div>hello world</div>;
34 6 | }
35 7 |
36 +
37 +
38 ```
39
40
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/bailout-retry/error.callsite-in-non-react-fn-default-import.expect.md
+7 -1
@@ -16,10 +16,16 @@ function nonReactFn(arg) {
16 ## Error
17
18 ```
19 +Found 1 error:
20 +Error: Cannot infer dependencies of this effect. This will break your build!
21 +
22 +To resolve, either pass a dependency array or fix reported compiler bailout diagnostics.
23 +
24 +error.callsite-in-non-react-fn-default-import.ts:6:2
25 4 |
26 5 | function nonReactFn(arg) {
27 > 6 | useMyEffect(() => [1, 2, arg], AUTODEPS);
22 - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ InvalidReact: [InferEffectDependencies] React Compiler is unable to infer dependencies of this effect. This will break your build! To resolve, either pass your own dependency array or fix reported compiler bailout diagnostics. (6:6)
28 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Cannot infer dependencies
29 7 | }
30 8 |
31 ```
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/bailout-retry/error.callsite-in-non-react-fn.expect.md
+7 -1
@@ -15,10 +15,16 @@ function nonReactFn(arg) {
15 ## Error
16
17 ```
18 +Found 1 error:
19 +Error: Cannot infer dependencies of this effect. This will break your build!
20 +
21 +To resolve, either pass a dependency array or fix reported compiler bailout diagnostics.
22 +
23 +error.callsite-in-non-react-fn.ts:5:2
24 3 |
25 4 | function nonReactFn(arg) {
26 > 5 | useEffect(() => [1, 2, arg], AUTODEPS);
21 - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ InvalidReact: [InferEffectDependencies] React Compiler is unable to infer dependencies of this effect. This will break your build! To resolve, either pass your own dependency array or fix reported compiler bailout diagnostics. (5:5)
27 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Cannot infer dependencies
28 6 | }
29 7 |
30 ```
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/bailout-retry/error.non-inlined-effect-fn.expect.md
+7 -1
@@ -30,10 +30,16 @@ function Component({foo}) {
30 ## Error
31
32 ```
33 +Found 1 error:
34 +Error: Cannot infer dependencies of this effect. This will break your build!
35 +
36 +To resolve, either pass a dependency array or fix reported compiler bailout diagnostics.
37 +
38 +error.non-inlined-effect-fn.ts:20:2
39 18 |
40 19 | // No inferred dep array, the argument is not a lambda
41 > 20 | useEffect(f, AUTODEPS);
36 - | ^^^^^^^^^^^^^^^^^^^^^^ InvalidReact: [InferEffectDependencies] React Compiler is unable to infer dependencies of this effect. This will break your build! To resolve, either pass your own dependency array or fix reported compiler bailout diagnostics. (20:20)
42 + | ^^^^^^^^^^^^^^^^^^^^^^ Cannot infer dependencies
43 21 | }
44 22 |
45 ```
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/bailout-retry/error.todo-dynamic-gating.expect.md
+7 -1
@@ -31,10 +31,16 @@ export const FIXTURE_ENTRYPOINT = {
31 ## Error
32
33 ```
34 +Found 1 error:
35 +Error: Cannot infer dependencies of this effect. This will break your build!
36 +
37 +To resolve, either pass a dependency array or fix reported compiler bailout diagnostics.
38 +
39 +error.todo-dynamic-gating.ts:13:2
40 11 | 'use memo if(getTrue)';
41 12 | const arr = [];
42 > 13 | useEffectWrapper(() => arr.push(foo), AUTODEPS);
37 - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ InvalidReact: [InferEffectDependencies] React Compiler is unable to infer dependencies of this effect. This will break your build! To resolve, either pass your own dependency array or fix reported compiler bailout diagnostics. (13:13)
43 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Cannot infer dependencies
44 14 | arr.push(2);
45 15 | return arr;
46 16 | }
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/bailout-retry/error.todo-gating.expect.md
+7 -1
@@ -29,10 +29,16 @@ export const FIXTURE_ENTRYPOINT = {
29 ## Error
30
31 ```
32 +Found 1 error:
33 +Error: Cannot infer dependencies of this effect. This will break your build!
34 +
35 +To resolve, either pass a dependency array or fix reported compiler bailout diagnostics.
36 +
37 +error.todo-gating.ts:11:2
38 9 | function Component({foo}) {
39 10 | const arr = [];
40 > 11 | useEffectWrapper(() => arr.push(foo), AUTODEPS);
35 - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ InvalidReact: [InferEffectDependencies] React Compiler is unable to infer dependencies of this effect. This will break your build! To resolve, either pass your own dependency array or fix reported compiler bailout diagnostics. (11:11)
41 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Cannot infer dependencies
42 12 | arr.push(2);
43 13 | return arr;
44 14 | }
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/bailout-retry/error.todo-import-default-property-useEffect.expect.md
+7 -1
@@ -16,10 +16,16 @@ function NonReactiveDepInEffect() {
16 ## Error
17
18 ```
19 +Found 1 error:
20 +Error: Cannot infer dependencies of this effect. This will break your build!
21 +
22 +To resolve, either pass a dependency array or fix reported compiler bailout diagnostics.
23 +
24 +error.todo-import-default-property-useEffect.ts:6:2
25 4 | function NonReactiveDepInEffect() {
26 5 | const obj = makeObject_Primitives();
27 > 6 | React.useEffect(() => print(obj), React.AUTODEPS);
22 - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ InvalidReact: [InferEffectDependencies] React Compiler is unable to infer dependencies of this effect. This will break your build! To resolve, either pass your own dependency array or fix reported compiler bailout diagnostics. (6:6)
28 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Cannot infer dependencies
29 7 | }
30 8 |
31 ```
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/bailout-retry/error.todo-syntax.expect.md
+7 -1
@@ -32,6 +32,12 @@ function Component({prop1}) {
32 ## Error
33
34 ```
35 +Found 1 error:
36 +Error: Cannot infer dependencies of this effect. This will break your build!
37 +
38 +To resolve, either pass a dependency array or fix reported compiler bailout diagnostics. Todo: (BuildHIR::lowerStatement) Handle TryStatement without a catch clause (13:6)
39 +
40 +error.todo-syntax.ts:11:2
41 9 | function Component({prop1}) {
42 10 | 'use memo';
43 > 11 | useSpecialEffect(
@@ -55,7 +61,7 @@ function Component({prop1}) {
61 > 20 | AUTODEPS
62 | ^^^^^^^^^^^
63 > 21 | );
58 - | ^^^^ InvalidReact: [InferEffectDependencies] React Compiler is unable to infer dependencies of this effect. This will break your build! To resolve, either pass your own dependency array or fix reported compiler bailout diagnostics.. (Bailout reason: Todo: (BuildHIR::lowerStatement) Handle TryStatement without a catch clause (13:17)) (11:21)
64 + | ^^^^ Cannot infer dependencies
65 22 | return <div>{prop1}</div>;
66 23 | }
67 24 |
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/bailout-retry/error.use-no-memo.expect.md
+7 -1
@@ -16,10 +16,16 @@ function Component({propVal}) {
16 ## Error
17
18 ```
19 +Found 1 error:
20 +Error: Cannot infer dependencies of this effect. This will break your build!
21 +
22 +To resolve, either pass a dependency array or fix reported compiler bailout diagnostics.
23 +
24 +error.use-no-memo.ts:6:2
25 4 | function Component({propVal}) {
26 5 | 'use no memo';
27 > 6 | useEffect(() => [propVal], AUTODEPS);
22 - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ InvalidReact: [InferEffectDependencies] React Compiler is unable to infer dependencies of this effect. This will break your build! To resolve, either pass your own dependency array or fix reported compiler bailout diagnostics. (6:6)
28 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Cannot infer dependencies
29 7 | }
30 8 |
31 ```
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/bailout-retry/mutate-after-useeffect-optional-chain.expect.md
+1 -1
@@ -48,7 +48,7 @@ export const FIXTURE_ENTRYPOINT = {
48 ## Logs
49
50 ```
51 -{"kind":"CompileError","fnLoc":{"start":{"line":5,"column":0,"index":149},"end":{"line":12,"column":1,"index":404},"filename":"mutate-after-useeffect-optional-chain.ts"},"detail":{"reason":"Updating a value used previously in an effect function or as an effect dependency is not allowed. Consider moving the mutation before calling useEffect()","description":null,"severity":"InvalidReact","suggestions":null,"loc":{"start":{"line":10,"column":2,"index":365},"end":{"line":10,"column":5,"index":368},"filename":"mutate-after-useeffect-optional-chain.ts","identifierName":"arr"}}}
51 +{"kind":"CompileError","fnLoc":{"start":{"line":5,"column":0,"index":149},"end":{"line":12,"column":1,"index":404},"filename":"mutate-after-useeffect-optional-chain.ts"},"detail":{"options":{"reason":"Updating a value used previously in an effect function or as an effect dependency is not allowed. Consider moving the mutation before calling useEffect()","description":null,"severity":"InvalidReact","suggestions":null,"loc":{"start":{"line":10,"column":2,"index":365},"end":{"line":10,"column":5,"index":368},"filename":"mutate-after-useeffect-optional-chain.ts","identifierName":"arr"}}}}
52 {"kind":"AutoDepsDecorations","fnLoc":{"start":{"line":9,"column":2,"index":314},"end":{"line":9,"column":49,"index":361},"filename":"mutate-after-useeffect-optional-chain.ts"},"decorations":[{"start":{"line":9,"column":24,"index":336},"end":{"line":9,"column":27,"index":339},"filename":"mutate-after-useeffect-optional-chain.ts","identifierName":"arr"}]}
53 {"kind":"CompileSuccess","fnLoc":{"start":{"line":5,"column":0,"index":149},"end":{"line":12,"column":1,"index":404},"filename":"mutate-after-useeffect-optional-chain.ts"},"fnName":"Component","memoSlots":0,"memoBlocks":0,"memoValues":0,"prunedMemoBlocks":0,"prunedMemoValues":0}
54 ```
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/bailout-retry/mutate-after-useeffect-ref-access.expect.md
+1 -1
@@ -47,7 +47,7 @@ export const FIXTURE_ENTRYPOINT = {
47 ## Logs
48
49 ```
50 -{"kind":"CompileError","fnLoc":{"start":{"line":6,"column":0,"index":158},"end":{"line":11,"column":1,"index":331},"filename":"mutate-after-useeffect-ref-access.ts"},"detail":{"reason":"Mutating component props or hook arguments is not allowed. Consider using a local variable instead","description":null,"severity":"InvalidReact","suggestions":null,"loc":{"start":{"line":9,"column":2,"index":289},"end":{"line":9,"column":16,"index":303},"filename":"mutate-after-useeffect-ref-access.ts"}}}
50 +{"kind":"CompileError","fnLoc":{"start":{"line":6,"column":0,"index":158},"end":{"line":11,"column":1,"index":331},"filename":"mutate-after-useeffect-ref-access.ts"},"detail":{"options":{"reason":"Mutating component props or hook arguments is not allowed. Consider using a local variable instead","description":null,"severity":"InvalidReact","suggestions":null,"loc":{"start":{"line":9,"column":2,"index":289},"end":{"line":9,"column":16,"index":303},"filename":"mutate-after-useeffect-ref-access.ts"}}}}
51 {"kind":"AutoDepsDecorations","fnLoc":{"start":{"line":8,"column":2,"index":237},"end":{"line":8,"column":50,"index":285},"filename":"mutate-after-useeffect-ref-access.ts"},"decorations":[{"start":{"line":8,"column":24,"index":259},"end":{"line":8,"column":30,"index":265},"filename":"mutate-after-useeffect-ref-access.ts","identifierName":"arrRef"}]}
52 {"kind":"CompileSuccess","fnLoc":{"start":{"line":6,"column":0,"index":158},"end":{"line":11,"column":1,"index":331},"filename":"mutate-after-useeffect-ref-access.ts"},"fnName":"Component","memoSlots":0,"memoBlocks":0,"memoValues":0,"prunedMemoBlocks":0,"prunedMemoValues":0}
53 ```
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/bailout-retry/mutate-after-useeffect.expect.md
+1 -1
@@ -47,7 +47,7 @@ export const FIXTURE_ENTRYPOINT = {
47 ## Logs
48
49 ```
50 -{"kind":"CompileError","fnLoc":{"start":{"line":4,"column":0,"index":111},"end":{"line":11,"column":1,"index":242},"filename":"mutate-after-useeffect.ts"},"detail":{"reason":"Updating a value used previously in an effect function or as an effect dependency is not allowed. Consider moving the mutation before calling useEffect()","description":null,"severity":"InvalidReact","suggestions":null,"loc":{"start":{"line":9,"column":2,"index":214},"end":{"line":9,"column":5,"index":217},"filename":"mutate-after-useeffect.ts","identifierName":"arr"}}}
50 +{"kind":"CompileError","fnLoc":{"start":{"line":4,"column":0,"index":111},"end":{"line":11,"column":1,"index":242},"filename":"mutate-after-useeffect.ts"},"detail":{"options":{"reason":"Updating a value used previously in an effect function or as an effect dependency is not allowed. Consider moving the mutation before calling useEffect()","description":null,"severity":"InvalidReact","suggestions":null,"loc":{"start":{"line":9,"column":2,"index":214},"end":{"line":9,"column":5,"index":217},"filename":"mutate-after-useeffect.ts","identifierName":"arr"}}}}
51 {"kind":"AutoDepsDecorations","fnLoc":{"start":{"line":6,"column":2,"index":159},"end":{"line":8,"column":14,"index":210},"filename":"mutate-after-useeffect.ts"},"decorations":[{"start":{"line":7,"column":4,"index":181},"end":{"line":7,"column":7,"index":184},"filename":"mutate-after-useeffect.ts","identifierName":"arr"},{"start":{"line":7,"column":4,"index":181},"end":{"line":7,"column":7,"index":184},"filename":"mutate-after-useeffect.ts","identifierName":"arr"},{"start":{"line":7,"column":13,"index":190},"end":{"line":7,"column":16,"index":193},"filename":"mutate-after-useeffect.ts","identifierName":"foo"}]}
52 {"kind":"CompileSuccess","fnLoc":{"start":{"line":4,"column":0,"index":111},"end":{"line":11,"column":1,"index":242},"filename":"mutate-after-useeffect.ts"},"fnName":"Component","memoSlots":0,"memoBlocks":0,"memoValues":0,"prunedMemoBlocks":0,"prunedMemoValues":0}
53 ```
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/error.wrong-index-no-func.expect.md
+7 -1
@@ -15,10 +15,16 @@ function Component({foo}) {
15 ## Error
16
17 ```
18 +Found 1 error:
19 +Error: Cannot infer dependencies of this effect. This will break your build!
20 +
21 +To resolve, either pass a dependency array or fix reported compiler bailout diagnostics.
22 +
23 +error.wrong-index-no-func.ts:5:2
24 3 |
25 4 | function Component({foo}) {
26 > 5 | useEffect(AUTODEPS);
21 - | ^^^^^^^^^^^^^^^^^^^ InvalidReact: [InferEffectDependencies] React Compiler is unable to infer dependencies of this effect. This will break your build! To resolve, either pass your own dependency array or fix reported compiler bailout diagnostics. (5:5)
27 + | ^^^^^^^^^^^^^^^^^^^ Cannot infer dependencies
28 6 | }
29 7 |
30 ```
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/error.wrong-index.expect.md
+7 -1
@@ -22,6 +22,12 @@ function Component({foo}) {
22 ## Error
23
24 ```
25 +Found 1 error:
26 +Error: Cannot infer dependencies of this effect. This will break your build!
27 +
28 +To resolve, either pass a dependency array or fix reported compiler bailout diagnostics.
29 +
30 +error.wrong-index.ts:6:2
31 4 |
32 5 | function Component({foo}) {
33 > 6 | useEffectWrapper(
@@ -37,7 +43,7 @@ function Component({foo}) {
43 > 11 | AUTODEPS
44 | ^^^^^^^^^^^
45 > 12 | );
40 - | ^^^^ InvalidReact: [InferEffectDependencies] React Compiler is unable to infer dependencies of this effect. This will break your build! To resolve, either pass your own dependency array or fix reported compiler bailout diagnostics. (6:12)
46 + | ^^^^ Cannot infer dependencies
47 13 | }
48 14 |
49 ```
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/no-emit/retry-no-emit.expect.md
+1 -1
@@ -54,7 +54,7 @@ export const FIXTURE_ENTRYPOINT = {
54 ## Logs
55
56 ```
57 -{"kind":"CompileError","fnLoc":{"start":{"line":6,"column":0,"index":195},"end":{"line":14,"column":1,"index":409},"filename":"retry-no-emit.ts"},"detail":{"reason":"Updating a value previously passed as an argument to a hook is not allowed. Consider moving the mutation before calling the hook","description":null,"severity":"InvalidReact","suggestions":null,"loc":{"start":{"line":12,"column":2,"index":372},"end":{"line":12,"column":6,"index":376},"filename":"retry-no-emit.ts","identifierName":"arr2"}}}
57 +{"kind":"CompileError","fnLoc":{"start":{"line":6,"column":0,"index":195},"end":{"line":14,"column":1,"index":409},"filename":"retry-no-emit.ts"},"detail":{"options":{"reason":"Updating a value previously passed as an argument to a hook is not allowed. Consider moving the mutation before calling the hook","description":null,"severity":"InvalidReact","suggestions":null,"loc":{"start":{"line":12,"column":2,"index":372},"end":{"line":12,"column":6,"index":376},"filename":"retry-no-emit.ts","identifierName":"arr2"}}}}
58 {"kind":"AutoDepsDecorations","fnLoc":{"start":{"line":8,"column":2,"index":248},"end":{"line":8,"column":46,"index":292},"filename":"retry-no-emit.ts"},"decorations":[{"start":{"line":8,"column":31,"index":277},"end":{"line":8,"column":34,"index":280},"filename":"retry-no-emit.ts","identifierName":"arr"}]}
59 {"kind":"AutoDepsDecorations","fnLoc":{"start":{"line":11,"column":2,"index":316},"end":{"line":11,"column":54,"index":368},"filename":"retry-no-emit.ts"},"decorations":[{"start":{"line":11,"column":25,"index":339},"end":{"line":11,"column":29,"index":343},"filename":"retry-no-emit.ts","identifierName":"arr2"},{"start":{"line":11,"column":25,"index":339},"end":{"line":11,"column":29,"index":343},"filename":"retry-no-emit.ts","identifierName":"arr2"},{"start":{"line":11,"column":35,"index":349},"end":{"line":11,"column":42,"index":356},"filename":"retry-no-emit.ts","identifierName":"propVal"}]}
60 {"kind":"CompileSuccess","fnLoc":{"start":{"line":6,"column":0,"index":195},"end":{"line":14,"column":1,"index":409},"filename":"retry-no-emit.ts"},"fnName":"Foo","memoSlots":0,"memoBlocks":0,"memoValues":0,"prunedMemoBlocks":0,"prunedMemoValues":0}
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/error.invalid-impure-functions-in-render.expect.md
+36 -4
@@ -17,17 +17,49 @@ function Component() {
17 ## Error
18
19 ```
20 +Found 3 errors:
21 +Error: Calling an impure function can produce unstable results. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#components-and-hooks-must-be-idempotent)
22 +
23 +`Date.now` is an impure function whose results may change on every call.
24 +
25 +error.invalid-impure-functions-in-render.ts:4:15
26 2 |
27 3 | function Component() {
28 > 4 | const date = Date.now();
23 - | ^^^^^^^^^^ InvalidReact: Calling an impure function can produce unstable results. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#components-and-hooks-must-be-idempotent). `Date.now` is an impure function whose results may change on every call (4:4)
29 + | ^^^^^^^^^^ Calling an impure function can produce unstable results. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#components-and-hooks-must-be-idempotent)
30 + 5 | const now = performance.now();
31 + 6 | const rand = Math.random();
32 + 7 | return <Foo date={date} now={now} rand={rand} />;
33
25 -InvalidReact: Calling an impure function can produce unstable results. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#components-and-hooks-must-be-idempotent). `performance.now` is an impure function whose results may change on every call (5:5)
34
27 -InvalidReact: Calling an impure function can produce unstable results. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#components-and-hooks-must-be-idempotent). `Math.random` is an impure function whose results may change on every call (6:6)
28 - 5 | const now = performance.now();
35 +Error: Calling an impure function can produce unstable results. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#components-and-hooks-must-be-idempotent)
36 +
37 +`performance.now` is an impure function whose results may change on every call.
38 +
39 +error.invalid-impure-functions-in-render.ts:5:14
40 + 3 | function Component() {
41 + 4 | const date = Date.now();
42 +> 5 | const now = performance.now();
43 + | ^^^^^^^^^^^^^^^^^ Calling an impure function can produce unstable results. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#components-and-hooks-must-be-idempotent)
44 6 | const rand = Math.random();
45 7 | return <Foo date={date} now={now} rand={rand} />;
46 + 8 | }
47 +
48 +
49 +Error: Calling an impure function can produce unstable results. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#components-and-hooks-must-be-idempotent)
50 +
51 +`Math.random` is an impure function whose results may change on every call.
52 +
53 +error.invalid-impure-functions-in-render.ts:6:15
54 + 4 | const date = Date.now();
55 + 5 | const now = performance.now();
56 +> 6 | const rand = Math.random();
57 + | ^^^^^^^^^^^^^ Calling an impure function can produce unstable results. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#components-and-hooks-must-be-idempotent)
58 + 7 | return <Foo date={date} now={now} rand={rand} />;
59 + 8 | }
60 + 9 |
61 +
62 +
63 ```
64
65
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/error.invalid-reassign-local-variable-in-jsx-callback.expect.md
+9 -1
@@ -42,13 +42,21 @@ function Component() {
42 ## Error
43
44 ```
45 +Found 1 error:
46 +Error: Reassigning a variable after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead
47 +
48 +Variable `local` cannot be reassigned after render.
49 +
50 +error.invalid-reassign-local-variable-in-jsx-callback.ts:6:4
51 4 |
52 5 | const reassignLocal = newValue => {
53 > 6 | local = newValue;
48 - | ^^^^^ InvalidReact: Reassigning a variable after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead. Variable `local` cannot be reassigned after render (6:6)
54 + | ^^^^^ Reassigning a variable after render has completed can cause inconsistent behavior on subsequent renders. Consider using state instead
55 7 | };
56 8 |
57 9 | const onClick = newValue => {
58 +
59 +
60 ```
61
62
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/error.invalid-referencing-frozen-hoisted-storecontext-const.expect.md
+23 -3
@@ -31,15 +31,35 @@ function Component({content, refetch}) {
31 ## Error
32
33 ```
34 +Found 2 errors:
35 +Error: This variable is accessed before it is declared, which may prevent it from updating as the assigned value changes over time
36 +
37 +Variable `data` is accessed before it is declared.
38 +
39 +undefined:11:12
40 9 | // TDZ violation!
41 10 | const onRefetch = useCallback(() => {
42 > 11 | refetch(data);
37 - | ^^^^ InvalidReact: This variable is accessed before it is declared, which may prevent it from updating as the assigned value changes over time. Variable `data` is accessed before it is declared (11:11)
38 -
39 -InvalidReact: This variable is accessed before it is declared, which prevents the earlier access from updating when this value changes over time. Variable `data` is accessed before it is declared (19:19)
43 + | ^^^^ This variable is accessed before it is declared, which may prevent it from updating as the assigned value changes over time
44 12 | }, [refetch]);
45 13 |
46 14 | // The context variable gets frozen here since it's passed to a hook
47 +
48 +
49 +Error: This variable is accessed before it is declared, which prevents the earlier access from updating when this value changes over time
50 +
51 +Variable `data` is accessed before it is declared.
52 +
53 +undefined:19:9
54 + 17 | // This has to error: onRefetch needs to memoize with `content` as a
55 + 18 | // dependency, but the dependency comes later
56 +> 19 | const {data = null} = content;
57 + | ^^^^^^^^^^^ This variable is accessed before it is declared, which prevents the earlier access from updating when this value changes over time
58 + 20 |
59 + 21 | return <Foo data={data} onSubmit={onSubmit} />;
60 + 22 | }
61 +
62 +
63 ```
64
65
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/error.invalid-useCallback-captures-reassigned-context.expect.md
+18 -2
@@ -29,15 +29,31 @@ export const FIXTURE_ENTRYPOINT = {
29 ## Error
30
31 ```
32 +Found 2 errors:
33 +Memoization: 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
34 +
35 +error.invalid-useCallback-captures-reassigned-context.ts:11:37
36 9 |
37 10 | // makeArray() is captured, but depsList contains [props]
38 > 11 | const cb = useCallback(() => [x], [x]);
35 - | ^ CannotPreserveMemoization: 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 (11:11)
39 + | ^ 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 + 12 |
41 + 13 | x = makeArray();
42 + 14 |
43 +
44 +
45 +Memoization: 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.
46
37 -CannotPreserveMemoization: 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. (11:11)
47 +error.invalid-useCallback-captures-reassigned-context.ts:11:25
48 + 9 |
49 + 10 | // makeArray() is captured, but depsList contains [props]
50 +> 11 | const cb = useCallback(() => [x], [x]);
51 + | ^^^^^^^^^ 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.
52 12 |
53 13 | x = makeArray();
54 14 |
55 +
56 +
57 ```
58
59
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/error.mutate-frozen-value.expect.md
+7 -1
@@ -16,13 +16,19 @@ function Component({a, b}) {
16 ## Error
17
18 ```
19 +Found 1 error:
20 +Error: Updating a value previously passed as an argument to a hook is not allowed. Consider moving the mutation before calling the hook
21 +
22 +error.mutate-frozen-value.ts:5:2
23 3 | const x = {a};
24 4 | useFreeze(x);
25 > 5 | x.y = true;
22 - | ^ InvalidReact: Updating a value previously passed as an argument to a hook is not allowed. Consider moving the mutation before calling the hook (5:5)
26 + | ^ Updating a value previously passed as an argument to a hook is not allowed. Consider moving the mutation before calling the hook
27 6 | return <div>error</div>;
28 7 | }
29 8 |
30 +
31 +
32 ```
33
34
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/error.mutate-hook-argument.expect.md
+18 -3
@@ -14,15 +14,30 @@ function useHook(a, b) {
14 ## Error
15
16 ```
17 +Found 2 errors:
18 +Error: Mutating component props or hook arguments is not allowed. Consider using a local variable instead
19 +
20 +error.mutate-hook-argument.ts:3:2
21 1 | // @enableNewMutationAliasingModel
22 2 | function useHook(a, b) {
23 > 3 | b.test = 1;
20 - | ^ InvalidReact: Mutating component props or hook arguments is not allowed. Consider using a local variable instead (3:3)
21 -
22 -InvalidReact: Mutating component props or hook arguments is not allowed. Consider using a local variable instead (4:4)
24 + | ^ Mutating component props or hook arguments is not allowed. Consider using a local variable instead
25 4 | a.test = 2;
26 5 | }
27 6 |
28 +
29 +
30 +Error: Mutating component props or hook arguments is not allowed. Consider using a local variable instead
31 +
32 +error.mutate-hook-argument.ts:4:2
33 + 2 | function useHook(a, b) {
34 + 3 | b.test = 1;
35 +> 4 | a.test = 2;
36 + | ^ Mutating component props or hook arguments is not allowed. Consider using a local variable instead
37 + 5 | }
38 + 6 |
39 +
40 +
41 ```
42
43
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/error.not-useEffect-external-mutate.expect.md
+19 -3
@@ -18,15 +18,31 @@ function Component(props) {
18 ## Error
19
20 ```
21 +Found 2 errors:
22 +Error: Writing to a variable defined outside a component or hook is not allowed. Consider using an effect
23 +
24 +error.not-useEffect-external-mutate.ts:6:4
25 4 | function Component(props) {
26 5 | foo(() => {
27 > 6 | x.a = 10;
24 - | ^ InvalidReact: Writing to a variable defined outside a component or hook is not allowed. Consider using an effect (6:6)
25 -
26 -InvalidReact: Writing to a variable defined outside a component or hook is not allowed. Consider using an effect (7:7)
28 + | ^ Writing to a variable defined outside a component or hook is not allowed. Consider using an effect
29 7 | x.a = 20;
30 8 | });
31 9 | }
32 +
33 +
34 +Error: Writing to a variable defined outside a component or hook is not allowed. Consider using an effect
35 +
36 +error.not-useEffect-external-mutate.ts:7:4
37 + 5 | foo(() => {
38 + 6 | x.a = 10;
39 +> 7 | x.a = 20;
40 + | ^ Writing to a variable defined outside a component or hook is not allowed. Consider using an effect
41 + 8 | });
42 + 9 | }
43 + 10 |
44 +
45 +
46 ```
47
48
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/error.reassignment-to-global-indirect.expect.md
+19 -3
@@ -18,15 +18,31 @@ function Component() {
18 ## Error
19
20 ```
21 +Found 2 errors:
22 +Error: Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render)
23 +
24 +error.reassignment-to-global-indirect.ts:5:4
25 3 | const foo = () => {
26 4 | // Cannot assign to globals
27 > 5 | someUnknownGlobal = true;
24 - | ^^^^^^^^^^^^^^^^^ InvalidReact: Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render) (5:5)
25 -
26 -InvalidReact: Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render) (6:6)
28 + | ^^^^^^^^^^^^^^^^^ Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render)
29 6 | moduleLocal = true;
30 7 | };
31 8 | foo();
32 +
33 +
34 +Error: Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render)
35 +
36 +error.reassignment-to-global-indirect.ts:6:4
37 + 4 | // Cannot assign to globals
38 + 5 | someUnknownGlobal = true;
39 +> 6 | moduleLocal = true;
40 + | ^^^^^^^^^^^ Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render)
41 + 7 | };
42 + 8 | foo();
43 + 9 | }
44 +
45 +
46 ```
47
48
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/error.reassignment-to-global.expect.md
+18 -3
@@ -15,15 +15,30 @@ function Component() {
15 ## Error
16
17 ```
18 +Found 2 errors:
19 +Error: Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render)
20 +
21 +error.reassignment-to-global.ts:4:2
22 2 | function Component() {
23 3 | // Cannot assign to globals
24 > 4 | someUnknownGlobal = true;
21 - | ^^^^^^^^^^^^^^^^^ InvalidReact: Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render) (4:4)
22 -
23 -InvalidReact: Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render) (5:5)
25 + | ^^^^^^^^^^^^^^^^^ Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render)
26 5 | moduleLocal = true;
27 6 | }
28 7 |
29 +
30 +
31 +Error: Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render)
32 +
33 +error.reassignment-to-global.ts:5:2
34 + 3 | // Cannot assign to globals
35 + 4 | someUnknownGlobal = true;
36 +> 5 | moduleLocal = true;
37 + | ^^^^^^^^^^^ Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render)
38 + 6 | }
39 + 7 |
40 +
41 +
42 ```
43
44
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/error.todo-repro-named-function-with-shadowed-local-same-name.expect.md
+9 -1
@@ -20,12 +20,20 @@ function Component(props) {
20 ## Error
21
22 ```
23 +Found 1 error:
24 +Invariant: [InferMutationAliasingEffects] Expected value kind to be initialized
25 +
26 +<unknown> hasErrors_0$15:TFunction.
27 +
28 +error.todo-repro-named-function-with-shadowed-local-same-name.ts:10:9
29 8 | return hasErrors;
30 9 | }
31 > 10 | return hasErrors();
26 - | ^^^^^^^^^ Invariant: [InferMutationAliasingEffects] Expected value kind to be initialized. <unknown> hasErrors_0$15:TFunction (10:10)
32 + | ^^^^^^^^^ [InferMutationAliasingEffects] Expected value kind to be initialized
33 11 | }
34 12 |
35 +
36 +
37 ```
38
39
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/mutate-after-useeffect-optional-chain.expect.md
+1 -1
@@ -48,7 +48,7 @@ export const FIXTURE_ENTRYPOINT = {
48 ## Logs
49
50 ```
51 -{"kind":"CompileError","fnLoc":{"start":{"line":5,"column":0,"index":181},"end":{"line":12,"column":1,"index":436},"filename":"mutate-after-useeffect-optional-chain.ts"},"detail":{"reason":"Updating a value used previously in an effect function or as an effect dependency is not allowed. Consider moving the mutation before calling useEffect()","description":null,"severity":"InvalidReact","suggestions":null,"loc":{"start":{"line":10,"column":2,"index":397},"end":{"line":10,"column":5,"index":400},"filename":"mutate-after-useeffect-optional-chain.ts","identifierName":"arr"}}}
51 +{"kind":"CompileError","fnLoc":{"start":{"line":5,"column":0,"index":181},"end":{"line":12,"column":1,"index":436},"filename":"mutate-after-useeffect-optional-chain.ts"},"detail":{"options":{"reason":"Updating a value used previously in an effect function or as an effect dependency is not allowed. Consider moving the mutation before calling useEffect()","description":null,"severity":"InvalidReact","suggestions":null,"loc":{"start":{"line":10,"column":2,"index":397},"end":{"line":10,"column":5,"index":400},"filename":"mutate-after-useeffect-optional-chain.ts","identifierName":"arr"}}}}
52 {"kind":"AutoDepsDecorations","fnLoc":{"start":{"line":9,"column":2,"index":346},"end":{"line":9,"column":49,"index":393},"filename":"mutate-after-useeffect-optional-chain.ts"},"decorations":[{"start":{"line":9,"column":24,"index":368},"end":{"line":9,"column":27,"index":371},"filename":"mutate-after-useeffect-optional-chain.ts","identifierName":"arr"}]}
53 {"kind":"CompileSuccess","fnLoc":{"start":{"line":5,"column":0,"index":181},"end":{"line":12,"column":1,"index":436},"filename":"mutate-after-useeffect-optional-chain.ts"},"fnName":"Component","memoSlots":0,"memoBlocks":0,"memoValues":0,"prunedMemoBlocks":0,"prunedMemoValues":0}
54 ```
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/mutate-after-useeffect-ref-access.expect.md
+1 -1
@@ -47,7 +47,7 @@ export const FIXTURE_ENTRYPOINT = {
47 ## Logs
48
49 ```
50 -{"kind":"CompileError","fnLoc":{"start":{"line":6,"column":0,"index":190},"end":{"line":11,"column":1,"index":363},"filename":"mutate-after-useeffect-ref-access.ts"},"detail":{"reason":"Mutating component props or hook arguments is not allowed. Consider using a local variable instead","description":null,"severity":"InvalidReact","suggestions":null,"loc":{"start":{"line":9,"column":2,"index":321},"end":{"line":9,"column":16,"index":335},"filename":"mutate-after-useeffect-ref-access.ts"}}}
50 +{"kind":"CompileError","fnLoc":{"start":{"line":6,"column":0,"index":190},"end":{"line":11,"column":1,"index":363},"filename":"mutate-after-useeffect-ref-access.ts"},"detail":{"options":{"reason":"Mutating component props or hook arguments is not allowed. Consider using a local variable instead","description":null,"severity":"InvalidReact","suggestions":null,"loc":{"start":{"line":9,"column":2,"index":321},"end":{"line":9,"column":16,"index":335},"filename":"mutate-after-useeffect-ref-access.ts"}}}}
51 {"kind":"AutoDepsDecorations","fnLoc":{"start":{"line":8,"column":2,"index":269},"end":{"line":8,"column":50,"index":317},"filename":"mutate-after-useeffect-ref-access.ts"},"decorations":[{"start":{"line":8,"column":24,"index":291},"end":{"line":8,"column":30,"index":297},"filename":"mutate-after-useeffect-ref-access.ts","identifierName":"arrRef"}]}
52 {"kind":"CompileSuccess","fnLoc":{"start":{"line":6,"column":0,"index":190},"end":{"line":11,"column":1,"index":363},"filename":"mutate-after-useeffect-ref-access.ts"},"fnName":"Component","memoSlots":0,"memoBlocks":0,"memoValues":0,"prunedMemoBlocks":0,"prunedMemoValues":0}
53 ```
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/mutate-after-useeffect.expect.md
+1 -1
@@ -47,7 +47,7 @@ export const FIXTURE_ENTRYPOINT = {
47 ## Logs
48
49 ```
50 -{"kind":"CompileError","fnLoc":{"start":{"line":4,"column":0,"index":143},"end":{"line":11,"column":1,"index":274},"filename":"mutate-after-useeffect.ts"},"detail":{"reason":"Updating a value used previously in an effect function or as an effect dependency is not allowed. Consider moving the mutation before calling useEffect()","description":null,"severity":"InvalidReact","suggestions":null,"loc":{"start":{"line":9,"column":2,"index":246},"end":{"line":9,"column":5,"index":249},"filename":"mutate-after-useeffect.ts","identifierName":"arr"}}}
50 +{"kind":"CompileError","fnLoc":{"start":{"line":4,"column":0,"index":143},"end":{"line":11,"column":1,"index":274},"filename":"mutate-after-useeffect.ts"},"detail":{"options":{"reason":"Updating a value used previously in an effect function or as an effect dependency is not allowed. Consider moving the mutation before calling useEffect()","description":null,"severity":"InvalidReact","suggestions":null,"loc":{"start":{"line":9,"column":2,"index":246},"end":{"line":9,"column":5,"index":249},"filename":"mutate-after-useeffect.ts","identifierName":"arr"}}}}
51 {"kind":"AutoDepsDecorations","fnLoc":{"start":{"line":6,"column":2,"index":191},"end":{"line":8,"column":14,"index":242},"filename":"mutate-after-useeffect.ts"},"decorations":[{"start":{"line":7,"column":4,"index":213},"end":{"line":7,"column":7,"index":216},"filename":"mutate-after-useeffect.ts","identifierName":"arr"},{"start":{"line":7,"column":4,"index":213},"end":{"line":7,"column":7,"index":216},"filename":"mutate-after-useeffect.ts","identifierName":"arr"},{"start":{"line":7,"column":13,"index":222},"end":{"line":7,"column":16,"index":225},"filename":"mutate-after-useeffect.ts","identifierName":"foo"}]}
52 {"kind":"CompileSuccess","fnLoc":{"start":{"line":4,"column":0,"index":143},"end":{"line":11,"column":1,"index":274},"filename":"mutate-after-useeffect.ts"},"fnName":"Component","memoSlots":0,"memoBlocks":0,"memoValues":0,"prunedMemoBlocks":0,"prunedMemoValues":0}
53 ```
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/retry-no-emit.expect.md
+1 -1
@@ -54,7 +54,7 @@ export const FIXTURE_ENTRYPOINT = {
54 ## Logs
55
56 ```
57 -{"kind":"CompileError","fnLoc":{"start":{"line":6,"column":0,"index":227},"end":{"line":14,"column":1,"index":441},"filename":"retry-no-emit.ts"},"detail":{"reason":"Updating a value previously passed as an argument to a hook is not allowed. Consider moving the mutation before calling the hook","description":null,"severity":"InvalidReact","suggestions":null,"loc":{"start":{"line":12,"column":2,"index":404},"end":{"line":12,"column":6,"index":408},"filename":"retry-no-emit.ts","identifierName":"arr2"}}}
57 +{"kind":"CompileError","fnLoc":{"start":{"line":6,"column":0,"index":227},"end":{"line":14,"column":1,"index":441},"filename":"retry-no-emit.ts"},"detail":{"options":{"reason":"Updating a value previously passed as an argument to a hook is not allowed. Consider moving the mutation before calling the hook","description":null,"severity":"InvalidReact","suggestions":null,"loc":{"start":{"line":12,"column":2,"index":404},"end":{"line":12,"column":6,"index":408},"filename":"retry-no-emit.ts","identifierName":"arr2"}}}}
58 {"kind":"AutoDepsDecorations","fnLoc":{"start":{"line":8,"column":2,"index":280},"end":{"line":8,"column":46,"index":324},"filename":"retry-no-emit.ts"},"decorations":[{"start":{"line":8,"column":31,"index":309},"end":{"line":8,"column":34,"index":312},"filename":"retry-no-emit.ts","identifierName":"arr"}]}
59 {"kind":"AutoDepsDecorations","fnLoc":{"start":{"line":11,"column":2,"index":348},"end":{"line":11,"column":54,"index":400},"filename":"retry-no-emit.ts"},"decorations":[{"start":{"line":11,"column":25,"index":371},"end":{"line":11,"column":29,"index":375},"filename":"retry-no-emit.ts","identifierName":"arr2"},{"start":{"line":11,"column":25,"index":371},"end":{"line":11,"column":29,"index":375},"filename":"retry-no-emit.ts","identifierName":"arr2"},{"start":{"line":11,"column":35,"index":381},"end":{"line":11,"column":42,"index":388},"filename":"retry-no-emit.ts","identifierName":"propVal"}]}
60 {"kind":"CompileSuccess","fnLoc":{"start":{"line":6,"column":0,"index":227},"end":{"line":14,"column":1,"index":441},"filename":"retry-no-emit.ts"},"fnName":"Foo","memoSlots":0,"memoBlocks":0,"memoValues":0,"prunedMemoBlocks":0,"prunedMemoValues":0}
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.false-positive-useMemo-dropped-infer-always-invalidating.expect.md
+7 -1
@@ -30,13 +30,19 @@ export const FIXTURE_ENTRYPOINT = {
30 ## Error
31
32 ```
33 +Found 1 error:
34 +Memoization: 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.
35 +
36 +error.false-positive-useMemo-dropped-infer-always-invalidating.ts:15:9
37 13 | x.push(props);
38 14 |
39 > 15 | return useMemo(() => [x], [x]);
36 - | ^^^^^^^^^^^^^^^^^^^^^^^ CannotPreserveMemoization: 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. (15:15)
40 + | ^^^^^^^^^^^^^^^^^^^^^^^ 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.
41 16 | }
42 17 |
43 18 | export const FIXTURE_ENTRYPOINT = {
44 +
45 +
46 ```
47
48
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.false-positive-useMemo-infer-mutate-deps.expect.md
+7 -1
@@ -29,13 +29,19 @@ export const FIXTURE_ENTRYPOINT = {
29 ## Error
30
31 ```
32 +Found 1 error:
33 +Memoization: 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
34 +
35 +error.false-positive-useMemo-infer-mutate-deps.ts:14:6
36 12 | return useMemo(() => {
37 13 | return identity(val);
38 > 14 | }, [val]);
35 - | ^^^ CannotPreserveMemoization: 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 (14:14)
39 + | ^^^ 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 15 | }
41 16 |
42 17 | export const FIXTURE_ENTRYPOINT = {
43 +
44 +
45 ```
46
47
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.false-positive-useMemo-overlap-scopes.expect.md
+7 -1
@@ -40,13 +40,19 @@ export const FIXTURE_ENTRYPOINT = {
40 ## Error
41
42 ```
43 +Found 1 error:
44 +Memoization: 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 +
46 +error.false-positive-useMemo-overlap-scopes.ts:23:9
47 21 | const result = useMemo(() => {
48 22 | return [Math.max(x[1], a)];
49 > 23 | }, [a, x]);
46 - | ^ CannotPreserveMemoization: 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 (23:23)
50 + | ^ 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
51 24 | arrayPush(y, 3);
52 25 | return {result, y};
53 26 | }
54 +
55 +
56 ```
57
58
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.hoist-useCallback-conditional-access-own-scope.expect.md
+9 -1
@@ -26,6 +26,12 @@ export const FIXTURE_ENTRYPOINT = {
26 ## Error
27
28 ```
29 +Found 1 error:
30 +Memoization: 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
31 +
32 +The inferred dependency was `propB`, but the source dependencies were [propA, propB.x.y]. Inferred less specific property than source.
33 +
34 +error.hoist-useCallback-conditional-access-own-scope.ts:5:21
35 3 |
36 4 | function Component({propA, propB}) {
37 > 5 | return useCallback(() => {
@@ -41,10 +47,12 @@ export const FIXTURE_ENTRYPOINT = {
47 > 10 | }
48 | ^^^^^^^^^^^^^^^^
49 > 11 | }, [propA, propB.x.y]);
44 - | ^^^^ CannotPreserveMemoization: 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 (5:11)
50 + | ^^^^ 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
51 12 | }
52 13 |
53 14 | export const FIXTURE_ENTRYPOINT = {
54 +
55 +
56 ```
57
58
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.hoist-useCallback-infer-conditional-value-block.expect.md
+38 -2
@@ -29,6 +29,12 @@ export const FIXTURE_ENTRYPOINT = {
29 ## Error
30
31 ```
32 +Found 2 errors:
33 +Memoization: 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
34 +
35 +The inferred dependency was `propA`, but the source dependencies were [propA.a, propB.x.y]. Inferred less specific property than source.
36 +
37 +error.hoist-useCallback-infer-conditional-value-block.ts:6:21
38 4 |
39 5 | function useHook(propA, propB) {
40 > 6 | return useCallback(() => {
@@ -48,12 +54,42 @@ export const FIXTURE_ENTRYPOINT = {
54 > 13 | }
55 | ^^^^^^^^^^^^^^^^^
56 > 14 | }, [propA.a, propB.x.y]);
51 - | ^^^^ CannotPreserveMemoization: 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 (6:14)
57 + | ^^^^ 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
58 + 15 | }
59 + 16 |
60 + 17 | export const FIXTURE_ENTRYPOINT = {
61 +
62 +
63 +Memoization: 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
64 +
65 +The inferred dependency was `propB`, but the source dependencies were [propA.a, propB.x.y]. Inferred less specific property than source.
66
53 -CannotPreserveMemoization: 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 (6:14)
67 +error.hoist-useCallback-infer-conditional-value-block.ts:6:21
68 + 4 |
69 + 5 | function useHook(propA, propB) {
70 +> 6 | return useCallback(() => {
71 + | ^^^^^^^
72 +> 7 | const x = {};
73 + | ^^^^^^^^^^^^^^^^^
74 +> 8 | if (identity(null) ?? propA.a) {
75 + | ^^^^^^^^^^^^^^^^^
76 +> 9 | mutate(x);
77 + | ^^^^^^^^^^^^^^^^^
78 +> 10 | return {
79 + | ^^^^^^^^^^^^^^^^^
80 +> 11 | value: propB.x.y,
81 + | ^^^^^^^^^^^^^^^^^
82 +> 12 | };
83 + | ^^^^^^^^^^^^^^^^^
84 +> 13 | }
85 + | ^^^^^^^^^^^^^^^^^
86 +> 14 | }, [propA.a, propB.x.y]);
87 + | ^^^^ 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
88 15 | }
89 16 |
90 17 | export const FIXTURE_ENTRYPOINT = {
91 +
92 +
93 ```
94
95
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.invalid-useCallback-captures-reassigned-context.expect.md
+18 -2
@@ -30,15 +30,31 @@ export const FIXTURE_ENTRYPOINT = {
30 ## Error
31
32 ```
33 +Found 2 errors:
34 +Memoization: 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
35 +
36 +error.invalid-useCallback-captures-reassigned-context.ts:12:37
37 10 |
38 11 | // makeArray() is captured, but depsList contains [props]
39 > 12 | const cb = useCallback(() => [x], [x]);
36 - | ^ CannotPreserveMemoization: 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 (12:12)
40 + | ^ 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
41 + 13 |
42 + 14 | x = makeArray();
43 + 15 |
44 +
45 +
46 +Memoization: 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.
47
38 -CannotPreserveMemoization: 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. (12:12)
48 +error.invalid-useCallback-captures-reassigned-context.ts:12:25
49 + 10 |
50 + 11 | // makeArray() is captured, but depsList contains [props]
51 +> 12 | const cb = useCallback(() => [x], [x]);
52 + | ^^^^^^^^^ 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.
53 13 |
54 14 | x = makeArray();
55 15 |
56 +
57 +
58 ```
59
60
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.maybe-invalid-useCallback-read-maybeRef.expect.md
+9 -1
@@ -17,6 +17,12 @@ function useHook(maybeRef) {
17 ## Error
18
19 ```
20 +Found 1 error:
21 +Memoization: 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
22 +
23 +The inferred dependency was `maybeRef.current`, but the source dependencies were [maybeRef]. Differences in ref.current access.
24 +
25 +error.maybe-invalid-useCallback-read-maybeRef.ts:5:21
26 3 |
27 4 | function useHook(maybeRef) {
28 > 5 | return useCallback(() => {
@@ -24,9 +30,11 @@ function useHook(maybeRef) {
30 > 6 | return [maybeRef.current];
31 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
32 > 7 | }, [maybeRef]);
27 - | ^^^^ CannotPreserveMemoization: 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 `maybeRef.current`, but the source dependencies were [maybeRef]. Differences in ref.current access (5:7)
33 + | ^^^^ 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
34 8 | }
35 9 |
36 +
37 +
38 ```
39
40
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.maybe-invalid-useMemo-read-maybeRef.expect.md
+9 -1
@@ -17,6 +17,12 @@ function useHook(maybeRef, shouldRead) {
17 ## Error
18
19 ```
20 +Found 1 error:
21 +Memoization: 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
22 +
23 +The inferred dependency was `maybeRef.current`, but the source dependencies were [shouldRead, maybeRef]. Differences in ref.current access.
24 +
25 +error.maybe-invalid-useMemo-read-maybeRef.ts:5:17
26 3 |
27 4 | function useHook(maybeRef, shouldRead) {
28 > 5 | return useMemo(() => {
@@ -24,9 +30,11 @@ function useHook(maybeRef, shouldRead) {
30 > 6 | return () => [maybeRef.current];
31 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
32 > 7 | }, [shouldRead, maybeRef]);
27 - | ^^^^ CannotPreserveMemoization: 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 `maybeRef.current`, but the source dependencies were [shouldRead, maybeRef]. Differences in ref.current access (5:7)
33 + | ^^^^ 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
34 8 | }
35 9 |
36 +
37 +
38 ```
39
40
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.maybe-mutable-ref-not-preserved.expect.md
+7 -1
@@ -23,13 +23,19 @@ export const FIXTURE_ENTRYPOINT = {
23 ## Error
24
25 ```
26 +Found 1 error:
27 +Error: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
28 +
29 +error.maybe-mutable-ref-not-preserved.ts:8:33
30 6 | function useFoo() {
31 7 | const r = useRef();
32 > 8 | return useMemo(() => makeArray(r), []);
29 - | ^ InvalidReact: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef) (8:8)
33 + | ^ Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
34 9 | }
35 10 |
36 11 | export const FIXTURE_ENTRYPOINT = {
37 +
38 +
39 ```
40
41
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.preserve-use-memo-ref-missing-reactive.expect.md
+9 -1
@@ -28,6 +28,12 @@ export const FIXTURE_ENTRYPOINT = {
28 ## Error
29
30 ```
31 +Found 1 error:
32 +Memoization: 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
33 +
34 +The inferred dependency was `ref`, but the source dependencies were []. Inferred dependency not present in source.
35 +
36 +error.preserve-use-memo-ref-missing-reactive.ts:9:21
37 7 | const ref = cond ? ref1 : ref2;
38 8 |
39 > 9 | return useCallback(() => {
@@ -39,10 +45,12 @@ export const FIXTURE_ENTRYPOINT = {
45 > 12 | }
46 | ^^^^^^^^^^^^^^^^^^^^^^
47 > 13 | }, []);
42 - | ^^^^ CannotPreserveMemoization: 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 (9:13)
48 + | ^^^^ 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
49 14 | }
50 15 |
51 16 | export const FIXTURE_ENTRYPOINT = {
52 +
53 +
54 ```
55
56
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.todo-useCallback-captures-invalidating-value.expect.md
+7 -1
@@ -28,13 +28,19 @@ export const FIXTURE_ENTRYPOINT = {
28 ## Error
29
30 ```
31 +Found 1 error:
32 +Memoization: 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.
33 +
34 +error.todo-useCallback-captures-invalidating-value.ts:13:21
35 11 | x.push(props);
36 12 |
37 > 13 | return useCallback(() => [x], [x]);
34 - | ^^^^^^^^^ CannotPreserveMemoization: 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. (13:13)
38 + | ^^^^^^^^^ 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.
39 14 | }
40 15 |
41 16 | export const FIXTURE_ENTRYPOINT = {
42 +
43 +
44 ```
45
46
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useCallback-aliased-var.expect.md
+9 -1
@@ -19,12 +19,20 @@ function useHook(x) {
19 ## Error
20
21 ```
22 +Found 1 error:
23 +Memoization: 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
24 +
25 +The inferred dependency was `aliasedX`, but the source dependencies were [x, aliasedProp]. Inferred different dependency than source.
26 +
27 +error.useCallback-aliased-var.ts:9:21
28 7 | const aliasedProp = x.y.z;
29 8 |
30 > 9 | return useCallback(() => [aliasedX, x.y.z], [x, aliasedProp]);
25 - | ^^^^^^^^^^^^^^^^^^^^^^^ CannotPreserveMemoization: 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 (9:9)
31 + | ^^^^^^^^^^^^^^^^^^^^^^^ 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
32 10 | }
33 11 |
34 +
35 +
36 ```
37
38
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useCallback-conditional-access-noAlloc.expect.md
+9 -1
@@ -25,6 +25,12 @@ export const FIXTURE_ENTRYPOINT = {
25 ## Error
26
27 ```
28 +Found 1 error:
29 +Memoization: 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
30 +
31 +The inferred dependency was `propB?.x.y`, but the source dependencies were [propA, propB.x.y]. Inferred different dependency than source.
32 +
33 +error.useCallback-conditional-access-noAlloc.ts:5:21
34 3 |
35 4 | function Component({propA, propB}) {
36 > 5 | return useCallback(() => {
@@ -38,10 +44,12 @@ export const FIXTURE_ENTRYPOINT = {
44 > 9 | };
45 | ^^^^^^^^^^^^
46 > 10 | }, [propA, propB.x.y]);
41 - | ^^^^ CannotPreserveMemoization: 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 (5:10)
47 + | ^^^^ 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
48 11 | }
49 12 |
50 13 | export const FIXTURE_ENTRYPOINT = {
51 +
52 +
53 ```
54
55
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useCallback-infer-less-specific-conditional-access.expect.md
+9 -1
@@ -24,6 +24,12 @@ function Component({propA, propB}) {
24 ## Error
25
26 ```
27 +Found 1 error:
28 +Memoization: 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
29 +
30 +The inferred dependency was `propB`, but the source dependencies were [propA?.a, propB.x.y]. Inferred less specific property than source.
31 +
32 +error.useCallback-infer-less-specific-conditional-access.ts:6:21
33 4 |
34 5 | function Component({propA, propB}) {
35 > 6 | return useCallback(() => {
@@ -43,9 +49,11 @@ function Component({propA, propB}) {
49 > 13 | }
50 | ^^^^^^^^^^^^^^^^^
51 > 14 | }, [propA?.a, propB.x.y]);
46 - | ^^^^ CannotPreserveMemoization: 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 (6:14)
52 + | ^^^^ 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
53 15 | }
54 16 |
55 +
56 +
57 ```
58
59
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useCallback-property-call-dep.expect.md
+9 -1
@@ -17,6 +17,12 @@ function Component({propA}) {
17 ## Error
18
19 ```
20 +Found 1 error:
21 +Memoization: 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
22 +
23 +The inferred dependency was `propA`, but the source dependencies were [propA.x]. Inferred less specific property than source.
24 +
25 +error.useCallback-property-call-dep.ts:5:21
26 3 |
27 4 | function Component({propA}) {
28 > 5 | return useCallback(() => {
@@ -24,9 +30,11 @@ function Component({propA}) {
30 > 6 | return propA.x();
31 | ^^^^^^^^^^^^^^^^^^^^^
32 > 7 | }, [propA.x]);
27 - | ^^^^ CannotPreserveMemoization: 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 (5:7)
33 + | ^^^^ 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
34 8 | }
35 9 |
36 +
37 +
38 ```
39
40
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useMemo-aliased-var.expect.md
+9 -1
@@ -19,12 +19,20 @@ function useHook(x) {
19 ## Error
20
21 ```
22 +Found 1 error:
23 +Memoization: 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
24 +
25 +The inferred dependency was `x`, but the source dependencies were [aliasedX, aliasedProp]. Inferred different dependency than source.
26 +
27 +error.useMemo-aliased-var.ts:9:17
28 7 | const aliasedProp = x.y.z;
29 8 |
30 > 9 | return useMemo(() => [x, x.y.z], [aliasedX, aliasedProp]);
25 - | ^^^^^^^^^^^^^^^^ CannotPreserveMemoization: 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 (9:9)
31 + | ^^^^^^^^^^^^^^^^ 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
32 10 | }
33 11 |
34 +
35 +
36 ```
37
38
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useMemo-infer-less-specific-conditional-access.expect.md
+9 -1
@@ -24,6 +24,12 @@ function Component({propA, propB}) {
24 ## Error
25
26 ```
27 +Found 1 error:
28 +Memoization: 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
29 +
30 +The inferred dependency was `propB`, but the source dependencies were [propA?.a, propB.x.y]. Inferred less specific property than source.
31 +
32 +error.useMemo-infer-less-specific-conditional-access.ts:6:17
33 4 |
34 5 | function Component({propA, propB}) {
35 > 6 | return useMemo(() => {
@@ -43,9 +49,11 @@ function Component({propA, propB}) {
49 > 13 | }
50 | ^^^^^^^^^^^^^^^^^
51 > 14 | }, [propA?.a, propB.x.y]);
46 - | ^^^^ CannotPreserveMemoization: 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 (6:14)
52 + | ^^^^ 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
53 15 | }
54 16 |
55 +
56 +
57 ```
58
59
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useMemo-infer-less-specific-conditional-value-block.expect.md
+37 -2
@@ -24,6 +24,12 @@ function Component({propA, propB}) {
24 ## Error
25
26 ```
27 +Found 2 errors:
28 +Memoization: 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
29 +
30 +The inferred dependency was `propA`, but the source dependencies were [propA.a, propB.x.y]. Inferred less specific property than source.
31 +
32 +error.useMemo-infer-less-specific-conditional-value-block.ts:6:17
33 4 |
34 5 | function Component({propA, propB}) {
35 > 6 | return useMemo(() => {
@@ -43,11 +49,40 @@ function Component({propA, propB}) {
49 > 13 | }
50 | ^^^^^^^^^^^^^^^^^
51 > 14 | }, [propA.a, propB.x.y]);
46 - | ^^^^ CannotPreserveMemoization: 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 (6:14)
52 + | ^^^^ 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
53 + 15 | }
54 + 16 |
55 +
56 +
57 +Memoization: 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
58 +
59 +The inferred dependency was `propB`, but the source dependencies were [propA.a, propB.x.y]. Inferred less specific property than source.
60
48 -CannotPreserveMemoization: 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 (6:14)
61 +error.useMemo-infer-less-specific-conditional-value-block.ts:6:17
62 + 4 |
63 + 5 | function Component({propA, propB}) {
64 +> 6 | return useMemo(() => {
65 + | ^^^^^^^
66 +> 7 | const x = {};
67 + | ^^^^^^^^^^^^^^^^^
68 +> 8 | if (identity(null) ?? propA.a) {
69 + | ^^^^^^^^^^^^^^^^^
70 +> 9 | mutate(x);
71 + | ^^^^^^^^^^^^^^^^^
72 +> 10 | return {
73 + | ^^^^^^^^^^^^^^^^^
74 +> 11 | value: propB.x.y,
75 + | ^^^^^^^^^^^^^^^^^
76 +> 12 | };
77 + | ^^^^^^^^^^^^^^^^^
78 +> 13 | }
79 + | ^^^^^^^^^^^^^^^^^
80 +> 14 | }, [propA.a, propB.x.y]);
81 + | ^^^^ 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
82 15 | }
83 16 |
84 +
85 +
86 ```
87
88
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useMemo-property-call-chained-object.expect.md
+9 -1
@@ -19,6 +19,12 @@ function Component({propA}) {
19 ## Error
20
21 ```
22 +Found 1 error:
23 +Memoization: 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
24 +
25 +The inferred dependency was `propA`, but the source dependencies were [propA.x]. Inferred less specific property than source.
26 +
27 +error.useMemo-property-call-chained-object.ts:5:17
28 3 |
29 4 | function Component({propA}) {
30 > 5 | return useMemo(() => {
@@ -30,9 +36,11 @@ function Component({propA}) {
36 > 8 | };
37 | ^^^^^^^^^^^^
38 > 9 | }, [propA.x]);
33 - | ^^^^ CannotPreserveMemoization: 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 (5:9)
39 + | ^^^^ 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
40 10 | }
41 11 |
42 +
43 +
44 ```
45
46
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useMemo-property-call-dep.expect.md
+9 -1
@@ -17,6 +17,12 @@ function Component({propA}) {
17 ## Error
18
19 ```
20 +Found 1 error:
21 +Memoization: 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
22 +
23 +The inferred dependency was `propA`, but the source dependencies were [propA.x]. Inferred less specific property than source.
24 +
25 +error.useMemo-property-call-dep.ts:5:17
26 3 |
27 4 | function Component({propA}) {
28 > 5 | return useMemo(() => {
@@ -24,9 +30,11 @@ function Component({propA}) {
30 > 6 | return propA.x();
31 | ^^^^^^^^^^^^^^^^^^^^^
32 > 7 | }, [propA.x]);
27 - | ^^^^ CannotPreserveMemoization: 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 (5:7)
33 + | ^^^^ 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
34 8 | }
35 9 |
36 +
37 +
38 ```
39
40
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useMemo-unrelated-mutation-in-depslist.expect.md
+9 -1
@@ -30,6 +30,12 @@ function useFoo(input1) {
30 ## Error
31
32 ```
33 +Found 1 error:
34 +Memoization: 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
35 +
36 +The inferred dependency was `input1`, but the source dependencies were [y]. Inferred different dependency than source.
37 +
38 +error.useMemo-unrelated-mutation-in-depslist.ts:16:27
39 14 | const x = {};
40 15 | const y = [input1];
41 > 16 | const memoized = useMemo(() => {
@@ -37,10 +43,12 @@ function useFoo(input1) {
43 > 17 | return [y];
44 | ^^^^^^^^^^^^^^^
45 > 18 | }, [(mutate(x), y)]);
40 - | ^^^^ CannotPreserveMemoization: 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 (16:18)
46 + | ^^^^ 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
47 19 |
48 20 | return [x, memoized];
49 21 | }
50 +
51 +
52 ```
53
54
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.useMemo-with-refs.flow.expect.md
+7 -1
@@ -19,13 +19,19 @@ component Component(disableLocalRef, ref) {
19 ## Error
20
21 ```
22 +Found 1 error:
23 +Error: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
24 +
25 +undefined:7:44
26 5 | const localRef = useFooRef();
27 6 | const mergedRef = useMemo(() => {
28 > 7 | return disableLocalRef ? ref : identity(ref, localRef);
25 - | ^^^ InvalidReact: Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef) (7:7)
29 + | ^^^ Ref values (the `current` property) may not be accessed during render. (https://react.dev/reference/react/useRef)
30 8 | }, [disableLocalRef, ref, localRef]);
31 9 | return <div ref={mergedRef} />;
32 10 | }
33 +
34 +
35 ```
36
37
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/error.validate-useMemo-named-function.expect.md
+7 -1
@@ -20,13 +20,19 @@ function Component(props) {
20 ## Error
21
22 ```
23 +Found 1 error:
24 +Error: Expected the first argument to be an inline function expression
25 +
26 +error.validate-useMemo-named-function.ts:9:20
27 7 | // for now.
28 8 | function Component(props) {
29 > 9 | const x = useMemo(someHelper, []);
26 - | ^^^^^^^^^^ InvalidReact: Expected the first argument to be an inline function expression (9:9)
30 + | ^^^^^^^^^^ Expected the first argument to be an inline function expression
31 10 | return x;
32 11 | }
33 12 |
34 +
35 +
36 ```
37
38
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/error.todo-optional-call-chain-in-optional.expect.md
+7 -1
@@ -23,13 +23,19 @@ export const FIXTURE_ENTRYPONT = {
23 ## Error
24
25 ```
26 +Found 1 error:
27 +Todo: Unexpected terminal kind `optional` for optional fallthrough block
28 +
29 +error.todo-optional-call-chain-in-optional.ts:4:21
30 2 | function useFoo(props: {value: {x: string; y: string} | null}) {
31 3 | const value = props.value;
32 > 4 | return createArray(value?.x, value?.y)?.join(', ');
29 - | ^^^^^^^^ Todo: Unexpected terminal kind `optional` for optional fallthrough block (4:4)
33 + | ^^^^^^^^ Unexpected terminal kind `optional` for optional fallthrough block
34 5 | }
35 6 |
36 7 | function createArray<T>(...args: Array<T>): Array<T> {
37 +
38 +
39 ```
40
41
\ No newline at end of file
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
+9 -1
@@ -24,6 +24,12 @@ function Component(props) {
24 ## Error
25
26 ```
27 +Found 1 error:
28 +Memoization: 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
29 +
30 +The inferred dependency was `props.items`, but the source dependencies were [props?.items, props.cond]. Inferred different dependency than source.
31 +
32 +error.todo-optional-member-expression-with-conditional-optional.ts:4:23
33 2 | import {ValidateMemoization} from 'shared-runtime';
34 3 | function Component(props) {
35 > 4 | const data = useMemo(() => {
@@ -41,10 +47,12 @@ function Component(props) {
47 > 10 | return x;
48 | ^^^^^^^^^^^^^^^^^
49 > 11 | }, [props?.items, props.cond]);
44 - | ^^^^ CannotPreserveMemoization: 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 (4:11)
50 + | ^^^^ 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
51 12 | return (
52 13 | <ValidateMemoization inputs={[props?.items, props.cond]} output={data} />
53 14 | );
54 +
55 +
56 ```
57
58
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/propagate-scope-deps-hir-fork/error.todo-optional-member-expression-with-conditional.expect.md
+9 -1
@@ -24,6 +24,12 @@ function Component(props) {
24 ## Error
25
26 ```
27 +Found 1 error:
28 +Memoization: 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
29 +
30 +The inferred dependency was `props.items`, but the source dependencies were [props?.items, props.cond]. Inferred different dependency than source.
31 +
32 +error.todo-optional-member-expression-with-conditional.ts:4:23
33 2 | import {ValidateMemoization} from 'shared-runtime';
34 3 | function Component(props) {
35 > 4 | const data = useMemo(() => {
@@ -41,10 +47,12 @@ function Component(props) {
47 > 10 | return x;
48 | ^^^^^^^^^^^^^^^^^
49 > 11 | }, [props?.items, props.cond]);
44 - | ^^^^ CannotPreserveMemoization: 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 (4:11)
50 + | ^^^^ 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
51 12 | return (
52 13 | <ValidateMemoization inputs={[props?.items, props.cond]} output={data} />
53 14 | );
54 +
55 +
56 ```
57
58
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.bail.rules-of-hooks-3d692676194b.expect.md
+9 -1
@@ -20,13 +20,21 @@ const ComponentWithHookInsideCallback = React.forwardRef((props, ref) => {
20 ## Error
21
22 ```
23 +Found 1 error:
24 +Error: Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
25 +
26 +Cannot call hook within a function expression.
27 +
28 +error.bail.rules-of-hooks-3d692676194b.ts:8:4
29 6 | const ComponentWithHookInsideCallback = React.forwardRef((props, ref) => {
30 7 | useEffect(() => {
31 > 8 | useHookInsideCallback();
26 - | ^^^^^^^^^^^^^^^^^^^^^ InvalidReact: Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning). Cannot call hook within a function expression (8:8)
32 + | ^^^^^^^^^^^^^^^^^^^^^ Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
33 9 | });
34 10 | return <button {...props} ref={ref} />;
35 11 | });
36 +
37 +
38 ```
39
40
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.bail.rules-of-hooks-8503ca76d6f8.expect.md
+9 -1
@@ -20,13 +20,21 @@ const ComponentWithHookInsideCallback = React.memo(props => {
20 ## Error
21
22 ```
23 +Found 1 error:
24 +Error: Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
25 +
26 +Cannot call hook within a function expression.
27 +
28 +error.bail.rules-of-hooks-8503ca76d6f8.ts:8:4
29 6 | const ComponentWithHookInsideCallback = React.memo(props => {
30 7 | useEffect(() => {
31 > 8 | useHookInsideCallback();
26 - | ^^^^^^^^^^^^^^^^^^^^^ InvalidReact: Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning). Cannot call hook within a function expression (8:8)
32 + | ^^^^^^^^^^^^^^^^^^^^^ Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
33 9 | });
34 10 | return <button {...props} />;
35 11 | });
36 +
37 +
38 ```
39
40
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-call-phi-possibly-hook.expect.md
+28 -3
@@ -18,17 +18,42 @@ function Component(props) {
18 ## Error
19
20 ```
21 +Found 3 errors:
22 +Error: Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values
23 +
24 +error.invalid-call-phi-possibly-hook.ts:3:31
25 1 | function Component(props) {
26 2 | // This is a violation of using a hook as a normal value rule:
27 > 3 | const getUser = props.cond ? useGetUser : emptyFunction;
24 - | ^^^^^^^^^^ InvalidReact: Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values (3:3)
28 + | ^^^^^^^^^^ Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values
29 + 4 |
30 + 5 | // Ideally we would report a "conditional hook call" error here.
31 + 6 | // It's an unconditional call, but the value may or may not be a hook.
32
26 -InvalidReact: Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values (3:3)
33
28 -InvalidReact: Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values (8:8)
34 +Error: Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values
35 +
36 +error.invalid-call-phi-possibly-hook.ts:3:18
37 + 1 | function Component(props) {
38 + 2 | // This is a violation of using a hook as a normal value rule:
39 +> 3 | const getUser = props.cond ? useGetUser : emptyFunction;
40 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values
41 4 |
42 5 | // Ideally we would report a "conditional hook call" error here.
43 6 | // It's an unconditional call, but the value may or may not be a hook.
44 +
45 +
46 +Error: Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values
47 +
48 +error.invalid-call-phi-possibly-hook.ts:8:9
49 + 6 | // It's an unconditional call, but the value may or may not be a hook.
50 + 7 | // TODO: report a conditional hook call error here
51 +> 8 | return getUser();
52 + | ^^^^^^^ Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values
53 + 9 | }
54 + 10 |
55 +
56 +
57 ```
58
59
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-conditionally-call-local-named-like-hook.expect.md
+7 -1
@@ -17,13 +17,19 @@ function Component(props) {
17 ## Error
18
19 ```
20 +Found 1 error:
21 +Error: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
22 +
23 +error.invalid-conditionally-call-local-named-like-hook.ts:6:4
24 4 | const useFoo = makeObject_Primitives();
25 5 | if (props.cond) {
26 > 6 | useFoo();
23 - | ^^^^^^ InvalidReact: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning) (6:6)
27 + | ^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
28 7 | }
29 8 | }
30 9 |
31 +
32 +
33 ```
34
35
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-conditionally-call-prop-named-like-hook.expect.md
+7 -1
@@ -14,13 +14,19 @@ function Component({cond, useFoo}) {
14 ## Error
15
16 ```
17 +Found 1 error:
18 +Error: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
19 +
20 +error.invalid-conditionally-call-prop-named-like-hook.ts:3:4
21 1 | function Component({cond, useFoo}) {
22 2 | if (cond) {
23 > 3 | useFoo();
20 - | ^^^^^^ InvalidReact: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning) (3:3)
24 + | ^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
25 4 | }
26 5 | }
27 6 |
28 +
29 +
30 ```
31
32
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-conditionally-methodcall-hooklike-property-of-local.expect.md
+7 -1
@@ -17,13 +17,19 @@ function Component(props) {
17 ## Error
18
19 ```
20 +Found 1 error:
21 +Error: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
22 +
23 +error.invalid-conditionally-methodcall-hooklike-property-of-local.ts:6:4
24 4 | const local = makeObject_Primitives();
25 5 | if (props.cond) {
26 > 6 | local.useFoo();
23 - | ^^^^^^^^^^^^ InvalidReact: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning) (6:6)
27 + | ^^^^^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
28 7 | }
29 8 | }
30 9 |
31 +
32 +
33 ```
34
35
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-condtionally-call-hooklike-property-of-local.expect.md
+7 -1
@@ -18,13 +18,19 @@ function Component(props) {
18 ## Error
19
20 ```
21 +Found 1 error:
22 +Error: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
23 +
24 +error.invalid-condtionally-call-hooklike-property-of-local.ts:7:4
25 5 | if (props.cond) {
26 6 | const foo = local.useFoo;
27 > 7 | foo();
24 - | ^^^ InvalidReact: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning) (7:7)
28 + | ^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
29 8 | }
30 9 | }
31 10 |
32 +
33 +
34 ```
35
36
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-dynamic-hook-via-hooklike-local.expect.md
+7 -1
@@ -14,12 +14,18 @@ function Component() {
14 ## Error
15
16 ```
17 +Found 1 error:
18 +Error: Hooks must be the same function on every render, but this value may change over time to a different function. See https://react.dev/reference/rules/react-calls-components-and-hooks#dont-dynamically-use-hooks
19 +
20 +error.invalid-dynamic-hook-via-hooklike-local.ts:4:2
21 2 | const someFunction = useContext(FooContext);
22 3 | const useOhItsNamedLikeAHookNow = someFunction;
23 > 4 | useOhItsNamedLikeAHookNow();
20 - | ^^^^^^^^^^^^^^^^^^^^^^^^^ InvalidReact: Hooks must be the same function on every render, but this value may change over time to a different function. See https://react.dev/reference/rules/react-calls-components-and-hooks#dont-dynamically-use-hooks (4:4)
24 + | ^^^^^^^^^^^^^^^^^^^^^^^^^ Hooks must be the same function on every render, but this value may change over time to a different function. See https://react.dev/reference/rules/react-calls-components-and-hooks#dont-dynamically-use-hooks
25 5 | }
26 6 |
27 +
28 +
29 ```
30
31
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-hook-after-early-return.expect.md
+7 -1
@@ -15,12 +15,18 @@ function Component(props) {
15 ## Error
16
17 ```
18 +Found 1 error:
19 +Error: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
20 +
21 +error.invalid-hook-after-early-return.ts:5:9
22 3 | return null;
23 4 | }
24 > 5 | return useHook();
21 - | ^^^^^^^ InvalidReact: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning) (5:5)
25 + | ^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
26 6 | }
27 7 |
28 +
29 +
30 ```
31
32
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-hook-as-conditional-test.expect.md
+7 -1
@@ -13,12 +13,18 @@ function Component(props) {
13 ## Error
14
15 ```
16 +Found 1 error:
17 +Error: Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values
18 +
19 +error.invalid-hook-as-conditional-test.ts:2:26
20 1 | function Component(props) {
21 > 2 | const x = props.cond ? (useFoo ? 1 : 2) : 3;
18 - | ^^^^^^ InvalidReact: Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values (2:2)
22 + | ^^^^^^ Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values
23 3 | return x;
24 4 | }
25 5 |
26 +
27 +
28 ```
29
30
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-hook-as-prop.expect.md
+7 -1
@@ -12,11 +12,17 @@ function Component({useFoo}) {
12 ## Error
13
14 ```
15 +Found 1 error:
16 +Error: Hooks must be the same function on every render, but this value may change over time to a different function. See https://react.dev/reference/rules/react-calls-components-and-hooks#dont-dynamically-use-hooks
17 +
18 +error.invalid-hook-as-prop.ts:2:2
19 1 | function Component({useFoo}) {
20 > 2 | useFoo();
17 - | ^^^^^^ InvalidReact: Hooks must be the same function on every render, but this value may change over time to a different function. See https://react.dev/reference/rules/react-calls-components-and-hooks#dont-dynamically-use-hooks (2:2)
21 + | ^^^^^^ Hooks must be the same function on every render, but this value may change over time to a different function. See https://react.dev/reference/rules/react-calls-components-and-hooks#dont-dynamically-use-hooks
22 3 | }
23 4 |
24 +
25 +
26 ```
27
28
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-hook-for.expect.md
+19 -3
@@ -16,15 +16,31 @@ function Component(props) {
16 ## Error
17
18 ```
19 +Found 2 errors:
20 +Error: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
21 +
22 +error.invalid-hook-for.ts:4:9
23 2 | let i = 0;
24 3 | for (let x = 0; useHook(x) < 10; useHook(i), x++) {
25 > 4 | i += useHook(x);
22 - | ^^^^^^^ InvalidReact: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning) (4:4)
23 -
24 -InvalidReact: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning) (3:3)
26 + | ^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
27 5 | }
28 6 | return i;
29 7 | }
30 +
31 +
32 +Error: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
33 +
34 +error.invalid-hook-for.ts:3:35
35 + 1 | function Component(props) {
36 + 2 | let i = 0;
37 +> 3 | for (let x = 0; useHook(x) < 10; useHook(i), x++) {
38 + | ^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
39 + 4 | i += useHook(x);
40 + 5 | }
41 + 6 | return i;
42 +
43 +
44 ```
45
46
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-hook-from-hook-return.expect.md
+7 -1
@@ -14,13 +14,19 @@ function useFoo({data}) {
14 ## Error
15
16 ```
17 +Found 1 error:
18 +Error: Hooks must be the same function on every render, but this value may change over time to a different function. See https://react.dev/reference/rules/react-calls-components-and-hooks#dont-dynamically-use-hooks
19 +
20 +error.invalid-hook-from-hook-return.ts:3:14
21 1 | function useFoo({data}) {
22 2 | const useMedia = useVideoPlayer();
23 > 3 | const foo = useMedia();
20 - | ^^^^^^^^ InvalidReact: Hooks must be the same function on every render, but this value may change over time to a different function. See https://react.dev/reference/rules/react-calls-components-and-hooks#dont-dynamically-use-hooks (3:3)
24 + | ^^^^^^^^ Hooks must be the same function on every render, but this value may change over time to a different function. See https://react.dev/reference/rules/react-calls-components-and-hooks#dont-dynamically-use-hooks
25 4 | return foo;
26 5 | }
27 6 |
28 +
29 +
30 ```
31
32
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-hook-from-property-of-other-hook.expect.md
+7 -1
@@ -14,13 +14,19 @@ function useFoo({data}) {
14 ## Error
15
16 ```
17 +Found 1 error:
18 +Error: Hooks must be the same function on every render, but this value may change over time to a different function. See https://react.dev/reference/rules/react-calls-components-and-hooks#dont-dynamically-use-hooks
19 +
20 +error.invalid-hook-from-property-of-other-hook.ts:3:14
21 1 | function useFoo({data}) {
22 2 | const player = useVideoPlayer();
23 > 3 | const foo = player.useMedia();
20 - | ^^^^^^^^^^^^^^^ InvalidReact: Hooks must be the same function on every render, but this value may change over time to a different function. See https://react.dev/reference/rules/react-calls-components-and-hooks#dont-dynamically-use-hooks (3:3)
24 + | ^^^^^^^^^^^^^^^ Hooks must be the same function on every render, but this value may change over time to a different function. See https://react.dev/reference/rules/react-calls-components-and-hooks#dont-dynamically-use-hooks
25 4 | return foo;
26 5 | }
27 6 |
28 +
29 +
30 ```
31
32
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-hook-if-alternate.expect.md
+7 -1
@@ -17,13 +17,19 @@ function Component(props) {
17 ## Error
18
19 ```
20 +Found 1 error:
21 +Error: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
22 +
23 +error.invalid-hook-if-alternate.ts:5:8
24 3 | if (props.cond) {
25 4 | } else {
26 > 5 | x = useHook();
23 - | ^^^^^^^ InvalidReact: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning) (5:5)
27 + | ^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
28 6 | }
29 7 | return x;
30 8 | }
31 +
32 +
33 ```
34
35
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-hook-if-consequent.expect.md
+7 -1
@@ -16,13 +16,19 @@ function Component(props) {
16 ## Error
17
18 ```
19 +Found 1 error:
20 +Error: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
21 +
22 +error.invalid-hook-if-consequent.ts:4:8
23 2 | let x = null;
24 3 | if (props.cond) {
25 > 4 | x = useHook();
22 - | ^^^^^^^ InvalidReact: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning) (4:4)
26 + | ^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
27 5 | }
28 6 | return x;
29 7 | }
30 +
31 +
32 ```
33
34
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-hook-in-nested-function-expression-object-expression.expect.md
+9 -1
@@ -28,13 +28,21 @@ function Component() {
28 ## Error
29
30 ```
31 +Found 1 error:
32 +Error: Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
33 +
34 +Cannot call hook within a function expression.
35 +
36 +error.invalid-hook-in-nested-function-expression-object-expression.ts:10:21
37 8 | const y = {
38 9 | inner() {
39 > 10 | return useFoo();
34 - | ^^^^^^ InvalidReact: Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning). Cannot call hook within a function expression (10:10)
40 + | ^^^^^^ Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
41 11 | },
42 12 | };
43 13 | return y;
44 +
45 +
46 ```
47
48
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-hook-in-nested-object-method.expect.md
+9 -1
@@ -24,13 +24,21 @@ function Component() {
24 ## Error
25
26 ```
27 +Found 1 error:
28 +Error: Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
29 +
30 +Cannot call hook within a function expression.
31 +
32 +error.invalid-hook-in-nested-object-method.ts:8:17
33 6 | const y = {
34 7 | inner() {
35 > 8 | return useFoo();
30 - | ^^^^^^ InvalidReact: Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning). Cannot call hook within a function expression (8:8)
36 + | ^^^^^^ Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
37 9 | },
38 10 | };
39 11 | return y;
40 +
41 +
42 ```
43
44
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-hook-optional-methodcall.expect.md
+7 -1
@@ -13,12 +13,18 @@ function Component() {
13 ## Error
14
15 ```
16 +Found 1 error:
17 +Error: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
18 +
19 +error.invalid-hook-optional-methodcall.ts:2:19
20 1 | function Component() {
21 > 2 | const {result} = Module.useConditionalHook?.() ?? {};
18 - | ^^^^^^^^^^^^^^^^^^^^^^^^^ InvalidReact: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning) (2:2)
22 + | ^^^^^^^^^^^^^^^^^^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
23 3 | return result;
24 4 | }
25 5 |
26 +
27 +
28 ```
29
30
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-hook-optional-property.expect.md
+7 -1
@@ -13,12 +13,18 @@ function Component() {
13 ## Error
14
15 ```
16 +Found 1 error:
17 +Error: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
18 +
19 +error.invalid-hook-optional-property.ts:2:19
20 1 | function Component() {
21 > 2 | const {result} = Module?.useConditionalHook() ?? {};
18 - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ InvalidReact: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning) (2:2)
22 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
23 3 | return result;
24 4 | }
25 5 |
26 +
27 +
28 ```
29
30
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-hook-optionalcall.expect.md
+7 -1
@@ -13,12 +13,18 @@ function Component() {
13 ## Error
14
15 ```
16 +Found 1 error:
17 +Error: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
18 +
19 +error.invalid-hook-optionalcall.ts:2:19
20 1 | function Component() {
21 > 2 | const {result} = useConditionalHook?.() ?? {};
18 - | ^^^^^^^^^^^^^^^^^^ InvalidReact: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning) (2:2)
22 + | ^^^^^^^^^^^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
23 3 | return result;
24 4 | }
25 5 |
26 +
27 +
28 ```
29
30
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-hook-reassigned-in-conditional.expect.md
+28 -3
@@ -14,17 +14,42 @@ function Component(props) {
14 ## Error
15
16 ```
17 +Found 3 errors:
18 +Error: Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values
19 +
20 +error.invalid-hook-reassigned-in-conditional.ts:3:20
21 1 | function Component(props) {
22 2 | let y;
23 > 3 | props.cond ? (y = useFoo) : null;
20 - | ^^^^^^ InvalidReact: Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values (3:3)
24 + | ^^^^^^ Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values
25 + 4 | return y();
26 + 5 | }
27 + 6 |
28
22 -InvalidReact: Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values (3:3)
29
24 -InvalidReact: Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values (4:4)
30 +Error: Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values
31 +
32 +error.invalid-hook-reassigned-in-conditional.ts:3:16
33 + 1 | function Component(props) {
34 + 2 | let y;
35 +> 3 | props.cond ? (y = useFoo) : null;
36 + | ^ Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values
37 4 | return y();
38 5 | }
39 6 |
40 +
41 +
42 +Error: Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values
43 +
44 +error.invalid-hook-reassigned-in-conditional.ts:4:9
45 + 2 | let y;
46 + 3 | props.cond ? (y = useFoo) : null;
47 +> 4 | return y();
48 + | ^ Hooks may not be referenced as normal values, they must be called. See https://react.dev/reference/rules/react-calls-components-and-hooks#never-pass-around-hooks-as-regular-values
49 + 5 | }
50 + 6 |
51 +
52 +
53 ```
54
55
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-rules-of-hooks-1b9527f967f3.expect.md
+41 -5
@@ -25,19 +25,55 @@ function useHookInLoops() {
25 ## Error
26
27 ```
28 +Found 4 errors:
29 +Error: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
30 +
31 +error.invalid-rules-of-hooks-1b9527f967f3.ts:7:4
32 5 | function useHookInLoops() {
33 6 | while (a) {
34 > 7 | useHook1();
31 - | ^^^^^^^^ InvalidReact: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning) (7:7)
35 + | ^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
36 + 8 | if (b) return;
37 + 9 | useHook2();
38 + 10 | }
39
33 -InvalidReact: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning) (9:9)
40
35 -InvalidReact: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning) (12:12)
41 +Error: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
42
37 -InvalidReact: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning) (14:14)
43 +error.invalid-rules-of-hooks-1b9527f967f3.ts:9:4
44 + 7 | useHook1();
45 8 | if (b) return;
39 - 9 | useHook2();
46 +> 9 | useHook2();
47 + | ^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
48 + 10 | }
49 + 11 | while (c) {
50 + 12 | useHook3();
51 +
52 +
53 +Error: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
54 +
55 +error.invalid-rules-of-hooks-1b9527f967f3.ts:12:4
56 10 | }
57 + 11 | while (c) {
58 +> 12 | useHook3();
59 + | ^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
60 + 13 | if (d) return;
61 + 14 | useHook4();
62 + 15 | }
63 +
64 +
65 +Error: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
66 +
67 +error.invalid-rules-of-hooks-1b9527f967f3.ts:14:4
68 + 12 | useHook3();
69 + 13 | if (d) return;
70 +> 14 | useHook4();
71 + | ^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
72 + 15 | }
73 + 16 | }
74 + 17 |
75 +
76 +
77 ```
78
79
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-rules-of-hooks-2aabd222fc6a.expect.md
+7 -1
@@ -18,13 +18,19 @@ function ComponentWithConditionalHook() {
18 ## Error
19
20 ```
21 +Found 1 error:
22 +Error: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
23 +
24 +error.invalid-rules-of-hooks-2aabd222fc6a.ts:7:4
25 5 | function ComponentWithConditionalHook() {
26 6 | if (cond) {
27 > 7 | useConditionalHook();
24 - | ^^^^^^^^^^^^^^^^^^ InvalidReact: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning) (7:7)
28 + | ^^^^^^^^^^^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
29 8 | }
30 9 | }
31 10 |
32 +
33 +
34 ```
35
36
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-rules-of-hooks-49d341e5d68f.expect.md
+7 -1
@@ -19,13 +19,19 @@ function useLabeledBlock() {
19 ## Error
20
21 ```
22 +Found 1 error:
23 +Error: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
24 +
25 +error.invalid-rules-of-hooks-49d341e5d68f.ts:8:4
26 6 | label: {
27 7 | if (a) break label;
28 > 8 | useHook();
25 - | ^^^^^^^ InvalidReact: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning) (8:8)
29 + | ^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
30 9 | }
31 10 | }
32 11 |
33 +
34 +
35 ```
36
37
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-rules-of-hooks-79128a755612.expect.md
+7 -1
@@ -18,13 +18,19 @@ function ComponentWithHookInsideLoop() {
18 ## Error
19
20 ```
21 +Found 1 error:
22 +Error: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
23 +
24 +error.invalid-rules-of-hooks-79128a755612.ts:7:4
25 5 | function ComponentWithHookInsideLoop() {
26 6 | while (cond) {
27 > 7 | useHookInsideLoop();
24 - | ^^^^^^^^^^^^^^^^^ InvalidReact: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning) (7:7)
28 + | ^^^^^^^^^^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
29 8 | }
30 9 | }
31 10 |
32 +
33 +
34 ```
35
36
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-rules-of-hooks-9718e30b856c.expect.md
+7 -1
@@ -22,12 +22,18 @@ function useHook() {
22 ## Error
23
24 ```
25 +Found 1 error:
26 +Error: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
27 +
28 +error.invalid-rules-of-hooks-9718e30b856c.ts:12:2
29 10 | console.log('false');
30 11 | }
31 > 12 | useState();
28 - | ^^^^^^^^ InvalidReact: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning) (12:12)
32 + | ^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
33 13 | }
34 14 |
35 +
36 +
37 ```
38
39
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-rules-of-hooks-9bf17c174134.expect.md
+18 -3
@@ -17,15 +17,30 @@ function useHook() {
17 ## Error
18
19 ```
20 +Found 2 errors:
21 +Error: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
22 +
23 +error.invalid-rules-of-hooks-9bf17c174134.ts:6:7
24 4 | // This *must* be invalid.
25 5 | function useHook() {
26 > 6 | a && useHook1();
23 - | ^^^^^^^^ InvalidReact: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning) (6:6)
24 -
25 -InvalidReact: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning) (7:7)
27 + | ^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
28 7 | b && useHook2();
29 8 | }
30 9 |
31 +
32 +
33 +Error: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
34 +
35 +error.invalid-rules-of-hooks-9bf17c174134.ts:7:7
36 + 5 | function useHook() {
37 + 6 | a && useHook1();
38 +> 7 | b && useHook2();
39 + | ^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
40 + 8 | }
41 + 9 |
42 +
43 +
44 ```
45
46
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-rules-of-hooks-b4dcda3d60ed.expect.md
+7 -1
@@ -16,12 +16,18 @@ function ComponentWithTernaryHook() {
16 ## Error
17
18 ```
19 +Found 1 error:
20 +Error: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
21 +
22 +error.invalid-rules-of-hooks-b4dcda3d60ed.ts:6:9
23 4 | // This *must* be invalid.
24 5 | function ComponentWithTernaryHook() {
25 > 6 | cond ? useTernaryHook() : null;
22 - | ^^^^^^^^^^^^^^ InvalidReact: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning) (6:6)
26 + | ^^^^^^^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
27 7 | }
28 8 |
29 +
30 +
31 ```
32
33
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-rules-of-hooks-c906cace44e9.expect.md
+7 -1
@@ -17,12 +17,18 @@ function useHook() {
17 ## Error
18
19 ```
20 +Found 1 error:
21 +Error: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
22 +
23 +error.invalid-rules-of-hooks-c906cace44e9.ts:7:2
24 5 | function useHook() {
25 6 | if (a) return;
26 > 7 | useState();
23 - | ^^^^^^^^ InvalidReact: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning) (7:7)
27 + | ^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
28 8 | }
29 9 |
30 +
31 +
32 ```
33
34
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-rules-of-hooks-d740d54e9c21.expect.md
+7 -1
@@ -18,13 +18,19 @@ function normalFunctionWithConditionalHook() {
18 ## Error
19
20 ```
21 +Found 1 error:
22 +Error: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
23 +
24 +error.invalid-rules-of-hooks-d740d54e9c21.ts:7:4
25 5 | function normalFunctionWithConditionalHook() {
26 6 | if (cond) {
27 > 7 | useHookInsideNormalFunction();
24 - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ InvalidReact: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning) (7:7)
28 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
29 8 | }
30 9 | }
31 10 |
32 +
33 +
34 ```
35
36
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-rules-of-hooks-d85c144bdf40.expect.md
+19 -3
@@ -20,15 +20,31 @@ function useHookInLoops() {
20 ## Error
21
22 ```
23 +Found 2 errors:
24 +Error: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
25 +
26 +error.invalid-rules-of-hooks-d85c144bdf40.ts:7:4
27 5 | function useHookInLoops() {
28 6 | while (a) {
29 > 7 | useHook1();
26 - | ^^^^^^^^ InvalidReact: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning) (7:7)
27 -
28 -InvalidReact: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning) (9:9)
30 + | ^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
31 8 | if (b) continue;
32 9 | useHook2();
33 10 | }
34 +
35 +
36 +Error: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
37 +
38 +error.invalid-rules-of-hooks-d85c144bdf40.ts:9:4
39 + 7 | useHook1();
40 + 8 | if (b) continue;
41 +> 9 | useHook2();
42 + | ^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
43 + 10 | }
44 + 11 | }
45 + 12 |
46 +
47 +
48 ```
49
50
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-rules-of-hooks-ea7c2fb545a9.expect.md
+7 -1
@@ -18,13 +18,19 @@ function useHookWithConditionalHook() {
18 ## Error
19
20 ```
21 +Found 1 error:
22 +Error: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
23 +
24 +error.invalid-rules-of-hooks-ea7c2fb545a9.ts:7:4
25 5 | function useHookWithConditionalHook() {
26 6 | if (cond) {
27 > 7 | useConditionalHook();
24 - | ^^^^^^^^^^^^^^^^^^ InvalidReact: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning) (7:7)
28 + | ^^^^^^^^^^^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
29 8 | }
30 9 | }
31 10 |
32 +
33 +
34 ```
35
36
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-rules-of-hooks-f3d6c5e9c83d.expect.md
+7 -1
@@ -22,12 +22,18 @@ function useHook() {
22 ## Error
23
24 ```
25 +Found 1 error:
26 +Error: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
27 +
28 +error.invalid-rules-of-hooks-f3d6c5e9c83d.ts:12:2
29 10 | }
30 11 | if (a) return;
31 > 12 | useState();
28 - | ^^^^^^^^ InvalidReact: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning) (12:12)
32 + | ^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
33 13 | }
34 14 |
35 +
36 +
37 ```
38
39
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid-rules-of-hooks-f69800950ff0.expect.md
+30 -5
@@ -18,17 +18,42 @@ function useHook({bar}) {
18 ## Error
19
20 ```
21 +Found 3 errors:
22 +Error: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
23 +
24 +error.invalid-rules-of-hooks-f69800950ff0.ts:6:20
25 4 | // This *must* be invalid.
26 5 | function useHook({bar}) {
27 > 6 | let foo1 = bar && useState();
24 - | ^^^^^^^^ InvalidReact: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning) (6:6)
25 -
26 -InvalidReact: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning) (7:7)
27 -
28 -InvalidReact: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning) (8:8)
28 + | ^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
29 7 | let foo2 = bar || useState();
30 8 | let foo3 = bar ?? useState();
31 9 | }
32 +
33 +
34 +Error: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
35 +
36 +error.invalid-rules-of-hooks-f69800950ff0.ts:7:20
37 + 5 | function useHook({bar}) {
38 + 6 | let foo1 = bar && useState();
39 +> 7 | let foo2 = bar || useState();
40 + | ^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
41 + 8 | let foo3 = bar ?? useState();
42 + 9 | }
43 + 10 |
44 +
45 +
46 +Error: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
47 +
48 +error.invalid-rules-of-hooks-f69800950ff0.ts:8:20
49 + 6 | let foo1 = bar && useState();
50 + 7 | let foo2 = bar || useState();
51 +> 8 | let foo3 = bar ?? useState();
52 + | ^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
53 + 9 | }
54 + 10 |
55 +
56 +
57 ```
58
59
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid.invalid-rules-of-hooks-0a1dbff27ba0.expect.md
+9 -1
@@ -18,13 +18,21 @@ function createHook() {
18 ## Error
19
20 ```
21 +Found 1 error:
22 +Error: Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
23 +
24 +Cannot call hook within a function expression.
25 +
26 +error.invalid.invalid-rules-of-hooks-0a1dbff27ba0.ts:6:6
27 4 | return function useHookWithConditionalHook() {
28 5 | if (cond) {
29 > 6 | useConditionalHook();
24 - | ^^^^^^^^^^^^^^^^^^ InvalidReact: Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning). Cannot call hook within a function expression (6:6)
30 + | ^^^^^^^^^^^^^^^^^^ Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
31 7 | }
32 8 | };
33 9 | }
34 +
35 +
36 ```
37
38
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid.invalid-rules-of-hooks-0de1224ce64b.expect.md
+23 -3
@@ -18,15 +18,35 @@ function createComponent() {
18 ## Error
19
20 ```
21 +Found 2 errors:
22 +Error: Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
23 +
24 +Cannot call hook within a function expression.
25 +
26 +error.invalid.invalid-rules-of-hooks-0de1224ce64b.ts:6:6
27 4 | return function ComponentWithHookInsideCallback() {
28 5 | useEffect(() => {
29 > 6 | useHookInsideCallback();
24 - | ^^^^^^^^^^^^^^^^^^^^^ InvalidReact: Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning). Cannot call hook within a function expression (6:6)
25 -
26 -InvalidReact: Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning). Cannot call useEffect within a function expression (5:5)
30 + | ^^^^^^^^^^^^^^^^^^^^^ Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
31 7 | });
32 8 | };
33 9 | }
34 +
35 +
36 +Error: Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
37 +
38 +Cannot call useEffect within a function expression.
39 +
40 +error.invalid.invalid-rules-of-hooks-0de1224ce64b.ts:5:4
41 + 3 | function createComponent() {
42 + 4 | return function ComponentWithHookInsideCallback() {
43 +> 5 | useEffect(() => {
44 + | ^^^^^^^^^ Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
45 + 6 | useHookInsideCallback();
46 + 7 | });
47 + 8 | };
48 +
49 +
50 ```
51
52
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid.invalid-rules-of-hooks-449a37146a83.expect.md
+9 -1
@@ -18,13 +18,21 @@ function createComponent() {
18 ## Error
19
20 ```
21 +Found 1 error:
22 +Error: Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
23 +
24 +Cannot call useState within a function expression.
25 +
26 +error.invalid.invalid-rules-of-hooks-449a37146a83.ts:6:6
27 4 | return function ComponentWithHookInsideCallback() {
28 5 | function handleClick() {
29 > 6 | useState();
24 - | ^^^^^^^^ InvalidReact: Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning). Cannot call useState within a function expression (6:6)
30 + | ^^^^^^^^ Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
31 7 | }
32 8 | };
33 9 | }
34 +
35 +
36 ```
37
38
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid.invalid-rules-of-hooks-76a74b4666e9.expect.md
+9 -1
@@ -16,13 +16,21 @@ function ComponentWithHookInsideCallback() {
16 ## Error
17
18 ```
19 +Found 1 error:
20 +Error: Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
21 +
22 +Cannot call useState within a function expression.
23 +
24 +error.invalid.invalid-rules-of-hooks-76a74b4666e9.ts:5:4
25 3 | function ComponentWithHookInsideCallback() {
26 4 | function handleClick() {
27 > 5 | useState();
22 - | ^^^^^^^^ InvalidReact: Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning). Cannot call useState within a function expression (5:5)
28 + | ^^^^^^^^ Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
29 6 | }
30 7 | }
31 8 |
32 +
33 +
34 ```
35
36
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid.invalid-rules-of-hooks-d842d36db450.expect.md
+9 -1
@@ -18,13 +18,21 @@ function createComponent() {
18 ## Error
19
20 ```
21 +Found 1 error:
22 +Error: Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
23 +
24 +Cannot call hook within a function expression.
25 +
26 +error.invalid.invalid-rules-of-hooks-d842d36db450.ts:6:6
27 4 | return function ComponentWithConditionalHook() {
28 5 | if (cond) {
29 > 6 | useConditionalHook();
24 - | ^^^^^^^^^^^^^^^^^^ InvalidReact: Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning). Cannot call hook within a function expression (6:6)
30 + | ^^^^^^^^^^^^^^^^^^ Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
31 7 | }
32 8 | };
33 9 | }
34 +
35 +
36 ```
37
38
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/error.invalid.invalid-rules-of-hooks-d952b82c2597.expect.md
+9 -1
@@ -16,13 +16,21 @@ function ComponentWithHookInsideCallback() {
16 ## Error
17
18 ```
19 +Found 1 error:
20 +Error: Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
21 +
22 +Cannot call hook within a function expression.
23 +
24 +error.invalid.invalid-rules-of-hooks-d952b82c2597.ts:5:4
25 3 | function ComponentWithHookInsideCallback() {
26 4 | useEffect(() => {
27 > 5 | useHookInsideCallback();
22 - | ^^^^^^^^^^^^^^^^^^^^^ InvalidReact: Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning). Cannot call hook within a function expression (5:5)
28 + | ^^^^^^^^^^^^^^^^^^^^^ Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
29 6 | });
30 7 | }
31 8 |
32 +
33 +
34 ```
35
36
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/todo.error.invalid-rules-of-hooks-368024110a58.expect.md
+7 -1
@@ -20,13 +20,19 @@ const FancyButton = forwardRef(function (props, ref) {
20 ## Error
21
22 ```
23 +Found 1 error:
24 +Error: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
25 +
26 +todo.error.invalid-rules-of-hooks-368024110a58.ts:8:4
27 6 | const FancyButton = forwardRef(function (props, ref) {
28 7 | if (props.fancy) {
29 > 8 | useCustomHook();
26 - | ^^^^^^^^^^^^^ InvalidReact: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning) (8:8)
30 + | ^^^^^^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
31 9 | }
32 10 | return <button ref={ref}>{props.children}</button>;
33 11 | });
34 +
35 +
36 ```
37
38
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/todo.error.invalid-rules-of-hooks-8566f9a360e2.expect.md
+7 -1
@@ -20,13 +20,19 @@ const MemoizedButton = memo(function (props) {
20 ## Error
21
22 ```
23 +Found 1 error:
24 +Error: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
25 +
26 +todo.error.invalid-rules-of-hooks-8566f9a360e2.ts:8:4
27 6 | const MemoizedButton = memo(function (props) {
28 7 | if (props.fancy) {
29 > 8 | useCustomHook();
26 - | ^^^^^^^^^^^^^ InvalidReact: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning) (8:8)
30 + | ^^^^^^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
31 9 | }
32 10 | return <button>{props.children}</button>;
33 11 | });
34 +
35 +
36 ```
37
38
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/todo.error.invalid-rules-of-hooks-a0058f0b446d.expect.md
+7 -1
@@ -19,13 +19,19 @@ function ComponentWithConditionalHook() {
19 ## Error
20
21 ```
22 +Found 1 error:
23 +Error: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
24 +
25 +todo.error.invalid-rules-of-hooks-a0058f0b446d.ts:8:4
26 6 | function ComponentWithConditionalHook() {
27 7 | if (cond) {
28 > 8 | Namespace.useConditionalHook();
25 - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ InvalidReact: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning) (8:8)
29 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
30 9 | }
31 10 | }
32 11 |
33 +
34 +
35 ```
36
37
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/todo.error.rules-of-hooks-27c18dc8dad2.expect.md
+7 -1
@@ -20,13 +20,19 @@ const FancyButton = React.forwardRef((props, ref) => {
20 ## Error
21
22 ```
23 +Found 1 error:
24 +Error: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
25 +
26 +todo.error.rules-of-hooks-27c18dc8dad2.ts:8:4
27 6 | const FancyButton = React.forwardRef((props, ref) => {
28 7 | if (props.fancy) {
29 > 8 | useCustomHook();
26 - | ^^^^^^^^^^^^^ InvalidReact: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning) (8:8)
30 + | ^^^^^^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
31 9 | }
32 10 | return <button ref={ref}>{props.children}</button>;
33 11 | });
34 +
35 +
36 ```
37
38
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/todo.error.rules-of-hooks-d0935abedc42.expect.md
+7 -1
@@ -19,13 +19,19 @@ React.unknownFunction((foo, bar) => {
19 ## Error
20
21 ```
22 +Found 1 error:
23 +Error: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
24 +
25 +todo.error.rules-of-hooks-d0935abedc42.ts:8:4
26 6 | React.unknownFunction((foo, bar) => {
27 7 | if (foo) {
28 > 8 | useNotAHook(bar);
25 - | ^^^^^^^^^^^ InvalidReact: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning) (8:8)
29 + | ^^^^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
30 9 | }
31 10 | });
32 11 |
33 +
34 +
35 ```
36
37
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/todo.error.rules-of-hooks-e29c874aa913.expect.md
+7 -1
@@ -20,13 +20,19 @@ function useHook() {
20 ## Error
21
22 ```
23 +Found 1 error:
24 +Error: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
25 +
26 +todo.error.rules-of-hooks-e29c874aa913.ts:9:4
27 7 | try {
28 8 | f();
29 > 9 | useState();
26 - | ^^^^^^^^ InvalidReact: Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning) (9:9)
30 + | ^^^^^^^^ Hooks must always be called in a consistent order, and may not be called conditionally. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
31 10 | } catch {}
32 11 | }
33 12 |
34 +
35 +
36 ```
37
38
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/todo.error.object-pattern-computed-key.expect.md
+7 -1
@@ -21,13 +21,19 @@ export const FIXTURE_ENTRYPOINT = {
21 ## Error
22
23 ```
24 +Found 1 error:
25 +Todo: (BuildHIR::lowerAssignment) Handle computed properties in ObjectPattern
26 +
27 +todo.error.object-pattern-computed-key.ts:5:9
28 3 | const SCALE = 2;
29 4 | function Component(props) {
30 > 5 | const {[props.name]: value} = props;
27 - | ^^^^^^^^^^^^^^^^^^^ Todo: (BuildHIR::lowerAssignment) Handle computed properties in ObjectPattern (5:5)
31 + | ^^^^^^^^^^^^^^^^^^^ (BuildHIR::lowerAssignment) Handle computed properties in ObjectPattern
32 6 | return value;
33 7 | }
34 8 |
35 +
36 +
37 ```
38
39
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transform-fire/bailout-retry/error.todo-syntax.expect.md
+7 -1
@@ -29,10 +29,16 @@ function Component({prop1}) {
29 ## Error
30
31 ```
32 +Found 1 error:
33 +Error: [Fire] Untransformed reference to compiler-required feature.
34 +
35 + Todo: (BuildHIR::lowerStatement) Handle TryStatement without a catch clause (11:4)
36 +
37 +error.todo-syntax.ts:18:4
38 16 | };
39 17 | useEffect(() => {
40 > 18 | fire(foo());
35 - | ^^^^ InvalidReact: [Fire] Untransformed reference to compiler-required feature. Either remove this `fire` call or ensure it is successfully transformed by the compiler. (Bailout reason: Todo: (BuildHIR::lowerStatement) Handle TryStatement without a catch clause (11:15)) (18:18)
41 + | ^^^^ Untransformed `fire` call
42 19 | });
43 20 | }
44 21 |
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transform-fire/bailout-retry/error.untransformed-fire-reference.expect.md
+7 -1
@@ -13,10 +13,16 @@ console.log(fire == null);
13 ## Error
14
15 ```
16 +Found 1 error:
17 +Error: [Fire] Untransformed reference to compiler-required feature.
18 +
19 + null
20 +
21 +error.untransformed-fire-reference.ts:4:12
22 2 | import {fire} from 'react';
23 3 |
24 > 4 | console.log(fire == null);
19 - | ^^^^ InvalidReact: [Fire] Untransformed reference to compiler-required feature. Either remove this `fire` call or ensure it is successfully transformed by the compiler (4:4)
25 + | ^^^^ Untransformed `fire` call
26 5 |
27 ```
28
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transform-fire/bailout-retry/error.use-no-memo.expect.md
+7 -1
@@ -30,10 +30,16 @@ function Component({props, bar}) {
30 ## Error
31
32 ```
33 +Found 1 error:
34 +Error: [Fire] Untransformed reference to compiler-required feature.
35 +
36 + null
37 +
38 +error.use-no-memo.ts:15:4
39 13 | };
40 14 | useEffect(() => {
41 > 15 | fire(foo(props));
36 - | ^^^^ InvalidReact: [Fire] Untransformed reference to compiler-required feature. Either remove this `fire` call or ensure it is successfully transformed by the compiler (15:15)
42 + | ^^^^ Untransformed `fire` call
43 16 | fire(foo());
44 17 | fire(bar());
45 18 | });
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transform-fire/error.invalid-mix-fire-and-no-fire.expect.md
+9 -1
@@ -27,13 +27,21 @@ function Component(props) {
27 ## Error
28
29 ```
30 +Found 1 error:
31 +Error: Cannot compile `fire`
32 +
33 +All uses of foo must be either used with a fire() call in this effect or not used with a fire() call at all. foo was used with fire() on line 10:10 in this effect.
34 +
35 +error.invalid-mix-fire-and-no-fire.ts:11:6
36 9 | function nested() {
37 10 | fire(foo(props));
38 > 11 | foo(props);
33 - | ^^^ InvalidReact: Cannot compile `fire`. All uses of foo must be either used with a fire() call in this effect or not used with a fire() call at all. foo was used with fire() on line 10:10 in this effect (11:11)
39 + | ^^^ Cannot compile `fire`
40 12 | }
41 13 |
42 14 | nested();
43 +
44 +
45 ```
46
47
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transform-fire/error.invalid-multiple-args.expect.md
+9 -1
@@ -22,13 +22,21 @@ function Component({bar, baz}) {
22 ## Error
23
24 ```
25 +Found 1 error:
26 +Error: Cannot compile `fire`
27 +
28 +fire() can only take in a single call expression as an argument but received multiple arguments.
29 +
30 +error.invalid-multiple-args.ts:9:4
31 7 | };
32 8 | useEffect(() => {
33 > 9 | fire(foo(bar), baz);
28 - | ^^^^^^^^^^^^^^^^^^^ InvalidReact: Cannot compile `fire`. fire() can only take in a single call expression as an argument but received multiple arguments (9:9)
34 + | ^^^^^^^^^^^^^^^^^^^ Cannot compile `fire`
35 10 | });
36 11 |
37 12 | return null;
38 +
39 +
40 ```
41
42
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transform-fire/error.invalid-nested-use-effect.expect.md
+9 -1
@@ -28,13 +28,21 @@ function Component(props) {
28 ## Error
29
30 ```
31 +Found 1 error:
32 +Error: Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
33 +
34 +Cannot call useEffect within a function expression.
35 +
36 +error.invalid-nested-use-effect.ts:9:4
37 7 | };
38 8 | useEffect(() => {
39 > 9 | useEffect(() => {
34 - | ^^^^^^^^^ InvalidReact: Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning). Cannot call useEffect within a function expression (9:9)
40 + | ^^^^^^^^^ Hooks must be called at the top level in the body of a function component or custom hook, and may not be called within function expressions. See the Rules of Hooks (https://react.dev/warnings/invalid-hook-call-warning)
41 10 | function nested() {
42 11 | fire(foo(props));
43 12 | }
44 +
45 +
46 ```
47
48
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transform-fire/error.invalid-not-call.expect.md
+9 -1
@@ -22,13 +22,21 @@ function Component(props) {
22 ## Error
23
24 ```
25 +Found 1 error:
26 +Error: Cannot compile `fire`
27 +
28 +`fire()` can only receive a function call such as `fire(fn(a,b)). Method calls and other expressions are not allowed.
29 +
30 +error.invalid-not-call.ts:9:4
31 7 | };
32 8 | useEffect(() => {
33 > 9 | fire(props);
28 - | ^^^^^^^^^^^ InvalidReact: Cannot compile `fire`. `fire()` can only receive a function call such as `fire(fn(a,b)). Method calls and other expressions are not allowed (9:9)
34 + | ^^^^^^^^^^^ Cannot compile `fire`
35 10 | });
36 11 |
37 12 | return null;
38 +
39 +
40 ```
41
42
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transform-fire/error.invalid-outside-effect.expect.md
+23 -3
@@ -24,15 +24,35 @@ function Component({props, bar}) {
24 ## Error
25
26 ```
27 +Found 2 errors:
28 +Invariant: Cannot compile `fire`
29 +
30 +Cannot use `fire` outside of a useEffect function.
31 +
32 +error.invalid-outside-effect.ts:8:2
33 6 | console.log(props);
34 7 | };
35 > 8 | fire(foo(props));
30 - | ^^^^ Invariant: Cannot compile `fire`. Cannot use `fire` outside of a useEffect function (8:8)
31 -
32 -Invariant: Cannot compile `fire`. Cannot use `fire` outside of a useEffect function (11:11)
36 + | ^^^^ Cannot compile `fire`
37 9 |
38 10 | useCallback(() => {
39 11 | fire(foo(props));
40 +
41 +
42 +Invariant: Cannot compile `fire`
43 +
44 +Cannot use `fire` outside of a useEffect function.
45 +
46 +error.invalid-outside-effect.ts:11:4
47 + 9 |
48 + 10 | useCallback(() => {
49 +> 11 | fire(foo(props));
50 + | ^^^^ Cannot compile `fire`
51 + 12 | }, [foo, props]);
52 + 13 |
53 + 14 | return null;
54 +
55 +
56 ```
57
58
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transform-fire/error.invalid-rewrite-deps-no-array-literal.expect.md
+9 -1
@@ -25,13 +25,21 @@ function Component(props) {
25 ## Error
26
27 ```
28 +Found 1 error:
29 +Invariant: Cannot compile `fire`
30 +
31 +You must use an array literal for an effect dependency array when that effect uses `fire()`.
32 +
33 +error.invalid-rewrite-deps-no-array-literal.ts:13:5
34 11 | useEffect(() => {
35 12 | fire(foo(props));
36 > 13 | }, deps);
31 - | ^^^^ Invariant: Cannot compile `fire`. You must use an array literal for an effect dependency array when that effect uses `fire()` (13:13)
37 + | ^^^^ Cannot compile `fire`
38 14 |
39 15 | return null;
40 16 | }
41 +
42 +
43 ```
44
45
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transform-fire/error.invalid-rewrite-deps-spread.expect.md
+9 -1
@@ -28,13 +28,21 @@ function Component(props) {
28 ## Error
29
30 ```
31 +Found 1 error:
32 +Invariant: Cannot compile `fire`
33 +
34 +You must use an array literal for an effect dependency array when that effect uses `fire()`.
35 +
36 +error.invalid-rewrite-deps-spread.ts:15:7
37 13 | fire(foo(props));
38 14 | },
39 > 15 | ...deps
34 - | ^^^^ Invariant: Cannot compile `fire`. You must use an array literal for an effect dependency array when that effect uses `fire()` (15:15)
40 + | ^^^^ Cannot compile `fire`
41 16 | );
42 17 |
43 18 | return null;
44 +
45 +
46 ```
47
48
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transform-fire/error.invalid-spread.expect.md
+9 -1
@@ -22,13 +22,21 @@ function Component(props) {
22 ## Error
23
24 ```
25 +Found 1 error:
26 +Error: Cannot compile `fire`
27 +
28 +fire() can only take in a single call expression as an argument but received a spread argument.
29 +
30 +error.invalid-spread.ts:9:4
31 7 | };
32 8 | useEffect(() => {
33 > 9 | fire(...foo);
28 - | ^^^^^^^^^^^^ InvalidReact: Cannot compile `fire`. fire() can only take in a single call expression as an argument but received a spread argument (9:9)
34 + | ^^^^^^^^^^^^ Cannot compile `fire`
35 10 | });
36 11 |
37 12 | return null;
38 +
39 +
40 ```
41
42
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transform-fire/error.todo-method.expect.md
+9 -1
@@ -22,13 +22,21 @@ function Component(props) {
22 ## Error
23
24 ```
25 +Found 1 error:
26 +Error: Cannot compile `fire`
27 +
28 +`fire()` can only receive a function call such as `fire(fn(a,b)). Method calls and other expressions are not allowed.
29 +
30 +error.todo-method.ts:9:4
31 7 | };
32 8 | useEffect(() => {
33 > 9 | fire(props.foo());
28 - | ^^^^^^^^^^^^^^^^^ InvalidReact: Cannot compile `fire`. `fire()` can only receive a function call such as `fire(fn(a,b)). Method calls and other expressions are not allowed (9:9)
34 + | ^^^^^^^^^^^^^^^^^ Cannot compile `fire`
35 10 | });
36 11 |
37 12 | return null;
38 +
39 +
40 ```
41
42
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/index.ts
+3
@@ -9,9 +9,12 @@ export {runBabelPluginReactCompiler} from './Babel/RunReactCompilerBabelPlugin';
9 export {
10 CompilerError,
11 CompilerErrorDetail,
12 + CompilerDiagnostic,
13 CompilerSuggestionOperation,
14 ErrorSeverity,
15 type CompilerErrorDetailOptions,
16 + type CompilerDiagnosticOptions,
17 + type CompilerDiagnosticDetail,
18 } from './CompilerError';
19 export {
20 compileFn as compile,
compiler/packages/eslint-plugin-react-compiler/__tests__/ReactCompilerRule-test.ts
+7 -13
@@ -104,8 +104,7 @@ const tests: CompilerTestCases = {
104 }`,
105 errors: [
106 {
107 - message:
108 - '(BuildHIR::lowerStatement) Handle var kinds in VariableDeclaration',
107 + message: /Handle var kinds in VariableDeclaration/,
108 },
109 ],
110 },
@@ -119,8 +118,7 @@ const tests: CompilerTestCases = {
118 }`,
119 errors: [
120 {
122 - message:
123 - 'React Compiler has skipped optimizing this component because one or more React ESLint rules were disabled. React Compiler only works when your components follow all the rules of React, disabling them may result in unexpected or incorrect behavior',
121 + message: /React Compiler has skipped optimizing this component/,
122 suggestions: [
123 {
124 output: normalizeIndent`
@@ -158,12 +156,10 @@ const tests: CompilerTestCases = {
156 }`,
157 errors: [
158 {
161 - message:
162 - '(BuildHIR::lowerStatement) Handle var kinds in VariableDeclaration',
159 + message: /Handle var kinds in VariableDeclaration/,
160 },
161 {
165 - message:
166 - 'Mutating component props or hook arguments is not allowed. Consider using a local variable instead',
162 + message: /Mutating component props or hook arguments is not allowed/,
163 },
164 ],
165 },
@@ -182,8 +178,7 @@ const tests: CompilerTestCases = {
178 }`,
179 errors: [
180 {
185 - message:
186 - '[ReactCompilerBailout] (BuildHIR::lowerStatement) Handle var kinds in VariableDeclaration (@:3:2)',
181 + message: /Handle var kinds in VariableDeclaration/,
182 },
183 ],
184 },
@@ -200,7 +195,7 @@ const tests: CompilerTestCases = {
195 errors: [
196 {
197 message:
203 - 'Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render)',
198 + /Unexpected reassignment of a variable which was defined outside of the component/,
199 },
200 ],
201 },
@@ -274,8 +269,7 @@ const tests: CompilerTestCases = {
269 ],
270 errors: [
271 {
277 - message:
278 - '[InferEffectDependencies] React Compiler is unable to infer dependencies of this effect. This will break your build! To resolve, either pass your own dependency array or fix reported compiler bailout diagnostics.',
272 + message: /Cannot infer dependencies of this effect/,
273 },
274 ],
275 },
compiler/packages/eslint-plugin-react-compiler/__tests__/ReactCompilerRuleTypescript-test.ts
+1 -2
@@ -61,8 +61,7 @@ const tests: CompilerTestCases = {
61 `,
62 errors: [
63 {
64 - message:
65 - "Mutating a value returned from 'useState()', which should not be mutated. Use the setter function to update instead",
64 + message: /Mutating a value returned from 'useState\(\)'/,
65 line: 7,
66 },
67 ],
compiler/packages/eslint-plugin-react-compiler/src/rules/ReactCompilerRule.ts
+37 -40
@@ -10,6 +10,9 @@ import {transformFromAstSync} from '@babel/core';
10 import PluginProposalPrivateMethods from '@babel/plugin-proposal-private-methods';
11 import type {SourceLocation as BabelSourceLocation} from '@babel/types';
12 import BabelPluginReactCompiler, {
13 + CompilerDiagnostic,
14 + CompilerDiagnosticOptions,
15 + CompilerErrorDetail,
16 CompilerErrorDetailOptions,
17 CompilerSuggestionOperation,
18 ErrorSeverity,
@@ -18,15 +21,11 @@ import BabelPluginReactCompiler, {
21 OPT_OUT_DIRECTIVES,
22 type PluginOptions,
23 } from 'babel-plugin-react-compiler/src';
21 -import {Logger} from 'babel-plugin-react-compiler/src/Entrypoint';
24 +import {Logger, LoggerEvent} from 'babel-plugin-react-compiler/src/Entrypoint';
25 import type {Rule} from 'eslint';
26 import {Statement} from 'estree';
27 import * as HermesParser from 'hermes-parser';
28
26 -type CompilerErrorDetailWithLoc = Omit<CompilerErrorDetailOptions, 'loc'> & {
27 - loc: BabelSourceLocation;
28 -};
29 -
29 function assertExhaustive(_: never, errorMsg: string): never {
30 throw new Error(errorMsg);
31 }
@@ -38,19 +37,15 @@ const DEFAULT_REPORTABLE_LEVELS = new Set([
37 let reportableLevels = DEFAULT_REPORTABLE_LEVELS;
38
39 function isReportableDiagnostic(
41 - detail: CompilerErrorDetailOptions,
42 -): detail is CompilerErrorDetailWithLoc {
43 - return (
44 - reportableLevels.has(detail.severity) &&
45 - detail.loc != null &&
46 - typeof detail.loc !== 'symbol'
47 - );
40 + detail: CompilerErrorDetail | CompilerDiagnostic,
41 +): boolean {
42 + return reportableLevels.has(detail.severity);
43 }
44
45 function makeSuggestions(
51 - detail: CompilerErrorDetailOptions,
46 + detail: CompilerErrorDetailOptions | CompilerDiagnosticOptions,
47 ): Array<Rule.SuggestionReportDescriptor> {
53 - let suggest: Array<Rule.SuggestionReportDescriptor> = [];
48 + const suggest: Array<Rule.SuggestionReportDescriptor> = [];
49 if (Array.isArray(detail.suggestions)) {
50 for (const suggestion of detail.suggestions) {
51 switch (suggestion.op) {
@@ -134,10 +129,10 @@ const rule: Rule.RuleModule = {
129 const filename = context.filename ?? context.getFilename();
130 const userOpts = context.options[0] ?? {};
131 if (
137 - userOpts['reportableLevels'] != null &&
138 - userOpts['reportableLevels'] instanceof Set
132 + userOpts.reportableLevels != null &&
133 + userOpts.reportableLevels instanceof Set
134 ) {
140 - reportableLevels = userOpts['reportableLevels'];
135 + reportableLevels = userOpts.reportableLevels;
136 } else {
137 reportableLevels = DEFAULT_REPORTABLE_LEVELS;
138 }
@@ -150,11 +145,11 @@ const rule: Rule.RuleModule = {
145 */
146 let __unstable_donotuse_reportAllBailouts: boolean = false;
147 if (
153 - userOpts['__unstable_donotuse_reportAllBailouts'] != null &&
154 - typeof userOpts['__unstable_donotuse_reportAllBailouts'] === 'boolean'
148 + userOpts.__unstable_donotuse_reportAllBailouts != null &&
149 + typeof userOpts.__unstable_donotuse_reportAllBailouts === 'boolean'
150 ) {
151 __unstable_donotuse_reportAllBailouts =
157 - userOpts['__unstable_donotuse_reportAllBailouts'];
152 + userOpts.__unstable_donotuse_reportAllBailouts;
153 }
154
155 let shouldReportUnusedOptOutDirective = true;
@@ -168,16 +163,17 @@ const rule: Rule.RuleModule = {
163 });
164 const userLogger: Logger | null = options.logger;
165 options.logger = {
171 - logEvent: (filename, event): void => {
172 - userLogger?.logEvent(filename, event);
166 + logEvent: (eventFilename, event): void => {
167 + userLogger?.logEvent(eventFilename, event);
168 if (event.kind === 'CompileError') {
169 shouldReportUnusedOptOutDirective = false;
170 const detail = event.detail;
176 - const suggest = makeSuggestions(detail);
171 + const suggest = makeSuggestions(detail.options);
172 if (__unstable_donotuse_reportAllBailouts && event.fnLoc != null) {
173 + const loc = detail.primaryLocation();
174 const locStr =
179 - detail.loc != null && typeof detail.loc !== 'symbol'
180 - ? ` (@:${detail.loc.start.line}:${detail.loc.start.column})`
175 + loc != null && typeof loc !== 'symbol'
176 + ? ` (@:${loc.start.line}:${loc.start.column})`
177 : '';
178 /**
179 * Report bailouts with a smaller span (just the first line).
@@ -193,10 +189,10 @@ const rule: Rule.RuleModule = {
189 endLoc = {
190 line: event.fnLoc.start.line,
191 // Babel loc line numbers are 1-indexed
196 - column: sourceCode.text.split(
197 - /\r?\n|\r|\n/g,
198 - event.fnLoc.start.line,
199 - )[event.fnLoc.start.line - 1].length,
192 + column:
193 + sourceCode.text.split(/\r?\n|\r|\n/g)[
194 + event.fnLoc.start.line - 1
195 + ]?.length ?? 0,
196 };
197 }
198 const firstLineLoc = {
@@ -204,29 +200,30 @@ const rule: Rule.RuleModule = {
200 end: endLoc,
201 };
202 context.report({
207 - message: `[ReactCompilerBailout] ${detail.reason}${locStr}`,
203 + message: `${detail.printErrorMessage(sourceCode.text)} ${locStr}`,
204 loc: firstLineLoc,
205 suggest,
206 });
207 }
208
213 - if (!isReportableDiagnostic(detail)) {
209 + const loc = detail.primaryLocation();
210 + if (
211 + !isReportableDiagnostic(detail) ||
212 + loc == null ||
213 + typeof loc === 'symbol'
214 + ) {
215 return;
216 }
217 if (
217 - hasFlowSuppression(detail.loc, 'react-rule-hook') ||
218 - hasFlowSuppression(detail.loc, 'react-rule-unsafe-ref')
218 + hasFlowSuppression(loc, 'react-rule-hook') ||
219 + hasFlowSuppression(loc, 'react-rule-unsafe-ref')
220 ) {
221 // If Flow already caught this error, we don't need to report it again.
222 return;
223 }
223 - const loc =
224 - detail.loc == null || typeof detail.loc == 'symbol'
225 - ? event.fnLoc
226 - : detail.loc;
224 if (loc != null) {
225 context.report({
229 - message: detail.reason,
226 + message: detail.printErrorMessage(sourceCode.text),
227 loc,
228 suggest,
229 });
@@ -239,8 +236,8 @@ const rule: Rule.RuleModule = {
236 options.environment = validateEnvironmentConfig(
237 options.environment ?? {},
238 );
242 - } catch (err) {
243 - options.logger?.logEvent('', err);
239 + } catch (err: unknown) {
240 + options.logger?.logEvent('', err as LoggerEvent);
241 }
242
243 function hasFlowSuppression(
compiler/packages/snap/src/runner-worker.ts
-23
@@ -145,29 +145,6 @@ async function compile(
145 console.error(e.stack);
146 }
147 error = e.message.replace(/\u001b[^m]*m/g, '');
148 - const loc = e.details?.[0]?.loc;
149 - if (loc != null) {
150 - try {
151 - error = codeFrameColumns(
152 - input,
153 - {
154 - start: {
155 - line: loc.start.line,
156 - column: loc.start.column + 1,
157 - },
158 - end: {
159 - line: loc.end.line,
160 - column: loc.end.column + 1,
161 - },
162 - },
163 - {
164 - message: e.message,
165 - },
166 - );
167 - } catch {
168 - // In case the location data isn't valid, skip printing a code frame.
169 - }
170 - }
148 }
149
150 // Promote console errors so they can be recorded in fixture output
packages/eslint-plugin-react-hooks/__tests__/ReactCompilerRule-test.ts
+38 -12
@@ -106,8 +106,7 @@ const tests: CompilerTestCases = {
106 }`,
107 errors: [
108 {
109 - message:
110 - '(BuildHIR::lowerStatement) Handle var kinds in VariableDeclaration',
109 + message: /Handle var kinds in VariableDeclaration/,
110 },
111 ],
112 },
@@ -121,8 +120,7 @@ const tests: CompilerTestCases = {
120 }`,
121 errors: [
122 {
124 - message:
125 - 'React Compiler has skipped optimizing this component because one or more React ESLint rules were disabled. React Compiler only works when your components follow all the rules of React, disabling them may result in unexpected or incorrect behavior',
123 + message: /React Compiler has skipped optimizing this component/,
124 suggestions: [
125 {
126 output: normalizeIndent`
@@ -160,12 +158,10 @@ const tests: CompilerTestCases = {
158 }`,
159 errors: [
160 {
163 - message:
164 - '(BuildHIR::lowerStatement) Handle var kinds in VariableDeclaration',
161 + message: /Handle var kinds in VariableDeclaration/,
162 },
163 {
167 - message:
168 - 'Mutating component props or hook arguments is not allowed. Consider using a local variable instead',
164 + message: /Mutating component props or hook arguments is not allowed/,
165 },
166 ],
167 },
@@ -184,8 +180,7 @@ const tests: CompilerTestCases = {
180 }`,
181 errors: [
182 {
187 - message:
188 - '[ReactCompilerBailout] (BuildHIR::lowerStatement) Handle var kinds in VariableDeclaration (@:3:2)',
183 + message: /Handle var kinds in VariableDeclaration/,
184 },
185 ],
186 },
@@ -202,7 +197,7 @@ const tests: CompilerTestCases = {
197 errors: [
198 {
199 message:
205 - 'Unexpected reassignment of a variable which was defined outside of the component. Components and hooks should be pure and side-effect free, but variable reassignment is a form of side-effect. If this variable is used in rendering, use useState instead. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#side-effects-must-run-outside-of-render)',
200 + /Unexpected reassignment of a variable which was defined outside of the component/,
201 },
202 ],
203 },
@@ -248,6 +243,37 @@ const tests: CompilerTestCases = {
243 },
244 ],
245 },
246 + {
247 + name: 'Pipeline errors are reported',
248 + code: normalizeIndent`
249 + import useMyEffect from 'useMyEffect';
250 + function Component({a}) {
251 + 'use no memo';
252 + useMyEffect(() => console.log(a.b));
253 + return <div>Hello world</div>;
254 + }
255 + `,
256 + options: [
257 + {
258 + environment: {
259 + inferEffectDependencies: [
260 + {
261 + function: {
262 + source: 'useMyEffect',
263 + importSpecifierName: 'default',
264 + },
265 + numRequiredArgs: 1,
266 + },
267 + ],
268 + },
269 + },
270 + ],
271 + errors: [
272 + {
273 + message: /Cannot infer dependencies of this effect/,
274 + },
275 + ],
276 + },
277 ],
278 };
279
@@ -259,4 +285,4 @@ const eslintTester = new ESLintTesterV8({
285 enableExperimentalComponentSyntax: true,
286 },
287 });
262 -eslintTester.run('react-compiler - eslint: v8', ReactCompilerRule, tests);
288 +eslintTester.run('react-compiler', ReactCompilerRule, tests);
packages/eslint-plugin-react-hooks/__tests__/ReactCompilerRuleTypescript-test.ts
+2 -3
@@ -63,8 +63,7 @@ const tests: CompilerTestCases = {
63 `,
64 errors: [
65 {
66 - message:
67 - "Mutating a value returned from 'useState()', which should not be mutated. Use the setter function to update instead",
66 + message: /Mutating a value returned from 'useState\(\)'/,
67 line: 7,
68 },
69 ],
@@ -75,4 +74,4 @@ const tests: CompilerTestCases = {
74 const eslintTester = new ESLintTesterV8({
75 parser: require.resolve('@typescript-eslint/parser-v5'),
76 });
78 -eslintTester.run('react-compiler - eslint: v8', ReactCompilerRule, tests);
77 +eslintTester.run('react-compiler', ReactCompilerRule, tests);
packages/eslint-plugin-react-hooks/src/rules/ReactCompiler.ts
+21 -24
@@ -11,7 +11,10 @@ import {transformFromAstSync} from '@babel/core';
11 import PluginProposalPrivateMethods from '@babel/plugin-transform-private-methods';
12 import type {SourceLocation as BabelSourceLocation} from '@babel/types';
13 import BabelPluginReactCompiler, {
14 + type CompilerErrorDetail,
15 type CompilerErrorDetailOptions,
16 + type CompilerDiagnostic,
17 + type CompilerDiagnosticOptions,
18 CompilerSuggestionOperation,
19 ErrorSeverity,
20 parsePluginOptions,
@@ -25,10 +28,6 @@ import type {Rule} from 'eslint';
28 import {Statement} from 'estree';
29 import * as HermesParser from 'hermes-parser';
30
28 -type CompilerErrorDetailWithLoc = Omit<CompilerErrorDetailOptions, 'loc'> & {
29 - loc: BabelSourceLocation;
30 -};
31 -
31 function assertExhaustive(_: never, errorMsg: string): never {
32 throw new Error(errorMsg);
33 }
@@ -40,17 +39,13 @@ const DEFAULT_REPORTABLE_LEVELS = new Set([
39 let reportableLevels = DEFAULT_REPORTABLE_LEVELS;
40
41 function isReportableDiagnostic(
43 - detail: CompilerErrorDetailOptions,
44 -): detail is CompilerErrorDetailWithLoc {
45 - return (
46 - reportableLevels.has(detail.severity) &&
47 - detail.loc != null &&
48 - typeof detail.loc !== 'symbol'
49 - );
42 + detail: CompilerErrorDetail | CompilerDiagnostic,
43 +): boolean {
44 + return reportableLevels.has(detail.severity);
45 }
46
47 function makeSuggestions(
53 - detail: CompilerErrorDetailOptions,
48 + detail: CompilerErrorDetailOptions | CompilerDiagnosticOptions,
49 ): Array<Rule.SuggestionReportDescriptor> {
50 const suggest: Array<Rule.SuggestionReportDescriptor> = [];
51 if (Array.isArray(detail.suggestions)) {
@@ -175,11 +170,12 @@ const rule: Rule.RuleModule = {
170 if (event.kind === 'CompileError') {
171 shouldReportUnusedOptOutDirective = false;
172 const detail = event.detail;
178 - const suggest = makeSuggestions(detail);
173 + const suggest = makeSuggestions(detail.options);
174 if (__unstable_donotuse_reportAllBailouts && event.fnLoc != null) {
175 + const loc = detail.primaryLocation();
176 const locStr =
181 - detail.loc != null && typeof detail.loc !== 'symbol'
182 - ? ` (@:${detail.loc.start.line}:${detail.loc.start.column})`
177 + loc != null && typeof loc !== 'symbol'
178 + ? ` (@:${loc.start.line}:${loc.start.column})`
179 : '';
180 /**
181 * Report bailouts with a smaller span (just the first line).
@@ -206,29 +202,30 @@ const rule: Rule.RuleModule = {
202 end: endLoc,
203 };
204 context.report({
209 - message: `[ReactCompilerBailout] ${detail.reason}${locStr}`,
205 + message: `${detail.printErrorMessage(sourceCode.text)} ${locStr}`,
206 loc: firstLineLoc,
207 suggest,
208 });
209 }
210
215 - if (!isReportableDiagnostic(detail)) {
211 + const loc = detail.primaryLocation();
212 + if (
213 + !isReportableDiagnostic(detail) ||
214 + loc == null ||
215 + typeof loc === 'symbol'
216 + ) {
217 return;
218 }
219 if (
219 - hasFlowSuppression(detail.loc, 'react-rule-hook') ||
220 - hasFlowSuppression(detail.loc, 'react-rule-unsafe-ref')
220 + hasFlowSuppression(loc, 'react-rule-hook') ||
221 + hasFlowSuppression(loc, 'react-rule-unsafe-ref')
222 ) {
223 // If Flow already caught this error, we don't need to report it again.
224 return;
225 }
225 - const loc =
226 - detail.loc == null || typeof detail.loc === 'symbol'
227 - ? event.fnLoc
228 - : detail.loc;
226 if (loc != null) {
227 context.report({
231 - message: detail.reason,
228 + message: detail.printErrorMessage(sourceCode.text),
229 loc,
230 suggest,
231 });