@samitouri / QOS-React-2 / commits / dffacc7b80

InferEffectDeps takes a React.AUTODEPS sigil (#33799)

--- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/facebook/react/pull/33799). * #33800 * __->__ #33799

Jordan Brown committed Jul 17, 2025 at 05:31 UTC dffacc7b8094576c19790fe8341996f743ba4a89
69 files changed +246 -272
compiler/packages/babel-plugin-react-compiler/src/HIR/Globals.ts
+2
@@ -9,6 +9,7 @@ import {Effect, ValueKind, ValueReason} from './HIR';
9 import {
10 BUILTIN_SHAPES,
11 BuiltInArrayId,
12 + BuiltInAutodepsId,
13 BuiltInFireFunctionId,
14 BuiltInFireId,
15 BuiltInMapId,
@@ -780,6 +781,7 @@ const REACT_APIS: Array<[string, BuiltInType]> = [
781 BuiltInUseEffectEventId,
782 ),
783 ],
784 + ['AUTODEPS', addObject(DEFAULT_SHAPES, BuiltInAutodepsId, [])],
785 ];
786
787 TYPED_GLOBALS.push(
compiler/packages/babel-plugin-react-compiler/src/HIR/ObjectShape.ts
+1
@@ -384,6 +384,7 @@ export const BuiltInFireId = 'BuiltInFire';
384 export const BuiltInFireFunctionId = 'BuiltInFireFunction';
385 export const BuiltInUseEffectEventId = 'BuiltInUseEffectEvent';
386 export const BuiltinEffectEventId = 'BuiltInEffectEventFunction';
387 +export const BuiltInAutodepsId = 'BuiltInAutoDepsId';
388
389 // See getReanimatedModuleType() in Globals.ts — this is part of supporting Reanimated's ref-like types
390 export const ReanimatedSharedValueId = 'ReanimatedSharedValueId';
compiler/packages/babel-plugin-react-compiler/src/Inference/InferEffectDependencies.ts
+23 -5
@@ -57,6 +57,8 @@ import {
57 } from '../HIR/visitors';
58 import {empty} from '../Utils/Stack';
59 import {getOrInsertWith} from '../Utils/utils';
60 +import {deadCodeElimination} from '../Optimization';
61 +import {BuiltInAutodepsId} from '../HIR/ObjectShape';
62
63 /**
64 * Infers reactive dependencies captured by useEffect lambdas and adds them as
@@ -135,7 +137,6 @@ export function inferEffectDependencies(fn: HIRFunction): void {
137 }
138 } else if (value.kind === 'LoadGlobal') {
139 loadGlobals.add(lvalue.identifier.id);
138 -
140 /*
141 * TODO: Handle properties on default exports, like
142 * import React from 'react';
@@ -169,8 +170,17 @@ export function inferEffectDependencies(fn: HIRFunction): void {
170 ) {
171 const callee =
172 value.kind === 'CallExpression' ? value.callee : value.property;
173 +
174 + const autodepsArgIndex = value.args.findIndex(
175 + arg =>
176 + arg.kind === 'Identifier' &&
177 + arg.identifier.type.kind === 'Object' &&
178 + arg.identifier.type.shapeId === BuiltInAutodepsId,
179 + );
180 if (
173 - value.args.length === autodepFnLoads.get(callee.identifier.id) &&
181 + value.args.length > 1 &&
182 + autodepsArgIndex > 0 &&
183 + autodepFnLoads.has(callee.identifier.id) &&
184 value.args[0].kind === 'Identifier'
185 ) {
186 // We have a useEffect call with no deps array, so we need to infer the deps
@@ -260,7 +270,10 @@ export function inferEffectDependencies(fn: HIRFunction): void {
270 effects: null,
271 },
272 });
263 - value.args.push({...depsPlace, effect: Effect.Freeze});
273 + value.args[autodepsArgIndex] = {
274 + ...depsPlace,
275 + effect: Effect.Freeze,
276 + };
277 fn.env.inferredEffectLocations.add(callee.loc);
278 } else if (loadGlobals.has(value.args[0].identifier.id)) {
279 // Global functions have no reactive dependencies, so we can insert an empty array
@@ -275,7 +288,10 @@ export function inferEffectDependencies(fn: HIRFunction): void {
288 effects: null,
289 },
290 });
278 - value.args.push({...depsPlace, effect: Effect.Freeze});
291 + value.args[autodepsArgIndex] = {
292 + ...depsPlace,
293 + effect: Effect.Freeze,
294 + };
295 fn.env.inferredEffectLocations.add(callee.loc);
296 }
297 } else if (
@@ -323,6 +339,7 @@ export function inferEffectDependencies(fn: HIRFunction): void {
339 // Renumber instructions and fix scope ranges
340 markInstructionIds(fn.body);
341 fixScopeAndIdentifierRanges(fn.body);
342 + deadCodeElimination(fn);
343
344 fn.env.hasInferredEffect = true;
345 }
@@ -408,6 +425,7 @@ function rewriteSplices(
425 rewriteBlocks.push(currBlock);
426
427 let cursor = 0;
428 +
429 for (const rewrite of splices) {
430 while (originalInstrs[cursor].id < rewrite.location) {
431 CompilerError.invariant(
@@ -429,7 +447,7 @@ function rewriteSplices(
447
448 if (rewrite.kind === 'instr') {
449 currBlock.instructions.push(rewrite.value);
432 - } else {
450 + } else if (rewrite.kind === 'block') {
451 const {entry, blocks} = rewrite.value;
452 const entryBlock = blocks.get(entry)!;
453 // splice in all instructions from the entry block
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/bailout-retry/mutate-after-useeffect-granular-access.expect.md
+3 -3
@@ -3,14 +3,14 @@
3
4 ```javascript
5 // @inferEffectDependencies @panicThreshold:"none"
6 -import {useEffect} from 'react';
6 +import {useEffect, AUTODEPS} from 'react';
7 import {print} from 'shared-runtime';
8
9 function Component({foo}) {
10 const arr = [];
11 // Taking either arr[0].value or arr as a dependency is reasonable
12 // as long as developers know what to expect.
13 - useEffect(() => print(arr[0].value));
13 + useEffect(() => print(arr[0].value), AUTODEPS);
14 arr.push({value: foo});
15 return arr;
16 }
@@ -21,7 +21,7 @@ function Component({foo}) {
21
22 ```javascript
23 // @inferEffectDependencies @panicThreshold:"none"
24 -import { useEffect } from "react";
24 +import { useEffect, AUTODEPS } from "react";
25 import { print } from "shared-runtime";
26
27 function Component(t0) {
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/bailout-retry/mutate-after-useeffect-granular-access.js
+2 -2
@@ -1,12 +1,12 @@
1 // @inferEffectDependencies @panicThreshold:"none"
2 -import {useEffect} from 'react';
2 +import {useEffect, AUTODEPS} from 'react';
3 import {print} from 'shared-runtime';
4
5 function Component({foo}) {
6 const arr = [];
7 // Taking either arr[0].value or arr as a dependency is reasonable
8 // as long as developers know what to expect.
9 - useEffect(() => print(arr[0].value));
9 + useEffect(() => print(arr[0].value), AUTODEPS);
10 arr.push({value: foo});
11 return arr;
12 }
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/bailout-retry/mutate-after-useeffect-optional-chain.expect.md
+6 -6
@@ -3,14 +3,14 @@
3
4 ```javascript
5 // @inferEffectDependencies @panicThreshold:"none" @loggerTestOnly
6 -import {useEffect} from 'react';
6 +import {useEffect, AUTODEPS} from 'react';
7 import {print} from 'shared-runtime';
8
9 function Component({foo}) {
10 const arr = [];
11 // Taking either arr[0].value or arr as a dependency is reasonable
12 // as long as developers know what to expect.
13 - useEffect(() => print(arr[0]?.value));
13 + useEffect(() => print(arr[0]?.value), AUTODEPS);
14 arr.push({value: foo});
15 return arr;
16 }
@@ -26,7 +26,7 @@ export const FIXTURE_ENTRYPOINT = {
26
27 ```javascript
28 // @inferEffectDependencies @panicThreshold:"none" @loggerTestOnly
29 -import { useEffect } from "react";
29 +import { useEffect, AUTODEPS } from "react";
30 import { print } from "shared-runtime";
31
32 function Component(t0) {
@@ -48,9 +48,9 @@ export const FIXTURE_ENTRYPOINT = {
48 ## Logs
49
50 ```
51 -{"kind":"CompileError","fnLoc":{"start":{"line":5,"column":0,"index":139},"end":{"line":12,"column":1,"index":384},"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":345},"end":{"line":10,"column":5,"index":348},"filename":"mutate-after-useeffect-optional-chain.ts","identifierName":"arr"}}}
52 -{"kind":"AutoDepsDecorations","fnLoc":{"start":{"line":9,"column":2,"index":304},"end":{"line":9,"column":39,"index":341},"filename":"mutate-after-useeffect-optional-chain.ts"},"decorations":[{"start":{"line":9,"column":24,"index":326},"end":{"line":9,"column":27,"index":329},"filename":"mutate-after-useeffect-optional-chain.ts","identifierName":"arr"}]}
53 -{"kind":"CompileSuccess","fnLoc":{"start":{"line":5,"column":0,"index":139},"end":{"line":12,"column":1,"index":384},"filename":"mutate-after-useeffect-optional-chain.ts"},"fnName":"Component","memoSlots":0,"memoBlocks":0,"memoValues":0,"prunedMemoBlocks":0,"prunedMemoValues":0}
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"}}}
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 ```
55
56 ### Eval output
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/bailout-retry/mutate-after-useeffect-optional-chain.js
+2 -2
@@ -1,12 +1,12 @@
1 // @inferEffectDependencies @panicThreshold:"none" @loggerTestOnly
2 -import {useEffect} from 'react';
2 +import {useEffect, AUTODEPS} from 'react';
3 import {print} from 'shared-runtime';
4
5 function Component({foo}) {
6 const arr = [];
7 // Taking either arr[0].value or arr as a dependency is reasonable
8 // as long as developers know what to expect.
9 - useEffect(() => print(arr[0]?.value));
9 + useEffect(() => print(arr[0]?.value), AUTODEPS);
10 arr.push({value: foo});
11 return arr;
12 }
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/bailout-retry/mutate-after-useeffect-ref-access.expect.md
+6 -6
@@ -4,12 +4,12 @@
4 ```javascript
5 // @inferEffectDependencies @panicThreshold:"none" @loggerTestOnly
6
7 -import {useEffect, useRef} from 'react';
7 +import {useEffect, useRef, AUTODEPS} from 'react';
8 import {print} from 'shared-runtime';
9
10 function Component({arrRef}) {
11 // Avoid taking arr.current as a dependency
12 - useEffect(() => print(arrRef.current));
12 + useEffect(() => print(arrRef.current), AUTODEPS);
13 arrRef.current.val = 2;
14 return arrRef;
15 }
@@ -26,7 +26,7 @@ export const FIXTURE_ENTRYPOINT = {
26 ```javascript
27 // @inferEffectDependencies @panicThreshold:"none" @loggerTestOnly
28
29 -import { useEffect, useRef } from "react";
29 +import { useEffect, useRef, AUTODEPS } from "react";
30 import { print } from "shared-runtime";
31
32 function Component(t0) {
@@ -47,9 +47,9 @@ export const FIXTURE_ENTRYPOINT = {
47 ## Logs
48
49 ```
50 -{"kind":"CompileError","fnLoc":{"start":{"line":6,"column":0,"index":148},"end":{"line":11,"column":1,"index":311},"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":269},"end":{"line":9,"column":16,"index":283},"filename":"mutate-after-useeffect-ref-access.ts"}}}
51 -{"kind":"AutoDepsDecorations","fnLoc":{"start":{"line":8,"column":2,"index":227},"end":{"line":8,"column":40,"index":265},"filename":"mutate-after-useeffect-ref-access.ts"},"decorations":[{"start":{"line":8,"column":24,"index":249},"end":{"line":8,"column":30,"index":255},"filename":"mutate-after-useeffect-ref-access.ts","identifierName":"arrRef"}]}
52 -{"kind":"CompileSuccess","fnLoc":{"start":{"line":6,"column":0,"index":148},"end":{"line":11,"column":1,"index":311},"filename":"mutate-after-useeffect-ref-access.ts"},"fnName":"Component","memoSlots":0,"memoBlocks":0,"memoValues":0,"prunedMemoBlocks":0,"prunedMemoValues":0}
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"}}}
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 ```
54
55 ### Eval output
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/bailout-retry/mutate-after-useeffect-ref-access.js
+2 -2
@@ -1,11 +1,11 @@
1 // @inferEffectDependencies @panicThreshold:"none" @loggerTestOnly
2
3 -import {useEffect, useRef} from 'react';
3 +import {useEffect, useRef, AUTODEPS} from 'react';
4 import {print} from 'shared-runtime';
5
6 function Component({arrRef}) {
7 // Avoid taking arr.current as a dependency
8 - useEffect(() => print(arrRef.current));
8 + useEffect(() => print(arrRef.current), AUTODEPS);
9 arrRef.current.val = 2;
10 return arrRef;
11 }
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/bailout-retry/mutate-after-useeffect.expect.md
+6 -6
@@ -3,13 +3,13 @@
3
4 ```javascript
5 // @inferEffectDependencies @panicThreshold:"none" @loggerTestOnly
6 -import {useEffect} from 'react';
6 +import {useEffect, AUTODEPS} from 'react';
7
8 function Component({foo}) {
9 const arr = [];
10 useEffect(() => {
11 arr.push(foo);
12 - });
12 + }, AUTODEPS);
13 arr.push(2);
14 return arr;
15 }
@@ -25,7 +25,7 @@ export const FIXTURE_ENTRYPOINT = {
25
26 ```javascript
27 // @inferEffectDependencies @panicThreshold:"none" @loggerTestOnly
28 -import { useEffect } from "react";
28 +import { useEffect, AUTODEPS } from "react";
29
30 function Component(t0) {
31 const { foo } = t0;
@@ -47,9 +47,9 @@ export const FIXTURE_ENTRYPOINT = {
47 ## Logs
48
49 ```
50 -{"kind":"CompileError","fnLoc":{"start":{"line":4,"column":0,"index":101},"end":{"line":11,"column":1,"index":222},"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":194},"end":{"line":9,"column":5,"index":197},"filename":"mutate-after-useeffect.ts","identifierName":"arr"}}}
51 -{"kind":"AutoDepsDecorations","fnLoc":{"start":{"line":6,"column":2,"index":149},"end":{"line":8,"column":4,"index":190},"filename":"mutate-after-useeffect.ts"},"decorations":[{"start":{"line":7,"column":4,"index":171},"end":{"line":7,"column":7,"index":174},"filename":"mutate-after-useeffect.ts","identifierName":"arr"},{"start":{"line":7,"column":4,"index":171},"end":{"line":7,"column":7,"index":174},"filename":"mutate-after-useeffect.ts","identifierName":"arr"},{"start":{"line":7,"column":13,"index":180},"end":{"line":7,"column":16,"index":183},"filename":"mutate-after-useeffect.ts","identifierName":"foo"}]}
52 -{"kind":"CompileSuccess","fnLoc":{"start":{"line":4,"column":0,"index":101},"end":{"line":11,"column":1,"index":222},"filename":"mutate-after-useeffect.ts"},"fnName":"Component","memoSlots":0,"memoBlocks":0,"memoValues":0,"prunedMemoBlocks":0,"prunedMemoValues":0}
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"}}}
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 ```
54
55 ### Eval output
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/bailout-retry/mutate-after-useeffect.js
+2 -2
@@ -1,11 +1,11 @@
1 // @inferEffectDependencies @panicThreshold:"none" @loggerTestOnly
2 -import {useEffect} from 'react';
2 +import {useEffect, AUTODEPS} from 'react';
3
4 function Component({foo}) {
5 const arr = [];
6 useEffect(() => {
7 arr.push(foo);
8 - });
8 + }, AUTODEPS);
9 arr.push(2);
10 return arr;
11 }
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/helper-nonreactive.expect.md
+3 -3
@@ -3,7 +3,7 @@
3
4 ```javascript
5 // @inferEffectDependencies
6 -import {useEffect, useRef} from 'react';
6 +import {useEffect, useRef, AUTODEPS} from 'react';
7 function useCustomRef() {
8 const ref = useRef();
9 return ref;
@@ -12,7 +12,7 @@ function NonReactiveWrapper() {
12 const ref = useCustomRef();
13 useEffect(() => {
14 print(ref);
15 - });
15 + }, AUTODEPS);
16 }
17
18 ```
@@ -21,7 +21,7 @@ function NonReactiveWrapper() {
21
22 ```javascript
23 import { c as _c } from "react/compiler-runtime"; // @inferEffectDependencies
24 -import { useEffect, useRef } from "react";
24 +import { useEffect, useRef, AUTODEPS } from "react";
25 function useCustomRef() {
26 const ref = useRef();
27 return ref;
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/helper-nonreactive.js
+2 -2
@@ -1,5 +1,5 @@
1 // @inferEffectDependencies
2 -import {useEffect, useRef} from 'react';
2 +import {useEffect, useRef, AUTODEPS} from 'react';
3 function useCustomRef() {
4 const ref = useRef();
5 return ref;
@@ -8,5 +8,5 @@ function NonReactiveWrapper() {
8 const ref = useCustomRef();
9 useEffect(() => {
10 print(ref);
11 - });
11 + }, AUTODEPS);
12 }
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/import-namespace-useEffect.expect.md
+2 -2
@@ -8,8 +8,8 @@ import * as SharedRuntime from 'shared-runtime';
8
9 function NonReactiveDepInEffect() {
10 const obj = makeObject_Primitives();
11 - React.useEffect(() => print(obj));
12 - SharedRuntime.useSpecialEffect(() => print(obj), [obj]);
11 + React.useEffect(() => print(obj), React.AUTODEPS);
12 + SharedRuntime.useSpecialEffect(() => print(obj), [obj], React.AUTODEPS);
13 }
14
15 ```
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/import-namespace-useEffect.js
+2 -2
@@ -4,6 +4,6 @@ import * as SharedRuntime from 'shared-runtime';
4
5 function NonReactiveDepInEffect() {
6 const obj = makeObject_Primitives();
7 - React.useEffect(() => print(obj));
8 - SharedRuntime.useSpecialEffect(() => print(obj), [obj]);
7 + React.useEffect(() => print(obj), React.AUTODEPS);
8 + SharedRuntime.useSpecialEffect(() => print(obj), [obj], React.AUTODEPS);
9 }
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/infer-deps-custom-config.expect.md
+3 -1
@@ -4,10 +4,11 @@
4 ```javascript
5 // @inferEffectDependencies
6 import {print, useSpecialEffect} from 'shared-runtime';
7 +import {AUTODEPS} from 'react';
8
9 function CustomConfig({propVal}) {
10 // Insertion
10 - useSpecialEffect(() => print(propVal), [propVal]);
11 + useSpecialEffect(() => print(propVal), [propVal], AUTODEPS);
12 // No insertion
13 useSpecialEffect(() => print(propVal), [propVal], [propVal]);
14 }
@@ -19,6 +20,7 @@ function CustomConfig({propVal}) {
20 ```javascript
21 import { c as _c } from "react/compiler-runtime"; // @inferEffectDependencies
22 import { print, useSpecialEffect } from "shared-runtime";
23 +import { AUTODEPS } from "react";
24
25 function CustomConfig(t0) {
26 const $ = _c(7);
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/infer-deps-custom-config.js
+2 -1
@@ -1,9 +1,10 @@
1 // @inferEffectDependencies
2 import {print, useSpecialEffect} from 'shared-runtime';
3 +import {AUTODEPS} from 'react';
4
5 function CustomConfig({propVal}) {
6 // Insertion
6 - useSpecialEffect(() => print(propVal), [propVal]);
7 + useSpecialEffect(() => print(propVal), [propVal], AUTODEPS);
8 // No insertion
9 useSpecialEffect(() => print(propVal), [propVal], [propVal]);
10 }
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/infer-effect-dependencies.expect.md
+5 -5
@@ -3,7 +3,7 @@
3
4 ```javascript
5 // @inferEffectDependencies
6 -import {useEffect, useRef} from 'react';
6 +import {useEffect, useRef, AUTODEPS} from 'react';
7 import useEffectWrapper from 'useEffectWrapper';
8
9 const moduleNonReactive = 0;
@@ -24,7 +24,7 @@ function Component({foo, bar}) {
24 console.log(ref.current);
25 console.log(localNonPrimitiveReactive);
26 console.log(localNonPrimitiveNonreactive);
27 - });
27 + }, AUTODEPS);
28
29 // Optional chains and property accesses
30 // TODO: we may be able to save bytes by omitting property accesses if the
@@ -32,11 +32,11 @@ function Component({foo, bar}) {
32 useEffect(() => {
33 console.log(bar?.baz);
34 console.log(bar.qux);
35 - });
35 + }, AUTODEPS);
36
37 useEffectWrapper(() => {
38 console.log(foo);
39 - });
39 + }, AUTODEPS);
40 }
41
42 ```
@@ -45,7 +45,7 @@ function Component({foo, bar}) {
45
46 ```javascript
47 import { c as _c } from "react/compiler-runtime"; // @inferEffectDependencies
48 -import { useEffect, useRef } from "react";
48 +import { useEffect, useRef, AUTODEPS } from "react";
49 import useEffectWrapper from "useEffectWrapper";
50
51 const moduleNonReactive = 0;
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/infer-effect-dependencies.js
+4 -4
@@ -1,5 +1,5 @@
1 // @inferEffectDependencies
2 -import {useEffect, useRef} from 'react';
2 +import {useEffect, useRef, AUTODEPS} from 'react';
3 import useEffectWrapper from 'useEffectWrapper';
4
5 const moduleNonReactive = 0;
@@ -20,7 +20,7 @@ function Component({foo, bar}) {
20 console.log(ref.current);
21 console.log(localNonPrimitiveReactive);
22 console.log(localNonPrimitiveNonreactive);
23 - });
23 + }, AUTODEPS);
24
25 // Optional chains and property accesses
26 // TODO: we may be able to save bytes by omitting property accesses if the
@@ -28,9 +28,9 @@ function Component({foo, bar}) {
28 useEffect(() => {
29 console.log(bar?.baz);
30 console.log(bar.qux);
31 - });
31 + }, AUTODEPS);
32
33 useEffectWrapper(() => {
34 console.log(foo);
35 - });
35 + }, AUTODEPS);
36 }
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/no-emit/no-emit-lint-repro.expect.md
+4 -2
@@ -5,10 +5,11 @@
5 // @inferEffectDependencies @noEmit
6 import {print} from 'shared-runtime';
7 import useEffectWrapper from 'useEffectWrapper';
8 +import {AUTODEPS} from 'react';
9
10 function ReactiveVariable({propVal}) {
11 const arr = [propVal];
11 - useEffectWrapper(() => print(arr));
12 + useEffectWrapper(() => print(arr), AUTODEPS);
13 }
14
15 ```
@@ -19,10 +20,11 @@ function ReactiveVariable({propVal}) {
20 // @inferEffectDependencies @noEmit
21 import { print } from "shared-runtime";
22 import useEffectWrapper from "useEffectWrapper";
23 +import { AUTODEPS } from "react";
24
25 function ReactiveVariable({ propVal }) {
26 const arr = [propVal];
25 - useEffectWrapper(() => print(arr));
27 + useEffectWrapper(() => print(arr), AUTODEPS);
28 }
29
30 ```
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/no-emit/no-emit-lint-repro.js
+2 -1
@@ -1,8 +1,9 @@
1 // @inferEffectDependencies @noEmit
2 import {print} from 'shared-runtime';
3 import useEffectWrapper from 'useEffectWrapper';
4 +import {AUTODEPS} from 'react';
5
6 function ReactiveVariable({propVal}) {
7 const arr = [propVal];
7 - useEffectWrapper(() => print(arr));
8 + useEffectWrapper(() => print(arr), AUTODEPS);
9 }
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/no-emit/retry-no-emit.expect.md
+10 -8
@@ -5,13 +5,14 @@
5 // @inferEffectDependencies @noEmit @panicThreshold:"none" @loggerTestOnly
6 import {print} from 'shared-runtime';
7 import useEffectWrapper from 'useEffectWrapper';
8 +import {AUTODEPS} from 'react';
9
10 function Foo({propVal}) {
11 const arr = [propVal];
11 - useEffectWrapper(() => print(arr));
12 + useEffectWrapper(() => print(arr), AUTODEPS);
13
14 const arr2 = [];
14 - useEffectWrapper(() => arr2.push(propVal));
15 + useEffectWrapper(() => arr2.push(propVal), AUTODEPS);
16 arr2.push(2);
17 return {arr, arr2};
18 }
@@ -30,13 +31,14 @@ export const FIXTURE_ENTRYPOINT = {
31 // @inferEffectDependencies @noEmit @panicThreshold:"none" @loggerTestOnly
32 import { print } from "shared-runtime";
33 import useEffectWrapper from "useEffectWrapper";
34 +import { AUTODEPS } from "react";
35
36 function Foo({ propVal }) {
37 const arr = [propVal];
36 - useEffectWrapper(() => print(arr));
38 + useEffectWrapper(() => print(arr), AUTODEPS);
39
40 const arr2 = [];
39 - useEffectWrapper(() => arr2.push(propVal));
41 + useEffectWrapper(() => arr2.push(propVal), AUTODEPS);
42 arr2.push(2);
43 return { arr, arr2 };
44 }
@@ -52,10 +54,10 @@ export const FIXTURE_ENTRYPOINT = {
54 ## Logs
55
56 ```
55 -{"kind":"CompileError","fnLoc":{"start":{"line":5,"column":0,"index":163},"end":{"line":13,"column":1,"index":357},"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":11,"column":2,"index":320},"end":{"line":11,"column":6,"index":324},"filename":"retry-no-emit.ts","identifierName":"arr2"}}}
56 -{"kind":"AutoDepsDecorations","fnLoc":{"start":{"line":7,"column":2,"index":216},"end":{"line":7,"column":36,"index":250},"filename":"retry-no-emit.ts"},"decorations":[{"start":{"line":7,"column":31,"index":245},"end":{"line":7,"column":34,"index":248},"filename":"retry-no-emit.ts","identifierName":"arr"}]}
57 -{"kind":"AutoDepsDecorations","fnLoc":{"start":{"line":10,"column":2,"index":274},"end":{"line":10,"column":44,"index":316},"filename":"retry-no-emit.ts"},"decorations":[{"start":{"line":10,"column":25,"index":297},"end":{"line":10,"column":29,"index":301},"filename":"retry-no-emit.ts","identifierName":"arr2"},{"start":{"line":10,"column":25,"index":297},"end":{"line":10,"column":29,"index":301},"filename":"retry-no-emit.ts","identifierName":"arr2"},{"start":{"line":10,"column":35,"index":307},"end":{"line":10,"column":42,"index":314},"filename":"retry-no-emit.ts","identifierName":"propVal"}]}
58 -{"kind":"CompileSuccess","fnLoc":{"start":{"line":5,"column":0,"index":163},"end":{"line":13,"column":1,"index":357},"filename":"retry-no-emit.ts"},"fnName":"Foo","memoSlots":0,"memoBlocks":0,"memoValues":0,"prunedMemoBlocks":0,"prunedMemoValues":0}
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"}}}
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}
61 ```
62
63 ### Eval output
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/no-emit/retry-no-emit.js
+3 -2
@@ -1,13 +1,14 @@
1 // @inferEffectDependencies @noEmit @panicThreshold:"none" @loggerTestOnly
2 import {print} from 'shared-runtime';
3 import useEffectWrapper from 'useEffectWrapper';
4 +import {AUTODEPS} from 'react';
5
6 function Foo({propVal}) {
7 const arr = [propVal];
7 - useEffectWrapper(() => print(arr));
8 + useEffectWrapper(() => print(arr), AUTODEPS);
9
10 const arr2 = [];
10 - useEffectWrapper(() => arr2.push(propVal));
11 + useEffectWrapper(() => arr2.push(propVal), AUTODEPS);
12 arr2.push(2);
13 return {arr, arr2};
14 }
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/no-emit/retry-opt-in--no-emit.expect.md
+6 -4
@@ -4,15 +4,16 @@
4 ```javascript
5 // @compilationMode:"all" @inferEffectDependencies @panicThreshold:"none" @noEmit
6 import {print} from 'shared-runtime';
7 +import {AUTODEPS} from 'react';
8 import useEffectWrapper from 'useEffectWrapper';
9
10 function Foo({propVal}) {
11 'use memo';
12 const arr = [propVal];
12 - useEffectWrapper(() => print(arr));
13 + useEffectWrapper(() => print(arr), AUTODEPS);
14
15 const arr2 = [];
15 - useEffectWrapper(() => arr2.push(propVal));
16 + useEffectWrapper(() => arr2.push(propVal), AUTODEPS);
17 arr2.push(2);
18
19 return {arr, arr2};
@@ -31,15 +32,16 @@ export const FIXTURE_ENTRYPOINT = {
32 ```javascript
33 // @compilationMode:"all" @inferEffectDependencies @panicThreshold:"none" @noEmit
34 import { print } from "shared-runtime";
35 +import { AUTODEPS } from "react";
36 import useEffectWrapper from "useEffectWrapper";
37
38 function Foo({ propVal }) {
39 "use memo";
40 const arr = [propVal];
39 - useEffectWrapper(() => print(arr));
41 + useEffectWrapper(() => print(arr), AUTODEPS);
42
43 const arr2 = [];
42 - useEffectWrapper(() => arr2.push(propVal));
44 + useEffectWrapper(() => arr2.push(propVal), AUTODEPS);
45 arr2.push(2);
46
47 return { arr, arr2 };
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/no-emit/retry-opt-in--no-emit.js
+3 -2
@@ -1,14 +1,15 @@
1 // @compilationMode:"all" @inferEffectDependencies @panicThreshold:"none" @noEmit
2 import {print} from 'shared-runtime';
3 +import {AUTODEPS} from 'react';
4 import useEffectWrapper from 'useEffectWrapper';
5
6 function Foo({propVal}) {
7 'use memo';
8 const arr = [propVal];
8 - useEffectWrapper(() => print(arr));
9 + useEffectWrapper(() => print(arr), AUTODEPS);
10
11 const arr2 = [];
11 - useEffectWrapper(() => arr2.push(propVal));
12 + useEffectWrapper(() => arr2.push(propVal), AUTODEPS);
13 arr2.push(2);
14
15 return {arr, arr2};
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/nonreactive-dep.expect.md
+3 -3
@@ -3,7 +3,7 @@
3
4 ```javascript
5 // @inferEffectDependencies
6 -import {useEffect} from 'react';
6 +import {useEffect, AUTODEPS} from 'react';
7 import {makeObject_Primitives, print} from 'shared-runtime';
8
9 /**
@@ -25,7 +25,7 @@ import {makeObject_Primitives, print} from 'shared-runtime';
25 */
26 function NonReactiveDepInEffect() {
27 const obj = makeObject_Primitives();
28 - useEffect(() => print(obj));
28 + useEffect(() => print(obj), AUTODEPS);
29 }
30
31 ```
@@ -34,7 +34,7 @@ function NonReactiveDepInEffect() {
34
35 ```javascript
36 import { c as _c } from "react/compiler-runtime"; // @inferEffectDependencies
37 -import { useEffect } from "react";
37 +import { useEffect, AUTODEPS } from "react";
38 import { makeObject_Primitives, print } from "shared-runtime";
39
40 /**
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/nonreactive-dep.js
+2 -2
@@ -1,5 +1,5 @@
1 // @inferEffectDependencies
2 -import {useEffect} from 'react';
2 +import {useEffect, AUTODEPS} from 'react';
3 import {makeObject_Primitives, print} from 'shared-runtime';
4
5 /**
@@ -21,5 +21,5 @@ import {makeObject_Primitives, print} from 'shared-runtime';
21 */
22 function NonReactiveDepInEffect() {
23 const obj = makeObject_Primitives();
24 - useEffect(() => print(obj));
24 + useEffect(() => print(obj), AUTODEPS);
25 }
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/nonreactive-effect-event.expect.md
+3 -3
@@ -3,7 +3,7 @@
3
4 ```javascript
5 // @inferEffectDependencies
6 -import {useEffect, useEffectEvent} from 'react';
6 +import {useEffect, useEffectEvent, AUTODEPS} from 'react';
7 import {print} from 'shared-runtime';
8
9 /**
@@ -11,7 +11,7 @@ import {print} from 'shared-runtime';
11 */
12 function NonReactiveEffectEvent() {
13 const fn = useEffectEvent(() => print('hello world'));
14 - useEffect(() => fn());
14 + useEffect(() => fn(), AUTODEPS);
15 }
16
17 ```
@@ -20,7 +20,7 @@ function NonReactiveEffectEvent() {
20
21 ```javascript
22 import { c as _c } from "react/compiler-runtime"; // @inferEffectDependencies
23 -import { useEffect, useEffectEvent } from "react";
23 +import { useEffect, useEffectEvent, AUTODEPS } from "react";
24 import { print } from "shared-runtime";
25
26 /**
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/nonreactive-effect-event.js
+2 -2
@@ -1,5 +1,5 @@
1 // @inferEffectDependencies
2 -import {useEffect, useEffectEvent} from 'react';
2 +import {useEffect, useEffectEvent, AUTODEPS} from 'react';
3 import {print} from 'shared-runtime';
4
5 /**
@@ -7,5 +7,5 @@ import {print} from 'shared-runtime';
7 */
8 function NonReactiveEffectEvent() {
9 const fn = useEffectEvent(() => print('hello world'));
10 - useEffect(() => fn());
10 + useEffect(() => fn(), AUTODEPS);
11 }
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/nonreactive-ref-helper.expect.md
+3 -3
@@ -3,7 +3,7 @@
3
4 ```javascript
5 // @inferEffectDependencies
6 -import {useEffect} from 'react';
6 +import {useEffect, AUTODEPS} from 'react';
7 import {print} from 'shared-runtime';
8
9 /**
@@ -19,7 +19,7 @@ function RefsInEffects() {
19 useEffect(() => {
20 print(ref.current);
21 print(wrapped.foo.current);
22 - });
22 + }, AUTODEPS);
23 }
24
25 function useRefHelper() {
@@ -36,7 +36,7 @@ function useDeeperRefHelper() {
36
37 ```javascript
38 import { c as _c } from "react/compiler-runtime"; // @inferEffectDependencies
39 -import { useEffect } from "react";
39 +import { useEffect, AUTODEPS } from "react";
40 import { print } from "shared-runtime";
41
42 /**
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/nonreactive-ref-helper.js
+2 -2
@@ -1,5 +1,5 @@
1 // @inferEffectDependencies
2 -import {useEffect} from 'react';
2 +import {useEffect, AUTODEPS} from 'react';
3 import {print} from 'shared-runtime';
4
5 /**
@@ -15,7 +15,7 @@ function RefsInEffects() {
15 useEffect(() => {
16 print(ref.current);
17 print(wrapped.foo.current);
18 - });
18 + }, AUTODEPS);
19 }
20
21 function useRefHelper() {
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/nonreactive-ref.expect.md
+3 -3
@@ -3,7 +3,7 @@
3
4 ```javascript
5 // @inferEffectDependencies
6 -import {useEffect, useRef} from 'react';
6 +import {useEffect, useRef, AUTODEPS} from 'react';
7 import {print} from 'shared-runtime';
8
9 /**
@@ -14,7 +14,7 @@ import {print} from 'shared-runtime';
14 */
15 function NonReactiveRefInEffect() {
16 const ref = useRef('initial value');
17 - useEffect(() => print(ref.current));
17 + useEffect(() => print(ref.current), AUTODEPS);
18 }
19
20 ```
@@ -23,7 +23,7 @@ function NonReactiveRefInEffect() {
23
24 ```javascript
25 import { c as _c } from "react/compiler-runtime"; // @inferEffectDependencies
26 -import { useEffect, useRef } from "react";
26 +import { useEffect, useRef, AUTODEPS } from "react";
27 import { print } from "shared-runtime";
28
29 /**
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/nonreactive-ref.js
+2 -2
@@ -1,5 +1,5 @@
1 // @inferEffectDependencies
2 -import {useEffect, useRef} from 'react';
2 +import {useEffect, useRef, AUTODEPS} from 'react';
3 import {print} from 'shared-runtime';
4
5 /**
@@ -10,5 +10,5 @@ import {print} from 'shared-runtime';
10 */
11 function NonReactiveRefInEffect() {
12 const ref = useRef('initial value');
13 - useEffect(() => print(ref.current));
13 + useEffect(() => print(ref.current), AUTODEPS);
14 }
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/nonreactive-setState.expect.md
+3 -3
@@ -3,7 +3,7 @@
3
4 ```javascript
5 // @inferEffectDependencies
6 -import {useEffect, useState} from 'react';
6 +import {useEffect, useState, AUTODEPS} from 'react';
7 import {print} from 'shared-runtime';
8
9 /**
@@ -14,7 +14,7 @@ import {print} from 'shared-runtime';
14 */
15 function NonReactiveSetStateInEffect() {
16 const [_, setState] = useState('initial value');
17 - useEffect(() => print(setState));
17 + useEffect(() => print(setState), AUTODEPS);
18 }
19
20 ```
@@ -23,7 +23,7 @@ function NonReactiveSetStateInEffect() {
23
24 ```javascript
25 import { c as _c } from "react/compiler-runtime"; // @inferEffectDependencies
26 -import { useEffect, useState } from "react";
26 +import { useEffect, useState, AUTODEPS } from "react";
27 import { print } from "shared-runtime";
28
29 /**
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/nonreactive-setState.js
+2 -2
@@ -1,5 +1,5 @@
1 // @inferEffectDependencies
2 -import {useEffect, useState} from 'react';
2 +import {useEffect, useState, AUTODEPS} from 'react';
3 import {print} from 'shared-runtime';
4
5 /**
@@ -10,5 +10,5 @@ import {print} from 'shared-runtime';
10 */
11 function NonReactiveSetStateInEffect() {
12 const [_, setState] = useState('initial value');
13 - useEffect(() => print(setState));
13 + useEffect(() => print(setState), AUTODEPS);
14 }
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/outlined-function.expect.md
+3 -3
@@ -3,7 +3,7 @@
3
4 ```javascript
5 // @inferEffectDependencies
6 -import {useEffect} from 'react';
6 +import {useEffect, AUTODEPS} from 'react';
7 import {print} from 'shared-runtime';
8 /**
9 * This compiled output is technically incorrect but this is currently the same
@@ -14,7 +14,7 @@ import {print} from 'shared-runtime';
14 * before OutlineFunctions
15 */
16 function OutlinedFunctionInEffect() {
17 - useEffect(() => print('hello world!'));
17 + useEffect(() => print('hello world!'), AUTODEPS);
18 }
19
20 ```
@@ -23,7 +23,7 @@ function OutlinedFunctionInEffect() {
23
24 ```javascript
25 // @inferEffectDependencies
26 -import { useEffect } from "react";
26 +import { useEffect, AUTODEPS } from "react";
27 import { print } from "shared-runtime";
28 /**
29 * This compiled output is technically incorrect but this is currently the same
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/outlined-function.js
+2 -2
@@ -1,5 +1,5 @@
1 // @inferEffectDependencies
2 -import {useEffect} from 'react';
2 +import {useEffect, AUTODEPS} from 'react';
3 import {print} from 'shared-runtime';
4 /**
5 * This compiled output is technically incorrect but this is currently the same
@@ -10,5 +10,5 @@ import {print} from 'shared-runtime';
10 * before OutlineFunctions
11 */
12 function OutlinedFunctionInEffect() {
13 - useEffect(() => print('hello world!'));
13 + useEffect(() => print('hello world!'), AUTODEPS);
14 }
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/pruned-nonreactive-obj.expect.md
+3 -3
@@ -4,7 +4,7 @@
4 ```javascript
5 // @inferEffectDependencies
6 import {useIdentity, mutate, makeObject} from 'shared-runtime';
7 -import {useEffect} from 'react';
7 +import {useEffect, AUTODEPS} from 'react';
8
9 /**
10 * When a semantically non-reactive value has a pruned scope (i.e. the object
@@ -48,7 +48,7 @@ function PrunedNonReactive() {
48 useIdentity(null);
49 mutate(obj);
50
51 - useEffect(() => print(obj.value));
51 + useEffect(() => print(obj.value), AUTODEPS);
52 }
53
54 ```
@@ -58,7 +58,7 @@ function PrunedNonReactive() {
58 ```javascript
59 import { c as _c } from "react/compiler-runtime"; // @inferEffectDependencies
60 import { useIdentity, mutate, makeObject } from "shared-runtime";
61 -import { useEffect } from "react";
61 +import { useEffect, AUTODEPS } from "react";
62
63 /**
64 * When a semantically non-reactive value has a pruned scope (i.e. the object
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/pruned-nonreactive-obj.js
+2 -2
@@ -1,6 +1,6 @@
1 // @inferEffectDependencies
2 import {useIdentity, mutate, makeObject} from 'shared-runtime';
3 -import {useEffect} from 'react';
3 +import {useEffect, AUTODEPS} from 'react';
4
5 /**
6 * When a semantically non-reactive value has a pruned scope (i.e. the object
@@ -44,5 +44,5 @@ function PrunedNonReactive() {
44 useIdentity(null);
45 mutate(obj);
46
47 - useEffect(() => print(obj.value));
47 + useEffect(() => print(obj.value), AUTODEPS);
48 }
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/reactive-memberexpr-merge.expect.md
+3 -3
@@ -3,12 +3,12 @@
3
4 ```javascript
5 // @inferEffectDependencies
6 -import {useEffect} from 'react';
6 +import {useEffect, AUTODEPS} from 'react';
7 import {print} from 'shared-runtime';
8
9 function ReactiveMemberExprMerge({propVal}) {
10 const obj = {a: {b: propVal}};
11 - useEffect(() => print(obj.a, obj.a.b));
11 + useEffect(() => print(obj.a, obj.a.b), AUTODEPS);
12 }
13
14 ```
@@ -17,7 +17,7 @@ function ReactiveMemberExprMerge({propVal}) {
17
18 ```javascript
19 import { c as _c } from "react/compiler-runtime"; // @inferEffectDependencies
20 -import { useEffect } from "react";
20 +import { useEffect, AUTODEPS } from "react";
21 import { print } from "shared-runtime";
22
23 function ReactiveMemberExprMerge(t0) {
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/reactive-memberexpr-merge.js
+2 -2
@@ -1,8 +1,8 @@
1 // @inferEffectDependencies
2 -import {useEffect} from 'react';
2 +import {useEffect, AUTODEPS} from 'react';
3 import {print} from 'shared-runtime';
4
5 function ReactiveMemberExprMerge({propVal}) {
6 const obj = {a: {b: propVal}};
7 - useEffect(() => print(obj.a, obj.a.b));
7 + useEffect(() => print(obj.a, obj.a.b), AUTODEPS);
8 }
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/reactive-memberexpr.expect.md
+3 -3
@@ -3,12 +3,12 @@
3
4 ```javascript
5 // @inferEffectDependencies
6 -import {useEffect} from 'react';
6 +import {useEffect, AUTODEPS} from 'react';
7 import {print} from 'shared-runtime';
8
9 function ReactiveMemberExpr({propVal}) {
10 const obj = {a: {b: propVal}};
11 - useEffect(() => print(obj.a.b));
11 + useEffect(() => print(obj.a.b), AUTODEPS);
12 }
13
14 ```
@@ -17,7 +17,7 @@ function ReactiveMemberExpr({propVal}) {
17
18 ```javascript
19 import { c as _c } from "react/compiler-runtime"; // @inferEffectDependencies
20 -import { useEffect } from "react";
20 +import { useEffect, AUTODEPS } from "react";
21 import { print } from "shared-runtime";
22
23 function ReactiveMemberExpr(t0) {
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/reactive-memberexpr.js
+2 -2
@@ -1,8 +1,8 @@
1 // @inferEffectDependencies
2 -import {useEffect} from 'react';
2 +import {useEffect, AUTODEPS} from 'react';
3 import {print} from 'shared-runtime';
4
5 function ReactiveMemberExpr({propVal}) {
6 const obj = {a: {b: propVal}};
7 - useEffect(() => print(obj.a.b));
7 + useEffect(() => print(obj.a.b), AUTODEPS);
8 }
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/reactive-optional-chain-complex.expect.md
+5 -4
@@ -3,15 +3,16 @@
3
4 ```javascript
5 // @inferEffectDependencies
6 -import {useEffect} from 'react';
6 +import {useEffect, AUTODEPS} from 'react';
7 import {print, shallowCopy} from 'shared-runtime';
8
9 function ReactiveMemberExpr({cond, propVal}) {
10 const obj = {a: cond ? {b: propVal} : null, c: null};
11 const other = shallowCopy({a: {b: {c: {d: {e: {f: propVal + 1}}}}}});
12 const primitive = shallowCopy(propVal);
13 - useEffect(() =>
14 - print(obj.a?.b, other?.a?.b?.c?.d?.e.f, primitive.a?.b.c?.d?.e.f)
13 + useEffect(
14 + () => print(obj.a?.b, other?.a?.b?.c?.d?.e.f, primitive.a?.b.c?.d?.e.f),
15 + AUTODEPS
16 );
17 }
18
@@ -26,7 +27,7 @@ export const FIXTURE_ENTRYPOINT = {
27
28 ```javascript
29 import { c as _c } from "react/compiler-runtime"; // @inferEffectDependencies
29 -import { useEffect } from "react";
30 +import { useEffect, AUTODEPS } from "react";
31 import { print, shallowCopy } from "shared-runtime";
32
33 function ReactiveMemberExpr(t0) {
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/reactive-optional-chain-complex.js
+4 -3
@@ -1,13 +1,14 @@
1 // @inferEffectDependencies
2 -import {useEffect} from 'react';
2 +import {useEffect, AUTODEPS} from 'react';
3 import {print, shallowCopy} from 'shared-runtime';
4
5 function ReactiveMemberExpr({cond, propVal}) {
6 const obj = {a: cond ? {b: propVal} : null, c: null};
7 const other = shallowCopy({a: {b: {c: {d: {e: {f: propVal + 1}}}}}});
8 const primitive = shallowCopy(propVal);
9 - useEffect(() =>
10 - print(obj.a?.b, other?.a?.b?.c?.d?.e.f, primitive.a?.b.c?.d?.e.f)
9 + useEffect(
10 + () => print(obj.a?.b, other?.a?.b?.c?.d?.e.f, primitive.a?.b.c?.d?.e.f),
11 + AUTODEPS
12 );
13 }
14
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/reactive-optional-chain.expect.md
+4 -4
@@ -3,13 +3,13 @@
3
4 ```javascript
5 // @inferEffectDependencies
6 -import {useEffect} from 'react';
6 +import {useEffect, AUTODEPS} from 'react';
7 import {print} from 'shared-runtime';
8
9 function ReactiveMemberExpr({cond, propVal}) {
10 const obj = {a: cond ? {b: propVal} : null, c: null};
11 - useEffect(() => print(obj.a?.b));
12 - useEffect(() => print(obj.c?.d));
11 + useEffect(() => print(obj.a?.b), AUTODEPS);
12 + useEffect(() => print(obj.c?.d), AUTODEPS);
13 }
14
15 export const FIXTURE_ENTRYPOINT = {
@@ -23,7 +23,7 @@ export const FIXTURE_ENTRYPOINT = {
23
24 ```javascript
25 import { c as _c } from "react/compiler-runtime"; // @inferEffectDependencies
26 -import { useEffect } from "react";
26 +import { useEffect, AUTODEPS } from "react";
27 import { print } from "shared-runtime";
28
29 function ReactiveMemberExpr(t0) {
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/reactive-optional-chain.js
+3 -3
@@ -1,11 +1,11 @@
1 // @inferEffectDependencies
2 -import {useEffect} from 'react';
2 +import {useEffect, AUTODEPS} from 'react';
3 import {print} from 'shared-runtime';
4
5 function ReactiveMemberExpr({cond, propVal}) {
6 const obj = {a: cond ? {b: propVal} : null, c: null};
7 - useEffect(() => print(obj.a?.b));
8 - useEffect(() => print(obj.c?.d));
7 + useEffect(() => print(obj.a?.b), AUTODEPS);
8 + useEffect(() => print(obj.c?.d), AUTODEPS);
9 }
10
11 export const FIXTURE_ENTRYPOINT = {
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/reactive-ref-ternary.expect.md
+3 -3
@@ -3,7 +3,7 @@
3
4 ```javascript
5 // @inferEffectDependencies
6 -import {useRef, useEffect} from 'react';
6 +import {useRef, useEffect, AUTODEPS} from 'react';
7 import {print, mutate} from 'shared-runtime';
8
9 function Component({cond}) {
@@ -14,7 +14,7 @@ function Component({cond}) {
14 useEffect(() => {
15 mutate(derived.current);
16 print(derived.current);
17 - });
17 + }, AUTODEPS);
18 return arr;
19 }
20
@@ -24,7 +24,7 @@ function Component({cond}) {
24
25 ```javascript
26 import { c as _c } from "react/compiler-runtime"; // @inferEffectDependencies
27 -import { useRef, useEffect } from "react";
27 +import { useRef, useEffect, AUTODEPS } from "react";
28 import { print, mutate } from "shared-runtime";
29
30 function Component(t0) {
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/reactive-ref-ternary.js
+2 -2
@@ -1,5 +1,5 @@
1 // @inferEffectDependencies
2 -import {useRef, useEffect} from 'react';
2 +import {useRef, useEffect, AUTODEPS} from 'react';
3 import {print, mutate} from 'shared-runtime';
4
5 function Component({cond}) {
@@ -10,6 +10,6 @@ function Component({cond}) {
10 useEffect(() => {
11 mutate(derived.current);
12 print(derived.current);
13 - });
13 + }, AUTODEPS);
14 return arr;
15 }
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/reactive-ref.expect.md
+3 -3
@@ -3,7 +3,7 @@
3
4 ```javascript
5 // @inferEffectDependencies
6 -import {useEffect, useRef} from 'react';
6 +import {useEffect, useRef, AUTODEPS} from 'react';
7 import {print} from 'shared-runtime';
8
9 /*
@@ -18,7 +18,7 @@ function ReactiveRefInEffect(props) {
18 } else {
19 ref = ref2;
20 }
21 - useEffect(() => print(ref));
21 + useEffect(() => print(ref), AUTODEPS);
22 }
23
24 ```
@@ -27,7 +27,7 @@ function ReactiveRefInEffect(props) {
27
28 ```javascript
29 import { c as _c } from "react/compiler-runtime"; // @inferEffectDependencies
30 -import { useEffect, useRef } from "react";
30 +import { useEffect, useRef, AUTODEPS } from "react";
31 import { print } from "shared-runtime";
32
33 /*
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/reactive-ref.js
+2 -2
@@ -1,5 +1,5 @@
1 // @inferEffectDependencies
2 -import {useEffect, useRef} from 'react';
2 +import {useEffect, useRef, AUTODEPS} from 'react';
3 import {print} from 'shared-runtime';
4
5 /*
@@ -14,5 +14,5 @@ function ReactiveRefInEffect(props) {
14 } else {
15 ref = ref2;
16 }
17 - useEffect(() => print(ref));
17 + useEffect(() => print(ref), AUTODEPS);
18 }
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/reactive-setState.expect.md
+3 -3
@@ -3,7 +3,7 @@
3
4 ```javascript
5 // @inferEffectDependencies
6 -import {useEffect, useState} from 'react';
6 +import {useEffect, useState, AUTODEPS} from 'react';
7 import {print} from 'shared-runtime';
8
9 /*
@@ -18,7 +18,7 @@ function ReactiveRefInEffect(props) {
18 } else {
19 setState = setState2;
20 }
21 - useEffect(() => print(setState));
21 + useEffect(() => print(setState), AUTODEPS);
22 }
23
24 ```
@@ -27,7 +27,7 @@ function ReactiveRefInEffect(props) {
27
28 ```javascript
29 import { c as _c } from "react/compiler-runtime"; // @inferEffectDependencies
30 -import { useEffect, useState } from "react";
30 +import { useEffect, useState, AUTODEPS } from "react";
31 import { print } from "shared-runtime";
32
33 /*
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/reactive-setState.js
+2 -2
@@ -1,5 +1,5 @@
1 // @inferEffectDependencies
2 -import {useEffect, useState} from 'react';
2 +import {useEffect, useState, AUTODEPS} from 'react';
3 import {print} from 'shared-runtime';
4
5 /*
@@ -14,5 +14,5 @@ function ReactiveRefInEffect(props) {
14 } else {
15 setState = setState2;
16 }
17 - useEffect(() => print(setState));
17 + useEffect(() => print(setState), AUTODEPS);
18 }
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/reactive-variable.expect.md
+3 -3
@@ -3,12 +3,12 @@
3
4 ```javascript
5 // @inferEffectDependencies
6 -import {useEffect} from 'react';
6 +import {useEffect, AUTODEPS} from 'react';
7 import {print} from 'shared-runtime';
8
9 function ReactiveVariable({propVal}) {
10 const arr = [propVal];
11 - useEffect(() => print(arr));
11 + useEffect(() => print(arr), AUTODEPS);
12 }
13
14 ```
@@ -17,7 +17,7 @@ function ReactiveVariable({propVal}) {
17
18 ```javascript
19 import { c as _c } from "react/compiler-runtime"; // @inferEffectDependencies
20 -import { useEffect } from "react";
20 +import { useEffect, AUTODEPS } from "react";
21 import { print } from "shared-runtime";
22
23 function ReactiveVariable(t0) {
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/infer-effect-dependencies/reactive-variable.js
+2 -2
@@ -1,8 +1,8 @@
1 // @inferEffectDependencies
2 -import {useEffect} from 'react';
2 +import {useEffect, AUTODEPS} from 'react';
3 import {print} from 'shared-runtime';
4
5 function ReactiveVariable({propVal}) {
6 const arr = [propVal];
7 - useEffect(() => print(arr));
7 + useEffect(() => print(arr), AUTODEPS);
8 }
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/mutate-after-useeffect-optional-chain.expect.md
+6 -6
@@ -3,14 +3,14 @@
3
4 ```javascript
5 // @inferEffectDependencies @panicThreshold:"none" @loggerTestOnly @enableNewMutationAliasingModel
6 -import {useEffect} from 'react';
6 +import {useEffect, AUTODEPS} from 'react';
7 import {print} from 'shared-runtime';
8
9 function Component({foo}) {
10 const arr = [];
11 // Taking either arr[0].value or arr as a dependency is reasonable
12 // as long as developers know what to expect.
13 - useEffect(() => print(arr[0]?.value));
13 + useEffect(() => print(arr[0]?.value), AUTODEPS);
14 arr.push({value: foo});
15 return arr;
16 }
@@ -26,7 +26,7 @@ export const FIXTURE_ENTRYPOINT = {
26
27 ```javascript
28 // @inferEffectDependencies @panicThreshold:"none" @loggerTestOnly @enableNewMutationAliasingModel
29 -import { useEffect } from "react";
29 +import { useEffect, AUTODEPS } from "react";
30 import { print } from "shared-runtime";
31
32 function Component(t0) {
@@ -48,9 +48,9 @@ export const FIXTURE_ENTRYPOINT = {
48 ## Logs
49
50 ```
51 -{"kind":"CompileError","fnLoc":{"start":{"line":5,"column":0,"index":171},"end":{"line":12,"column":1,"index":416},"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":377},"end":{"line":10,"column":5,"index":380},"filename":"mutate-after-useeffect-optional-chain.ts","identifierName":"arr"}}}
52 -{"kind":"AutoDepsDecorations","fnLoc":{"start":{"line":9,"column":2,"index":336},"end":{"line":9,"column":39,"index":373},"filename":"mutate-after-useeffect-optional-chain.ts"},"decorations":[{"start":{"line":9,"column":24,"index":358},"end":{"line":9,"column":27,"index":361},"filename":"mutate-after-useeffect-optional-chain.ts","identifierName":"arr"}]}
53 -{"kind":"CompileSuccess","fnLoc":{"start":{"line":5,"column":0,"index":171},"end":{"line":12,"column":1,"index":416},"filename":"mutate-after-useeffect-optional-chain.ts"},"fnName":"Component","memoSlots":0,"memoBlocks":0,"memoValues":0,"prunedMemoBlocks":0,"prunedMemoValues":0}
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"}}}
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 ```
55
56 ### Eval output
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/mutate-after-useeffect-optional-chain.js
+2 -2
@@ -1,12 +1,12 @@
1 // @inferEffectDependencies @panicThreshold:"none" @loggerTestOnly @enableNewMutationAliasingModel
2 -import {useEffect} from 'react';
2 +import {useEffect, AUTODEPS} from 'react';
3 import {print} from 'shared-runtime';
4
5 function Component({foo}) {
6 const arr = [];
7 // Taking either arr[0].value or arr as a dependency is reasonable
8 // as long as developers know what to expect.
9 - useEffect(() => print(arr[0]?.value));
9 + useEffect(() => print(arr[0]?.value), AUTODEPS);
10 arr.push({value: foo});
11 return arr;
12 }
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/mutate-after-useeffect-ref-access.expect.md
+6 -6
@@ -4,12 +4,12 @@
4 ```javascript
5 // @inferEffectDependencies @panicThreshold:"none" @loggerTestOnly @enableNewMutationAliasingModel
6
7 -import {useEffect, useRef} from 'react';
7 +import {useEffect, useRef, AUTODEPS} from 'react';
8 import {print} from 'shared-runtime';
9
10 function Component({arrRef}) {
11 // Avoid taking arr.current as a dependency
12 - useEffect(() => print(arrRef.current));
12 + useEffect(() => print(arrRef.current), AUTODEPS);
13 arrRef.current.val = 2;
14 return arrRef;
15 }
@@ -26,7 +26,7 @@ export const FIXTURE_ENTRYPOINT = {
26 ```javascript
27 // @inferEffectDependencies @panicThreshold:"none" @loggerTestOnly @enableNewMutationAliasingModel
28
29 -import { useEffect, useRef } from "react";
29 +import { useEffect, useRef, AUTODEPS } from "react";
30 import { print } from "shared-runtime";
31
32 function Component(t0) {
@@ -47,9 +47,9 @@ export const FIXTURE_ENTRYPOINT = {
47 ## Logs
48
49 ```
50 -{"kind":"CompileError","fnLoc":{"start":{"line":6,"column":0,"index":180},"end":{"line":11,"column":1,"index":343},"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":301},"end":{"line":9,"column":16,"index":315},"filename":"mutate-after-useeffect-ref-access.ts"}}}
51 -{"kind":"AutoDepsDecorations","fnLoc":{"start":{"line":8,"column":2,"index":259},"end":{"line":8,"column":40,"index":297},"filename":"mutate-after-useeffect-ref-access.ts"},"decorations":[{"start":{"line":8,"column":24,"index":281},"end":{"line":8,"column":30,"index":287},"filename":"mutate-after-useeffect-ref-access.ts","identifierName":"arrRef"}]}
52 -{"kind":"CompileSuccess","fnLoc":{"start":{"line":6,"column":0,"index":180},"end":{"line":11,"column":1,"index":343},"filename":"mutate-after-useeffect-ref-access.ts"},"fnName":"Component","memoSlots":0,"memoBlocks":0,"memoValues":0,"prunedMemoBlocks":0,"prunedMemoValues":0}
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"}}}
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 ```
54
55 ### Eval output
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/mutate-after-useeffect-ref-access.js
+2 -2
@@ -1,11 +1,11 @@
1 // @inferEffectDependencies @panicThreshold:"none" @loggerTestOnly @enableNewMutationAliasingModel
2
3 -import {useEffect, useRef} from 'react';
3 +import {useEffect, useRef, AUTODEPS} from 'react';
4 import {print} from 'shared-runtime';
5
6 function Component({arrRef}) {
7 // Avoid taking arr.current as a dependency
8 - useEffect(() => print(arrRef.current));
8 + useEffect(() => print(arrRef.current), AUTODEPS);
9 arrRef.current.val = 2;
10 return arrRef;
11 }
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/mutate-after-useeffect.expect.md
+6 -6
@@ -3,13 +3,13 @@
3
4 ```javascript
5 // @inferEffectDependencies @panicThreshold:"none" @loggerTestOnly @enableNewMutationAliasingModel
6 -import {useEffect} from 'react';
6 +import {useEffect, AUTODEPS} from 'react';
7
8 function Component({foo}) {
9 const arr = [];
10 useEffect(() => {
11 arr.push(foo);
12 - });
12 + }, AUTODEPS);
13 arr.push(2);
14 return arr;
15 }
@@ -25,7 +25,7 @@ export const FIXTURE_ENTRYPOINT = {
25
26 ```javascript
27 // @inferEffectDependencies @panicThreshold:"none" @loggerTestOnly @enableNewMutationAliasingModel
28 -import { useEffect } from "react";
28 +import { useEffect, AUTODEPS } from "react";
29
30 function Component(t0) {
31 const { foo } = t0;
@@ -47,9 +47,9 @@ export const FIXTURE_ENTRYPOINT = {
47 ## Logs
48
49 ```
50 -{"kind":"CompileError","fnLoc":{"start":{"line":4,"column":0,"index":133},"end":{"line":11,"column":1,"index":254},"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":226},"end":{"line":9,"column":5,"index":229},"filename":"mutate-after-useeffect.ts","identifierName":"arr"}}}
51 -{"kind":"AutoDepsDecorations","fnLoc":{"start":{"line":6,"column":2,"index":181},"end":{"line":8,"column":4,"index":222},"filename":"mutate-after-useeffect.ts"},"decorations":[{"start":{"line":7,"column":4,"index":203},"end":{"line":7,"column":7,"index":206},"filename":"mutate-after-useeffect.ts","identifierName":"arr"},{"start":{"line":7,"column":4,"index":203},"end":{"line":7,"column":7,"index":206},"filename":"mutate-after-useeffect.ts","identifierName":"arr"},{"start":{"line":7,"column":13,"index":212},"end":{"line":7,"column":16,"index":215},"filename":"mutate-after-useeffect.ts","identifierName":"foo"}]}
52 -{"kind":"CompileSuccess","fnLoc":{"start":{"line":4,"column":0,"index":133},"end":{"line":11,"column":1,"index":254},"filename":"mutate-after-useeffect.ts"},"fnName":"Component","memoSlots":0,"memoBlocks":0,"memoValues":0,"prunedMemoBlocks":0,"prunedMemoValues":0}
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"}}}
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 ```
54
55 ### Eval output
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/mutate-after-useeffect.js
+2 -2
@@ -1,11 +1,11 @@
1 // @inferEffectDependencies @panicThreshold:"none" @loggerTestOnly @enableNewMutationAliasingModel
2 -import {useEffect} from 'react';
2 +import {useEffect, AUTODEPS} from 'react';
3
4 function Component({foo}) {
5 const arr = [];
6 useEffect(() => {
7 arr.push(foo);
8 - });
8 + }, AUTODEPS);
9 arr.push(2);
10 return arr;
11 }
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/reactive-setState.expect.md
+3 -3
@@ -3,7 +3,7 @@
3
4 ```javascript
5 // @inferEffectDependencies @enableNewMutationAliasingModel
6 -import {useEffect, useState} from 'react';
6 +import {useEffect, useState, AUTODEPS} from 'react';
7 import {print} from 'shared-runtime';
8
9 /*
@@ -18,7 +18,7 @@ function ReactiveRefInEffect(props) {
18 } else {
19 setState = setState2;
20 }
21 - useEffect(() => print(setState));
21 + useEffect(() => print(setState), AUTODEPS);
22 }
23
24 ```
@@ -27,7 +27,7 @@ function ReactiveRefInEffect(props) {
27
28 ```javascript
29 import { c as _c } from "react/compiler-runtime"; // @inferEffectDependencies @enableNewMutationAliasingModel
30 -import { useEffect, useState } from "react";
30 +import { useEffect, useState, AUTODEPS } from "react";
31 import { print } from "shared-runtime";
32
33 /*
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/reactive-setState.js
+2 -2
@@ -1,5 +1,5 @@
1 // @inferEffectDependencies @enableNewMutationAliasingModel
2 -import {useEffect, useState} from 'react';
2 +import {useEffect, useState, AUTODEPS} from 'react';
3 import {print} from 'shared-runtime';
4
5 /*
@@ -14,5 +14,5 @@ function ReactiveRefInEffect(props) {
14 } else {
15 setState = setState2;
16 }
17 - useEffect(() => print(setState));
17 + useEffect(() => print(setState), AUTODEPS);
18 }
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/retry-no-emit.expect.md
+10 -8
@@ -5,13 +5,14 @@
5 // @inferEffectDependencies @noEmit @panicThreshold:"none" @loggerTestOnly @enableNewMutationAliasingModel
6 import {print} from 'shared-runtime';
7 import useEffectWrapper from 'useEffectWrapper';
8 +import {AUTODEPS} from 'react';
9
10 function Foo({propVal}) {
11 const arr = [propVal];
11 - useEffectWrapper(() => print(arr));
12 + useEffectWrapper(() => print(arr), AUTODEPS);
13
14 const arr2 = [];
14 - useEffectWrapper(() => arr2.push(propVal));
15 + useEffectWrapper(() => arr2.push(propVal), AUTODEPS);
16 arr2.push(2);
17 return {arr, arr2};
18 }
@@ -30,13 +31,14 @@ export const FIXTURE_ENTRYPOINT = {
31 // @inferEffectDependencies @noEmit @panicThreshold:"none" @loggerTestOnly @enableNewMutationAliasingModel
32 import { print } from "shared-runtime";
33 import useEffectWrapper from "useEffectWrapper";
34 +import { AUTODEPS } from "react";
35
36 function Foo({ propVal }) {
37 const arr = [propVal];
36 - useEffectWrapper(() => print(arr));
38 + useEffectWrapper(() => print(arr), AUTODEPS);
39
40 const arr2 = [];
39 - useEffectWrapper(() => arr2.push(propVal));
41 + useEffectWrapper(() => arr2.push(propVal), AUTODEPS);
42 arr2.push(2);
43 return { arr, arr2 };
44 }
@@ -52,10 +54,10 @@ export const FIXTURE_ENTRYPOINT = {
54 ## Logs
55
56 ```
55 -{"kind":"CompileError","fnLoc":{"start":{"line":5,"column":0,"index":195},"end":{"line":13,"column":1,"index":389},"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":11,"column":2,"index":352},"end":{"line":11,"column":6,"index":356},"filename":"retry-no-emit.ts","identifierName":"arr2"}}}
56 -{"kind":"AutoDepsDecorations","fnLoc":{"start":{"line":7,"column":2,"index":248},"end":{"line":7,"column":36,"index":282},"filename":"retry-no-emit.ts"},"decorations":[{"start":{"line":7,"column":31,"index":277},"end":{"line":7,"column":34,"index":280},"filename":"retry-no-emit.ts","identifierName":"arr"}]}
57 -{"kind":"AutoDepsDecorations","fnLoc":{"start":{"line":10,"column":2,"index":306},"end":{"line":10,"column":44,"index":348},"filename":"retry-no-emit.ts"},"decorations":[{"start":{"line":10,"column":25,"index":329},"end":{"line":10,"column":29,"index":333},"filename":"retry-no-emit.ts","identifierName":"arr2"},{"start":{"line":10,"column":25,"index":329},"end":{"line":10,"column":29,"index":333},"filename":"retry-no-emit.ts","identifierName":"arr2"},{"start":{"line":10,"column":35,"index":339},"end":{"line":10,"column":42,"index":346},"filename":"retry-no-emit.ts","identifierName":"propVal"}]}
58 -{"kind":"CompileSuccess","fnLoc":{"start":{"line":5,"column":0,"index":195},"end":{"line":13,"column":1,"index":389},"filename":"retry-no-emit.ts"},"fnName":"Foo","memoSlots":0,"memoBlocks":0,"memoValues":0,"prunedMemoBlocks":0,"prunedMemoValues":0}
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"}}}
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}
61 ```
62
63 ### Eval output
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/new-mutability/retry-no-emit.js
+3 -2
@@ -1,13 +1,14 @@
1 // @inferEffectDependencies @noEmit @panicThreshold:"none" @loggerTestOnly @enableNewMutationAliasingModel
2 import {print} from 'shared-runtime';
3 import useEffectWrapper from 'useEffectWrapper';
4 +import {AUTODEPS} from 'react';
5
6 function Foo({propVal}) {
7 const arr = [propVal];
7 - useEffectWrapper(() => print(arr));
8 + useEffectWrapper(() => print(arr), AUTODEPS);
9
10 const arr2 = [];
10 - useEffectWrapper(() => arr2.push(propVal));
11 + useEffectWrapper(() => arr2.push(propVal), AUTODEPS);
12 arr2.push(2);
13 return {arr, arr2};
14 }
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transform-fire/bailout-retry/infer-deps-on-retry.expect.md
+9 -5
@@ -3,7 +3,7 @@
3
4 ```javascript
5 // @inferEffectDependencies @panicThreshold:"none"
6 -import {useRef} from 'react';
6 +import {useRef, AUTODEPS} from 'react';
7 import {useSpecialEffect} from 'shared-runtime';
8
9 /**
@@ -14,9 +14,13 @@ import {useSpecialEffect} from 'shared-runtime';
14 function useFoo({cond}) {
15 const ref = useRef();
16 const derived = cond ? ref.current : makeObject();
17 - useSpecialEffect(() => {
18 - log(derived);
19 - }, [derived]);
17 + useSpecialEffect(
18 + () => {
19 + log(derived);
20 + },
21 + [derived],
22 + AUTODEPS
23 + );
24 return ref;
25 }
26
@@ -26,7 +30,7 @@ function useFoo({cond}) {
30
31 ```javascript
32 // @inferEffectDependencies @panicThreshold:"none"
29 -import { useRef } from "react";
33 +import { useRef, AUTODEPS } from "react";
34 import { useSpecialEffect } from "shared-runtime";
35
36 /**
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transform-fire/bailout-retry/infer-deps-on-retry.js
+8 -4
@@ -1,5 +1,5 @@
1 // @inferEffectDependencies @panicThreshold:"none"
2 -import {useRef} from 'react';
2 +import {useRef, AUTODEPS} from 'react';
3 import {useSpecialEffect} from 'shared-runtime';
4
5 /**
@@ -10,8 +10,12 @@ import {useSpecialEffect} from 'shared-runtime';
10 function useFoo({cond}) {
11 const ref = useRef();
12 const derived = cond ? ref.current : makeObject();
13 - useSpecialEffect(() => {
14 - log(derived);
15 - }, [derived]);
13 + useSpecialEffect(
14 + () => {
15 + log(derived);
16 + },
17 + [derived],
18 + AUTODEPS
19 + );
20 return ref;
21 }
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transform-fire/fire-and-autodeps.expect.md deleted
-59
@@ -1,59 +0,0 @@
1 -
2 -## Input
3 -
4 -```javascript
5 -// @enableFire @inferEffectDependencies
6 -import {fire, useEffect} from 'react';
7 -
8 -function Component(props) {
9 - const foo = arg => {
10 - console.log(arg, props.bar);
11 - };
12 - useEffect(() => {
13 - fire(foo(props));
14 - });
15 -
16 - return null;
17 -}
18 -
19 -```
20 -
21 -## Code
22 -
23 -```javascript
24 -import { c as _c, useFire } from "react/compiler-runtime"; // @enableFire @inferEffectDependencies
25 -import { fire, useEffect } from "react";
26 -
27 -function Component(props) {
28 - const $ = _c(5);
29 - let t0;
30 - if ($[0] !== props.bar) {
31 - t0 = (arg) => {
32 - console.log(arg, props.bar);
33 - };
34 - $[0] = props.bar;
35 - $[1] = t0;
36 - } else {
37 - t0 = $[1];
38 - }
39 - const foo = t0;
40 - const t1 = useFire(foo);
41 - let t2;
42 - if ($[2] !== props || $[3] !== t1) {
43 - t2 = () => {
44 - t1(props);
45 - };
46 - $[2] = props;
47 - $[3] = t1;
48 - $[4] = t2;
49 - } else {
50 - t2 = $[4];
51 - }
52 - useEffect(t2, [props]);
53 - return null;
54 -}
55 -
56 -```
57 -
58 -### Eval output
59 -(kind: exception) Fixture not implemented
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transform-fire/fire-and-autodeps.js deleted
-13
@@ -1,13 +0,0 @@
1 -// @enableFire @inferEffectDependencies
2 -import {fire, useEffect} from 'react';
3 -
4 -function Component(props) {
5 - const foo = arg => {
6 - console.log(arg, props.bar);
7 - };
8 - useEffect(() => {
9 - fire(foo(props));
10 - });
11 -
12 - return null;
13 -}