@samitouri / QOS-React-1 / commits / 7dc08d79be

PropagateScopeDeps treats switch w only default as unconditional

If we have a switch with only a default case, then that code will be executed unconditionally. PropagateScopeDeps can take advantage of this to record dependencies in these cases as unconditional, which avoids the issue seen in the previous PR.

Joe Savona committed Mar 22, 2024 at 09:02 UTC 7dc08d79be1bd7938757d03bd58fc662f647bbd7
5 files changed +85 -27
compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/PropagateScopeDependencies.ts
+9
@@ -732,6 +732,15 @@ class PropagationVisitor extends ReactiveFunctionVisitor<Context> {
732 }
733 case "switch": {
734 context.visitOperand(terminal.test);
735 + const isDefaultOnly =
736 + terminal.cases.length === 1 && terminal.cases[0].test == null;
737 + if (isDefaultOnly) {
738 + const case_ = terminal.cases[0];
739 + if (case_.block != null) {
740 + this.visitBlock(case_.block, context);
741 + break;
742 + }
743 + }
744 const depsInCases = [];
745 let foundDefault = false;
746 /*
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.todo-switch-with-only-default.expect.md deleted
-21
@@ -1,21 +0,0 @@
1 -
2 -## Input
3 -
4 -```javascript
5 -function Component({ kind, ...props }) {
6 - switch (kind) {
7 - default:
8 - return <Stringify {...props} />;
9 - }
10 -}
11 -
12 -```
13 -
14 -
15 -## Error
16 -
17 -```
18 -[ReactForget] Invariant: Expected trees to be at least 2 elements long.
19 -```
20 -
21 -
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.todo-switch-with-only-default.js deleted
-6
@@ -1,6 +0,0 @@
1 -function Component({ kind, ...props }) {
2 - switch (kind) {
3 - default:
4 - return <Stringify {...props} />;
5 - }
6 -}
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/switch-with-only-default.expect.md new
+63
@@ -0,0 +1,63 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +import { Stringify } from "shared-runtime";
6 +
7 +function Component({ kind, ...props }) {
8 + switch (kind) {
9 + default:
10 + return <Stringify {...props} />;
11 + }
12 +}
13 +
14 +export const FIXTURE_ENTRYPOINT = {
15 + fn: Component,
16 + params: [{ kind: "foo", a: 1, b: true, c: "sathya" }],
17 +};
18 +
19 +```
20 +
21 +## Code
22 +
23 +```javascript
24 +import { unstable_useMemoCache as useMemoCache } from "react";
25 +import { Stringify } from "shared-runtime";
26 +
27 +function Component(t0) {
28 + const $ = useMemoCache(5);
29 + let kind;
30 + let props;
31 + if ($[0] !== t0) {
32 + ({ kind, ...props } = t0);
33 + $[0] = t0;
34 + $[1] = kind;
35 + $[2] = props;
36 + } else {
37 + kind = $[1];
38 + props = $[2];
39 + }
40 + switch (kind) {
41 + default: {
42 + let t1;
43 + if ($[3] !== props) {
44 + t1 = <Stringify {...props} />;
45 + $[3] = props;
46 + $[4] = t1;
47 + } else {
48 + t1 = $[4];
49 + }
50 + return t1;
51 + }
52 + }
53 +}
54 +
55 +export const FIXTURE_ENTRYPOINT = {
56 + fn: Component,
57 + params: [{ kind: "foo", a: 1, b: true, c: "sathya" }],
58 +};
59 +
60 +```
61 +
62 +### Eval output
63 +(kind: ok) <div>{"a":1,"b":true,"c":"sathya"}</div>
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/switch-with-only-default.js new
+13
@@ -0,0 +1,13 @@
1 +import { Stringify } from "shared-runtime";
2 +
3 +function Component({ kind, ...props }) {
4 + switch (kind) {
5 + default:
6 + return <Stringify {...props} />;
7 + }
8 +}
9 +
10 +export const FIXTURE_ENTRYPOINT = {
11 + fn: Component,
12 + params: [{ kind: "foo", a: 1, b: true, c: "sathya" }],
13 +};