Commit Graph
16512 Commits
Author SHA1 Message Date
potetoandJordan Brown ba8f56d7cf [compiler] Fix copyright script (#33003)
Don't try to open directories
---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/33003).
* #33004
* __->__ #33003
* #33002

---------

Co-authored-by: Jordan Brown <jmbrown@meta.com>

DiffTrain build for [8b9629c810](https://github.com/facebook/react/commit/8b9629c8106b55965ac6e4f078110b484b358101)
2025-04-23 19:01:22 -07:00
potetoandJordan Brown 7eda227443 [forgive] Add code action to remove dependency array (#33000)
Adds a new codeaction event in the compiler and handler in forgive. This
allows you to remove a dependency array when you're editing a range that
is within an autodep eligible function.

Co-authored-by: Jordan Brown <jmbrown@meta.com>
---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/33000).
* #33002
* #33001
* __->__ #33000

Co-authored-by: Jordan Brown <jmbrown@meta.com>

DiffTrain build for [f765082996](https://github.com/facebook/react/commit/f765082996f056c2abb354eb43cec3a3bf535264)
2025-04-23 18:37:54 -07:00
potetoandJordan Brown b6017b21cf [forgive] Refactor inferred deps (#32999)
Refactor.

Co-authored-by: Jordan Brown <jmbrown@meta.com>
---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/32999).
* #33002
* #33001
* #33000
* __->__ #32999

Co-authored-by: Jordan Brown <jmbrown@meta.com>

DiffTrain build for [7b21c46489](https://github.com/facebook/react/commit/7b21c464890ec991d95c88b5d68802a6c8b3bd8e)
2025-04-23 18:32:50 -07:00
potetoandJordan Brown 4af5ca837a [forgive] Emit AutoDepsDecoration event when inferring effect deps (#32997)
Emits a new event for decorating inferred effect dependencies.

Co-authored-by: Jordan Brown <jmbrown@meta.com>
---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/32997).
* #33002
* #33001
* #33000
* #32999
* #32998
* __->__ #32997
* #32996

---------

Co-authored-by: Jordan Brown <jmbrown@meta.com>

DiffTrain build for [cd7d236682](https://github.com/facebook/react/commit/cd7d236682ff3ba4996a5e1568f148bd6ac91862)
2025-04-23 17:57:06 -07:00
potetoandJordan Brown 7d80c9dbda [forgive] Log inferEffectDependencies (#32996)
This was missed earlier.

Co-authored-by: Jordan Brown <jmbrown@meta.com>
---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/32996).
* #33002
* #33001
* #33000
* #32999
* #32998
* #32997
* __->__ #32996

Co-authored-by: Jordan Brown <jmbrown@meta.com>

DiffTrain build for [71d0896a4a](https://github.com/facebook/react/commit/71d0896a4a1b31e14baeb7e427fc4724dbe972ff)
2025-04-23 17:55:25 -07:00
unstubbable e4c48b8b7e [Flight] Don't hang forever when prerendering a rejected promise (#32953)
DiffTrain build for [914319ae59](https://github.com/facebook/react/commit/914319ae595010cd5d3f0e277c77eb86da18e4f0)
2025-04-23 02:08:08 -07:00
sebmarkbage ccc770d61e 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:17 -07:00
sebmarkbage 1bc9b2ad48 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:17 -07:00
sebmarkbage 0b9ba06e94 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:25 -07:00
sebmarkbage 8d4a351d9c 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:34:56 -07:00
poteto afed35b486 [eprh] Bump stable version (#32978)
https://www.npmjs.com/package/eslint-plugin-react-hooks/v/6.0.0 was just
released, so we can bump this now.

DiffTrain build for [b303610c33](https://github.com/facebook/react/commit/b303610c33ab903f6f0d9d1c6297b704781b3678)
2025-04-21 11:41:40 -07:00
poteto df7ab8b838 [ci] Remove compiler weekly release (#32977)
No longer needed.

DiffTrain build for [fea92d8462](https://github.com/facebook/react/commit/fea92d846284bb7f4427ccbe8c16aaf85f0e2943)
2025-04-21 10:55:50 -07:00
jbrown215 25f69b725f [compiler][autodeps/fire] Do not include fire functions in autodep arrays (#32532)
Summary: We landed on not including fire functions in dep arrays. They
aren't needed because all values returned from the useFire hook call
will read from the same ref. The linter will error if you include a
fired function in an explicit dep array.

Test Plan: yarn snap --watch

--

DiffTrain build for [b8bedc267f](https://github.com/facebook/react/commit/b8bedc267f79db375f3147db4d766e09de599b68)
2025-04-17 10:09:19 -07:00
poteto c684ed4ef3 [ci] Only label on PR open (#32936)
No reason to label it every update, only do it once when it's first
opened.
---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/32936).
* __->__ #32936
* #32935

DiffTrain build for [4a36d3eab7](https://github.com/facebook/react/commit/4a36d3eab7d9bbbfae62699989aa95e5a0297c16)
2025-04-16 15:07:17 -07:00
poteto 0de480943e [ci] Fix check_access again (#32935)
I can see the value being output and set correctly but not sure why it's
skipping the 2nd job.
---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/32935).
* #32936
* __->__ #32935

DiffTrain build for [2ddf8caa9d](https://github.com/facebook/react/commit/2ddf8caa9d3abd22f54304bf7650e512efb93f18)
2025-04-16 15:05:49 -07:00
sebmarkbage d9958b393f 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:25 -07:00
sebmarkbage 3187da070d 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:19 -07:00
sebmarkbage 457073e5e1 Clear Update flag for unchanged trees in the beginning of the commit phase (#32849)
We use the Update flag to track if a View Transition had any mutations
or relayout. Unlike the other usage of it, this is just temporary state
during the commit phase.

Normally the flags gets used in the render phase and we reset it when we
rerender but in the case of "nested" updates, those trees didn't update.
We're only looking for relayouts. So we need to manually reset it before
we start using it.

We probably shouldn't abuse the Update flag for this and instead use
something like temporary state on ViewTransitionState.

DiffTrain build for [1d6c8168db](https://github.com/facebook/react/commit/1d6c8168db1d82713202e842df3167787ffa00ed)
2025-04-11 08:02:13 -07:00
sebmarkbage 6d8b652355 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:57:37 -07:00
sebmarkbage e21a42ec22 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:13 -07:00
sebmarkbage 015014b344 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:00 -07:00
sebmarkbage 0bf585bb32 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:30:31 -07:00
poteto 402cf9f099 [eprh] Temporarily disable ref access in render validation (#32839)
This rule currently has a few false positives, so let's disable it for
now (just in the eslint rule, it's still enabled in the compiler) while
we iterate on it.

DiffTrain build for [ff697fc58b](https://github.com/facebook/react/commit/ff697fc58be53dd485bd2babb826bc6cd664929c)
2025-04-09 11:56:15 -07:00
eps1lon 7857e82b39 Send notification to Discord if automated publish fails (#32840)
DiffTrain build for [096dd7385d](https://github.com/facebook/react/commit/096dd7385dfc6e9732d588189e59c8c6fe7a4975)
2025-04-09 10:21:05 -07:00
sebmarkbage 375bc21668 Emit Activity boundaries as comments in Fizz (#32834)
Uses `&` for Activity as opposed to `$` for Suspense. This will be used
to delimitate which nodes we can skip hydrating.

This isn't used on the client yet. It's just a noop on the client
because it's just an unknown comment. This just adds the SSR parts.

DiffTrain build for [3fbfb9baaf](https://github.com/facebook/react/commit/3fbfb9baaf38528349b86372bd7eff36c6a3261a)
2025-04-09 08:08:03 -07:00
sebmarkbage 5c01acf862 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:08 -07:00
sebmarkbage b154791a6c 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:18:31 -07:00
sebmarkbage 5959f7d082 Fix Failed to execute 'measure' on 'Performance' error (#32823)
When `startTime` still has its initial value of `-1.1` we must not call
`logComponentMount`. This can occur when rendering a `'next/dynamic'`
component with `{ssr: false}` in a client component, for example.
Unfortunately, I didn't manage to reproduce this scenario in a unit
test.

DiffTrain build for [3366146796](https://github.com/facebook/react/commit/336614679600af371b06371c0fbdd31fd9838231)
2025-04-07 07:20:00 -07:00
sebmarkbage e4590b3b90 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:07 -07:00
acdlite 2ae9f1a870 [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:54:51 -07:00
sebmarkbage 3d2497a0ae 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 11:59:39 -07:00
sebmarkbage e91382d91c 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:39:42 -07:00
sebmarkbage 50f7631330 Minor Tweak to Performance Track (#32808)
Rename "Suspended" commit to "Suspended on CSS" since that's the only
reason for this particular branch. This will not hold true because with
suspended images and with view transitions those can also be the reason.
So in the future we need to add those.

Only log "Blocked" in the components track if we yield for 3ms or
longer. It's common to have like 1-2ms yield times for various reasons
going on which is not worth the noise to consider "blocking".

Rename "Blocked" to "Update" in the Blocking/Transition tracks. This is
when a setState happens and with stack traces it's where you should look
for the stack trace of the setState. So we want to indicate that this is
the "Update".

I only added the "Blocked" part if we're blocked for more than 5ms
before we can start rendering - indicating that some other track was
working at the same time and preventing us from rendering.

DiffTrain build for [b2f6365745](https://github.com/facebook/react/commit/b2f6365745416be4d7dad7799a2cfbfbbf425389)
2025-04-02 14:09:02 -07:00
sebmarkbage 7a01de6a11 Follow through all the phases when an error happens during snapshotting (#32803)
This can happen for example if you have duplicate names in the "old"
state. This errors the transition before the updateCallback is invoked
so we haven't yet applied mutations etc.

This runs through those phases after the error to get us back to a
consistent state.

DiffTrain build for [040f8286e9](https://github.com/facebook/react/commit/040f8286e97eab7aac23a89d5f59967be3bf8f3e)
2025-04-02 07:56:07 -07:00
sebmarkbage 1fbbc5f182 Clarify that the transitionLanes used by Transition Tracing is a LaneMap (#32800)
We have a high level concept for this used elsewhere.

We should use this for `transitionTypes` too:

https://github.com/facebook/react/blob/main/packages/react-reconciler/src/ReactInternalTypes.js#L285

As mentioned in #32797 we could also just use the `transitionLanes`
since the `types` are also on the `Transition` objects. If we always
stored this set.

DiffTrain build for [450f8df886](https://github.com/facebook/react/commit/450f8df8865303f14be7ddd7c951f020115aa27c)
2025-04-01 15:24:16 -07:00
sebmarkbage 25fe23d1a1 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:28:48 -07:00
sebmarkbage 95b5d5ffaf Support addTransitionType in startGestureTransition (#32792)
Stacked on #32788.

Normally we track `addTransitionType` globally because of the async gap
that can happen in Actions where we lack AsyncContext to associate it
with a particular Transition. This unfortunately also means it's
possible to call outside of `startTransition` which is something we want
to warn for.

We need to be able to distinguish whether `addTransitionType` is for a
regular Transition or a Gesture Transition though.

Since `startGestureTransition` is only synchronous we can track it
within that execution scope and move it to a separate set. Since we know
for sure which call owns it we can properly associate it with that
specific provider's `ScheduledGesture`.

This does not yet handle calling `addTransitionType` inside the render
phase of a gesture. That would currently still be associated with the
next Transition instead.

DiffTrain build for [0b1a9e90c5](https://github.com/facebook/react/commit/0b1a9e90c5d5b6a4633c225c9100af69f53752c8)
2025-04-01 09:28:08 -07:00
sebmarkbage e26abae912 Get rid of the directional gesture options (#32788)
Stacked on #32786.

`startGestureTransition` doesn't have a concept of two directions. It's
just a start and end range now.

DiffTrain build for [8b2046d0ce](https://github.com/facebook/react/commit/8b2046d0ce379e083b4f5678598c2af9d507f507)
2025-04-01 09:26:58 -07:00
sebmarkbage e98f9863fd Remove useSwipeTransition (#32786)
Stacked on #32785.

This is now replaced by `startGestureTransition` added in #32785.

I also renamed the flag from `enableSwipeTransition` to
`enableGestureTransition` to correspond to the new name.

DiffTrain build for [0a7cf20b22](https://github.com/facebook/react/commit/0a7cf20b220a9f719e06fd8a12dfde3ab029c651)
2025-04-01 08:57:32 -07:00
sebmarkbage 764be659f1 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:16:53 -07:00
sebmarkbage b5a296772d 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:29 -07:00
sebmarkbage 81dc31ede7 Mark the root as animating if any Portal mutates or resizes (#32772)
Portals and `<ViewTransition>` are tricky because they leave the React
tree. You might think of a Portal's container conceptually as also being
part of a React tree but that's not quite how they're modeled today.
They're more like their own roots. So instead, of trying to find a
conceptual place in the React tree we treat Portals as their own root.

We have two ways of tracking whether an update to a ViewTransition
boundary has occurred. Either a DOM mutation has happened within it, or
a resize of a child has caused it to potentially relayout its parent.
Normally that just follows the tree structure of React, but not when
it's a Portal.

When it's a Portal we don't know which DOM parent it might have
affected. For all we know it's at the root (and in fact, in most cases
that's where Portals go).

With this PR we mark the root as having been affected by a mutation or
resize. This means that the whole document will animate and we can't
optimize away from it. This ensures that a mutation to the root of a
Portal doesn't go unanimated with other things are animating such as its
parent.

You can regain this optimization by adding a `<ViewTransition>` boundary
directly inside the Portal itself so it owns its own animation. If that
DOM node is also absolutely positioned it doesn't leak.

Conversely this also means that a mutation inside a Portal doesn't
affect its React parent so it won't trigger its parent's animation if
this was the only thing animating. That could be unfortunate if this
container is actually inside the same React parent. However, because
this would have been an update we would've marked it for "maybe
animating" and updates can't only get their animations cancelled if the
root is cancelled, in practice this will actually animate anyway.

DiffTrain build for [95671b4eb3](https://github.com/facebook/react/commit/95671b4eb3ceb51278a2ba959667da04f0b09809)
2025-03-31 12:19:16 -07:00
mofeiZandRodrigo Faria cb70b73d5a feat(babel-plugin-react-compiler): support satisfies operator (#32742)
Solve https://github.com/facebook/react/pull/29818

---------

Co-authored-by: Rodrigo Faria <rodrigo.faria@cartrack.com>

DiffTrain build for [ef4bc8b4f9](https://github.com/facebook/react/commit/ef4bc8b4f91023afac437be9179beef350b32db3)
2025-03-28 08:16:33 -07:00
mofeiZ 0c1b2bf6d6 [compiler] Fix inferEffectDependencies lint false positives (#32769)
Currently, inferred effect dependencies are considered a
"compiler-required" feature. This means that untransformed callsites
should escalate to a build error.

`ValidateNoUntransformedReferences` iterates 'special effect' callsites
and checks that the compiler was able to successfully transform them.
Prior to this PR, this relied on checking the number of arguments passed
to this special effect.

This obviously doesn't work with `noEmit: true`, which is used for our
eslint plugin (this avoids mutating the babel program as other linters
run with the same ast). This PR adds a set of `babel.SourceLocation`s to
do best effort matching in this mode.

DiffTrain build for [8039f1b2a0](https://github.com/facebook/react/commit/8039f1b2a05d00437cd29707761aeae098c80adc)
2025-03-27 09:24:40 -07:00
sebmarkbage d587415660 Mark shouldStartViewTransition as true when there's an enter animation (#32764)
Typically we mark the name of things that might animate in the snapshot
phase. At the same time we track that should call startViewTransition
too. However, we don't do this for "enter" since they're only marked
later. Leading to having just an "enter" not to animate unless there's
at least another update too.

This tracks if there's a ViewTransitionComponent in the tree that
enters. Luckily we know that from the static flag so we don't have to
traverse it.

DiffTrain build for [4280563b04](https://github.com/facebook/react/commit/4280563b04898baad423dc7d0f8b0dfea3b1797a)
2025-03-26 15:18:39 -07:00
rickhanlonii 473ee29cdb s/HTML/text for text hydration mismatches (#32763)
DiffTrain build for [3e88e97c11](https://github.com/facebook/react/commit/3e88e97c116c7a1535976f2d4486bbf345476443)
2025-03-26 14:45:27 -07:00
sebmarkbage c06bad4f71 Add getComputedStyle helper to ViewTransition refs (#32751)
This is also sometimes useful to read the style of the pseudo-element
itself without an animation.

DiffTrain build for [f134b3993a](https://github.com/facebook/react/commit/f134b3993a84d53cc99fe66b426ba13548f142ec)
2025-03-26 13:00:00 -07:00
poteto 204d73a37e Add "auto" class to mean the built-in should run (#32761)
Stacked on https://github.com/facebook/react/pull/32734

In React a ViewTransition class of `"none"` doesn't just mean that it
has no class but also that it has no ViewTransition name. The default
(`null | undefined`) means that it has no specific class but should run
with the default built-in animation. This adds this as an explicit
string called `"auto"` as well.

That way you can do `<ViewTransition default="foo" enter="auto">` to
override the "foo" just for the "enter" trigger to be the default
built-in animation. Where as if you just specified `null` it would be
like not specifying enter at all which would trigger "foo".

DiffTrain build for [fceb0f80bc](https://github.com/facebook/react/commit/fceb0f80bc729d061bcb5031801cfc824adc07a9)
2025-03-26 12:52:56 -07:00
sebmarkbage 86c53b445d Rename <ViewTransition className="..."> to <ViewTransition default="..."> (#32734)
It was always confusing that this is not a CSS class but a
view-transition-class.

The `className` sticks out a bit among its siblings `enter`, `exit`,
`update` and `share`. The idea is that the most specific definition
override is the class name that gets applied and this prop is really
just the fallback, catch-all or "any" that is applied if you didn't
specify a more specific one.

It has also since evolved not just to take a string but also a map of
Transition Type to strings.

The "class" is really the type of the value. We could add a suffix to
all of them like `defaultClass`, `enterClass`, `exitClass`,
`updateClass` and `shareClass`. However, this doesn't necessarily make
sense with the mapping of Transition Type to string. It also makes it a
bit too DOM centric. In React Native this might still be called a
"class" but it might be represented by an object definition. We might
even allow some kind of inline style form for the DOM too. Really this
is about picking which "animation" that runs which can be a string or
instance. "Animation" is too broad because there's also a concept of a
CSS Animation and these are really sets of CSS animations (group,
image-pair, old, new). It could maybe be `defaultTransition`,
`enterTransition`, etc but that seems unnecessarily repetitive and still
doesn't say anything about it being a class.

We also already have the name "default" in the map of Transition Types.
In fact you can now specify a default for default:

```
<ViewTransition default={{"navigation-back": "slide-out", "default": "fade-in"}}>
```

One thing I don't like about the name `"default"` is that it might be
common to just apply a named class that does it matching to
enter/exit/update in the CSS selectors (such as the `:only-child` rule)
instead of doing that mapping to each one using React. In that can you
end up specifying only `default={...}` a lot and then what is it the
"default" for? It's more like "all". I think it's likely that you end up
with either "default" or the specific forms instead of both at once.

DiffTrain build for [e0c99c4ea1](https://github.com/facebook/react/commit/e0c99c4ea1cae566ad8040180cf180ae058cb8bf)
2025-03-26 12:12:23 -07:00
sebmarkbage 7c2bf8c31d 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:22 -07:00