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
+};