From 24613ba9da29fbe1783b486d41c6eedcb09d0442 Mon Sep 17 00:00:00 2001 From: Raashish Aggarwal <94279692+raashish1601@users.noreply.github.com> Date: Sat, 2 May 2026 11:07:49 +0530 Subject: [PATCH] Preserve module global snapshots in effects --- .../src/Optimization/ConstantPropagation.ts | 8 ++ ...copy-before-assignment-in-effect.expect.md | 74 +++++++++++++++++++ ...global-copy-before-assignment-in-effect.js | 21 ++++++ 3 files changed, 103 insertions(+) create mode 100644 compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/global-copy-before-assignment-in-effect.expect.md create mode 100644 compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/global-copy-before-assignment-in-effect.js diff --git a/compiler/packages/babel-plugin-react-compiler/src/Optimization/ConstantPropagation.ts b/compiler/packages/babel-plugin-react-compiler/src/Optimization/ConstantPropagation.ts index 52a5a8b8c769..ce65787940b9 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Optimization/ConstantPropagation.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Optimization/ConstantPropagation.ts @@ -231,6 +231,14 @@ function evaluateInstruction( return value; } case 'LoadGlobal': { + /* + * Module-local bindings may be reassigned by code outside the current + * function's reactive graph. A load from one of those bindings is a + * snapshot, not a constant reference that can replace later local reads. + */ + if (value.binding.kind === 'ModuleLocal') { + return null; + } return value; } case 'ComputedLoad': { diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/global-copy-before-assignment-in-effect.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/global-copy-before-assignment-in-effect.expect.md new file mode 100644 index 000000000000..defb550d8219 --- /dev/null +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/global-copy-before-assignment-in-effect.expect.md @@ -0,0 +1,74 @@ + +## Input + +```javascript +import {useEffect} from 'react'; + +let i = 0; +const log = []; + +function Component() { + useEffect(() => { + const runNumber = i; + log.push(`effect ${runNumber}`); + i += 1; + return () => { + log.push(`cleanup ${runNumber}`); + }; + }, []); + return