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

Feature flag to opt-in to emitting change variables

Joe Savona committed Oct 12, 2023 at 16:26 UTC fa2a67dd1da70ef05eb6f0e259de2cfbcecc0cf3
4 files changed +92 -7
compiler/packages/babel-plugin-react-forget/src/HIR/Environment.ts
+21
@@ -210,6 +210,26 @@ export type EnvironmentConfig = {
210 * https://github.com/babel/babel/pull/10917/files#diff-19b555d2f3904c206af406540d9df200b1e16befedb83ff39ebfcbd876f7fa8aL52-R56
211 */
212 bailoutOnHoleyArrays: boolean;
213 +
214 + /**
215 + * Enable emitting "change variables" which store the result of whether a particular
216 + * reactive scope dependency has changed since the scope was last executed.
217 + *
218 + * Ex:
219 + * ```
220 + * const c_0 = $[0] !== input; // change variable
221 + * let output;
222 + * if (c_0) ...
223 + * ```
224 + *
225 + * Defaults to false, where the comparison is inlined:
226 + *
227 + * ```
228 + * let output;
229 + * if ($[0] !== input) ...
230 + * ```
231 + */
232 + enableChangeVariableCodegen: boolean;
233 };
234
235 export const DEFAULT_ENVIRONMENT_CONFIG: Readonly<EnvironmentConfig> = {
@@ -225,6 +245,7 @@ export const DEFAULT_ENVIRONMENT_CONFIG: Readonly<EnvironmentConfig> = {
245 enableAssumeHooksFollowRulesOfReact: false,
246 enableEmitFreeze: null,
247 enableForest: false,
248 + enableChangeVariableCodegen: false,
249
250 validateFrozenLambdas: false,
251 validateNoSetStateInRender: false,
compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/CodegenReactiveFunction.ts
+16 -7
@@ -241,14 +241,23 @@ function codegenMemoBlockForReactiveScope(
241 for (const dep of scope.dependencies) {
242 const index = cx.nextCacheIndex;
243 const depValue = codegenDependency(cx, dep);
244 -
245 - changeExpressions.push(
246 - t.binaryExpression(
247 - "!==",
248 - t.memberExpression(t.identifier("$"), t.numericLiteral(index), true),
249 - depValue
250 - )
244 + const comparison = t.binaryExpression(
245 + "!==",
246 + t.memberExpression(t.identifier("$"), t.numericLiteral(index), true),
247 + depValue
248 );
249 +
250 + if (cx.env.config.enableChangeVariableCodegen) {
251 + const changeIdentifier = t.identifier(`c_${index}`);
252 + statements.push(
253 + t.variableDeclaration("const", [
254 + t.variableDeclarator(changeIdentifier, comparison),
255 + ])
256 + );
257 + changeExpressions.push(changeIdentifier);
258 + } else {
259 + changeExpressions.push(comparison);
260 + }
261 cacheStoreStatements.push(
262 t.expressionStatement(
263 t.assignmentExpression(
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/option-enable-change-variable-codegen.expect.md new
+45
@@ -0,0 +1,45 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +// @enableChangeVariableCodegen
6 +function Component(props) {
7 + const x = [props.a, props.b.c];
8 + return x;
9 +}
10 +
11 +export const FIXTURE_ENTRYPOINT = {
12 + fn: Component,
13 + params: [{ a: 3.14, b: { c: true } }],
14 +};
15 +
16 +```
17 +
18 +## Code
19 +
20 +```javascript
21 +import { unstable_useMemoCache as useMemoCache } from "react"; // @enableChangeVariableCodegen
22 +function Component(props) {
23 + const $ = useMemoCache(3);
24 + const c_0 = $[0] !== props.a;
25 + const c_1 = $[1] !== props.b.c;
26 + let t0;
27 + if (c_0 || c_1) {
28 + t0 = [props.a, props.b.c];
29 + $[0] = props.a;
30 + $[1] = props.b.c;
31 + $[2] = t0;
32 + } else {
33 + t0 = $[2];
34 + }
35 + const x = t0;
36 + return x;
37 +}
38 +
39 +export const FIXTURE_ENTRYPOINT = {
40 + fn: Component,
41 + params: [{ a: 3.14, b: { c: true } }],
42 +};
43 +
44 +```
45 +
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/option-enable-change-variable-codegen.js new
+10
@@ -0,0 +1,10 @@
1 +// @enableChangeVariableCodegen
2 +function Component(props) {
3 + const x = [props.a, props.b.c];
4 + return x;
5 +}
6 +
7 +export const FIXTURE_ENTRYPOINT = {
8 + fn: Component,
9 + params: [{ a: 3.14, b: { c: true } }],
10 +};