@samitouri / QOS-React-2 / commits / b61cfc01a5

Support rest params

Adds support for lowering rest element parameters to spreads. We eagerly create a temporary, similar to the approach for destructuring. In theory we could do something more optimal if you have a `...foo` (rest element where the argument is an Identifier) but it doesn't seem worth optimizing yet.

Joe Savona committed Sep 27, 2023 at 14:04 UTC b61cfc01a50e184d427bd2b873d82e140e0989d9
8 files changed +172 -5
compiler/packages/babel-plugin-react-forget/src/HIR/BuildHIR.ts
+19 -1
@@ -89,7 +89,7 @@ export function lower(
89 id = idNode.node.name;
90 }
91 }
92 - const params: Array<Place> = [];
92 + const params: Array<Place | SpreadPattern> = [];
93 func.get("params").forEach((param) => {
94 if (param.isIdentifier()) {
95 const identifier = builder.resolveIdentifier(param);
@@ -128,6 +128,24 @@ export function lower(
128 param,
129 place
130 );
131 + } else if (param.isRestElement()) {
132 + const place: Place = {
133 + kind: "Identifier",
134 + identifier: builder.makeTemporary(),
135 + effect: Effect.Unknown,
136 + loc: param.node.loc ?? GeneratedSource,
137 + };
138 + params.push({
139 + kind: "Spread",
140 + place,
141 + });
142 + lowerAssignment(
143 + builder,
144 + param.node.loc ?? GeneratedSource,
145 + InstructionKind.Let,
146 + param.get("argument"),
147 + place
148 + );
149 } else {
150 builder.errors.push({
151 reason: `(BuildHIR::lower) Handle ${param.node.type} params`,
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/error.todo-kitchensink.expect.md
-4
@@ -79,16 +79,12 @@ let moduleLocal = false;
79 ## Error
80
81 ```
82 -[ReactForget] Todo: (BuildHIR::lower) Handle RestElement params (1:1)
83 -
82 [ReactForget] Todo: (BuildHIR::lowerStatement) Handle var kinds in VariableDeclaration (3:3)
83
84 [ReactForget] Todo: (BuildHIR::lowerStatement) Handle ClassDeclaration statements (5:10)
85
86 [ReactForget] Todo: (BuildHIR::lowerExpression) Handle ObjectMethod properties in ObjectExpression (12:12)
87
90 -[ReactForget] Todo: (BuildHIR::lower) Handle RestElement params (18:18)
91 -
88 [ReactForget] Todo: (BuildHIR::lowerStatement) Handle non-variable initialization in ForStatement (20:22)
89
90 [ReactForget] Todo: (BuildHIR::lowerStatement) Handle non-variable initialization in ForStatement (23:25)
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rest-param-with-array-pattern.expect.md new
+43
@@ -0,0 +1,43 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +function Component(foo, ...[bar]) {
6 + return [foo, bar];
7 +}
8 +
9 +export const FIXTURE_ENTRYPOINT = {
10 + fn: Component,
11 + params: ["foo", ["bar", "baz"]],
12 +};
13 +
14 +```
15 +
16 +## Code
17 +
18 +```javascript
19 +import { unstable_useMemoCache as useMemoCache } from "react";
20 +function Component(foo, ...t9) {
21 + const $ = useMemoCache(3);
22 + const [bar] = t9;
23 + const c_0 = $[0] !== foo;
24 + const c_1 = $[1] !== bar;
25 + let t0;
26 + if (c_0 || c_1) {
27 + t0 = [foo, bar];
28 + $[0] = foo;
29 + $[1] = bar;
30 + $[2] = t0;
31 + } else {
32 + t0 = $[2];
33 + }
34 + return t0;
35 +}
36 +
37 +export const FIXTURE_ENTRYPOINT = {
38 + fn: Component,
39 + params: ["foo", ["bar", "baz"]],
40 +};
41 +
42 +```
43 +
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rest-param-with-array-pattern.js new
+8
@@ -0,0 +1,8 @@
1 +function Component(foo, ...[bar]) {
2 + return [foo, bar];
3 +}
4 +
5 +export const FIXTURE_ENTRYPOINT = {
6 + fn: Component,
7 + params: ["foo", ["bar", "baz"]],
8 +};
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rest-param-with-identifier.expect.md new
+43
@@ -0,0 +1,43 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +function Component(foo, ...bar) {
6 + return [foo, bar];
7 +}
8 +
9 +export const FIXTURE_ENTRYPOINT = {
10 + fn: Component,
11 + params: ["foo", "bar", "baz"],
12 +};
13 +
14 +```
15 +
16 +## Code
17 +
18 +```javascript
19 +import { unstable_useMemoCache as useMemoCache } from "react";
20 +function Component(foo, ...t9) {
21 + const $ = useMemoCache(3);
22 + const bar = t9;
23 + const c_0 = $[0] !== foo;
24 + const c_1 = $[1] !== bar;
25 + let t0;
26 + if (c_0 || c_1) {
27 + t0 = [foo, bar];
28 + $[0] = foo;
29 + $[1] = bar;
30 + $[2] = t0;
31 + } else {
32 + t0 = $[2];
33 + }
34 + return t0;
35 +}
36 +
37 +export const FIXTURE_ENTRYPOINT = {
38 + fn: Component,
39 + params: ["foo", "bar", "baz"],
40 +};
41 +
42 +```
43 +
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rest-param-with-identifier.js new
+8
@@ -0,0 +1,8 @@
1 +function Component(foo, ...bar) {
2 + return [foo, bar];
3 +}
4 +
5 +export const FIXTURE_ENTRYPOINT = {
6 + fn: Component,
7 + params: ["foo", "bar", "baz"],
8 +};
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rest-param-with-object-spread-pattern.expect.md new
+43
@@ -0,0 +1,43 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +function Component(foo, ...{ bar }) {
6 + return [foo, bar];
7 +}
8 +
9 +export const FIXTURE_ENTRYPOINT = {
10 + fn: Component,
11 + params: ["foo", { bar: "bar" }],
12 +};
13 +
14 +```
15 +
16 +## Code
17 +
18 +```javascript
19 +import { unstable_useMemoCache as useMemoCache } from "react";
20 +function Component(foo, ...t9) {
21 + const $ = useMemoCache(3);
22 + const { bar } = t9;
23 + const c_0 = $[0] !== foo;
24 + const c_1 = $[1] !== bar;
25 + let t0;
26 + if (c_0 || c_1) {
27 + t0 = [foo, bar];
28 + $[0] = foo;
29 + $[1] = bar;
30 + $[2] = t0;
31 + } else {
32 + t0 = $[2];
33 + }
34 + return t0;
35 +}
36 +
37 +export const FIXTURE_ENTRYPOINT = {
38 + fn: Component,
39 + params: ["foo", { bar: "bar" }],
40 +};
41 +
42 +```
43 +
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/rest-param-with-object-spread-pattern.js new
+8
@@ -0,0 +1,8 @@
1 +function Component(foo, ...{ bar }) {
2 + return [foo, bar];
3 +}
4 +
5 +export const FIXTURE_ENTRYPOINT = {
6 + fn: Component,
7 + params: ["foo", { bar: "bar" }],
8 +};