Commit Graph

16783 Commits

Author SHA1 Message Date
eps1lon bb3facf2ee [Fiber] Ensure useEffectEvent reads latest values in forwardRef and memo() Components (#34831)
DiffTrain build for [93d4458fdc](https://github.com/facebook/react/commit/93d4458fdc054929e54fb25017d237ed85415533)
2025-10-13 09:04:21 -07:00
sebmarkbage eacf8b80b7 [Fiber] Don't unhide a node if a direct parent offscreen is still hidden (#34821)
If an inner Offscreen commits an unhide, but an outer Offscreen is still
hidden but they're controlling the same DOM node then we shouldn't
unhide the DOM node yet.

This keeps track of whether we're directly inside a hidden offscreen. It
might be better to just do the tree search instead of keeping the stack
state since it's a rare case. Although this hide/unhide path does
trigger a lot of times even when there's no change.

This was technically a bug with Suspense too but it doesn't appear
because a suspended Suspense boundary never commits its partial state.
If it did, it would trigger this same path. But it can happen with an
outer Activity and inner Suspense.

DiffTrain build for [1d68bce19c](https://github.com/facebook/react/commit/1d68bce19c9409ed70604d1d16b70b68ce71dc4a)
2025-10-12 16:55:40 -07:00
poteto b5356aa43b [compiler] Add VoidUseMemo rule to RecommendedLatest (#34783)
Adds a new error category VoidUseMemo which is only enabled in the
RecommendedLatest preset for now.

DiffTrain build for [4b3e662e4c](https://github.com/facebook/react/commit/4b3e662e4ce54eb54a8701c48a967cc84a389501)
2025-10-08 13:01:53 -07:00
poteto bb67c72632 [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

DiffTrain build for [3e1b34dc51](https://github.com/facebook/react/commit/3e1b34dc51dfc3cbada2cdd0ead5acee6998f444)
2025-10-08 12:50:52 -07:00
poteto f0f4198266 [eprh] Prepare for 7.0.0 (#34757)
For 7.0.0:

Slim down presets to just 2 configurations:

- `recommended`: legacy and flat config with all recommended rules, and
- `recommended-latest`: legacy and flat config with all recommended
rules plus new bleeding edge experimental compiler rules

Removed:
- `recommended-latest-legacy`
- `flat/recommended`

Please see the README for new install instructions.

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/34757).
* #34783
* #34782
* __->__ #34757

DiffTrain build for [7568e71854](https://github.com/facebook/react/commit/7568e718549b85f60e3943f02d079d20d077077f)
2025-10-08 12:23:57 -07:00
poteto eb8c620a6e [eprh] Update plugin config to be compatible with flat and legacy (#34762)
This has been incredibly frustrating as [ESLint's own
docs](https://eslint.org/docs/latest/extend/plugins#backwards-compatibility-for-legacy-configs)
are clearly wrong (see #34679).

This PR uses [eslint-plugin-react's
setup](https://github.com/jsx-eslint/eslint-plugin-react/blob/master/index.js)
as a reference, where the presets are assigned to `configs.flat` (not
documented by eslint).

DiffTrain build for [848e0e3a4f](https://github.com/facebook/react/commit/848e0e3a4f12022d396ddbc2b52fd8fa7ac31fa9)
2025-10-07 13:33:21 -07:00
jackpope 9a487761ec Release Fragment refs to Canary (#34720)
## Overview

This PR adds the `ref` prop to `<Fragment>` in `react@canary`.

This means this API is ready for final feedback and prepared for a
semver stable release.

## What this means

Shipping Fragment refs to canary means they have gone through extensive
testing in production, we are confident in the stability of the APIs,
and we are preparing to release it in a future semver stable version.

Libraries and frameworks following the [Canary
Workflow](https://react.dev/blog/2023/05/03/react-canaries) should begin
implementing and testing these features.

## Why we follow the Canary Workflow

To prepare for semver stable, libraries should test canary features like
Fragment refs with `react@canary` to confirm compatibility and prepare
for the next semver release in a myriad of environments and
configurations used throughout the React ecosystem. This provides
libraries with ample time to catch any issues we missed before slamming
them with problems in the wider semver release.

Since these features have already gone through extensive production
testing, and we are confident they are stable, frameworks following the
[Canary Workflow](https://react.dev/blog/2023/05/03/react-canaries) can
also begin adopting canary features like Fragment refs.

This adoption is similar to how different Browsers implement new
proposed browser features before they are added to the standard. If a
frameworks adopts a canary feature, they are committing to stability for
their users by ensuring any API changes before a semver stable release
are opaque and non-breaking to their users.

Apps not using a framework are also free to adopt canary features like
Fragment refs as long as they follow the [Canary
Workflow](https://react.dev/blog/2023/05/03/react-canaries), but we
generally recommend waiting for a semver stable release unless you have
the capacity to commit to following along with the canary changes and
debugging library compatibility issues.

Waiting for semver stable means you're able to benefit from libraries
testing and confirming support, and use semver as signal for which
version of a library you can use with support of the feature.

## Docs

Check out the ["React Labs: View Transitions, Activity, and
more"](https://react.dev/blog/2025/04/23/react-labs-view-transitions-activity-and-more#fragment-refs)
blog post, and [the new docs for Fragment
refs`](https://react.dev/reference/react/Fragment#fragmentinstance) for
more info.

DiffTrain build for [a4eb2dfa6f](https://github.com/facebook/react/commit/a4eb2dfa6fec3da5a947eb84c99b059890bb5241)
2025-10-06 21:29:54 -07:00
jackpope 52b29f2276 Release <ViewTransition /> to Canary (#34712)
## Overview

This PR ships the View Transition APIs to `react@canary`:
- [`<ViewTransition
/>`](https://react.dev/reference/react/ViewTransition)
-
[`addTransitionType`](https://react.dev/reference/react/addTransitionType)

This means these APIs are ready for final feedback and prepare for
semver stable release.

## What this means

Shipping `<ViewTransition />` and `addTransitionType` to canary means
they have gone through extensive testing in production, we are confident
in the stability of the APIs, and we are preparing to release it in a
future semver stable version.

Libraries and frameworks following the [Canary
Workflow](https://react.dev/blog/2023/05/03/react-canaries) should begin
implementing and testing these features.

## Why we follow the Canary Workflow

To prepare for semver stable, libraries should test canary features like
`<ViewTransition />` with `react@canary` to confirm compatibility and
prepare for the next semver release in a myriad of environments and
configurations used throughout the React ecosystem. This provides
libraries with ample time to catch any issues we missed before slamming
them with problems in the wider semver release.

Since these features have already gone through extensive production
testing, and we are confident they are stable, frameworks following the
[Canary Workflow](https://react.dev/blog/2023/05/03/react-canaries) can
also begin adopting canary features like `<ViewTransition />`.

This adoption is similar to how different Browsers implement new
proposed browser features before they are added to the standard. If a
frameworks adopts a canary feature, they are committing to stability for
their users by ensuring any API changes before a semver stable release
are opaque and non-breaking to their users.

Apps not using a framework are also free to adopt canary features like
`<ViewTransition>` as long as they follow the [Canary
Workflow](https://react.dev/blog/2023/05/03/react-canaries), but we
generally recommend waiting for a semver stable release unless you have
the capacity to commit to following along with the canary changes and
debugging library compatibility issues.

Waiting for semver stable means you're able to benefit from libraries
testing and confirming support, and use semver as signal for which
version of a library you can use with support of the feature.

## Docs

Check out the ["React Labs: View Transitions, Activity, and
more"](https://react.dev/blog/2025/04/23/react-labs-view-transitions-activity-and-more#view-transitions)
blog post, and [the new docs for `<ViewTransition
/>`](https://react.dev/reference/react/ViewTransition) and
[`addTransitionType`](https://react.dev/reference/react/addTransitionType)
for more info.

DiffTrain build for [6a8c7fb6f1](https://github.com/facebook/react/commit/6a8c7fb6f1108577c97eeb5703018ece915dcdeb)
2025-10-06 21:28:53 -07:00
poteto 9898943ab4 Revert [eprh] Remove hermes-parser (#34747)
Adds back HermesParser to eslint-plugin-react-hooks. There are still
[external users of
Flow](https://github.com/facebook/react/pull/34719#issuecomment-3368137743)
using the plugin, so we shouldn't break the plugin for them. However, we
still have the problem of double parsing: once from eslint (which we
discard) and then another via babel/hermes parser.

In the long run we should investigate a translation layer from estree to
babel (or alternatively, update the compiler to take estree as input).
But for now, I am reverting the PR.

This does mean that [Sandpack in
react.dev](https://github.com/reactjs/react.dev/blob/11cb6b591571caf5fa2a192117b6a6445c3f2027/src/components/MDX/Sandpack/runESLint.tsx#L31)
cannot update to the latest eprh as HermesParser does not appear to be
able to be run in a browser. I discovered this while trying to update
eprh on react.dev last week, but didn't investigate deeply. I'll need to
double check that again to find out more.

DiffTrain build for [b65e6fc58b](https://github.com/facebook/react/commit/b65e6fc58b8c9a35e2c2ea7d1952fc1499cef09b)
2025-10-06 10:02:50 -07:00
eps1lon f17ceab328 [Fiber] Bail out of diffing wide objects and arrays (#34742)
DiffTrain build for [1be3ce9996](https://github.com/facebook/react/commit/1be3ce9996f05ceb74fd8c11f08a84a5e57098f3)
2025-10-05 16:21:06 -07:00
josephsavona cd6793729e [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>

DiffTrain build for [d6eb735938](https://github.com/facebook/react/commit/d6eb735938bc67b41ad723206ea395ba4d761139)
2025-10-03 10:16:40 -07:00
poteto 4f9bad85d4 [eprh] Remove hermes-parser (#34719)
We will be focusing eslint-plugin-react-hooks as the primary OSS-only
package for our lint plugin. eslint-plugin-react-compiler will remain as
a Meta only package as some limitations of our internal infra require us
to use packages that aren't widely adopted by the rest of the industry.

This PR removes `hermes-parser`, which was meant to support parsing Flow
syntax.

DiffTrain build for [71753ac90a](https://github.com/facebook/react/commit/71753ac90a009ddefe2f7653165902d55edd1898)
2025-10-03 10:07:07 -07:00
josephsavona 9736c57d27 [compiler] Remove @babel/plugin-proposal-private-methods (#34715)
redo of #34458 but fixing up prettier

Co-authored-by: Arnaud Barré <arnaud.barre@carbometrix.com>

DiffTrain build for [85c427d822](https://github.com/facebook/react/commit/85c427d822baad6e654256b707b7d8755da7db26)
2025-10-03 09:24:08 -07:00
poteto d1f4552318 [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

DiffTrain build for [19f65ff179](https://github.com/facebook/react/commit/19f65ff179d377ff0c9284704dff2fce370745be)
2025-10-02 16:24:59 -07:00
poteto 1332041a08 [eprh] Fix recommended config for flat config compatibility (#34700)
Previously, the `recommended` config used the legacy ESLint format
(plugins as an array of strings). This causes errors when used with
ESLint v9's `defineConfig()` helper. This was following [eslint's own
docs](https://eslint.org/docs/latest/extend/plugins#backwards-compatibility-for-legacy-configs):

> With this approach, both configuration systems recognize
"recommended". The old config system uses the recommended key while the
current config system uses the flat/recommended key. The defineConfig()
helper first looks at the recommended key, and if that is not in the
correct format, it looks for the flat/recommended key. This allows you
an upgrade path if you’d later like to rename flat/recommended to
recommended when you no longer need to support the old config system.

However,
[`isLegacyConfig()`](https://github.com/eslint/rewrite/blob/main/packages/config-helpers/src/define-config.js#L73-L81)
(also see
[`eslintrcKeys`](https://github.com/eslint/rewrite/blob/main/packages/config-helpers/src/define-config.js#L24-L35))
function doesn't check for the `plugins` key, so our config was
incorrectly treated as flat config despite being in legacy format.

This PR fixes the issue, along with a few other fixes combined:

1. Convert `recommended` to flat config format
2. Separate basic rules (exhaustive-deps, rules-of-hooks) from compiler
rules
3. Add `recommended-latest-legacy` config for non-flat config users who
want all recommended rules (including compiler rules)
4. Adding more types for the exported config

Our shipped presets in 6.x.x will essentially be:
- `recommended-legacy`: legacy (non-flat), with basic rules only
- `recommended-latest-legacy`: legacy (non-flat), all rules (basic +
compiler)
- `flat/recommended`: flat, basic rules only (now the same as
recommended, but to avoid making a breaking change we'll just keep it
around in 6.x.x)
- `recommended-latest`: flat, all rules (basic + compiler)
- `recommended`: flat, basic rules only

In the next breaking release 7.x.x, we will collapse down the presets
into three:

- `recommended-legacy`: all recommended rules
- `recommended`: all recommended rules
- `recommended-experimental`: all recommended rules + new bleeding edge
experimental rules

Closes #34679

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/34700).
* #34703
* __->__ #34700

DiffTrain build for [26b177bc5e](https://github.com/facebook/react/commit/26b177bc5e1d287c60c50fc1e185b2fb398488a0)
2025-10-02 15:58:26 -07:00
poteto ebb0c7ffeb [fixtures] Update eslint fixture lockfiles (#34699)
Updates the eslint fixture lockfiles.

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/34699).
* #34703
* #34700
* __->__ #34699
* #34675

DiffTrain build for [056a586928](https://github.com/facebook/react/commit/056a586928fe1b6186d3693743ac7019ce39cb7b)
2025-10-02 15:50:29 -07:00
gnoff fff42746c8 [Fizz] Detatch boundary after flushing segment with boundary (#34694)
When we flush a Suspense boundary we might not flush the fallback
segment, it might only flush a placeholder instead. In this case the
segment can flush again but we do not want to flush the boundary itself
a second time. We now detach the boundary after flushing it.

better solution to: https://github.com/facebook/react/pull/34668

DiffTrain build for [7d9f876cbc](https://github.com/facebook/react/commit/7d9f876cbc7e9363092e60436704cf8ae435b969)
2025-10-02 13:27:15 -07:00
josephsavona fc4307aeb9 [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.

DiffTrain build for [70b52beca6](https://github.com/facebook/react/commit/70b52beca64aeac447a6cf57cfe1fda0691435c1)
2025-10-02 10:30:21 -07:00
josephsavona e7a3c5cffe [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

DiffTrain build for [57d5a59748](https://github.com/facebook/react/commit/57d5a59748bbec1b507bb778c9fbe4bcb82b0a94)
2025-10-02 09:53:59 -07:00
sebmarkbage 87f0469566 [Fiber] Clean up ViewTransition when it fails to start (#34676)
The View Transition docs were unclear about this but apparently the
`finished` promise never settles if the animation never started. So if
there's an error that rejects the `ready` promise, we'll never run the
clean up which can cause it to stall.

Fixes #34662.

However, ultimately that is caused by Chrome stalling our default
`onDefaultTransitionIndicator` but it should be unblocked after 10
seconds, not a minute.

DiffTrain build for [d74f061b69](https://github.com/facebook/react/commit/d74f061b6908e4841b2eb09c296ca4658dbdd38e)
2025-10-01 19:03:31 -07:00
poteto 108e31bee4 [eprh] Allow compiler rules to be opted-in but not in the preset (#34672)
Follow up to #34649. This adds the compiler rules back so they can be
opted-in 6.1.0, but aren't included in the presets as that would be a
breaking change.

DiffTrain build for [ae74234eae](https://github.com/facebook/react/commit/ae74234eae6ebd62f19190731278e20bc1c37d51)
2025-10-01 14:13:45 -07:00
jackpope a2f07ff4e1 Improve lint error messages for useEffectEvent (#34669)
Called Before:

> `logEvent` is a function created with React Hook "useEffectEvent", and
can only be called from the same component.

Called After:

> `logEvent` is a function created with React Hook "useEffectEvent", and
can only be called from Effects and Effect Events in the same component.

Referenced Before:

> `logEvent` is a function created with React Hook "useEffectEvent", and
can only be called from the same component. They cannot be assigned to
variables or passed down.

Referenced After:

> `logEvent` is a function created with React Hook "useEffectEvent", and
can only be called from Effects and Effect Events in the same component.
It cannot be assigned to a variable or passed down.

DiffTrain build for [67e24bc527](https://github.com/facebook/react/commit/67e24bc5279204108b749fe48b4d395ef9e49e67)
2025-10-01 12:22:30 -07:00
sebmarkbage c604f2d7e0 Traverse down an updated tree even if it has no passive effects in profiling mode (#34667)
We need this to be able to log the renders that happened inside.

This is the same thing we do here but for the offscreen special cases:

https://github.com/facebook/react/blob/main/packages/react-reconciler/src/ReactFiberCommitWork.js#L3452-L3457

DiffTrain build for [bbc2d596fa](https://github.com/facebook/react/commit/bbc2d596fa48b64d359b96e167403693caaaabd9)
2025-10-01 10:55:23 -07:00
eps1lon dc5eef2aec Ship partial-prerendering APIs to Canary (#34633)
DiffTrain build for [1bd1f01f2a](https://github.com/facebook/react/commit/1bd1f01f2a46fa453de5099280b54385ca7773b1)
2025-10-01 09:27:37 -07:00
sebmarkbage f0ee5708d1 Fix "Consecutive" Event Logs in Performance Track (#34659)
Reset EventTime when clearing timers. We need to track repeat updates
separately.

Typically we always reset all timers when we've logged an update. The
same update shouldn't be logged again.

I was trying to be clever and not reset the XEventTime because we also
need the timestamp to know if it's a repeat event. However, because of
this it looked like we had an event schedule an update even after we had
reset them.

This always resets the XEventTime to -1.1 and then stashes the old time
on EventRepeatTime which is our indication whether the next update was a
repeat of the old event.

---------

Co-authored-by: Ruslan Lesiutin <28902667+hoxyq@users.noreply.github.com>
Co-authored-by: Ricky <rickhanlonii@gmail.com>

DiffTrain build for [7bccdbd765](https://github.com/facebook/react/commit/7bccdbd765f03254658da9086e9c5763842aa3ed)
2025-10-01 07:58:32 -07:00
poteto 2cc1516164 [eprh] Temporarily disable compiler rules (#34649)
Temporarily disables the compiler rules in eslint-plugin-react-hooks.
Will revert this later.

DiffTrain build for [cf884083e0](https://github.com/facebook/react/commit/cf884083e0cbd5aac68317585a60c937c04e4a20)
2025-09-30 15:50:34 -07:00
jackpope e064d0a923 [lint] Remove experimental gating useEffectEvent rules (#34660)
Stacked on https://github.com/facebook/react/pull/34637

`useEffectEvent` is now in canary so we need to remove this
`__EXPERIMENTAL__` gating on the rules and tests

DiffTrain build for [57b16e3788](https://github.com/facebook/react/commit/57b16e37887b324e4a077fd302b805d63421b695)
2025-09-30 14:00:56 -07:00
jbrown215 34ecbfddcf [lint] Enable custom hooks configuration for useEffectEvent calling rules (#34497)
We need to be able to specify additional effect hooks for the
RulesOfHooks lint rule
in order to allow useEffectEvent to be called by custom effects.
ExhaustiveDeps
does this with a regex suppplied to the rule, but that regex is not
accessible from
other rules.

This diff introduces a `react-hooks` entry you can put in the eslint
settings that
allows you to specify custom effect hooks and share them across all
rules.

This works like:
```
{
  settings: {
    'react-hooks': {
      additionalEffectHooks: string,
    },
  },
}
```

The next diff allows useEffect to read from the same configuration.

----

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/34497).
* #34637
* __->__ #34497

DiffTrain build for [92cfdc3a4e](https://github.com/facebook/react/commit/92cfdc3a4ed8f3350b746bd79d87f6549db8003c)
2025-09-30 13:49:41 -07:00
hoxyq 52328994c7 [Perf Tracks]: Always log effect that spawned blocking update (#34648)
We've observed some scenarios, where cascading update happens in an
effect that was shorter than 0.05ms. In this case, this effect won't be
displayed on a timeline, because of the threshold that we are using, but
it would be shown in entry properties or in a stack trace.

To avoid confusion, we should always log such effects.

Validated via manually changing the threshold to 100ms+ and observing
that only effects that triggered an update are visible on a timeline.

DiffTrain build for [063394cf82](https://github.com/facebook/react/commit/063394cf821e5082e834c72ffb9cf6f8575c9b34)
2025-09-30 12:11:13 -07:00
sebmarkbage 0a29f91f57 [Fiber] Reset remaining child lanes after propagating context inside Offscreen (#34658)
Otherwise, when a context is propagated into an Activity (or Suspense)
this will leave work behind on the Offscreen component itself. Which
will cause an extra unnecessary render and commit pass just to figure
out that we're still defering it to idle.

This is because lazy context propagation, when calling to schedule some
work walks back up the tree all the way to the root. This is usually
fine for other nodes since they'll recompute their remaining child lanes
on the way up. However, for the Offscreen component we'll have already
computed it. We need to set it after propagation to ensure it gets
reset.

DiffTrain build for [d8a15c49a4](https://github.com/facebook/react/commit/d8a15c49a4bac8fb6730737c34eaf9c74c2f0d7e)
2025-09-30 11:58:50 -07:00
javache 5106a9808d Rollout enablePersistedModeClonedFlag (#34520)
## Summary

Experimentation has completed for this at Meta and we've observed
positive impact on key React Native surfaces.

## How did you test this change?

yarn flow fabric

DiffTrain build for [ef8894452b](https://github.com/facebook/react/commit/ef8894452b826f905d69e61435c6f2c30731bfa6)
2025-09-30 04:39:51 -07:00
sebmarkbage ac910f7978 [Fiber][DevTools] Add scheduleRetry to DevTools Hook (#34635)
When forcing suspense/error we're doing that by scheduling a sync update
on the fiber. Resuspending a Suspense boundary can only happen sync
update so that makes sense. Erroring also forces a sync commit. This
means that no View Transitions fire.

However, unsuspending (and dismissing an error dialog) can be async so
the reveal should be able to be async.

This adds another hook for scheduling using the Retry lane. That way
when you play through a reveal sequence of Suspense boundaries (like
playing through the timeline), it'll run the animations that would've
ran during a loading sequence.

DiffTrain build for [8309724cb4](https://github.com/facebook/react/commit/8309724cb4a497383cc7b3267483ab5c65dad7d6)
2025-09-28 10:56:42 -07:00
hoxyq adc21166b9 flags: make enableAsyncDebugInfo dynamic for www (#34430)
As titled. This adds dev-only debugging information to Fizz / Flight
that could be used for tracking Promise's stack traces in "suspended by"
section of DevTools.

DiffTrain build for [c552618a82](https://github.com/facebook/react/commit/c552618a8203866a8bf80324f6efa708d4bdb146)
2025-09-26 11:47:51 -07:00
eps1lon c4d4bc18c1 Ensure useEffectEvent implementation is available in Canary (#34614)
DiffTrain build for [df38ac9a3b](https://github.com/facebook/react/commit/df38ac9a3b9a5ea43c1d07c00d090a448acfd56c)
2025-09-26 10:01:06 -07:00
jackpope 1106071a2b Bump useEffectEvent to Canary (#34610)
Bumps `useEffectEvent` from `@experimental` to `@canary`. Removes the
`experimental_` prefix from the export.

## TODO
- [ ] Update useEffectEvent reference page and Canary badging in docs:
https://github.com/reactjs/react.dev/pull/8025

DiffTrain build for [8bb7241f4c](https://github.com/facebook/react/commit/8bb7241f4c773376893701bfe8b8ff03687342a0)
2025-09-26 08:57:14 -07:00
sebmarkbage a0310426b8 [Fizz] Outline a Suspense Boundary if it has Suspensey CSS or Images (#34552)
We should favor outlining a boundary if it contains Suspensey CSS or
Suspensey Images since then we can load that content separately and not
block the main content. This also allows us to animate the reveal.

For example this should be able to animate the reveal even though the
actual HTML content isn't large in this case it's worth outlining so
that the JS runtime can choose to animate this reveal.

```js
<ViewTransition>
  <Suspense>
    <img src="..." />
  </Suspense>
</ViewTransition>
```

For Suspensey Images, in Fizz, we currently only implement the suspensey
semantics when a View Transition is running. Therefore the outlining
only applies if it appears inside a Suspense boundary which might
animate. Otherwise there's no point in outlining. It is also only if the
Suspense boundary itself might animate its appear and not just any
ViewTransition. So the effect is very conservative.

For CSS it applies even without ViewTransition though, since it can help
unblock the main content faster.

DiffTrain build for [6eb5d67e9c](https://github.com/facebook/react/commit/6eb5d67e9c4c5c456783dbbd454d79016c43b07d)
2025-09-25 06:53:32 -07:00
josephsavona 8669b9eb31 [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.

DiffTrain build for [8ad773b1f3](https://github.com/facebook/react/commit/8ad773b1f342d20e4773c8d086028c6927445a22)
2025-09-24 11:23:49 -07:00
josephsavona 2b6b1b4db4 [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).

DiffTrain build for [2c6d92fd80](https://github.com/facebook/react/commit/2c6d92fd80ec6917cb7387dbb771e35e82b0126d)
2025-09-24 09:23:53 -07:00
sebmarkbage fed5e2721f Track "Animating" Entry for Gestures while the Gesture is Still On-going (#34548)
Stacked on #34546.

Same as #34538 but for gestures.

Includes various fixes.

This shows how it ends with a Transition when you release in the
committed state. Note how the Animation of the Gesture continues until
the Transition is done so that the handoff is seamless.

<img width="853" height="134" alt="Screenshot 2025-09-20 at 7 37 29 PM"
src="https://github.com/user-attachments/assets/6192a033-4bec-43b9-884b-77e3a6f00da6"
/>

DiffTrain build for [e233218359](https://github.com/facebook/react/commit/e2332183591ff3a5657c3322a21bcdcccae32088)
2025-09-24 08:32:24 -07:00
eps1lon ae41e13932 Add Gesture Track in Performance Tab (#34546)
DiffTrain build for [05b61f812a](https://github.com/facebook/react/commit/05b61f812a2070276c5db0d2107808a6161632fc)
2025-09-24 08:26:08 -07:00
sebmarkbage 5f4fa92339 Include SyncLane in includesBlockingLane helper (#34543)
This helper weirdly doesn't include the sync lane.

Everywhere we use it we have to check the sync lane separately. We can
simplify things by simply including the sync lane.

This fixes a lack of optimization because we should not check the store
consistency for a `flushSync` render.

https://github.com/facebook/react/blob/d91d28c8ba6fe7c96e651f82fc47c9d5481bf5f9/packages/react-reconciler/src/ReactFiberHooks.js#L1691-L1693

DiffTrain build for [e0c421ab71](https://github.com/facebook/react/commit/e0c421ab71e26c05afe506662a4574070c13d131)
2025-09-24 06:44:34 -07:00
jbrown215 191f8c8dc2 [lint] Allow useEffectEvent in useLayoutEffect and useInsertionEffect (#34492)
---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/34492).
* #34497
* __->__ #34492

DiffTrain build for [e02c173fa5](https://github.com/facebook/react/commit/e02c173fa597ce914c6876f71556c39bf20f40dc)
2025-09-23 14:02:34 -07:00
eps1lon 1c44392116 [compiler] Export PluginOptions as a type that can be used in input positions (#34550)
DiffTrain build for [720bb13069](https://github.com/facebook/react/commit/720bb130694169f8d1bf1e8001a2177dd18cdf92)
2025-09-22 09:33:51 -07:00
sebmarkbage f1bdc931ee Use the JSX of the ViewTransition as the Stack Trace of "Animating" Traces (#34539)
Stacked on #34538.

Track the Task of the first ViewTransition that we detected as
animating. Use this as the Task as "Starting Animation", "Animating"
etc. That way you can see which ViewTransition spawned the Animation.
Although it's likely to be multiple.

<img width="757" height="393" alt="Screenshot 2025-09-19 at 10 19 18 PM"
src="https://github.com/user-attachments/assets/a6cdcb89-bd02-40ec-b3c3-11121c29e892"
/>

DiffTrain build for [d91d28c8ba](https://github.com/facebook/react/commit/d91d28c8ba6fe7c96e651f82fc47c9d5481bf5f9)
2025-09-20 08:16:57 -07:00
sebmarkbage eeb522e03f Log the time until the Animation finishes as "Animating" (#34538)
Stacked on #34522.

<img width="1025" height="200" alt="Screenshot 2025-09-19 at 6 37 28 PM"
src="https://github.com/user-attachments/assets/f25900f6-6503-48b1-876d-bd6697a29c6f"
/>

We already cover the time between "Starting Animation" and "Remaining
Effects" as "Animating". However, if the effects are forced then we can
still be animating after that. This fills in that gap.

This also fills in the gap if another render starts before the animation
finishes on the same track. It'll mark the blank space between the
previous render finishing and the next render starting as "Animating".

This should correspond roughly to the native "Animations" track.

DiffTrain build for [b4fe1e6c7e](https://github.com/facebook/react/commit/b4fe1e6c7eb3807afbbdad7bac4cc6bb2ad7efaf)
2025-09-20 08:16:18 -07:00
sebmarkbage 109631e6de Log Custom Reason for the Suspended Commit Track (#34522)
Stacked on #34511.

We currently log all Suspended Commit as "Suspended on Images or CSS"
but it can really be other reasons too now. Like waiting on the previous
View Transition. This allows the host config configure this reason.

Now when one animation starts before another one finishes we log that as
"Waiting for the previous Animation".

<img width="592" height="257" alt="Screenshot 2025-09-17 at 11 53 45 PM"
src="https://github.com/user-attachments/assets/817af8b5-37ae-46d8-bfd1-cd3fc637f3f3"
/>

DiffTrain build for [b204edda3a](https://github.com/facebook/react/commit/b204edda3aa397243faa267512811b778542f6a5)
2025-09-20 08:07:17 -07:00
sebmarkbage 9f8abe3169 Log Suspended startViewTransition Phase (#34511)
Stacked on #34510.

The "Commit" phase for a View Transition starts before the snapshot
phase (before mutation) and then stretches into the async gap of
`startViewTransition`, encompasses the mutation phase inside of its
update callback and finally the layout phase.

However, between the mutation phase and the layout phase we may suspend
the start of the view transition on fonts and/or images. In that case we
now split the Commit phase into first one before we suspend and then we
log "Waiting for Images and/or Fonts" and then another Commit phase
around the layout effects.

<img width="897" height="119" alt="Screenshot 2025-09-16 at 11 37 26 PM"
src="https://github.com/user-attachments/assets/0fe21388-bb48-4456-a594-62227d12d9b7"
/>

DiffTrain build for [ad578aa01f](https://github.com/facebook/react/commit/ad578aa01fcd08488b8378c7538d802e7a1e8b26)
2025-09-18 12:31:01 -07:00
josephsavona cf5bcb56bc [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

DiffTrain build for [581321160f](https://github.com/facebook/react/commit/581321160fe0d9d9ef461174c7e14cbbed341d28)
2025-09-18 09:40:17 -07:00
josephsavona 4ad8af040f [compiler] Don't show hint about ref-like naming if we infer another type (#34521)
Some components accept a union of a ref callback function or ref object.
In this case we may infer the type as a function due to the presence of
invoking the ref callback function. In that case, we currently report a
"Hint: name `fooRef` as "ref" or with a "-Ref" suffix..." even though
the variable is already named appropriately — the problem is that we
inferred a non-ref type. So here we check the type and don't report this
hint if we inferred another type.

DiffTrain build for [1bcdd224b1](https://github.com/facebook/react/commit/1bcdd224b10999138ef5aa1c1917b28d918e5421)
2025-09-18 09:35:00 -07:00
sebmarkbage e375e1e96e Log Performance Track Entries for View Transitions (#34510)
Stacked on #34509.

View Transitions introduces a bunch of new types of gaps in the commit
phase which needs to be logged differently in the performance track.

One thing that can happen is that a `flushSync` update forces the View
Transition to abort before it has started if it happens in the gap
before the transition is ready. In that case we log "Interrupted View
Transition".

Otherwise, when we're done in `startViewTransition` there's some work to
finalize the animations before the `ready` calllback. This is logged as
"Starting Animation".

Then there's a gap before the passive effects fire which we log as
"Animating". This can be long unless they're forced to flush early e.g.
due to another lane updating.

The "Animating" track should then pick up which doesn't do yet. This one
is tricky because this is after the actual commit phase and needs to be
interrupted by new renders which themselves can be suspended on the
animation finshing.

This PR is just a subset of all the cases. Will need a lot more work.

<img width="679" height="161" alt="Screenshot 2025-09-16 at 10 19 06 PM"
src="https://github.com/user-attachments/assets/0407372d-aaed-41f5-a262-059b2686ae87"
/>

DiffTrain build for [84af9085c1](https://github.com/facebook/react/commit/84af9085c11411e44cc5e5aee6cf00c02a78986e)
2025-09-17 10:12:22 -07:00