@samitouri / QOS-React-1 / commits / 14d54869ed

[patch][codegen] don't reuse babel nodes in codegen for dependencies

--- Reusing optionalMemberExpression nodes recently led to a bug when compiling Forget playground. ```js // the two a?.b's here should be different nodes! if (a?.b !== $[0]) { // ... $[0] = a?.b; } ``` Forget playground uses `babel-plugin-react-forget` and `next/babel`. Reusing the same node in two positions in the AST lead to invalid mutations: - the first `a?.b` is visited and transpiled to `a === void 0 ? ...`, which (1) inserts nodes between the original node and its parent and (2) mutates `a?.b` in place to a non-optional call - the second `a?.b` in source gets updated to `a.b` and does not get visited again ```js // Source in `EditorImpl.tsx` compilerOutput.kind === "err" ? compilerOutput.error.details : [] // Forget transformed: if ($[2] !== compilerOutput.kind || $[3] !== compilerOutput.error?.details) { t4 = compilerOutput.kind === "err" ? compilerOutput.error.details : []; $[2] = compilerOutput.kind; // this is good! $[3] = compilerOutput.error?.details; $[4] = t4; } else { t4 = $[4]; } // After next/babel if ($[2] !== compilerOutput.kind || $[3] !== ((_compilerOutput$error = compilerOutput.error) === null || _compilerOutput$error === void 0 ? void 0 : _compilerOutput$error.details)) { t4 = compilerOutput.kind === "err" ? compilerOutput.error.details : []; $[2] = compilerOutput.kind; // Oh no!! $[3] = _compilerOutput$error.details; $[4] = t4; } else { t4 = $[4]; } ```

Mofei Zhang committed Mar 20, 2024 at 19:29 UTC 14d54869ed934d20912fd65f12017a2b03d71008
1 file changed +2 -3
compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/CodegenReactiveFunction.ts
+2 -3
@@ -370,7 +370,6 @@ function codegenReactiveScope(
370 const outputComments: Array<string> = [];
371 for (const dep of scope.dependencies) {
372 const index = cx.nextCacheIndex;
373 - const depValue = codegenDependency(cx, dep);
373 changeExpressionComments.push(printDependencyComment(dep));
374 const comparison = t.binaryExpression(
375 "!==",
@@ -379,7 +378,7 @@ function codegenReactiveScope(
378 t.numericLiteral(index),
379 true
380 ),
382 - depValue
381 + codegenDependency(cx, dep)
382 );
383
384 if (cx.env.config.enableChangeVariableCodegen) {
@@ -402,7 +401,7 @@ function codegenReactiveScope(
401 t.numericLiteral(index),
402 true
403 ),
405 - depValue
404 + codegenDependency(cx, dep)
405 )
406 )
407 );