@samitouri / QOS-React / commits / 9d7f02d9ab

[compiler] General-purpose function outlining

Implements general-purpose function outlining. Specifically, anonymous function expressions which have no dependencies/context variables are extracted into named top-level functions. The original function expression is replaced with a `LoadGlobal` of the generated name. Note that the architecture is designed to allow very general purpose forms of outlining, though we currently are very conservative in what we outline. Specifically, the outlining allows annotating functions with an optional ReactiveFunctionType, which if set will cause the outlined function to get compiled as that type. So we could for example outline a helper hook or helper component, set the type, and then have the hook/component get memoized as well. For now though we just outline with no type set, and generate the function as-is without running it through compilation. ghstack-source-id: 2a7da6c8e85c3f8becb22d3869d9b6200f7db126 Pull Request resolved: https://github.com/facebook/react/pull/30331

Joe Savona committed Jul 15, 2024 at 12:28 UTC 9d7f02d9abbbba951b9af951be403f12d6adebf1
73 files changed +751 -750
compiler/packages/babel-plugin-react-compiler/scripts/jest/makeTransform.ts
+1
@@ -28,6 +28,7 @@ import { basename } from "path";
28 const e2eTransformerCacheKey = 1;
29 const forgetOptions: EnvironmentConfig = validateEnvironmentConfig({
30 enableAssumeHooksFollowRulesOfReact: true,
31 + enableFunctionOutlining: false,
32 });
33 const debugMode = process.env["DEBUG_FORGET_COMPILER"] != null;
34
compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Pipeline.ts
+9
@@ -97,6 +97,7 @@ import {
97 validateUseMemo,
98 } from "../Validation";
99 import { validateLocalsNotReassignedAfterRender } from "../Validation/ValidateLocalsNotReassignedAfterRender";
100 +import { outlineFunctions } from "../Optimization/OutlineFunctions";
101
102 export type CompilerPipelineValue =
103 | { kind: "ast"; name: string; value: CodegenFunction }
@@ -242,6 +243,11 @@ function* runWithEnvironment(
243 inferReactiveScopeVariables(hir);
244 yield log({ kind: "hir", name: "InferReactiveScopeVariables", value: hir });
245
246 + if (env.config.enableFunctionOutlining) {
247 + outlineFunctions(hir);
248 + yield log({ kind: "hir", name: "OutlineFunctions", value: hir });
249 + }
250 +
251 alignMethodCallScopes(hir);
252 yield log({
253 kind: "hir",
@@ -480,6 +486,9 @@ function* runWithEnvironment(
486
487 const ast = codegenFunction(reactiveFunction, uniqueIdentifiers).unwrap();
488 yield log({ kind: "ast", name: "Codegen", value: ast });
489 + for (const outlined of ast.outlined) {
490 + yield log({ kind: "ast", name: "Codegen (outlined)", value: outlined.fn });
491 + }
492
493 /**
494 * This flag should be only set for unit / fixture tests to check
compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Program.ts
+36 -3
@@ -87,6 +87,12 @@ export type BabelFn =
87 | NodePath<t.ArrowFunctionExpression>;
88
89 export type CompileResult = {
90 + /**
91 + * Distinguishes existing functions that were compiled ('original') from
92 + * functions which were outlined. Only original functions need to be gated
93 + * if gating mode is enabled.
94 + */
95 + kind: "original" | "outlined";
96 originalFn: BabelFn;
97 compiledFn: CodegenFunction;
98 };
@@ -266,6 +272,7 @@ export function compileProgram(
272 const lintError = suppressionsToCompilerError(suppressions);
273 let hasCriticalError = lintError != null;
274 const queue: Array<{
275 + kind: "original" | "outlined";
276 fn: BabelFn;
277 fnType: ReactFunctionType;
278 }> = [];
@@ -285,7 +292,7 @@ export function compileProgram(
292 ALREADY_COMPILED.add(fn.node);
293 fn.skip();
294
288 - queue.push({ fn, fnType });
295 + queue.push({ kind: "original", fn, fnType });
296 };
297
298 // Main traversal to compile with Forget
@@ -395,7 +402,33 @@ export function compileProgram(
402 if (compiled === null) {
403 continue;
404 }
405 + for (const outlined of compiled.outlined) {
406 + CompilerError.invariant(outlined.fn.outlined.length === 0, {
407 + reason: "Unexpected nested outlined functions",
408 + loc: outlined.fn.loc,
409 + });
410 + const fn = current.fn.insertAfter(
411 + createNewFunctionNode(current.fn, outlined.fn)
412 + )[0]!;
413 + fn.skip();
414 + ALREADY_COMPILED.add(fn.node);
415 + if (outlined.type !== null) {
416 + CompilerError.throwTodo({
417 + reason: `Implement support for outlining React functions (components/hooks)`,
418 + loc: outlined.fn.loc,
419 + });
420 + /*
421 + * Above should be as simple as the following, but needs testing:
422 + * queue.push({
423 + * kind: "outlined",
424 + * fn,
425 + * fnType: outlined.type,
426 + * });
427 + */
428 + }
429 + }
430 compiledFns.push({
431 + kind: current.kind,
432 compiledFn: compiled,
433 originalFn: current.fn,
434 });
@@ -466,10 +499,10 @@ export function compileProgram(
499 * error elsewhere in the file, regardless of bailout mode.
500 */
501 for (const result of compiledFns) {
469 - const { originalFn, compiledFn } = result;
502 + const { kind, originalFn, compiledFn } = result;
503 const transformedFn = createNewFunctionNode(originalFn, compiledFn);
504
472 - if (gating != null) {
505 + if (gating != null && kind === "original") {
506 insertGatedFunctionDeclaration(originalFn, transformedFn, gating);
507 } else {
508 originalFn.replaceWith(transformedFn);
compiler/packages/babel-plugin-react-compiler/src/HIR/Environment.ts
+31
@@ -23,14 +23,17 @@ import {
23 BuiltInType,
24 Effect,
25 FunctionType,
26 + HIRFunction,
27 IdentifierId,
28 NonLocalBinding,
29 PolyType,
30 ScopeId,
31 Type,
32 + ValidatedIdentifier,
33 ValueKind,
34 makeBlockId,
35 makeIdentifierId,
36 + makeIdentifierName,
37 makeScopeId,
38 } from "./HIR";
39 import {
@@ -284,6 +287,12 @@ const EnvironmentConfigSchema = z.object({
287 */
288 enableInstructionReordering: z.boolean().default(false),
289
290 + /**
291 + * Enables function outlinining, where anonymous functions that do not close over
292 + * local variables can be extracted into top-level helper functions.
293 + */
294 + enableFunctionOutlining: z.boolean().default(true),
295 +
296 /*
297 * Enables instrumentation codegen. This emits a dev-mode only call to an
298 * instrumentation function, for components and hooks that Forget compiles.
@@ -506,6 +515,10 @@ export class Environment {
515 #nextBlock: number = 0;
516 #nextScope: number = 0;
517 #scope: BabelScope;
518 + #outlinedFunctions: Array<{
519 + fn: HIRFunction;
520 + type: ReactFunctionType | null;
521 + }> = [];
522 logger: Logger | null;
523 filename: string | null;
524 code: string | null;
@@ -599,6 +612,24 @@ export class Environment {
612 return this.#hoistedIdentifiers.has(node);
613 }
614
615 + generateGloballyUniqueIdentifierName(
616 + name: string | null
617 + ): ValidatedIdentifier {
618 + const identifierNode = this.#scope.generateUidIdentifier(name ?? undefined);
619 + return makeIdentifierName(identifierNode.name);
620 + }
621 +
622 + outlineFunction(fn: HIRFunction, type: ReactFunctionType | null): void {
623 + this.#outlinedFunctions.push({ fn, type });
624 + }
625 +
626 + getOutlinedFunctions(): Array<{
627 + fn: HIRFunction;
628 + type: ReactFunctionType | null;
629 + }> {
630 + return this.#outlinedFunctions;
631 + }
632 +
633 getGlobalDeclaration(binding: NonLocalBinding): Global | null {
634 if (this.config.hookPattern != null) {
635 const match = new RegExp(this.config.hookPattern).exec(binding.name);
compiler/packages/babel-plugin-react-compiler/src/Optimization/OutlineFunctions.ts new
+47
@@ -0,0 +1,47 @@
1 +/**
2 + * Copyright (c) Meta Platforms, Inc. and affiliates.
3 + *
4 + * This source code is licensed under the MIT license found in the
5 + * LICENSE file in the root directory of this source tree.
6 + */
7 +
8 +import { HIRFunction } from "../HIR";
9 +
10 +export function outlineFunctions(fn: HIRFunction): void {
11 + for (const [, block] of fn.body.blocks) {
12 + for (const instr of block.instructions) {
13 + const { value } = instr;
14 +
15 + if (
16 + value.kind === "FunctionExpression" ||
17 + value.kind === "ObjectMethod"
18 + ) {
19 + // Recurse in case there are inner functions which can be outlined
20 + outlineFunctions(value.loweredFunc.func);
21 + }
22 +
23 + if (
24 + value.kind === "FunctionExpression" &&
25 + value.loweredFunc.dependencies.length === 0 &&
26 + value.loweredFunc.func.context.length === 0 &&
27 + // TODO: handle outlining named functions
28 + value.loweredFunc.func.id === null
29 + ) {
30 + const loweredFunc = value.loweredFunc.func;
31 +
32 + const id = fn.env.generateGloballyUniqueIdentifierName(loweredFunc.id);
33 + loweredFunc.id = id.value;
34 +
35 + fn.env.outlineFunction(loweredFunc, null);
36 + instr.value = {
37 + kind: "LoadGlobal",
38 + binding: {
39 + kind: "Global",
40 + name: id.value,
41 + },
42 + loc: value.loc,
43 + };
44 + }
45 + }
46 + }
47 +}
compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/CodegenReactiveFunction.ts
+49 -1
@@ -7,7 +7,12 @@
7
8 import * as t from "@babel/types";
9 import { createHmac } from "crypto";
10 -import { pruneHoistedContexts, pruneUnusedLValues, pruneUnusedLabels } from ".";
10 +import {
11 + pruneHoistedContexts,
12 + pruneUnusedLValues,
13 + pruneUnusedLabels,
14 + renameVariables,
15 +} from ".";
16 import { CompilerError, ErrorSeverity } from "../CompilerError";
17 import { Environment, EnvironmentConfig, ExternalFunction } from "../HIR";
18 import {
@@ -36,6 +41,7 @@ import {
41 ValidIdentifierName,
42 getHookKind,
43 makeIdentifierName,
44 + promoteTemporary,
45 } from "../HIR/HIR";
46 import { printIdentifier, printPlace } from "../HIR/PrintHIR";
47 import { eachPatternOperand } from "../HIR/visitors";
@@ -45,6 +51,8 @@ import { assertExhaustive } from "../Utils/utils";
51 import { buildReactiveFunction } from "./BuildReactiveFunction";
52 import { SINGLE_CHILD_FBT_TAGS } from "./MemoizeFbtAndMacroOperandsInSameScope";
53 import { ReactiveFunctionVisitor, visitReactiveFunction } from "./visitors";
54 +import { ReactFunctionType } from "../HIR/Environment";
55 +import { logReactiveFunction } from "../Utils/logger";
56
57 export const MEMO_CACHE_SENTINEL = "react.memo_cache_sentinel";
58 export const EARLY_RETURN_SENTINEL = "react.early_return_sentinel";
@@ -85,6 +93,11 @@ export type CodegenFunction = {
93 * because they were part of a pruned memo block.
94 */
95 prunedMemoValues: number;
96 +
97 + outlined: Array<{
98 + fn: CodegenFunction;
99 + type: ReactFunctionType | null;
100 + }>;
101 };
102
103 export function codegenFunction(
@@ -258,6 +271,40 @@ export function codegenFunction(
271 compiled.body.body.unshift(test);
272 }
273
274 + const outlined: CodegenFunction["outlined"] = [];
275 + for (const { fn: outlinedFunction, type } of cx.env.getOutlinedFunctions()) {
276 + const reactiveFunction = buildReactiveFunction(outlinedFunction);
277 + pruneUnusedLabels(reactiveFunction);
278 + pruneUnusedLValues(reactiveFunction);
279 + pruneHoistedContexts(reactiveFunction);
280 +
281 + /*
282 + * TODO: temporary function params (due to destructuring) should always be
283 + * promoted so that they can be renamed
284 + */
285 + for (const param of reactiveFunction.params) {
286 + const place = param.kind === "Identifier" ? param : param.place;
287 + if (place.identifier.name === null) {
288 + promoteTemporary(place.identifier);
289 + }
290 + }
291 + const identifiers = renameVariables(reactiveFunction);
292 + logReactiveFunction("Outline", reactiveFunction);
293 + const codegen = codegenReactiveFunction(
294 + new Context(
295 + cx.env,
296 + reactiveFunction.id ?? "[[ anonymous ]]",
297 + identifiers
298 + ),
299 + reactiveFunction
300 + );
301 + if (codegen.isErr()) {
302 + return codegen;
303 + }
304 + outlined.push({ fn: codegen.unwrap(), type });
305 + }
306 + compiled.outlined = outlined;
307 +
308 return compileResult;
309 }
310
@@ -306,6 +353,7 @@ function codegenReactiveFunction(
353 memoValues: countMemoBlockVisitor.memoValues,
354 prunedMemoBlocks: countMemoBlockVisitor.prunedMemoBlocks,
355 prunedMemoValues: countMemoBlockVisitor.prunedMemoValues,
356 + outlined: [],
357 });
358 }
359
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-global-mutation-in-effect-indirect-usecallback.expect.md
+25 -30
@@ -40,57 +40,52 @@ import { useCallback, useEffect, useState } from "react";
40 let someGlobal = {};
41
42 function Component() {
43 - const $ = _c(7);
43 + const $ = _c(6);
44 const [state, setState] = useState(someGlobal);
45 +
46 + const setGlobal = _temp;
47 let t0;
48 + let t1;
49 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
50 t0 = () => {
48 - someGlobal.value = true;
49 - };
50 - $[0] = t0;
51 - } else {
52 - t0 = $[0];
53 - }
54 - const setGlobal = t0;
55 - let t1;
56 - let t2;
57 - if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
58 - t1 = () => {
51 setGlobal();
52 };
61 - t2 = [];
53 + t1 = [];
54 + $[0] = t0;
55 $[1] = t1;
63 - $[2] = t2;
56 } else {
57 + t0 = $[0];
58 t1 = $[1];
66 - t2 = $[2];
59 }
68 - useEffect(t1, t2);
60 + useEffect(t0, t1);
61 + let t2;
62 let t3;
70 - let t4;
71 - if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
72 - t3 = () => {
63 + if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
64 + t2 = () => {
65 setState(someGlobal.value);
66 };
75 - t4 = [someGlobal];
67 + t3 = [someGlobal];
68 + $[2] = t2;
69 $[3] = t3;
77 - $[4] = t4;
70 } else {
71 + t2 = $[2];
72 t3 = $[3];
80 - t4 = $[4];
73 }
82 - useEffect(t3, t4);
74 + useEffect(t2, t3);
75
84 - const t5 = String(state);
85 - let t6;
86 - if ($[5] !== t5) {
87 - t6 = <div>{t5}</div>;
76 + const t4 = String(state);
77 + let t5;
78 + if ($[4] !== t4) {
79 + t5 = <div>{t4}</div>;
80 + $[4] = t4;
81 $[5] = t5;
89 - $[6] = t6;
82 } else {
91 - t6 = $[6];
83 + t5 = $[5];
84 }
93 - return t6;
85 + return t5;
86 +}
87 +function _temp() {
88 + someGlobal.value = true;
89 }
90
91 export const FIXTURE_ENTRYPOINT = {
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-global-mutation-in-effect-indirect.expect.md
+25 -30
@@ -39,57 +39,52 @@ import { useEffect, useState } from "react";
39 let someGlobal = {};
40
41 function Component() {
42 - const $ = _c(7);
42 + const $ = _c(6);
43 const [state, setState] = useState(someGlobal);
44 +
45 + const setGlobal = _temp;
46 let t0;
47 + let t1;
48 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
49 t0 = () => {
47 - someGlobal.value = true;
48 - };
49 - $[0] = t0;
50 - } else {
51 - t0 = $[0];
52 - }
53 - const setGlobal = t0;
54 - let t1;
55 - let t2;
56 - if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
57 - t1 = () => {
50 setGlobal();
51 };
60 - t2 = [];
52 + t1 = [];
53 + $[0] = t0;
54 $[1] = t1;
62 - $[2] = t2;
55 } else {
56 + t0 = $[0];
57 t1 = $[1];
65 - t2 = $[2];
58 }
67 - useEffect(t1, t2);
59 + useEffect(t0, t1);
60 + let t2;
61 let t3;
69 - let t4;
70 - if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
71 - t3 = () => {
62 + if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
63 + t2 = () => {
64 setState(someGlobal.value);
65 };
74 - t4 = [someGlobal];
66 + t3 = [someGlobal];
67 + $[2] = t2;
68 $[3] = t3;
76 - $[4] = t4;
69 } else {
70 + t2 = $[2];
71 t3 = $[3];
79 - t4 = $[4];
72 }
81 - useEffect(t3, t4);
73 + useEffect(t2, t3);
74
83 - const t5 = String(state);
84 - let t6;
85 - if ($[5] !== t5) {
86 - t6 = <div>{t5}</div>;
75 + const t4 = String(state);
76 + let t5;
77 + if ($[4] !== t4) {
78 + t5 = <div>{t4}</div>;
79 + $[4] = t4;
80 $[5] = t5;
88 - $[6] = t6;
81 } else {
90 - t6 = $[6];
82 + t5 = $[5];
83 }
92 - return t6;
84 + return t5;
85 +}
86 +function _temp() {
87 + someGlobal.value = true;
88 }
89
90 export const FIXTURE_ENTRYPOINT = {
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-global-reassignment-in-effect-indirect.expect.md
+25 -30
@@ -39,57 +39,52 @@ import { useEffect, useState } from "react";
39 let someGlobal = false;
40
41 function Component() {
42 - const $ = _c(7);
42 + const $ = _c(6);
43 const [state, setState] = useState(someGlobal);
44 +
45 + const setGlobal = _temp;
46 let t0;
47 + let t1;
48 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
49 t0 = () => {
47 - someGlobal = true;
48 - };
49 - $[0] = t0;
50 - } else {
51 - t0 = $[0];
52 - }
53 - const setGlobal = t0;
54 - let t1;
55 - let t2;
56 - if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
57 - t1 = () => {
50 setGlobal();
51 };
60 - t2 = [];
52 + t1 = [];
53 + $[0] = t0;
54 $[1] = t1;
62 - $[2] = t2;
55 } else {
56 + t0 = $[0];
57 t1 = $[1];
65 - t2 = $[2];
58 }
67 - useEffect(t1, t2);
59 + useEffect(t0, t1);
60 + let t2;
61 let t3;
69 - let t4;
70 - if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
71 - t3 = () => {
62 + if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
63 + t2 = () => {
64 setState(someGlobal);
65 };
74 - t4 = [someGlobal];
66 + t3 = [someGlobal];
67 + $[2] = t2;
68 $[3] = t3;
76 - $[4] = t4;
69 } else {
70 + t2 = $[2];
71 t3 = $[3];
79 - t4 = $[4];
72 }
81 - useEffect(t3, t4);
73 + useEffect(t2, t3);
74
83 - const t5 = String(state);
84 - let t6;
85 - if ($[5] !== t5) {
86 - t6 = <div>{t5}</div>;
75 + const t4 = String(state);
76 + let t5;
77 + if ($[4] !== t4) {
78 + t5 = <div>{t4}</div>;
79 + $[4] = t4;
80 $[5] = t5;
88 - $[6] = t6;
81 } else {
90 - t6 = $[6];
82 + t5 = $[5];
83 }
92 - return t6;
84 + return t5;
85 +}
86 +function _temp() {
87 + someGlobal = true;
88 }
89
90 export const FIXTURE_ENTRYPOINT = {
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-global-reassignment-in-effect.expect.md
+20 -24
@@ -36,48 +36,44 @@ import { useEffect, useState } from "react";
36 let someGlobal = false;
37
38 function Component() {
39 - const $ = _c(6);
39 + const $ = _c(5);
40 const [state, setState] = useState(someGlobal);
41 let t0;
42 - let t1;
42 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
44 - t0 = () => {
45 - someGlobal = true;
46 - };
47 -
48 - t1 = [];
43 + t0 = [];
44 $[0] = t0;
50 - $[1] = t1;
45 } else {
46 t0 = $[0];
53 - t1 = $[1];
47 }
55 - useEffect(t0, t1);
48 + useEffect(_temp, t0);
49 + let t1;
50 let t2;
57 - let t3;
58 - if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
59 - t2 = () => {
51 + if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
52 + t1 = () => {
53 setState(someGlobal);
54 };
62 - t3 = [someGlobal];
55 + t2 = [someGlobal];
56 + $[1] = t1;
57 $[2] = t2;
64 - $[3] = t3;
58 } else {
59 + t1 = $[1];
60 t2 = $[2];
67 - t3 = $[3];
61 }
69 - useEffect(t2, t3);
62 + useEffect(t1, t2);
63
71 - const t4 = String(state);
72 - let t5;
73 - if ($[4] !== t4) {
74 - t5 = <div>{t4}</div>;
64 + const t3 = String(state);
65 + let t4;
66 + if ($[3] !== t3) {
67 + t4 = <div>{t3}</div>;
68 + $[3] = t3;
69 $[4] = t4;
76 - $[5] = t5;
70 } else {
78 - t5 = $[5];
71 + t4 = $[4];
72 }
80 - return t5;
73 + return t4;
74 +}
75 +function _temp() {
76 + someGlobal = true;
77 }
78
79 export const FIXTURE_ENTRYPOINT = {
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/allow-reassignment-to-global-function-jsx-prop.expect.md
+5 -5
@@ -27,13 +27,9 @@ export const FIXTURE_ENTRYPOINT = {
27 import { c as _c } from "react/compiler-runtime";
28 function Component() {
29 const $ = _c(1);
30 + const onClick = _temp;
31 let t0;
32 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
32 - const onClick = () => {
33 - someUnknownGlobal = true;
34 - moduleLocal = true;
35 - };
36 -
33 t0 = <div onClick={onClick} />;
34 $[0] = t0;
35 } else {
@@ -41,6 +37,10 @@ function Component() {
37 }
38 return t0;
39 }
40 +function _temp() {
41 + someUnknownGlobal = true;
42 + moduleLocal = true;
43 +}
44
45 export const FIXTURE_ENTRYPOINT = {
46 fn: Component,
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/array-join.expect.md
+13 -17
@@ -16,7 +16,7 @@ function Component(props) {
16 ```javascript
17 import { c as _c } from "react/compiler-runtime";
18 function Component(props) {
19 - const $ = _c(8);
19 + const $ = _c(7);
20 let t0;
21 let t1;
22 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
@@ -37,25 +37,21 @@ function Component(props) {
37 t2 = $[3];
38 }
39 const x = t2;
40 - let t3;
41 - if ($[4] === Symbol.for("react.memo_cache_sentinel")) {
42 - t3 = () => "this closure gets stringified, not called";
43 - $[4] = t3;
44 - } else {
45 - t3 = $[4];
46 - }
47 - const y = x.join(t3);
40 + const y = x.join(_temp);
41 foo(y);
49 - let t4;
50 - if ($[5] !== x || $[6] !== y) {
51 - t4 = [x, y];
52 - $[5] = x;
53 - $[6] = y;
54 - $[7] = t4;
42 + let t3;
43 + if ($[4] !== x || $[5] !== y) {
44 + t3 = [x, y];
45 + $[4] = x;
46 + $[5] = y;
47 + $[6] = t3;
48 } else {
56 - t4 = $[7];
49 + t3 = $[6];
50 }
58 - return t4;
51 + return t3;
52 +}
53 +function _temp() {
54 + return "this closure gets stringified, not called";
55 }
56
57 ```
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/array-map-captures-receiver-noAlias.expect.md
+4 -1
@@ -44,7 +44,7 @@ function Component(props) {
44 const items = t1;
45 let t2;
46 if ($[4] !== items) {
47 - t2 = items.map((item_0) => item_0);
47 + t2 = items.map(_temp);
48 $[4] = items;
49 $[5] = t2;
50 } else {
@@ -53,6 +53,9 @@ function Component(props) {
53 const mapped = t2;
54 return mapped;
55 }
56 +function _temp(item_0) {
57 + return item_0;
58 +}
59
60 export const FIXTURE_ENTRYPOINT = {
61 fn: Component,
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/array-map-frozen-array-noAlias.expect.md
+4 -1
@@ -33,7 +33,7 @@ function Component(props) {
33 const x = t0;
34 let t1;
35 if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
36 - const y = x.map((item) => item);
36 + const y = x.map(_temp);
37 t1 = [x, y];
38 $[1] = t1;
39 } else {
@@ -41,6 +41,9 @@ function Component(props) {
41 }
42 return t1;
43 }
44 +function _temp(item) {
45 + return item;
46 +}
47
48 export const FIXTURE_ENTRYPOINT = {
49 fn: Component,
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/array-map-frozen-array.expect.md
+4 -1
@@ -33,7 +33,7 @@ function Component(props) {
33 const x = t0;
34 let t1;
35 if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
36 - const y = x.map((item) => item);
36 + const y = x.map(_temp);
37 t1 = [x, y];
38 $[1] = t1;
39 } else {
@@ -41,6 +41,9 @@ function Component(props) {
41 }
42 return t1;
43 }
44 +function _temp(item) {
45 + return item;
46 +}
47
48 export const FIXTURE_ENTRYPOINT = {
49 fn: Component,
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/array-map-mutable-array-mutating-lambda-noAlias.expect.md
+5 -4
@@ -28,10 +28,7 @@ function Component(props) {
28 let t0;
29 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
30 const x = [];
31 - const y = x.map((item) => {
32 - item.updated = true;
33 - return item;
34 - });
31 + const y = x.map(_temp);
32 t0 = [x, y];
33 $[0] = t0;
34 } else {
@@ -39,6 +36,10 @@ function Component(props) {
36 }
37 return t0;
38 }
39 +function _temp(item) {
40 + item.updated = true;
41 + return item;
42 +}
43
44 export const FIXTURE_ENTRYPOINT = {
45 fn: Component,
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/array-map-mutable-array-mutating-lambda.expect.md
+5 -4
@@ -28,10 +28,7 @@ function Component(props) {
28 let t0;
29 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
30 const x = [];
31 - const y = x.map((item) => {
32 - item.updated = true;
33 - return item;
34 - });
31 + const y = x.map(_temp);
32 t0 = [x, y];
33 $[0] = t0;
34 } else {
@@ -39,6 +36,10 @@ function Component(props) {
36 }
37 return t0;
38 }
39 +function _temp(item) {
40 + item.updated = true;
41 + return item;
42 +}
43
44 export const FIXTURE_ENTRYPOINT = {
45 fn: Component,
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/array-map-mutable-array-non-mutating-lambda-mutated-result.expect.md
+4 -1
@@ -28,7 +28,7 @@ function Component(props) {
28 let t0;
29 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
30 const x = [{}];
31 - const y = x.map((item) => item);
31 + const y = x.map(_temp);
32 y[0].flag = true;
33 t0 = [x, y];
34 $[0] = t0;
@@ -37,6 +37,9 @@ function Component(props) {
37 }
38 return t0;
39 }
40 +function _temp(item) {
41 + return item;
42 +}
43
44 export const FIXTURE_ENTRYPOINT = {
45 fn: Component,
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/array-map-noAlias-escaping-function.expect.md
+17 -21
@@ -21,33 +21,29 @@ export const FIXTURE_ENTRYPOINT = {
21 ```javascript
22 import { c as _c } from "react/compiler-runtime";
23 function Component(props) {
24 - const $ = _c(5);
24 + const $ = _c(4);
25 + const f = _temp;
26 let t0;
26 - if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
27 - t0 = (item) => item;
28 - $[0] = t0;
27 + if ($[0] !== props.items) {
28 + t0 = [...props.items].map(f);
29 + $[0] = props.items;
30 + $[1] = t0;
31 } else {
30 - t0 = $[0];
32 + t0 = $[1];
33 }
32 - const f = t0;
34 + const x = t0;
35 let t1;
34 - if ($[1] !== props.items) {
35 - t1 = [...props.items].map(f);
36 - $[1] = props.items;
37 - $[2] = t1;
36 + if ($[2] !== x) {
37 + t1 = [x, f];
38 + $[2] = x;
39 + $[3] = t1;
40 } else {
39 - t1 = $[2];
41 + t1 = $[3];
42 }
41 - const x = t1;
42 - let t2;
43 - if ($[3] !== x) {
44 - t2 = [x, f];
45 - $[3] = x;
46 - $[4] = t2;
47 - } else {
48 - t2 = $[4];
49 - }
50 - return t2;
43 + return t1;
44 +}
45 +function _temp(item) {
46 + return item;
47 }
48
49 export const FIXTURE_ENTRYPOINT = {
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/arrow-function-one-line-directive.expect.md
+5 -13
@@ -21,22 +21,14 @@ export const FIXTURE_ENTRYPOINT = {
21 ## Code
22
23 ```javascript
24 -import { c as _c } from "react/compiler-runtime";
24 function useFoo() {
26 - const $ = _c(1);
27 - let t0;
28 - if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
29 - t0 = () => {
30 - "worklet";
31 - return 1;
32 - };
33 - $[0] = t0;
34 - } else {
35 - t0 = $[0];
36 - }
37 - const update = t0;
25 + const update = _temp;
26 return update;
27 }
28 +function _temp() {
29 + "worklet";
30 + return 1;
31 +}
32
33 export const FIXTURE_ENTRYPOINT = {
34 fn: useFoo,
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-shadow-captured.expect.md
+5 -13
@@ -16,22 +16,14 @@ function component(a) {
16 ## Code
17
18 ```javascript
19 -import { c as _c } from "react/compiler-runtime";
19 function component(a) {
21 - const $ = _c(1);
22 - let t0;
23 - if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
24 - t0 = function () {
25 - let z_0;
26 - mutate(z_0);
27 - };
28 - $[0] = t0;
29 - } else {
30 - t0 = $[0];
31 - }
32 - const x = t0;
20 + const x = _temp;
21 return x;
22 }
23 +function _temp() {
24 + let z_0;
25 + mutate(z_0);
26 +}
27
28 ```
29
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/component-inner-function-with-many-args.expect.md
+11 -15
@@ -22,24 +22,20 @@ export const FIXTURE_ENTRYPOINT = {
22 import { c as _c } from "react/compiler-runtime";
23 import { Stringify } from "shared-runtime";
24 function Component(props) {
25 - const $ = _c(3);
25 + const $ = _c(2);
26 + const cb = _temp;
27 let t0;
27 - if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
28 - t0 = (x, y, z) => x + y + z;
29 - $[0] = t0;
28 + if ($[0] !== props.id) {
29 + t0 = <Stringify cb={cb} id={props.id} />;
30 + $[0] = props.id;
31 + $[1] = t0;
32 } else {
31 - t0 = $[0];
33 + t0 = $[1];
34 }
33 - const cb = t0;
34 - let t1;
35 - if ($[1] !== props.id) {
36 - t1 = <Stringify cb={cb} id={props.id} />;
37 - $[1] = props.id;
38 - $[2] = t1;
39 - } else {
40 - t1 = $[2];
41 - }
42 - return t1;
35 + return t0;
36 +}
37 +function _temp(x, y, z) {
38 + return x + y + z;
39 }
40
41 export const FIXTURE_ENTRYPOINT = {
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/computed-call-evaluation-order.expect.md
+15 -15
@@ -30,30 +30,30 @@ export const FIXTURE_ENTRYPOINT = {
30 ```javascript
31 import { c as _c } from "react/compiler-runtime"; // Should print A, B, arg, original
32 function Component() {
33 - const $ = _c(2);
34 - let t0;
35 - if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
36 - t0 = (o) => {
37 - o.f = () => console.log("new");
38 - };
39 - $[0] = t0;
40 - } else {
41 - t0 = $[0];
42 - }
43 - const changeF = t0;
33 + const $ = _c(1);
34 + const changeF = _temp2;
35 let x;
45 - if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
46 - x = { f: () => console.log("original") };
36 + if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
37 + x = { f: _temp3 };
38
39 (console.log("A"), x)[(console.log("B"), "f")](
40 (changeF(x), console.log("arg"), 1),
41 );
51 - $[1] = x;
42 + $[0] = x;
43 } else {
53 - x = $[1];
44 + x = $[0];
45 }
46 return x;
47 }
48 +function _temp3() {
49 + return console.log("original");
50 +}
51 +function _temp2(o) {
52 + o.f = _temp;
53 +}
54 +function _temp() {
55 + return console.log("new");
56 +}
57
58 export const FIXTURE_ENTRYPOINT = {
59 fn: Component,
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/constant-prop-colliding-identifier.expect.md
+4 -1
@@ -27,11 +27,14 @@ export const FIXTURE_ENTRYPOINT = {
27 import { invoke } from "shared-runtime";
28
29 function Component() {
30 - const fn = () => ({ x: "value" });
30 + const fn = _temp;
31
32 invoke(fn);
33 return 3;
34 }
35 +function _temp() {
36 + return { x: "value" };
37 +}
38
39 export const FIXTURE_ENTRYPOINT = {
40 fn: Component,
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/deeply-nested-function-expressions-with-params.expect.md
+2 -1
@@ -31,7 +31,7 @@ function Foo() {
31 let t1;
32 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
33 t1 = function a(t2) {
34 - const x_0 = t2 === undefined ? () => {} : t2;
34 + const x_0 = t2 === undefined ? _temp : t2;
35 return (function b(t3) {
36 const y_0 = t3 === undefined ? [] : t3;
37 return [x_0, y_0];
@@ -44,6 +44,7 @@ function Foo() {
44 t0 = t1;
45 return t0;
46 }
47 +function _temp() {}
48
49 export const FIXTURE_ENTRYPOINT = {
50 fn: Foo,
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/default-param-calls-global-function.expect.md
+2 -1
@@ -25,7 +25,7 @@ function Component(t0) {
25 const $ = _c(2);
26 let t1;
27 if ($[0] !== t0) {
28 - t1 = t0 === undefined ? identity([() => {}, true, 42, "hello"]) : t0;
28 + t1 = t0 === undefined ? identity([_temp, true, 42, "hello"]) : t0;
29 $[0] = t0;
30 $[1] = t1;
31 } else {
@@ -34,6 +34,7 @@ function Component(t0) {
34 const x = t1;
35 return x;
36 }
37 +function _temp() {}
38
39 export const FIXTURE_ENTRYPOINT = {
40 fn: Component,
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/default-param-with-empty-callback.expect.md
+2 -11
@@ -16,20 +16,11 @@ export const FIXTURE_ENTRYPOINT = {
16 ## Code
17
18 ```javascript
19 -import { c as _c } from "react/compiler-runtime";
19 function Component(t0) {
21 - const $ = _c(2);
22 - let t1;
23 - if ($[0] !== t0) {
24 - t1 = t0 === undefined ? () => {} : t0;
25 - $[0] = t0;
26 - $[1] = t1;
27 - } else {
28 - t1 = $[1];
29 - }
30 - const x = t1;
20 + const x = t0 === undefined ? _temp : t0;
21 return x;
22 }
23 +function _temp() {}
24
25 export const FIXTURE_ENTRYPOINT = {
26 fn: Component,
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/default-param-with-reorderable-callback.expect.md
+4 -11
@@ -16,20 +16,13 @@ export const FIXTURE_ENTRYPOINT = {
16 ## Code
17
18 ```javascript
19 -import { c as _c } from "react/compiler-runtime";
19 function Component(t0) {
21 - const $ = _c(2);
22 - let t1;
23 - if ($[0] !== t0) {
24 - t1 = t0 === undefined ? () => [-1, true, 42, "hello"] : t0;
25 - $[0] = t0;
26 - $[1] = t1;
27 - } else {
28 - t1 = $[1];
29 - }
30 - const x = t1;
20 + const x = t0 === undefined ? _temp : t0;
21 return x;
22 }
23 +function _temp() {
24 + return [-1, true, 42, "hello"];
25 +}
26
27 export const FIXTURE_ENTRYPOINT = {
28 fn: Component,
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fast-refresh-dont-refresh-const-changes-prod.expect.md
+15 -21
@@ -58,37 +58,31 @@ function unsafeUpdateConst() {
58 }
59
60 function Component() {
61 - const $ = _c(3);
61 + const $ = _c(2);
62 + useState(_temp);
63 +
64 + unsafeUpdateConst();
65 let t0;
66 + let t1;
67 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
64 - t0 = () => {
65 - unsafeResetConst();
66 - };
67 - $[0] = t0;
68 + t1 = [{ pretendConst }];
69 + $[0] = t1;
70 } else {
69 - t0 = $[0];
71 + t1 = $[0];
72 }
71 - useState(t0);
72 -
73 - unsafeUpdateConst();
74 - let t1;
73 + t0 = t1;
74 + const value = t0;
75 let t2;
76 if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
77 - t2 = [{ pretendConst }];
77 + t2 = <ValidateMemoization inputs={[]} output={value} />;
78 $[1] = t2;
79 } else {
80 t2 = $[1];
81 }
82 - t1 = t2;
83 - const value = t1;
84 - let t3;
85 - if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
86 - t3 = <ValidateMemoization inputs={[]} output={value} />;
87 - $[2] = t3;
88 - } else {
89 - t3 = $[2];
90 - }
91 - return t3;
82 + return t2;
83 +}
84 +function _temp() {
85 + unsafeResetConst();
86 }
87
88 export const FIXTURE_ENTRYPOINT = {
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fast-refresh-refresh-on-const-changes-dev.expect.md
+16 -22
@@ -61,45 +61,39 @@ function unsafeUpdateConst() {
61 }
62
63 function Component() {
64 - const $ = _c(4);
64 + const $ = _c(3);
65 if (
66 $[0] !== "4bf230b116dd95f382060ad17350e116395e41ed757e51fd074ea0b4ed281272"
67 ) {
68 - for (let $i = 0; $i < 4; $i += 1) {
68 + for (let $i = 0; $i < 3; $i += 1) {
69 $[$i] = Symbol.for("react.memo_cache_sentinel");
70 }
71 $[0] = "4bf230b116dd95f382060ad17350e116395e41ed757e51fd074ea0b4ed281272";
72 }
73 + useState(_temp);
74 +
75 + unsafeUpdateConst();
76 let t0;
77 + let t1;
78 if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
75 - t0 = () => {
76 - unsafeResetConst();
77 - };
78 - $[1] = t0;
79 + t1 = [{ pretendConst }];
80 + $[1] = t1;
81 } else {
80 - t0 = $[1];
82 + t1 = $[1];
83 }
82 - useState(t0);
83 -
84 - unsafeUpdateConst();
85 - let t1;
84 + t0 = t1;
85 + const value = t0;
86 let t2;
87 if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
88 - t2 = [{ pretendConst }];
88 + t2 = <ValidateMemoization inputs={[pretendConst]} output={value} />;
89 $[2] = t2;
90 } else {
91 t2 = $[2];
92 }
93 - t1 = t2;
94 - const value = t1;
95 - let t3;
96 - if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
97 - t3 = <ValidateMemoization inputs={[pretendConst]} output={value} />;
98 - $[3] = t3;
99 - } else {
100 - t3 = $[3];
101 - }
102 - return t3;
93 + return t2;
94 +}
95 +function _temp() {
96 + unsafeResetConst();
97 }
98
99 export const FIXTURE_ENTRYPOINT = {
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/lambda-with-fbt.expect.md
+27 -33
@@ -42,47 +42,41 @@ import { c as _c } from "react/compiler-runtime";
42 import { fbt } from "fbt";
43
44 function Component() {
45 - const $ = _c(2);
45 + const $ = _c(1);
46 + const buttonLabel = _temp;
47 let t0;
48 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
48 - t0 = () => {
49 - if (!someCondition) {
50 - return fbt._("Purchase as a gift", null, { hk: "1gHj4g" });
51 - } else {
52 - if (
53 - !iconOnly &&
54 - showPrice &&
55 - item?.current_gift_offer?.price?.formatted != null
56 - ) {
57 - return fbt._(
58 - "Gift | {price}",
59 - [fbt._param("price", item?.current_gift_offer?.price?.formatted)],
60 - { hk: "3GTnGE" },
61 - );
62 - } else {
63 - if (!iconOnly && !showPrice) {
64 - return fbt._("Gift", null, { hk: "3fqfrk" });
65 - }
66 - }
67 - }
68 - };
69 - $[0] = t0;
70 - } else {
71 - t0 = $[0];
72 - }
73 - const buttonLabel = t0;
74 - let t1;
75 - if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
76 - t1 = (
49 + t0 = (
50 <View>
51 <Button text={buttonLabel()} />
52 </View>
53 );
81 - $[1] = t1;
54 + $[0] = t0;
55 } else {
83 - t1 = $[1];
56 + t0 = $[0];
57 + }
58 + return t0;
59 +}
60 +function _temp() {
61 + if (!someCondition) {
62 + return fbt._("Purchase as a gift", null, { hk: "1gHj4g" });
63 + } else {
64 + if (
65 + !iconOnly &&
66 + showPrice &&
67 + item?.current_gift_offer?.price?.formatted != null
68 + ) {
69 + return fbt._(
70 + "Gift | {price}",
71 + [fbt._param("price", item?.current_gift_offer?.price?.formatted)],
72 + { hk: "3GTnGE" },
73 + );
74 + } else {
75 + if (!iconOnly && !showPrice) {
76 + return fbt._("Gift", null, { hk: "3fqfrk" });
77 + }
78 + }
79 }
85 - return t1;
80 }
81
82 ```
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/function-expression-with-store-to-parameter.expect.md
+10 -16
@@ -19,29 +19,23 @@ function Component(props) {
19 ```javascript
20 import { c as _c } from "react/compiler-runtime";
21 function Component(props) {
22 - const $ = _c(3);
23 - let t0;
24 - if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
25 - t0 = (object, key, value) => {
26 - object.updated = true;
27 - object[key] = value;
28 - };
29 - $[0] = t0;
30 - } else {
31 - t0 = $[0];
32 - }
33 - const mutate = t0;
22 + const $ = _c(2);
23 + const mutate = _temp;
24 let x;
35 - if ($[1] !== props) {
25 + if ($[0] !== props) {
26 x = makeObject(props);
27 mutate(x);
38 - $[1] = props;
39 - $[2] = x;
28 + $[0] = props;
29 + $[1] = x;
30 } else {
41 - x = $[2];
31 + x = $[1];
32 }
33 return x;
34 }
35 +function _temp(object, key, value) {
36 + object.updated = true;
37 + object[key] = value;
38 +}
39
40 ```
41
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hoisting-nested-const-declaration-2.expect.md
+4 -1
@@ -36,7 +36,7 @@ function hoisting(cond) {
36 items.push(bar());
37 };
38
39 - const bar = () => true;
39 + const bar = _temp;
40 foo();
41 }
42 $[0] = cond;
@@ -46,6 +46,9 @@ function hoisting(cond) {
46 }
47 return items;
48 }
49 +function _temp() {
50 + return true;
51 +}
52
53 export const FIXTURE_ENTRYPOINT = {
54 fn: hoisting,
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hoisting-object-method.expect.md
+4 -1
@@ -36,7 +36,7 @@ function hoisting() {
36 },
37 };
38
39 - const bar = () => 1;
39 + const bar = _temp;
40
41 t0 = x.foo();
42 $[0] = t0;
@@ -45,6 +45,9 @@ function hoisting() {
45 }
46 return t0;
47 }
48 +function _temp() {
49 + return 1;
50 +}
51
52 export const FIXTURE_ENTRYPOINT = {
53 fn: hoisting,
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hoisting-recursive-call-within-lambda.expect.md
+10 -10
@@ -28,18 +28,9 @@ export const FIXTURE_ENTRYPOINT = {
28 import { c as _c } from "react/compiler-runtime";
29 function Foo(t0) {
30 const $ = _c(1);
31 + const outer = _temp;
32 let t1;
33 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
33 - const outer = (val) => {
34 - const fact = (x) => {
35 - if (x <= 0) {
36 - return 1;
37 - }
38 - return x * fact(x - 1);
39 - };
40 - return fact(val);
41 - };
42 -
34 t1 = outer(3);
35 $[0] = t1;
36 } else {
@@ -47,6 +38,15 @@ function Foo(t0) {
38 }
39 return t1;
40 }
41 +function _temp(val) {
42 + const fact = (x) => {
43 + if (x <= 0) {
44 + return 1;
45 + }
46 + return x * fact(x - 1);
47 + };
48 + return fact(val);
49 +}
50
51 export const FIXTURE_ENTRYPOINT = {
52 fn: Foo,
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hoisting-simple-function-expression.expect.md
+4 -1
@@ -31,7 +31,7 @@ function hoisting() {
31 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
32 const foo = () => bar();
33
34 - const bar = () => 1;
34 + const bar = _temp;
35
36 t0 = foo();
37 $[0] = t0;
@@ -40,6 +40,9 @@ function hoisting() {
40 }
41 return t0;
42 }
43 +function _temp() {
44 + return 1;
45 +}
46
47 export const FIXTURE_ENTRYPOINT = {
48 fn: hoisting,
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/hoisting-within-lambda.expect.md
+6 -7
@@ -26,15 +26,9 @@ export const FIXTURE_ENTRYPOINT = {
26 import { c as _c } from "react/compiler-runtime";
27 function Component(t0) {
28 const $ = _c(1);
29 + const outer = _temp;
30 let t1;
31 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
31 - const outer = () => {
32 - const inner = () => x;
33 -
34 - const x = 3;
35 - return inner();
36 - };
37 -
32 t1 = <div>{outer()}</div>;
33 $[0] = t1;
34 } else {
@@ -42,6 +36,11 @@ function Component(t0) {
36 }
37 return t1;
38 }
39 +function _temp() {
40 + const inner = () => x;
41 + const x = 3;
42 + return inner();
43 +}
44
45 export const FIXTURE_ENTRYPOINT = {
46 fn: Component,
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-attribute-with-jsx-element-value.expect.md
+4 -11
@@ -49,17 +49,7 @@ function Component(t0) {
49 let t1;
50 if ($[0] !== items) {
51 t1 =
52 - items.length > 0 ? (
53 - <Foo
54 - value={
55 - <Bar>
56 - {items.map((item) => (
57 - <Item key={item.id} item={item} />
58 - ))}
59 - </Bar>
60 - }
61 - />
62 - ) : null;
52 + items.length > 0 ? <Foo value={<Bar>{items.map(_temp)}</Bar>} /> : null;
53 $[0] = items;
54 $[1] = t1;
55 } else {
@@ -67,6 +57,9 @@ function Component(t0) {
57 }
58 return t1;
59 }
60 +function _temp(item) {
61 + return <Item key={item.id} item={item} />;
62 +}
63
64 function Foo(t0) {
65 const { value } = t0;
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/jsx-attribute-with-jsx-fragment-value.flow.expect.md
+4 -12
@@ -39,18 +39,7 @@ function Component(t0) {
39 const { items } = t0;
40 let t1;
41 if ($[0] !== items) {
42 - t1 =
43 - items.length > 0 ? (
44 - <Foo
45 - value={
46 - <>
47 - {items.map((item) => (
48 - <Stringify key={item.id} item={item} />
49 - ))}
50 - </>
51 - }
52 - />
53 - ) : null;
42 + t1 = items.length > 0 ? <Foo value={<>{items.map(_temp)}</>} /> : null;
43 $[0] = items;
44 $[1] = t1;
45 } else {
@@ -58,6 +47,9 @@ function Component(t0) {
47 }
48 return t1;
49 }
50 +function _temp(item) {
51 + return <Stringify key={item.id} item={item} />;
52 +}
53
54 function Foo(t0) {
55 const $ = _c(2);
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/nested-function-with-param-as-captured-dep.expect.md
+2 -1
@@ -29,7 +29,7 @@ function Foo() {
29 let t1;
30 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
31 t1 = function a(t2) {
32 - const x_0 = t2 === undefined ? () => {} : t2;
32 + const x_0 = t2 === undefined ? _temp : t2;
33 return x_0;
34 };
35 $[0] = t1;
@@ -39,6 +39,7 @@ function Foo() {
39 t0 = t1;
40 return t0;
41 }
42 +function _temp() {}
43
44 export const FIXTURE_ENTRYPOINT = {
45 fn: Foo,
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/noAlias-filter-on-array-prop.expect.md
+5 -9
@@ -33,17 +33,10 @@ export const FIXTURE_ENTRYPOINT = {
33 ```javascript
34 import { c as _c } from "react/compiler-runtime";
35 function Component(props) {
36 - const $ = _c(3);
36 + const $ = _c(2);
37 let t0;
38 if ($[0] !== props.items) {
39 - let t1;
40 - if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
41 - t1 = (item) => item != null;
42 - $[2] = t1;
43 - } else {
44 - t1 = $[2];
45 - }
46 - t0 = props.items.filter(t1);
39 + t0 = props.items.filter(_temp);
40 $[0] = props.items;
41 $[1] = t0;
42 } else {
@@ -52,6 +45,9 @@ function Component(props) {
45 const filtered = t0;
46 return filtered;
47 }
48 +function _temp(item) {
49 + return item != null;
50 +}
51
52 export const FIXTURE_ENTRYPOINT = {
53 fn: Component,
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/optional-call-logical.expect.md
+4 -1
@@ -18,7 +18,7 @@ function Component(props) {
18 const item = useFragment(graphql`...`, props.item);
19 let t0;
20 if ($[0] !== item.items) {
21 - t0 = item.items?.map((item_0) => renderItem(item_0)) ?? [];
21 + t0 = item.items?.map(_temp) ?? [];
22 $[0] = item.items;
23 $[1] = t0;
24 } else {
@@ -26,6 +26,9 @@ function Component(props) {
26 }
27 return t0;
28 }
29 +function _temp(item_0) {
30 + return renderItem(item_0);
31 +}
32
33 ```
34
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/outlined-helper.expect.md
+9 -13
@@ -28,32 +28,28 @@ import { c as _c } from "react/compiler-runtime";
28 import { Stringify } from "shared-runtime";
29
30 function Component(props) {
31 - const $ = _c(5);
31 + const $ = _c(4);
32 let t0;
33 if ($[0] !== props.items) {
34 - let t1;
35 - if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
36 - t1 = (item) => <Stringify key={item.id} item={item.name} />;
37 - $[2] = t1;
38 - } else {
39 - t1 = $[2];
40 - }
41 - t0 = props.items.map(t1);
34 + t0 = props.items.map(_temp);
35 $[0] = props.items;
36 $[1] = t0;
37 } else {
38 t0 = $[1];
39 }
40 let t1;
48 - if ($[3] !== t0) {
41 + if ($[2] !== t0) {
42 t1 = <div>{t0}</div>;
50 - $[3] = t0;
51 - $[4] = t1;
43 + $[2] = t0;
44 + $[3] = t1;
45 } else {
53 - t1 = $[4];
46 + t1 = $[3];
47 }
48 return t1;
49 }
50 +function _temp(item) {
51 + return <Stringify key={item.id} item={item.name} />;
52 +}
53
54 export const FIXTURE_ENTRYPOINT = {
55 fn: Component,
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useCallback-infer-scope-global.expect.md
+5 -10
@@ -22,22 +22,17 @@ export const FIXTURE_ENTRYPOINT = {
22 ## Code
23
24 ```javascript
25 -import { c as _c } from "react/compiler-runtime"; // @validatePreserveExistingMemoizationGuarantees
25 +// @validatePreserveExistingMemoizationGuarantees
26
27 import { useCallback } from "react";
28 import { CONST_STRING0 } from "shared-runtime";
29
30 // It's correct to infer a useCallback block has no reactive dependencies
31 function useFoo() {
32 - const $ = _c(1);
33 - let t0;
34 - if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
35 - t0 = () => [CONST_STRING0];
36 - $[0] = t0;
37 - } else {
38 - t0 = $[0];
39 - }
40 - return t0;
32 + return _temp;
33 +}
34 +function _temp() {
35 + return [CONST_STRING0];
36 }
37
38 export const FIXTURE_ENTRYPOINT = {
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/preserve-memo-validation/useCallback-reordering-deplist-controlflow.expect.md
+11 -14
@@ -40,7 +40,7 @@ import { useCallback } from "react";
40 import { Stringify } from "shared-runtime";
41
42 function Foo(t0) {
43 - const $ = _c(9);
43 + const $ = _c(8);
44 const { arr1, arr2, foo } = t0;
45 let t1;
46 let getVal1;
@@ -49,14 +49,8 @@ function Foo(t0) {
49
50 let y;
51 y = [];
52 - let t2;
53 - if ($[5] === Symbol.for("react.memo_cache_sentinel")) {
54 - t2 = () => ({ x: 2 });
55 - $[5] = t2;
56 - } else {
57 - t2 = $[5];
58 - }
59 - getVal1 = t2;
52 +
53 + getVal1 = _temp;
54
55 t1 = () => [y];
56 foo ? (y = x.concat(arr2)) : y;
@@ -71,16 +65,19 @@ function Foo(t0) {
65 }
66 const getVal2 = t1;
67 let t2;
74 - if ($[6] !== getVal1 || $[7] !== getVal2) {
68 + if ($[5] !== getVal1 || $[6] !== getVal2) {
69 t2 = <Stringify val1={getVal1} val2={getVal2} shouldInvokeFns={true} />;
76 - $[6] = getVal1;
77 - $[7] = getVal2;
78 - $[8] = t2;
70 + $[5] = getVal1;
71 + $[6] = getVal2;
72 + $[7] = t2;
73 } else {
80 - t2 = $[8];
74 + t2 = $[7];
75 }
76 return t2;
77 }
78 +function _temp() {
79 + return { x: 2 };
80 +}
81
82 export const FIXTURE_ENTRYPOINT = {
83 fn: Foo,
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/property-call-evaluation-order.expect.md
+15 -15
@@ -30,28 +30,28 @@ export const FIXTURE_ENTRYPOINT = {
30 import { c as _c } from "react/compiler-runtime"; // Should print A, arg, original
31
32 function Component() {
33 - const $ = _c(2);
34 - let t0;
35 - if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
36 - t0 = (o) => {
37 - o.f = () => console.log("new");
38 - };
39 - $[0] = t0;
40 - } else {
41 - t0 = $[0];
42 - }
43 - const changeF = t0;
33 + const $ = _c(1);
34 + const changeF = _temp2;
35 let x;
45 - if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
46 - x = { f: () => console.log("original") };
36 + if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
37 + x = { f: _temp3 };
38
39 (console.log("A"), x).f((changeF(x), console.log("arg"), 1));
49 - $[1] = x;
40 + $[0] = x;
41 } else {
51 - x = $[1];
42 + x = $[0];
43 }
44 return x;
45 }
46 +function _temp3() {
47 + return console.log("original");
48 +}
49 +function _temp2(o) {
50 + o.f = _temp;
51 +}
52 +function _temp() {
53 + return console.log("new");
54 +}
55
56 export const FIXTURE_ENTRYPOINT = {
57 fn: Component,
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/readonly-object-method-calls.expect.md
+4 -1
@@ -30,7 +30,7 @@ function Component(props) {
30 );
31 let posts;
32 if ($[0] !== user.timeline.posts.edges.nodes) {
33 - posts = user.timeline.posts.edges.nodes.map((node) => <Post post={node} />);
33 + posts = user.timeline.posts.edges.nodes.map(_temp);
34 let t0;
35 if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
36 t0 = {};
@@ -56,6 +56,9 @@ function Component(props) {
56 }
57 return t0;
58 }
59 +function _temp(node) {
60 + return <Post post={node} />;
61 +}
62
63 ```
64
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ref-like-name-in-effect.expect.md
+2 -1
@@ -37,13 +37,14 @@ function useCustomRef() {
37 const $ = _c(1);
38 let t0;
39 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
40 - t0 = { click: () => {} };
40 + t0 = { click: _temp };
41 $[0] = t0;
42 } else {
43 t0 = $[0];
44 }
45 return useRef(t0);
46 }
47 +function _temp() {}
48
49 function Foo() {
50 const $ = _c(3);
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ref-like-name-in-useCallback-2.expect.md
+2 -1
@@ -37,13 +37,14 @@ function useCustomRef() {
37 const $ = _c(1);
38 let t0;
39 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
40 - t0 = { click: () => {} };
40 + t0 = { click: _temp };
41 $[0] = t0;
42 } else {
43 t0 = $[0];
44 }
45 return useRef(t0);
46 }
47 +function _temp() {}
48
49 function Foo() {
50 const $ = _c(3);
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ref-like-name-in-useCallback.expect.md
+2 -1
@@ -37,13 +37,14 @@ function useCustomRef() {
37 const $ = _c(1);
38 let t0;
39 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
40 - t0 = { click: () => {} };
40 + t0 = { click: _temp };
41 $[0] = t0;
42 } else {
43 t0 = $[0];
44 }
45 return useRef(t0);
46 }
47 +function _temp() {}
48
49 function Foo() {
50 const $ = _c(3);
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-dont-memoize-array-with-capturing-map-after-hook.expect.md
+14 -17
@@ -39,48 +39,45 @@ import { useEffect, useState } from "react";
39 import { mutate } from "shared-runtime";
40
41 function Component(props) {
42 - const $ = _c(6);
42 + const $ = _c(5);
43 const x = [{ ...props.value }];
44 let t0;
45 - let t1;
45 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
47 - t0 = () => {};
48 - t1 = [];
46 + t0 = [];
47 $[0] = t0;
50 - $[1] = t1;
48 } else {
49 t0 = $[0];
53 - t1 = $[1];
50 }
55 - useEffect(t0, t1);
51 + useEffect(_temp, t0);
52 const onClick = () => {
53 console.log(x.length);
54 };
55
56 let y;
57
62 - const t2 = x.map((item) => {
58 + const t1 = x.map((item) => {
59 y = item;
60 return <span key={item.id}>{item.text}</span>;
61 });
66 - const t3 = mutate(y);
67 - let t4;
68 - if ($[2] !== onClick || $[3] !== t2 || $[4] !== t3) {
69 - t4 = (
62 + const t2 = mutate(y);
63 + let t3;
64 + if ($[1] !== onClick || $[2] !== t1 || $[3] !== t2) {
65 + t3 = (
66 <div onClick={onClick}>
67 + {t1}
68 {t2}
72 - {t3}
69 </div>
70 );
75 - $[2] = onClick;
71 + $[1] = onClick;
72 + $[2] = t1;
73 $[3] = t2;
74 $[4] = t3;
78 - $[5] = t4;
75 } else {
80 - t4 = $[5];
76 + t3 = $[4];
77 }
82 - return t4;
78 + return t3;
79 }
80 +function _temp() {}
81
82 export const FIXTURE_ENTRYPOINT = {
83 fn: Component,
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-dont-memoize-array-with-mutable-map-after-hook.expect.md
+23 -25
@@ -39,55 +39,53 @@ import { useEffect, useState } from "react";
39 import { mutate } from "shared-runtime";
40
41 function Component(props) {
42 - const $ = _c(8);
42 + const $ = _c(7);
43 const x = [{ ...props.value }];
44 let t0;
45 - let t1;
45 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
47 - t0 = () => {};
48 - t1 = [];
46 + t0 = [];
47 $[0] = t0;
50 - $[1] = t1;
48 } else {
49 t0 = $[0];
53 - t1 = $[1];
50 }
55 - useEffect(t0, t1);
51 + useEffect(_temp, t0);
52 const onClick = () => {
53 console.log(x.length);
54 };
55
56 let y;
57
62 - const t2 = x.map((item) => {
63 - item.flag = true;
64 - return <span key={item.id}>{item.text}</span>;
65 - });
66 - let t3;
67 - if ($[2] !== y) {
68 - t3 = mutate(y);
69 - $[2] = y;
70 - $[3] = t3;
58 + const t1 = x.map(_temp2);
59 + let t2;
60 + if ($[1] !== y) {
61 + t2 = mutate(y);
62 + $[1] = y;
63 + $[2] = t2;
64 } else {
72 - t3 = $[3];
65 + t2 = $[2];
66 }
74 - let t4;
75 - if ($[4] !== onClick || $[5] !== t2 || $[6] !== t3) {
76 - t4 = (
67 + let t3;
68 + if ($[3] !== onClick || $[4] !== t1 || $[5] !== t2) {
69 + t3 = (
70 <div onClick={onClick}>
71 + {t1}
72 {t2}
79 - {t3}
73 </div>
74 );
82 - $[4] = onClick;
75 + $[3] = onClick;
76 + $[4] = t1;
77 $[5] = t2;
78 $[6] = t3;
85 - $[7] = t4;
79 } else {
87 - t4 = $[7];
80 + t3 = $[6];
81 }
89 - return t4;
82 + return t3;
83 +}
84 +function _temp2(item) {
85 + item.flag = true;
86 + return <span key={item.id}>{item.text}</span>;
87 }
88 +function _temp() {}
89
90 export const FIXTURE_ENTRYPOINT = {
91 fn: Component,
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-hoisting-variable-collision.expect.md
+9 -13
@@ -20,17 +20,10 @@ export const FIXTURE_ENTRYPOINT = {
20 ```javascript
21 import { c as _c } from "react/compiler-runtime";
22 function Component(props) {
23 - const $ = _c(5);
23 + const $ = _c(4);
24 let t0;
25 if ($[0] !== props.items) {
26 - let t1;
27 - if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
28 - t1 = (x) => x;
29 - $[2] = t1;
30 - } else {
31 - t1 = $[2];
32 - }
33 - t0 = props.items.map(t1);
26 + t0 = props.items.map(_temp);
27 $[0] = props.items;
28 $[1] = t0;
29 } else {
@@ -38,15 +31,18 @@ function Component(props) {
31 }
32 const items = t0;
33 let t1;
41 - if ($[3] !== items) {
34 + if ($[2] !== items) {
35 t1 = [42, items];
43 - $[3] = items;
44 - $[4] = t1;
36 + $[2] = items;
37 + $[3] = t1;
38 } else {
46 - t1 = $[4];
39 + t1 = $[3];
40 }
41 return t1;
42 }
43 +function _temp(x) {
44 + return x;
45 +}
46
47 export const FIXTURE_ENTRYPOINT = {
48 fn: Component,
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-hoisting.expect.md
+13 -19
@@ -26,35 +26,29 @@ export const FIXTURE_ENTRYPOINT = {
26 ```javascript
27 import { c as _c } from "react/compiler-runtime";
28 function Component(props) {
29 - const $ = _c(4);
29 + const $ = _c(3);
30 + const wat = _temp;
31 +
32 + const pathname_0 = props.wat;
33 + const deeplinkItemId = pathname_0 ? props.itemID : null;
34 let t0;
35 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
32 - t0 = () => {};
36 + t0 = () => wat();
37 $[0] = t0;
38 } else {
39 t0 = $[0];
40 }
37 - const wat = t0;
38 -
39 - const pathname_0 = props.wat;
40 - const deeplinkItemId = pathname_0 ? props.itemID : null;
41 let t1;
42 - if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
43 - t1 = () => wat();
44 - $[1] = t1;
45 - } else {
46 - t1 = $[1];
47 - }
48 - let t2;
49 - if ($[2] !== deeplinkItemId) {
50 - t2 = <button onClick={t1}>{deeplinkItemId}</button>;
51 - $[2] = deeplinkItemId;
52 - $[3] = t2;
42 + if ($[1] !== deeplinkItemId) {
43 + t1 = <button onClick={t0}>{deeplinkItemId}</button>;
44 + $[1] = deeplinkItemId;
45 + $[2] = t1;
46 } else {
54 - t2 = $[3];
47 + t1 = $[2];
48 }
56 - return t2;
49 + return t1;
50 }
51 +function _temp() {}
52
53 export const FIXTURE_ENTRYPOINT = {
54 fn: Component,
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-memoize-array-with-immutable-map-after-hook.expect.md
+27 -27
@@ -34,7 +34,7 @@ import { c as _c } from "react/compiler-runtime";
34 import { useEffect, useState } from "react";
35
36 function Component(props) {
37 - const $ = _c(11);
37 + const $ = _c(10);
38 let t0;
39 if ($[0] !== props.value) {
40 t0 = [props.value];
@@ -45,47 +45,47 @@ function Component(props) {
45 }
46 const x = t0;
47 let t1;
48 - let t2;
48 if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
50 - t1 = () => {};
51 - t2 = [];
49 + t1 = [];
50 $[2] = t1;
53 - $[3] = t2;
51 } else {
52 t1 = $[2];
56 - t2 = $[3];
53 }
58 - useEffect(t1, t2);
59 - let t3;
60 - if ($[4] !== x.length) {
61 - t3 = () => {
54 + useEffect(_temp, t1);
55 + let t2;
56 + if ($[3] !== x.length) {
57 + t2 = () => {
58 console.log(x.length);
59 };
64 - $[4] = x.length;
65 - $[5] = t3;
60 + $[3] = x.length;
61 + $[4] = t2;
62 } else {
67 - t3 = $[5];
63 + t2 = $[4];
64 }
69 - const onClick = t3;
70 - let t4;
71 - if ($[6] !== x) {
72 - t4 = x.map((item) => <span key={item}>{item}</span>);
73 - $[6] = x;
74 - $[7] = t4;
65 + const onClick = t2;
66 + let t3;
67 + if ($[5] !== x) {
68 + t3 = x.map(_temp2);
69 + $[5] = x;
70 + $[6] = t3;
71 } else {
76 - t4 = $[7];
72 + t3 = $[6];
73 }
78 - let t5;
79 - if ($[8] !== onClick || $[9] !== t4) {
80 - t5 = <div onClick={onClick}>{t4}</div>;
81 - $[8] = onClick;
74 + let t4;
75 + if ($[7] !== onClick || $[8] !== t3) {
76 + t4 = <div onClick={onClick}>{t3}</div>;
77 + $[7] = onClick;
78 + $[8] = t3;
79 $[9] = t4;
83 - $[10] = t5;
80 } else {
85 - t5 = $[10];
81 + t4 = $[9];
82 }
87 - return t5;
83 + return t4;
84 +}
85 +function _temp2(item) {
86 + return <span key={item}>{item}</span>;
87 }
88 +function _temp() {}
89
90 export const FIXTURE_ENTRYPOINT = {
91 fn: Component,
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-mutable-range-extending-into-ternary.expect.md
+4 -9
@@ -57,15 +57,10 @@ import { useState } from "react";
57 function Component(props) {
58 const items = props.items ? props.items.slice() : [];
59 const [state] = useState("");
60 - return props.cond ? (
61 - <div>{state}</div>
62 - ) : (
63 - <div>
64 - {items.map((item) => (
65 - <div key={item.id}>{item.name}</div>
66 - ))}
67 - </div>
68 - );
60 + return props.cond ? <div>{state}</div> : <div>{items.map(_temp)}</div>;
61 +}
62 +function _temp(item) {
63 + return <div key={item.id}>{item.name}</div>;
64 }
65
66 export const FIXTURE_ENTRYPOINT = {
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-no-declarations-in-reactive-scope-with-early-return.expect.md
+11 -16
@@ -39,7 +39,7 @@ function Component() {
39 ```javascript
40 import { c as _c } from "react/compiler-runtime"; // @enableAssumeHooksFollowRulesOfReact @enableTransitivelyFreezeFunctionExpressions
41 function Component() {
42 - const $ = _c(9);
42 + const $ = _c(8);
43 const items = useItems();
44 let t0;
45 let t1;
@@ -74,17 +74,8 @@ function Component() {
74 t2 = t4;
75 break bb0;
76 }
77 - let t4;
78 - if ($[6] === Symbol.for("react.memo_cache_sentinel")) {
79 - t4 = (t5) => {
80 - const [item_0] = t5;
81 - return <Stringify item={item_0} />;
82 - };
83 - $[6] = t4;
84 - } else {
85 - t4 = $[6];
86 - }
87 - t1 = filteredItems.map(t4);
77 +
78 + t1 = filteredItems.map(_temp);
79 }
80 $[0] = items;
81 $[1] = t1;
@@ -99,15 +90,19 @@ function Component() {
90 return t2;
91 }
92 let t3;
102 - if ($[7] !== t1) {
93 + if ($[6] !== t1) {
94 t3 = <>{t1}</>;
104 - $[7] = t1;
105 - $[8] = t3;
95 + $[6] = t1;
96 + $[7] = t3;
97 } else {
107 - t3 = $[8];
98 + t3 = $[7];
99 }
100 return t3;
101 }
102 +function _temp(t0) {
103 + const [item_0] = t0;
104 + return <Stringify item={item_0} />;
105 +}
106
107 ```
108
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-undefined-expression-of-jsxexpressioncontainer.expect.md
+17 -23
@@ -48,7 +48,7 @@ import { c as _c } from "react/compiler-runtime";
48 import { StaticText1, Stringify, Text } from "shared-runtime";
49
50 function Component(props) {
51 - const $ = _c(7);
51 + const $ = _c(6);
52 const { buttons } = props;
53 let nonPrimaryButtons;
54 if ($[0] !== buttons) {
@@ -61,24 +61,7 @@ function Component(props) {
61 }
62 let t0;
63 if ($[2] !== nonPrimaryButtons) {
64 - let t1;
65 - if ($[4] === Symbol.for("react.memo_cache_sentinel")) {
66 - t1 = (buttonProps, i) => (
67 - <Stringify
68 - {...buttonProps}
69 - key={`button-${i}`}
70 - style={
71 - i % 2 === 0
72 - ? styles.leftSecondaryButton
73 - : styles.rightSecondaryButton
74 - }
75 - />
76 - );
77 - $[4] = t1;
78 - } else {
79 - t1 = $[4];
80 - }
81 - t0 = nonPrimaryButtons.map(t1);
64 + t0 = nonPrimaryButtons.map(_temp);
65 $[2] = nonPrimaryButtons;
66 $[3] = t0;
67 } else {
@@ -86,15 +69,26 @@ function Component(props) {
69 }
70 const renderedNonPrimaryButtons = t0;
71 let t1;
89 - if ($[5] !== renderedNonPrimaryButtons) {
72 + if ($[4] !== renderedNonPrimaryButtons) {
73 t1 = <StaticText1>{renderedNonPrimaryButtons}</StaticText1>;
91 - $[5] = renderedNonPrimaryButtons;
92 - $[6] = t1;
74 + $[4] = renderedNonPrimaryButtons;
75 + $[5] = t1;
76 } else {
94 - t1 = $[6];
77 + t1 = $[5];
78 }
79 return t1;
80 }
81 +function _temp(buttonProps, i) {
82 + return (
83 + <Stringify
84 + {...buttonProps}
85 + key={`button-${i}`}
86 + style={
87 + i % 2 === 0 ? styles.leftSecondaryButton : styles.rightSecondaryButton
88 + }
89 + />
90 + );
91 +}
92
93 const styles = {
94 leftSecondaryButton: { left: true },
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/rules-of-hooks/rules-of-hooks-93dc5d5e538a.expect.md
+4 -10
@@ -17,22 +17,16 @@ function RegressionTest() {
17 ## Code
18
19 ```javascript
20 -import { c as _c } from "react/compiler-runtime"; // Valid because the loop doesn't change the order of hooks calls.
20 +// Valid because the loop doesn't change the order of hooks calls.
21 function RegressionTest() {
22 - const $ = _c(1);
22 const res = [];
23 for (let i = 0; i !== 10 && true; ++i) {
24 res.push(i);
25 }
27 - let t0;
28 - if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
29 - t0 = () => {};
30 - $[0] = t0;
31 - } else {
32 - t0 = $[0];
33 - }
34 - React.useLayoutEffect(t0);
26 +
27 + React.useLayoutEffect(_temp);
28 }
29 +function _temp() {}
30
31 ```
32
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/simple-function-1.expect.md
+4 -12
@@ -20,21 +20,13 @@ export const FIXTURE_ENTRYPOINT = {
20 ## Code
21
22 ```javascript
23 -import { c as _c } from "react/compiler-runtime";
23 function component() {
25 - const $ = _c(1);
26 - let t0;
27 - if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
28 - t0 = function (a) {
29 - a.foo();
30 - };
31 - $[0] = t0;
32 - } else {
33 - t0 = $[0];
34 - }
35 - const x = t0;
24 + const x = _temp;
25 return x;
26 }
27 +function _temp(a) {
28 + a.foo();
29 +}
30
31 export const FIXTURE_ENTRYPOINT = {
32 fn: component,
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/todo.unnecessary-lambda-memoization.expect.md
+9 -13
@@ -24,18 +24,11 @@ function Component(props) {
24 ```javascript
25 import { c as _c } from "react/compiler-runtime";
26 function Component(props) {
27 - const $ = _c(5);
27 + const $ = _c(4);
28 const data = useFreeze();
29 let t0;
30 if ($[0] !== data.items) {
31 - let t1;
32 - if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
33 - t1 = (item) => <Item item={item} />;
34 - $[2] = t1;
35 - } else {
36 - t1 = $[2];
37 - }
38 - t0 = data.items.map(t1);
31 + t0 = data.items.map(_temp);
32 $[0] = data.items;
33 $[1] = t0;
34 } else {
@@ -43,15 +36,18 @@ function Component(props) {
36 }
37 const items = t0;
38 let t1;
46 - if ($[3] !== items) {
39 + if ($[2] !== items) {
40 t1 = <div>{items}</div>;
48 - $[3] = items;
49 - $[4] = t1;
41 + $[2] = items;
42 + $[3] = t1;
43 } else {
51 - t1 = $[4];
44 + t1 = $[3];
45 }
46 return t1;
47 }
48 +function _temp(item) {
49 + return <Item item={item} />;
50 +}
51
52 ```
53
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/transitive-freeze-function-expressions.expect.md
+5 -9
@@ -33,7 +33,7 @@ function Component(props) {
33 ```javascript
34 import { c as _c } from "react/compiler-runtime"; // @enableTransitivelyFreezeFunctionExpressions
35 function Component(props) {
36 - const $ = _c(10);
36 + const $ = _c(9);
37 const { data, loadNext, isLoadingNext } =
38 usePaginationFragment(props.key).items ?? [];
39 let t0;
@@ -74,14 +74,7 @@ function Component(props) {
74 useEffect(t1, t2);
75 let t3;
76 if ($[7] !== data) {
77 - let t4;
78 - if ($[9] === Symbol.for("react.memo_cache_sentinel")) {
79 - t4 = (x) => x;
80 - $[9] = t4;
81 - } else {
82 - t4 = $[9];
83 - }
84 - t3 = data.map(t4);
77 + t3 = data.map(_temp);
78 $[7] = data;
79 $[8] = t3;
80 } else {
@@ -90,6 +83,9 @@ function Component(props) {
83 const items = t3;
84 return items;
85 }
86 +function _temp(x) {
87 + return x;
88 +}
89
90 ```
91
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/try-catch-within-function-expression.expect.md
+8 -8
@@ -26,16 +26,9 @@ export const FIXTURE_ENTRYPOINT = {
26 import { c as _c } from "react/compiler-runtime";
27 function Component(props) {
28 const $ = _c(1);
29 + const callback = _temp;
30 let t0;
31 if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
31 - const callback = () => {
32 - try {
33 - return [];
34 - } catch (t1) {
35 - return;
36 - }
37 - };
38 -
32 t0 = callback();
33 $[0] = t0;
34 } else {
@@ -43,6 +36,13 @@ function Component(props) {
36 }
37 return t0;
38 }
39 +function _temp() {
40 + try {
41 + return [];
42 + } catch (t0) {
43 + return;
44 + }
45 +}
46
47 export const FIXTURE_ENTRYPOINT = {
48 fn: Component,
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/type-alias-used-as-annotation.expect.md
+4 -3
@@ -25,12 +25,13 @@ export const FIXTURE_ENTRYPOINT = {
25 // @enableAssumeHooksFollowRulesOfReact @enableTransitivelyFreezeFunctionExpressions
26 type Bar = string;
27 function TypeAliasUsedAsParamAnnotation() {
28 - const fun = (f) => {
29 - console.log(f);
30 - };
28 + const fun = _temp;
29
30 fun("hello, world");
31 }
32 +function _temp(f) {
33 + console.log(f);
34 +}
35
36 export const FIXTURE_ENTRYPOINT = {
37 fn: TypeAliasUsedAsParamAnnotation,
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/type-alias-used-as-annotation_.flow.expect.md
+4 -3
@@ -23,12 +23,13 @@ export const FIXTURE_ENTRYPOINT = {
23 ```javascript
24 type Bar = string;
25 function TypeAliasUsedAsAnnotation() {
26 - const fun = (f) => {
27 - console.log(f);
28 - };
26 + const fun = _temp;
27
28 fun("hello, world");
29 }
30 +function _temp(f) {
31 + console.log(f);
32 +}
33
34 export const FIXTURE_ENTRYPOINT = {
35 fn: TypeAliasUsedAsAnnotation,
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/type-alias-used-as-variable-annotation.expect.md
+5 -4
@@ -26,13 +26,14 @@ export const FIXTURE_ENTRYPOINT = {
26 // @enableAssumeHooksFollowRulesOfReact @enableTransitivelyFreezeFunctionExpressions
27 type Bar = string;
28 function TypeAliasUsedAsVariableAnnotation() {
29 - const fun = (f) => {
30 - const g = f;
31 - console.log(g);
32 - };
29 + const fun = _temp;
30
31 fun("hello, world");
32 }
33 +function _temp(f) {
34 + const g = f;
35 + console.log(g);
36 +}
37
38 export const FIXTURE_ENTRYPOINT = {
39 fn: TypeAliasUsedAsVariableAnnotation,
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/type-alias-used-as-variable-annotation_.flow.expect.md
+5 -4
@@ -25,13 +25,14 @@ export const FIXTURE_ENTRYPOINT = {
25 ```javascript
26 type Bar = string;
27 function TypeAliasUsedAsAnnotation() {
28 - const fun = (f) => {
29 - const g = f;
30 - console.log(g);
31 - };
28 + const fun = _temp;
29
30 fun("hello, world");
31 }
32 +function _temp(f) {
33 + const g = f;
34 + console.log(g);
35 +}
36
37 export const FIXTURE_ENTRYPOINT = {
38 fn: TypeAliasUsedAsAnnotation,
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/type-annotations/todo_type-annotations-props.expect.md
+5 -9
@@ -22,17 +22,10 @@ export const FIXTURE_ENTRYPOINT = {
22 ```javascript
23 import { c as _c } from "react/compiler-runtime"; // @enableUseTypeAnnotations
24 function useArray(items) {
25 - const $ = _c(3);
25 + const $ = _c(2);
26 let t0;
27 if ($[0] !== items) {
28 - let t1;
29 - if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
30 - t1 = (x) => x !== 0;
31 - $[2] = t1;
32 - } else {
33 - t1 = $[2];
34 - }
35 - t0 = items.filter(t1);
28 + t0 = items.filter(_temp);
29 $[0] = items;
30 $[1] = t0;
31 } else {
@@ -40,6 +33,9 @@ function useArray(items) {
33 }
34 return t0;
35 }
36 +function _temp(x) {
37 + return x !== 0;
38 +}
39
40 export const FIXTURE_ENTRYPOINT = {
41 fn: useArray,
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useEffect-external-mutate.expect.md
+4 -12
@@ -22,23 +22,15 @@ export const FIXTURE_ENTRYPOINT = {
22 ## Code
23
24 ```javascript
25 -import { c as _c } from "react/compiler-runtime";
25 import { useEffect } from "react";
26
27 let x = { a: 42 };
28
29 function Component(props) {
31 - const $ = _c(1);
32 - let t0;
33 - if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
34 - t0 = () => {
35 - x.a = 10;
36 - };
37 - $[0] = t0;
38 - } else {
39 - t0 = $[0];
40 - }
41 - useEffect(t0);
30 + useEffect(_temp);
31 +}
32 +function _temp() {
33 + x.a = 10;
34 }
35
36 export const FIXTURE_ENTRYPOINT = {
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useEffect-global-pruned.expect.md
+12 -18
@@ -36,35 +36,29 @@ import { useEffect } from "react";
36
37 function someGlobal() {}
38 function useFoo() {
39 - const $ = _c(3);
39 + const $ = _c(2);
40 let t0;
41 - let t1;
42 - if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
43 - t1 = function () {
44 - someGlobal();
45 - };
46 - $[0] = t1;
47 - } else {
48 - t1 = $[0];
49 - }
50 - t0 = t1;
41 + t0 = _temp;
42 const fn = t0;
43 + let t1;
44 let t2;
53 - let t3;
54 - if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
55 - t2 = () => {
45 + if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
46 + t1 = () => {
47 fn();
48 };
58 - t3 = [fn];
49 + t2 = [fn];
50 + $[0] = t1;
51 $[1] = t2;
60 - $[2] = t3;
52 } else {
53 + t1 = $[0];
54 t2 = $[1];
63 - t3 = $[2];
55 }
65 - useEffect(t2, t3);
56 + useEffect(t1, t2);
57 return null;
58 }
59 +function _temp() {
60 + someGlobal();
61 +}
62
63 export const FIXTURE_ENTRYPOINT = {
64 fn: useFoo,
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useEffect-method-call.expect.md
+4 -12
@@ -19,20 +19,12 @@ export const FIXTURE_ENTRYPOINT = {
19 ## Code
20
21 ```javascript
22 -import { c as _c } from "react/compiler-runtime";
22 let x = {};
23 function Component() {
25 - const $ = _c(1);
26 - let t0;
27 - if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
28 - t0 = () => {
29 - x.foo = 1;
30 - };
31 - $[0] = t0;
32 - } else {
33 - t0 = $[0];
34 - }
35 - React.useEffect(t0);
24 + React.useEffect(_temp);
25 +}
26 +function _temp() {
27 + x.foo = 1;
28 }
29
30 export const FIXTURE_ENTRYPOINT = {
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/useEffect-namespace-pruned.expect.md
+12 -18
@@ -36,35 +36,29 @@ import * as React from "react";
36
37 function someGlobal() {}
38 function useFoo() {
39 - const $ = _c(3);
39 + const $ = _c(2);
40 let t0;
41 - let t1;
42 - if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
43 - t1 = function () {
44 - someGlobal();
45 - };
46 - $[0] = t1;
47 - } else {
48 - t1 = $[0];
49 - }
50 - t0 = t1;
41 + t0 = _temp;
42 const fn = t0;
43 + let t1;
44 let t2;
53 - let t3;
54 - if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
55 - t2 = () => {
45 + if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
46 + t1 = () => {
47 fn();
48 };
58 - t3 = [fn];
49 + t2 = [fn];
50 + $[0] = t1;
51 $[1] = t2;
60 - $[2] = t3;
52 } else {
53 + t1 = $[0];
54 t2 = $[1];
63 - t3 = $[2];
55 }
65 - React.useEffect(t2, t3);
56 + React.useEffect(t1, t2);
57 return null;
58 }
59 +function _temp() {
60 + someGlobal();
61 +}
62
63 export const FIXTURE_ENTRYPOINT = {
64 fn: useFoo,
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/value-block-mutates-outer-value.expect.md
+4 -10
@@ -34,7 +34,6 @@ export const FIXTURE_ENTRYPOINT = {
34 ## Code
35
36 ```javascript
37 -import { c as _c } from "react/compiler-runtime";
37 import { makeArray, useHook } from "shared-runtime";
38
39 /**
@@ -46,16 +45,8 @@ import { makeArray, useHook } from "shared-runtime";
45 * merged with the scope producing customList
46 */
47 function Foo(t0) {
49 - const $ = _c(1);
48 const { defaultList, cond } = t0;
51 - let t1;
52 - if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
53 - t1 = (a, b) => a - b;
54 - $[0] = t1;
55 - } else {
56 - t1 = $[0];
57 - }
58 - const comparator = t1;
49 + const comparator = _temp;
50 useHook();
51 const customList = makeArray(1, 5, 2);
52 useHook();
@@ -64,6 +55,9 @@ function Foo(t0) {
55 : defaultList;
56 return result;
57 }
58 +function _temp(a, b) {
59 + return a - b;
60 +}
61
62 export const FIXTURE_ENTRYPOINT = {
63 fn: Foo,