2359 Commits
Author SHA1 Message Date
Sebastian Markbåge 84af9085c1 Log Performance Track Entries for View Transitions (#34510)
Stacked on #34509.

View Transitions introduces a bunch of new types of gaps in the commit
phase which needs to be logged differently in the performance track.

One thing that can happen is that a `flushSync` update forces the View
Transition to abort before it has started if it happens in the gap
before the transition is ready. In that case we log "Interrupted View
Transition".

Otherwise, when we're done in `startViewTransition` there's some work to
finalize the animations before the `ready` calllback. This is logged as
"Starting Animation".

Then there's a gap before the passive effects fire which we log as
"Animating". This can be long unless they're forced to flush early e.g.
due to another lane updating.

The "Animating" track should then pick up which doesn't do yet. This one
is tricky because this is after the actual commit phase and needs to be
interrupted by new renders which themselves can be suspended on the
animation finshing.

This PR is just a subset of all the cases. Will need a lot more work.

<img width="679" height="161" alt="Screenshot 2025-09-16 at 10 19 06 PM"
src="https://github.com/user-attachments/assets/0407372d-aaed-41f5-a262-059b2686ae87"
/>
2025-09-17 13:06:30 -04:00
Sebastian Markbåge e3c9656d20 Ensure Performance Track are Clamped and Don't overlap (#34509)
This simplifies the logic for clamping the start times of various
phases. Instead of checking in multiple places I ensure we compute a
value for each phase that is then clamped to the next phase so they
don't overlap. If they're zero they're not printed.

I also added a name for all the anonymous labels. Those are mainly
fillers for sync work that should be quick but it helps debugging if we
can name them.

Finally the real fix is to update the clamp time which previously could
lead to overlapping entries for consecutive updates when a previous
update never finalized before the next update.
2025-09-17 10:52:02 -04:00
Sebastian Markbåge 5d49b2b7f4 [Fiber] Track SuspendedState on stack instead of global (#34486)
Stacked on #34481.

We currently track the suspended state temporarily with a global which
is safe as long as we always read it during a sync pass. However, we
sometimes read it in closures and then we have to be carefully to pass
the right one since it's possible another commit on a different root has
started at that point. This avoids this footgun.

Another reason to do this is that I want to read it in
`startViewTransition` which is in an async gap after which point it's no
longer safe. So I have to pass that through the `commitRoot` bound
function.
2025-09-15 16:10:47 -04:00
Sebastian Markbåge e3f191803c [Fiber] Adjust the suspensey image/css timeout based on already elapsed time (#34478)
Currently suspensey images doesn't account for how long we've already
been waiting. This means that you can for example wait for 300ms for the
throttle + 500ms for the images. If a Transition takes a while to
complete you can also wait that time + an additional 500ms for the
images.

This tracks the start time of a Transition so that we can count the
timeout starting from when the user interacted or when the last fallback
committed (which is where the 300ms throttle is computed from). Creating
a single timeline.

This also moves the timeout to a central place which I'll use in a
follow up.
2025-09-15 16:05:20 -04:00
RickyandSebastian Sebbie Silbermann 68f00c901c Release Activity in Canary (#34374)
## Overview

This PR ships `<Activity />` to the `react@canary` release channel for
final feedback and prepare for semver stable release.

## What this means

Shipping `<Activity />` to canary means it has gone through extensive
testing in production, we are confident in the stability of the feature,
and we are preparing to release it in a future semver stable version.

Libraries and frameworks following the [Canary
Workflow](https://react.dev/blog/2023/05/03/react-canaries) should begin
implementing and testing the feature.

## Why we follow the Canary Workflow

To prepare for semver stable, libraries should test canary features like
`<Activity>` with `react@canary` to confirm compatibility and prepare
for the next semver release in a myriad of environments and
configurations used throughout the React ecosystem. This provides
libraries with ample time to catch any issues we missed before slamming
them with problems in the wider semver release.

Since these features have already gone through extensive production
testing, and we are confident they are stable, frameworks following the
[Canary Workflow](https://react.dev/blog/2023/05/03/react-canaries) can
also begin adopting canary features like `<Activity />`.

This adoption is similar to how different Browsers implement new
proposed browser features before they are added to the standard. If a
frameworks adopts a canary feature, they are committing to stability for
their users by ensuring any API changes before a semver stable release
are opaque and non-breaking to their users.

Apps not using a framework are also free to adopt canary features like
Activity as long as they follow the [Canary
Workflow](https://react.dev/blog/2023/05/03/react-canaries), but we
generally recommend waiting for a semver stable release unless you have
the capacity to commit to following along with the canary changes and
debugging library compatibility issues.

Waiting for semver stable means you're able to benefit from libraries
testing and confirming support, and use semver as signal for which
version of a library you can use with support of the feature.

## Docs 

Check out the ["React Labs: View Transitions, Activity, and
more"](https://react.dev/blog/2025/04/23/react-labs-view-transitions-activity-and-more#activity)
blog post, and [the new docs for
`<Activity>`](https://react.dev/reference/react/Activity) for more info.

## TODO
- [x] Bump Activity docs to Canary
https://github.com/reactjs/react.dev/pull/7974

---------

Co-authored-by: Sebastian Sebbie Silbermann <sebastian.silbermann@vercel.com>
2025-09-12 12:47:40 -04:00
Sebastian Markbåge 20e5431747 [Flight][Fiber] Encode owner in the error payload in dev and use it as the Error's Task (#34460)
When we report an error we typically log the owner stack of the thing
that caught the error. Similarly we restore the `console.createTask`
scope of the catching component when we call `reportError` or
`console.error`.

We also have a special case if something throws during reconciliation
which uses the Server Component task as far as we got before we threw.


https://github.com/facebook/react/blob/main/packages/react-reconciler/src/ReactChildFiber.js#L1952-L1960

Chrome has since fixed it (on our request) that the Error constructor
snapshots the Task at the time the constructor was created and logs that
in `reportError`. This is a good thing since it means we get a coherent
stack. Unfortunately, it means that the fake Errors that we create in
Flight Client gets a snapshot of the task where they were created so
when they're reported in the console they get the root Task instead of
the Task of the handler of the error.

Ideally we'd transfer the Task from the server and restore it. However,
since we don't instrument the Error object to snapshot the owner and we
can't read the native Task (if it's even enabled on the server) we don't
actually have a correct snapshot to transfer for a Server Component
Error. However, we can use the parent's task for where the error was
observed by Flight Server and then encode that as a pseudo owner of the
Error.

Then we use this owner as the Task which the Error is created within.
Now the client snapshots that Task which is reported by `reportError` so
now we have an async stack for Server Component errors again. (Note that
this owner may differ from the one observed by `captureOwnerStack` which
gets the nearest Server Component from where it was caught. We could
attach the owner to the Error object and use that owner when calling
`onCaughtError`/`onUncaughtError`).

Before:

<img width="911" height="57" alt="Screenshot 2025-09-10 at 10 57 54 AM"
src="https://github.com/user-attachments/assets/0446ef96-fad9-4e17-8a9a-d89c334233ec"
/>

After:

<img width="910" height="128" alt="Screenshot 2025-09-10 at 11 06 20 AM"
src="https://github.com/user-attachments/assets/b30e5892-cf40-4246-a588-0f309575439b"
/>

Similarly, there are Errors and warnings created by ChildFiber itself.
Those execute in the scope of the general render of the parent Fiber.
They used to get the scope of the nearest client component parent (e.g.
div in this case) but that's the parent of the Server Component. It
would be too expensive to run every level of reconciliation in its own
task optimistically, so this does it only when we know that we'll throw
or log an error that needs this context. Unfortunately this doesn't
cover user space errors (such as if an iterable errors).

Before:

<img width="903" height="298" alt="Screenshot 2025-09-10 at 11 31 55 AM"
src="https://github.com/user-attachments/assets/cffc94da-8c14-4d6e-9a5b-bf0833b8b762"
/>

After:

<img width="1216" height="252" alt="Screenshot 2025-09-10 at 11 50
54 AM"
src="https://github.com/user-attachments/assets/f85f93cf-ab73-4046-af3d-dd93b73b3552"
/>

<img width="412" height="115" alt="Screenshot 2025-09-10 at 11 52 46 AM"
src="https://github.com/user-attachments/assets/a76cef7b-b162-4ecf-9b0a-68bf34afc239"
/>
2025-09-12 11:55:07 -04:00
Ruslan Lesiutin 0e10ee906e [Reconciler] Set ProfileMode for Host Root Fiber by default in dev (#34432)
Requiring DevTools to be present for dev builds seems like an overkill,
let's enable the instrumentation by default.

Nothing changes for profiling or production artifacts.
2025-09-12 12:20:39 +01:00
Ruslan Lesiutin 0c813c528d [Tracks]: display method name and component name for updates in DEV (#34463)
For every "Update" entry we are going to add properties that will be
displayed when the user clicks on that entry: name of the method that
caused this first update and name of the component where this update
happened.

We could use the name of the component as a deeplink to React DevTools
components panel in the future, once we support stable identificators on
Fibers.

<img width="1444" height="530" alt="Screenshot 2025-09-10 at 18 31 10"
src="https://github.com/user-attachments/assets/7f9af037-2e7f-4e7b-9b7e-bf9f7d5a6e72"
/>
<img width="2088" height="530" alt="Screenshot 2025-09-10 at 18 24 21"
src="https://github.com/user-attachments/assets/f557a173-bd9b-43f7-9333-74066f433ced"
/>
<img width="2088" height="530" alt="Screenshot 2025-09-10 at 18 26 04"
src="https://github.com/user-attachments/assets/ff37d13f-bbe3-4f85-800e-81aa3aed7833"
/>
2025-09-12 11:34:41 +01:00
Andrew Clark 3302d1f791 Fix: uDV skipped initial value if earlier transition suspended (#34376)
Fixes a bug in useDeferredValue's optional `initialValue` argument. In
the regression case, if a new useDeferredValue hook is mounted while an
earlier transition is suspended, the `initialValue` argument of the new
hook was ignored. After the fix, the `initialValue` argument is
correctly rendered during the initial mount, regardless of whether other
transitions were suspended.

The culprit was related to the mechanism we use to track whether a
render is the result of a `useDeferredValue` hook: we assign the
deferred lane a TransitionLane, then entangle that lane with the
DeferredLane bit. During the subsequent render, we check for the
presence of the DeferredLane bit to determine whether to switch to the
final, canonical value.

But because transition lanes can themselves become entangled with other
transitions, the effect is that every entangled transition was being
treated as if it were the result of a `useDeferredValue` hook, causing
us to skip the initial value and go straight to the final one.

The fix I've chosen is to reserve some subset of TransitionLanes to be
used only for deferred work, instead of using entanglement. This is
similar to how retries are already implemented. Originally I tried not
to implement it this way because it means there are now slightly fewer
lanes allocated for regular transitions, but I underestimated how
similar deferred work is to retries; they end up having a lot of the
same requirements. Eventually it may be possible to merge the two
concepts.
2025-09-03 19:24:38 -04:00
Ruslan Lesiutin 2805f0ed9e Performance Tracks: log properties diff for renders in DEV if no console task available (#34370)
React Native doesn't support `console.createTask` yet, but it does
support `performance.measure` and extensibility APIs for Performance
panel, including `detail.devtools` field.

Previously, this logic was gated with `if (__DEV__ && debugTask)`, now
`debugTask` is no longer required to log render. If there is no console
task, we will just call `performance.measure(...)`. The same pattern is
used in other reporters.
2025-09-03 17:08:05 +01:00
Jack Pope 3434ff4f4b Add scrollIntoView to fragment instances (#32814)
This adds `experimental_scrollIntoView(alignToTop)`. It doesn't yet
support `scrollIntoView(options)`.

Cases:
- No host children: Without host children, we represent the virtual
space of the Fragment by attempting to scroll to the nearest edge by
using its siblings. If the preferred sibling is not found, we'll try the
other side, and then the parent.
- 1 or more host children: In order to handle the case of children
spread between multiple scroll containers, we scroll to each child in
reverse order based on the `alignToTop` flag.

Due to the complexity of multiple scroll containers and dealing with
portals, I've added this under a separate feature flag with an
experimental prefix. We may stabilize it along with the other APIs, but
this allows us to not block the whole feature on it.

This PR was previously implementing a much more complex approach to
handling multiple scroll containers and portals. We're going to start
with the simple loop and see if we can find any concrete use cases where
that doesn't suffice. 01f31d4301 is the
diff between approaches here.
2025-08-27 18:05:57 -04:00
Jan Kassens df10309e2b Update Flow to 0.279 (#34277)
Multiple of these version upgrades required minor additional
annotations.
2025-08-25 11:02:56 -04:00
Jan Kassens 4049cfeeab Update Flow to 0.273 (#34274)
This version introduces "Natural Inference" which requires a couple more
type annotations to make Flow pass.
2025-08-22 16:58:01 -04:00
Jan Kassens 06cfa99f37 Update Flow to 0.267 (#34272)
Changes to type inference require some more annotations.
2025-08-22 15:53:07 -04:00
Jan Kassens 05addfc663 Update Flow to 0.266 (#34271)
- replace `$ElementType` and `$PropertyType` with `T[K]` accesses.
- Use component types
2025-08-22 15:46:41 -04:00
Jan Kassens d260b0d8b8 Update Flow to 0.265 (#34270)
Looks like this version removed `Object.prototype` although I didn't see
that in the changelog. This is fine for this code here.
2025-08-22 15:22:22 -04:00
Jan Kassens 6de32a5a07 Update Flow to 0.263 (#34269)
This update was a bit more involved.

- `React$Component` was removed, I replaced it with Flow component
types.
- Flow removed shipping the standard library. This adds the environment
libraries back from `flow-typed` which seemed to have changed slightly
(probably got more precise and less `any`s). Suppresses some new type
errors.
2025-08-22 12:10:13 -04:00
Jan Kassens d5586e2059 Update Flow to 0.258 (#34254)
Minor new suppressions only.
2025-08-21 14:17:13 -04:00
Jan Kassens ec5dd0ab3a Update Flow to 0.257 (#34253)
After an easy couple version with #34252, this version is less flexible
(and safer) on inferring exported types mainly.

We require to annotate some exported types to differentiate between
`boolean` and literal `true` types, etc.
2025-08-21 13:30:01 -04:00
Sebastian "Sebbie" Silbermann 2cb8edbb05 [DevTools] Handle dehydrated Suspense boundaries (#34196) 2025-08-16 10:34:19 +02:00
Jack Pope a96a0f3903 Fix fragmentInstance#compareDocumentPosition nesting and portal cases (#34069)
Found a couple of issues while integrating
FragmentInstance#compareDocumentPosition into Fabric.

1. Basic checks of nested host instances were inaccurate. For example,
checking the first child of the first child of the Fragment would not
return CONTAINED_BY.
2. Then fixing that logic exposed issues with Portals. The DOM
positioning relied on the assumption that the first and last top-level
children were in the same order as the Fiber tree. I added additional
checks against the parent's position in the DOM, and special cased a
portaled Fragment by getting its DOM parent from the child instance,
rather than taking the instance from the Fiber return. This should be
accurate in more cases. Though its still a guess and I'm not sure yet
I've covered every variation of this. Portals are hard to deal with and
we may end up having to push more results towards
IMPLEMENTATION_SPECIFIC if accuracy is an issue.
2025-08-15 12:14:23 -04:00
Sebastian "Sebbie" Silbermann 379a083b9a Include stack of cause in React instrumentation errors (#34198) 2025-08-13 19:18:02 +02:00
Sebastian Markbåge f1222f7652 [Fiber] Don't bind retry listener if it's in the cache (#34183)
This did an unnecessary bind allocation even if there's cache hit.
2025-08-12 21:42:24 -04:00
Sebastian "Sebbie" Silbermann ac7820a99e Create fresh Offscreen instance when replaying (#34127) 2025-08-11 20:55:48 +02:00
Sebastian Markbåge 53d07944df [Fiber] Assign implicit debug info to used thenables (#34146)
Similar to #34137 but for Promises.

This lets us pick up the debug info from a raw Promise as a child which
is not covered by `_debugThenables`. Currently ChildFiber doesn't stash
its thenables so we can't pick them up from devtools after the fact
without some debug info added to the parent.

It also lets us track some approximate start/end time of use():ed
promises based on the first time we saw this particular Promise.
2025-08-11 11:44:05 -04:00
Sophie Alpert cf6e502ed2 Hot reloading: Avoid stack overflow on wide trees (#34145)
Every sibling added to the stack here. Not sure this needs to be
recursive at all but certainly for siblings this can just be a loop.
2025-08-09 08:02:22 -07:00
Sebastian Markbåge 4c9c109cea [Fiber] Try to give a stack trace to every entry in the Scheduler Performance Track (#34123)
For "render" and "commit" phases we don't give any specific stack atm.
This tries to always provide something useful to say the cause of the
render.

For normal renders this will now show the same thing as the "Event" and
"Update" entries already showed. We stash the task that was used for
those and use them throughout the render and commit phases.

For Suspense (Retry lane) and Idle (Offscreen lane), we don't have any
updates. Instead for those there's a component that left work behind in
previous passes. For those I use the debugTask of the `<Suspense>` or
`<Activity>` boundary to indicate that this was the root of the render.

Similarly when an Action is invoked on a `<form action={...}>` component
using the built-in submit handler, there's no actionable stack in user
space that called it. So we use the stack of the JSX for the form
instead.
2025-08-07 10:26:30 -04:00
Sebastian Markbåge 9be531cd37 [Fiber] Treat unwrapping React.lazy more like a use() (#34031)
While we want to get rid of React.lazy's special wrapper type and just
use a Promise for the type, we still have the wrapper.

However, this is still conceptually the same as a Usable in that it
should be have the same if you `use(promise)` or render a Promise as a
child or type position.

This PR makes it behave like a `use()` when we unwrap them. We could
move to a model where it actually reaches the internal of the Lazy's
Promise when it unwraps but for now I leave the lazy API signature
intact by just catching the Promise and then "use()" that.

This lets us align on the semantics with `use()` such as the suspense
yield optimization. It also lets us warn or fork based on legacy
throw-a-Promise behavior where as `React.lazy` is not deprecated.
2025-07-29 11:50:12 -04:00
Sebastian "Sebbie" Silbermann 7ca2d4cd2e Work around Chrome DevTools crash on performance.measure (#33997) 2025-07-25 12:32:30 +02:00
Sebastian Markbåge 4f34cc4a2e [Fiber] Don't throw away the Error object retaining the owner stack (#33976)
We currently throw away the Error once we've used to the owner stack of
a Fiber once. This maybe helps a bit with memory and redoing it but we
really don't expect most Fibers to hit this at all. It's not very hot.

If we throw away the Error, then we can't use native debugger protocols
to inspect the native stack. Instead, we'd have to maintain a url to
resource map indefinitely like what Chrome DevTools does to map a url to
a resource. Technically it's not even technically correct since the file
path might not be reversible and could in theory conflict.
2025-07-24 13:33:03 -04:00
Ruslan Lesiutin 9fec565a9b fix: log renders from passive effects for only newly finished work (#33797)
This fixes displaying incorrect component render entries on a timeline,
when we are reconnecting passive effects.

### Before
<img width="2318" height="1127" alt="1"
src="https://github.com/user-attachments/assets/9b6b2824-d2de-43a3-8615-2c45d67c3668"
/>

The cloned nodes will persist original `actualStartTime`, when these
were first mounted. When we "replay", the end time will be "now" or
whatever the actual start time of the sibling. Depending on when this is
being recorded, the diff between end and start could be tens of seconds
and doesn't represent what React was doing.

We shouldn't log these entries at all.

### After
We are only logging newly finished renders, but could potentially loose
renders that never commit.
2025-07-16 18:09:35 +01:00
Sebastian Markbåge b44a99bf58 [Fiber] Name content inside "Suspense fallback" (#33724)
Same as #33723 but for Fiber.
2025-07-08 00:00:00 -04:00
Ricky e43986f1f3 Finally remove favorSafetyOverHydrationPerf (#33619)
This is rolled out to 100%.

Let me merge it though.
2025-07-07 13:57:51 -04:00
Sebastian Markbåge 0b78161d7d [Fiber] Highlight a Component with Deeply Equal Props in the Performance Track (#33660)
Stacked on #33658 and #33659.

If we detect that a component is receiving only deeply equal objects,
then we highlight it as potentially problematic and worth looking into.

<img width="1055" alt="Screenshot 2025-06-27 at 4 15 28 PM"
src="https://github.com/user-attachments/assets/e96c6a05-7fff-4fd7-b59a-36ed79f8e609"
/>

It's fairly conservative and can bail out for a number of reasons:

- We only log it on the first parent that triggered this case since
other children could be indirect causes.
- If children has changed then we bail out since this component will
rerender anyway. This means that it won't warn for a lot of cases that
receive plain DOM children since the DOM children won't themselves get
logged.
- If the component's total render time including children is 100ms or
less then we skip warning because rerendering might not be a big deal.
- We don't warn if you have shallow equality but could memoize the JSX
element itself since we don't typically recommend that and React
Compiler doesn't do that. It only warns if you have nested objects too.
- If the depth of the objects is deeper than like the 3 levels that we
print diffs for then we wouldn't warn since we don't know if they were
equal (although we might still warn on a child).
- If the component had any updates scheduled on itself (e.g. setState)
then we don't warn since it would rerender anyway. This should really
consider Context updates too but we don't do that atm. Technically you
should still memoize the incoming props even if you also had unrelated
updates since it could apply to deeper bailouts.
2025-07-02 17:33:07 -04:00
Sebastian Markbåge 508f7aa78f [Fiber] Switch back to using performance.measure for trigger logs (#33659)
Stacked on #33658.

Unfortunately `console.timeStamp` has the same bug that
`performance.measure` used to have where equal start/end times stack in
call order instead of reverse call-order. We rely on that in general so
we should really switch back all.

But there is one case in particular where we always add the same
start/time and that's for the "triggers" -
Mount/Unmount/Reconnect/Disconnect. Switching to `console.timeStamp`
broke this because they now showed below the thing that mounted.

After:

<img width="726" alt="Screenshot 2025-06-27 at 3 31 16 PM"
src="https://github.com/user-attachments/assets/422341c8-bef6-4909-9403-933d76b71508"
/>

Also fixed a bug where clamped update times could end up logging zero
width entries that stacked up on top of each other causing a two row
scheduler lane which should always be one row.
2025-07-02 16:10:52 -04:00
Sebastian Markbåge e104795f63 [Fiber] Show Diff Render Props in Performance Track in DEV (#33658)
<img width="634" alt="Screenshot 2025-06-27 at 1 13 20 PM"
src="https://github.com/user-attachments/assets/dc8c488b-4a23-453f-918f-36b245364934"
/>

We have to be careful with performance in DEV. It can slow down DX since
these are ran whether you're currently running a performance trace or
not. It can also show up as misleading since these add time to the
"Remaining Effects" entry.

I'm not adding all props to the entries. Instead, I'm only adding the
changed props after diffing and none for initial mount. I'm trying to as
much as possible pick a fast path when possible. I'm also only logging
this for the "render" entries and not the effects. If we did something
for effects, it would be more like checking with dep changed.

This could still have a negative effect on dev performance since we're
now also using the slower `performance.measure` API when there's a diff.
2025-07-02 16:10:07 -04:00
Jan Kassens 73aa744b70 Remove now dead argument from resolveClassComponentProps (#33682)
No longer used after https://github.com/facebook/react/pull/33648
2025-07-02 10:45:37 -04:00
Jan Kassens 602917c8cb Cleanup disableDefaultPropsExceptForClasses flag (#33648) 2025-07-01 15:52:56 -04:00
Ruslan Lesiutin 91d097b2c5 fix: rename bottom stack frame (#33680)
`react-stack-bottom-frame` -> `react_stack_bottom_frame`.

This survives `@babel/plugin-transform-function-name`, but now frames
will be displayed as `at Object.react_stack_bottom_frame (...)` in V8.
Checks that were relying on exact function name match were updated to
use either `.indexOf()` or `.includes()`

For backwards compatibility, both React DevTools and Flight Client will
look for both options. I am not so sure about the latter and if React
version is locked.
2025-07-01 18:06:26 +01:00
Sebastian Markbåge d2a288febf Include Component Props in Performance Track (#33655)
Similar to how we can include a Promise resolved value we can include
Component Props.

For now I left out props for Client Components for perf unless they
error. I'll try it for Client Components in general in a separate PR.

<img width="730" alt="Screenshot 2025-06-26 at 5 54 29 PM"
src="https://github.com/user-attachments/assets/f0c86911-2899-4b5f-b45f-5326bdbc630f"
/>
<img width="762" alt="Screenshot 2025-06-26 at 5 54 12 PM"
src="https://github.com/user-attachments/assets/97540d19-5950-4346-99e6-066af086040e"
/>
2025-06-27 08:45:56 -04:00
Sebastian Markbåge 4a523489b7 Get Server Component Function Location for Parent Stacks using Child's Owner Stack (#33629)
This is using the same trick as #30798 but for runtime code too. It's
essential zero cost.

This lets us include a source location for parent stacks of Server
Components when it has an owned child's location. Either from JSX or
I/O.

Ironically, a Component that throws an error will likely itself not get
the stack because it won't have any JSX rendered yet.
2025-06-24 16:35:28 -04:00
Ricky 12eaef7ef5 [refactor] remove unused fiberstack functions (#33623) 2025-06-23 20:07:04 -04:00
Jan Kassens aab72cb1cb rename ReactFiberContext to ReactFiberLegacyContext (#33622)
It wasn't immediately obvious to me, that all the exports here are
related to legacy context, so renaming for clarity.

Modern context lives in `ReactFiberNewContext` which we could probably
also raname in a separate step to just Context.
2025-06-23 17:21:18 -04:00
Sebastian Markbåge e1dc03492e Expose cacheSignal() alongside cache() (#33557)
This was really meant to be there from the beginning. A `cache()`:ed
entry has a life time. On the server this ends when the render finishes.
On the client this ends when the cache of that scope gets refreshed.

When a cache is no longer needed, it should be possible to abort any
outstanding network requests or other resources. That's what
`cacheSignal()` gives you. It returns an `AbortSignal` which aborts when
the cache lifetime is done based on the same execution scope as a
`cache()`ed function - i.e. `AsyncLocalStorage` on the server or the
render scope on the client.

```js
import {cacheSignal} from 'react';
async function Component() {
  await fetch(url, { signal: cacheSignal() });
}
```

For `fetch` in particular, a patch should really just do this
automatically for you. But it's useful for other resources like database
connections.

Another reason it's useful to have a `cacheSignal()` is to ignore any
errors that might have triggered from the act of being aborted. This is
just a general useful JavaScript pattern if you have access to a signal:

```js
async function getData(id, signal) {
  try {
     await queryDatabase(id, { signal });
  } catch (x) {
     if (!signal.aborted) {
       logError(x); // only log if it's a real error and not due to cancellation
     }
     return null;
  }
}
```

This just gets you a convenient way to get to it without drilling
through so a more idiomatic code in React might look something like.

```js
import {cacheSignal} from "react";

async function getData(id) {
  try {
     await queryDatabase(id);
  } catch (x) {
     if (!cacheSignal()?.aborted) {
       logError(x);
     }
     return null;
  }
}
```

If it's called outside of a React render, we normally treat any cached
functions as uncached. They're not an error call. They can still load
data. It's just not cached. This is not like an aborted signal because
then you couldn't issue any requests. It's also not like an infinite
abort signal because it's not actually cached forever. Therefore,
`cacheSignal()` returns `null` when called outside of a React render
scope.

Notably the `signal` option passed to `renderToReadableStream` in both
SSR (Fizz) and RSC (Flight Server) is not the same instance that comes
out of `cacheSignal()`. If you abort the `signal` passed in, then the
`cacheSignal()` is also aborted with the same reason. However, the
`cacheSignal()` can also get aborted if the render completes
successfully or fatally errors during render - allowing any outstanding
work that wasn't used to clean up. In the future we might also expand on
this to give different
[`TaskSignal`](https://developer.mozilla.org/en-US/docs/Web/API/TaskSignal)
to different scopes to pass different render or network priorities.

On the client version of `"react"` this exposes a noop (both for
Fiber/Fizz) due to `disableClientCache` flag but it's exposed so that
you can write shared code.
2025-06-17 17:04:40 -04:00
Jan Kassens 5d24c64cc9 Remove feature flag enableDO_NOT_USE_disableStrictPassiveEffect (#33524) 2025-06-16 12:22:47 -04:00
Jan Kassens b7e2de632b Stringify context as SomeContext instead of SomeContext.Provider (#33507)
This matches the change in React 19 to use `<SomeContext>` as the
preferred way to provide a context.
2025-06-11 12:08:04 -04:00
Jan Kassens 6c86e56a0f Remove feature flag enableRenderableContext (#33505)
The flag is fully rolled out.
2025-06-11 11:53:04 -04:00
c38e268978 [Fiber] Fix hydration of useId in SuspenseList (#33491)
Includes #31412.

The issue is that `pushTreeFork` stores some global state when reconcile
children. This gets popped by `popTreeContext` in `completeWork`.
Normally `completeWork` returns its own `Fiber` again if it wants to do
a second pass which will call `pushTreeFork` again in the next pass.
However, `SuspenseList` doesn't return itself, it returns the next child
to work on.

The fix is to keep track of the count and push it again it when we
return the next child to attempt.

There are still some outstanding issues with hydration. Like the
backwards test still has the wrong behavior in it because it hydrates
backwards and so it picks up the DOM nodes in reverse order.
`tail="hidden"` also doesn't work correctly.

There's also another issue with `useId` and `AsyncIterable` in
SuspenseList when there's an unknown number of children. We don't
support those showing one at a time yet though so it's not an issue yet.
To fix it we need to add variable total count to the `useId` algorithm.
E.g. by falling back to varint encoding.

---------

Co-authored-by: Rick Hanlon <rickhanlonii@fb.com>
Co-authored-by: Ricky <rickhanlonii@gmail.com>
2025-06-09 19:37:49 -04:00
Sebastian Markbåge d742611ce4 Replace Implicit Options on SuspenseList with Explicit Options (#33424)
We want to change the defaults for `revealOrder` and `tail` on
SuspenseList. This is an intermediate step to allow experimental users
to upgrade.

To explicitly specify these options I added `revealOrder="independent"`
and `tail="visible"`.

I then added warnings if `undefined` or `null` is passed. You must now
always explicitly specify them. However, semantics are still preserved
for now until the next step.

We also want to change the rendering order of the `children` prop for
`revealOrder="backwards"`. As an intermediate step I first added
`revealOrder="unstable_legacy-backwards"` option. This will only be
temporary until all users can switch to the new `"backwards"` semantics
once we flip it in the next step.

I also clarified the types that the directional props requires iterable
children but not iterable inside of those. Rows with multiple items can
be modeled as explicit fragments.
2025-06-03 17:40:30 -04:00
Sebastian Markbåge 1ae0a845bd Use underscore instead of « » for useId algorithm (#33422)
Alternative to #33421. The difference is that this also adds an
underscore between the "R" and the ID.

The reason we wanted to use special characters is because we use the
full spectrum of A-Z 0-9 in our ID generation so we can basically
collide with any common word (or anyone using a similar algorithm,
base64 or even base16). It's a little less likely that someone would put
`_R_` specifically unless you generate like two IDs separated by
underscore.


![9w2ogt](https://github.com/user-attachments/assets/21b2d2ac-1a3a-4657-ba0b-1616e49dfdee)
2025-06-03 11:30:17 -04:00