Commit Graph
6742 Commits
Author SHA1 Message Date
Sebastian MarkbågeandGitHub c52efffceb Ignore generic InvalidStateError in View Transitions (#34450)
Fixes #34098.

There's an issue in Chrome where the `InvalidStateError` always has the
same error message. The spec doesn't specify the error message to use
but it's more useful to have a specific one for each case like Safari
does.

One reason it's better to have a specific error message is because the
browser console is not the main surface that people look for errors.
Chrome relies on a separate log also in the console. Frameworks has
built-in error dialogs that pop up first and that's where you see the
error and that dialog can't show something specific. Additionally, these
errors can't log something specific to servers in production logging. So
this is a bad strategy.

It's not good to have those error dialogs pop up for non-actionable
errors like when it doesn't start because the document was hidden. Since
we don't have more specific information we have no choice but to hide
all of them. This includes actionable things like duplicate names
(although we also have a React specific warning for that in the common
case).
2025-09-10 09:07:11 -04:00
Sebastian MarkbågeandGitHub 0e700041c8 Add missing Activity export to development mode (#34439)
This is exported in the prod version of ReactServer experimental but not
the development version so we can't use it in fixtures from Server
Components.
2025-09-09 21:30:37 -04:00
Sebastian MarkbågeandGitHub 8157a20f71 [Flight] Track I/O Entry for the RSC Stream itself (#34425)
One thing that can suspend is the downloading of the RSC stream itself.
This tracks an I/O entry for each Promise (`SomeChunk<T>`) that
represents the request to the RSC stream. As the value we use the
`Response` for `createFromFetch` (or the `ReadableStream` for
`createFromReadableStream`). The start time is when you called those.

Since we're not awaiting the whole stream, each I/O entry represents the
part of the stream up until it got unblocked. However, in a production
environment with TLS packets and buffering in practice the chunks
received by the client isn't exactly at the boundary of each row. It's a
bit longer into larger chunks. From testing, it seems like multiples of
16kb or 64kb uncompressed are common. To simulate a production
environment we group into roughly 64kb chunks if they happen in rapid
sequence. Note that this might be too small to give a good idea because
of the throttle many boundaries might be skipped anyway so this might
show too many.

The React DevTools will see each I/O entry as separate but dedupe if an
outer boundary already depends on the same chunk. This deduping makes it
so that small boundaries that are blocked on the same chunk, don't get
treated as having unique suspenders. If you have a boundary with large
content, then that content will likely be in a separate chunk which is
not in the parent and then it gets marked as.

This is all just an approximation. The goal of this is just to highlight
that very large boundaries will very likely suspend even if they don't
suspend on any I/O on the server. In practice, these boundaries can
float around a lot and it's really any Suspense boundary that might
suspend but some are more likely than others which this is meant to
highlight.

It also just lets you inspect how many bytes needs to be transferred
before you can show a particular part of the content, to give you an
idea that it's not just I/O on the server that might suspend.

If you don't use the debug channel it can be misleading since the data
in development mode stream will have a lot more data in it which leads
to more chunking.

Similarly to "client references" these I/O infos don't have an "env"
since it's the client that has the I/O and so those are excluded from
flushing in the Server performance tracks.

Note that currently the same Response can appear many times in the same
Instance of SuspenseNode in DevTools when there are multiple chunks. In
a follow up I'll show only the last one per Response at any given level.

Note that when a separate debugChannel is used it has its own I/O entry
that's on the `_debugInfo` for the debug chunks in that channel.
However, if everything works correctly these should never leak into the
DevTools UI since they should never be propagated from a debug chunk to
the values waited by the runtime. This is easy to break though.
2025-09-09 16:46:11 -04:00
Sebastian "Sebbie" SilbermannandGitHub 1dededb81b [Flight] Only use debug component info for parent stacks (#34431) 2025-09-09 19:58:02 +02:00
Sebastian "Sebbie" SilbermannandGitHub c7bd5b30f2 [DevTools] Finalize heuristic for naming unnamed <Suspense> (#34428) 2025-09-09 17:56:26 +02:00
Ruslan LesiutinandGitHub de4379d617 [DevTools] feat: propagate fetchFileWithCaching from initialization options for Fusebox (#34429)
Each integrator: browser extension, Chrome DevTools Frontend fork,
Electron shell must define and provide `fetchFileWithCaching` in order
for DevTools to be able to fetch application resources, such as scripts
or source maps.

More specifically, if this is available, React DevTools will be able to
symbolicate source locations for component frames, owner stacks,
"suspended by" Promises call frames.

This will be available with the next release of React DevTools.
2025-09-09 13:00:53 +01:00
Sebastian "Sebbie" SilbermannandGitHub e354c90876 [DevTools] Fix handling of host roots on mount (#34400) 2025-09-08 22:53:02 +02:00
Sebastian MarkbågeandGitHub 63bed00c1f [Flight] Always initialize a debug info array for each Chunk (#34419)
I'm about to add info for pretty much all of these anyway since they all
depend on the data stream itself.
2025-09-08 12:28:14 -04:00
Sebastian "Sebbie" SilbermannandGitHub e0b99f3fc8 [DevTools] Avoid renders of stale Suspense store (#34396) 2025-09-08 11:42:03 +02:00
laurenandGitHub de568a08d9 [compiler] Derive ErrorSeverity from ErrorCategory (#34401)
With #34176 we now have granular lint rules created for each compiler
ErrorCategory. However, we had remnants of our old error severities
still in use which makes reporting errors quite clunky. Previously you
would need to specify both a category and severity which often ended up
being the same.

This PR moves severity definition into our rules which are generated
from our categories. For now I decided to defer "upgrading" categories
from a simple string to a sum type since we are only using severities to
map errors to eslint severity.

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/34401).
* #34409
* #34404
* #34403
* #34402
* __->__ #34401
2025-09-06 12:41:29 -04:00
KimCookieYaandGitHub 6fcff6fc70 [react-devtools-shared] Fix URL construction when base URL is invalid (#34407)
### Problem
- Users encounter “Failed to construct 'URL': Invalid base URL” when
clicking the “View source” action in DevTools if the underlying base URL
is invalid.
- This exception originates from `new URL(relative, base)` and bubbles
up, interrupting the DevTools UI.
- Fixes GitHub issue
[#34317](https://github.com/facebook/react/issues/34317)

### Solution
- Wrap URL construction to:
  - First try `new URL(sourceMapAt, sourceURL)`.
  - If that fails, try `new URL(sourceMapAt)` as an absolute URL.
  - If both fail, return `null` (no symbolication) rather than throwing.
- This preserves normal behavior for valid bases and absolute URLs,
while avoiding crashes for invalid bases.

### Implementation details
- Updated `symbolicateSource` in
`packages/react-devtools-shared/src/symbolicateSource.js` to handle
invalid base URL scenarios without throwing.
- Added/verified tests in
`packages/react-devtools-shared/src/__tests__/utils-test.js`:
- “should not throw for invalid base URL with relative source map” →
resolves to `null`.
- “should resolve absolute source map even if base URL is invalid” →
still resolves correctly.

### Test plan
- Lint/format:
  - `yarn prettier-check`
  - `yarn linc`
- Type checking:
  - `yarn flow dom-node`
- Unit tests:
  - `yarn test --watchAll=false utils-test`
  - Optionally: `yarn test --watchAll=false utils-test inspectedElement`
- All of the above pass locally for experimental channel.

### Risks and rollout
- Risk: Low. Only affects cases where the base URL is invalid.
- Normal cases (valid base or absolute `sourceMappingURL`) are
unchanged.
- No user-facing API changes; DevTools UX becomes more resilient.

### Affected packages
- `react-devtools-shared`

### Related
- Fixes GitHub issue
[#34317](https://github.com/facebook/react/issues/34317)

### Checklist
- [x] Ran `yarn prettier-check`
- [x] Ran `yarn linc`
- [x] Ran `yarn flow dom-node`
- [x] Relevant unit tests passing
- [x] Linked issue and added a concise summary


<!--
  Thanks for submitting a pull request!
We appreciate you spending the time to work on these changes. Please
provide enough information so that others can review your pull request.
The three fields below are mandatory.

Before submitting a pull request, please make sure the following is
done:

1. Fork [the repository](https://github.com/facebook/react) and create
your branch from `main`.
  2. Run `yarn` in the repository root.
3. If you've fixed a bug or added code that should be tested, add tests!
4. Ensure the test suite passes (`yarn test`). Tip: `yarn test --watch
TestName` is helpful in development.
5. Run `yarn test --prod` to test in the production environment. It
supports the same options as `yarn test`.
6. If you need a debugger, run `yarn test --debug --watch TestName`,
open `chrome://inspect`, and press "Inspect".
7. Format your code with
[prettier](https://github.com/prettier/prettier) (`yarn prettier`).
8. Make sure your code lints (`yarn lint`). Tip: `yarn linc` to only
check changed files.
  9. Run the [Flow](https://flowtype.org/) type checks (`yarn flow`).
  10. If you haven't already, complete the CLA.

Learn more about contributing:
https://reactjs.org/docs/how-to-contribute.html
-->

## Summary

<!--
Explain the **motivation** for making this change. What existing problem
does the pull request solve?
-->

## How did you test this change?

<!--
Demonstrate the code is solid. Example: The exact commands you ran and
their output, screenshots / videos if the pull request changes the user
interface.
How exactly did you verify that your PR solves the issue you wanted to
solve?
  If you leave this empty, your PR will very likely be closed.
-->
2025-09-06 14:00:45 +01:00
Sebastian "Sebbie" SilbermannandGitHub 945532fafa [DevTools] Allow inspecting root when navigating Suspense timeline (#34380) 2025-09-04 16:42:25 +02:00
Sebastian "Sebbie" SilbermannandGitHub 5a552858cb [DevTools] Don't suspend shell while retrieving original source for "open-in-editor" (#34381) 2025-09-04 16:39:07 +02:00
Sebastian "Sebbie" SilbermannandGitHub fb2d8ae6e3 [DevTools] Allow inspection before streaming has finished in Chrome (#34360) 2025-09-04 12:21:06 +02:00
Sebastian "Sebbie" SilbermannandGitHub e8e1440fe1 [DevTools] Rerender boundaries when they unsuspend when advancing the timeline (#34359) 2025-09-04 10:49:16 +02:00
Andrew ClarkandGitHub e349d9912e 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
RickyandGitHub 2fedd565bf [flags] enable opt-in for enableDefaultTransitionIndicator (#34373)
So we can test the feature.
2025-09-03 12:33:55 -04:00
Ruslan LesiutinandGitHub 267b9a68e9 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
Sebastian "Sebbie" SilbermannandGitHub e02e296c30 [DevTools] Remove markers from Suspense timeline (#34357) 2025-09-02 14:59:15 +02:00
Sebastian "Sebbie" SilbermannandGitHub e0f9c8f710 [DevTools] Only inspect elements on left mouseclick (#34361) 2025-09-02 12:40:54 +02:00
Sebastian "Sebbie" SilbermannandGitHub 04ab5b607b [DevTools] Fix inspected element scroll in Suspense tab (#34355) 2025-09-01 16:40:30 +02:00
Hendrik LiebauandGitHub b84ce75512 [Flight] Only assign _store in dev mode when creating lazy types (#34354)
Small follow-up to #34350. The `_store` property is now only assigned in
development mode when creating lazy types. It also uses the `validated`
value that was passed to `createElement`, if applicable.
2025-09-01 12:13:05 +02:00
Hendrik LiebauandGitHub a2b3c58d8c [Flight] Fix wrong missing key warning when static child is blocked (#34350) 2025-09-01 11:03:57 +02:00
Hendrik LiebauandGitHub fb001ce23b [Flight] Don't try to close debug channel twice (#34340)
When the debug channel was already closed, we must not try to close it
again when the Response gets garbage collected.

**Test plan:**

1. reduce the Flight fixture `App` component to a minimum [^1]
    - remove everything from `<body>`
    - delete the `console.log` statement
2. open the app in Firefox (seems to have a more aggressive GC strategy)
3. wait a few seconds

On `main`, you will see the following error in the browser console:

```
TypeError: Can not close stream after closing or error
```

With this change, the error is gone.

[^1]: It's a bit concerning that step 1 is needed to reproduce the
issue. Either GC is behaving differently with the unmodified App, or we
may hold on to the Response under certain conditions, potentially
creating a memory leak. This needs further investigation.
2025-08-29 17:22:39 +02:00
laurenandGitHub 5b722a9eb3 [eprh] Update installation instructions in readme (#34331)
Small PR to update our readme for eslint-plugin-react-hooks, to better
describe what a minimal but complete eslint config would look like.
2025-08-28 18:27:49 -04:00
Sebastian "Sebbie" SilbermannandGitHub 0e67f362f4 [DevTools] Add breadcrumbs to Suspense tab (#34312) 2025-08-28 16:03:54 +02:00
Jack PopeandGitHub 851e413b30 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. 01f31d43013ba7f6f54fd8a36990bbafc3c3cc68 is the
diff between approaches here.
2025-08-27 18:05:57 -04:00
Sebastian "Sebbie" SilbermannandGitHub e4cd0f4c0a [DevTools] Better scrolling in Suspense tab (#34299) 2025-08-27 16:00:06 +02:00
Hendrik LiebauandGitHub 56cc69bb7f [Flight] Don't drop debug info if there's only a readable debug channel (#34304)
When the Flight Client is waiting for pending debug chunks, it drops the
debug info if there is no writable side of the debug channel defined.
However, it should instead check if there's no readable side defined.

Fixing this is not only important for browser clients that don't want or
need a return channel, but it's also crucial for server-side rendering,
because the Node and Edge clients only accept a readable side of the
debug channel. So they can't even define a noop writable side as a
workaround.
2025-08-27 13:50:19 +02:00
Sebastian "Sebbie" SilbermannandGitHub 7ebec60b7c [Fizz] Skip past hidden inputs when attempting to hydrate hydration boundaries (#34302) 2025-08-26 17:28:36 +02:00
Sebastian "Sebbie" SilbermannandGitHub 30cce6ed8f [DevTools] Batch Suspense toggles when advancing the Suspense timeline (#34251) 2025-08-26 17:22:30 +02:00
Hendrik LiebauandGitHub fa7b92a7ea [Flight] Wait for both streams to end before closing the response (#34301)
When a debug channel is defined, we must ensure that we don't close the
Flight Client's response when the debug channel's readable is done, but
the RSC stream is still flowing. Now, we wait for both streams to end
before closing the response.
2025-08-26 17:15:25 +02:00
Sebastian "Sebbie" SilbermannandGitHub f2d60e4cb7 Create more realistic containers in DevTools fixture (#34296) 2025-08-26 17:13:37 +02:00
Sebastian "Sebbie" SilbermannandGitHub cf78fcfb3b [DevTools] Avoid tearing Suspense store (#34294) 2025-08-26 17:09:55 +02:00
Sebastian "Sebbie" SilbermannandGitHub 00aa04c37d [DevTools] Fix symbolication with Index Source Maps (#34300) 2025-08-26 15:18:20 +02:00
Jan KassensandGitHub 0ad9f7507b Fix Flow issue from land race (#34293)
A Flow upgrade removed the bundled library definitinos for
SynthaticEvent and we probably want to use our internal definitions.
Those are not properly typed at this point yet, but we can look into
that as a followup.
2025-08-25 12:58:12 -04:00
Sebastian "Sebbie" SilbermannandGitHub 913de7c110 [DevTools] Initial version of Suspense timeline (#34233) 2025-08-25 17:47:29 +02:00
Jan KassensandGitHub 04cfc7a52d Update Flow to 0.279 (#34277)
Multiple of these version upgrades required minor additional
annotations.
2025-08-25 11:02:56 -04:00
Sebastian "Sebbie" SilbermannandGitHub 30b50eec36 [DevTools] Include name prop when highlighting host instances (#34258) 2025-08-25 16:40:56 +02:00
Sebastian "Sebbie" SilbermannandGitHub f0fc654881 [compiler] Fix missing dependency in eslint-plugin-react-hooks (#34287) 2025-08-25 16:39:23 +02:00
Jan KassensandGitHub c917471e14 Update Flow to 0.274 (#34275)
An exported needed explicit typing as it was inferred incorrectly.
2025-08-22 17:46:37 -04:00
Jan KassensandGitHub 1d7b147992 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 KassensandGitHub a6f4168796 Update Flow to 0.267 (#34272)
Changes to type inference require some more annotations.
2025-08-22 15:53:07 -04:00
Jan KassensandGitHub 16a1f65d70 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 KassensandGitHub f822b87822 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 KassensandGitHub 71d66667aa 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
cc2e4a24c4 Add support for ARIA 1.3 attributes (#34264)
Co-authored-by: Abdulwahab Omira <[email protected]>
Co-authored-by: Sebastian Sebbie Silbermann <[email protected]>
2025-08-22 16:22:18 +02:00
Sebastian MarkbågeandGitHub af7fc7c297 [DevTools] Use source maps to infer name asynchronously (#34212) 2025-08-22 00:38:09 +02:00
0be8a3d2d3 [DevTools] Ignore List Stack Traces (#34210)
Co-authored-by: Sebastian Sebbie Silbermann <[email protected]>
2025-08-22 00:03:05 +02:00
226a7c2941 [compiler] Aggregate error reporting, separate eslint rules (#34176)
NOTE: this is a merged version of @mofeiZ's original PR along with my
edits per offline discussion. The description is updated to reflect the
latest approach.

The key problem we're trying to solve with this PR is to allow
developers more control over the compiler's various validations. The
idea is to have a number of rules targeting a specific category of
issues, such as enforcing immutability of props/state/etc or disallowing
access to refs during render. We don't want to have to run the compiler
again for every single rule, though, so @mofeiZ added an LRU cache that
caches the full compilation output of N most recent files. The first
rule to run on a given file will cause it to get cached, and then
subsequent rules can pull from the cache, with each rule filtering down
to its specific category of errors.

For the categories, I went through and assigned a category roughly 1:1
to existing validations, and then used my judgement on some places that
felt distinct enough to warrant a separate error. Every error in the
compiler now has to supply both a severity (for legacy reasons) and a
category (for ESLint). Each category corresponds 1:1 to a ESLint rule
definition, so that the set of rules is automatically populated based on
the defined categories.

Categories include a flag for whether they should be in the recommended
set or not.

Note that as with the original version of this PR, only
eslint-plugin-react-compiler is changed. We still have to update the
main lint rule.

## Test Plan

* Created a sample project using ESLint v9 and verified that the plugin
can be configured correctly and detects errors
* Edited `fixtures/eslint-v9` and introduced errors, verified that the w
latest config changes in that fixture it correctly detects the errors
* In the sample project, confirmed that the LRU caching is correctly
caching compiler output, ie compiling files just once.

Co-authored-by: Mofei Zhang <[email protected]>
2025-08-21 14:53:34 -07:00