@samitouri / QOS-React-2 / commits / 20841f9a62

[compiler] Always emit variable decl in gating mode

This PR makes it so we always emit a const VariableDeclaration for compiled functions in gating mode. If the original declaration's parent was an ExportDefaultDeclaration we'll also append a new ExportDefaultDeclaration pointing to the new identifier. This allows code that adds optional properties to the function declaration to still work in gating mode ghstack-source-id: 5705479135baa268eeb3c85bfbf1883964e84916 Pull Request resolved: https://github.com/facebook/react/pull/29806

Lauren Tan committed Jun 7, 2024 at 15:39 UTC 20841f9a6205a633e6d08a274db974481daaca23
6 files changed +32 -31
compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Gating.ts
+20 -7
@@ -18,14 +18,13 @@ export function insertGatedFunctionDeclaration(
18 | t.ArrowFunctionExpression
19 | t.FunctionExpression,
20 gating: NonNullable<PluginOptions["gating"]>
21 -): NodePath<t.ConditionalExpression | t.VariableDeclaration> {
21 +): void {
22 const gatingExpression = t.conditionalExpression(
23 t.callExpression(t.identifier(gating.importSpecifierName), []),
24 buildFunctionExpression(compiled),
25 buildFunctionExpression(fnPath.node)
26 );
27
28 - let compiledFn;
28 /*
29 * Convert function declarations to named variables *unless* this is an
30 * `export default function ...` since `export default const ...` is
@@ -37,16 +36,30 @@ export function insertGatedFunctionDeclaration(
36 fnPath.node.type === "FunctionDeclaration" &&
37 fnPath.node.id != null
38 ) {
40 - compiledFn = fnPath.replaceWith(
39 + fnPath.replaceWith(
40 t.variableDeclaration("const", [
41 t.variableDeclarator(fnPath.node.id, gatingExpression),
42 ])
44 - )[0];
43 + );
44 + } else if (
45 + fnPath.parentPath.node.type === "ExportDefaultDeclaration" &&
46 + fnPath.node.type !== "ArrowFunctionExpression" &&
47 + fnPath.node.id != null
48 + ) {
49 + fnPath.insertAfter(
50 + t.exportDefaultDeclaration(t.identifier(fnPath.node.id.name))
51 + );
52 + fnPath.parentPath.replaceWith(
53 + t.variableDeclaration("const", [
54 + t.variableDeclarator(
55 + t.identifier(fnPath.node.id.name),
56 + gatingExpression
57 + ),
58 + ])
59 + );
60 } else {
46 - compiledFn = fnPath.replaceWith(gatingExpression)[0];
61 + fnPath.replaceWith(gatingExpression);
62 }
48 -
49 - return compiledFn;
63 }
64
65 function buildFunctionExpression(
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating-preserves-function-properties.expect.md renamed
+7 -15
@@ -4,11 +4,6 @@
4 ```javascript
5 // @gating
6
7 -/**
8 - * Fail: bug-gating-invalid-function-properties
9 - * Unexpected error in Forget runner
10 - * Component is not defined
11 - */
7 export default function Component() {
8 return <></>;
9 }
@@ -23,7 +18,7 @@ Component2.displayName = "Component TWO";
18 export const FIXTURE_ENTRYPOINT = {
19 fn: Component,
20 params: [],
26 - sequentialRenders: [],
21 + sequentialRenders: [{}],
22 };
23
24 ```
@@ -33,13 +28,7 @@ export const FIXTURE_ENTRYPOINT = {
28 ```javascript
29 import { isForgetEnabled_Fixtures } from "ReactForgetFeatureFlag";
30 import { c as _c } from "react/compiler-runtime"; // @gating
36 -
37 -/**
38 - * Fail: bug-gating-invalid-function-properties
39 - * Unexpected error in Forget runner
40 - * Component is not defined
41 - */
42 -export default isForgetEnabled_Fixtures()
31 +const Component = isForgetEnabled_Fixtures()
32 ? function Component() {
33 const $ = _c(1);
34 let t0;
@@ -54,6 +43,7 @@ export default isForgetEnabled_Fixtures()
43 : function Component() {
44 return <></>;
45 };
46 +export default Component;
47
48 export const Component2 = isForgetEnabled_Fixtures()
49 ? function Component2() {
@@ -77,8 +67,10 @@ Component2.displayName = "Component TWO";
67 export const FIXTURE_ENTRYPOINT = {
68 fn: Component,
69 params: [],
80 - sequentialRenders: [],
70 + sequentialRenders: [{}],
71 };
72
73 ```
84 -
\ No newline at end of file
74 +
75 +### Eval output
76 +(kind: ok)
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating-preserves-function-properties.tsx renamed
+1 -6
@@ -1,10 +1,5 @@
1 // @gating
2
3 -/**
4 - * Fail: bug-gating-invalid-function-properties
5 - * Unexpected error in Forget runner
6 - * Component is not defined
7 - */
3 export default function Component() {
4 return <></>;
5 }
@@ -19,5 +14,5 @@ Component2.displayName = "Component TWO";
14 export const FIXTURE_ENTRYPOINT = {
15 fn: Component,
16 params: [],
22 - sequentialRenders: [],
17 + sequentialRenders: [{}],
18 };
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating-test-export-default-function.expect.md
+2 -1
@@ -24,7 +24,7 @@ function Foo(props) {
24 ```javascript
25 import { isForgetEnabled_Fixtures } from "ReactForgetFeatureFlag";
26 import { c as _c } from "react/compiler-runtime"; // @gating @compilationMode(annotation)
27 -export default isForgetEnabled_Fixtures()
27 +const Bar = isForgetEnabled_Fixtures()
28 ? function Bar(props) {
29 "use forget";
30 const $ = _c(2);
@@ -42,6 +42,7 @@ export default isForgetEnabled_Fixtures()
42 "use forget";
43 return <div>{props.bar}</div>;
44 };
45 +export default Bar;
46
47 function NoForget(props) {
48 return <Bar>{props.noForget}</Bar>;
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/gating-test-export-function-and-default.expect.md
+2 -1
@@ -24,7 +24,7 @@ export function Foo(props) {
24 ```javascript
25 import { isForgetEnabled_Fixtures } from "ReactForgetFeatureFlag";
26 import { c as _c } from "react/compiler-runtime"; // @gating @compilationMode(annotation)
27 -export default isForgetEnabled_Fixtures()
27 +const Bar = isForgetEnabled_Fixtures()
28 ? function Bar(props) {
29 "use forget";
30 const $ = _c(2);
@@ -42,6 +42,7 @@ export default isForgetEnabled_Fixtures()
42 "use forget";
43 return <div>{props.bar}</div>;
44 };
45 +export default Bar;
46
47 function NoForget(props) {
48 return <Bar>{props.noForget}</Bar>;
compiler/packages/snap/src/SproutTodoFilter.ts
-1
@@ -490,7 +490,6 @@ const skipFilter = new Set([
490 "bug-invalid-hoisting-functionexpr",
491 "original-reactive-scopes-fork/bug-nonmutating-capture-in-unsplittable-memo-block",
492 "original-reactive-scopes-fork/bug-hoisted-declaration-with-scope",
493 - "bug-gating-invalid-function-properties",
493
494 // 'react-compiler-runtime' not yet supported
495 "flag-enable-emit-hook-guards",