Commit Graph

1288 Commits

Author SHA1 Message Date
jackpope a4ffeb264d Ship enableFabricCompleteRootInCommitPhase (#33064)
This was shipped internally. Cleaning up the flag.

DiffTrain build for [edf550b679](https://github.com/facebook/react/commit/edf550b67936f2c62534ad5549bf580a4f581bd8)
2025-05-05 10:43:14 -07:00
eps1lon 59155fde4b [Flight] Prevent serialized size leaking across requests (#33121)
DiffTrain build for [b9cfa0d308](https://github.com/facebook/react/commit/b9cfa0d3083f80bdd11ba76a55aa08fa659b7359)
2025-05-05 09:37:30 -07:00
mofeiZ fbdaa3f702 [compiler][repro] Nested fbt test fixture (#32779)
Ideally we should detect and bail out on this case to avoid babel build
failures.

DiffTrain build for [c129c2424b](https://github.com/facebook/react/commit/c129c2424b662a371865a0145c562a1cf934b023)
2025-05-05 08:59:49 -07:00
mofeiZ 45b4735773 [compiler][bugfix] Bail out when a memo block declares hoisted fns (#32765)
Note that bailing out adds false positives for hoisted functions whose
only references are within other functions. For example, this rewrite
would be safe.
```js
// source program
  function foo() {
    return bar();
  }
  function bar() {
    return 42;
  }

// compiler output
let bar;
if (/* deps changed */) {
  function foo() {
    return bar();
  }
  bar = function bar() {
    return 42;
  }
}
```
These false positives are difficult to detect because any maybe-call of
foo before the definition of bar would be invalid.

Instead of bailing out, we should rewrite hoisted function declarations
to the following form.
```js
let bar$0;
if (/* deps changed */) {
  // All references within the declaring memo block
  // or before the function declaration should use
  // the original identifier `bar`
  function foo() {
    return bar();
  }
  function bar() {
    return 42;
  }
  bar$0 = bar;
}
// All references after the declaring memo block
// or after the function declaration should use
// the rewritten declaration `bar$0`
```

DiffTrain build for [0c1575cee8](https://github.com/facebook/react/commit/0c1575cee8a78dd097edcafc307522ad000e372c)
2025-05-05 08:52:26 -07:00
eps1lon d45b272868 [eslint-plugin-react-hooks] update doc url for rules of hooks (#33118)
DiffTrain build for [3ec88e797f](https://github.com/facebook/react/commit/3ec88e797f7352c87cb79292b02fdfc53050133f)
2025-05-05 08:44:00 -07:00
eps1lon 16e2c886df [Flight] Use valid CSS selectors in useId format (#33099)
DiffTrain build for [0ca8420f9d](https://github.com/facebook/react/commit/0ca8420f9d051285c452a590ac4a4c9476406bef)
2025-05-04 04:56:36 -07:00
josephsavona d3ae62070c [compiler] Validate against mutable functions being frozen
This revisits a validation I built a while ago, trying to make it more strict this time to ensure that it's high-signal.

We detect function expressions which are *known* mutable — they definitely can modify a variable defined outside of the function expression itself (modulo control flow). This uses types to look for known Store and Mutate effects only, and disregards mutations of effects. Any such function passed to a location with a Freeze effect is reported as a validation error.

This is behind a flag and disabled by default. If folks agree this makes sense to revisit, i'll test out internally and we can consider enabling by default.

ghstack-source-id: 075a731444
Pull Request resolved: https://github.com/facebook/react/pull/33079

DiffTrain build for [0db8db178c](https://github.com/facebook/react/commit/0db8db178c1521f979535bdba32bf9db9f47ca05)
2025-05-02 17:22:33 -07:00
josephsavona 31e777b1b6 [compiler] ValidatePreservedManualMemoization reports detailed errors
This pass didn't previously report the precise difference btw inferred/manual dependencies unless a debug flag was set. But the error message is really good (nice job mofeiz): the only catch is that in theory the inferred dep could be a temporary that can't trivially be reported to the user.

But the messages are really useful for quickly verifying why the compiler couldn't preserve memoization. So here we switch to outputting a detailed message about the discrepancy btw inferred/manual deps so long as the inferred dep root is a named variable. I also slightly adjusted the message to handle the case where there is no diagnostic, which can occur if there were no manual deps but the compiler inferred a dependency.

ghstack-source-id: 534f6f1fec
Pull Request resolved: https://github.com/facebook/react/pull/33095

DiffTrain build for [73d7e816b7](https://github.com/facebook/react/commit/73d7e816b7746c700ab843964aaf11c17351fac1)
2025-05-02 17:15:46 -07:00
josephsavona 4c4b5dcb6f [compiler] Fix for string attribute values with emoji
If a JSX attribute value is a string that contains unicode or other characters that need special escaping, we wrap the attribute value in an expression container. However, our unicode to detect this only handled the basic unicode character plane, not the "astral" plane which includes emojis.

This PR updates the regex to detect such extended characters and also use an expression container.

ghstack-source-id: 6d9c8e4dd2
Pull Request resolved: https://github.com/facebook/react/pull/33096

DiffTrain build for [ac2cae5245](https://github.com/facebook/react/commit/ac2cae524576b8091a6d78d9ab05627053949df1)
2025-05-02 17:14:24 -07:00
kassens e088016fbd [eslint-plugin-react-hooks] move eslint plugin once again (#33110)
DiffTrain build for [66de8e5a99](https://github.com/facebook/react/commit/66de8e5a9975a4b53734ebed8a1c1f07892426a8)
2025-05-02 15:21:33 -07:00
poteto a405810329 [mcp] Prompt improvements for smarter tool composition (#33108)
Our runtime results are still bogus, but so far this tweak let's the llm
use the tools a little more intelligently.

example:
---

```js
import React from 'react';

function App() {
  const [count, setCount] = React.useState(0);
  const [data, setData] = React.useState([]);

  React.useEffect(() => {
    const processData = () => {
      console.log("Processing data...");
      const newData = [];
      for (let i = 0; i < 1000000000; i++) {
        newData.push({ id: i, value: Math.random() * count });
      }
      return newData;
    };

    const processedData = processData();
    setData(processedData);
  }, [count]);

  return (
    <div>
      <p>Count: {count}</p>
      <p>Data Length: {data.length}</p>
      <ul>
        {data.slice(0, 5).map((item) => (
          <li key={item.id}>Item {item.id}: {item.value.toFixed(2)}</li>
        ))}
      </ul>
    </div>
  );
};
```
why is this component slow? use the react tools to figure this out.

> I'll analyze why this component is slow using the React tools. Let's
first evaluate the performance of the original code.
>
[review-react-runtime ...]
>
> The performance measurement tool timed out, which is a strong
indication of just how severe the performance issue is in this
component. Let's now try to compile the code to see if React Compiler
can identify any issues:
>
[compile...]
>
> Now I understand the issue. Let's analyze why this component > is
extremely slow:
> Main Performance Issues:
>
> Massive Data Processing: The component is trying to create an array
with a billion (1,000,000,000) objects in the processData function. This
is an enormous amount of data that will:
>
> Consume massive amounts of memory
> Take an extremely long time to process
> Likely crash the browser
>
>
> Unnecessary Recalculation: The effect depends on [count], meaning
every time the count changes, it will reprocess this enormous dataset.
> Inefficient Data Handling: Even though only 5 items are displayed, the
component processes a billion items.
>
> Let's fix these issues:
>
[compile...]
>
> Now let's check if our modified code performs better:
>
[review-react-runtime...]
>
> Excellent! The performance has dramatically improved. Now let's check
the React documentation to make sure we're following the best practices:
>
[query-react-dev-docs...]

(hit the maximum length conversation limit because i'm on a free plan)

DiffTrain build for [26ecc98a00](https://github.com/facebook/react/commit/26ecc98a0014700524e78d938e3654c73213cf3b)
2025-05-02 14:58:11 -07:00
kassens ee8cbecf82 [eslint-plugin-react-hooks] another CI update... (#33107)
We currently created a nested directory, this should remove that.

See:

https://github.com/facebook/react/tree/builds/facebook-fbsource/compiled-rn/facebook-fbsource/xplat/js/RKJSModules/vendor/react/eslint-plugin-react-hooks/eslint-plugin-react-hooks

DiffTrain build for [f0ca53d133](https://github.com/facebook/react/commit/f0ca53d1337780ccfd49c132170d378c789cb463)
2025-05-02 14:12:21 -07:00
poteto 703c496bfd [mcp] Fix unresolved imports (#33105)
We need to explicitly import the modules so they'll be inlined correctly
into the bundle.

DiffTrain build for [e39b380a21](https://github.com/facebook/react/commit/e39b380a21aa4ef48d5880aa2c800ec5b1b044bd)
2025-05-02 14:01:14 -07:00
kassens 6a15b09f98 Add missing copyright header (#33106)
This made the build fail since there was no file header comment.

DiffTrain build for [9de0304ad7](https://github.com/facebook/react/commit/9de0304ad72bc3f8a77d2d84efa530b8051d1c15)
2025-05-02 13:59:14 -07:00
sebmarkbage 7f00c48042 [Fizz] Add "Queued" Status to SSR:ed Suspense Boundaries (#33087)
Stacked on #33076.

This fixes a bug where we used the "complete" status but the
DOMContentLoaded event. This checks for not "loading" instead.

We also add a new status where the boundary has been marked as complete
by the server but has not yet flushed either due to being throttled,
suspended on CSS or animating.

DiffTrain build for [0ed6ceb9f6](https://github.com/facebook/react/commit/0ed6ceb9f6c19f28c504cf46193cef40166a61f6)
2025-05-01 13:18:31 -07:00
jackpope e4b4f1304c Add Fragment Refs to Fabric with intersection observer support (#33056)
Adds Fragment Ref support to RN through the Fabric config, starting with
`observeUsing`/`unobserveUsing`. This is mostly a copy from the
implementation on DOM, and some of it can likely be shared in the future
but keeping it separate for now and we can refactor as we add more
features.

Added a basic test with Fabric, but testing specific methods requires so
much mocking that it doesn't seem valuable here.

I built Fabric and ran on the Catalyst app internally to test with
intersection observers end to end.

DiffTrain build for [408d055a3b](https://github.com/facebook/react/commit/408d055a3b89794088130ed39bf42ca540766275)
2025-04-30 07:55:26 -07:00
sebmarkbage f1021c7e9f Hack to recover from reading the wrong Fiber (#33055)
`requestFormReset` incorrectly tries to get the current dispatch queue
from the Fiber. However, the Fiber might be the workInProgress which is
an inconsistent state.

This hack just tries the other Fiber if it detects one of the known
inconsistent states but there can be more.

Really we should stash the dispatch queue somewhere stateful which is
effectively what `setState` does by binding it to the closure.

DiffTrain build for [88b9767404](https://github.com/facebook/react/commit/88b976740467f9dfabae03c79a8eff9033c35050)
2025-04-29 13:16:55 -07:00
javache 63af232d46 [react-native] Pull up enableFastAddPropertiesInDiffing check (#33043)
## Summary

We don't need the isArray check for this experiment, as
`fastAddProperties` already does the same. Also renaming
slowAddProperties to make it clearer we can fully remove this codepath
once fastAddProperties is fully rolled out.

## How did you test this change?

```
yarn test packages/react-native-renderer -r=xplat --variant=true
```

DiffTrain build for [0038c501a3](https://github.com/facebook/react/commit/0038c501a307e5ddc0cb80027e55740ddda09520)
2025-04-29 03:16:29 -07:00
sebmarkbage 520902d9c2 Implement Partial Hydration for Activity (#32863)
Stacked on #32862 and #32842.

This means that Activity boundaries now act as boundaries which can have
their effects mounted independently. Just like Suspense boundaries, we
hydrate the outer content first and then start hydrating the content in
an Offscreen lane. Flowing props or interacting with the content
increases the priority just like Suspense boundaries.

This skips emitting even the comments for `<Activity mode="hidden">` so
we don't hydrate those. Instead those are deferred to a later client
render.

The implementation are just forked copies of the SuspenseComponent
branches and then carefully going through each line and tweaking it.

The main interesting bit is that, unlike Suspense, Activity boundaries
don't have fallbacks so all those branches where you might commit a
suspended tree disappears. Instead, if something suspends while
hydration, we can just leave the dehydrated content in place. However,
if something does suspend during client rendering then it should bubble
up to the parent. Therefore, we have to be careful to only
pushSuspenseHandler when hydrating. That's really the main difference.

This just uses the existing basic Activity tests but I've started work
on port all of the applicable Suspense tests in SelectiveHydration-test
and PartialHydration-test to Activity versions.

DiffTrain build for [3ef31d196a](https://github.com/facebook/react/commit/3ef31d196a83e45d4c70b300a265a9c657c386b4)
2025-04-22 18:07:47 -07:00
sebmarkbage 1ed5cd364a Implement ActivityInstance in FiberConfigDOM (#32842)
Stacked on #32851 and #32900.

This implements the equivalent Configs for ActivityInstance as we have
for SuspenseInstance. These can be implemented as comments but they
don't have to be and can be implemented differently in the renderer.

This seems like a lot duplication but it's actually ends mostly just
calling the same methods underneath and the wrappers compiles out.

This doesn't leave the Activity dehydrated yet. It just hydrates into it
immediately.

DiffTrain build for [17f88c80ed](https://github.com/facebook/react/commit/17f88c80ed20b4e5f21255d9e1268542a2fbc1bd)
2025-04-22 16:50:48 -07:00
sebmarkbage b480230f1b Set hidden Offscreen to the shellBoundary regardless of previous state (#32844)
I think this was probably just copy-paste from the Suspense path.

It shouldn't matter what the previous state of an Offscreen boundary
was. What matters is that it's now hidden and therefore if it suspends,
we can just leave it as is without the tree becoming inconsistent.

DiffTrain build for [3fbd6b7b50](https://github.com/facebook/react/commit/3fbd6b7b50e3a174883633695586b892249e5635)
2025-04-22 16:45:55 -07:00
sebmarkbage f75bdfdeac Hide/unhide the content of dehydrated suspense boundaries if they resuspend (#32900)
Found this bug while working on Activity. There's a weird edge case when
a dehydrated Suspense boundary is a direct child of another Suspense
boundary which is hydrated but then it resuspends without forcing the
inner one to hydrate/delete.

It used to just leave that in place because hiding/unhiding didn't deal
with dehydrated fragments.

Not sure this is really worth fixing.

DiffTrain build for [ebf7318e87](https://github.com/facebook/react/commit/ebf7318e87cf2e10b6bd9a6bb0ad8bf6f6186f80)
2025-04-22 16:35:26 -07:00
sebmarkbage 6c77e921d6 Don't try to hydrate a hidden Offscreen tree (#32862)
I found a bug even before the Activity hydration stuff.

If we're hydrating an Offscreen boundary in its "hidden" state it won't
have any content to hydrate so will trigger hydration errors (which are
then eaten by the Offscreen boundary itself). Leaving it not prewarmed.

This doesn't happen in the simple case because we'd be hydrating at a
higher priority than Offscreen at the root, and those are deferred to
Offscreen by not having higher priority. However, we've hydrating at the
Offscreen priority, which we do inside Suspense boundaries, then it
tries to hydrate against an empty set.

I ended up moving this to the Activity boundary in a future PR since
it's the SSR side that decided where to not render something and it only
has a concept of Activity, no Offscreen.

https://github.com/facebook/react/pull/32863/commits/1dc05a5e2222e18fc3a2062ee1bd957109e21344#diff-d5166797ebbc5b646a49e6a06a049330ca617985d7a6edf3ad1641b43fde1ddfR1111

DiffTrain build for [b04254fdce](https://github.com/facebook/react/commit/b04254fdcee30871760301f34236ee0dfadf86ab)
2025-04-15 14:49:57 -07:00
sebmarkbage a0c6870f0c Warn if you pass a hidden prop to Activity (#32916)
Since `hidden` is a prop on arbitrary DOM elements it's a common mistake
to think that it would also work that way on `<Activity>` but it
doesn't. In fact, we even had this mistakes in our own tests.

Maybe there's an argument that we should actually just support it but we
also have more modes planned.

So this adds a warning. It should also already be covered by TypeScript.

DiffTrain build for [539bbdbd86](https://github.com/facebook/react/commit/539bbdbd86d9cd342aabde4cb08e398751789103)
2025-04-15 14:23:51 -07:00
sebmarkbage 609b3ae8de Try not. Do... or do not. Hydrate Suspense Boundaries. (#32851)
Assertively claim a SuspenseInstance. We already know we're hydrating.

If there's no match, it throws anyway. So there's no other code path.

DiffTrain build for [961b625ab5](https://github.com/facebook/react/commit/961b625ab5d180180e836e0c7b221789f0ee336b)
2025-04-11 07:58:07 -07:00
sebmarkbage 0e2734eb2f Emit Preamble Contribution inline instead of the end of a boundary (#32850)
This lets us write them early in the render phase.

This should be safe because even if we write them deeply, then they
still can't be wrapped by a element because then they'd no longer be in
the document scope anymore. They end up flat in the body and so when we
search the content we'll discover them.

DiffTrain build for [8a3c5e1a8d](https://github.com/facebook/react/commit/8a3c5e1a8d1d89a68ca36c6959c1f253710f6cef)
2025-04-10 16:47:41 -07:00
rubennorte 3aee0d9b2a [RN] Map Fabric priorities to reconciler priorities correctly (#32847)
## Summary

This fixes how we map priorities between Fabric and the React
reconciler. At the moment, we're only considering default and discrete
priorities, when there's a larger range of priorities available.

In Fabric, we'll test supporting additional priorities soon. For that
test to do something useful, we need the new priorities to be mapped to
reconciler priorities correctly, which is what this change is done.

> [!IMPORTANT]
> At the moment, this is a no-op because Fabric is only reporting
default and discrete event priorities.

## How did you test this change?

Will test e2e on React Native on top of
https://github.com/facebook/react-native/pull/50627

The changes are gated in React Native, so we'll use that feature flag to
test this.

DiffTrain build for [5e9b48778c](https://github.com/facebook/react/commit/5e9b48778c83dd8b2c63966db3e23abefebe910c)
2025-04-10 09:40:48 -07:00
sebmarkbage 0a20a318f6 Move Built-in Props Types to React Types (#32841)
Stacked on #32838.

We don't always type the Props of built-ins. This adds typing for most
of the built-ins.

When we did type them, we used to put it in the `ReactFiber...Component`
files but any public API like this can be implemented in other renderers
too such as Fizz. So I moved them to `shared/ReactTypes` which is where
we put other public API types (that are not already built-in to Flow).
That way Fizz can import them and assert properly when it accesses the
props.

DiffTrain build for [c44e4a2505](https://github.com/facebook/react/commit/c44e4a250557e53b120e40db8b01fb5fd93f1e35)
2025-04-09 19:52:23 -07:00
sebmarkbage 6ea2efb3ca Clarify that there's three different kinds of OffscreenProps (#32838)
ActivityProps - Public API
LegacyHiddenProps - Public Legacy API
OffscreenProps - Internal implementation detail

DiffTrain build for [31ecc9804a](https://github.com/facebook/react/commit/31ecc9804a3f263033611f069774e50059c0743a)
2025-04-09 19:31:01 -07:00
sebmarkbage 32ddf34caf Enable Suspensey Images inside <ViewTransition> subtrees (#32820)
Even if the `enableSuspenseyImages` flag is off.

Started View Transitions already wait for Suspensey Fonts and this is
another Suspensey feature that is even more important for View
Transitions - even though we eventually want it all the time. So this
uses `<ViewTransition>` as an early opt-in for that tree into Suspensey
Images, which we can ship in a minor.

If you're doing an update inside a ViewTransition then we're eligible to
start a ViewTransition in any Transition that might suspend. Even if
that doesn't end up animating after all, we still consider it Suspensey.
We could try to suspend inside the startViewTransition but that's not
how it would work with `enableSuspenseyImages` on and we can't do that
for startGestureTransition.

Even so we still need some opt-in to trigger the Suspense fallback even
before we know whether we'll animate or not. So the simple solution is
just that `<ViewTransition>` opts in the whole subtree into Suspensey
Images in general.

In this PR I disable `enableSuspenseyImages` in experimental so that we
can instead test the path that only enables it inside `<ViewTransition>`
tree since that's the path that would next graduate to a minor.

DiffTrain build for [8da36d0508](https://github.com/facebook/react/commit/8da36d0508e83dd342ddbb98cb18f0606fd4045b)
2025-04-08 15:01:37 -07:00
sebmarkbage f0a6a89dea Allow Passing Blob/File/MediaSource/MediaStream to src of <img>, <video> and <audio> (#32828)
Behind the `enableSrcObject` flag. This is revisiting a variant of what
was discussed in #11163.

Instead of supporting the [`srcObject`
property](https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/srcObject)
as a separate name, this adds an overload of `src` to allow objects to
be passed. The DOM needs to add separate properties for the object forms
since you read back but it doesn't make sense for React's write-only API
to do that. Similar to how we'll like add an overload for
`popoverTarget` instead of calling it `popoverTargetElement` and how
`style` accepts an object and it's not `styleObject={{...}}`.

There are a number of reason to revisit this.

- It's just way more convenient to have this built-in and it makes
conceptual sense. We typically support declarative APIs and polyfill
them when necessary.
- RSC supports Blobs and by having it built-in you don't need a Client
Component wrapper to render it where as doing it with effects would
require more complex wrappers. By picking Blobs over base64,
client-navigations can use the more optimized binary encoding in the RSC
protocol.
- The timing aspect of coordinating it with Suspensey images and image
decoding is a bit tricky to get right because if you set it in an effect
it's too late because you've already rendered it.
- SSR gets complicated when done in user space because you have to
handle both branches. Likely with `useSyncExternalStore`.
- By having it built-in we could optimize the payloads shared between
RSC payloads embedded in the HTML and data URLs.

This does not support objects for `<source src>` nor `<img srcset>`.
Those don't really have equivalents in the DOM neither. They're mainly
for picking an option when you don't know programmatically. However, for
this use case you're really better off picking a variant before
generating the blobs.

We may support Response objects in the future too as per
https://github.com/whatwg/fetch/issues/49

DiffTrain build for [ea05b750a5](https://github.com/facebook/react/commit/ea05b750a5374458fc8c74ea0918059c818d1167)
2025-04-08 09:19:00 -07:00
sebmarkbage a4e2d3cbd1 Workaround against display: inline bug in Safari (#32822)
Safari has a bug where if you put a block element inside an inline
element and the inline element has a `view-transition-name` assigned it
finds it as duplicate names.

https://bugs.webkit.org/show_bug.cgi?id=290923

This adds a warning if we detect this scenario in dev mode.

For the case where it renders into a single block, we can model this by
making the parent either `block` or `inline-block` automatically to fix
the issue. So we do that to automatically cover simple cases like
`<a><div>...</div></a>`. This unfortunately causes layout/styling thrash
so we might want to delete it once the bug has been fixed in enough
Safari versions.

DiffTrain build for [365c031fd2](https://github.com/facebook/react/commit/365c031fd2354e94248ed9390f13fe2975b994f6)
2025-04-07 07:15:32 -07:00
acdlite dc32e7cb2c [Bugfix] Infinite uDV loop in popstate event (#32821)
Found a bug that occurs during a specific combination of very subtle
implementation details.

It occurs sometimes (not always) when 1) a transition is scheduled
during a popstate event, and 2) as a result, a new value is passed to an
already-mounted useDeferredValue hook.

The fix is relatively straightforward, and I found it almost
immediately; it took a bit longer to figure out exactly how the scenario
occurred in production and create a test case to simulate it.

Rather than couple the test to the implementation details, I've chosen
to keep it as high-level as possible so that it doesn't break if the
details change. In the future, it might not be trigger the exact set of
internal circumstances anymore, but it could be useful for catching
similar bugs because it represents a realistic real world situation —
namely, switching tabs repeatedly in an app that uses useDeferredValue.

DiffTrain build for [6a7650c75c](https://github.com/facebook/react/commit/6a7650c75c1bc110517bd9b3eefdc66eadbb9cbf)
2025-04-04 21:55:17 -07:00
sebmarkbage 28c3ec94a9 Add Suspensey Images behind a Flag (#32819)
We've known we've wanted this for many years and most of the
implementation was already done for Suspensey CSS. This waits to commit
until images have decoded by default or up to 500ms timeout (same as
suspensey fonts).

It only applies to Transitions, Retries (Suspense), Gesture Transitions
(flag) and Idle (doesn't exist). Sync updates just commit immediately.

`<img loading="lazy" src="..." />` opts out since you explicitly want it
to load lazily in that case.

`<img onLoad={...} src="..." />` also opts out since that implies you're
ok with managing your own reveal.

In the future, we may add an opt in e.g. `<img blocking="render"
src="..." />` that opts into longer timeouts and re-suspends even sync
updates. Perhaps also triggering error boundaries on errors.

The rollout for this would have to go in a major and we may have to
relax the default timeout to not delay too much by default. However, we
can also make this part of `enableViewTransition` so that if you opt-in
by using View Transitions then those animations will suspend on images.
That we could ship in a minor.

DiffTrain build for [efb22d8850](https://github.com/facebook/react/commit/efb22d8850382c3b53c1b2b8d22036d7e6cc9488)
2025-04-04 12:00:08 -07:00
sebmarkbage 7e5dab9fe1 Fix Bugs Measuring Performance Track for Effects (#32815)
This fixes two bugs with commit phase effect tracking.

I missed, or messed up the rebase for, deletion effects when a subtree
was deleted and for passive disconnects when a subtree was hidden.

The other bug is that when I started using self time
(componentEffectDuration) for color and for determining whether to
bother logging an entry, I didn't consider that the component with
effects can have children which end up resetting this duration before we
log. Which lead to most effects not having their components logged since
they almost always have children.

We don't necessarily have to push/pop but we have to store at least one
thing on the stack unfortunately. That's because we have to do the
actual log after the children to get the right end time. So might as
well use the push/pop strategy like the rest of them.

DiffTrain build for [c0f08ae74a](https://github.com/facebook/react/commit/c0f08ae74a46686f5718e9e6c511d27419fd632c)
2025-04-03 20:40:11 -07:00
sebmarkbage 00e3f22c1a Don't shadow EventListenerOptionsOrUseCapture and FocusOptions types (#32801)
These are built-in to Flow.

DiffTrain build for [7a728dffd1](https://github.com/facebook/react/commit/7a728dffd14550cd22e6d8b8514e82435bbeba76)
2025-04-01 11:29:17 -07:00
sebmarkbage 67628e7676 Warn if addTransitionType is called when there are no pending Actions (#32793)
Stacked on #32792.

It's tricky to associate a specific `addTransitionType` call to a
specific `startTransition` call because we don't have `AsyncContext` in
browsers yet. However, we can keep track if there are any async
transitions running at all, and if not, warn. This should cover most
cases.

This also errors when inside a React render which might be a legit way
to associate a Transition Type to a specific render (e.g. based on props
changing) but we want to be a more conservative about allowing that yet.
If we wanted to support calling it in render, we might want to set which
Transition object is currently rendering but it's still tricky if the
render has `async function` components. So it might at least be
restricted to sync components (like Hooks).

DiffTrain build for [deca96520f](https://github.com/facebook/react/commit/deca96520f1e9e804b0e5b0d81563327d9c55521)
2025-04-01 09:28:47 -07:00
sebmarkbage 70814b1b24 Add startGestureTransition API (#32785)
Stacked on #32783. This will replace [the `useSwipeTransition`
API](https://github.com/facebook/react/pull/32373).

Instead, of a special Hook, you can make updates to `useOptimistic`
Hooks within the `startGestureTransition` scope.

```
import {unstable_startGestureTransition as startGestureTransition} from 'react';

const cancel = startGestureTransition(timeline, () => {
  setOptimistic(...);
}, options);
```

There are some downsides to this like you can't define two directions as
once and there's no "standard" direction protocol. It's instead up to
libraries to come up with their own conventions (although we can suggest
some).

The convention is still that a gesture recognizer has two props `action`
and `gesture`. The `gesture` prop is a Gesture concept which now behaves
more like an Action but 1) it can't be async 2) it shouldn't have
side-effects. For example you can't call `setState()` in it except on
`useOptimistic` since those can be reverted if needed. The `action` is
invoked with whatever side-effects you want after the gesture fulfills.

This is isomorphic and not associated with a specific renderer nor root
so it's a bit more complicated.

To implement this I unify with the `ReactSharedInternal.T` property to
contain a regular Transition or a Gesture Transition (the `gesture`
field). The benefit of this unification means that every time we
override this based on some scope like entering `flushSync` we also
override the `startGestureTransition` scope. We just have to be careful
when we read it to check the `gesture` field to know which one it is.
(E.g. I error for setState / requestFormReset.)

The other thing that's unique is the `cancel` return value to know when
to stop the gesture. That cancellation is no longer associated with any
particular Hook. It's more associated with the scope of the
`startGestureTransition`. Since the schedule of whether a particular
gesture has rendered or committed is associated with a root, we need to
somehow associate any scheduled gestures with a root.

We could track which roots we update inside the scope but instead, I
went with a model where I check all the roots and see if there's a
scheduled gesture matching the timeline. This means that you could
"retain" a gesture across roots. Meaning this wouldn't cancel until both
are cancelled:

```
const cancelA = startGestureTransition(timeline, () => {
  setOptimisticOnRootA(...);
}, options);

const cancelB = startGestureTransition(timeline, () => {
  setOptimisticOnRootB(...);
}, options);
```

It's more like it's a global transition than associated with the roots
that were updated.

Optimistic updates mostly just work but I now associate them with a
specific "ScheduledGesture" instance since we can only render one at a
time and so if it's not the current one, we leave it for later.

Clean up of optimistic updates is now lazy rather than when we cancel.
Allowing the cancel closure not to have to be associated with each
particular update.

DiffTrain build for [b286430c8a](https://github.com/facebook/react/commit/b286430c8a585dc2e2e3cc023e7c455ec2b34ab7)
2025-03-31 17:17:22 -07:00
sebmarkbage f8bbdb7c32 Unify BatchConfigTransition and Transition types (#32783)
This is some overdue refactoring. The two types never made sense. It
also should be defined by isomorphic since it defines how it should be
used by renderers rather than isomorphic depending on Fiber.

Clean up hidden classes to be consistent.

Fix missing name due to wrong types. I choose not to invoke the
transition tracing callbacks if there's no name since the name is
required there.

DiffTrain build for [d3b8ff6e58](https://github.com/facebook/react/commit/d3b8ff6e589bcacfd1c9b0aa48c42fd1c93001c1)
2025-03-31 17:05:59 -07:00
rickhanlonii bea1002a4f s/HTML/text for text hydration mismatches (#32763)
DiffTrain build for [3e88e97c11](https://github.com/facebook/react/commit/3e88e97c116c7a1535976f2d4486bbf345476443)
2025-03-26 14:46:01 -07:00
sebmarkbage a28916b5dd Don't flush synchronous work if we're in the middle of a ViewTransition async sequence (#32760)
Starting a View Transition is an async sequence. Since React can get a
sync update in the middle of sequence we sometimes interrupt that
sequence.

Currently, we don't actually cancel the View Transition so it can just
run as a partial. This ensures that we fully skip it when that happens,
as well as warn.

However, it's very easy to trigger this with just a setState in
useLayoutEffect right now. Therefore if we're inside the preparing
sequence of a startViewTransition, this delays work that would've
normally flushed in a microtask. ~Maybe we want to do the same for
Default work already scheduled through a scheduler Task.~ Edit: This was
already done.

`flushSync` currently will still lead to an interrupted View Transition
(with a warning). There's a tradeoff here whether we want to try our
best to preserve the guarantees of `flushSync` or favor the animation.
It's already possible to suspend at the root with `flushSync` which
means it's not always 100% guaranteed to commit anyway. We could treat
it as suspended. But let's see how much this is a problem in practice.

DiffTrain build for [a5297ece62](https://github.com/facebook/react/commit/a5297ece6217f5495cbe38ba58f928b2697b0f99)
2025-03-26 11:50:54 -07:00
poteto 0c4df01e80 [crud] Revert CRUD overload (#32741)
Cleans up this experiment. After some internal experimentation we are
deprioritizing this project for now and may revisit it at a later point.

DiffTrain build for [313332d111](https://github.com/facebook/react/commit/313332d111a2fba2db94c584334d8895e8d73c61)
2025-03-26 09:16:06 -07:00
jackpope 9477f11aa2 Fix ownerStackLimit feature gating for tests (#32726)
https://github.com/facebook/react/pull/32529 added a dynamic flag for
this, but that breaks tests since the flags are not defined everywhere.

However, this is a static value and the flag is only for supporting
existing tests. So we can override it in the test config, and make it
static at built time instead.

DiffTrain build for [f99c9feaf7](https://github.com/facebook/react/commit/f99c9feaf786fbdad0ad8d2d81196a247302dd3c)
2025-03-26 09:09:26 -07:00
SamChou19815 19714aa0d5 [flow] Replace $PropertyType with indexed access type in ReactNativeTypes (#32733)
DiffTrain build for [b59f186011](https://github.com/facebook/react/commit/b59f18601179bb06a2c32a76547fd4929aa1ce9c)
2025-03-24 20:06:45 -07:00
eps1lon 8b3404306d Stop creating Owner Stacks if many have been created recently (#32529)
Co-authored-by: Jack Pope <jackpope1@gmail.com>

DiffTrain build for [4a9df08157](https://github.com/facebook/react/commit/4a9df08157f001c01b078d259748512211233dcf)
2025-03-23 15:53:15 -07:00
poteto 7c8cabc1cf [ci] Add missing permissions to runtime_commit_artifacts.yml (#32710)
Turns out we need permissions to write to `contents` after all.
---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/32710).
* #32711
* __->__ #32710

DiffTrain build for [de4aad5ba6](https://github.com/facebook/react/commit/de4aad5ba693be099b215b5819b5f25d05051a84)
2025-03-21 15:07:21 -07:00
rickhanlonii 8a468f1a72 [refactor] move isValidElementType to react-is (#32518)
DiffTrain build for [b630219b13](https://github.com/facebook/react/commit/b630219b1377f3117036b1c6118676c16fdb21b7)
2025-03-20 14:01:27 -07:00
poteto 1f072d9af9 [ci] Fix Will commit these changes www step (#32681)
Unlike the fbsource version of the step, www doesn't add any changes so
the `force` input doesn't actually work

DiffTrain build for [ff8f6f21f7](https://github.com/facebook/react/commit/ff8f6f21f756c81fba284557357eb6e6ce765149)
2025-03-19 15:38:03 -07:00
poteto af02928d40 [ci] Properly format commit message take 2 (#32673)
We need to use the commit message from `main`, not the builds branch

DiffTrain build for [b0446ff06a](https://github.com/facebook/react/commit/b0446ff06a484127412638c2be9a0382c6f3a84b)
2025-03-19 11:19:28 -07:00
sebmarkbage 861b14904a Measure Updated ViewTransition Boundaries (#32653)
This does the same thing for  that we did
for  in
https://github.com/facebook/react/pull/32612/commits/e3cbaffef05c7b476c07f7495e06788a9503e636.
If a boundary hasn't mutated and didn't change in size, we mark it for
cancellation. Otherwise we add names to it. The different from the
CommitViewTransition path is that the old names are added to the
clones so this is the first time the new names.

Now we also cancel any boundaries that were unchanged. So now the root
no longer animates. We still have to clone them. There are other
optimizations that can avoid cloning but once we've done all the layouts
we can still cancel the running animation and let them just be the
regular content if they didn't change. Just like the regular
fire-and-forget path.

This also fixes the measurement so that we measure clones by adjusting
their position back into the viewport.

This actually surfaces a bug in Safari that was already in #32612. It
turns out that the old names aren't picked up for some reason and so in
Safari they looked more like a cross-fade than what #32612 was supposed
to fix. However, now that bug is even more apparent because they
actually just disappear in Safari. I'm not sure what that bug is but
it's unrelated to this PR so will fix that separately.

DiffTrain build for [3c3696d554](https://github.com/facebook/react/commit/3c3696d5548c8a67f2332fd78332b9366abaf2f9)
2025-03-17 18:45:36 -07:00