2639 Commits

Author SHA1 Message Date
Joe Savona
8deecf5085 [compiler] Repro for false positive mutation of a value derived from props
Repro from the compiler WG (Thanks Cody!) of a case where the compiler incorrectly thinks a value is mutable.
2025-11-14 11:28:12 -08:00
Nathan
3a495ae722 [compiler] source location validator (#35109)
@josephsavona this was briefly discussed in an old thread, lmk your
thoughts on the approach. I have some fixes ready as well but wanted to
get this test case in first... there's some things I don't _love_ about
this approach, but end of the day it's just a tool for the test suite
rather than something for end user folks so even if it does a 70% good
enough job that's fine.

### refresher on the problem
when we generate coverage reports with jest (istanbul), our coverage
ends up completely out of whack due to the AST missing a ton of (let's
call them "important") source locations after the compiler pipeline has
run.

At the moment to get around this, we've been doing something a bit
unorthodox and also running our test suite with istanbul running before
the compiler -- which results in its own set of issues (for eg, things
being memoized differently, or the compiler completely bailing out on
the instrumented code, etc).

before getting in fixes, I wanted to set up a test case to start
chipping away on as you had recommended.

### how it works

The validator basically:
1. Traverses the original AST and collects the source locations for some
"important" node types
- (excludes useMemo/useCallback calls, as those are stripped out by the
compiler)
3. Traverses the generated AST and looks for nodes with matching source
locations.
4. Generates errors for source locations missing nodes in the generated
AST

### caveats/drawbacks

There are some things that don't work super well with this approach. A
more natural test fit I think would be just having some explicit
assertions made against an AST in a test file, as you can just bake all
of the assumptions/nuance in there that are difficult to handle in a
generic manner. However, this is maybe "good enough" for now.

1. Have to be careful what you put into the test fixture. If you put in
some code that the compiler just removes (for eg, a variable assignment
that is unused), you're creating a failure case that's impossible to
fix. I added a skip for useMemo/useCallback.
2. "Important" locations must exactly match for validation to pass.
- Might get tricky making sure things are mapped correctly when a node
type is completely changed, for eg, when a block statement arrow
function body gets turned into an implicit return via the body just
being an expression/identifier.
- This can/could result in scenarios where more changes are needed to
shuttle the locations through due to HIR not having a 1:1 mapping all
the babel nuances, even if some combination of other data might be good
enough even if not 10000% accurate. This might be the _right_ thing
anyways so we don't end up with edge cases having incorrect source
locations.
2025-11-12 19:02:46 -08:00
Jorge Cabiedes
5e94655cbb [compiler] _exp version of ValidateNoDerivedComputationsInEffects take precedence over stable version when enabled (#35099)
Summary:
We should only run one version of the validation. I think it makes sense
that if the exp version is enable it takes precedence over the stable
one

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/35099).
* __->__ #35099
* #35100
2025-11-11 10:16:20 -08:00
Jorge Cabiedes
db8273c12f [compiler] Update test snap to include fixture comment (#35100)
Summary:
I missed this test case failing and now having @loggerTestOnly after
landing some other PRs good to know they're not land blocking

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/35100).
* #35099
* __->__ #35100
2025-11-11 10:16:04 -08:00
Jorge Cabiedes
100fc4a8cf [compiler] Prevent local state source variables from depending on other state (#35044)
Summary:
When a local state is created sometimes it uses a `prop` or even other
local state for its initial value.

This value is only relevant on first render so we shouldn't consider it
part of our data flow

Test Plan:
Added tests
2025-11-10 12:29:34 -08:00
Jorge Cabiedes
92ac4e8b80 [compiler] Don't validate when effect cleanup function depends on effect localized setState state derived values (#35020)
Summary:
If we are using a clean up function in an effect and that clean up
function depends on a value that is used to set the state we are
validating for we shouldn't throw an error since it is a valid use case
for an effect.

Test Plan:
added test

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/35020).
* #35044
* __->__ #35020
2025-11-10 12:28:19 -08:00
Jorge Cabiedes
f76c3617e0 [compiler] Switch to track setStates by aliasing and id instead of identifier names (#34973)
Summary:
This makes the setState usage logic much more robust. We no longer rely
on identifierName.

Now we track when a setState is loaded into a new promoted identifier
variable and track this in a map `setStateLoaded` map.

For other types of instructions we consider the setState to be being
used. In this case we record its usage into the `setStateUsages` map.



Test Plan:
We expect no changes in behavior for the current tests

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/34973).
* #35044
* #35020
* __->__ #34973
* #34972
2025-11-10 12:16:27 -08:00
Jorge Cabiedes
7296120396 [compiler] Update ValidateNoDerivedComputationsInEffects_exp to log the error instead of throwing (#34972)
Summary:
TSIA

Simple change to log errors in Pipeline.ts instead of throwing in the
validation

Test Plan:
updated snap tests

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/34972).
* #35044
* #35020
* #34973
* __->__ #34972
2025-11-10 12:16:13 -08:00
Jorge Cabiedes
6347c6d373 [compiler] Fix false negatives and add data flow tree to compiler error for no-deriving-state-in-effects (#34995)
Summary:
Revamped the derivationCache graph.

This fixes a bunch of bugs where sometimes we fail to track from which
props/state we derived values from.

Also, it is more intuitive and allows us to easily implement a Data Flow
Tree.

We can print this tree which gives insight on how the data is derived
and should facilitate error resolution in complicated components

Test Plan:
Added a test case where we were failing to track derivations. Also
updated the test cases with the new error containing the data flow tree

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/34995).
* #35044
* #35020
* #34973
* #34972
* __->__ #34995
* #34967
2025-11-10 12:09:13 -08:00
Jorge Cabiedes
01fb328632 [compiler] Prevent overriding a derivationEntry on effect mutation and instead update typeOfValue and fix infinite loops (#34967)
Summary:
With this we are now comparing a snapshot of the derivationCache with
the new changes every time we are done recording the derivations
happening in the HIR.

We have to do this after recording everything since we still do some
mutations on the cache when recording mutations.



Test Plan:
Test the following in playground:
```
// @validateNoDerivedComputationsInEffects_exp

function Component({ value }) {
  const [checked, setChecked] = useState('');

  useEffect(() => {
    setChecked(value === '' ? [] : value.split(','));
  }, [value]);

  return (
    <div>{checked}</div>
  )
}
```

This no longer causes an infinite loop.

Added a test case in the next PR in the stack

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/34967).
* #35044
* #35020
* #34973
* #34972
* #34995
* __->__ #34967
2025-11-10 12:08:05 -08:00
Eugene Choi
ba0590f306 [playground] Upgrade playwright (#34991)
Some vulnerabilities were detected in older versions of Playwright,
upgrading for the playground.
2025-10-27 13:42:02 -04:00
Joseph Savona
408b38ef73 [compiler] Improve display of errors on multi-line expressions (#34963)
When a longer function or expression is identified as the source of an
error, we currently print the entire expression in our error message.
This is because we delegate to a Babel helper to print codeframes. Here,
we add some checking and abbreviate the result if it spans too many
lines.
2025-10-23 11:30:28 -07:00
Jorge Cabiedes
09056abde7 [Compiler] Improve error for calculate in render useEffect validation (#34580)
Summary:
Change error and update snapshots

The error now mentions what values are causing the issue which should
provide better context on how to fix the issue

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/34580).
* __->__ #34580
* #34579
* #34578
* #34577
* #34575
* #34574
2025-10-23 11:05:55 -07:00
Timothy Lau
6160773f30 [playground] Refactor ConfigEditor to use <Activity> component (#34958)
## Summary

This PR addresses a pending TODO comment left in
https://github.com/facebook/react/pull/34499


eb2f784e75/compiler/apps/playground/components/Editor/ConfigEditor.tsx (L37)

This change removes the temporary workaround and replaces it with
`<Activity>`, as originally intended.

## How did you test this change?

- Updated the component to use `<Activity>` directly
- Verified the editor renders correctly in both development and
production builds.
- The `<Activity>` UI updates as expected.



https://github.com/user-attachments/assets/ce976123-da59-4579-b063-b308a9167b21
2025-10-23 11:13:18 -04:00
lauren
71b3a03cc9 [forgive] Various fixes to prepare for internal sync (#34928)
Fixes a few small things:

- Update imports to reference root babel-plugin-react-compiler rather
than from `[...]/src/...`
- Remove unused cosmiconfig options parsing for now
- Update type exports in babel-plugin-react-compiler accordingly
2025-10-21 10:57:18 -04:00
Nathan
ea0c17b095 [compiler] loosen computed key restriction for compiler (#34902)
We have a whole ton of compiler errors due to us using a helper to
return breakpoints for CSS-in-js, which results in code like:

```
const styles = {
  [responsive.up('xl')]: { ... }
}
```

this results in TONS of bailouts due to `(BuildHIR::lowerExpression)
Expected Identifier, got CallExpression key in ObjectExpression`.

I was looking into what it would take to fix it and why we don't allow
it, and following the paper trail is seems like the gotchas have been
fixed with the new mutability aliasing model that is fully rolled out.
It looks like this is the same pattern/issue that was fixed (see
https://github.com/facebook/react/blob/main/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/repro-object-expression-computed-key-modified-during-after-construction-hoisted-sequence-expr.js
and the old bug in
d58c07b563/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/bug-object-expression-computed-key-modified-during-after-construction-hoisted-sequence-expr.expect.md).

@josephsavona can you confirm if that's the case and if we're able to
drop this restriction now? (or alternatively, is there another case we
can ignore?)
2025-10-20 13:52:11 -07:00
Joseph Savona
2bcbf254f1 [compiler] Fix false positive for useMemo reassigning context vars (#34904)
Within a function expression local variables may use StoreContext for
local context variables, so the reassignment check here was firing too
often. We should only report an error for variables that are declared
outside the function, ie part of its `context`.

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/34904).
* #34903
* __->__ #34904
2025-10-20 08:42:04 -07:00
Joseph Savona
c35f6a3041 [compiler] Optimize props spread for common cases (#34900)
As part of the new inference model we updated to (correctly) treat
destructuring spread as creating a new mutable object. This had the
unfortunate side-effect of reducing precision on destructuring of props,
though:

```js
function Component({x, ...rest}) {
  const z = rest.z;
  identity(z);
  return <Stringify x={x} z={z} />;
}
```

Memoized as the following, where we don't realize that `z` is actually
frozen:

```js
function Component(t0) {
  const $ = _c(6);
  let x;
  let z;
  if ($[0] !== t0) {
    const { x: t1, ...rest } = t0;
    x = t1;
    z = rest.z;
    identity(z);
...
```

#34341 was our first thought of how to do this (thanks @poteto for
exploring this idea!). But during review it became clear that it was a
bit more complicated than I had thought. So this PR explores a more
conservative alternative. The idea is:

* Track known sources of frozen values: component props, hook params,
and hook return values.
* Find all object spreads where the rvalue is a known frozen value.
* Look at how such objects are used, and if they are only used to access
properties (PropertyLoad/Destructure), pass to hooks, or pass to jsx
then we can be very confident the object is not mutated. We consider any
such objects to be frozen, even though technically spread creates a new
object.

See new fixtures for more examples.

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/34900).
* __->__ #34900
* #34887
2025-10-17 11:59:17 -07:00
Joseph Savona
adbc32de32 [compiler] More fbt compatibility (#34887)
In my previous PR I fixed some cases but broke others. So, new approach.
Two phase algorithm:

* First pass is forward data flow to determine all usages of macros.
This is necessary because many of Meta's macros have variants that can
be accessed via properties, eg you can do `macro(...)` but also
`macro.variant(...)`.
* Second pass is backwards data flow to find macro invocations (JSX and
calls) and then merge their operands into the same scope as the macro
call.

Note that this required updating PromoteUsedTemporaries to avoid
promoting macro calls that have interposing instructions between their
creation and usage. Macro calls in general are pure so it should be safe
to reorder them.

In addition, we're now more precise about `<fb:plural>`, `<fbt:param>`,
`fbt.plural()` and `fbt.param()`, which don't actually require all their
arguments to be inlined. The whole point is that the plural/param value
is an arbitrary value (along with a string name). So we no longer
transitively inline the arguments, we just make sure that they don't get
inadvertently promoted to named variables.

One caveat: we actually don't do anything to treat macro functions as
non-mutating, so `fbt.plural()` and friends (function form) may still
sometimes group arguments just due to mutability inference. In a
follow-up, i'll work to infer the types of nested macro functions as
non-mutating.

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/34887).
* #34900
* __->__ #34887
2025-10-17 11:37:28 -07:00
Joseph Savona
1324e1bb1f [compiler] Cleanup and enable validateNoVoidUseMemo (#34882)
This is a great validation, so let's enable by default. Changes:
* Move the validation logic into ValidateUseMemo alongside the new check
that the useMemo result is used
* Update the lint description
* Make the void memo errors lint-only, they don't require us to skip
compilation (as evidenced by the fact that we've had this validation
off)

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/34882).
* #34855
* __->__ #34882
2025-10-16 13:08:57 -07:00
Joseph Savona
7f5ea1bf67 [compiler] More useMemo validation (#34868)
Two additional validations for useMemo:
* Disallow reassigning to values declared outside the useMemo callback
(always on)
* Disallow unused useMemo calls (part of the validateNoVoidUseMemo
feature flag, which in turn is off by default)

We should probably enable this flag though!

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/34868).
* #34855
* #34882
* __->__ #34868
2025-10-16 13:05:18 -07:00
Henry Q. Dineen
ed1351c4fb [compiler] improve zod v3 backwards compat (#34877)
## Summary

When upgrading to `babel-plugin-react-compiler@1.0.0` in a project that
uses `zod@3` we are running into TypeScript errors like:

```
node_modules/babel-plugin-react-compiler/dist/index.d.ts:435:10 - error TS2694: Namespace '"/REDACTED/node_modules/zod/v3/external"' has no exported member 'core'.

435     }, z.core.$strip>>>;
             ~~~~
```

This problem seems to be related to
d6eb735938, which introduced zod v3/v4
compatibility. Since `zod` is bundled into the compiler source this does
not cause runtime issues and only manifests as TypeScript errors. My
proposed solution is this PR is to use zod's [subpath versioning
strategy](https://zod.dev/v4/versioning?id=versioning-in-zod-4) which
allows you to support v3 and v4 APIs on both major versions.

Changes in this PR include:

- Updated `zod` import paths to `zod/v4`
- Bumped min `zod` version to `^3.25.0` for zod which guarantees the
`zod/v4` subpath is available.
- Updated `zod-validation-error` import paths to
`zod-validation-error/v4`
- Bumped min `zod-validation-error ` version to `^3.5.0` 
- Updated `externals` tsup configuration where appropriate. 

Once the compiler drops zod v3 support we could optionally remove the
`/v4` subpath from the imports.

## How did you test this change?

Not totally sure the best way to test. I ran `NODE_ENV=production yarn
workspace babel-plugin-react-compiler run build --dts` and diffed the
`dist/` folder between my change and `v1.0.0` and it looks correct. We
have a `patch-package` patch to workaround this for now and it works as
expected.

```diff
diff --git a/node_modules/babel-plugin-react-compiler/dist/index.d.ts b/node_modules/babel-plugin-react-compiler/dist/index.d.ts
index 81c3f3d..daafc2c 100644
--- a/node_modules/babel-plugin-react-compiler/dist/index.d.ts
+++ b/node_modules/babel-plugin-react-compiler/dist/index.d.ts
@@ -1,7 +1,7 @@
 import * as BabelCore from '@babel/core';
 import { NodePath as NodePath$1 } from '@babel/core';
 import * as t from '@babel/types';
-import { z } from 'zod';
+import { z } from 'zod/v4';
 import { NodePath, Scope } from '@babel/traverse';
 
 interface Result<T, E> {
```

Co-authored-by: Henry Q. Dineen <henryqdineen@gmail.com>
2025-10-16 09:46:55 -07:00
Joseph Savona
85f415e33b [compiler] Fix fbt for the ∞th time (#34865)
We now do a single pass over the HIR, building up two data structures:
* One tracks values that are known macro tags or macro calls.
* One tracks operands of macro-related instructions so that we can later
group them.

After building up these data structures, we do a pass over the latter
structure. For each macro call instruction, we recursively traverse its
operands to ensure they're in the same scope. Thus, something like
`fbt('hello' + fbt.param(foo(), "..."))` will correctly merge the fbt
call, the `+` binary expression, the `fbt.param()` call, and `foo()`
into a single scope.

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/34865).
* #34855
* __->__ #34865
2025-10-15 16:23:31 -07:00
Joseph Savona
e096403c59 [compiler] Infer types for properties after holes in array patterns (#34847)
In InferTypes when we infer types for properties during destructuring,
we were breaking out of the loop when we encounter a hole in the array.
Instead we should just skip that element and continue inferring later
properties.

Closes #34748

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/34847).
* #34855
* __->__ #34847
2025-10-15 09:45:06 -07:00
Eugene Choi
e7984651e4 [playground] Allow accordion tabs to open on error (#34844)
There was a bug where the other output passes (aside from the "Output"
tab) were unable to open on compiler error. This PR still allows for the
"Output" tab to automatically open on error, but also allows other tabs
to be opened.


https://github.com/user-attachments/assets/157bf5d6-c289-46fd-bafb-073c2e0ff52b
2025-10-14 15:07:27 -04:00
Ian Duvall
06fcc8f380 [playground] Fix syntax error from crashing the Compiler playground (#34623)
<!--
  Thanks for submitting a pull request!
We appreciate you spending the time to work on these changes. Please
provide enough information so that others can review your pull request.
The three fields below are mandatory.

Before submitting a pull request, please make sure the following is
done:

1. Fork [the repository](https://github.com/facebook/react) and create
your branch from `main`.
  2. Run `yarn` in the repository root.
3. If you've fixed a bug or added code that should be tested, add tests!
4. Ensure the test suite passes (`yarn test`). Tip: `yarn test --watch
TestName` is helpful in development.
5. Run `yarn test --prod` to test in the production environment. It
supports the same options as `yarn test`.
6. If you need a debugger, run `yarn test --debug --watch TestName`,
open `chrome://inspect`, and press "Inspect".
7. Format your code with
[prettier](https://github.com/prettier/prettier) (`yarn prettier`).
8. Make sure your code lints (`yarn lint`). Tip: `yarn linc` to only
check changed files.
  9. Run the [Flow](https://flowtype.org/) type checks (`yarn flow`).
  10. If you haven't already, complete the CLA.

Learn more about contributing:
https://reactjs.org/docs/how-to-contribute.html
-->

## Summary

<!--
Explain the **motivation** for making this change. What existing problem
does the pull request solve?
-->

Fixes a syntax error causing the Compiler playground to crash. Resolves
https://github.com/facebook/react/issues/34622.

## How did you test this change?

<!--
Demonstrate the code is solid. Example: The exact commands you ran and
their output, screenshots / videos if the pull request changes the user
interface.
How exactly did you verify that your PR solves the issue you wanted to
solve?
  If you leave this empty, your PR will very likely be closed.
-->

Tested locally and added a test.

<img width="1470" height="836" alt="Screenshot 2025-09-27 at 8 13 07 AM"
src="https://github.com/user-attachments/assets/29473682-94c3-49dc-9ee9-c2004062aaea"
/>
2025-10-09 12:02:55 -07:00
lauren
4b3e662e4c [compiler] Add VoidUseMemo rule to RecommendedLatest (#34783)
Adds a new error category VoidUseMemo which is only enabled in the
RecommendedLatest preset for now.
2025-10-08 15:55:13 -04:00
lauren
3e1b34dc51 [compiler] Setup RecommendedLatest preset (#34782)
Renames the `recommended` property on LintRule to `preset`, to allow
exporting rules for different presets. For now the `Recommended` and
`RecommendedLatest` presets are the same, but in the next PR I will
enable more rules for the latest preset.

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/34782).
* #34783
* __->__ #34782
2025-10-08 15:45:22 -04:00
lauren
a664f5f2ee [compiler] Fix incorrect version name (#34764)
Script was using the wrong version name.

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/34764).
* #34765
* __->__ #34764
2025-10-07 14:32:51 -04:00
lauren
1384ea8230 [compiler] Update release script for latest tag (#34763)
Updates our release script so we can publish to the `latest` tag.
2025-10-07 14:14:50 -04:00
Joseph Savona
d6eb735938 [compiler] Update for Zod v3/v4 compatibility (#34717)
Partial redo of #34710. The changes there tried to use `z.function(args,
return)` to be compatible across Zod v3 and v4, but Zod 4's function API
has completely changed. Instead, I've updated to just use `z.any()`
where we expect a function, and manually validate that it's a function
before we call the value. We already have validation of the return type
(also using Zod).

Co-authored-by: kolvian <eliot@pontarelli.com>
2025-10-03 10:08:20 -07:00
Joseph Savona
85c427d822 [compiler] Remove @babel/plugin-proposal-private-methods (#34715)
redo of #34458 but fixing up prettier

Co-authored-by: Arnaud Barré <arnaud.barre@carbometrix.com>
2025-10-03 09:13:55 -07:00
Eugene Choi
0eebd37041 [playground] Config panel quality fixes (#34611)
Fixed two small issues with the config panel in the compiler playground:
1. Object descriptions were being confined in the config box and most of
it would not be visible upon hover
2. Changed it so that "Applied Configs" would only display a valid set
of configs, rather than switching between "Invalid Configs" and the set
of options. This would be less visually jarring for users as the Output
panel already displays errors. Additionally, if users want to see the
list of config options but have a currently broken config, they would
previously not know how to fix it.

Object hover before: 
<img width="702" height="481" alt="Screenshot 2025-09-26 at 10 41 03 AM"
src="https://github.com/user-attachments/assets/b2ddec2f-16ba-41a1-be1f-96211f46764c"
/>
Hover after:
<img width="702" height="481" alt="Screenshot 2025-09-26 at 10 40 37 AM"
src="https://github.com/user-attachments/assets/dc713a22-4710-46a8-a5d7-485060cc9074"
/>

Applied Configs always displays the last valid set of configs:


https://github.com/user-attachments/assets/2fb9232f-7388-4488-9b7a-bb48bf09e4ca
2025-10-03 10:52:36 -04:00
lauren
19f65ff179 [eprh] Remove NoUnusedOptOutDirectives (#34703)
This rule was a leftover from a while ago and doesn't actually lint
anything useful. Specifically, you get a lint error if you try to opt
out a component that isn't already bailing out. If there's a bailout the
compiler already safely skips over it, so adding `'use no memo'` there
is unnecessary.

Fixes #31407

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/34703).
* __->__ #34703
* #34700
2025-10-02 19:19:01 -04:00
Eugene Choi
289f070d64 [playground] Improve DiffEditor scrollbar + view (#34691)
The previous DiffEditor view of the playground looked broken and not
cohesive. There would be parts of the scrollbar appearing on the left
side for some reason, along with two scrollbars on the right side. This
PR makes the DiffEditor look more cohesive.

Previous:


https://github.com/user-attachments/assets/1aa1c775-5940-43b2-a75a-9b46452fb78b

After:


https://github.com/user-attachments/assets/b5c04998-6a6c-4b52-b3c5-b2fef21729e0
2025-10-02 17:41:29 -04:00
Joseph Savona
70b52beca6 [compiler] @enablePreserveExistingMemoizationGuarantees on by default (#34689)
This enables `@enablePreserveExistingMemoizationGuarantees` by default.
As of the previous PR (#34503), this mode now enables the following
behaviors:

- Treating variables referenced within a `useMemo()` or `useCallback()`
as "frozen" (immutable) as of the start of the call. Ie, the compiler
will assume that the values you reference are not mutated by the body of
the useMemo, not are they mutated later. Directly modifying them (eg
`var.property = true`) will be an error.
- Similarly, the results of the useMemo/useCallback are treated as
frozen (immutable) after the call.

These two rules match the behavior for other hooks: this means that
developers will see similar behavior to swapping out `useMemo()` for a
custom `useMyMemo()` wrapper/alias.

Additionally, as of #34503 the compiler uses information from the manual
dependencies to know which variables are non-nullable. Even if a useMemo
block conditionally accesses a nested property — `if (cond) { log(x.y.z)
}` — where the compiler would not usually know that `x` is non-nullable,
if the user specifies `x.y.z` as a manual dependency then the compiler
knows that `x` and `x.y` are non-nullable and can infer a more precise
dependency.

Finally, this mode also ensures that we always memoize function calls
that return primitives. See #34343 for more details.

For now, I've explicitly opted out of this feature in all test fixtures
where the behavior changed.
2025-10-02 10:25:00 -07:00
Joseph Savona
57d5a59748 [compiler] enablePreserveMemo treats manual deps as non-nullable (#34503)
The `@enablePreserveExistingMemoizationGuarantees` mode can still fail
to preserve manual memoization due to mismtached dependencies.
Specifically, where the user's dependencies are more precise than the
compiler infers bc the compiler is being conservative about what might
be nullable. In this mode though we're intentionally using information
from the manual memoization and can also rely on the deps as a signal
for what's non-nullable.

The idea of the PR is that we treat manual memo deps just like other
inferred-as-non-nullable objects during PropagateScopeDeps. We're
careful to not treat the full path as non-nullable, only up to the last
property index. So `x.y.z` as a manual dep treats `x` and `x.y` as
non-nullable, allowing us to preserve a conditional dependency on
`x.y.z`.

Optionals within manual dependencies are a bit trickier and aren't
handled yet, but hopefully that's less common and something we can
improve in a follow-up. Not handling them just means that developers may
hit false positives on validating existing memoization if they use
optional chains in manual dependencies.

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/34503).
* #34689
* __->__ #34503
2025-10-02 09:48:52 -07:00
Eugene Choi
f7254efc5c [playground] Persist open tabs on compiler error (#34673)
This change allows it so that tabs that were open before a compiler
error are automatically opened again when the error is resolved. Quality
of life change for those especially working with the advanced view of
the playground.


https://github.com/user-attachments/assets/cd2dc117-e6fc-4f57-a08f-259757c4f5e8
2025-10-01 21:26:16 -04:00
Eugene Choi
a55e98f738 [playground] ViewTransition on internals toggle & tab expansion (#34597)
<!--
  Thanks for submitting a pull request!
We appreciate you spending the time to work on these changes. Please
provide enough information so that others can review your pull request.
The three fields below are mandatory.

Before submitting a pull request, please make sure the following is
done:

1. Fork [the repository](https://github.com/facebook/react) and create
your branch from `main`.
  2. Run `yarn` in the repository root.
3. If you've fixed a bug or added code that should be tested, add tests!
4. Ensure the test suite passes (`yarn test`). Tip: `yarn test --watch
TestName` is helpful in development.
5. Run `yarn test --prod` to test in the production environment. It
supports the same options as `yarn test`.
6. If you need a debugger, run `yarn test --debug --watch TestName`,
open `chrome://inspect`, and press "Inspect".
7. Format your code with
[prettier](https://github.com/prettier/prettier) (`yarn prettier`).
8. Make sure your code lints (`yarn lint`). Tip: `yarn linc` to only
check changed files.
  9. Run the [Flow](https://flowtype.org/) type checks (`yarn flow`).
  10. If you haven't already, complete the CLA.

Learn more about contributing:
https://reactjs.org/docs/how-to-contribute.html
-->

## Summary

<!--
Explain the **motivation** for making this change. What existing problem
does the pull request solve?
-->

Added `<ViewTransition>` for when the "Show Internals" button is toggled
for a basic fade transition. Additionally added a transition for when
tabs are expanded in the advanced view of the Compiler Playground to
display a smoother show/hide animation.

## How did you test this change?

<!--
Demonstrate the code is solid. Example: The exact commands you ran and
their output, screenshots / videos if the pull request changes the user
interface.
How exactly did you verify that your PR solves the issue you wanted to
solve?
  If you leave this empty, your PR will very likely be closed.
-->


https://github.com/user-attachments/assets/c706b337-289e-488d-8cd7-45ff1d27788d
2025-09-30 15:25:10 -04:00
Eugene Choi
3580584ba2 [playground] ViewTransition on tab switch (#34596)
<!--
  Thanks for submitting a pull request!
We appreciate you spending the time to work on these changes. Please
provide enough information so that others can review your pull request.
The three fields below are mandatory.

Before submitting a pull request, please make sure the following is
done:

1. Fork [the repository](https://github.com/facebook/react) and create
your branch from `main`.
  2. Run `yarn` in the repository root.
3. If you've fixed a bug or added code that should be tested, add tests!
4. Ensure the test suite passes (`yarn test`). Tip: `yarn test --watch
TestName` is helpful in development.
5. Run `yarn test --prod` to test in the production environment. It
supports the same options as `yarn test`.
6. If you need a debugger, run `yarn test --debug --watch TestName`,
open `chrome://inspect`, and press "Inspect".
7. Format your code with
[prettier](https://github.com/prettier/prettier) (`yarn prettier`).
8. Make sure your code lints (`yarn lint`). Tip: `yarn linc` to only
check changed files.
  9. Run the [Flow](https://flowtype.org/) type checks (`yarn flow`).
  10. If you haven't already, complete the CLA.

Learn more about contributing:
https://reactjs.org/docs/how-to-contribute.html
-->

## Summary

<!--
Explain the **motivation** for making this change. What existing problem
does the pull request solve?
-->

Utilized `<ViewTransition>` to introduce a sliding animation upon
switching between the Output and SourceMap tabs in the default
playground view.

## How did you test this change?

<!--
Demonstrate the code is solid. Example: The exact commands you ran and
their output, screenshots / videos if the pull request changes the user
interface.
How exactly did you verify that your PR solves the issue you wanted to
solve?
  If you leave this empty, your PR will very likely be closed.
-->


https://github.com/user-attachments/assets/1ac93482-8104-4f9a-887e-6adca3537dca
2025-09-29 14:40:33 -04:00
Eugene Choi
319a7867d0 [playground] ViewTransition on config expand (#34595)
<!--
  Thanks for submitting a pull request!
We appreciate you spending the time to work on these changes. Please
provide enough information so that others can review your pull request.
The three fields below are mandatory.

Before submitting a pull request, please make sure the following is
done:

1. Fork [the repository](https://github.com/facebook/react) and create
your branch from `main`.
  2. Run `yarn` in the repository root.
3. If you've fixed a bug or added code that should be tested, add tests!
4. Ensure the test suite passes (`yarn test`). Tip: `yarn test --watch
TestName` is helpful in development.
5. Run `yarn test --prod` to test in the production environment. It
supports the same options as `yarn test`.
6. If you need a debugger, run `yarn test --debug --watch TestName`,
open `chrome://inspect`, and press "Inspect".
7. Format your code with
[prettier](https://github.com/prettier/prettier) (`yarn prettier`).
8. Make sure your code lints (`yarn lint`). Tip: `yarn linc` to only
check changed files.
  9. Run the [Flow](https://flowtype.org/) type checks (`yarn flow`).
  10. If you haven't already, complete the CLA.

Learn more about contributing:
https://reactjs.org/docs/how-to-contribute.html
-->

## Summary

<!--
Explain the **motivation** for making this change. What existing problem
does the pull request solve?
-->

Introduced `<ViewTransition>` to the React Compiler Playground. Added an
initial animation on the config panel opening/closing to allow for a
smoother visual experience. Previously, the panel would flash in and out
of the screen upon open/close.

## How did you test this change?

<!--
Demonstrate the code is solid. Example: The exact commands you ran and
their output, screenshots / videos if the pull request changes the user
interface.
How exactly did you verify that your PR solves the issue you wanted to
solve?
  If you leave this empty, your PR will very likely be closed.
-->




https://github.com/user-attachments/assets/9dc77a6b-d4a5-4a7a-9d81-007ebb55e8d2
2025-09-29 14:09:37 -04:00
Eugene Choi
250f1b20e0 [playground] Fix useEffect on tabify (#34594)
There was a bug in the Compiler Playground related to the "Show
Internals" toggle due to a useEffect that was causing the tab names to
flicker from a rerender. Rewritten instead with a `<Suspense>` boundary
+ `use`.
2025-09-25 14:56:41 -04:00
Joseph Savona
8ad773b1f3 [compiler] Add support for commonjs (#34589)
We previously always generated import statements for any modules that
had to be required, notably the `import {c} from
'react/compiler-runtime'` for the memo cache function. However, this
obviously doesn't work when the source is using commonjs. Now we check
the sourceType of the module and generate require() statements if the
source type is 'script'.

I initially explored using
https://babeljs.io/docs/babel-helper-module-imports, but the API design
was unfortunately not flexible enough for our use-case. Specifically,
our pipeline is as follows:
* Compile individual functions. Generate candidate imports,
pre-allocating the local names for those imports.
* If the file is compiled successfully, actually add the imports to the
program.

Ie we need to pre-allocate identifier names for the imports before we
add them to the program — but that isn't supported by
babel-helper-module-imports. So instead we generate our own require()
calls if the sourceType is script.
2025-09-24 11:17:42 -07:00
Joseph Savona
2c6d92fd80 [compiler] Name anonymous functions from inlined useCallbacks (#34586)
@eps1lon flagged this case. Inlined useCallback has an extra LoadLocal
indirection which caused us not to add a name. While I was there I added
some extra checks to make sure we don't generate names for a given node
twice (just in case).
2025-09-24 09:18:16 -07:00
Sebastian "Sebbie" Silbermann
cad813ac1e Fix CI from stale merge (#34555) 2025-09-23 08:49:16 +02:00
Sebastian "Sebbie" Silbermann
720bb13069 [compiler] Export PluginOptions as a type that can be used in input positions (#34550) 2025-09-22 18:28:19 +02:00
Eugene Choi
1eca9a2747 [playground] Add compiler playground tests (#34528)
<!--
  Thanks for submitting a pull request!
We appreciate you spending the time to work on these changes. Please
provide enough information so that others can review your pull request.
The three fields below are mandatory.

Before submitting a pull request, please make sure the following is
done:

1. Fork [the repository](https://github.com/facebook/react) and create
your branch from `main`.
  2. Run `yarn` in the repository root.
3. If you've fixed a bug or added code that should be tested, add tests!
4. Ensure the test suite passes (`yarn test`). Tip: `yarn test --watch
TestName` is helpful in development.
5. Run `yarn test --prod` to test in the production environment. It
supports the same options as `yarn test`.
6. If you need a debugger, run `yarn test --debug --watch TestName`,
open `chrome://inspect`, and press "Inspect".
7. Format your code with
[prettier](https://github.com/prettier/prettier) (`yarn prettier`).
8. Make sure your code lints (`yarn lint`). Tip: `yarn linc` to only
check changed files.
  9. Run the [Flow](https://flowtype.org/) type checks (`yarn flow`).
  10. If you haven't already, complete the CLA.

Learn more about contributing:
https://reactjs.org/docs/how-to-contribute.html
-->

## Summary

<!--
Explain the **motivation** for making this change. What existing problem
does the pull request solve?
-->

Added more tests for the compiler playground with the addition of the
new config editor and "Show Internals" button. Added testing to check
for incomplete store params in the URL, toggle functionality, and
correct errors showing for syntax/validation errors in the config
overrides.
2025-09-22 12:11:45 -04:00
Sebastian "Sebbie" Silbermann
07e4974bad [compiler] Don't leak global __DEV__ type (#34551) 2025-09-22 16:51:57 +02:00
Eugene Choi
6eda534718 [playground] bug fixes & UX improvements (#34499)
<!--
  Thanks for submitting a pull request!
We appreciate you spending the time to work on these changes. Please
provide enough information so that others can review your pull request.
The three fields below are mandatory.

Before submitting a pull request, please make sure the following is
done:

1. Fork [the repository](https://github.com/facebook/react) and create
your branch from `main`.
  2. Run `yarn` in the repository root.
3. If you've fixed a bug or added code that should be tested, add tests!
4. Ensure the test suite passes (`yarn test`). Tip: `yarn test --watch
TestName` is helpful in development.
5. Run `yarn test --prod` to test in the production environment. It
supports the same options as `yarn test`.
6. If you need a debugger, run `yarn test --debug --watch TestName`,
open `chrome://inspect`, and press "Inspect".
7. Format your code with
[prettier](https://github.com/prettier/prettier) (`yarn prettier`).
8. Make sure your code lints (`yarn lint`). Tip: `yarn linc` to only
check changed files.
  9. Run the [Flow](https://flowtype.org/) type checks (`yarn flow`).
  10. If you haven't already, complete the CLA.

Learn more about contributing:
https://reactjs.org/docs/how-to-contribute.html
-->

## Summary

Made many small changes to the compiler playground to improve user
experience. Removed any "Loading" indicators that would flash in before
a component would finish loading in. Additionally, before users would
see the "Show Internals" button toggling from false to true if they had
set it at true previously. I was able to refactor the URL/local storage
loading so that the `Store` would be fully initialized before the
components would load in.

Attempted to integrate `<Activity>` into showing/hiding these different
editors, but the current state of [monaco
editors](https://github.com/suren-atoyan/monaco-react) does not allow
for this. I created an issue for them to address:
https://github.com/suren-atoyan/monaco-react/issues/753

Added a debounce to the config editor so every key type wouldn't cause
the output panel to respond instantly. Users can type for 500 ms before
an error is thrown at them.

<!--
Explain the **motivation** for making this change. What existing problem
does the pull request solve?
-->

## How did you test this change?

Here is what loading the page would look like before (not sure why its
so blurry):


https://github.com/user-attachments/assets/58f4281a-cc02-4141-b9b5-f70d6ace12a2


Here is how it looks now:


https://github.com/user-attachments/assets/40535165-fc7c-44fb-9282-9c7fa76e7d53

Here is the debouncing:


https://github.com/user-attachments/assets/e4ab29e4-1afd-4249-beca-671fb6542f5e



<!--
Demonstrate the code is solid. Example: The exact commands you ran and
their output, screenshots / videos if the pull request changes the user
interface.
How exactly did you verify that your PR solves the issue you wanted to
solve?
  If you leave this empty, your PR will very likely be closed.
-->
2025-09-18 15:44:25 -04:00
zeki
581321160f [Compiler Bug] Complier mark ts instantiation expression as reorderable in build hir (#34488)
<!--
  Thanks for submitting a pull request!
We appreciate you spending the time to work on these changes. Please
provide enough information so that others can review your pull request.
The three fields below are mandatory.

Before submitting a pull request, please make sure the following is
done:

1. Fork [the repository](https://github.com/facebook/react) and create
your branch from `main`.
  2. Run `yarn` in the repository root.
3. If you've fixed a bug or added code that should be tested, add tests!
4. Ensure the test suite passes (`yarn test`). Tip: `yarn test --watch
TestName` is helpful in development.
5. Run `yarn test --prod` to test in the production environment. It
supports the same options as `yarn test`.
6. If you need a debugger, run `yarn test --debug --watch TestName`,
open `chrome://inspect`, and press "Inspect".
7. Format your code with
[prettier](https://github.com/prettier/prettier) (`yarn prettier`).
8. Make sure your code lints (`yarn lint`). Tip: `yarn linc` to only
check changed files.
  9. Run the [Flow](https://flowtype.org/) type checks (`yarn flow`).
  10. If you haven't already, complete the CLA.

Learn more about contributing:
https://reactjs.org/docs/how-to-contribute.html
-->

## Summary

<!--
Explain the **motivation** for making this change. What existing problem
does the pull request solve?
--> The React Compiler rejected a default parameter that contains a
TSInstantiationExpression with the todo message that the expression
cannot be safely reordered. This change teaches the reorder check in
BuildHIR.ts to treat TSInstantiationExpression as reorderable. This is
safe because TypeScript instantiation only affects types and is erased
at runtime, so it has no side effects and does not change semantics.

## How did you test this change?

```
Set-Content testfilter.txt 'ts-instantiation-default-param'

yarn test --filter --update

yarn test --filter
```


<!--
Demonstrate the code is solid. Example: The exact commands you ran and
their output, screenshots / videos if the pull request changes the user
interface.
How exactly did you verify that your PR solves the issue you wanted to
solve?
  If you leave this empty, your PR will very likely be closed.
--> I added a fixture: 
>
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/ts-instantiation-default-param.js
2025-09-18 09:34:47 -07:00