Skip to content

Commit 2c6d92f

Browse files
authored
[compiler] Name anonymous functions from inlined useCallbacks (#34586)
@eps1lon flagged this case. Inlined useCallback has an extra LoadLocal indirection which caused us not to add a name. While I was there I added some extra checks to make sure we don't generate names for a given node twice (just in case).
1 parent e233218 commit 2c6d92f

File tree

3 files changed

+60
-33
lines changed

3 files changed

+60
-33
lines changed

compiler/packages/babel-plugin-react-compiler/src/Transform/NameAnonymousFunctions.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export function nameAnonymousFunctions(fn: HIRFunction): void {
1919
const parentName = fn.id;
2020
const functions = nameAnonymousFunctionsImpl(fn);
2121
function visit(node: Node, prefix: string): void {
22-
if (node.generatedName != null) {
22+
if (node.generatedName != null && node.fn.nameHint == null) {
2323
/**
2424
* Note that we don't generate a name for functions that already had one,
2525
* so we'll only add the prefix to anonymous functions regardless of
@@ -70,6 +70,10 @@ function nameAnonymousFunctionsImpl(fn: HIRFunction): Array<Node> {
7070
if (name != null && name.kind === 'named') {
7171
names.set(lvalue.identifier.id, name.value);
7272
}
73+
const func = functions.get(value.place.identifier.id);
74+
if (func != null) {
75+
functions.set(lvalue.identifier.id, func);
76+
}
7377
break;
7478
}
7579
case 'PropertyLoad': {
@@ -106,6 +110,7 @@ function nameAnonymousFunctionsImpl(fn: HIRFunction): Array<Node> {
106110
const variableName = value.lvalue.place.identifier.name;
107111
if (
108112
node != null &&
113+
node.generatedName == null &&
109114
variableName != null &&
110115
variableName.kind === 'named'
111116
) {
@@ -137,7 +142,7 @@ function nameAnonymousFunctionsImpl(fn: HIRFunction): Array<Node> {
137142
continue;
138143
}
139144
const node = functions.get(arg.identifier.id);
140-
if (node != null) {
145+
if (node != null && node.generatedName == null) {
141146
const generatedName =
142147
fnArgCount > 1 ? `${calleeName}(arg${i})` : `${calleeName}()`;
143148
node.generatedName = generatedName;
@@ -152,7 +157,7 @@ function nameAnonymousFunctionsImpl(fn: HIRFunction): Array<Node> {
152157
continue;
153158
}
154159
const node = functions.get(attr.place.identifier.id);
155-
if (node != null) {
160+
if (node != null && node.generatedName == null) {
156161
const elementName =
157162
value.tag.kind === 'BuiltinTag'
158163
? value.tag.name

compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/name-anonymous-functions.expect.md

Lines changed: 45 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,19 @@
44
```javascript
55
// @enableNameAnonymousFunctions
66

7-
import {useEffect} from 'react';
7+
import {useCallback, useEffect} from 'react';
88
import {identity, Stringify, useIdentity} from 'shared-runtime';
99
import * as SharedRuntime from 'shared-runtime';
1010

1111
function Component(props) {
1212
function named() {
1313
const inner = () => props.named;
14-
return inner();
14+
const innerIdentity = identity(() => props.named);
15+
return inner(innerIdentity());
1516
}
17+
const callback = useCallback(() => {
18+
return 'ok';
19+
}, []);
1620
const namedVariable = function () {
1721
return props.namedVariable;
1822
};
@@ -30,6 +34,7 @@ function Component(props) {
3034
return (
3135
<>
3236
{named()}
37+
{callback()}
3338
{namedVariable()}
3439
{methodCall()}
3540
{call()}
@@ -63,7 +68,7 @@ export const TODO_FIXTURE_ENTRYPOINT = {
6368
```javascript
6469
import { c as _c } from "react/compiler-runtime"; // @enableNameAnonymousFunctions
6570

66-
import { useEffect } from "react";
71+
import { useCallback, useEffect } from "react";
6772
import { identity, Stringify, useIdentity } from "shared-runtime";
6873
import * as SharedRuntime from "shared-runtime";
6974

@@ -75,14 +80,21 @@ function Component(props) {
7580
const inner = { "Component[named > inner]": () => props.named }[
7681
"Component[named > inner]"
7782
];
78-
return inner();
83+
const innerIdentity = identity(
84+
{ "Component[named > identity()]": () => props.named }[
85+
"Component[named > identity()]"
86+
],
87+
);
88+
return inner(innerIdentity());
7989
};
8090
$[0] = props.named;
8191
$[1] = t0;
8292
} else {
8393
t0 = $[1];
8494
}
8595
const named = t0;
96+
97+
const callback = _ComponentCallback;
8698
let t1;
8799
if ($[2] !== props.namedVariable) {
88100
t1 = {
@@ -197,57 +209,62 @@ function Component(props) {
197209
} else {
198210
t9 = $[18];
199211
}
200-
let t10;
212+
const t10 = callback();
213+
let t11;
201214
if ($[19] !== namedVariable) {
202-
t10 = namedVariable();
215+
t11 = namedVariable();
203216
$[19] = namedVariable;
204-
$[20] = t10;
217+
$[20] = t11;
205218
} else {
206-
t10 = $[20];
219+
t11 = $[20];
207220
}
208-
const t11 = methodCall();
209-
const t12 = call();
210-
let t13;
221+
const t12 = methodCall();
222+
const t13 = call();
223+
let t14;
211224
if ($[21] !== hookArgument) {
212-
t13 = hookArgument();
225+
t14 = hookArgument();
213226
$[21] = hookArgument;
214-
$[22] = t13;
227+
$[22] = t14;
215228
} else {
216-
t13 = $[22];
229+
t14 = $[22];
217230
}
218-
let t14;
231+
let t15;
219232
if (
220233
$[23] !== builtinElementAttr ||
221234
$[24] !== namedElementAttr ||
222-
$[25] !== t10 ||
223-
$[26] !== t11 ||
224-
$[27] !== t12 ||
225-
$[28] !== t13 ||
235+
$[25] !== t11 ||
236+
$[26] !== t12 ||
237+
$[27] !== t13 ||
238+
$[28] !== t14 ||
226239
$[29] !== t9
227240
) {
228-
t14 = (
241+
t15 = (
229242
<>
230243
{t9}
231244
{t10}
232245
{t11}
233246
{t12}
247+
{t13}
234248
{builtinElementAttr}
235249
{namedElementAttr}
236-
{t13}
250+
{t14}
237251
</>
238252
);
239253
$[23] = builtinElementAttr;
240254
$[24] = namedElementAttr;
241-
$[25] = t10;
242-
$[26] = t11;
243-
$[27] = t12;
244-
$[28] = t13;
255+
$[25] = t11;
256+
$[26] = t12;
257+
$[27] = t13;
258+
$[28] = t14;
245259
$[29] = t9;
246-
$[30] = t14;
260+
$[30] = t15;
247261
} else {
248-
t14 = $[30];
262+
t15 = $[30];
249263
}
250-
return t14;
264+
return t15;
265+
}
266+
function _ComponentCallback() {
267+
return "ok";
251268
}
252269

253270
export const TODO_FIXTURE_ENTRYPOINT = {

compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/name-anonymous-functions.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
11
// @enableNameAnonymousFunctions
22

3-
import {useEffect} from 'react';
3+
import {useCallback, useEffect} from 'react';
44
import {identity, Stringify, useIdentity} from 'shared-runtime';
55
import * as SharedRuntime from 'shared-runtime';
66

77
function Component(props) {
88
function named() {
99
const inner = () => props.named;
10-
return inner();
10+
const innerIdentity = identity(() => props.named);
11+
return inner(innerIdentity());
1112
}
13+
const callback = useCallback(() => {
14+
return 'ok';
15+
}, []);
1216
const namedVariable = function () {
1317
return props.namedVariable;
1418
};
@@ -26,6 +30,7 @@ function Component(props) {
2630
return (
2731
<>
2832
{named()}
33+
{callback()}
2934
{namedVariable()}
3035
{methodCall()}
3136
{call()}

0 commit comments

Comments
 (0)