Commit Graph
6323 Commits
Author SHA1 Message Date
Hendrik LiebauandGitHub 3366146796 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.
2025-04-07 10:13:34 -04:00
Sebastian MarkbågeandGitHub 365c031fd2 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.
2025-04-07 10:08:07 -04:00
Jason ZhangandGitHub a9d63f3f97 fix: incorrect type in getTypeSymbol (#32825)
`getTypeSymbol` also returns string
2025-04-07 10:51:28 +01:00
Andrew ClarkandGitHub 6a7650c75c [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.
2025-04-05 00:49:28 -04:00
Sebastian MarkbågeandGitHub efb22d8850 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.
2025-04-04 14:54:05 -04:00
Sebastian MarkbågeandGitHub 540cd65252 Log Mount/Unmount/Reconnect/Disconnect in the Component Track (#32816)
Stacked on #32815.

To be able to differentiate mounted subtrees from updated subtrees. This
adds a yellow entry above the component subtree that mounted. This is
added both to the render phase, mutation effect phase, layout effect
phase and passive effect phase.

<img width="962" alt="Screenshot 2025-04-03 at 10 41 02 PM"
src="https://github.com/user-attachments/assets/13777347-07e8-458c-9127-8675ef08b54f"
/>

Ideally we could probably give an annotation to the component instead of
adding a whole other line which is also a color that's kind of
distracting. However, not all components are included and keeping track
of which one is the first one below is kind of annoying. Adding a marker
to all components is kind of noisy. So this is a compromise. It's only
one per depth so it won't make it too deep even on larger trees.

If this is an unmount, those are added to the mutation effect phase for
the layout unmounts and passive unmount effect phase. Since these never
have a render, they're not in the render phase.

<img width="1010" alt="Screenshot 2025-04-03 at 11 05 57 PM"
src="https://github.com/user-attachments/assets/ab39f27e-13be-4281-94fa-9391bb293fd2"
/>

For showing / hiding `<Activity>` the terminology "Reconnect" and
"Disconnect" is used instead.
2025-04-03 23:33:29 -04:00
Sebastian MarkbågeandGitHub c0f08ae74a 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.
2025-04-03 23:33:14 -04:00
Sebastian MarkbågeandGitHub b10cb4c01e [DevTools] Release and aquire host instances when they're cloned in persistent mode (#32812)
In persistent mode they can change when they're closned and so we need
to release the old copy and acquire the new copy.
2025-04-03 10:06:04 -04:00
Ruslan LesiutinandGitHub f0c767e2a2 feat[devtools]: display native tag for host components for Native (#32762)
Native only. Displays the native tag for Native Host components inside a
badge, when user inspects the component.

Only displaying will be supported for now, because in order to get
native tags indexable, they should be part of the bridge operations,
which is technically a breaking change that requires significantly more
time investment.

The text will only be shown when user hovers over the badge.
![Screenshot 2025-03-26 at 19 46
40](https://github.com/user-attachments/assets/787530cf-c5e5-4b85-8e2a-15b006a3d783)
2025-04-02 22:44:38 +01:00
Sebastian MarkbågeandGitHub b2f6365745 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.
2025-04-02 17:01:10 -04:00
Sebastian MarkbågeandGitHub 040f8286e9 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.
2025-04-02 10:49:44 -04:00
Sebastian MarkbågeandGitHub 450f8df886 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.
2025-04-01 18:18:33 -04:00
Sebastian MarkbågeandGitHub 7a728dffd1 Don't shadow EventListenerOptionsOrUseCapture and FocusOptions types (#32801)
These are built-in to Flow.
2025-04-01 14:22:57 -04:00
Sebastian MarkbågeandGitHub e5dd82a79d Warn for using a React owned node as a Container if it also has text content (#32774)
The problem with setting both `children` or `dangerouslySetInnerHTML`
and also using a ref on a DOM node to either manually append children or
using it as a Container for `createRoot` or `createPortal` is that it's
ambiguous which children should win. Ideally you use one of the four
options to control children. Meaning that ideally you always use a leaf
container for refs like this.

Unfortunately it's very common to use a React owned thing with children
as a Container of a Portal. For example `document.body` can have both
regular React children and be used as a Portal container. This isn't
really fully supported and has some undefined behavior like relative
order isn't guaranteed but still very common.

It is extra bad if the children are a `string`/`number` or if
`dangerouslySetInnerHTML` is set. Because then when ever that reactively
updates it'll clear out any manually added DOM nodes. When this happens
isn't guaranteed. It's always happening as far as the reactivity is
concerned. See https://github.com/facebook/react/issues/31600

Therefore, we should warn for this specific pattern. This still allows
non-text children as a compromise even though that behavior is also
somewhat undefined.
2025-04-01 12:11:29 -04:00
Sebastian MarkbågeandGitHub 731ae3e0ad Solidify addTransitionType Semantics (#32797)
Stacked on #32793.

This is meant to model the intended semantics of `addTransitionType`
better. The previous hack just consumed all transition types when any
root committed so it could steal them from other roots. Really each root
should get its own set. Really each transition lane should get its own
set.

We can't implement the full ideal semantics yet because 1) we currently
entangle transition lanes 2) we lack `AsyncContext` on the client so for
async actions we can't associate a `addTransitionType` call to a
specific `startTransition`.

This starts by modeling Transition Types to be stored on the Transition
instance. Conceptually they belong to the Transition instance of that
`startTransition` they belong to. That instance is otherwise mostly just
used for Transition Tracing but it makes sense that those would be able
to be passed the Transition Types for that specific instance.

Nested `startTransition` need to get entangled. So that this
`addTransitionType` can be associated with the `setState`:

```js
startTransition(() => {
  startTransition(() => {
    addTransitionType(...)
  });
  setState(...);
});
```

Ideally we'd probably just use the same Transition instance itself since
these are conceptually all part of one entangled one. But transition
tracing uses multiple names and start times. Unclear what we want to do
with that. So I kept separate instances but shared `types` set.

Next I collect the types added during a `startTransition` to any root
scheduled with a Transition. This should really be collected one set per
Transition lane in a `LaneMap`. In fact, the information would already
be there if Transition Tracing was always enabled because it tracks all
Transition instances per lane. For now I just keep track of one set for
all Transition lanes. Maybe we should only add it if a `setState` was
done on this root in this particular `startTransition` call rather
having already scheduled any Transition earlier.

While async transitions are entangled, we don't know if there will be a
startTransition+setState on a new root in the future. Therefore, we
collect all transition types while this is happening and if a new root
gets startTransition+setState they get added to that root.

```js
startTransition(async () => {
  addTransitionType(...)
  await ...;
  setState(...);
});
```
2025-04-01 12:11:19 -04:00
Sebastian MarkbågeandGitHub deca96520f 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).
2025-04-01 12:10:10 -04:00
Sebastian MarkbågeandGitHub 0b1a9e90c5 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.
2025-04-01 12:08:55 -04:00
Sebastian MarkbågeandGitHub 8b2046d0ce 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.
2025-04-01 12:07:07 -04:00
Sebastian MarkbågeandGitHub d20c2802b4 Adjust range start/end based on the duration and delay of the animation (#32790)
When different animations in a View Transition have different durations,
we shouldn't stretch them out to run the full range of swipe. Because
then they wouldn't line up the same way as when played using plain time.

This adjusts the range start/end to be what it would've been when played
by time. Except since we are playing animations in reverse, the
animation-delay is actually applied from the range end and then the
duration from there to get closer to the start.

Reverse the range if the original animation was reversed.

Interestingly, the range it takes can be adjusted by what is in the
viewport since if a long duration animation is excluded then everything
else adjusts too.

I left some todos too. We really should also handle if the original
animation has multiple iterations. Currently we only play those once.
2025-04-01 11:44:44 -04:00
Sebastian MarkbågeandGitHub 0a7cf20b22 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.
2025-04-01 11:43:33 -04:00
Sebastian MarkbågeandGitHub b286430c8a 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.
2025-03-31 20:05:50 -04:00
Sebastian MarkbågeandGitHub d3b8ff6e58 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.
2025-03-31 19:59:07 -04:00
Sebastian MarkbågeandGitHub 95671b4eb3 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.
2025-03-31 15:13:11 -04:00
laurenandGitHub 50c5cdb653 Bump next prerelease version numbers (#32782)
Updates the version numbers in the prerelease channels.
2025-03-28 16:20:04 -04:00
Sebastian MarkbågeandGitHub 4280563b04 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.
2025-03-26 18:12:59 -04:00
RickyandGitHub 3e88e97c11 s/HTML/text for text hydration mismatches (#32763) 2025-03-26 17:39:52 -04:00
Sebastian MarkbågeandGitHub f134b3993a Add getComputedStyle helper to ViewTransition refs (#32751)
This is also sometimes useful to read the style of the pseudo-element
itself without an animation.
2025-03-26 15:02:53 -04:00
Sebastian MarkbågeandGitHub fceb0f80bc 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".
2025-03-26 15:02:43 -04:00
Sebastian MarkbågeandGitHub e0c99c4ea1 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.
2025-03-26 15:02:05 -04:00
Sebastian MarkbågeandGitHub a5297ece62 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.
2025-03-26 14:40:23 -04:00
laurenandGitHub 313332d111 [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.
2025-03-26 12:04:57 -04:00
RickyandGitHub f99c9feaf7 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.
2025-03-26 12:01:05 -04:00
Sebastian MarkbågeandGitHub 8ac25e5201 Warn for duplicate ViewTransition names (#32752)
This adds early logging when two ViewTransitions with the same name are
mounted at the same time. Whether they're part of a View Transition or
not.

This lets us include the owner stack of each one. I do two logs so that
you can get the stack trace of each one of the duplicates.

It currently only logs once for each name which also avoids the scenario
when you have many hits for the same name in one commit. However, we
could also possibly log a stack for each of them but seems noisy.

Currently we don't log if a SwipeTransition is the first time the pair
gets mounted which could lead to a View Transition error before we've
warned. That could be a separate improvement.
2025-03-25 22:03:05 -04:00
Sebastian MarkbågeandGitHub f9e1b16098 Avoid double logging component render time (#32749)
This got moved into the functional component and class component case
statements here:
https://github.com/facebook/react/commit/0de1233fd180969f7ffdfc98151922f2466ceb1f.
So that we could separate the error case for class components.

However, due to a faulty rebase this got restored at the top as well.
Leading to double component renders being logged.

In the other offscreen reconnect passes we don't do this in each case
statement but still once at the top. The reason this doesn't matter is
because use the PerformedWork flag and that is only set for function and
class components. Although maybe it should be set for expensive DOM
components too and then we have to remember this.
2025-03-25 20:57:20 -04:00
dc9b74647e [DevTools] Add fb local build command (#32644)
<!--
  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
1. Having a development build for FB will be convenient for fb internal
feature development
2. Add a new checkbox to toggle new internal features added to React
Devtools.

## How did you test this change?
1. yarn test
2. set extra env variables in bash profile and build an internal version
with the new script.
3. toggle on/off the new checkbox, the value is stored in local storage
correctly.

---------

Co-authored-by: Aohua Mu <muaohua@fb.com>
2025-03-25 13:45:48 +00:00
Sam ZhouandGitHub b59f186011 [flow] Replace $PropertyType with indexed access type in ReactNativeTypes (#32733) 2025-03-24 23:00:47 -04:00
Sebastian MarkbågeandGitHub 42a57ea802 Merge ViewTransition layout/onLayout props into update/onUpdate (#32723)
We currently have the ability to have a separate animation for a
ViewTransition that relayouts but doesn't actually have any internal
mutations. This can be useful if you want to separate just a move from
for example flashing an update.

However, we're concerned that this might be more confusion than its
worth because subtle differences in mutations can cause it to trigger
the other case. The existence of the property name might also make you
start looking for it to solve something that it's not meant for.

We already fallback to using the "update" property if it exists but
layout doesn't. So if we ever decide to add this back it would backwards
compatible. We've also shown in implementation that it can work.
2025-03-24 14:04:27 -04:00
Jack PopeandGitHub 04bf10e6a9 Add getRootNode to fragment instances (#32682)
This implements `getRootNode(options)` on fragment instances as the
equivalent of calling `getRootNode` on the fragment's parent host node.

The parent host instance will also be used to proxy dispatchEvent in an
upcoming PR.
2025-03-24 10:19:55 -04:00
4a9df08157 Stop creating Owner Stacks if many have been created recently (#32529)
Co-authored-by: Jack Pope <jackpope1@gmail.com>
2025-03-23 15:47:03 -07:00
RickyandGitHub daee08562c [activity] remove ref for now (#32645)
Followup from https://github.com/facebook/react/pull/32499

Manual mode is unused and has some bugs such as revealing hidden
boundaries when manually toggling. We also want to change how manual
mode works, and do some refactors to Activity to make it easier to
support. For now we'll remove it, then add it back after the other
changes we have planned.
2025-03-21 14:44:02 -04:00
Sebastian MarkbågeandGitHub e1e740717b Force layout before startViewTransition (#32699)
This works around this Safari bug.
https://bugs.webkit.org/show_bug.cgi?id=290146

This unfortunate because it may cause additional layouts if there's more
updates to the tree coming by manual mutation before it gets painted
naturally. However, we might end up wanting to read layout early anyway.

This affects the fixture because we clone the `<link>` from the `<head>`
which is itself another bug. However, it should be possible to have
`<link>` tags inserted into the new tree so this is still relevant.
2025-03-21 10:05:31 -04:00
RickyandGitHub b630219b13 [refactor] move isValidElementType to react-is (#32518) 2025-03-20 16:51:33 -04:00
Jack PopeandGitHub 7943da1e81 Set accurate value for alwaysThrottleRetries on www (#32684)
This flag value was updated in
https://github.com/facebook/react/pull/28965 (seemingly unrelated, maybe
as part of unit testing). But its still controlled by a dynamic flag in
www. Let's update this to VARIANT to accurately represent the state of
the rollout.

Before:
<img width="1340" alt="Screenshot 2025-03-20 at 10 45 30 AM"
src="https://github.com/user-attachments/assets/d0405a36-eb71-4108-9e23-8d462cc68fb4"
/>

After:
<img width="1351" alt="Screenshot 2025-03-20 at 10 45 11 AM"
src="https://github.com/user-attachments/assets/459d260d-7a25-430b-95a6-d6a91d958417"
/>
2025-03-20 14:28:55 -04:00
Sebastian MarkbågeandGitHub a4f9bd586b Enable Fragment refs in Experimental (#32670)
That we can test it out in Next.js router conditionally when
experimental is on for other reasons.
2025-03-19 20:38:27 -04:00
danandGitHub 86d5ac0882 Revert "Fix:- Improve HOC support and state preservation in React Refresh" (#32214)
Reverts facebook/react#30660

I don’t feel confident in the approach. This part of code is supposed to
rely on the module bundler behaving as expected. _Maybe_ this is correct
but I need to review it closer — it was intentionally _not_ implemented
this way originally.

I’ll try to take a closer look some time this week. We don’t have to
merge this revert right now but just flagging that I don’t understand
the thinking behind the new approach and don’t have confidence in it.
2025-03-18 19:05:56 +00:00
Jack PopeandGitHub 476f53879e Add getClientRects to fragment instances (#32660)
Adds `getClientRects()` to fragment instances with a fixture test case.
`Element.getClientRect` returns a collection of `DOMRect`s (see example
of multiline span returning two `DOMRect` boxes).
`fragmentInstance.getClientRects` here flattens those collections into
an array of rects.
2025-03-18 13:54:26 -04:00
Jack PopeandGitHub c69a5fc53a Add blur() and focusLast() to fragment instances (#32654)
`focus()` was added in https://github.com/facebook/react/pull/32465.
Here we add `focusLast()` and `blur()`. I also extended `focus` to take
options.

`focus` will focus the first focusable element. `focusLast` will focus
the last focusable element. We could consider a `focusFirst` naming or
even the `focusWithin` used by test selector APIs as well.

`blur` will only have an effect if the current `document.activeElement`
is one of the fragment children.
2025-03-18 11:58:12 -04:00
Sebastian MarkbågeandGitHub 3c3696d554 Measure Updated ViewTransition Boundaries (#32653)
This does the same thing for `measureUpdateViewTransition` that we did
for `measureNestedViewTransitions` 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.
2025-03-17 21:38:13 -04:00
Sebastian MarkbågeandGitHub 9fde224a53 Materialize the tree ID when ViewTransition name=auto consumes one (#32651)
ViewTransition uses the `useId` algorithm to auto-assign names. This
ensures that we could animate between SSR content and client content by
ensuring that the names line up.

However, I missed that we need to bump the id (materialize it) when we
do that. This is what function components do if they use one or more
`useId()`. This caused duplicate names when two ViewTransitions were
nested without any siblings since they would share name.
2025-03-17 16:17:01 -04:00
RickyandGitHub fbcda19a23 [devtools] add filters for internal builds (#32646)
We don't have an experimental-only build of devtools, but we can at
least add these filters to the internal build.

A better way would be to use feature detection, but I'm not sure how and
this isn't a very heavily used feautre.
2025-03-17 12:14:19 -04:00