Commit Graph
5670 Commits
Author SHA1 Message Date
Timothy Yung ef0f44ecff Enable enableDeferRootSchedulingToMicrotask and enableInfiniteRenderLoopDetection for React Native (Meta) (#30090) 2024-06-26 08:50:06 -07:00
Ruslan Lesiutin a8b465c6e0 fix[react-devtools]: restore original args when recording errors (#30091)
## Summary

When DevTools frontend and backend are connected, we patch console in 2
places:
- `patch()`, when renderer is attached to:
  - listen to any errors / warnings emitted
  - append component stack if requested by the user
- `patchForStrictMode()`, when React notifies about that the next
invocation is about to happed during StrictMode

`patchForStrictMode()` will always be at the top of the patch stack,
because it is called at runtime when React notifies React DevTools,
because of this, `patch()` may receive already modified arguments (with
stylings for dimming), we should attempt to restore the original
arguments

## How did you test this change?

Look at yellow warnings on the element view:
| Before | After |
| --- | --- |
| ![Screenshot 2024-06-25 at 14 38
26](https://github.com/facebook/react/assets/28902667/6b0ec512-f0c9-4557-a524-d7f31b03464d)
| ![Screenshot 2024-06-25 at 17 26
23](https://github.com/facebook/react/assets/28902667/60ff5d80-06ea-4447-bbe8-b57bc0c63f6d)
|
2024-06-26 14:17:09 +01:00
LoganDarkandRuslan Lesiutin 133ada7254 Read constructor name more carefully (#29954)
## Summary

Sometimes `constructor` happens to be the name of an unrelated property,
or we may be dealing with a `Proxy` that intercepts every read. Verify
the constructor is a function before using its name, and reset the name
anyway if it turns out not to be serializable.

Fixes some cases of the devtools crashing and becoming inoperable upon
attempting to inspect components whose props are Hookstate `State`s.

## How did you test this change?

Installed a patched version of the extension and confirmed that it
solves the problem.

---------

Co-authored-by: Ruslan Lesiutin <rdlesyutin@gmail.com>
2024-06-25 19:30:28 +01:00
Jack Pope 89580f209c Set renameElementSymbol to dynamic value (#30066)
Prepare to roll this out with dynamic flag

`yarn flags --diff www canary`

<img width="514" alt="Screenshot 2024-06-24 at 11 33 55 AM"
src="https://github.com/facebook/react/assets/8965173/31508fdc-4cb1-4ce0-8e22-c02a034377b0">
2024-06-24 12:28:39 -04:00
Jack Pope c21bcd627b Clean up enableUnifiedSyncLane flag (#30062)
`enableUnifiedSyncLane` now passes everywhere. Let's clean it up

Implemented with https://github.com/facebook/react/pull/27646

Flag enabled with https://github.com/facebook/react/pull/27646,
https://github.com/facebook/react/pull/28269,
https://github.com/facebook/react/pull/29052
2024-06-24 11:18:22 -04:00
Ruslan Lesiutin 7608516479 refactor[react-devtools/extensions]: dont debounce cleanup logic on navigation (#30027)
## Summary
There is a race condition in the way we poll if React is on the page and
when we actually clear this polling instance. When user navigates to a
different page, we will debounce a callback for 500ms, which will:
1. Cleanup previous React polling instance
2. Start a new React polling instance

Since the cleanup logic is debounced, there is a small chance that by
the time we are going to clean up this polling instance, it will be
`eval`-ed on the page, that is using React. For example, when user is
navigating from the page which doesn't have React running, to a page
that has React running.

Next, we incorrectly will try to mount React DevTools panels twice,
which will result into conflicts in the Store, and the error will be
shown to the user

## How did you test this change?
Since this is a race condition, it is hard to reproduce consistently,
but you can try this flow:
1. Open a page that is using React, open browser DevTools and React
DevTools components panel
2. Open a page that is NOT using React, like google.com, wait ~5 seconds
until you see `"Looks like this page doesn't have React, or it hasn't
been loaded yet"` message in RDT panel
3. Open a page that is using React, observe the error `"Uncaught Error:
Cannot add node "1" because a node with that id is already in the
Store."`

Couldn't been able to reproduce this with these changes.
2024-06-24 13:28:17 +01:00
Lauren Tan 85215413cb [ci] Improve parallelism of yarn test
This PR adds parallelism similar to our existing circleci setup for
running yarn tests with the various test params. It does this by
sharding tests into `$SHARD_COUNT` number of groups, then spawning a job
for each of them and using jest's built in `--shard` option.

Effectively this means that the job will spawn an additional (where `n`
is the number of test params)

`n * $SHARD_COUNT` number of jobs to run tests in parallel

for a total of `n + (n * $SHARD_COUNT)` jobs. This does mean the
GitHub UI at the bottom of each PR gets longer and unfortunately it's
not sorted in any way as far as I can tell. But if something goes wrong
it should still be easy to find out what the problem is.

The PR also changes the `ci` argument for jest-cli to be an enum instead
so the tests use all available workers in GitHub actions. This will have
to live around for a bit until we can fully migrate off of circleci.

ghstack-source-id: 08f2d16353
Pull Request resolved: https://github.com/facebook/react/pull/30033
2024-06-22 12:37:42 -04:00
Jan Kassens b565373afd lint: enable reportUnusedDisableDirectives and remove unused suppressions (#28721)
This enables linting against unused suppressions and removes the ones
that were unused.
2024-06-21 12:24:32 -04:00
Jan Kassens 0b724e9e9c www: remove dynamic scheduler feature flag: enableProfiling (#29996)
I removed the wrong feature flag in #29995, this is the correct one to
match D58682445.
2024-06-21 09:51:46 -04:00
Sebastian Markbåge 6fb39ec9e9 Plumbing of isomorphic code (#29967)
Need to tighten up this a bit.

react-dom isomorphic currently depends on react-reconciler which is
mostly DCE but it's pulled in which makes it hard to make other bundling
changes.

ReactFlightServer can have a hard dependency on the module that imports
its internals since even if other internals are aliased it still always
needs the server one.
2024-06-21 06:39:10 -04:00
Jan Kassens 6ab67c35f1 Revert "www: remove dynamic feature flag enableSchedulingProfiler" (#29995)
Reverts facebook/react#29994
2024-06-20 17:17:25 -04:00
Jan Kassens babe5a2f1b www: remove dynamic feature flag enableSchedulingProfiler (#29994) 2024-06-20 16:47:28 -04:00
Ruslan Lesiutin b15c8492ca fix[react-devtools/extensions]: propagate globals from env (#29963)
Somehow missed this while working on
https://github.com/facebook/react/pull/29869.

With these changes, manual inspection of the
`react_devtools_backend_compact.js` doesn't have any occurences of
`__IS_FIREFOX__` flag.
2024-06-20 09:29:05 +01:00
Sebastian Markbåge 6b4646cbd0 Export captureOwnerStacks() only in DEV "react" builds (#29923)
Only with the enableOwnerStacks flag (which is not on in www).

This is a new DEV-only API to be able to implement what we do for
console.error in user space.

This API does not actually include the current stack that you'd get from
`new Error().stack`. That you'd have to add yourself.

This adds the ability to have conditional development exports because we
plan on eventually having separate ESM builds that use the "development"
or "production" export conditions.

NOTE: This removes the export of `act` from `react` in prod (as opposed
to a function that throws) - inline with what we do with other
conditional exports.
2024-06-19 14:19:48 -04:00
Ruslan Lesiutin e684ca66ab refactor[react-devtools/tests]: use registered marks instead of cleared in tests (#29929)
## Summary
This is the pre-requisite for
https://github.com/facebook/react/pull/29231.

Current implementation of profiling hooks is only using
`performance.mark` and then makes `performance.clearMarks` call right
after it to free the memory. We've been relying on this assumption in
the tests that every mark is cleared by the time we check something.

https://github.com/facebook/react/pull/29231 adds `performance.measure`
calls and the `start` mark is not cleared until the corresponding `stop`
one is registered, and then they are cleared together.

## How did you test this change?
To test against React from source:
```
yarn test --build --project=devtools -r=experimental --ci
```

To test against React 18:
```
./scripts/circleci/download_devtools_regression_build.js 18.0 --replaceBuild
node ./scripts/jest/jest-cli.js --build --project devtools --release-channel=experimental --reactVersion 18.0 --ci
```
2024-06-19 15:45:01 +01:00
Ruslan Lesiutin 1434af3d22 React DevTools 5.2.0 -> 5.3.0 (#29918)
Full list of changes:

* chore[react-devtools]: improve console arguments formatting before
passing it to original console ([hoxyq](https://github.com/hoxyq) in
[#29873](https://github.com/facebook/react/pull/29873))
* chore[react-devtools]: unify console patching and default to ansi
escape symbols ([hoxyq](https://github.com/hoxyq) in
[#29869](https://github.com/facebook/react/pull/29869))
* chore[react-devtools/backend]: remove
consoleManagedByDevToolsDuringStrictMode
([hoxyq](https://github.com/hoxyq) in
[#29856](https://github.com/facebook/react/pull/29856))
* chore[react-devtools/extensions]: make source maps url relative
([hoxyq](https://github.com/hoxyq) in
[#29886](https://github.com/facebook/react/pull/29886))
* fix[react-devtools] divided inspecting elements between inspecting do…
([vzaidman](https://github.com/vzaidman) in
[#29885](https://github.com/facebook/react/pull/29885))
* [Fiber] Create virtual Fiber when an error occurs during reconcilation
([sebmarkbage](https://github.com/sebmarkbage) in
[#29804](https://github.com/facebook/react/pull/29804))
* fix[react-devtools] component badge in light mode is now not invisible
([vzaidman](https://github.com/vzaidman) in
[#29852](https://github.com/facebook/react/pull/29852))
* Remove Warning: prefix and toString on console Arguments
([sebmarkbage](https://github.com/sebmarkbage) in
[#29839](https://github.com/facebook/react/pull/29839))
* Add jest lint rules ([rickhanlonii](https://github.com/rickhanlonii)
in [#29760](https://github.com/facebook/react/pull/29760))
* [Fiber] Track the Real Fiber for Key Warnings
([sebmarkbage](https://github.com/sebmarkbage) in
[#29791](https://github.com/facebook/react/pull/29791))
* fix[react-devtools/store-test]: fork the test to represent current be…
([hoxyq](https://github.com/hoxyq) in
[#29777](https://github.com/facebook/react/pull/29777))
* Default native inspections config false
([vzaidman](https://github.com/vzaidman) in
[#29784](https://github.com/facebook/react/pull/29784))
* fix[react-devtools] remove native inspection button when it can't be
used ([vzaidman](https://github.com/vzaidman) in
[#29779](https://github.com/facebook/react/pull/29779))
* chore[react-devtools]: ip => internal-ip
([hoxyq](https://github.com/hoxyq) in
[#29772](https://github.com/facebook/react/pull/29772))
* Fix #29724: `ip` dependency update for CVE-2024-29415
([Rekl0w](https://github.com/Rekl0w) in
[#29725](https://github.com/facebook/react/pull/29725))
* cleanup[react-devtools]: remove unused supportsProfiling flag from
store config ([hoxyq](https://github.com/hoxyq) in
[#29193](https://github.com/facebook/react/pull/29193))
* [Fiber] Enable Native console.createTask Stacks When Available
([sebmarkbage](https://github.com/sebmarkbage) in
[#29223](https://github.com/facebook/react/pull/29223))
* Move createElement/JSX Warnings into the Renderer
([sebmarkbage](https://github.com/sebmarkbage) in
[#29088](https://github.com/facebook/react/pull/29088))
* Set the current fiber to the source of the error during error
reporting ([sebmarkbage](https://github.com/sebmarkbage) in
[#29044](https://github.com/facebook/react/pull/29044))
* Unify ReactFiberCurrentOwner and ReactCurrentFiber
([sebmarkbage](https://github.com/sebmarkbage) in
[#29038](https://github.com/facebook/react/pull/29038))
* Dim `console` calls on additional Effect invocations due to
`StrictMode` ([eps1lon](https://github.com/eps1lon) in
[#29007](https://github.com/facebook/react/pull/29007))
* refactor[react-devtools]: rewrite context menus
([hoxyq](https://github.com/hoxyq) in
[#29049](https://github.com/facebook/react/pull/29049))
2024-06-18 12:12:27 +01:00
Ruslan Lesiutin 107a2f8c3e chore[react-devtools]: improve console arguments formatting before passing it to original console (#29873)
Stacked on https://github.com/facebook/react/pull/29869.

## Summary

When using ANSI escape sequences, we construct a message in the
following way: `console.<method>('\x1b...%s\x1b[0m',
userspaceArgument1?, userspaceArgument2?, userspaceArgument3?, ...)`.

This won't dim all arguments, if user had something like `console.log(1,
2, 3)`, we would only apply it to `1`, since this is the first
arguments, so we need to:
- inline everything whats possible into a single string, while
preserving console substitutions defined by the user
- omit css and object substitutions, since we can't really inline them
and will delegate in to the environment

## How did you test this change?

Added some tests, manually inspected that it works well for web and
native cases.
2024-06-17 16:38:03 +01:00
Ruslan Lesiutin ff6e05a705 chore[react-devtools]: unify console patching and default to ansi escape symbols (#29869)
Stacked on https://github.com/facebook/react/pull/29856.

## Summary

By default, React DevTools will apply dimming with ANSI escape symbols,
so it works for both terminals and browser consoles.

For Firefox, which doesn't support ANSI escape symbols console stylings,
we fallback to css properties, like we used to do before.

## How did you test this change?

| Environment | Dark mode | Light mode |
|--------|--------|--------|
| Terminal | ![Screenshot 2024-06-12 at 19 39
46](https://github.com/facebook/react/assets/28902667/2d470eee-ec5f-4362-be7d-8d80c6c72d09)
| ![Screenshot 2024-06-12 at 19 39
09](https://github.com/facebook/react/assets/28902667/616f2c58-a251-406b-aee6-841e07d652ba)
|
| Fusebox&nbsp;console | ![Screenshot 2024-06-12 at 21 03
14](https://github.com/facebook/react/assets/28902667/6050f730-8e82-4aa1-acbc-7179aac3a8aa)
| ![Screenshot 2024-06-12 at 21 02
48](https://github.com/facebook/react/assets/28902667/6708b938-8a90-476f-a057-427963d58caa)
|
| Firefox&nbsp;console | ![Screenshot 2024-06-12 at 21 40
29](https://github.com/facebook/react/assets/28902667/4721084f-bbfa-438c-b61b-395da8ded590)
| ![Screenshot 2024-06-12 at 21 40
42](https://github.com/facebook/react/assets/28902667/72bbf001-2d3d-49e7-91c9-20a4f0914d4d)
|
| Chrome&nbsp;console | ![Screenshot 2024-06-12 at 21 43
09](https://github.com/facebook/react/assets/28902667/93c47881-a0dd-44f8-8dc2-8710149774e5)
| ![Screenshot 2024-06-12 at 21 43
00](https://github.com/facebook/react/assets/28902667/07ea4ff5-4322-4db9-9c12-4321d9577c9d)
|
2024-06-17 16:31:36 +01:00
Ruslan Lesiutin 92219ff9b8 chore[react-devtools/backend]: remove consoleManagedByDevToolsDuringStrictMode (#29856)
## Summary

Removes the usage of `consoleManagedByDevToolsDuringStrictMode` flag
from React DevTools backend, this is the only place in RDT where this
flag was used. The only remaining part is
[`ReactFiberDevToolsHook`](https://github.com/facebook/react/blob/67081159377b438b48e3c2f2278af8e5f56b9f64/packages/react-reconciler/src/ReactFiberDevToolsHook.js#L203),
so React renderers can start notifying DevTools when `render` runs in a
Strict Mode.

> TL;DR: it is broken, and we already incorrectly apply dimming, when
RDT frontend is not opened. Fixing in the next few changes, see next
steps.

Before explaining why I am removing this, some context is required. The
way RDT works is slightly different, based on the fact if RDT frontend
and RDT backend are actually connected:
1. For browser extension case, the Backend is a script, which is
injected by the extension when page is loaded and before React is
loaded. RDT Frontend is loaded together with the RDT panel in browser
DevTools, so ONLY when user actually opens the RDT panel.
2. For native case, RDT backend is shipped together with `react-native`
for DEV bundles. It is always injected before React is loaded. RDT
frontend is loaded only when user starts a standalone RDT app via `npx
react-devtools` or by opening React Native DevTools and then selecting
React DevTools panel.

When Frontend is not connected to the Backend, the only thing we have is
the `__REACT_DEVTOOLS_GLOBAL_HOOK__` — this thing inlines some APIs in
itself, so that it can work similarly when RDT Frontend is not even
opened. This is especially important for console logs, since they are
cached and stored, then later displayed to the user once the Console
panel is opened, but from RDT side, you want to modify these console
logs when they are emitted.

In order to do so, we [inline the console patching logic into the
hook](https://github.com/facebook/react/blob/3ac551e855f9bec3161da2fc8787958aa62113db/packages/react-devtools-shared/src/hook.js#L222-L319).
This implementation doesn't use the
`consoleManagedByDevToolsDuringStrictMode`. This means that if we enable
`consoleManagedByDevToolsDuringStrictMode` for Native right now, users
would see broken dimming in LogBox / Metro logs when RDT Frontend is not
opened.

Next steps:
1. Align this console patching implementation with the one in `hook.js`.
2. Make LogBox compatible with console stylings: both css and ASCII
escape symbols.
3. Ship new version of RDT with these changes.
4. Remove `consoleManagedByDevToolsDuringStrictMode` from
`ReactFiberDevToolsHook`, so this is rolled out for all renderers.
2024-06-17 16:13:04 +01:00
Ruslan Lesiutin d7bb6039de chore[react-devtools/extensions]: make source maps url relative (#29886)
This adds few changes:
1. We are going to ship source maps only for 2 artifacts:
`installHook.js` and `react_devtools_backend_compact.js`, because it is
only these modules that can patch console and be visible to the user via
stack traces in console. We need to ship source maps to be able to use
`ignoreList` feature in source maps, so we can actually hide these from
stack traces.

| Before | After |
|--------|--------|
| ![Screenshot 2024-06-13 at 17 44
25](https://github.com/facebook/react/assets/28902667/464e097b-a95e-47eb-967c-0579daad316b)
| ![Screenshot 2024-06-13 at 17 39
53](https://github.com/facebook/react/assets/28902667/e4afe642-d65b-4296-a2cf-26c0b925ebf2)
|
 
2. The `"sources"` field in source map will have relative urls listed,
instead of absolute with `webpack://` protocol. This will move the
sources to the `React Developer Tools` frame in `Sources` panel, instead
of `webpack://`.
 
 | Before | After |
|--------|--------|
| ![Screenshot 2024-06-13 at 17 48
24](https://github.com/facebook/react/assets/28902667/a18edad2-5b4e-4ad7-8a7a-8b389c2edf92)
| ![Screenshot 2024-06-13 at 17 49
41](https://github.com/facebook/react/assets/28902667/5db491f7-5d1d-4155-9910-16ac4384d34e)
|

> [!NOTE]  
> I still have 1 unresolved issue with shipping source maps in extension
build, and it is related to Firefox, which can't find them in the
extension bundle and returns 404, even though urls are relative and I
can actually open them via unique address like
`moz-extension://<extension-id>/build/intallHook.js.map` ¯\\\_(ツ)\_/¯
2024-06-17 11:58:19 +01:00
Timothy Yung f14d7f0d25 Prepare Feature Flags for React Native 0.75 (#29903)
## Summary

Configures the React Native open source feature flags in preparation for
React Native 0.75, which will be upgraded to React 19.

## How did you test this change?

```
$ yarn test
$ yarn flow fabric
```
2024-06-14 17:09:50 -07:00
Jan Kassens 88959fd54a Revert "Set disableLegacyMode to true for www" (#29901)
Reverts facebook/react#29871

Just temporarily while we're investigating something.
2024-06-14 15:27:32 -04:00
Eric Rozell 3154ec8a38 Use a constant HostContext in prod builds for Fabric renderer (#29888)
<!--
  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?
-->

In the Fabric renderer in React Native, we only use the HostContext to
issue soft errors in __DEV__ bundles when attempting to add a raw text
child to a node that may not support them. Moving the logic to set this
context to __DEV__ bundles only unblocks more expensive methods for
resolving whether a parent context supports raw text children, like
resolving this information from `getViewConfigForType`.

## 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.
-->

yarn test (--prod)
2024-06-14 13:37:19 -04:00
Jan Kassens f0e8164410 sanitize javascript: urls for <object> tags (#29808)
sanitize javascript: urls for <object> tags

React 19 added sanitization for `javascript:` URLs for `href` properties
on various tags. This PR also adds that sanitization for `<object>` tags
as well that Firefox otherwise executes.
2024-06-14 13:17:43 -04:00
Jan Kassens fb9a90fa48 Set disableLegacyMode to true for www (#29871)
Set disableLegacyMode to true for www
2024-06-14 09:52:49 -04:00
Vitali Zaidman d9a5b6393a fix[react-devtools] divided inspecting elements between inspecting do… (#29885)
# **before**
* nav to dom element from devtools
* nav to devtools element from page
are enabled on extension and disabled on the rest of the flavors.

## extension:
* nav to dom element from devtools **enabled** and working
* nav to devtools element from page **enabled** and working
![Screenshot 2024-06-13 at 11 15
11](https://github.com/facebook/react/assets/5188459/fef78b70-d22c-4405-8871-8b0449b51937)

## inline:
* nav to dom element from devtools **disabled**
* nav to devtools element from page **disabled**

![before-inline](https://github.com/facebook/react/assets/5188459/24020dc2-baec-4d0a-84d4-45c96d653843)

## standalone:
* nav to dom element from devtools **disabled**
* nav to devtools element from page **disabled**

![before-standalone](https://github.com/facebook/react/assets/5188459/19b4cb34-9d1f-412e-baea-59ea85f99d04)

## fusebox:
* nav to dom element from devtools **disabled**
* nav to devtools element from page **disabled**

![before-fusebox](https://github.com/facebook/react/assets/5188459/1a18fda4-04b8-40f4-ae8b-e059889fca93)

# **after**
same:
* nav to dom element from devtools
* nav to devtools element from page
are enabled on extension and disabled on inline.

change:
standalone and fusebox can nav to devtools element from page

## extension:
* nav to dom element from devtools **enabled** and working
* nav to devtools element from page **enabled** and working
![Screenshot 2024-06-13 at 10 50
25](https://github.com/facebook/react/assets/5188459/f4679c72-b211-43d6-b3ea-6380e0d1edf0)

## inline:
* nav to dom element from devtools **disabled**
* nav to devtools element from page **disabled**

![after-inline](https://github.com/facebook/react/assets/5188459/fdfdd87b-9bc3-47f3-b1e0-730239f6485d)

## standalone:
* nav to dom element from devtools **disabled**
* nav to devtools element from page **enabled** and working

![after-standalone](https://github.com/facebook/react/assets/5188459/b25e3c63-a697-4b0c-8ad2-0e12ec5c3e9c)

## fusebox:
* nav to dom element from devtools **disabled**
* nav to devtools element from page **enabled** and working

![after-fusebox](https://github.com/facebook/react/assets/5188459/f14147d8-9831-4909-a164-52f892c875e5)
2024-06-13 15:37:51 +01:00
Josh Story 7f3911fac0 Standardize condition order so that edge-lite preferred over browser (#29877)
The export maps for react packages have to choose an order of
preference. Many runtimes use multiple conditions, for instance when
building for edge webpack also uses the browser condition which makes
sense given most edge runtimes have a web-standards based set of APIs.
However React is building the browser builds primarily for actual
browsers and sometimes have builds intended for servers that might be
browser compat. This change updates the order of conditions to
preference specific named runtimes > node > generic edge runtimes >
browser > default
2024-06-12 15:31:23 -07:00
Sebastian Markbåge 195d5bb99e Execute event handlers in the context of the instance that it's associated with (#29876)
That way we get owner stacks (native or otherwise) for `console.error`
or `console.warn` inside of them.

Since the `reportError` is also called within this context, we also get
them for errors thrown within event listeners. You'll also be able to
observe this in in the `error` event. Similar to how `onUncaughtError`
is in the scope of the instance that errored - even though
`onUncaughtError` doesn't kick in for event listeners.

Chrome (from console.createTask):

<img width="306" alt="Screenshot 2024-06-12 at 2 08 19 PM"
src="https://github.com/facebook/react/assets/63648/34cd9d57-0df4-44df-a470-e89a5dd1b07d">

<img width="302" alt="Screenshot 2024-06-12 at 2 03 32 PM"
src="https://github.com/facebook/react/assets/63648/678117b1-e03a-47d4-9989-8350212c8135">

Firefox (from React DevTools):

<img width="493" alt="Screenshot 2024-06-12 at 2 05 01 PM"
src="https://github.com/facebook/react/assets/63648/94ca224d-354a-4ec8-a886-5740bcb418e5">

(This is the parent stack since React DevTools doesn't just yet print
owner stack.)

(Firefox doesn't print the component stack for uncaught since we don't
add component stacks for "error" events from React DevTools - just
console.error. Perhaps an oversight.)

If we didn't have the synthetic event system this would kind of just
work natively in Chrome because we have this task active when we attach
the event listeners to the DOM node and async stacks just follow along
that way. In fact, if you attach a manual listener in useEffect you get
this same effect. It's just because we use event delegation that this
doesn't work.

However, if we did get rid of the synthetic event system we'd likely
still want to add a wrapper on the DOM node to set our internal current
owner so that the non-native part of the system still can observe the
active instance. That wouldn't work with manually attached listeners
though.
2024-06-12 16:15:22 -04:00
Lenz Weber-Tronicandeps1lon 50e89ec9f2 Avoid acccessing React internals from use-sync-external-store/shim (#29868)
Co-authored-by: eps1lon <sebastian.silbermann@vercel.com>
2024-06-12 20:13:17 +02:00
Jan Kassens 93826c8483 remove unstable_renderSubtreeIntoContainer (#29771)
remove unstable_renderSubtreeIntoContainer

This is finally no longer used and can be deleted.
2024-06-12 11:14:51 -04:00
Jan Kassens 62af6b2280 delete ReactServerStreamConfig.dom-fb-experimental.js (#29836)
delete ReactServerStreamConfig.dom-fb-experimental.js

This config is no longer used since
1cd77a4ff7
2024-06-12 11:12:22 -04:00
Sebastian Markbåge 55c9d45f3b [Flight] Let environmentName vary over time by making it a function of string (#29867)
This lets the environment name vary within a request by the context a
component, log or error being executed in.

A potentially different API would be something like
`setEnvironmentName()` but we'd have to extend the `ReadableStream` or
something to do that like we do for `.allReady`. As a function though it
has some expansion possibilities, e.g. we could potentially also pass
some information to it for context about what is being asked for.

If it changes before completing a task, we also emit the change so that
we have the debug info for what the environment was before entering a
component and what it was after completing it.
2024-06-12 10:55:42 -04:00
Sebastian Markbågeandeps1lon fb57fc5a8a [Flight] Let Errored/Blocked Direct References Turn Nearest Element Lazy (#29823)
Stacked on #29807.

This lets the nearest Suspense/Error Boundary handle it even if that
boundary is defined by the model itself.

It also ensures that when we have an error during serialization of
properties, those can be associated with the nearest JSX element and
since we have a stack/owner for that element we can use it to point to
the source code of that line. We can't track the source of any nested
arbitrary objects deeper inside since objects don’t track their stacks
but close enough. Ideally we have the property path but we don’t have
that right now. We have a partial in the message itself.

<img width="813" alt="Screenshot 2024-06-09 at 10 08 27 PM"
src="https://github.com/facebook/react/assets/63648/917fbe0c-053c-4204-93db-d68a66e3e874">

Note: The component name (Counter) is lost in the first message because
we don't print it in the Task. We use `"use client"` instead because we
expect the next stack frame to have the name. We also don't include it
in the actual error message because the Server doesn't know the
component name yet. Ideally Client References should be able to have a
name. If the nearest is a Host Component then we do use the name though.
However, it's not actually inside that Component that the error happens
it's in App and that points to the right line number.

An interesting case is that if something that's actually going to be
consumed by the props to a Suspense/Error Boundary or the Client
Component that wraps them fails, then it can't be handled by the
boundary. However, a counter intuitive case might be when that's on the
`children` props. E.g.
`<ErrorBoundary>{clientReferenceOrInvalidSerialization}</ErrorBoundary>`.
This value can be inspected by the boundary so it's not safe to pass it
so if it's errored it is not caught.

## Implementation

The first insight is that this is best solved on the Client rather than
in the Server because that way it also covers Client References that end
up erroring.

The key insight is that while we don't have a true stack when using
`JSON.parse` and therefore no begin/complete we can still infer these
phases for Elements because the first child of an Element is always
`'$'` which is also a leaf. In depth first that's our begin phase. When
the Element itself completes, we have the complete phase. Anything in
between is within the Element.

Using this idea I was able to refactor the blocking tracking mechanism
to stash the blocked information on `initializingHandler` and then on
the way up do we let whatever is nearest handle it - whether that's an
Element or the root Chunk. It's kind of like an Algebraic Effect.

cc @unstubbable This is something you might want to deep dive into to
find more edge cases. I'm sure I've missed something.

---------

Co-authored-by: eps1lon <sebastian.silbermann@vercel.com>
2024-06-11 19:12:39 -04:00
Sebastian Markbåge 383b2a1845 Use the Nearest Parent of an Errored Promise as its Owner (#29814)
Stacked on #29807.

Conceptually the error's owner/task should ideally be captured when the
Error constructor is called but neither `console.createTask` does this,
nor do we override `Error` to capture our `owner`. So instead, we use
the nearest parent as the owner/task of the error. This is usually the
same thing when it's thrown from the same async component but not if you
await a promise started from a different component/task.

Before this stack the "owner" and "task" of a Lazy that errors was the
nearest Fiber but if the thing erroring is a Server Component, we need
to get that as the owner from the inner most part of debugInfo.

To get the Task for that Server Component, we need to expose it on the
ReactComponentInfo object. Unfortunately that makes the object not
serializable so we need to special case this to exclude it from
serialization. It gets restored again on the client.

Before (Shell):
<img width="813" alt="Screenshot 2024-06-06 at 5 16 20 PM"
src="https://github.com/facebook/react/assets/63648/7da2d4c9-539b-494e-ba63-1abdc58ff13c">

After (App):
<img width="811" alt="Screenshot 2024-06-08 at 12 29 23 AM"
src="https://github.com/facebook/react/assets/63648/dbf40bd7-c24d-4200-81a6-5018bef55f6d">
2024-06-11 18:10:24 -04:00
Sebastian Markbåge 2c959f1d77 [Fiber] Track debugInfo on module state instead of stack (#29807)
Stacked on #29804.

Transferring of debugInfo was added in #28286. It represents the parent
stack between the current Fiber and into the next Fiber we're about to
create. I.e. Server Components in between. ~I don't love passing
DEV-only fields as arguments anyway since I don't trust closure to
remove unused arguments that way.~ EDIT: Actually it seems like closure
handled that just fine before which is why this is no change in prod.

Instead, I track it on the module scope. Notably with DON'T use
try/finally because if something throws we want to observe what it was
at the time we threw. Like the pattern we use many other places.

Now we can use this when we create the Throw Fiber to associate the
Server Components that were part of the parent stack before this error
threw. There by giving us the correct parent stacks at the location that
threw.
2024-06-11 17:04:13 -04:00
Sebastian Markbåge 270229f0c3 [Fiber] Create virtual Fiber when an error occurs during reconcilation (#29804)
This lets us rethrow it in the conceptual place of the child.

There's currently a problem when we suspend or throw in the child fiber
reconciliation phase. This work is done by the parent component, so if
it suspends or errors it is as if that component errored or suspended.
However, conceptually it's like a child suspended or errored.

In theory any thing can throw but it is really mainly due to either
`React.lazy` (both in the element.type position and node position),
`Thenable`s or the `Thenable`s that make up `AsyncIterable`s.

Mainly this happens because a Server Component that errors turns into a
`React.lazy`. In practice this means that if you have a Server Component
as the direct child of an Error Boundary. Errors inside of it won't be
caught.

We used to have the same problem with Thenables and Suspense but because
it's now always nested inside an inner Offscreen boundary that shields
it by being one level nested. However, when we have raw Offscreen
(Activity) boundaries they should also be able to catch the suspense if
it's in a hidden state so the problem returns. This fixes it for thrown
promises but it doesn't fix it for SuspenseException. I'm not sure this
is even the right strategy for Suspense though. It kind of relies on the
node never actually mounting/committing.

It's conceptually a little tricky because the current component can
inspect the children and make decisions based on them. Such as
SuspenseList.

The other thing that this PR tries to address is that it sets the
foundation for dealing with error reporting for Server Components that
errored. If something client side errors it'll be a stack like Server
(DebugInfo) -> Fiber -> Fiber -> Server -> (DebugInfo) -> Fiber.
However, all error reporting relies on it eventually terminating into a
Fiber that is responsible for the error. To avoid having to fork too
much it would be nice if I could create a Fiber to associate with the
error so that even a Server component error in this case ultimately
terminates in a Fiber.
2024-06-11 15:57:41 -04:00
Sebastian Markbåge 01a40570c3 [Flight/Fizz] Use Constructors for Large Request/Response Objects in Flight/Fizz (#29858)
We know from Fiber that inline objects with more than 16 properties in
V8 turn into dictionaries instead of optimized objects. The trick is to
use a constructor instead of an inline object literal. I don't actually
know if that's still the case or not. I haven't benchmarked/tested the
output. Better safe than sorry.

It's unfortunate that this can have a negative effect for Hermes and JSC
but it's not as bad as it is for V8 because they don't deopt into
dictionaries. The time to construct these objects isn't a concern - the
time to access them frequently is.

We have to beware the Task objects in Fizz. Those are currently on 16
fields exactly so we shouldn't add anymore ideally.

We should ideally have a lint rule against object literals with more
than 16 fields on them. It might not help since sometimes the fields are
conditional.
2024-06-11 15:55:29 -04:00
Vitali Zaidman fb3b9ead47 fix[react-devtools] component badge in light mode is now not invisible (#29852)
In light mode, component badges in profiler were invisible due to using
the alpha channel to produce the grayish color. Instead I'm using the
equivalent RGB without that alpha.

**before**
In light mode, component badges in profiler were invisible (forwardRef
badge in this case):
![Screenshot 2024-06-11 at 13 15
16](https://github.com/facebook/react/assets/5188459/385b80a5-d385-4eac-bac6-7fec6938d78f)

**after**
Profiler tooltip fix. also notice there's no regression on the right
menu:
![Screenshot 2024-06-11 at 13 04
41](https://github.com/facebook/react/assets/5188459/64aa27f7-35b8-4e3b-91d4-c12d5a97330e)

also works in dark mode:
![Screenshot 2024-06-11 at 13 12
17](https://github.com/facebook/react/assets/5188459/99aa55fd-23ee-4881-9676-63eca86bf761)

Still visible in components in light mode, whether selected or not:
![Screenshot 2024-06-11 at 13 04
49](https://github.com/facebook/react/assets/5188459/59c0bf63-d9b0-4d46-a145-f615249d1da0)

components dark mode:
![Screenshot 2024-06-11 at 13 10
25](https://github.com/facebook/react/assets/5188459/16e61acc-c431-4bfa-8a65-ca6701f4379b)
2024-06-11 14:32:39 +01:00
Sebastian Markbåge 2774208039 Remove Warning: prefix and toString on console Arguments (#29839)
Basically make `console.error` and `console.warn` behave like normal -
when a component stack isn't appended. I need this because I need to be
able to print rich logs with the component stack option and to be able
to disable instrumentation completely in `console.createTask`
environments that don't need it.

Currently we can't print logs with richer objects because they're
toString:ed first. In practice, pretty much all arguments we log are
already toString:ed so it's not necessary anyway. Some might be like a
number. So it would only be a problem if some environment can't handle
proper consoles but then it's up to that environment to toString it
before logging.

The `Warning: ` prefix is historic and is both noisy and confusing. It's
mostly unnecessary since the UI surrounding `console.error` and
`console.warn` tend to have visual treatment around it anyway. However,
it's actively misleading when `console.error` gets prefixed with a
Warning that we consider an error level. There's an argument to be made
that some of our `console.error` don't make the bar for an error but
then the argument is to downgrade each of those to `console.warn` - not
to brand all our actual error logging with `Warning: `.

Apparently something needs to change in React Native before landing this
because it depends on the prefix somehow which probably doesn't make
sense already.
2024-06-10 18:41:56 -04:00
Ricky d172bdaf95 Add jest lint rules (#29760)
## Overview

Updates `eslint-plugin-jest` and enables the recommended rules with some
turned off that are unhelpful.

The main motivations is:
a) we have a few duplicated tests, which this found an I deleted 
b) making sure we don't accidentally commit skipped tests
2024-06-10 14:31:37 -04:00
RickyandTimothy Yung 6b35ff766a Move @generated from build to sync (#29799)
## Overview

Reverts https://github.com/facebook/react/pull/26616 and implements the
suggested way instead.

This change in #26616 broken the internal sync command, which now
results in duplicated `@generated` headers. It also makes it harder to
detect changes during the diff train sync. Instead, we will check for
changes, and if there are changes sign the files and commit them to the
sync branch.

## Strategy

The new sync strategy accounts for the generated headers during the
sync:
- **Revert Version**: Revert the version strings
- **Revert @generated**: Re-sign the files (will be the same hash as
before if unchanged)
- **Check**: Check if there are changes **if not, skip**
- **Re-apply Version**: Now add back the new version string
- **Re-sign @generated**: And re-generate the headers

Then commit to branch. This ensures that if there are no changes, we'll
skip.

---------

Co-authored-by: Timothy Yung <yungsters@gmail.com>
2024-06-10 10:16:40 -04:00
Sebastian Markbåge c2ae9e28bc Minify DEV bundles with closure (#29809)
The goal is to improve speed of the development by inlining and DCE
unused branches.

We have the ability to preserve some variable names and pretty print in
the production version so might as well do the same with DEV.
2024-06-08 11:15:57 -04:00
Josh Story 20b6f4c0e8 [Float][Fiber] Assume stylesheets in document are already loaded (#29811)
When we made stylesheets suspend even during high priority updates we
exposed a bug in the loading tracking of stylesheets that are loaded as
part of the preamble. This allowed these stylesheets to put suspense
boundaries into fallback mode more often than expected because cases
where a stylesheet was server rendered could now cause a fallback to
trigger which was never intended to happen.

This fix updates resource construction to evaluate whether the instance
exists in the DOM prior to construction and if so marks the resource as
loaded and inserted.

One ambiguity that needed to be solved still is how to tell whether a
stylesheet rendered as part of a late Suspense boundary reveal is
already loaded. I updated the instruction to clear out the loading
promise after successfully loading. This is useful because later if we
encounter this same resource again we can avoid the microtask if it is
already loaded. It also means that we can concretely understand that if
a stylesheet is in the DOM without this marker then it must have loaded
(or errored) already.
2024-06-07 16:53:24 -07:00
Sebastian Markbåge a0a435d68f [Fiber] Track the Real Fiber for Key Warnings (#29791)
This refactors key warning to happen inline after we've matched a Fiber.
I didn't want to do that originally because it was riskier. But it turns
out to be straightforward enough.

This lets us use that Fiber as the source of the warning which matters
to DevTools because then DevTools can associate it with the right
component after it mounts.

We can also associate the duplicate key warning with this Fiber. That
way we'll get the callsite with the duplicate key on the stack and can
associate this warning with the child that had the duplicate.

I kept the forked DevTools tests because the warning now is counted on
the Child instead of the Parent (18 behavior).

However, this won't be released in 19.0.0 so I only test this in
whatever the next version is.

Doesn't seem worth it to have a test for just the 19.0.0 behavior.
2024-06-07 13:38:44 -04:00
Sebastian Markbåge cc1ec60d0d [Flight] Run recreated Errors within a fake native stack (#29717)
Stacked on #29740.

Before:

<img width="719" alt="Screenshot 2024-06-02 at 11 51 20 AM"
src="https://github.com/facebook/react/assets/63648/8f79fa82-2474-4583-894e-a2329e9a6304">

After (updated with my patches to Chrome):

<img width="813" alt="Screenshot 2024-06-06 at 5 16 20 PM"
src="https://github.com/facebook/react/assets/63648/bcc4f52f-e0ac-4708-ac2b-9629acdff705">

Sources panel after:

<img width="1188" alt="Screenshot 2024-06-06 at 5 14 21 PM"
src="https://github.com/facebook/react/assets/63648/2c673fac-d32d-42e4-8fac-bb63704e4b7f">

The fake eval file is now under "React" and the real file is now under
`file://`
2024-06-07 11:54:14 -04:00
Jan Kassens 142b2a8230 www: make disableLegacyMode dynamic flag (#29774)
This makes the flag dynamic for Meta and turns it on for the www test
renderer.
2024-06-07 07:36:10 -04:00
Josh Story c4b433f8cb [Flight] Allow aborting during render (#29764)
Stacked on #29491

Previously if you aborted during a render the currently rendering task
would itself be aborted which will cause the entire model to be replaced
by the aborted error rather than just the slot currently being rendered.

This change updates the abort logic to mark currently rendering tasks as
aborted but allowing the current render to emit a partially serialized
model with an error reference in place of the current model.

The intent is to support aborting from rendering synchronously, in
microtasks (after an await or in a .then) and in lazy initializers. We
don't specifically support aborting from things like proxies that might
be triggered during serialization of props
2024-06-06 14:41:27 -07:00
Ruslan Lesiutin fe5ce4e3e9 fix[react-devtools/store-test]: fork the test to represent current be… (#29777)
## Summary

The test started to fail after
https://github.com/facebook/react/pull/29088.

Fork the test and the expected store state for:
- React 18.x, to represent the previous behavior
- React >= 19, to represent the current RDT behavior, where error can't
be connected to the fiber, because it was not yet mounted and shared
with DevTools.

Ideally, DevTools should start keeping track of such fibers, but also
distinguish them from some that haven't mounted due to Suspense or error
boundaries.
2024-06-06 20:01:15 +01:00
Josh Story 1e1e5cd252 [Flight] Schedule work in a microtask (#29491)
Stacked on #29551

Flight pings much more often than Fizz because async function components
will always take at least a microtask to resolve . Rather than
scheduling this work as a new macrotask Flight now schedules pings in a
microtask. This allows more microtasks to ping before actually doing a
work flush but doesn't force the vm to spin up a new task which is quite
common give n the nature of Server Components
2024-06-06 10:19:57 -07:00
Josh Story b526a0a419 [Flight][Fizz] schedule work async (#29551)
While most builds of Flight and Fizz schedule work in new tasks some do
execute work synchronously. While this is necessary for legacy APIs like
renderToString for modern APIs there really isn't a great reason to do
this synchronously.

We could schedule works as microtasks but we actually want to yield so
the runtime can run events and other things that will unblock additional
work before starting the next work loop.

This change updates all non-legacy uses to be async using the best
availalble macrotask scheduler.

Browser now uses postMessage
Bun uses setTimeout because while it also supports setImmediate the
scheduling is not as eager as the same API in node
the FB build also uses setTimeout

This change required a number of changes to tests which were utilizing
the sync nature of work in the Browser builds to avoid having to manage
timers and tasks. I added a patch to install MessageChannel which is
required by the browser builds and made this patched version integrate
with the Scheduler mock. This way we can effectively use `act` to flush
flight and fizz work similar to how we do this on the client.
2024-06-06 10:07:24 -07:00