Commit Graph

1320 Commits

Author SHA1 Message Date
sebmarkbage ffe6305552 [Fiber] Always flush Default priority in the microtask if a Transition was scheduled (#33186)
Stacked on #33160.

The purpose of this is to avoid calling `onDefaultTransitionIndicator`
when a Default priority update acts as the loading indicator, but still
call it when unrelated Default updates happens nearby.

When we schedule Default priority work that gets batched with other
events in the same frame more or less. This helps optimize by doing less
work. However, that batching means that we can't separate work from one
setState from another. If we would consider all Default priority work in
a frame when determining whether to show the default we might never show
it in cases like when you have a recurring timer updating something.

This instead flushes the Default priority work eagerly along with the
sync work at the end of the event, if this event scheduled any
Transition work. This is then used to determine if the default indicator
needs to be shown.

DiffTrain build for [b480865db0](https://github.com/facebook/react/commit/b480865db0babfcad602a1a1909775069b5779f9)
2025-05-13 12:59:50 -07:00
sebmarkbage 863c41cd67 [Fiber] Trigger default transition indicator if needed (#33160)
Stacked on #33159.

This implements `onDefaultTransitionIndicator`.

The sequence is:

1) In `markRootUpdated` we schedule Transition updates as needing
`indicatorLanes` on the root. This tracks the lanes that currently need
an indicator to either start or remain going until this lane commits.
2) Track mutations during any commit. We use the same hook that view
transitions use here but instead of tracking it just per view transition
scope, we also track a global boolean for the whole root.
3) If a sync/default commit had any mutations, then we clear the
indicator lane for the `currentEventTransitionLane`. This requires that
the lane is still active while we do these commits. See #33159. In other
words, a sync update gets associated with the current transition and it
is assumed to be rendering the loading state for that corresponding
transition so we don't need a default indicator for this lane.
4) At the end of `processRootScheduleInMicrotask`, right before we're
about to enter a new "event transition lane" scope, it is no longer
possible to render any more loading states for the current transition
lane. That's when we invoke `onDefaultTransitionIndicator` for any roots
that have new indicator lanes.
5) When we commit, we remove the finished lanes from `indicatorLanes`
and once that reaches zero again, then we can clean up the default
indicator. This approach means that you can start multiple different
transitions while an indicator is still going but it won't stop/restart
each time. Instead, it'll wait until all are done before stopping.

Follow ups:

- [x] Default updates are currently not enough to cancel because those
aren't flush in the same microtask. That's unfortunate. #33186
- [x] Handle async actions before the setState. Since these don't
necessarily have a root this is tricky. #33190
- [x] Disable for `useDeferredValue`. ~Since it also goes through
`markRootUpdated` and schedules a Transition lane it'll get a default
indicator even though it probably shouldn't have one.~ EDIT: Turns out
this just works because it doesn't go through `markRootUpdated` when
work is left behind.
- [x] Implement built-in DOM version by default. #33162

