@samitouri / QOS-React-2 / commits / 66ca1c75cb

Fix dropped constant declaration bug

Joe Savona committed Jun 5, 2023 at 14:08 UTC 66ca1c75cb6d205b88f7761d432a84710f0b1683
7 files changed +111
compiler/forget/packages/babel-plugin-react-forget/src/Optimization/ConstantPropagation.ts
+21
@@ -81,6 +81,23 @@ export function constantPropagation(fn: HIRFunction): void {
81 }
82
83 function applyConstantPropagation(fn: HIRFunction): boolean {
84 + // Track the set of identifiers which are used as dependencies for function expressions
85 + // in order to avoid propagating these constants. This is necessary because the function
86 + // itself will still reference the original value. If the dependency is propagated but the
87 + // function still refers to the original value, this can create a situation where DCE
88 + // will think the original expression is unused. Until we are able to propagate constants
89 + // into function expression bodies, we disable propagation of function deps.
90 + const functionDependencies = new Set<IdentifierId>();
91 + for (const [, block] of fn.body.blocks) {
92 + for (const instr of block.instructions) {
93 + if (instr.value.kind === "FunctionExpression") {
94 + for (const operand of instr.value.dependencies) {
95 + functionDependencies.add(operand.identifier.id);
96 + }
97 + }
98 + }
99 + }
100 +
101 let hasChanges = false;
102
103 const constants: Constants = new Map();
@@ -120,6 +137,10 @@ function applyConstantPropagation(fn: HIRFunction): boolean {
137 continue;
138 }
139 const instr = block.instructions[i]!;
140 + // Don't propagate constants used as function expression dependencies
141 + if (functionDependencies.has(instr.lvalue.identifier.id)) {
142 + continue;
143 + }
144 const value = evaluateInstruction(constants, instr);
145 if (value !== null) {
146 constants.set(instr.lvalue.identifier.id, value);
compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/const-propagation-into-function-expression-global.expect.md new
+45
@@ -0,0 +1,45 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +function foo() {
6 + const isX = GLOBAL_IS_X;
7 + const getJSX = () => {
8 + <Child x={isX}></Child>;
9 + };
10 + const result = getJSX();
11 + return result;
12 +}
13 +
14 +```
15 +
16 +## Code
17 +
18 +```javascript
19 +import { unstable_useMemoCache as useMemoCache } from "react";
20 +function foo() {
21 + const $ = useMemoCache(2);
22 + const isX = GLOBAL_IS_X;
23 + let t0;
24 + if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
25 + t0 = () => {
26 + <Child x={isX}></Child>;
27 + };
28 + $[0] = t0;
29 + } else {
30 + t0 = $[0];
31 + }
32 + const getJSX = t0;
33 + let t1;
34 + if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
35 + t1 = getJSX();
36 + $[1] = t1;
37 + } else {
38 + t1 = $[1];
39 + }
40 + const result = t1;
41 + return result;
42 +}
43 +
44 +```
45 +
\ No newline at end of file
compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/const-propagation-into-function-expression-global.js new
+8
@@ -0,0 +1,8 @@
1 +function foo() {
2 + const isX = GLOBAL_IS_X;
3 + const getJSX = () => {
4 + <Child x={isX}></Child>;
5 + };
6 + const result = getJSX();
7 + return result;
8 +}
compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/const-propagation-into-function-expression-primitive.expect.md new
+29
@@ -0,0 +1,29 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +function foo() {
6 + const x = 42;
7 + const f = () => {
8 + console.log(x);
9 + };
10 + f();
11 + return x;
12 +}
13 +
14 +```
15 +
16 +## Code
17 +
18 +```javascript
19 +function foo() {
20 + const x = 42;
21 + const f = () => {
22 + console.log(x);
23 + };
24 + f();
25 + return 42;
26 +}
27 +
28 +```
29 +
\ No newline at end of file
compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/const-propagation-into-function-expression-primitive.js new
+8
@@ -0,0 +1,8 @@
1 +function foo() {
2 + const x = 42;
3 + const f = () => {
4 + console.log(x);
5 + };
6 + f();
7 + return x;
8 +}
compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-ref-in-callback-invoked-during-render.expect.md renamed
compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.invalid-ref-in-callback-invoked-during-render.js renamed