Skip to content

[Compiler Bug]: Incorrect closure hoisting causes runtime error #34901

@zaqqaz

Description

@zaqqaz

What kind of issue is this?

  • React Compiler core (the JS output is incorrect, or your app works incorrectly after optimization)
  • babel-plugin-react-compiler (build issue installing or using the Babel plugin)
  • eslint-plugin-react-compiler (build issue installing or using the eslint plugin)
  • react-compiler-healthcheck (build issue installing or using the healthcheck script)

Link to repro

https://playground.react.dev/#N4Igzg9grgTgxgUxALhAgHgBwjALgAgDMoA7OXASwhPzhgQENcEBlCAWwVwAsKSBzABQAdEgEp8wUflrUwBeTgT4AvPhIIA7vjacWuJYLEBuafjNw5BAMLtMq-EdUA+SWZmWS8-BABGYBBgANwQAE30lBygAgBkIOAYAGwB5f0Cghl9EhEEnFVdFehNRd3x6XFgaERoZWoAeUIog52A-AOCwiPoAOmZ5AF86gHpG5tLimv7TEjNyyvxbTFF+0RAAGhBPQgp+FBAKOxwCXABPTGVgfAAFRKh+PmTMSjl8fqIYDnwAcl9MhESALSYW73EgA+gMcgAyx2CjZGAjCjyL7TUSCKQ1IZDGGYOFMKgkACyEFCCGQ5hASUSwhAy3wYHxYG2CDA1xBDyeBLAJnW4G4EE0AEkSMwYCQkmAUIQJQh+kA

Repro steps

The React Compiler incorrectly hoists closure-scoped variables to the top level when it detects they’re only used inside a closure.

This optimization breaks lexical scoping and leads to runtime errors because the moved variable is no longer properly bound.

Original Code

export function createSomething() {
  const store = new SomeStore();

  const Cmp = () => {
    const observedStore = useLocalObservable(() => store);
    return <div>{observedStore.test}</div>;
  };

  return Cmp;
}

Compiler Output

import { c as _c } from "react/compiler-runtime";

export function createSomething() {
  const store = new SomeStore();

  const Cmp = () => {
    const $ = _c(2);
    const observedStore = useLocalObservable(_temp);
    let t0;
    if ($[0] !== observedStore.test) {
      t0 = <div>{observedStore.test}</div>;
      $[0] = observedStore.test;
      $[1] = t0;
    } else {
      t0 = $[1];
    }
    return t0;
  };

  return Cmp;
}

function _temp() {
  return store;
}

How often does this bug happen?

Every time

What version of React are you using?

19

What version of React Compiler are you using?

19.1.0-rc.3

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions