diff --git a/compiler/packages/babel-plugin-react-compiler/src/HIR/Environment.ts b/compiler/packages/babel-plugin-react-compiler/src/HIR/Environment.ts index 206bfc0bca1a4..90a352620ce35 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/HIR/Environment.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/HIR/Environment.ts @@ -246,7 +246,7 @@ export const EnvironmentConfigSchema = z.object({ /** * Enable a new model for mutability and aliasing inference */ - enableNewMutationAliasingModel: z.boolean().default(false), + enableNewMutationAliasingModel: z.boolean().default(true), /** * Enables inference of optional dependency chains. Without this flag diff --git a/compiler/packages/babel-plugin-react-compiler/src/Inference/AnalyseFunctions.ts b/compiler/packages/babel-plugin-react-compiler/src/Inference/AnalyseFunctions.ts index fff913210347d..c8726f4e4b7bb 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Inference/AnalyseFunctions.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Inference/AnalyseFunctions.ts @@ -42,8 +42,16 @@ export default function analyseFunctions(func: HIRFunction): void { * Reset mutable range for outer inferReferenceEffects */ for (const operand of instr.value.loweredFunc.func.context) { - operand.identifier.mutableRange.start = makeInstructionId(0); - operand.identifier.mutableRange.end = makeInstructionId(0); + /** + * NOTE: inferReactiveScopeVariables makes identifiers in the scope + * point to the *same* mutableRange instance. Resetting start/end + * here is insufficient, because a later mutation of the range + * for any one identifier could affect the range for other identifiers. + */ + operand.identifier.mutableRange = { + start: makeInstructionId(0), + end: makeInstructionId(0), + }; operand.identifier.scope = null; } break; diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/aliased-nested-scope-truncated-dep.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/aliased-nested-scope-truncated-dep.expect.md index 933fafff5f1ba..12c7b4d5eab93 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/aliased-nested-scope-truncated-dep.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/aliased-nested-scope-truncated-dep.expect.md @@ -175,21 +175,14 @@ import { * and mutability. */ function Component(t0) { - const $ = _c(4); + const $ = _c(2); const { prop } = t0; let t1; if ($[0] !== prop) { const obj = shallowCopy(prop); const aliasedObj = identity(obj); - let t2; - if ($[2] !== obj) { - t2 = [obj.id]; - $[2] = obj; - $[3] = t2; - } else { - t2 = $[3]; - } - const id = t2; + + const id = [obj.id]; mutate(aliasedObj); setPropertyByKey(aliasedObj, "id", prop.id + 1); diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load-2-iife.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load-2-iife.expect.md index 2afc5fd25dbac..50480f1b2515e 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load-2-iife.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load-2-iife.expect.md @@ -25,17 +25,25 @@ export const FIXTURE_ENTRYPOINT = { ```javascript import { c as _c } from "react/compiler-runtime"; function bar(a) { - const $ = _c(2); - let y; + const $ = _c(4); + let t0; if ($[0] !== a) { - const x = [a]; + t0 = [a]; + $[0] = a; + $[1] = t0; + } else { + t0 = $[1]; + } + const x = t0; + let y; + if ($[2] !== x[0][1]) { y = {}; y = x[0][1]; - $[0] = a; - $[1] = y; + $[2] = x[0][1]; + $[3] = y; } else { - y = $[1]; + y = $[3]; } return y; } diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load-3-iife.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load-3-iife.expect.md index f0267c3309f5b..9678918b3d27f 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load-3-iife.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load-3-iife.expect.md @@ -29,20 +29,29 @@ export const FIXTURE_ENTRYPOINT = { ```javascript import { c as _c } from "react/compiler-runtime"; function bar(a, b) { - const $ = _c(3); - let y; + const $ = _c(6); + let t0; if ($[0] !== a || $[1] !== b) { - const x = [a, b]; + t0 = [a, b]; + $[0] = a; + $[1] = b; + $[2] = t0; + } else { + t0 = $[2]; + } + const x = t0; + let y; + if ($[3] !== x[0][1] || $[4] !== x[1][0]) { y = {}; let t = {}; y = x[0][1]; t = x[1][0]; - $[0] = a; - $[1] = b; - $[2] = y; + $[3] = x[0][1]; + $[4] = x[1][0]; + $[5] = y; } else { - y = $[2]; + y = $[5]; } return y; } diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load-4-iife.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load-4-iife.expect.md index 22728aaf4323d..edddf3715a453 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load-4-iife.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load-4-iife.expect.md @@ -25,17 +25,25 @@ export const FIXTURE_ENTRYPOINT = { ```javascript import { c as _c } from "react/compiler-runtime"; function bar(a) { - const $ = _c(2); - let y; + const $ = _c(4); + let t0; if ($[0] !== a) { - const x = [a]; + t0 = [a]; + $[0] = a; + $[1] = t0; + } else { + t0 = $[1]; + } + const x = t0; + let y; + if ($[2] !== x[0].a[1]) { y = {}; y = x[0].a[1]; - $[0] = a; - $[1] = y; + $[2] = x[0].a[1]; + $[3] = y; } else { - y = $[1]; + y = $[3]; } return y; } diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load-iife.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load-iife.expect.md index 60f829cdc4d66..c9ce6dda9f627 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load-iife.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/capturing-function-alias-computed-load-iife.expect.md @@ -24,17 +24,25 @@ export const FIXTURE_ENTRYPOINT = { ```javascript import { c as _c } from "react/compiler-runtime"; function bar(a) { - const $ = _c(2); - let y; + const $ = _c(4); + let t0; if ($[0] !== a) { - const x = [a]; + t0 = [a]; + $[0] = a; + $[1] = t0; + } else { + t0 = $[1]; + } + const x = t0; + let y; + if ($[2] !== x[0]) { y = {}; y = x[0]; - $[0] = a; - $[1] = y; + $[2] = x[0]; + $[3] = y; } else { - y = $[1]; + y = $[3]; } return y; } diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-impure-functions-in-render.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-impure-functions-in-render.expect.md index a67d467df8cfd..0fb17a8f6eab4 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-impure-functions-in-render.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-impure-functions-in-render.expect.md @@ -20,7 +20,7 @@ function Component() { 2 | 3 | function Component() { > 4 | const date = Date.now(); - | ^^^^^^^^ InvalidReact: Calling an impure function can produce unstable results. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#components-and-hooks-must-be-idempotent). `Date.now` is an impure function whose results may change on every call (4:4) + | ^^^^^^^^^^ InvalidReact: Calling an impure function can produce unstable results. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#components-and-hooks-must-be-idempotent). `Date.now` is an impure function whose results may change on every call (4:4) InvalidReact: Calling an impure function can produce unstable results. (https://react.dev/reference/rules/components-and-hooks-must-be-pure#components-and-hooks-must-be-idempotent). `performance.now` is an impure function whose results may change on every call (5:5) diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-non-imported-reanimated-shared-value-writes.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-non-imported-reanimated-shared-value-writes.expect.md index f1399a41b6fec..d3bb7f413622b 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-non-imported-reanimated-shared-value-writes.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.invalid-non-imported-reanimated-shared-value-writes.expect.md @@ -27,7 +27,7 @@ function SomeComponent() { 9 | return ( 10 |