Support multiple declarations in for init
This was an oversight in codegen. The entire pipeline supports multiple values in a for initializer, but codegen was dropping all but the first initializer.
Joe Savona committed
Mar 13, 2024 at 15:45 UTC
ca8e0d4527302f6af6a7890ba6e19b5eb5ebaa97
4 files changed
+40
-7
compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/CodegenReactiveFunction.ts
+21
-4
@@ -965,14 +965,31 @@ function codegenForInit(
965
instruction,
966
}))
967
).body;
968
- const declaration = body[0]!;
969
- CompilerError.invariant(declaration.type === "VariableDeclaration", {
968
+ const declarators: Array<t.VariableDeclarator> = [];
969
+ let kind: "let" | "const" = "const";
970
+ body.forEach((instr) => {
971
+ CompilerError.invariant(
972
+ instr.type === "VariableDeclaration" &&
973
+ (instr.kind === "let" || instr.kind === "const"),
974
+ {
975
+ reason: "Expected a variable declaration",
976
+ loc: init.loc,
977
+ description: null,
978
+ suggestions: null,
979
+ }
980
+ );
981
+ if (instr.kind === "let") {
982
+ kind = "let";
983
+ }
984
+ declarators.push(...instr.declarations);
985
+ });
986
+ CompilerError.invariant(declarators.length > 0, {
987
reason: "Expected a variable declaration",
988
+ loc: init.loc,
989
description: null,
972
- loc: declaration.loc ?? null,
990
suggestions: null,
991
});
975
- return declaration;
992
+ return t.variableDeclaration(kind, declarators);
993
} else {
994
return codegenInstructionValueToExpression(cx, init);
995
}
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/for-multiple-variable-declarations-in-initializer.expect.md
+14
-2
@@ -12,6 +12,11 @@ function Component(props) {
12
return items;
13
}
14
15
+export const FIXTURE_ENTRYPOINT = {
16
+ fn: Component,
17
+ params: [{ items: ["a", "b", 42] }],
18
+};
19
+
20
```
21
22
## Code
@@ -23,7 +28,7 @@ function Component(props) {
28
let items;
29
if ($[0] !== props.items) {
30
items = [];
26
- for (let i = 0; i < length; i++) {
31
+ for (let i = 0, length = props.items.length; i < length; i++) {
32
items.push(props.items[i]);
33
}
34
$[0] = props.items;
@@ -34,5 +39,12 @@ function Component(props) {
39
return items;
40
}
41
42
+export const FIXTURE_ENTRYPOINT = {
43
+ fn: Component,
44
+ params: [{ items: ["a", "b", 42] }],
45
+};
46
+
47
```
38
-
\ No newline at end of file
48
+
49
+### Eval output
50
+(kind: ok) ["a","b",42]
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/for-multiple-variable-declarations-in-initializer.js
+5
@@ -7,3 +7,8 @@ function Component(props) {
7
8
return items;
9
}
10
+
11
+export const FIXTURE_ENTRYPOINT = {
12
+ fn: Component,
13
+ params: [{ items: ["a", "b", 42] }],
14
+};
compiler/packages/snap/src/SproutTodoFilter.ts
-1
@@ -535,7 +535,6 @@ const skipFilter = new Set([
535
"bug-jsx-memberexpr-tag-in-lambda",
536
"bug-invalid-code-when-bailout",
537
"component-syntax-ref-gating.flow",
538
- "for-multiple-variable-declarations-in-initializer",
538
539
// 'react-forget-runtime' not yet supported
540
"flag-enable-emit-hook-guards",