Commit Graph

1209 Commits

Author SHA1 Message Date
poteto f88c2a0c76 Added dev-only warning for null/undefined create in use*Effect (#32355)
## Summary

Fixes #32354.

Re-creation of #15197: adds a dev-only warning if `create == null` to
the three `use*Effect` functions:

* `useEffect`
* `useInsertionEffect`
* `useLayoutEffect`

Updates the warning to match the same text given in the
`react/exhaustive-deps` lint rule.

## How did you test this change?

I applied the changes manually within `node_modules/` on a local clone
of
https://github.com/JoshuaKGoldberg/repros/tree/react-use-effect-no-arguments.

Please pardon me for opening a PR addressing a not-accepted issue. I was
excited to get back to #15194 -> #15197 now that I have time. 🙂

---------

Co-authored-by: lauren <poteto@users.noreply.github.com>

DiffTrain build for [192555bb0e](https://github.com/facebook/react/commit/192555bb0ed88db30f91c58651c421f178f90384)
2025-02-11 14:06:55 -08:00
poteto b4cbede0e9 [crud] Remove useResourceEffect (#32206)
Removes useResourceEffect.
---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/32206).
* __->__ #32206
* #32205

DiffTrain build for [a69b80d07e](https://github.com/facebook/react/commit/a69b80d07e5d1bf363ed15d6209a55b35e0765c2)
2025-02-11 11:25:52 -08:00
poteto 92fac77aa4 [crud] Rename useResourceEffect flag (#32204)
Rename the flag in preparation for the overload.
---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/32204).
* #32206
* #32205
* __->__ #32204

DiffTrain build for [0461c0d8a4](https://github.com/facebook/react/commit/0461c0d8a49730d1c8ebca2071d9bb7adfc8ac92)
2025-02-11 11:14:38 -08:00
poteto 8d80d81894 [crud] Narrow resource type (#32203)
Small refactor to the `resource` type to narrow it to an arbitrary
object or void/null instead of the top type. This makes the overload on
useEffect simpler since the return type of create is no longer widened
to the top type when we merge their definitions.
---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/32203).
* #32206
* #32205
* #32204
* __->__ #32203

DiffTrain build for [899e3d1297](https://github.com/facebook/react/commit/899e3d1297ec15a5aa8d73e2f1bd478918090a12)
2025-02-11 11:03:41 -08:00
lauren ea2c5b208a [builds/facebook-fbsource] Add workflow to close direct PRs (#32357) 2025-02-11 13:09:38 -05:00
poteto 7e59b47d91 [react-native] Suppress Flow nonstrict-import check in ReactNativeTypes (#32349)
Summary: Unblock internal sync.

Test Plan:

Reviewers:

Subscribers:

Tasks:

Tags:

DiffTrain build for [cd90a4d8c0](https://github.com/facebook/react/commit/cd90a4d8c0d5dbaa8ab61e839b112b1518d5058f)
2025-02-10 12:52:24 -08:00
poteto 2cf442e812 [react-native] fix divergence in synced code (#32348)
Alternative to #32334

DiffTrain build for [3dd2c62770](https://github.com/facebook/react/commit/3dd2c627707fea4f45fd8e5cc583036a72e3f77b)
2025-02-10 11:18:13 -08:00
jackpope e74ebbaf94 Ship enableFabricCompleteRootInCommitPhase (#32318)
DiffTrain build for [8759c5c8d6](https://github.com/facebook/react/commit/8759c5c8d6aef34df576827215ff7ebaeafc79ea)
2025-02-07 08:18:36 -08:00
gnoff 0b22ef9dc6 [Fiber][Dev] Relax dom nesting validation when the root is a Document, html tag, or body tag (#32252)
followup to
* https://github.com/facebook/react/pull/32069
* https://github.com/facebook/react/pull/32163
* https://github.com/facebook/react/pull/32224

in react-dom in Dev we validate that the tag nesting is valid. This is
motivated primarily because while browsers are tolerant to poor HTML
there are many cases that if server rendered will be hydrated in a way
that will break hydration.

With the changes to singleton scoping where the document body is now the
implicit render/hydration context for arbitrary tags at the root we need
to adjust the validation logic to allow for valid programs such as
rendering divs as a child of a Document (since this div will actually
insert into the body).

DiffTrain build for [a0fdb63060](https://github.com/facebook/react/commit/a0fdb6306043b9f049106e58dcec107d8dbed2b1)
2025-02-06 15:11:28 -08:00
gnoff 2ca4fae6b8 [Fiber] getHoistableRoot() should account for Document containers (#32321)
While modern DOM implementations all support getRootNode if you are
running React in a runtime which does not the fallback logic which uses
`.ownerDocument` works everywhere except when the container is a
Document itself. This change corrects this by returning the container
intsance if it is a Document type.

DiffTrain build for [b48e739998](https://github.com/facebook/react/commit/b48e739998432fc9672a42d0d04515980b8cae82)
2025-02-06 14:36:11 -08:00
rickhanlonii 9f6cb64e97 Export addTransitionType for www (#32311)
need dis based api

DiffTrain build for [ff6283340a](https://github.com/facebook/react/commit/ff6283340a10bb72ad0fb16ca027606a9ea1e67c)
2025-02-05 15:37:56 -08:00
jackpope 96aa3adcd4 Set enableViewTransition to dynamic for www (#32306)
Unblocks internal experimentation

DiffTrain build for [32b411496b](https://github.com/facebook/react/commit/32b411496b92455cede3b286eb37c8b183989051)
2025-02-04 12:58:38 -08:00
gnoff 781b67895f [Fiber] Disable comments as containers in OSS (#32250)
3 years ago we partially disabled comment nodes as valid containers.
Some unflagged support was left in due to legacy APIs like
`unmountComponentAtNode` and `unstable_renderSubtreeIntoContainer` but
these were since removed in React 19. This update flags the remaining
uses of comments as containers.

DiffTrain build for [0605cd9f38](https://github.com/facebook/react/commit/0605cd9f38f8b9d0ca6f8bd9dd3409db8d6c5c81)
2025-02-04 12:45:18 -08:00
gnoff 3f18106258 [Fiber] support hydration when rendering Suspense anywhere (#32224)
follow up to https://github.com/facebook/react/pull/32163

This continues the work of making Suspense workable anywhere in a
react-dom tree. See the prior PRs for how we handle server rendering and
client rendering. In this change we update the hydration implementation
to be able to locate expected nodes. In particular this means hydration
understands now that the default hydration context is the document body
when the container is above the body.

One case that is unique to hydration is clearing Suspense boundaries.
When hydration fails or when the server instructs the client to recover
an errored boundary it's possible that the html, head, and body tags in
the initial document were written from a fallback or a different primary
content on the server and need to be replaced by the client render.
However these tags (and in the case of head, their content) won't be
inside the comment nodes that identify the bounds of the Suspense
boundary. And when client rendering you may not even render the same
singletons that were server rendered. So when server rendering a
boudnary which contributes to the preamble (the html, head, and body tag
openings plus the head contents) we emit a special marker comment just
before closing the boundary out. This marker encodes which parts of the
preamble this boundary owned. If we need to clear the suspense boundary
on the client we read this marker and use it to reset the appropriate
singleton state.

DiffTrain build for [8bda71558c](https://github.com/facebook/react/commit/8bda71558c8b6f9f19af33271f1bfd0251a1c071)
2025-02-04 12:36:28 -08:00
gnoff 0c2639f426 Reconciler: Combine identical cases in findParent (#32210)
## Summary

When lookup `Parent`, `HostRoot` and `HostPortal` should be merged,
because when creating a `Portal`, it will also include
`containerInfo`(So we can directly use this `containerInfo` to delete
the real DOM nodes.), so there is no need to handle them separately.

## How did you test this change?

No behavior changes, all existing tests pass.

DiffTrain build for [19ca800caa](https://github.com/facebook/react/commit/19ca800caa01eec2f5e65e547c67b11592bec8b0)
2025-01-31 14:41:28 -08:00
yungsters 5d1509e2f0 Permit non-DEV Elements in React.Children w/ DEV (#32117)
DiffTrain build for [9ff42a8798](https://github.com/facebook/react/commit/9ff42a8798863c995523e284142b47e3cdfaee80)
2025-01-30 23:04:52 -08:00
sebmarkbage 084e7f259a [Fiber] Track Appearing Named ViewTransition in the accumulateSuspenseyCommit Phase (#32254)
When a named ViewTransition component unmounts in one place and mounts
in a different place we need to match these up so we know a pair has
been created. Since the unmounts are tracked in the snapshot phase we
need some way to track the mounts before that.

Originally the way I did that is by reusing the render phase since there
was no other phase in the commit before that. However, that's not quite
correct. Just because something is visited in render doesn't mean it'll
commit. E.g. if that tree ends up suspending or erroring. Which would
lead to a false positive on match. The unmount shouldn't animate in that
case.

(Un)fortunately we have already added a traversal before the snapshot
phase for tracking suspensey CSS. The `accumulateSuspenseyCommit` phase.
This needs to find new mounts of Suspensey CSS or if there was a
reappearing Offscreen boundary it needs to find any Suspensey CSS
already inside that tree. This is exactly the same traversal we need to
find newly appearing View Transition components. So we can just reuse
that.

DiffTrain build for [4b3728f05e](https://github.com/facebook/react/commit/4b3728f05efbab9624e981339d8a0992a58f9a41)
2025-01-30 09:19:24 -08:00
sebmarkbage 3faa55f7db [Fiber] Read the class name from props.layout (#32273)
Copypasta typo.

DiffTrain build for [2fe5b572bc](https://github.com/facebook/react/commit/2fe5b572bc79c51785bcd17dd16e85427c1d2548)
2025-01-30 08:54:01 -08:00
Rubén Norte 76dc00369f Expose new method in Fabric renderer to access root instance from root tag
Differential Revision: D68767143

Pull Request resolved: https://github.com/facebook/react/pull/32272
2025-01-30 07:23:17 -08:00
dmytrorykun 4c163ed18c Use fastAddProperties in diffing (#32243)
## Summary

`fastAddProperties` has shown some perf benefits when used for creating
props payload for new components. In this PR we'll try to use it for
diffing props for existing components.

It would be good enough if it simply doesn't regress perf. We'll be able
to delete the old `addProperties`, and make `fastAddProperties` the
default behaviour.

## How did you test this change?

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

DiffTrain build for [bb9a24d9fc](https://github.com/facebook/react/commit/bb9a24d9fc5faa57a85750cd3bb94546baa405ac)
2025-01-30 03:23:37 -08:00
rubennorte ace656de38 [RN] Add support for document instance in React Native (#32260)
## Summary

We're adding support for `Document` instances in React Native (as
`ReactNativeDocument` instances) in
https://github.com/facebook/react-native/pull/49012 , which requires the
React Fabric renderer to handle its lifecycle.

This modifies the renderer to create those document instances and
associate them with the React root, and provides a new method for React
Native to access them given its containerTag / rootTag.

## How did you test this change?

Tested e2e in https://github.com/facebook/react-native/pull/49012
manually syncing these changes.

DiffTrain build for [b2357ecd82](https://github.com/facebook/react/commit/b2357ecd8203341a3668a96d32d68dd519e5430d)
2025-01-29 09:14:13 -08:00
gnoff 029774ea07 [Fiber] Support Suspense boundaries anywhere (excluding hydration) (#32163)
This is a follow up to https://github.com/facebook/react/pull/32069

In the prior change I updated Fizz to allow you to render Suspense
boundaries at any level within a react-dom application by treating the
document body as the default render scope. This change updates Fiber to
provide similar semantics. Note that this update still does not deliver
hydration so unifying the Fizz and Fiber implementations in a single App
is not possible yet.

The implementation required a rework of the getHostSibling and
getHostParent algorithms. Now most HostSingletons are invisible from a
host positioning perspective. Head is special in that it is a valid host
scope so when you have Placements inside of it, it will act as the
parent. But body, and html, will not directly participate in host
positioning.

Additionally to support flipping to a fallback html, head, and body tag
in a Suspense fallback I updated the offscreen hiding/unhide logic to
pierce through singletons when lookin for matching hidable nod
boundaries anywhere (excluding hydration)

DiffTrain build for [c492f97541](https://github.com/facebook/react/commit/c492f97541486458ce21653d2669d53d380f0538)
2025-01-28 22:50:29 -08:00
sophiebits a88abd3f86 Clarify useActionState async non-transition warning (#32207)
https://github.com/facebook/react/pull/28491#issuecomment-2094861155

DiffTrain build for [b65afdd0c1](https://github.com/facebook/react/commit/b65afdd0c1f644f3630c4e8cfd9ac264c5ac329f)
2025-01-24 09:32:34 -08:00
sebmarkbage 7ab02f17cc Add Transition Types (#32105)
This adds an isomorphic API to add Transition Types, which represent the
cause, to the current Transition. This is currently mainly for View
Transitions but as a concept it's broader and we might expand it to more
features and object types in the future.

```js
import { unstable_addTransitionType as addTransitionType } from 'react';

startTransition(() => {
  addTransitionType('my-transition-type');
  setState(...);
});
```

If multiple transitions get entangled this is additive and all
Transition Types are collected. You can also add more than one type to a
Transition (hence the `add` prefix).

Transition Types are reset after each commit. Meaning that `<Suspense>`
revealing after a `startTransition` does not get any View Transition
types associated with it.

Note that the scoping rules for this is a little "wrong" in this
implementation. Ideally it would be scoped to the nearest outer
`startTransition` and grouped with any `setState` inside of it.
Including Actions. However, since we currently don't have AsyncContext
on the client, it would be too easy to drop a Transition Type if there
were no other `setState` in the same `await` task. Multiple Transitions
are entangled together anyway right now as a result. So this just tracks
a global of all pending Transition Types for the next Transition. An
inherent tricky bit with this API is that you could update multiple
roots. In that case it should ideally be associated with each root.
Transition Tracing solves this by associating a Transition with any
updates that are later collected but this suffers from the problem
mentioned above. Therefore, I just associate Transition Types with one
root - the first one to commit. Since the View Transitions across roots
are sequential anyway it kind of makes sense that only one really is the
cause and the other one is subsequent.

Transition Types can be used to apply different animations based on what
caused the Transition. You have three different ways to choose from for
how to use them:

## CSS

It integrates with [View Transition
Types](https://www.w3.org/TR/css-view-transitions-2/#active-view-transition-pseudo-examples)
so you can match different animations based on CSS scopes:

```css
:root:active-view-transition-type(my-transition-type) {
  &::view-transition-...(...) {
    ...
  }
}
```

This is kind of a PITA to write though and if you have a CSS library
that provide View Transition Classes it's difficult to import those into
these scopes.

## Class per Type

This PR also adds an object-as-map form that can be passed to all
`className` properties:

```js
<ViewTransition className={{
  'my-navigation-type': 'hello',
  'default': 'world',
}}>
```

If multiple types match, then they're joined together. If no types match
then the special `"default"` entry is used instead. If any type has the
value `"none"` then that wins and the ViewTransition is disabled (not
assigned a name).

These can be combined with `enter`/`exit`/`update`/`layout`/`share`
props to match based on kind of trigger and Transition Type.

```js
<ViewTransition enter={{
  'navigation-back': 'enter-right',
  'navigation-forward': 'enter-left',
}}
exit={{
  'navigation-back': 'exit-right',
  'navigation-forward': 'exit-left',
}}>
```

## Events

In addition, you can also observe the types in the View Transition Event
callbacks as the second argument. That way you can pick different
imperative Animations based on the cause.

```js
<ViewTransition onUpdate={(inst, types) => {
  if (types.includes('navigation-back')) {
    ...
  } else if (types.includes('navigation-forward')) {
    ...
  } else {
    ...
  }
}}>
```

## Future

In the future we might expose types to `useEffect` for more general
purpose usage. This would also allow non-View Transition based
Animations such as existing libraries to use this same feature to
coordinate the same concept.

We might also allow richer objects to be passed along here. Only the
strings would apply to View Transitions but the imperative code and
effects could do something else with them.

DiffTrain build for [028c8e6cf5](https://github.com/facebook/react/commit/028c8e6cf5ce2a87147a7e03e503ce94c7a7a0cf)
2025-01-21 12:09:38 -08:00
sebmarkbage 683d4f11e8 Fix moveBefore feature detection (#32087)
`moveBefore` was moved to the `ParentNode` mixin as per
https://github.com/whatwg/dom/pull/1307#discussion_r1881981120 _(and was
committed in
https://github.com/whatwg/dom/commit/3f3e94c5beda922962dacaeb606087f57bd7f7be)_

As a result, its existence can no longer be checked on `Node.prototype`
but must be checked in `Element.prototype`

DiffTrain build for [313c8c55de](https://github.com/facebook/react/commit/313c8c55de39cd5f009ebb033eec1666b3daa59e)
2025-01-17 08:50:46 -08:00
rickhanlonii 7784671e53 [internal] fix console patch, add RN (#32075)
The forking for `shared/ReactFeatureFlags` doesn't work in the console
patches. Since they're already forked, we can import the internal
ReactFeatureFlags files directly.

Would have caught this in testing a PR sync, but the PR syncs are broken
right now.

DiffTrain build for [43d18bc2d3](https://github.com/facebook/react/commit/43d18bc2d3d31f43706f513a996ef9b4a7495237)
2025-01-15 08:28:03 -08:00
eps1lon 4bb3447829 Use internal ReactCompilerRuntime in react/compiler-runtime entrypoint (#32054)
DiffTrain build for [6099351c76](https://github.com/facebook/react/commit/6099351c768670246e8b47e702545d03ddc97320)
2025-01-13 10:50:23 -08:00
sebmarkbage ee4a53063a View Transition Events (#32041)
This adds five events to `<ViewTransition>` that triggers when React
wants to animate it.

- `onEnter`: The `<ViewTransition>` or its parent Component is mounted
and there's no other `<ViewTransition>` with the same name being
deleted.
- `onExit`: The `<ViewTransition>` or its parent Component is unmounted
and there's no other `<ViewTransition>` with the same name being
deleted.
- `onLayout`: There are no updates to the content inside this
`<ViewTransition>` boundary itself but the boundary has resized or moved
due to other changes to siblings.
- `onShare`: This `<ViewTransition>` is being mounted and another
`<ViewTransition>` instance with the same name is being unmounted
elsewhere.
- `onUpdate`: The content of `<ViewTransition>` has changed either due
to DOM mutations or because an inner child `<ViewTransition>` has
resized.

Only one of these events is fired per Transition. If you want to cover
all updates you have to listen to `onLayout`, `onShare` and `onUpdate`.
We could potentially do something like fire `onUpdate` if `onLayout` or
`onShare` isn't specified but it's a little sketchy to have behavior
based on if someone is listening since it limits adding wrappers that
may or may not need it.

Each takes a `ViewTransitionInstance` as an argument so you don't need a
ref to animate it.

```js
<ViewTransition onEnter={inst => inst.new.animate(keyframes, options)}>
```

The timing of this event is after the View Transition's `ready` state
which means that's too late to do any changes to the View Transition's
snapshots but now both the new and old pseudo-elements are ready to
animate.

The order of `onExit` is parent first, where as the others are child
first. This mimics effect mount/unmount.

I implement this by adding to a queue in the commit phase and then call
it while we're finishing up the commit. This is after layout effects but
before passive effects since passive effects fire after the animation is
`finished`.

DiffTrain build for [540efebcc3](https://github.com/facebook/react/commit/540efebcc34357c98412a96805bfd9244d6aa678)
2025-01-12 10:24:13 -08:00
sebmarkbage c90b1c7b1e View Transition Refs (#32038)
This adds refs to View Transition that can resolve to an instance of:

```js
type ViewTransitionRef = {
  name: string,
  group: Animatable,
  imagePair: Animatable,
  old: Animatable,
  new: Animatable,
}
```

Animatable is a type that has `animate(keyframes, options)` and
`getAnimations()` on it. It's the interface that exists on Element that
lets you start animations on it. These ones are like that but for the
four pseudo-elements created by the view transition.

If a name changes, then a new ref is created. That way if you hold onto
a ref during an exit animation spawned by the name change, you can keep
calling functions on it. It will keep referring to the old name rather
than the new name.

This allows imperative control over the animations instead of using CSS
for this.

```js
const viewTransition = ref.current;
const groupAnimation = viewTransition.group.animate(keyframes, options);
const imagePairAnimation = viewTransition.imagePair.animate(keyframes, options);
const oldAnimation = viewTransition.old.animate(keyframes, options);
const newAnimation = viewTransition.new.animate(keyframes, options);
```

The downside of using this API is that it doesn't work with SSR so for
SSR rendered animations they'll fallback to the CSS. You could use this
for progressive enhancement though.

Note: In this PR the ref only controls one DOM node child but there can
be more than one DOM node in the ViewTransition fragment and they are
just left to their defaults. We could try something like making the
`animate()` function apply to multiple children but that could lead to
some weird consequences and the return value would be difficult to
merge. We could try to maintain an array of Animatable that updates with
how ever many things are currently animating but that makes the API more
complicated to use for the simple case. Conceptually this should be like
a fragment so we would ideally combine the multiple children into a
single isolate if we could. Maybe one day the same name could be applied
to multiple children to create a single isolate. For now I think I'll
just leave it like this and you're really expect to just use it with one
DOM node. If you have more than one they just get the default animations
from CSS.

Using this is a little tricky due timing. In this fixture I just use a
layout effect plus rAF to get into the right timing after the
startViewTransition is ready. In the future I'll add an event that fires
when View Transitions heuristics fire with the right timing.

DiffTrain build for [0bf1f39ec6](https://github.com/facebook/react/commit/0bf1f39ec6906c666011c0c57aa56aa34a262daf)
2025-01-10 08:59:24 -08:00
sebmarkbage 56d67721ae [Fiber] Support moveBefore at the top level of a container (#32036)
Parity with appendChild and insertBefore. This allows reordering at the
root while preserving state.

DiffTrain build for [056073de4c](https://github.com/facebook/react/commit/056073de4c50b65807cd77ae6715c9ea8ee64277)
2025-01-09 13:44:13 -08:00
sebmarkbage 98d49304c8 Add ViewTransitionComponent to Stacks and DevTools (#32034)
Just adding the name so it shows up.

(Note that no experimental ones are added to the list of filters atm.
Including SuspenseList etc.)

DiffTrain build for [c4595ca4c8](https://github.com/facebook/react/commit/c4595ca4c86a2a0795bf4d6d5ca4e074babf7fc3)
2025-01-09 08:40:48 -08:00
javache 609e7dac2e Remove enableGetInspectorDataForInstanceInProduction flag (#32033)
## Summary

Callers for this method has been removed in
https://github.com/facebook/react-native/commit/65bda542320a85f4627d7957e1c6f45c2776298d,
so these methods no longer need to be conditionally exported and the
feature flag can be removed.

## How did you test this change?

Flow fabric/native

DiffTrain build for [74ea0c73a2](https://github.com/facebook/react/commit/74ea0c73a26d1c61609c1f2fa2e4ee3c8d432bcb)
2025-01-09 07:59:12 -08:00
sebmarkbage 8e70bb2cf1 Execute layout phase before after mutation phase inside view transition (#32029)
This allows mutations and scrolling in the layout phase to be counted
towards the mutation. This would maybe not be the case for gestures but
it is useful for fire-and-forget.

This also avoids the issue that if you resolve navigation in
useLayoutEffect that it ends up dead locked.

It also means that useLayoutEffect does not observe the scroll
restoration and in fact, the scroll restoration would win over any
manual scrolling in layout effects. For better or worse, this is more in
line with how things worked before and how it works in popstate. So it's
less of a breaking change. This does mean that we can't unify the after
mutation phase with the layout phase though.

To do this we need split out flushSpawnedWork from the flushLayoutEffect
call.

Spawned work from setState inside the layout phase is done outside and
not counted towards the transition. They're sync updates and so are not
eligible for their own View Transitions. It's also tricky to support
this since it's unclear what things like exits in that update would
mean. This work will still be able to mutate the live DOM but it's just
not eligible to trigger new transitions or adjust the target of those.

One difference between popstate is that this spawned work is after
scroll restoration. So any scrolling spawned from a second pass would
now win over scroll restoration.

Another consequence of this change is that you can't safely animate
pseudo elements in useLayoutEffect. We'll introduce a better event for
that anyway.

DiffTrain build for [fd9cfa416f](https://github.com/facebook/react/commit/fd9cfa416f7c01ecdf76b10ab776a43f2430786d)
2025-01-08 16:20:32 -08:00
sebmarkbage 7697698ea7 ViewTransitions in Navigation (#32028)
This adds navigation support to the View Transition fixture using both
`history.pushState/popstate` and the Navigation API models.

Because `popstate` does scroll restoration synchronously at the end of
the event, but `startViewTransition` cannot start synchronously, it
would observe the "old" state as after applying scroll restoration. This
leads to weird artifacts. So we intentionally do not support View
Transitions in `popstate`. If it suspends anyway for some other reason,
then scroll restoration is broken anyway and then it is supported. We
don't have to do anything here because this is already how things worked
because the sync `popstate` special case already included the sync lane
which opts it out of View Transitions.

For the Navigation API, scroll restoration can be blocked. The best way
to do this is to resolve the Navigation API promise after React has
applied its mutation. We can detect if there's currently any pending
navigation and wait to resolve the `startViewTransition` until it
finishes and any scroll restoration has been applied.

https://github.com/user-attachments/assets/f53b3282-6315-4513-b3d6-b8981d66964e

There is a subtle thing here. If we read the viewport metrics before
scroll restoration has been applied, then we might assume something is
or isn't going to be within the viewport incorrectly. This is evident on
the "Slide In from Left" example. When we're going forward to that page
we shift the scroll position such that it's going to appear in the
viewport. If we did this before applying scroll restoration, it would
not animate because it wasn't in the viewport then. Therefore, we need
to run the after mutation phase after scroll restoration.

A consequence of this is that you have to resolve Navigation in
`useInsertionEffect` as otherwise it leads to a deadlock (which
eventually gets broken by `startViewTransition`'s timeout of 10
seconds). Another consequence is that now `useLayoutEffect` observes the
restored state. However, I think what we'll likely do is move the layout
phase to before the after mutation phase which also ensures that
auto-scrolling inside `useLayoutEffect` are considered in the viewport
measurements as well.

DiffTrain build for [800c9db22e](https://github.com/facebook/react/commit/800c9db22e69680f17e238724478537282215f89)
2025-01-08 16:05:43 -08:00
sebmarkbage 3fcc9f89dd [Fiber] Suspend the commit while we wait for the previous View Transition to finish (#32002)
Stacked on #31975.

View Transitions cannot handle interruptions in that if you start a new
one before the previous one has finished, it just stops and then
restarts. It doesn't seamlessly transition into the new transition.

This is generally considered a bad thing but I actually think it's quite
good for fire-and-forget animations (gestures is another story). There
are too many examples of bad animations in fast interactions because the
scenario wasn't predicted. Like overlapping toasts or stacked layers
that look bad. The only case interrupts tend to work well is when you do
a strict reversal of an animation like returning to the page you just
left or exiting a modal just being opened. However, we're limited by the
platform even in that regard.

I think one reason interruptions have traditionally been seen as good is
because it's hard if you have a synchronous framework to not interrupt
since your application state has already moved on. We don't have that
limitation since we can suspend commits. We can do all the work to
prepare for the next commit by rendering while the animation is going
but then delay the commit until the previous one finishes.

Another technical limitation earlier animation libraries suffered from
is only have the option to either interrupt or sequence animations since
it's modeling just one change set. Like showing one toast at a time.
That's bad. We don't have that limitation because we can interrupt a
previously suspended commit and start working on a new one instead.
That's what we do for suspended transitions in general. The net effect
is that we batch the commits.

Therefore if you get multiple toasts flying in fast, they can animate as
a batch in together all at once instead of overlapping slightly or being
staggered. Interruptions (often) bad. Staggered animations bad. Batched
animations good.

This PR stashes the currently active View Transition with an expando on
the container that's animating (currently always document). This is
similar to what we do with event handlers etc. We reason we do this with
an expando is that if you have multiple Reacts on the same page they
need to wait for each other. However, one of those might also be the SSR
runtime. So this lets us wait for the SSR runtime's animations to finish
before starting client ones. This could really be a more generic name
since this should ideally be shared across frameworks. It's kind of
strange that this property doesn't already exist in the DOM given that
there can only be one. It would be useful to be able to coordinate this
across libraries.

DiffTrain build for [98418e8902](https://github.com/facebook/react/commit/98418e8902d6045e5138a2e765e026ce2e4de82d)
2025-01-08 10:44:00 -08:00
sebmarkbage ef7a1aef74 [Fiber] Support only View Transitions v2 (#31996)
Stacked on #31975.

We're going to recommend that the primary way you style a View
Transition is using a View Transition Class (and/or Type). These are
only available in the View Transitions v2 spec. When they're not
available it's better to fallback to just not animating instead of
animating with the wrong styling rules applied.

This is already widely supported in Chrome and Safari 18.2. Safari 18.2
usage is still somewhat low but it's rolling out quickly as we speak.

A way to detect this is by just passing the object form to
`startViewTransition` which throws if it's an earlier version. The
object form is required for `types` but luckily classes rolled out at
the same time. Therefore we're only indirectly detecting class support.

This means that in practice Safari 18.0 and 18.1 won't animate. We could
try to only apply the feature detection if you're actually using classes
or types, but that would create an unfortunate ecosystem burden to try
to support names. It also leads to flaky effects when only some
animations work. Better to just disable them all.

Firefox has yet to ship anything. We'll have to look out for how the
feature detection happens there and if they roll things out in different
order but if you ship late, you deal with web compat as the ball lies.

DiffTrain build for [38127b2815](https://github.com/facebook/react/commit/38127b281567d43972b7fb44c3fcb0d1806e7c10)
2025-01-08 10:30:54 -08:00
sebmarkbage a2c417285a [Fiber] Use className on <ViewTransition> to assign view-transition-class (#31999)
Stacked on #31975.

This is the primary way we recommend styling your View Transitions since
it allows for reusable styling such as a CSS library specializing in
View Transitions in a way that's composable and without naming
conflicts. E.g.

```js
<ViewTransition className="enter-slide-in exit-fade-out update-cross-fade">
```

This doesn't change the HTML `class` attribute. It's not a CSS class.
Instead it assign the `view-transition-class` style prop of the
underlying DOM node while it's transitioning.

You can also just use `<div style={{viewTransitionClass: ...}}>` on the
DOM node but it's convenient to control the Transition completely from
the outside and conceptually we're transitioning the whole fragment. You
can even make Transition components that just wraps existing components.
`<RevealTransition><Component /></RevealTransition>` this way.

Since you can also have multiple wrappers for different circumstances it
allows React's heuristics to use different classes for different
scenarios. We'll likely add more options like configuring different
classes for different `types` or scenarios that can't be described by
CSS alone.

## CSS Modules

```js
import transitions from './transitions.module.css';

<ViewTransition className={transitions.bounceIn}>...</ViewTransition>
```

CSS Modules works well with this strategy because you can have globally
unique namespaces and define your transitions in the CSS modules as a
library that you can import. [As seen in the fixture
here.](https://github.com/facebook/react/commit/8b91b37bb8b4add5f3f8be5ef8f49bb23966b13b#diff-b4d9854171ffdac4d2c01be92a5eff4f8e9e761e6af953094f99ca243b054a85R11)

I did notice an unfortunate bug in how CSS Modules (at least in Webpack)
generates class names. Sometimes the `+` character is used in the hash
of the class name which is not valid for `view-transition-class` and so
it breaks. I had to rename my class names until the hash yielded
something different to work around it. Ideally that bug gets fixed soon.

## className, rly?

`className` isn't exactly the most loved property name, however, I'm
using `className` here too for consistency. Even though in this case
there's no direct equivalent DOM property name. The CSS property is
named `viewTransitionClass`, but the "viewTransition" prefix is implied
by the Component it is on in this case. For most people the fact that
this is actually a different namespace than other CSS classes doesn't
matter. You'll most just use a CSS library anyway and conceptually
you're just assigning classes the same way as `className` on a DOM node.

But if we ever rename the `class` prop then we can do that for this one
as well.

DiffTrain build for [3a5496b3f5](https://github.com/facebook/react/commit/3a5496b3f56f1c0b138811a564299ee0b64a64ba)
2025-01-08 10:29:53 -08:00
sebmarkbage a6f0acf54f Add <ViewTransition> Component (#31975)
This will provide the opt-in for using [View
Transitions](https://developer.mozilla.org/en-US/docs/Web/API/View_Transition_API)
in React.

View Transitions only trigger for async updates like `startTransition`,
`useDeferredValue`, Actions or `<Suspense>` revealing from fallback to
content. Synchronous updates provide an opt-out but also guarantee that
they commit immediately which View Transitions can't.

There's no need to opt-in to View Transitions at the "cause" side like
event handlers or actions. They don't know what UI will change and
whether that has an animated transition described.

Conceptually the `<ViewTransition>` component is like a DOM fragment
that transitions its children in its own isolate/snapshot. The API works
by wrapping a DOM node or inner component:

```js
import {ViewTransition} from 'react';

<ViewTransition><Component /></ViewTransition>
```

The default is `name="auto"` which will automatically assign a
`view-transition-name` to the inner DOM node. That way you can add a
View Transition to a Component without controlling its DOM nodes styling
otherwise.

A difference between this and the browser's built-in
`view-transition-name: auto` is that switching the DOM nodes within the
`<ViewTransition>` component preserves the same name so this example
cross-fades between the DOM nodes instead of causing an exit and enter:

```js
<ViewTransition>{condition ? <ComponentA /> : <ComponentB />}</ViewTransition>
```

This becomes especially useful with `<Suspense>` as this example
cross-fades between Skeleton and Content:

```js
<ViewTransition>
  <Suspense fallback={<Skeleton />}>
    <Content />
  </Suspense>
</ViewTransition>
```

Where as this example triggers an exit of the Skeleton and an enter of
the Content:

```js
<Suspense fallback={<ViewTransition><Skeleton /></ViewTransition>}>
  <ViewTransition><Content /></ViewTransition>
</Suspense>
```

Managing instances and keys becomes extra important.

You can also specify an explicit `name` property for example for
animating the same conceptual item from one page onto another. However,
best practices is to property namespace these since they can easily
collide. It's also useful to add an `id` to it if available.

```js
<ViewTransition name="my-shared-view">
```

The model in general is the same as plain `view-transition-name` except
React manages a set of heuristics for when to apply it. A problem with
the naive View Transitions model is that it overly opts in every
boundary that *might* transition into transitioning. This is leads to
unfortunate effects like things floating around when unrelated updates
happen. This leads the whole document to animate which means that
nothing is clickable in the meantime. It makes it not useful for smaller
and more local transitions. Best practice is to add
`view-transition-name` only right before you're about to need to animate
the thing. This is tricky to manage globally on complex apps and is not
compositional. Instead we let React manage when a `<ViewTransition>`
"activates" and add/remove the `view-transition-name`. This is also when
React calls `startViewTransition` behind the scenes while it mutates the
DOM.

I've come up with a number of heuristics that I think will make a lot
easier to coordinate this. The principle is that only if something that
updates that particular boundary do we activate it. I hope that one day
maybe browsers will have something like these built-in and we can remove
our implementation.

A `<ViewTransition>` only activates if:

- If a mounted Component renders a `<ViewTransition>` within it outside
the first DOM node, and it is within the viewport, then that
ViewTransition activates as an "enter" animation. This avoids inner
"enter" animations trigger when the parent mounts.
- If an unmounted Component had a `<ViewTransition>` within it outside
the first DOM node, and it was within the viewport, then that
ViewTransition activates as an "exit" animation. This avoids inner
"exit" animations triggering when the parent unmounts.
- If an explicitly named `<ViewTransition name="...">` is deep within an
unmounted tree and one with the same name appears in a mounted tree at
the same time, then both are activated as a pair, but only if they're
both in the viewport. This avoids these triggering "enter" or "exit"
animations when going between parents that don't have a pair.
- If an already mounted `<ViewTransition>` is visible and a DOM
mutation, that might affect how it's painted, happens within its
children but outside any nested `<ViewTransition>`. This allows it to
"cross-fade" between its updates.
- If an already mounted `<ViewTransition>` resizes or moves as the
result of direct DOM nodes siblings changing or moving around. This
allows insertion, deletion and reorders into a list to animate all
children. It is only within one DOM node though, to avoid unrelated
changes in the parent to trigger this. If an item is outside the
viewport before and after, then it's skipped to avoid things flying
across the screen.
- If a `<ViewTransition>` boundary changes size, due to a DOM mutation
within it, then the parent activates (or the root document if there are
no more parents). This ensures that the container can cross-fade to
avoid abrupt relayout. This can be avoided by using absolutely
positioned children. When this can avoid bubbling to the root document,
whatever is not animating is still responsive to clicks during the
transition.

Conceptually each DOM node has its own default that activates the parent
`<ViewTransition>` or no transition if the parent is the root. That
means that if you add a DOM node like `<div><ViewTransition><Component
/></ViewTransition></div>` this won't trigger an "enter" animation since
it was the div that was added, not the ViewTransition. Instead, it might
cause a cross-fade of the parent ViewTransition or no transition if it
had no parent. This ensures that only explicit boundaries perform coarse
animations instead of every single node which is really the benefit of
the View Transitions model. This ends up working out well for simple
cases like switching between two pages immediately while transitioning
one floating item that appears on both pages. Because only the floating
item transitions by default.

Note that it's possible to add manual `view-transition-name` with CSS or
`style={{ viewTransitionName: 'auto' }}` that always transitions as long
as something else has a `<ViewTransition>` that activates. For example a
`<ViewTransition>` can wrap a whole page for a cross-fade but inside of
it an explicit name can be added to something to ensure it animates as a
move when something relates else changes its layout. Instead of just
cross-fading it along with the Page which would be the default.

There's more PRs coming with some optimizations, fixes and expanded
APIs. This first PR explores the above core heuristic.

---------

Co-authored-by: Sebastian "Sebbie" Silbermann <silbermann.sebastian@gmail.com>

DiffTrain build for [a4d122f2d1](https://github.com/facebook/react/commit/a4d122f2d192fe0b6480e669cca43c8f953aaf85)
2025-01-08 09:19:38 -08:00
sebmarkbage 2bf194a2ca [Fiber] Delete isMounted internals (#31966)
The public API has been deleted a long time ago so this should be unused
unless it's used by hacks. It should be replaced with an
effect/lifecycle that manually tracks this if you need it.

The problem with this API is how the timing implemented because it
requires Placement/Hydration flags to be cleared too early. In fact,
that's why we also have a separate PlacementDEV flag that works
differently.

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

We should be able to remove this code now.

DiffTrain build for [e30c6693e4](https://github.com/facebook/react/commit/e30c6693e4c7f2aec25b07f5df69a87163dbee81)
2025-01-08 09:16:15 -08:00
sebmarkbage b878205c62 [Fiber] Don't work on scheduled tasks while we're in an async commit but flush it eagerly if we're sync (#31987)
This is a follow up to #31930 and a prerequisite for #31975.

With View Transitions, the commit phase becomes async which means that
other work can sneak in between. We need to be resilient to that.

This PR first refactors the flushMutationEffects and flushLayoutEffects
to use module scope variables to track its arguments so we can defer
them. It shares these with how we were already doing it for
flushPendingEffects.

We also track how far along the commit phase we are so we know what we
have left to flush.

Then callers of flushPassiveEffects become flushPendingEffects. That
helper synchronously flushes any remaining phases we've yet to commit.
That ensure that things are at least consistent if that happens.

Finally, when we are using a scheduled task, we don't do any work. This
ensures that we're not flushing any work too early if we could've
deferred it. This still ensures that we always do flush it before
starting any new work on any root so new roots observe the committed
state.

There are some unfortunate effects that could happen from allowing
things to flush eagerly. Such as if a flushSync sneaks in before
startViewTransition, it'll skip the animation. If it's during a
suspensey font it'll start the transition before the font has loaded
which might be better than breaking flushSync. It'll also potentially
flush passive effects inside the startViewTransition which should
typically be ok.

DiffTrain build for [defffdbba4](https://github.com/facebook/react/commit/defffdbba43f89b95d9f67a4fb0fa146c1211734)
2025-01-06 08:38:07 -08:00
rickhanlonii 2b7d8cd9f9 [fizz] fix empty string href double warning (#31783)
I think this is the suggested change from
https://github.com/facebook/react/pull/31765#discussion_r1884541447

But no tests fail and I'm not sure how to test it? Seems sus.

Also seems like the `removeAttribute` here should be changed?

https://github.com/facebook/react/blob/9d9f12f2699a049777fa88914306ad4de9e2b74d/packages/react-dom-bindings/src/client/ReactDOMComponent.js#L400-L427

DiffTrain build for [bf883bebbc](https://github.com/facebook/react/commit/bf883bebbc4973dea0e4801a5a62f82043ff57ee)
2025-01-03 10:00:41 -08:00
sebmarkbage ea06e7b55a Make RefStatic and LayoutStatic the same bit (#31965)
Refs are basically just fancy Layout Effects. These are conceptually the
same thing and are always visited together so they don't need to be
different flags.

Whenever we disappear/reappear Offscreen content we need to do both Refs
and Layout Effects.

This is just indicating which phase needs to be visited and these are
always the same phase.

DiffTrain build for [3b009b4cd5](https://github.com/facebook/react/commit/3b009b4cd58d382cfde2a72232c87df1a34d56d5)
2025-01-02 18:30:47 -08:00
sebmarkbage 9619b0daab [Fiber] Refactor Commit Phase into Separate Functions for Before Mutation/Mutation/Layout (#31930)
This is doing some general clean up to be able to split the commit root three phases into three separate async steps.

DiffTrain build for [c81312e3a7](https://github.com/facebook/react/commit/c81312e3a78dcbf71ed98c8893abe6dbfeaef3f2)
2025-01-02 12:02:37 -08:00
sebmarkbage 32a72c9e43 [Fiber] Avoid return value from commitBeforeMutationEffects (#31922)
This is behind an unusual flag (enableCreateEventHandleAPI) that doesn't
serve a special return value. I'll be collecting other flags from this
phase too.

We can just use the global flag and reset it before the next mutation
phase. Unlike focusedInstanceHandle this doesn't leak any memory in the
meantime.

DiffTrain build for [d8b903f49e](https://github.com/facebook/react/commit/d8b903f49edebdd9ed081ff0514c28fe130cd510)
2025-01-02 11:44:02 -08:00
sebmarkbage 80269ba62e [Fiber] Gate Update flag on BeforeMutationMask on flags (#31921)
We're currently visiting the snapshot phase for every `Update` flag even
though we rarely have to do anything in the Snapshot phase.

The only flags that seem to use these wider visits is
`enableCreateEventHandleAPI` and `enableUseEffectEventHook` but really
neither of those should do that neither. They should schedule explicit
Snapshot phases if needed.

DiffTrain build for [6ca7fbe884](https://github.com/facebook/react/commit/6ca7fbe884d17ef6c18d143421cc3e232bbba516)
2025-01-02 11:43:06 -08:00
sebmarkbage b675a57ad5 [Fiber] Mark error boundaries and commit phases when an error is thrown (#31876)
This tracks commit phase errors and marks the component that errored as
red. These also get the errors attached to the entry.

<img width="1505" alt="Screenshot 2024-12-20 at 2 40 14 PM"
src="https://github.com/user-attachments/assets/cac3ead7-a024-4e33-ab27-2e95293c4299"
/>

In the render phase I just mark the Error Boundary that caught the
error. We don't have access to the actual error since it's locked behind
closures in the update queue. We could probably expose that someway.

<img width="949" alt="Screenshot 2024-12-20 at 1 49 05 PM"
src="https://github.com/user-attachments/assets/3032455d-d9f2-462b-9c07-7be23663ecd3"
/>

Follow ups:

Since the Error Boundary doesn't commit its attempted render, we don't
log those. If we did then maybe we should just mark the errored
component like I do for the commit phase. We could potentially walk the
list of errors and log the captured fibers and just log their entries as
children.

We could also potentially walk the uncommitted Fiber tree by stashing it
somewhere or even getting it from the alternate. This could be done on
Suspense boundaries too to track failed hydrations.

---------

Co-authored-by: Ricky <rickhanlonii@gmail.com>

DiffTrain build for [0de1233fd1](https://github.com/facebook/react/commit/0de1233fd180969f7ffdfc98151922f2466ceb1f)
2025-01-02 10:35:45 -08:00
sebmarkbage c52345de2e [Fiber] Mark cascading updates (#31866)
A common source of performance problems is due to cascading renders from
calling `setState` in `useLayoutEffect` or `useEffect`. This marks the
entry from the update to when we start the render as red and `"Cascade"`
to highlight this.

<img width="964" alt="Screenshot 2024-12-19 at 10 54 59 PM"
src="https://github.com/user-attachments/assets/2bfa91e6-1dc1-4b7f-a659-50aaf2a97e83"
/>

In addition to this case, there's another case where you call `setState`
multiple times in the same event causing multiple renders. This might be
due to multiple `flushSync`, or spawned a microtasks from a
`useLayoutEffect`. In theory it could also be from a microtask scheduled
after the first `setState`. This one we can only detect if it's from an
event that has a `window.event` since otherwise it's hard to know if
we're still in the same event.

<img width="1210" alt="Screenshot 2024-12-19 at 11 38 44 PM"
src="https://github.com/user-attachments/assets/ee188bc4-8ebb-4e95-b5a5-4d724856c27d"
/>

I decided against making a ping in a microtask considered a cascade.
Because that should ideally be using the Suspense Optimization and so
wouldn't be considered multi-pass.

<img width="1284" alt="Screenshot 2024-12-19 at 11 07 30 PM"
src="https://github.com/user-attachments/assets/2d173750-a475-41a0-b6cf-679d15c4ca97"
/>

We might consider making the whole render phase and maybe commit phase
red but that should maybe reserved for actual errors. The "Blocked"
phase really represents the `setState` and so will have the stack trace
of the first update.

DiffTrain build for [1e9eb95db5](https://github.com/facebook/react/commit/1e9eb95db5b3a2064ecc26915a4e640b3a9bdaf5)
2025-01-02 10:11:43 -08:00
sebmarkbage dce2833bf0 [Fiber] Yield every other frame for Transition/Retry work (#31828)
This flag first moves the `shouldYield()` logic into React itself. We
need this for `postTask` compatibility anyway since this logic is no
longer a concern of the scheduler. This means that there can also be no
global `requestPaint()` that asks for painting earlier. So this is best
rolled out with `enableAlwaysYieldScheduler` (and ideally
`enableYieldingBeforePassive`) instead of `enableRequestPaint`.

Once in React we can change the yield timing heuristics. This uses the
previous 5ms for Idle work to keep everything responsive while doing
background work. However, for Transitions and Retries we have seen that
same thread animations (like loading states animating, or constant
animations like cool Three.js stuff) can take CPU time away from the
Transition that causes moving into new content to slow down. Therefore
we only yield every 25ms.

The purpose of this yield is not to avoid the overhead of yielding,
which is very low, but rather to intentionally block any frequently
occurring other main thread work like animations from starving our work.
If we could we could just tell everyone else to throttle their stuff for
ideal scheduling but that's not quite realistic. In other words, the
purpose of this is to reduce the frame rate of animations to 30 fps and
we achieve this by not yielding. We still do yield to allow the
animations to not just stall. This seems like a good balance.

The 5ms of Idle is because we don't really need to yield less often
since the overhead is low. We keep it low to allow 120 fps animations to
run if necessary and our work may not be the only work within a frame so
we need to yield early enough to leave enough time left.

Similarly we choose 25ms rather than say 35ms to ensure that we push
long enough to guarantee to half the frame rate but low enough that
there's plenty of time left for a rAF to power each animation every
other frame. It's also low enough that if something else interrupts the
work like a new interaction, we can still be responsive to that within
50ms or so. We also need to yield in case there's I/O work that needs to
get bounced through the main thread.

This flag is currently off everywhere since we have so many other
scheduling flags but that means there's some urgency to roll those out
fully so we can test this one. There's also some tests to update since
this doesn't go through the Mock scheduler anymore for yields.

DiffTrain build for [fe21c947c8](https://github.com/facebook/react/commit/fe21c947c82b173ae538aa1d215559ec3dccd103)
2025-01-02 10:09:44 -08:00
jackpope 8533013a0f Turn off enableYieldingBeforePassive in internal test renderers (#31863)
https://github.com/facebook/react/pull/31785 turned on
`enableYieldingBeforePassive` for the internal test renderer builds. We
have some failing tests on the RN side blocking the sync so lets turn
these off for now.

DiffTrain build for [de82912e62](https://github.com/facebook/react/commit/de82912e620518d501680bbd93fbb5cc8d134223)
2024-12-20 06:56:21 -08:00
jackpope 663e50c218 Fork Scheduler feature flags for native-fb (#31859)
#31787 introduces an experimental scheduler flag:
`enableAlwaysYieldScheduler`, which is turned off for www. There wasn't
a SchedulerFeatureFlags fork for native-fb, so the experimental change
was enabled in the Scheduler-dev build there which causes test failures
and is blocking the sync.

#31805 introduces another scheduler flag `enableRequestPaint`, which is
set as a `__VARIANT__` on www. I've set this to `true` here to preserve
the existing behavior. We can follow up with dynamic flags for native-fb
after unblocking the sync.

DiffTrain build for [bd76ce54d9](https://github.com/facebook/react/commit/bd76ce54d93153cc84d861bd59e906bc28e1c160)
2024-12-19 09:01:14 -08:00