Commit Graph

194 Commits

Author SHA1 Message Date
Andrew Clark
0ba4d7b0d8 DevTools: Inline references to fiber flags (#26542)
We shouldn't be referencing internal fields like fiber's `flag` directly
of DevTools. It's an implementation detail. However, over the years a
few of these have snuck in. Because of how DevTools is currently
shipped, where it's expected to be backwards compatible with older
versions of React, this prevents us from refactoring those fields inside
the reconciler.

The plan we have to address this is to fix how DevTools is shipped:
DevTools will be released in lockstep with each version of React.

Until then, though, I need a temporary solution because it's blocking a
feature I'm working on. So in meantime, I'm going to have to fork the
DevTool's code based on the React version, like we already do with the
fiber TypeOfWork enum.

As a first step, I've inlined all the references to fiber flags into the
specific call sites where they are used. Eventually we'll import these
functions from the reconciler so they stay in sync, rather than
maintaining duplicate copies of the logic.
2023-04-04 11:05:33 -04:00
Jan Kassens
afea1d0c53 [flow] make Flow suppressions explicit on the error (#26487)
Added an explicit type to all $FlowFixMe suppressions to reduce
over-suppressions of new errors that might be caused on the same lines.

Also removes suppressions that aren't used (e.g. in a `@noflow` file as
they're purely misleading)

Test Plan:
yarn flow-ci
2023-03-27 13:43:04 +02:00
Mengdi Chen
a22bd995c5 [DevTools] prevent StyleX plugin from throwing when inspecting CSS (#26364)
## Summary

An error might happen when we try to read the CSS rules, but the
stylesheet does not allow so (often happens on production).

Before:
<img width="713" alt="image"
src="https://user-images.githubusercontent.com/1001890/224376546-024f7a32-d314-4dd1-9333-7e47d96a2b7c.png">

After:

<img width="504" alt="image"
src="https://user-images.githubusercontent.com/1001890/224376426-964a33c4-0677-4a51-91c2-74074e4dde63.png">


## How did you test this change?

Built a fb version and tested locally (see above screenshot)

---------

Co-authored-by: Hendrik Liebau <mail@hendrik-liebau.de>
2023-03-10 15:43:05 -05:00
Mengdi Chen
fcf2187919 [DevTools] Remove renderer.js from extension build (#26234)
## Summary

When looking into the compiled code of `installHook.js` of the extension
build, I noticed that it actually includes the large `attach` function
(from renderer.js). I don't think it was expected.
This is because `hook.js` imports from `backend/console.js` which
imports from `backend/renderer.js` for `getInternalReactConstants`
A straightforward way is to extract function
`getInternalReactConstants`. However, I think it's more simplified to
just merge these two files and save the 361K renderer.js from the
extension build since we have always been loading this code anyways.
I changed the execution check from `__REACT_DEVTOOLS_ATTACH__ ` to the
session storage.

## How did you test this change?

Everything works normal in my local build.
2023-03-03 14:01:58 -05:00
Ming Ye
55542bc73d Update jest printBasicPrototype config (#26142) 2023-02-10 09:58:57 +01:00
Josh Story
6396b66411 Model Float on Hoistables semantics (#26106)
## Hoistables

In the original implementation of Float, all hoisted elements were
treated like Resources. They had deduplication semantics and hydrated
based on a key. This made certain kinds of hoists very challenging such
as sequences of meta tags for `og:image:...` metadata. The reason is
each tag along is not dedupable based on only it's intrinsic properties.
two identical tags may need to be included and hoisted together with
preceding meta tags that describe a semantic object with a linear set of
html nodes.

It was clear that the concept of Browser Resources (stylesheets /
scripts / preloads) did not extend universally to all hositable tags
(title, meta, other links, etc...)

Additionally while Resources benefit from deduping they suffer an
inability to update because while we may have multiple rendered elements
that refer to a single Resource it isn't unambiguous which element owns
the props on the underlying resource. We could try merging props, but
that is still really hard to reason about for authors. Instead we
restrict Resource semantics to freezing the props at the time the
Resource is first constructed and warn if you attempt to render the same
Resource with different props via another rendered element or by
updating an existing element for that Resource.

This lack of updating restriction is however way more extreme than
necessary for instances that get hoisted but otherwise do not dedupe;
where there is a well defined DOM instance for each rendered element. We
should be able to update props on these instances.

Hoistable is a generalization of what Float tries to model for hoisting.
Instead of assuming every hoistable element is a Resource we now have
two distinct categories, hoistable elements and hoistable resources. As
one might guess the former has semantics that match regular Host
Components except the placement of the node is usually in the <head>.
The latter continues to behave how the original implementation of
HostResource behaved with the first iteration of Float

### Hoistable Element
On the server hoistable elements render just like regular tags except
the output is stored in special queues that can be emitted in the stream
earlier than they otherwise would be if rendered in place. This also
allow for instance the ability to render a hoistable before even
rendering the <html> tag because the queues for hoistable elements won't
flush until after we have flushed the preamble (`<DOCTYPE
html><html><head>`).

On the client, hoistable elements largely operate like HostComponents.
The most notable difference is in the hydration strategy. If we are
hydrating and encounter a hoistable element we will look for all tags in
the document that could potentially be a match and we check whether the
attributes match the props for this particular instance. We also do this
in the commit phase rather than the render phase. The reason hydration
can be done for HostComponents in render is the instance will be removed
from the document if hydration fails so mutating it in render is safe.
For hoistables the nodes are not in a hydration boundary (Root or
SuspenseBoundary at time of writing) and thus if hydration fails and we
may have an instance marked as bound to some Fiber when that Fiber never
commits. Moving the hydration matching to commit ensures we will always
succeed in pairing the hoisted DOM instance with a Fiber that has
committed.

### Hoistable Resource
On the server and client the semantics of Resources are largely the same
they just don't apply to title, meta, and most link tags anymore.
Resources hoist and dedupe via an `href` key and are ref counted. In a
future update we will add a garbage collector so we can clean up
Resources that no longer have any references

## `<style>` support
In earlier implementations there was no support for <style> tags. This
PR adds support for treating `<style href="..."
precedence="...">...</style>` as a Resource analagous to `<link
rel="stylesheet" href="..." precedence="..." />`

It may seem odd at first to require an href to get Resource semantics
for a style tag. The rationale is that these are for inlining of actual
external stylesheets as an optimization and for URI like scoping of
inline styles for css-in-js libraries. The href indicates that the key
space for `<style>` and `<link rel="stylesheet" />` Resources is shared.
and the precedence is there to allow for interleaving of both kinds of
Style resources. This is an advanced feature that we do not expect most
app developers to use directly but will be quite handy for various
styling libraries and for folks who want to inline as much as possible
once Fizz supports this feature.

## refactor notes
* HostResource Fiber type is renamed HostHoistable to reflect the
generalization of the concept
* The Resource object representation is modified to reduce hidden class
checks and to use less memory overall
* The thing that distinguishes a resource from an element is whether the
Fiber has a memoizedState. If it does, it will use resource semantics,
otherwise element semantics
* The time complexity of matching hositable elements for hydration
should be improved
2023-02-09 22:59:29 -08:00
Jan Kassens
6ddcbd4f96 [flow] enable LTI inference mode (#26104)
This is the next generation inference mode for Flow.
2023-02-09 17:07:39 -05:00
Mark Erikson
78d2e9e2a8 Replace DevTools semver usages with compare-versions for smaller bundle size (#26122)
<!--
  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 debug-test --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

This PR:

- Replaces the existing usages of methods from the `semver` library in
the React DevTools source with an inlined version based on
https://www.npmjs.com/package/semver-compare.

This appears to drop the unminified bundle sizes of 3 separate
`react-devtools-extensions` build artifacts by about 50K:


![image](https://user-images.githubusercontent.com/1128784/217326947-4c26d1be-d834-4f77-9e6e-be2d5ed0954d.png)


## How did you test this change?

I was originally working on [a fork of React
DevTools](https://github.com/replayio/react/pull/2) for use with
https://replay.io , specifically our integration of the React DevTools
UI to show the React component tree while users are debugging a recorded
application.

As part of the dev work on that fork, I wanted to shrink the bundle size
of the extension's generated JS build artifacts. I noted that the
official NPM `semver` library was taking up a noticeable chunk of space
in the bundles, and saw that it's only being used in a handful of places
to do some very simple version string comparisons.

I was able to replace the `semver` imports and usages with a simple
alternate comparison function, and confirmed via hands-on checks and
console logging that the checks behaved the same way.

Given that, I wanted to upstream this particular change to help shrink
the real extension's bundle sizes.

I know that it's an extension, so bundle size isn't _as_ critical a
concern as it would be for a pure library. But, smaller download sizes
do benefit all users, and that also includes sites like CodeSandbox and
Replay that are using the React DevTools as a library as well.

I'm happy to tweak this PR if necessary.  Thanks!
2023-02-08 20:00:22 -05:00
Xin Chen
758fc7fde1 Support highlights for React Native apps in dev tools (#26060)
<!--
  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 debug-test --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?
-->

This pull request emit the trace update events `drawTraceUpdates` with
the trace frame information when the trace update drawer runs outside of
web environment. This allows React Devtool running in mobile or other
platforms have a chance to render such highlights and provide similar
feature on web to provide re-render highlights. This is a feature needed
for identifying unnecessary re-renders.

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

I tested this change with Flipper desktop app running against mobile
app, and verified that the event with correct array of frames are
passing through properly.
2023-02-07 14:47:05 -08:00
Jan Kassens
6b30832666 Upgrade prettier (#26081)
The old version of prettier we were using didn't support the Flow syntax
to access properties in a type using `SomeType['prop']`. This updates
`prettier` and `rollup-plugin-prettier` to the latest versions.

I added the prettier config `arrowParens: "avoid"` to reduce the diff
size as the default has changed in Prettier 2.0. The largest amount of
changes comes from function expressions now having a space. This doesn't
have an option to preserve the old behavior, so we have to update this.
2023-01-31 08:25:05 -05:00
Jan Kassens
c49131669b Remove unused Flow suppressions (#25977)
These suppressions are no longer required.

Generated using:
```sh
flow/tool update-suppressions .
```
followed by adding back 1 or 2 suppressions that were only triggered in
some configurations.
2023-01-10 10:32:42 -05:00
Jan Kassens
34464fb16c Upgrade to Flow 0.196.3 (#25974)
After the previous changes these upgrade are easy.

- removes config options that were removed
- object index access now requires an indexer key in the type, this
cause a handful of errors that were fixed
- undefined keys error in all places, this needed a few extra
suppressions for repeated undefined identifiers.

Flow's
[CHANGELOG.md](https://github.com/facebook/flow/blob/main/Changelog.md).
2023-01-09 17:52:42 -05:00
Jan Kassens
e2424f33b3 [flow] enable exact_empty_objects (#25973)
This enables the "exact_empty_objects" setting for Flow which makes
empty objects exact instead of building up the type as properties are
added in code below. This is in preparation to Flow 191 which makes this
the default and removes the config.

More about the change in the Flow blog
[here](https://medium.com/flow-type/improved-handling-of-the-empty-object-in-flow-ead91887e40c).
2023-01-09 17:00:36 -05:00
Jan Kassens
0b4f443020 [flow] enable enforce_local_inference_annotations (#25921)
This setting is an incremental path to the next Flow version enforcing
type annotations on most functions (except some inline callbacks).

Used
```
node_modules/.bin/flow codemod annotate-functions-and-classes --write .
```
to add a majority of the types with some hand cleanup when for large
inferred objects that should just be `Fiber` or weird constructs
including `any`.

Suppressed the remaining issues.

Builds on #25918
2023-01-09 15:46:48 -05:00
Mengdi Chen
d69b2cf820 [bug fix] revert values in ReactFiberFlags to keep consistency for devtools (#25832)
## Summary

We see recent bug reports like #25755 and #25769 for devtools. Whenever
a component uses hook `useEffect`, it triggers an error.
This was introduced in #25663 when we try to keep the `ReactFiberFlags`
numbers consistent with reconciler, in order to fix an issue with server
components.
However, the values of `ReactFiberFlags` in reconciler were actually
changed a while ago in
b4204ede66
We made this mistake because, although it's not mentioned in the
comment, `DidCapture` and `Hydrating` are actually used by DevTools

This caused
- the latest (not stable) react version is broken on devtools before
4.27.0 (but only in uncommon cases such server components)
- all earlier react versions are broken on latest devtools (4.27.0)

To keep most versions work, we need to revert the commit that changed
the `ReactFiberFlags` values

## How did you test this change?

1. add a `useEffect` in a component in the TodoList of the shell,
trigger the error in devtools
2. after change, the error is gone
2022-12-06 17:25:30 -05:00
Mengdi Chen
c54e3541b2 [DevTools] bug fix for Hydrating fibers (#25663)
## Summary

This PR is to fix a bug: an "element cannot be found" error when
hydrating Server Components

### The problem
<img width="1061" alt="image"
src="https://user-images.githubusercontent.com/1001890/201206046-ac32a5e3-b08a-4dc2-99f4-221dad504b28.png">

To reproduce:
1. setting up a vercel next.js 13 playground locally
https://github.com/vercel/app-playground
2. visit http://localhost:3000/loading
3. click "electronics" button to navigate to
http://localhost:3000/loading/electronics to trigger hydrating
4. inspect one of the skeleton card UI from React DevTools extension

### The root cause & fix
This bug was introduced in #22527. When syncing reconciler changes, the
value of `Hydrating` was copied from another variable `Visibility` (one
more zero in the binary number).
To avoid this kind of issue in the future, a new file `ReactFiberFlags`
is created following the same format of the one in reconciler, so that
it's easier to sync the number without making mistakes.
The reconciler fiber flag file is also updated to reflect which of the
flags are used in devtools

## How did you test this change?

I build it locally and the bug no longer exist on
http://localhost:3000/loading
2022-11-11 15:18:06 -05:00
Mengdi Chen
18dff7990a [DevTools] add support for HostSingleton & HostResource (#25616)
## Summary

This is to support two new reconciler work tags `HostSingleton` and
`HostResource` introduced in PRs #25243 #25426. The behavior is
described below.
I also renamed an option in components settings from an internal concept
"host" to more understood "dom nodes"

## How did you test this change?

Tested on the latest Vercel playground app
https://github.com/vercel/app-playground/

Before the change, devtools cannot show correct display name for these
new elements. Also, some unnecessary internal details are exposed to
users.
<img width="1395" alt="image"
src="https://user-images.githubusercontent.com/1001890/199578181-c4e4ea74-baa1-4507-83d0-91a62ad7de5f.png">

After the change, the display names are correctly shown and the "state"
would always be hidden in the detail view.
<img width="1417" alt="image"
src="https://user-images.githubusercontent.com/1001890/199578442-adc1951d-7d5b-4b84-ad64-85bcf7a8ebcc.png">

These elements will also be hidden just like other native dom elements
(e.g. `<div>`)
<img width="836" alt="image"
src="https://user-images.githubusercontent.com/1001890/199578598-2dfacf64-ddc9-42b5-a246-dd0b09f629af.png">
2022-11-07 15:23:17 -05:00
Robert Balicki
fecc288b7d [react devtools] Device storage support (#25452)
# Summary
* This PR adds support for persisting certain settings to device
storage, allowing e.g. RN apps to properly patch the console when
restarted.
* The device storage APIs have signature `getConsolePatchSettings()` and
`setConsolePatchSettings(string)`, in iOS, are thin wrappers around the
`Library/Settings` turbomodule, and wrap a new TM that uses the `SharedPreferences` class in Android.
* Pass device storage getters/setters from RN to DevTools'
`connectToDevtools`. The setters are then used to populate values on
`window`. Later, the console is patched using these values.
* If we receive a notification from DevTools that the console patching
fields have been updated, we write values back to local storage.
* See https://github.com/facebook/react-native/pull/34903

# How did you test this change?
Manual testing, `yarn run test-build-devtools`, `yarn run prettier`,
`yarn run flow dom`

## Manual testing setup:

### React DevTools Frontend
* Get the DevTools frontend in flipper:
* `nvm install -g react-devtools-core`, then replace that package with a
symlink to the local package
  * enable "use globally installed devtools" in flipper
* yarn run start in react-devtools, etc. as well

### React DevTools Backend
* `yarn run build:backend` in react-devtools-core, then copy-paste that
file to the expo app's node_modules directory

### React Native
* A local version of React Native can be patched in by modifying an expo
app's package.json, as in `"react-native":
"rbalicki2/react-native#branch-name"`

# Versioning safety
* There are three versioned modules to worry about: react native, the
devtools frontend and the devtools backend.
* The react devtools backend checks for whether a `cachedSettingsStore`
is passed from react native. If not (e.g. if React Native is outdated),
then no behavior changes.
* The devtools backend reads the patched console values from the cached
settings store. However, if nothing has been stored, for example because
the frontend is outdated or has never synced its settings, then behavior
doesn't change.
* The devtools frontend sends no new messages. However, if it did send a
new message (e.g. "store this value at this key"), and the backend was
outdated, that message would be silently ignored.
2022-10-25 13:25:33 +11:00
Andrew Clark
9cdf8a99ed [Codemod] Update copyright header to Meta (#25315)
* Facebook -> Meta in copyright

rg --files | xargs sed -i 's#Copyright (c) Facebook, Inc. and its affiliates.#Copyright (c) Meta Platforms, Inc. and affiliates.#g'

* Manual tweaks
2022-10-18 11:19:24 -04:00
Jan Kassens
ea04a486a7 Flow: remove unused suppressions (#25424)
Removes $FlowFixMe's that are no longer needed.

Used flow/tool from the Flow repo:

```
 ~/Developer/flow/tool update-suppressions .
```
2022-10-04 16:18:12 -04:00
Jan Kassens
9813edef29 Flow upgrade to 0.188
ghstack-source-id: 5c359b97cc
Pull Request resolved: https://github.com/facebook/react/pull/25423
2022-10-04 15:49:48 -04:00
Jan Kassens
3b6826ed9e Flow: inference_mode=constrain_writes
This mode is going to be the new default in Flow going forward.
There was an unfortuante large number of suppressions in this update.

More on the changes can be found in this [Flow blog post](https://medium.com/flow-type/new-flow-language-rule-constrained-writes-4c70e375d190).

Added some of the required annotations using the provided codemod:

```sh
node_modules/.bin/flow codemod annotate-declarations --write .
```

ghstack-source-id: 0b168e1b23
Pull Request resolved: https://github.com/facebook/react/pull/25422
2022-10-04 15:49:48 -04:00
Jan Kassens
338e6a967c Flow upgrade to 0.155
This version banned use of this in object functions.

ghstack-source-id: f49fd5e1b7
Pull Request resolved: https://github.com/facebook/react/pull/25414
2022-10-04 11:49:15 -04:00
Jan Kassens
9f8a98a390 Flow upgrade to 0.153
- method unbinding is no longer supported in Flow for soundness, this added a bunch of suppressions
- Flow now prevents objects to be supertypes of interfaces/classes

ghstack-source-id: d7749cbad8
Pull Request resolved: https://github.com/facebook/react/pull/25412
2022-10-04 11:30:06 -04:00
Jan Kassens
64fe791be8 Flow upgrade to 0.146
This upgrade made more expressions invalidate refinements. In some
places this lead to a large number of suppressions that I automatically
suppressed and should be followed up on when the code is touched.
I think most of them might require either manual annotations or moving
a value into a const to allow refinement.

ghstack-source-id: a45b40abf0
Pull Request resolved: https://github.com/facebook/react/pull/25410
2022-10-04 11:01:50 -04:00
Jan Kassens
fc16293f3f Flow: well_formed_exports for devtools (#25266) 2022-09-15 16:45:29 -04:00
Jan Kassens
e6a062bd2a Flow: add simple explicit export types to Devtools (#25251) 2022-09-13 12:03:20 -04:00
Robert Balicki
271bf90a94 [react devtools][easy] Centralize calls to patchConsoleUsingWindowValues (#25222)
* Instead of reading from window in two separate places, do this in a single function
* Add some type safety
2022-09-13 11:24:10 -04:00
Jan Kassens
ba7b6f4183 Flow: upgrade to 0.132 (#25244) 2022-09-12 14:36:02 -04:00
Jan Kassens
8003ab9cf5 Flow: remove explicit object syntax (#25223) 2022-09-09 16:03:48 -04:00
Robert Balicki
425f9fbba0 [react devtools] Don't check for NODE_ENV==='test' because it never is (#25186)
* remove useless condition
2022-09-09 11:31:32 -04:00
Jan Kassens
8a9e7b6cef Flow: implicit-inexact-object=error (#25210)
* implicit-inexact-object=error
* default everything ambiguous to exact object
* inexact where exact causes errors
2022-09-09 10:13:58 -04:00
Jan Kassens
a473d08fce Update to Flow from 0.97 to 0.122 (#25204)
* flow 0.122
* update ReactModel type
2022-09-08 11:46:07 -04:00
Luna Ruan
c80e54116e [DevTools][Bugfix] Don't hide fragment if it has a key (#25197)
resolves #25187

---

We shouldn't hide fragments that have a key because this is important information that the user might want in the future.
2022-09-07 10:21:30 -07:00
Tim Neutkens
a9dc73cfd4 Handle info, group, and groupCollapsed in Strict Mode logging (#25172)
* Handle info, group, and groupCollapsed in Strict Mode logging

While working on the new Next.js router which heavily relies on useReducer I noticed that `group` and `groupCollapsed` which both take labels were showing as-is in the console for the second render/dispatch in Strict Mode logs. While looking at the code I found that `info` was also not instrumented.

I've added additional handling for:
- `info`
- `group`
- `groupCollapsed`

* Remove console.log

* Fix tests
2022-09-06 10:03:27 -07:00
Tianyu Yao
181525338e [DevTools] Highlight RN elements on hover (#25106)
* [DevTools] Highlight RN elements on hover

* Remove unused TODO
2022-08-24 11:25:22 -07:00
Tianyu Yao
26ba5fb2e0 [DevTools] Add events necessary for click to inspect on RN (#25111)
* Add inspectingNative events for RN

* Enable inspection toggle UI for RN

* Add a stopInspectingNative method for agent
2022-08-19 16:18:14 -07:00
Sebastian Silbermann
b66936ece7 devtools: Remove ForwardRef/Memo from display name if displayName is set (#21952)
* feat(devtools): Remove ForwardRef/Memo from display name if `displayName` is set

* Avoid potentially wasting work by inlining `functionName`
2022-07-25 09:02:12 +02:00
Luna Ruan
c3b18571db [DevTools][Bugfix] Fix DevTools Perf Issue When Unmounting Large React Subtrees (#24863)
We've recently had multiple reports where, if React DevTools was installed, unmounting large React subtrees would take a huge performance hit (ex. from 50ms to 7 seconds). 

Digging in more, we realized for every fiber that unmounts, we called `untrackFibers`, which calls `clearTimeout` (and does some work manipulating a set, but this wasn't the bulk of the time). We ten call `recordUnmount`, which adds the timer back. Adding and removing the timer so many times was taking upwards of 50ms per timer add/remove call, which was resulting in exorbitant amounts of time spent in DevTools deleting subtrees.

It looks like we are calling `untrackFibers` so many times to avoid a race condition with Suspense children where we unmount them twice (first a "virtual" unmount when the suspense boundary is toggled from visible to invisible, and then an actual unmount when the new children are rendered) without modifying `fiberIDMap`. We can fix this race condition by using the `untrackFibersSet` as a lock and not calling `recordUnmount` if the fiber is in the set and hasn't been processed yet. This works because the only way fibers are added in the set is via `recordUnmount` anyway.

This PR also adds a test to make sure this change doesn't regress the previous behavior.

**Before**
![image](https://user-images.githubusercontent.com/2735514/177655428-774ee306-0568-49ce-987e-b5213b613265.png)

**After**
![image](https://user-images.githubusercontent.com/2735514/177655604-a217583f-787e-438e-b6f9-18953fe32444.png)
2022-07-07 10:43:25 -04:00
Luna Ruan
955cad9bcc [DevTools] Clean Up DevTools Code (#24782)
This PR cleans up the DevTools codebase by:
* Consolidating `normalizeCodeLocInfo` into one place
* Remove unused source argument in the DevTools component stacks code
2022-06-23 15:47:47 -07:00
Luna Ruan
9abe745aa7 [DevTools][Timeline Profiler] Component Stacks Backend (#24776)
This PR adds a component stack field to the `schedule-state-update` event. The algorithm is as follows:
* During profiling, whenever a state update happens collect the parents of the fiber that caused the state update and store it in a map
* After profiling finishes, post process the `schedule-state-update` event and using the parent fibers, generate the component stack by using`describeFiber`, a function that uses error throwing to get the location of the component by calling the component without props.

---

Co-authored-by: Blake Friedman <blake.friedman@gmail.com>
2022-06-23 11:19:23 -07:00
Mengdi Chen
3e92eb0fce [DevTools] find best renderer when inspecting (#24665)
* [DevTools] find best renderer when inspecting

* fix lint

* fix test

* fix lint

* move logic to agent

* fix lint

* style improvements per review comments

* fix lint & flow

* re-add try catch for safety
2022-06-08 16:01:06 -04:00
Luna Ruan
0ecb77d4c5 [DevTools] Fix formatWithStyles not styling the results if the first argument is an object + Added unit tests (#24554)
formatWithStyles currently doesn't style the array argument if the first argument is an object. This PR fixes this and also adds unit tests.
2022-05-13 15:34:33 -07:00
Mengdi "Monday" Chen
852f10b5cf fix a bug in console.log with non-string args (#24546) 2022-05-12 10:29:36 -04:00
Luna Ruan
d20c3af9d1 [DevTools][Bug] Fix Race Condition When Unmounting Fibers (#24510)
When we delete fibers, we will call onCommitFiberUnmount on every deleted fiber to also remove them from the element tree. However, there are some cases where fibers aren't deleted but we still want to remove them from the element tree (ex. offscreen). In the second case, we recursively remove these children during handleCommitFiberRoot.

When we remove an element, we will untrack its corresponding fiber ID. However, because of fast refresh, we don't do this immediately, opting to instead add the value to a set to process later. However, before the set has been processed, we unmount that fiber again, we will get duplicate unmounts.

To fix this, handleCommitFiberRoot explicitly flushes all the fibers in the set before starting the deletion process. We also need to do this in handleCommitFiberUnmount in case handleCommitFiberRoot gets called first.
2022-05-06 15:36:03 -04:00
Mengdi "Monday" Chen
e531a4a62d [React DevTools] Improve DevTools UI when Inspecting a user Component that Throws an Error (#24248)
* [ReactDevTools] custom view for errors occur in user's code

* [ReactDevTools] show message for unsupported feature

* fix bad import

* fix typo

* fix issues from rebasing

* prettier

* sync error names

* sync error name with upstream

* fix lint & better comment

* fix error message for test

* better error message per review

* add missing file

* remove dead enum & provide component name in error message

* better error message

* better user facing error message
2022-05-05 20:17:23 -04:00
Luna Ruan
3dc9a8af05 fix forward ref (#24494)
Resolves #24428

---

For fiber types that render user code, we check the PerformedWork flag rather than the props, ref, and state to see if the fiber rendered (rather than bailing out/etc.) so we know whether we need to do things like record profile durations. ForwardRef wasn't added to this list, which caused #24428.
2022-05-04 13:25:27 -07:00
Luna Ruan
c7e494b553 [React DevTools] Fix regex for formateWithStyles function (#24486)
The previous regex to detect string substitutions is not quite right, this PR fixes it by:

Check to make sure we are starting either at the beginning of the line or we match a character that's not % to make sure we capture all the % in a row.
Make sure there are an odd number of % (the first X pairs are escaped % characters. The odd % followed by a letter is the string substitution)
2022-05-03 15:52:56 -07:00
Billy Janitsch
726ba80298 Synchronize implementations of second render logging (#24381)
Minor followup to #24373. The fix for #24373 (comment) didn't get synchronized to the hook implementation.
2022-04-15 10:35:35 -05:00
Luna Ruan
d63cd97245 don't stringify objects for console log second render (#24373)
Fixes #24302 based on #24306.
---

The current implementation for strict mode double logging stringiness and dims the second log. However, because we stringify everything, including objects, this causes objects to be logged as `[object Object]` etc.

This PR creates a new function that formats console log arguments with a specified style. It does this by:
1. The first param is a string that contains %c: Bail out and return the args without modifying the styles. We don't want to affect styles that the developer deliberately set.
2. The first param is a string that doesn't contain %c but contains string formatting: `[`%c${args[0]}`, style, ...args.slice(1)]` Note: we assume that the string formatting that the developer uses is correct.
3. The first param is a string that doesn't contain string formatting OR is not a string: Create a formatting string where:
   -  boolean, string, symbol -> %s
   -  number -> %f OR %i depending on if it's an int or float
   -  default -> %o
---
Co-authored-by: Billy Janitsch <billy@kensho.com>
2022-04-14 11:30:04 -05:00