DiffTrain build for [62d3f36ea7](https://github.com/facebook/react/commit/62d3f36ea79fc0a10b514d4bbcc4ba3f21b3206e)
2025-05-13 12:52:35 -07:00
sebmarkbage bb4b9e402e Reset currentEventTransitionLane after flushing sync work (#33159)
This keeps track of the transition lane allocated for this event. I want
to be able to use the current one within sync work flushing to know
which lane needs its loading indicator cleared.

It's also a bit weird that transition work scheduled inside sync updates
in the same event aren't entangled with other transitions in that event
when `flushSync` is.

Therefore this moves it to reset after flushing.

It should have no impact. Just splitting it out into a separate PR for
an abundance of caution.

The only thing this might affect would be if the React internals throws
and it doesn't reset after. But really it doesn't really have to reset
and they're all entangled anyway.

DiffTrain build for [676f0879f3](https://github.com/facebook/react/commit/676f0879f315130309262ff3532707029f0288bb)
2025-05-13 12:28:58 -07:00
sebmarkbage 4a0575d571 [Fiber] Stash the entangled async action lane on currentEventTransitionLane (#33188)
When we're entangled with an async action lane we use that lane instead
of the currentEventTransitionLane. Conversely, if we start a new async
action lane we reuse the currentEventTransitionLane.

So they're basically supposed to be in sync but they're not if you
resolve the async action and then schedule new stuff in the same event.
Then you end up with two transitions in the same event with different
lanes.

By stashing it like this we fix that but it also gives us an opportunity
to check just the currentEventTransitionLane to see if this event
scheduled any regular Transition updates or Async Transitions.

DiffTrain build for [0cac32d60d](https://github.com/facebook/react/commit/0cac32d60dd4482b27fe8a54dffbabceb22c6272)
2025-05-13 12:27:45 -07:00
sebmarkbage 282bf23bad [DevTools] Get source location from structured callsites in prepareStackTrace (#33143)
When we get the source location for "View source for this element" we
should be using the enclosing function of the callsite of the child. So
that we don't just point to some random line within the component.

This is similar to the technique in #33136.

This technique is now really better than the fake throw technique, when
available. So I now favor the owner technique. The only problem it's
only available in DEV and only if it has a child that's owned (and not
filtered).

We could implement this same technique for the error that's thrown in
the fake throwing solution. However, we really shouldn't need that at
all because for client components we should be able to call
`inspect(fn)` at least in Chrome which is even better.

DiffTrain build for [997c7bc930](https://github.com/facebook/react/commit/997c7bc930304142b3af37bcb21599181124aeb4)
2025-05-13 09:46:46 -07:00
sebmarkbage d5a02f564b [Fizz] Gate rel="expect" behind enableFizzBlockingRender (#33183)
Enabled in experimental channel.

We know this is critical semantics to enforce at the HTML level since if
you don't then you can't add explicit boundaries after the fact.
However, this might have to go in a major release to allow for
upgrading.

DiffTrain build for [b94603b955](https://github.com/facebook/react/commit/b94603b95504130aec72f61e02d7b66d48f33653)
2025-05-13 07:24:17 -07:00
sebmarkbage f090b69fca [ReactFlightWebpackPlugin] Add support for .mjs file extension (#33028)
## Summary
Our builds generate files with a `.mjs` file extension. These are
currently filtered out by `ReactFlightWebpackPlugin` so I am updating it
to support this file extension.

This fixes https://github.com/facebook/react/issues/33155

## How did you test this change?
I built the plugin with this change and used `yalc` to test it in my
project. I confirmed the expected files now show up in
`react-client-manifest.json`

DiffTrain build for [2bcf06b692](https://github.com/facebook/react/commit/2bcf06b69254cad6f7e702bf7d65c4f30478668c)
2025-05-12 18:23:26 -07:00
sammy-SC 79b68866d3 Add eager alternate.stateNode cleanup (#33161)
This is a fix for a problem where React retains shadow nodes longer than
it needs to. The behaviour is shown in React Native test:
https://github.com/facebook/react-native/blob/main/packages/react-native/src/private/__tests__/utilities/__tests__/ShadowNodeReferenceCounter-itest.js#L169

# Problem
When React commits a new shadow tree, old shadow nodes are stored inside
`fiber.alternate.stateNode`. This is not cleared up until React clones
the node again. This may be problematic if mutation deletes a subtree,
in that case `fiber.alternate.stateNode` will retain entire subtree
until next update. In case of image nodes, this means retaining entire
images.

So when React goes from revision A: `<View><View /></View>` to revision
B: `<View />`, `fiber.alternate.stateNode` will be pointing to Shadow
Node that represents revision A..

![image](https://github.com/user-attachments/assets/076b677e-d152-4763-8c9d-4f923212b424)

# Fix
To fix this, this PR adds a new feature flag
`enableEagerAlternateStateNodeCleanup`. When enabled,
`alternate.stateNode` is proactively pointed towards finishedWork's
stateNode, releasing resources sooner.

I have verified this fixes the issue [demonstrated by React Native
tests](https://github.com/facebook/react-native/blob/main/packages/react-native/src/private/__tests__/utilities/__tests__/ShadowNodeReferenceCounter-itest.js#L169).
All existing React tests pass when the flag is enabled.

DiffTrain build for [5d04d73274](https://github.com/facebook/react/commit/5d04d73274a884ed53106677d56dd837ae668c45)
2025-05-12 09:45:35 -07:00
mofeiZ 865800150c [compiler][entrypoint] Fix edgecases for noEmit and opt-outs (#33148)
Title
---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/33148).
* #33149
* __->__ #33148

DiffTrain build for [3820740a7f](https://github.com/facebook/react/commit/3820740a7fbfc3b27a5127b43bdad44382ff3ce0)
2025-05-09 10:44:40 -07:00
mofeiZ 3f8a69cee6 [compiler][be] Make program traversal more readable (#33147)
React Compiler's program traversal logic is pretty lengthy and complex
as we've added a lot of features piecemeal. `compileProgram` is 300+
lines long and has confusing control flow (defining helpers inline,
invoking visitors, mutating-asts-while-iterating, mutating global
`ALREADY_COMPILED` state).

- Moved more stuff to `ProgramContext`
- Separated `compileProgram` into a bunch of helpers

Tested by syncing this stack to a Meta codebase and observing no
compilation output changes (D74487851, P1806855669, P1806855379)
---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/33147).
* #33149
* #33148
* __->__ #33147

DiffTrain build for [5069e18060](https://github.com/facebook/react/commit/5069e18060e00d7c07b2b04ebc8a3fa21e2d810a)
2025-05-09 10:29:54 -07:00
huntie 038fe5aafd Root import types from react-native in ReactNativeTypes (#33063)
DiffTrain build for [9518f11856](https://github.com/facebook/react/commit/9518f1185621aecb99fd72385cdb137c6e8bd8fe)
2025-05-09 04:18:34 -07:00
sebmarkbage e9cd841727 Use a shared noop function from shared/noop (#33154)
Stacked on #33150.

We use `noop` functions in a lot of places as place holders. I don't
think there's any real optimizations we get from having separate
instances. This moves them to use a common instance in `shared/noop`.

DiffTrain build for [21fdf308a1](https://github.com/facebook/react/commit/21fdf308a1a01af69c28c00a70086aa1bd4c2411)
2025-05-08 18:40:16 -07:00
jackpope a5a6ecd6f4 Clean up enableSiblingPrerendering flag (#32319)
DiffTrain build for [4ca97e4891](https://github.com/facebook/react/commit/4ca97e4891b6a664b4c3a183f16b81139655ff57)
2025-05-08 17:56:17 -07:00
sebmarkbage 4ab120c3e2 Add plumbing for onDefaultTransitionIndicator (#33150)
This just adds the options at the root and wire it up to the root but it
doesn't do anything yet.

DiffTrain build for [9b79292ae7](https://github.com/facebook/react/commit/9b79292ae7c2980acb531f1dff3cf1ca2d2f40b7)
2025-05-08 17:50:16 -07:00
josephsavona 49d9f3fc49 feat(compiler): Implement constant propagation for template literals (#33139)
New take on #29716

## Summary
Template literals consisting entirely of constant values will be inlined
to a string literal, effectively replacing the backticks with a double
quote.

This is done primarily to make the resulting instruction a string
literal, so it can be processed further in constant propatation. So this
is now correctly simplified to `true`:
```js
`` === "" // now true
`a${1}` === "a1" // now true
```

If a template string literal can only partially be comptime-evaluated,
it is not that useful for dead code elimination or further constant
folding steps and thus, is left as-is in that case. Same is true if the
literal contains an array, object, symbol or function.

## How did you test this change?

See added tests.

DiffTrain build for [ac06829246](https://github.com/facebook/react/commit/ac06829246287751e6b74bd99cd1b39d1aeba06a)
2025-05-08 09:31:02 -07:00
mofeiZ 8bf45a64d3 [compiler][playground][tests] Standardize more pragmas (#33146)
(Almost) all pragmas are now one of the following:
- `@...TestOnly`: custom pragma for test fixtures
- `@<configName>` | `@<configName>:true`: enables with either true or a
default enabled value
- `@<configName>:<json value>`

DiffTrain build for [38ef6550a8](https://github.com/facebook/react/commit/38ef6550a88f7744f5dcd4a3de7af6f13a540be5)
2025-05-08 08:34:54 -07:00
mofeiZ de1368397f [compiler][be] Move test pragma to separate file (#33145)
`Environment.ts` is getting complex so let's separate test / playground
parsing logic from it
---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/33145).
* #33146
* __->__ #33145

DiffTrain build for [b629a865fb](https://github.com/facebook/react/commit/b629a865fb18b899d251bf5c3c5ca2580d222720)
2025-05-08 08:32:08 -07:00
mofeiZ fa188d4d3c [compiler][be] repro edge cases for noEmit and module opt-outs (#33144)
see test fixtures
---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/33144).
* #33146
* #33145
* __->__ #33144

DiffTrain build for [fbe7bc21b9](https://github.com/facebook/react/commit/fbe7bc21b9aa00afa230132b3f7eee6d2b5c94a7)
2025-05-08 08:24:54 -07:00
hoxyq 312369393b React DevTools 6.1.1 -> 6.1.2 (#33142)
Patch release to mitigate https://github.com/facebook/react/issues/32659

Essentially just 6.1.1 with:
* Restore all Transitions for Tree updates
([eps1lon](https://github.com/eps1lon) in
[#33042](https://github.com/facebook/react/pull/33042))
* Restore "double-click to view owners tree" functionality
([eps1lon](https://github.com/eps1lon) in
[#33039](https://github.com/facebook/react/pull/33039))

DiffTrain build for [557a64795c](https://github.com/facebook/react/commit/557a64795c6b55e32a87c468c9069b05319d3b9b)
2025-05-08 00:08:06 -07:00
jackpope 2222d94322 Add dispatchEvent to fragment instances (#32813)
`fragmentInstance.dispatchEvent(evt)` calls `element.dispatchEvent(evt)`
on the fragment's host parent. This mimics bubbling if the
`fragmentInstance` could receive an event itself.

If the parent is disconnected, there is a dev warning and no event is
dispatched.

DiffTrain build for [8a8df5dbdd](https://github.com/facebook/react/commit/8a8df5dbdd57bf63d5156c1a9cba21ac6106b83d)
2025-05-07 11:08:46 -07:00
josephsavona dd523f1e28 feat(compiler): implement constant folding for unary minus (#33140)
## Summary
`-constant` is represented as a `UnaryExpression` node that is currently
not part of constant folding. If the operand is a constant number, the
node is folded to `constant * -1`. This also coerces `-0` to `0`,
resulting in `0 === -0` being folded to `true`.

## How did you test this change?
See attached tests

DiffTrain build for [946da518eb](https://github.com/facebook/react/commit/946da518eb2d64d808f9204a72e05892d3005f3f)
2025-05-07 10:21:45 -07:00
sebmarkbage 9b0f8d9d05 [Flight] Clarify that location field is a FunctionLocation not a CallSite (#33141)
Follow up to #33136.

This clarifies in the types where the conversion happens from a CallSite
which we use to simulate getting the enclosing line/col to a
FunctionLocation which doesn't represent a CallSite but actually just
the function which only has an enclosing line/col.

DiffTrain build for [a437c99ff7](https://github.com/facebook/react/commit/a437c99ff7a45025367571363653c2ad5db482a7)
2025-05-07 10:10:11 -07:00
jackpope a8615f88be Allow fragment refs to attempt focus/focusLast on nested host children (#33058)
This enables `focus` and `focusLast` methods on FragmentInstances to
search nested host components, depth first. Attempts focus on each child
and bails if one is successful. Previously, only the first level of host
children would attempt focus.

Now if we have an example like

```
component MenuItem() {
  return (<div><a>{...}</a></div>)
}

component Menu() {
  return <Fragment>{items.map(i => <MenuItem i={i} />)}</Fragment>
}
```
We can target focus on the first or last a tag, rather than checking
each wrapping div and then noop.

DiffTrain build for [4206fe4982](https://github.com/facebook/react/commit/4206fe49825787eda57a5d142640a63772ccbf2b)
2025-05-07 09:54:00 -07:00
sebmarkbage 1264bca160 [Flight] Encode enclosing line/column numbers and use it to align the fake function (#33136)
Stacked on #33135.

This encodes the line/column of the enclosing function as part of the
stack traces. When that information is available.

I adjusted the fake function code generation so that the beginning of
the arrow function aligns with these as much as possible.

This ensures that when the browser tries to look up the line/column of
the enclosing function, such as for getting the function name, it gets
the right one. If we can't get the enclosing line/column, then we encode
it at the beginning of the file. This is likely to get a miss in the
source map identifiers, which means that the function name gets
extracted from the runtime name instead which is better.

Another thing where this is used is the in the Performance Track.
Ideally that would be fixed by
https://issues.chromium.org/u/1/issues/415968771 but the enclosing
information is useful for other things like the function name resolution
anyway.

We can also use this for the "View source for this element" in React
DevTools.

DiffTrain build for [4a702865dd](https://github.com/facebook/react/commit/4a702865dd0c5849c1b454091560c3ef26121611)
2025-05-07 09:49:02 -07:00
sebmarkbage bd2fd378a8 [Flight] Parse Stack Trace from Structured CallSite if available (#33135)
This is first step to include more enclosing line/column in the parsed
data.

We install our own `prepareStackTrace` to collect structured callsite
data and only fall back to parsing the string if it was already
evaluated or if `prepareStackTrace` doesn't work in this environment.

We still mirror the default V8 format for encoding the function name
part. A lot of this is covered by tests already.

DiffTrain build for [0ff1d13b80](https://github.com/facebook/react/commit/0ff1d13b8055c801d8b9b6779958c09fd0dc63e0)
2025-05-07 08:50:43 -07:00
hoxyq 93ff544b29 [DevTools] Use Popover API for TraceUpdates highlighting (#32614)
## Summary

When using React DevTools to highlight component updates, the highlights
would sometimes appear behind elements that use the browser's
[top-layer](https://developer.mozilla.org/en-US/docs/Glossary/Top_layer)
(such as `<dialog>` elements or components using the Popover API). This
made it difficult to see which components were updating when they were
inside or behind top-layer elements.

This PR fixes the issue by using the Popover API to ensure that
highlighting appears on top of all content, including elements in the
top-layer. The implementation maintains backward compatibility with
browsers that don't support the Popover API.

## How did you test this change?

I tested this change in the following ways:

1. Manually tested in Chrome (which supports the Popover API) with:
- Created a test application with React components inside `<dialog>`
elements and custom elements using the Popover API
- Verified that component highlighting appears above these elements when
they update
- Confirmed that highlighting displays correctly for nested components
within top-layer elements

2. Verified backward compatibility:
- Tested in browsers without Popover API support to ensure fallback
behavior works correctly
- Confirmed that no errors occur and highlighting still functions as
before

3. Ran the React DevTools test suite:
   - All tests pass successfully
   - No regressions were introduced

[demo-page](https://devtools-toplayer-demo.vercel.app/)
[demo-repo](https://github.com/yongsk0066/devtools-toplayer-demo)

### AS-IS

https://github.com/user-attachments/assets/dc2e1281-969f-4f61-82c3-480153916969

### TO-BE

https://github.com/user-attachments/assets/dd52ce35-816c-42f0-819b-0d5d0a8a21e5

DiffTrain build for [53c9f81049](https://github.com/facebook/react/commit/53c9f81049b4440a02b5ed3edb128516821c0279)
2025-05-07 07:55:29 -07:00
jackpope 8b54080b18 Add compareDocumentPosition to fragment instances (#32722)
This adds `compareDocumentPosition(otherNode)` to fragment instances.

The semantics implemented are meant to match typical element
positioning, with some fragment specifics. See the unit tests for all
expectations.

- An element preceding a fragment is `Node.DOCUMENT_POSITION_PRECEDING`
- An element after a fragment is `Node.DOCUMENT_POSITION_FOLLOWING`
- An element containing the fragment is
`Node.DOCUMENT_POSITION_PRECEDING` and
`Node.DOCUMENT_POSITION_CONTAINING`
- An element within the fragment is
`Node.DOCUMENT_POSITION_CONTAINED_BY`
- An element compared against an empty fragment will result in
`Node.DOCUMENT_POSITION_DISCONNECTED` and
`Node.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC`

Since we assume a fragment instances target children are DOM siblings
and we want to compare the full fragment as a pseudo container, we can
compare against the first target child outside of handling the special
cases (empty fragments and contained elements).

DiffTrain build for [e5a8de81e5](https://github.com/facebook/react/commit/e5a8de81e57181692d33ce916dfd6aa23638ec92)
2025-05-06 10:07:58 -07:00
jorge-cab 6cf0f2acf1 [mcp] Add proper web-vitals metric collection (#33109)
Multiple things here:
- Improve the mean calculation for metrics so we don't report 0 when
web-vitals fail to be retrieved
- improve ui chaos monkey to use puppeteer APIs since only those trigger
INP/CLS metrics since we need emulated mouse clicks
- Add logic to navigate to a temp page after render since some
web-vitals metrics are only calculated when the page is backgrounded
- Some readability improvements

DiffTrain build for [7a2c7045ae](https://github.com/facebook/react/commit/7a2c7045aed222b1ece44a18db6326f2f10c89e3)
2025-05-06 08:58:05 -07:00
sebmarkbage f2955dbb6f Remove useId semantics from View Transition name generation (#33094)
Originally I thought it was important that SSR used the same View
Transition name as the client so that the Fizz runtime could emit those
names and then the client could pick up and take over. However, I no
longer believe that approach is feasible. Instead, the names can be
generated only during that particular animation.

Therefore we can simplify the auto name assignment to not have to
consider the hydration.

DiffTrain build for [845d93742f](https://github.com/facebook/react/commit/845d93742fb090e7a35abea409a55e2a14613255)
2025-05-06 07:39:53 -07:00
sebmarkbage a42f581a93 [Fiber] Replay events between commits (#33130)
Stacked on #33129. Flagged behind `enableHydrationChangeEvent`.

If you type into a controlled input before hydration and something else
rerenders like a setState in an effect, then the controlled input will
reset to whatever React thought it was. Even with event replaying that
this is stacked on, if the second render happens before event replaying
has fired in a separate task.

We don't want to flush inside the commit phase because then things like
flushSync in these events wouldn't work since they're inside the commit
stack.

This flushes all event replaying between renders by flushing it at the
end of `flushSpawned` work. We've already committed at that point and is
about to either do subsequent renders or yield to event loop for passive
effects which could have these events fired anyway. This just ensures
that they've already happened by the time subsequent renders fire. This
means that there's now a type of event that fire between sync render
passes.

DiffTrain build for [54a50729cc](https://github.com/facebook/react/commit/54a50729cc47a884c2110d7c59dd5f850748e142)
2025-05-05 21:30:15 -07:00
sebmarkbage b9cbc6c4d6 [Fiber] Replay onChange Events if input/textarea/select has changed before hydration (#33129)
This fixes a long standing issue that controlled inputs gets out of sync
with the browser state if it's changed before we hydrate.

This resolves the issue by replaying the change events (click, input and
change) if the value has changed by the time we commit the hydration.
That way you can reflect the new value in state to bring it in sync. It
does this whether controlled or uncontrolled.

The idea is that this should be ok to replay because it's similar to the
continuous events in that it doesn't replay a sequence but only reflects
the current state of the tree.

Since this is a breaking change I added it behind
`enableHydrationChangeEvent` flag.

There is still an additional issue remaining that I intend to address in
a follow up. If a `useLayoutEffect` triggers an sync rerender on
hydration (always a bad idea) then that can rerender before we have had
a chance to replay the change events. If that renders through a input
then that input will always override the browser value with the
controlled value. Which will reset it before we've had a change to
update to the new value.

DiffTrain build for [587cb8f896](https://github.com/facebook/react/commit/587cb8f8967866139bbfdbae3f519cb37e68a054)
2025-05-05 21:17:22 -07:00
mattcarrollcode a22ebb7322 Add test for multiple form submissions (#33059)
Test for #30041 and #33055

DiffTrain build for [79586c7eb6](https://github.com/facebook/react/commit/79586c7eb626c6b9362c308a54c9ee5b66e640e5)
2025-05-05 14:54:31 -07:00
jackpope a4ffeb264d Ship enableFabricCompleteRootInCommitPhase (#33064)
This was shipped internally. Cleaning up the flag.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

example:
---

```js
import React from 'react';

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

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

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

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

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

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

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

See:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

## How did you test this change?

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

DiffTrain build for [0038c501a3](https://github.com/facebook/react/commit/0038c501a307e5ddc0cb80027e55740ddda09520)
2025-04-29 03:16:29 -07:00