Support spread elements in CallExpression args
Joe Savona committed
Mar 15, 2023 at 17:13 UTC
f88713bba5f935370ba398f123e1a504303e6036
15 files changed
+375
-206
compiler/forget/src/HIR/BuildHIR.ts
+24
-7
@@ -916,17 +916,25 @@ function lowerExpression(
916
}
917
if (calleePath.isMemberExpression()) {
918
const { object, property } = lowerMemberExpression(builder, calleePath);
919
- let args: Place[] = [];
919
+ let args: Array<Place | SpreadPattern> = [];
920
for (const argPath of expr.get("arguments")) {
921
- if (!argPath.isExpression()) {
921
+ if (argPath.isSpreadElement()) {
922
+ args.push({
923
+ kind: "Spread",
924
+ place: lowerExpressionToTemporary(
925
+ builder,
926
+ argPath.get("argument")
927
+ ),
928
+ });
929
+ } else if (argPath.isExpression()) {
930
+ args.push(lowerExpressionToTemporary(builder, argPath));
931
+ } else {
932
builder.errors.push({
933
reason: `(BuildHIR::lowerExpression) Handle ${argPath.type} arguments in CallExpression`,
934
severity: ErrorSeverity.Todo,
935
nodePath: argPath,
936
});
927
- continue;
937
}
929
- args.push(lowerExpressionToTemporary(builder, argPath));
938
}
939
if (typeof property === "string") {
940
return {
@@ -947,9 +955,19 @@ function lowerExpression(
955
}
956
} else {
957
const callee = lowerExpressionToTemporary(builder, calleePath);
950
- let args: Place[] = [];
958
+ let args: Array<Place | SpreadPattern> = [];
959
for (const argPath of expr.get("arguments")) {
952
- if (!argPath.isExpression()) {
960
+ if (argPath.isSpreadElement()) {
961
+ args.push({
962
+ kind: "Spread",
963
+ place: lowerExpressionToTemporary(
964
+ builder,
965
+ argPath.get("argument")
966
+ ),
967
+ });
968
+ } else if (argPath.isExpression()) {
969
+ args.push(lowerExpressionToTemporary(builder, argPath));
970
+ } else {
971
builder.errors.push({
972
reason: `(BuildHIR::lowerExpression) Handle ${argPath.type} arguments in CallExpression`,
973
severity: ErrorSeverity.Todo,
@@ -957,7 +975,6 @@ function lowerExpression(
975
});
976
continue;
977
}
960
- args.push(lowerExpressionToTemporary(builder, argPath));
978
}
979
return {
980
kind: "CallExpression",
compiler/forget/src/HIR/HIR.ts
+3
-3
@@ -480,21 +480,21 @@ export type InstructionValue =
480
| {
481
kind: "CallExpression";
482
callee: Place;
483
- args: Array<Place>;
483
+ args: Array<Place | SpreadPattern>;
484
loc: SourceLocation;
485
}
486
| {
487
kind: "PropertyCall";
488
receiver: Place;
489
property: string;
490
- args: Array<Place>;
490
+ args: Array<Place | SpreadPattern>;
491
loc: SourceLocation;
492
}
493
| {
494
kind: "ComputedCall";
495
receiver: Place;
496
property: Place;
497
- args: Array<Place>;
497
+ args: Array<Place | SpreadPattern>;
498
loc: SourceLocation;
499
}
500
| {
compiler/forget/src/HIR/PrintHIR.ts
+3
-3
@@ -258,20 +258,20 @@ export function printInstructionValue(instrValue: ReactiveValue): string {
258
}
259
case "CallExpression": {
260
value = `Call ${printPlace(instrValue.callee)}(${instrValue.args
261
- .map((arg) => printPlace(arg))
261
+ .map((arg) => printPattern(arg))
262
.join(", ")})`;
263
break;
264
}
265
case "PropertyCall": {
266
value = `PropertyCall ${printPlace(instrValue.receiver)}.${
267
instrValue.property
268
- }(${instrValue.args.map((arg) => printPlace(arg)).join(", ")})`;
268
+ }(${instrValue.args.map((arg) => printPattern(arg)).join(", ")})`;
269
break;
270
}
271
case "ComputedCall": {
272
value = `ComputedCall ${printPlace(instrValue.receiver)}[${printPlace(
273
instrValue.property
274
- )}](${instrValue.args.map((arg) => printPlace(arg)).join(", ")})`;
274
+ )}](${instrValue.args.map((arg) => printPattern(arg)).join(", ")})`;
275
break;
276
}
277
case "JSXText":
compiler/forget/src/HIR/visitors.ts
+33
-6
@@ -14,6 +14,7 @@ import {
14
Pattern,
15
Place,
16
ReactiveInstruction,
17
+ SpreadPattern,
18
Terminal,
19
} from "./HIR";
20
@@ -45,7 +46,7 @@ export function* eachInstructionValueOperand(
46
case "NewExpression":
47
case "CallExpression": {
48
yield instrValue.callee;
48
- yield* instrValue.args;
49
+ yield* eachCallArgument(instrValue.args);
50
break;
51
}
52
case "BinaryExpression": {
@@ -55,13 +56,13 @@ export function* eachInstructionValueOperand(
56
}
57
case "PropertyCall": {
58
yield instrValue.receiver;
58
- yield* instrValue.args;
59
+ yield* eachCallArgument(instrValue.args);
60
break;
61
}
62
case "ComputedCall": {
63
yield instrValue.receiver;
64
yield instrValue.property;
64
- yield* instrValue.args;
65
+ yield* eachCallArgument(instrValue.args);
66
break;
67
}
68
case "LoadLocal": {
@@ -185,6 +186,18 @@ export function* eachInstructionValueOperand(
186
}
187
}
188
189
+export function* eachCallArgument(
190
+ args: Array<Place | SpreadPattern>
191
+): Iterable<Place> {
192
+ for (const arg of args) {
193
+ if (arg.kind === "Identifier") {
194
+ yield arg;
195
+ } else {
196
+ yield arg.place;
197
+ }
198
+ }
199
+}
200
+
201
export function doesPatternContainSpreadElement(pattern: Pattern): boolean {
202
switch (pattern.kind) {
203
case "ArrayPattern": {
@@ -331,18 +344,18 @@ export function mapInstructionOperands(
344
case "NewExpression":
345
case "CallExpression": {
346
instrValue.callee = fn(instrValue.callee);
334
- instrValue.args = instrValue.args.map((arg) => fn(arg));
347
+ instrValue.args = mapCallArguments(instrValue.args, fn);
348
break;
349
}
350
case "PropertyCall": {
351
instrValue.receiver = fn(instrValue.receiver);
339
- instrValue.args = instrValue.args.map((arg) => fn(arg));
352
+ instrValue.args = mapCallArguments(instrValue.args, fn);
353
break;
354
}
355
case "ComputedCall": {
356
instrValue.receiver = fn(instrValue.receiver);
357
instrValue.property = fn(instrValue.property);
345
- instrValue.args = instrValue.args.map((arg) => fn(arg));
358
+ instrValue.args = mapCallArguments(instrValue.args, fn);
359
break;
360
}
361
case "UnaryExpression": {
@@ -423,6 +436,20 @@ export function mapInstructionOperands(
436
}
437
}
438
439
+export function mapCallArguments(
440
+ args: Array<Place | SpreadPattern>,
441
+ fn: (place: Place) => Place
442
+): Array<Place | SpreadPattern> {
443
+ return args.map((arg) => {
444
+ if (arg.kind === "Identifier") {
445
+ return fn(arg);
446
+ } else {
447
+ arg.place = fn(arg.place);
448
+ return arg;
449
+ }
450
+ });
451
+}
452
+
453
export function mapPatternOperands(
454
pattern: Pattern,
455
fn: (place: Place) => Place
compiler/forget/src/Inference/DropMemoCalls.ts
+21
-17
@@ -21,14 +21,16 @@ export default function (func: HIRFunction): void {
21
//
22
// after:
23
// foo = Call $9()
24
- instr.value = {
25
- kind: "CallExpression",
26
- callee: fn,
27
- // Drop the args, including the deps array which DCE will remove
28
- // later.
29
- args: [],
30
- loc: instr.value.loc,
31
- };
24
+ if (fn.kind === "Identifier") {
25
+ instr.value = {
26
+ kind: "CallExpression",
27
+ callee: fn,
28
+ // Drop the args, including the deps array which DCE will remove
29
+ // later.
30
+ args: [],
31
+ loc: instr.value.loc,
32
+ };
33
+ }
34
} else if (name === "useCallback") {
35
const [fn] = instr.value.args;
36
@@ -39,16 +41,18 @@ export default function (func: HIRFunction): void {
41
//
42
// after:
43
// foo = $19
42
- instr.value = {
43
- kind: "LoadLocal",
44
- place: {
45
- kind: "Identifier",
46
- identifier: fn.identifier,
47
- effect: Effect.Unknown,
44
+ if (fn.kind === "Identifier") {
45
+ instr.value = {
46
+ kind: "LoadLocal",
47
+ place: {
48
+ kind: "Identifier",
49
+ identifier: fn.identifier,
50
+ effect: Effect.Unknown,
51
+ loc: instr.value.loc,
52
+ },
53
loc: instr.value.loc,
49
- },
50
- loc: instr.value.loc,
51
- };
54
+ };
55
+ }
56
}
57
}
58
}
compiler/forget/src/Inference/InferReferenceEffects.ts
+10
-2
@@ -673,7 +673,11 @@ function inferBlock(
673
674
state.reference(instrValue.receiver, Effect.Mutate);
675
for (const arg of instrValue.args) {
676
- state.reference(arg, Effect.Mutate);
676
+ if (arg.kind === "Identifier") {
677
+ state.reference(arg, Effect.Mutate);
678
+ } else {
679
+ state.reference(arg.place, Effect.Mutate);
680
+ }
681
}
682
state.initialize(instrValue, ValueKind.Mutable);
683
state.define(instr.lvalue, instrValue);
@@ -695,7 +699,11 @@ function inferBlock(
699
state.reference(instrValue.receiver, Effect.Mutate);
700
state.reference(instrValue.property, Effect.Read);
701
for (const arg of instrValue.args) {
698
- state.reference(arg, Effect.Mutate);
702
+ if (arg.kind === "Identifier") {
703
+ state.reference(arg, Effect.Mutate);
704
+ } else {
705
+ state.reference(arg.place, Effect.Mutate);
706
+ }
707
}
708
state.initialize(instrValue, ValueKind.Mutable);
709
state.define(instr.lvalue, instrValue);
compiler/forget/src/ReactiveScopes/CodegenReactiveFunction.ts
+14
-3
@@ -556,7 +556,7 @@ function codegenInstructionValue(
556
}
557
case "CallExpression": {
558
const callee = codegenPlace(cx, instrValue.callee);
559
- const args = instrValue.args.map((arg) => codegenPlace(cx, arg));
559
+ const args = instrValue.args.map((arg) => codegenArgument(cx, arg));
560
value = createCallExpression(instrValue.loc, callee, args);
561
break;
562
}
@@ -566,7 +566,7 @@ function codegenInstructionValue(
566
receiver,
567
t.identifier(instrValue.property)
568
);
569
- const args = instrValue.args.map((arg) => codegenPlace(cx, arg));
569
+ const args = instrValue.args.map((arg) => codegenArgument(cx, arg));
570
value = createCallExpression(instrValue.loc, callee, args);
571
break;
572
}
@@ -574,7 +574,7 @@ function codegenInstructionValue(
574
const receiver = codegenPlace(cx, instrValue.receiver);
575
const property = codegenPlace(cx, instrValue.property);
576
const callee = t.memberExpression(receiver, property, true);
577
- const args = instrValue.args.map((arg) => codegenPlace(cx, arg));
577
+ const args = instrValue.args.map((arg) => codegenArgument(cx, arg));
578
value = createCallExpression(instrValue.loc, callee, args);
579
break;
580
}
@@ -940,6 +940,17 @@ function codegenValue(
940
}
941
}
942
943
+function codegenArgument(
944
+ cx: Context,
945
+ arg: Place | SpreadPattern
946
+): t.Expression | t.SpreadElement {
947
+ if (arg.kind === "Identifier") {
948
+ return codegenPlace(cx, arg);
949
+ } else {
950
+ return t.spreadElement(codegenPlace(cx, arg.place));
951
+ }
952
+}
953
+
954
function codegenPlace(cx: Context, place: Place): t.Expression {
955
let tmp = cx.temp.get(place.identifier.id);
956
if (tmp != null) {
compiler/forget/src/__tests__/fixtures/compiler/call-spread.expect.md
new
+33
@@ -0,0 +1,33 @@
1
+
2
+## Input
3
+
4
+```javascript
5
+function Component(props) {
6
+ const x = foo(...props.a, null, ...props.b);
7
+ return x;
8
+}
9
+
10
+```
11
+
12
+## Code
13
+
14
+```javascript
15
+function Component(props) {
16
+ const $ = React.unstable_useMemoCache(3);
17
+ const c_0 = $[0] !== props.a;
18
+ const c_1 = $[1] !== props.b;
19
+ let t0;
20
+ if (c_0 || c_1) {
21
+ t0 = foo(...props.a, null, ...props.b);
22
+ $[0] = props.a;
23
+ $[1] = props.b;
24
+ $[2] = t0;
25
+ } else {
26
+ t0 = $[2];
27
+ }
28
+ const x = t0;
29
+ return x;
30
+}
31
+
32
+```
33
+
\ No newline at end of file
compiler/forget/src/__tests__/fixtures/compiler/call-spread.js
new
+4
@@ -0,0 +1,4 @@
1
+function Component(props) {
2
+ const x = foo(...props.a, null, ...props.b);
3
+ return x;
4
+}
compiler/forget/src/__tests__/fixtures/compiler/computed-call-spread.expect.md
new
+35
@@ -0,0 +1,35 @@
1
+
2
+## Input
3
+
4
+```javascript
5
+function Component(props) {
6
+ const x = foo[props.method](...props.a, null, ...props.b);
7
+ return x;
8
+}
9
+
10
+```
11
+
12
+## Code
13
+
14
+```javascript
15
+function Component(props) {
16
+ const $ = React.unstable_useMemoCache(4);
17
+ const c_0 = $[0] !== props.method;
18
+ const c_1 = $[1] !== props.a;
19
+ const c_2 = $[2] !== props.b;
20
+ let t0;
21
+ if (c_0 || c_1 || c_2) {
22
+ t0 = foo[props.method](...props.a, null, ...props.b);
23
+ $[0] = props.method;
24
+ $[1] = props.a;
25
+ $[2] = props.b;
26
+ $[3] = t0;
27
+ } else {
28
+ t0 = $[3];
29
+ }
30
+ const x = t0;
31
+ return x;
32
+}
33
+
34
+```
35
+
\ No newline at end of file
compiler/forget/src/__tests__/fixtures/compiler/computed-call-spread.js
new
+4
@@ -0,0 +1,4 @@
1
+function Component(props) {
2
+ const x = foo[props.method](...props.a, null, ...props.b);
3
+ return x;
4
+}
compiler/forget/src/__tests__/fixtures/compiler/error.todo-kitchensink.expect.md
+154
-164
@@ -15,7 +15,6 @@ function foo([a, b], { c, d, e = "e" }, f = "f", ...args) {
15
16
const g = { b() {}, c: () => {} };
17
new c(...args);
18
- c(...args);
18
const { z, aa = "aa" } = useCustom();
19
20
<Button xlink:href="localhost:3000"></Button>;
@@ -128,251 +127,242 @@ let moduleLocal = false;
127
> 12 | const g = { b() {}, c: () => {} };
128
| ^^^^^^
129
13 | new c(...args);
131
- 14 | c(...args);
132
- 15 | const { z, aa = "aa" } = useCustom();
130
+ 14 | const { z, aa = "aa" } = useCustom();
131
+ 15 |
132
133
[ReactForget] TodoError: (BuildHIR::lowerExpression) Handle SpreadElement arguments in NewExpression
134
11 |
135
12 | const g = { b() {}, c: () => {} };
136
> 13 | new c(...args);
137
| ^^^^^^^
139
- 14 | c(...args);
140
- 15 | const { z, aa = "aa" } = useCustom();
141
- 16 |
142
-
143
-[ReactForget] TodoError: (BuildHIR::lowerExpression) Handle SpreadElement arguments in CallExpression
144
- 12 | const g = { b() {}, c: () => {} };
145
- 13 | new c(...args);
146
-> 14 | c(...args);
147
- | ^^^^^^^
148
- 15 | const { z, aa = "aa" } = useCustom();
149
- 16 |
150
- 17 | <Button xlink:href="localhost:3000"></Button>;
138
+ 14 | const { z, aa = "aa" } = useCustom();
139
+ 15 |
140
+ 16 | <Button xlink:href="localhost:3000"></Button>;
141
142
[ReactForget] TodoError: (BuildHIR::lowerAssignment) Handle AssignmentPattern assignments
143
+ 12 | const g = { b() {}, c: () => {} };
144
13 | new c(...args);
154
- 14 | c(...args);
155
-> 15 | const { z, aa = "aa" } = useCustom();
145
+> 14 | const { z, aa = "aa" } = useCustom();
146
| ^^^^^^^^^
157
- 16 |
158
- 17 | <Button xlink:href="localhost:3000"></Button>;
159
- 18 | <Button haha={1}></Button>;
147
+ 15 |
148
+ 16 | <Button xlink:href="localhost:3000"></Button>;
149
+ 17 | <Button haha={1}></Button>;
150
151
[ReactForget] TodoError: (BuildHIR::lowerExpression) Handle JSXNamespacedName attribute names in JSXElement
162
- 15 | const { z, aa = "aa" } = useCustom();
163
- 16 |
164
-> 17 | <Button xlink:href="localhost:3000"></Button>;
152
+ 14 | const { z, aa = "aa" } = useCustom();
153
+ 15 |
154
+> 16 | <Button xlink:href="localhost:3000"></Button>;
155
| ^^^^^^^^^^
166
- 18 | <Button haha={1}></Button>;
167
- 19 | <Button>{/** empty */}</Button>;
168
- 20 | <DesignSystem.Button />;
156
+ 17 | <Button haha={1}></Button>;
157
+ 18 | <Button>{/** empty */}</Button>;
158
+ 19 | <DesignSystem.Button />;
159
160
[ReactForget] TodoError: (BuildHIR::lowerJsxElement) Handle JSXEmptyExpression expressions
171
- 17 | <Button xlink:href="localhost:3000"></Button>;
172
- 18 | <Button haha={1}></Button>;
173
-> 19 | <Button>{/** empty */}</Button>;
161
+ 16 | <Button xlink:href="localhost:3000"></Button>;
162
+ 17 | <Button haha={1}></Button>;
163
+> 18 | <Button>{/** empty */}</Button>;
164
| ^^^^^^^^^^^^
175
- 20 | <DesignSystem.Button />;
176
- 21 |
177
- 22 | const j = function bar([quz, qux], ...args) {};
165
+ 19 | <DesignSystem.Button />;
166
+ 20 |
167
+ 21 | const j = function bar([quz, qux], ...args) {};
168
169
[ReactForget] TodoError: (BuildHIR::lowerJsxElementName) Handle JSXMemberExpression tags
180
- 18 | <Button haha={1}></Button>;
181
- 19 | <Button>{/** empty */}</Button>;
182
-> 20 | <DesignSystem.Button />;
170
+ 17 | <Button haha={1}></Button>;
171
+ 18 | <Button>{/** empty */}</Button>;
172
+> 19 | <DesignSystem.Button />;
173
| ^^^^^^^^^^^^^^^^^^^
184
- 21 |
185
- 22 | const j = function bar([quz, qux], ...args) {};
186
- 23 |
174
+ 20 |
175
+ 21 | const j = function bar([quz, qux], ...args) {};
176
+ 22 |
177
178
[ReactForget] TodoError: (BuildHIR::lower) Handle RestElement params
189
- 20 | <DesignSystem.Button />;
190
- 21 |
191
-> 22 | const j = function bar([quz, qux], ...args) {};
179
+ 19 | <DesignSystem.Button />;
180
+ 20 |
181
+> 21 | const j = function bar([quz, qux], ...args) {};
182
| ^^^^^^^
193
- 23 |
194
- 24 | for (; i < 3; i += 1) {
195
- 25 | x.push(i);
183
+ 22 |
184
+ 23 | for (; i < 3; i += 1) {
185
+ 24 | x.push(i);
186
187
[ReactForget] TodoError: (BuildHIR::lowerStatement) Handle non-variable initialization in ForStatement
198
- 22 | const j = function bar([quz, qux], ...args) {};
199
- 23 |
200
-> 24 | for (; i < 3; i += 1) {
188
+ 21 | const j = function bar([quz, qux], ...args) {};
189
+ 22 |
190
+> 23 | for (; i < 3; i += 1) {
191
| ^
202
- 25 | x.push(i);
203
- 26 | }
204
- 27 | for (; i < 3; ) {
192
+ 24 | x.push(i);
193
+ 25 | }
194
+ 26 | for (; i < 3; ) {
195
196
[ReactForget] TodoError: (BuildHIR::lowerStatement) Handle non-variable initialization in ForStatement
207
- 25 | x.push(i);
208
- 26 | }
209
-> 27 | for (; i < 3; ) {
197
+ 24 | x.push(i);
198
+ 25 | }
199
+> 26 | for (; i < 3; ) {
200
| ^
211
- 28 | break;
212
- 29 | }
213
- 30 | for (;;) {
201
+ 27 | break;
202
+ 28 | }
203
+ 29 | for (;;) {
204
205
[ReactForget] TodoError: (BuildHIR::lowerStatement) Handle empty update in ForStatement
216
- 25 | x.push(i);
217
- 26 | }
218
-> 27 | for (; i < 3; ) {
206
+ 24 | x.push(i);
207
+ 25 | }
208
+> 26 | for (; i < 3; ) {
209
| ^
220
- 28 | break;
221
- 29 | }
222
- 30 | for (;;) {
210
+ 27 | break;
211
+ 28 | }
212
+ 29 | for (;;) {
213
214
[ReactForget] TodoError: (BuildHIR::lowerStatement) Handle non-variable initialization in ForStatement
225
- 28 | break;
226
- 29 | }
227
-> 30 | for (;;) {
215
+ 27 | break;
216
+ 28 | }
217
+> 29 | for (;;) {
218
| ^
229
- 31 | break;
230
- 32 | }
231
- 33 |
219
+ 30 | break;
220
+ 31 | }
221
+ 32 |
222
223
[ReactForget] TodoError: (BuildHIR::lowerStatement) Handle empty update in ForStatement
234
- 28 | break;
235
- 29 | }
236
-> 30 | for (;;) {
224
+ 27 | break;
225
+ 28 | }
226
+> 29 | for (;;) {
227
| ^
238
- 31 | break;
239
- 32 | }
240
- 33 |
228
+ 30 | break;
229
+ 31 | }
230
+ 32 |
231
232
[ReactForget] TodoError: (BuildHIR::lowerStatement) Handle empty test in ForStatement
243
- 28 | break;
244
- 29 | }
245
-> 30 | for (;;) {
233
+ 27 | break;
234
+ 28 | }
235
+> 29 | for (;;) {
236
| ^
247
- 31 | break;
248
- 32 | }
249
- 33 |
237
+ 30 | break;
238
+ 31 | }
239
+ 32 |
240
241
[ReactForget] TodoError: (BuildHIR::lowerExpression) Handle tagged template with interpolations
252
- 32 | }
253
- 33 |
254
-> 34 | graphql`
242
+ 31 | }
243
+ 32 |
244
+> 33 | graphql`
245
| ^
256
- 35 | ${g}
257
- 36 | `;
258
- 37 |
246
+ 34 | ${g}
247
+ 35 | `;
248
+ 36 |
249
250
[ReactForget] TodoError: (BuildHIR::lowerExpression) Handle tagged template where cooked value is different from raw value
261
- 36 | `;
262
- 37 |
263
-> 38 | graphql`\\t\n`;
251
+ 35 | `;
252
+ 36 |
253
+> 37 | graphql`\\t\n`;
254
| ^^^^^^^^^^^^^^
265
- 39 |
266
- 40 | for (const c of [1, 2]) {
267
- 41 | }
255
+ 38 |
256
+ 39 | for (const c of [1, 2]) {
257
+ 40 | }
258
259
[ReactForget] TodoError: (BuildHIR::lowerStatement) Handle ForOfStatement statements
270
- 38 | graphql`\\t\n`;
271
- 39 |
272
-> 40 | for (const c of [1, 2]) {
260
+ 37 | graphql`\\t\n`;
261
+ 38 |
262
+> 39 | for (const c of [1, 2]) {
263
| ^
274
- 41 | }
275
- 42 |
276
- 43 | for (let x in { a: 1 }) {
264
+ 40 | }
265
+ 41 |
266
+ 42 | for (let x in { a: 1 }) {
267
268
[ReactForget] TodoError: (BuildHIR::lowerStatement) Handle ForInStatement statements
279
- 41 | }
280
- 42 |
281
-> 43 | for (let x in { a: 1 }) {
269
+ 40 | }
270
+ 41 |
271
+> 42 | for (let x in { a: 1 }) {
272
| ^
283
- 44 | }
284
- 45 |
285
- 46 | let updateIdentifier = 0;
273
+ 43 | }
274
+ 44 |
275
+ 45 | let updateIdentifier = 0;
276
277
[ReactForget] TodoError: (BuildHIR::lowerExpression) Handle prefix UpdateExpression
288
- 45 |
289
- 46 | let updateIdentifier = 0;
290
-> 47 | --updateIdentifier;
278
+ 44 |
279
+ 45 | let updateIdentifier = 0;
280
+> 46 | --updateIdentifier;
281
| ^^^^^^^^^^^^^^^^^^
292
- 48 | ++updateIdentifier;
293
- 49 | updateIdentifier.y++;
294
- 50 | updateIdentifier.y--;
282
+ 47 | ++updateIdentifier;
283
+ 48 | updateIdentifier.y++;
284
+ 49 | updateIdentifier.y--;
285
286
[ReactForget] TodoError: (BuildHIR::lowerExpression) Handle prefix UpdateExpression
297
- 46 | let updateIdentifier = 0;
298
- 47 | --updateIdentifier;
299
-> 48 | ++updateIdentifier;
287
+ 45 | let updateIdentifier = 0;
288
+ 46 | --updateIdentifier;
289
+> 47 | ++updateIdentifier;
290
| ^^^^^^^^^^^^^^^^^^
301
- 49 | updateIdentifier.y++;
302
- 50 | updateIdentifier.y--;
303
- 51 |
291
+ 48 | updateIdentifier.y++;
292
+ 49 | updateIdentifier.y--;
293
+ 50 |
294
295
[ReactForget] TodoError: (BuildHIR::lowerExpression) Handle UpdateExpression with MemberExpression argument
306
- 47 | --updateIdentifier;
307
- 48 | ++updateIdentifier;
308
-> 49 | updateIdentifier.y++;
296
+ 46 | --updateIdentifier;
297
+ 47 | ++updateIdentifier;
298
+> 48 | updateIdentifier.y++;
299
| ^^^^^^^^^^^^^^^^^^^^
310
- 50 | updateIdentifier.y--;
311
- 51 |
312
- 52 | switch (i) {
300
+ 49 | updateIdentifier.y--;
301
+ 50 |
302
+ 51 | switch (i) {
303
304
[ReactForget] TodoError: (BuildHIR::lowerExpression) Handle UpdateExpression with MemberExpression argument
315
- 48 | ++updateIdentifier;
316
- 49 | updateIdentifier.y++;
317
-> 50 | updateIdentifier.y--;
305
+ 47 | ++updateIdentifier;
306
+ 48 | updateIdentifier.y++;
307
+> 49 | updateIdentifier.y--;
308
| ^^^^^^^^^^^^^^^^^^^^
319
- 51 |
320
- 52 | switch (i) {
321
- 53 | case 1 + 1: {
309
+ 50 |
310
+ 51 | switch (i) {
311
+ 52 | case 1 + 1: {
312
313
[ReactForget] TodoError: (BuildHIR::lowerStatement) Switch case test values must be identifiers or primitives, compound values are not yet supported
324
- 55 | case foo(): {
325
- 56 | }
326
-> 57 | case x.y: {
314
+ 54 | case foo(): {
315
+ 55 | }
316
+> 56 | case x.y: {
317
| ^^^
328
- 58 | }
329
- 59 | default: {
330
- 60 | }
318
+ 57 | }
319
+ 58 | default: {
320
+ 59 | }
321
322
[ReactForget] TodoError: (BuildHIR::lowerStatement) Switch case test values must be identifiers or primitives, compound values are not yet supported
333
- 53 | case 1 + 1: {
334
- 54 | }
335
-> 55 | case foo(): {
323
+ 52 | case 1 + 1: {
324
+ 53 | }
325
+> 54 | case foo(): {
326
| ^^^^^
337
- 56 | }
338
- 57 | case x.y: {
339
- 58 | }
327
+ 55 | }
328
+ 56 | case x.y: {
329
+ 57 | }
330
331
[ReactForget] TodoError: (BuildHIR::lowerStatement) Switch case test values must be identifiers or primitives, compound values are not yet supported
342
- 51 |
343
- 52 | switch (i) {
344
-> 53 | case 1 + 1: {
332
+ 50 |
333
+ 51 | switch (i) {
334
+> 52 | case 1 + 1: {
335
| ^^^^^
346
- 54 | }
347
- 55 | case foo(): {
348
- 56 | }
336
+ 53 | }
337
+ 54 | case foo(): {
338
+ 55 | }
339
340
[ReactForget] InvalidInputError: (BuildHIR::lowerAssignment) Assigning to an identifier defined outside the function scope is not supported.
351
- 62 |
352
- 63 | // Cannot assign to globals
353
-> 64 | someUnknownGlobal = true;
341
+ 61 |
342
+ 62 | // Cannot assign to globals
343
+> 63 | someUnknownGlobal = true;
344
| ^^^^^^^^^^^^^^^^^
355
- 65 | moduleLocal = true;
356
- 66 |
357
- 67 | function component(a) {
345
+ 64 | moduleLocal = true;
346
+ 65 |
347
+ 66 | function component(a) {
348
349
[ReactForget] InvalidInputError: (BuildHIR::lowerAssignment) Assigning to an identifier defined outside the function scope is not supported.
360
- 63 | // Cannot assign to globals
361
- 64 | someUnknownGlobal = true;
362
-> 65 | moduleLocal = true;
350
+ 62 | // Cannot assign to globals
351
+ 63 | someUnknownGlobal = true;
352
+> 64 | moduleLocal = true;
353
| ^^^^^^^^^^^
364
- 66 |
365
- 67 | function component(a) {
366
- 68 | // Add support for function declarations once we support `var` hoisting.
354
+ 65 |
355
+ 66 | function component(a) {
356
+ 67 | // Add support for function declarations once we support `var` hoisting.
357
358
[ReactForget] TodoError: (BuildHIR::lowerStatement) Handle FunctionDeclaration statements
369
- 65 | moduleLocal = true;
370
- 66 |
371
-> 67 | function component(a) {
359
+ 64 | moduleLocal = true;
360
+ 65 |
361
+> 66 | function component(a) {
362
| ^
373
- 68 | // Add support for function declarations once we support `var` hoisting.
374
- 69 | function t() {}
375
- 70 | t();
363
+ 67 | // Add support for function declarations once we support `var` hoisting.
364
+ 68 | function t() {}
365
+ 69 | t();
366
```
367
368
\ No newline at end of file
compiler/forget/src/__tests__/fixtures/compiler/error.todo-kitchensink.js
-1
@@ -11,7 +11,6 @@ function foo([a, b], { c, d, e = "e" }, f = "f", ...args) {
11
12
const g = { b() {}, c: () => {} };
13
new c(...args);
14
- c(...args);
14
const { z, aa = "aa" } = useCustom();
15
16
<Button xlink:href="localhost:3000"></Button>;
compiler/forget/src/__tests__/fixtures/compiler/property-call-spread.expect.md
new
+33
@@ -0,0 +1,33 @@
1
+
2
+## Input
3
+
4
+```javascript
5
+function Component(props) {
6
+ const x = foo.bar(...props.a, null, ...props.b);
7
+ return x;
8
+}
9
+
10
+```
11
+
12
+## Code
13
+
14
+```javascript
15
+function Component(props) {
16
+ const $ = React.unstable_useMemoCache(3);
17
+ const c_0 = $[0] !== props.a;
18
+ const c_1 = $[1] !== props.b;
19
+ let t0;
20
+ if (c_0 || c_1) {
21
+ t0 = foo.bar(...props.a, null, ...props.b);
22
+ $[0] = props.a;
23
+ $[1] = props.b;
24
+ $[2] = t0;
25
+ } else {
26
+ t0 = $[2];
27
+ }
28
+ const x = t0;
29
+ return x;
30
+}
31
+
32
+```
33
+
\ No newline at end of file
compiler/forget/src/__tests__/fixtures/compiler/property-call-spread.js
new
+4
@@ -0,0 +1,4 @@
1
+function Component(props) {
2
+ const x = foo.bar(...props.a, null, ...props.b);
3
+ return x;
4
+}