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

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",