@samitouri / QOS-React-1 / commits / bd4bb32fe7

compiler: fix for calls on builtin jsx/function types

When I added new builtin types for jsx and functions, i forget to add a shape definition. This meant that attempting to accesss a property or method on these types would cause an internal error with an unresolved shape. That wasn't obvious because we rarely call methods on these types. I confirmed that the new fixtures here fail without the fix. ghstack-source-id: aa8f8d75a302bb5bac126d3e963594545e71ec74 Pull Request resolved: https://github.com/facebook/react/pull/29624

Joe Savona committed May 28, 2024 at 15:09 UTC bd4bb32fe708bace6fa927834220f571ff583f39
7 files changed +261
compiler/packages/babel-plugin-react-compiler/src/HIR/ObjectShape.ts
+3
@@ -431,6 +431,9 @@ addObject(BUILTIN_SHAPES, BuiltInMixedReadonlyId, [
431 ["*", { kind: "Object", shapeId: BuiltInMixedReadonlyId }],
432 ]);
433
434 +addObject(BUILTIN_SHAPES, BuiltInJsxId, []);
435 +addObject(BUILTIN_SHAPES, BuiltInFunctionId, []);
436 +
437 export const DefaultMutatingHook = addHook(
438 BUILTIN_SHAPES,
439 {
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/fbt-to-string.expect.md new
+61
@@ -0,0 +1,61 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +import fbt from "fbt";
6 +
7 +function Component(props) {
8 + const element = (
9 + <fbt desc={"Dialog to show to user"}>
10 + Hello <fbt:param name="user name">{props.name}</fbt:param>
11 + </fbt>
12 + );
13 + return element.toString();
14 +}
15 +
16 +export const FIXTURE_ENTRYPOINT = {
17 + fn: Component,
18 + params: [{ name: "Jason" }],
19 +};
20 +
21 +```
22 +
23 +## Code
24 +
25 +```javascript
26 +import { c as _c } from "react/compiler-runtime";
27 +import fbt from "fbt";
28 +
29 +function Component(props) {
30 + const $ = _c(4);
31 + let t0;
32 + if ($[0] !== props.name) {
33 + t0 = fbt._("Hello {user name}", [fbt._param("user name", props.name)], {
34 + hk: "2zEDKF",
35 + });
36 + $[0] = props.name;
37 + $[1] = t0;
38 + } else {
39 + t0 = $[1];
40 + }
41 + const element = t0;
42 + let t1;
43 + if ($[2] !== element) {
44 + t1 = element.toString();
45 + $[2] = element;
46 + $[3] = t1;
47 + } else {
48 + t1 = $[3];
49 + }
50 + return t1;
51 +}
52 +
53 +export const FIXTURE_ENTRYPOINT = {
54 + fn: Component,
55 + params: [{ name: "Jason" }],
56 +};
57 +
58 +```
59 +
60 +### Eval output
61 +(kind: ok) "Hello Jason"
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/fbt/fbt-to-string.js new
+15
@@ -0,0 +1,15 @@
1 +import fbt from "fbt";
2 +
3 +function Component(props) {
4 + const element = (
5 + <fbt desc={"Dialog to show to user"}>
6 + Hello <fbt:param name="user name">{props.name}</fbt:param>
7 + </fbt>
8 + );
9 + return element.toString();
10 +}
11 +
12 +export const FIXTURE_ENTRYPOINT = {
13 + fn: Component,
14 + params: [{ name: "Jason" }],
15 +};
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/function-expression-prototype-call-mutating.expect.md new
+92
@@ -0,0 +1,92 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +import { useMemo } from "react";
6 +import { ValidateMemoization } from "shared-runtime";
7 +
8 +function Component(props) {
9 + const a = useMemo(() => {
10 + const a = [];
11 + const f = function () {
12 + a.push(props.name);
13 + };
14 + f.call();
15 + return a;
16 + }, [props.name]);
17 + return <ValidateMemoization inputs={[props.name]} output={a} />;
18 +}
19 +
20 +export const FIXTURE_ENTRYPOINT = {
21 + fn: Component,
22 + params: [{ name: "Jason" }],
23 + sequentialRenders: [
24 + { name: "Lauren" },
25 + { name: "Lauren" },
26 + { name: "Jason" },
27 + ],
28 +};
29 +
30 +```
31 +
32 +## Code
33 +
34 +```javascript
35 +import { c as _c } from "react/compiler-runtime";
36 +import { useMemo } from "react";
37 +import { ValidateMemoization } from "shared-runtime";
38 +
39 +function Component(props) {
40 + const $ = _c(7);
41 + let t0;
42 + let a;
43 + if ($[0] !== props.name) {
44 + a = [];
45 + const f = function () {
46 + a.push(props.name);
47 + };
48 +
49 + f.call();
50 + $[0] = props.name;
51 + $[1] = a;
52 + } else {
53 + a = $[1];
54 + }
55 + t0 = a;
56 + const a_0 = t0;
57 + let t1;
58 + if ($[2] !== props.name) {
59 + t1 = [props.name];
60 + $[2] = props.name;
61 + $[3] = t1;
62 + } else {
63 + t1 = $[3];
64 + }
65 + let t2;
66 + if ($[4] !== t1 || $[5] !== a_0) {
67 + t2 = <ValidateMemoization inputs={t1} output={a_0} />;
68 + $[4] = t1;
69 + $[5] = a_0;
70 + $[6] = t2;
71 + } else {
72 + t2 = $[6];
73 + }
74 + return t2;
75 +}
76 +
77 +export const FIXTURE_ENTRYPOINT = {
78 + fn: Component,
79 + params: [{ name: "Jason" }],
80 + sequentialRenders: [
81 + { name: "Lauren" },
82 + { name: "Lauren" },
83 + { name: "Jason" },
84 + ],
85 +};
86 +
87 +```
88 +
89 +### Eval output
90 +(kind: ok) <div>{"inputs":["Lauren"],"output":["Lauren"]}</div>
91 +<div>{"inputs":["Lauren"],"output":["Lauren"]}</div>
92 +<div>{"inputs":["Jason"],"output":["Jason"]}</div>
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/function-expression-prototype-call-mutating.js new
+24
@@ -0,0 +1,24 @@
1 +import { useMemo } from "react";
2 +import { ValidateMemoization } from "shared-runtime";
3 +
4 +function Component(props) {
5 + const a = useMemo(() => {
6 + const a = [];
7 + const f = function () {
8 + a.push(props.name);
9 + };
10 + f.call();
11 + return a;
12 + }, [props.name]);
13 + return <ValidateMemoization inputs={[props.name]} output={a} />;
14 +}
15 +
16 +export const FIXTURE_ENTRYPOINT = {
17 + fn: Component,
18 + params: [{ name: "Jason" }],
19 + sequentialRenders: [
20 + { name: "Lauren" },
21 + { name: "Lauren" },
22 + { name: "Jason" },
23 + ],
24 +};
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/function-expression-prototype-call.expect.md new
+55
@@ -0,0 +1,55 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +function Component(props) {
6 + const f = function () {
7 + return <div>{props.name}</div>;
8 + };
9 + return f.call();
10 +}
11 +
12 +export const FIXTURE_ENTRYPOINT = {
13 + fn: Component,
14 + params: [{ name: "Jason" }],
15 +};
16 +
17 +```
18 +
19 +## Code
20 +
21 +```javascript
22 +import { c as _c } from "react/compiler-runtime";
23 +function Component(props) {
24 + const $ = _c(4);
25 + let t0;
26 + if ($[0] !== props.name) {
27 + t0 = function () {
28 + return <div>{props.name}</div>;
29 + };
30 + $[0] = props.name;
31 + $[1] = t0;
32 + } else {
33 + t0 = $[1];
34 + }
35 + const f = t0;
36 + let t1;
37 + if ($[2] !== f) {
38 + t1 = f.call();
39 + $[2] = f;
40 + $[3] = t1;
41 + } else {
42 + t1 = $[3];
43 + }
44 + return t1;
45 +}
46 +
47 +export const FIXTURE_ENTRYPOINT = {
48 + fn: Component,
49 + params: [{ name: "Jason" }],
50 +};
51 +
52 +```
53 +
54 +### Eval output
55 +(kind: ok) <div>Jason</div>
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/function-expression-prototype-call.js new
+11
@@ -0,0 +1,11 @@
1 +function Component(props) {
2 + const f = function () {
3 + return <div>{props.name}</div>;
4 + };
5 + return f.call();
6 +}
7 +
8 +export const FIXTURE_ENTRYPOINT = {
9 + fn: Component,
10 + params: [{ name: "Jason" }],
11 +};