Commit Graph

447 Commits

Author SHA1 Message Date
Luna Ruan b77c12576d
[DevTools] Add React Version Pragma to Tests (#24576)
This PR adds the reactVersion pragma to tests.

Tests without the reactVersion pragma won't be run if the reactVersion pragma isn't specified.

Tested each React version manually with the pragma to make sure the tests pass
2022-05-18 12:37:17 -04:00
Luna Ruan 4c03bb6ed0
[DevTools] ignore tests without reactVersion pragma if REACT_VERSION specified (#24555)
In DevTools tests, if the REACT_VERSION specified, we know this is a regression test (testing older React Versions). Because a lot of tests test the DevTools front end and we don't want to run them in the regression test scenario, we decided to only run tests that have the // @reactVersion pragma defined.

Because if there are no tests specified, jest will fail, we also opt to use jest.skip to skip all the tests that we don't want to run for a specific React version istead.

This PR makes this change.
2022-05-14 00:54:50 -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 7d9e17a982
[DevTools] Add Pragma to Only Run Tests if Version Requirement Satisfied (#24533)
This PR:

Adds a transform-react-version-pragma that transforms // @reactVersion SEMVER_VERSION into _test_react_version(...) and _test_react_version_focus(...) that lets us only run a test if it satisfies the right react version.
Adds _test_react_version and _test_react_version_focus to the devtools setupEnv file
Add a devtools preprocessor file for devtools specific plugins
2022-05-11 12:01:05 -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
Brian Vaughn d4acbe85d5
Fixed possible undefined error in TreeContext reducer (#24501) 2022-05-05 08:46:57 -07: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
Brian Vaughn 6c36aee944
Fixed wrong method call for LRU cache (#24477) 2022-05-02 21:17:01 -04: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
Andrew Clark f993ffc514
Fix infinite update loop that happens when an unmemoized value is passed to useDeferredValue (#24247)
* Fix infinite loop if unmemoized val passed to uDV

The current implementation of useDeferredValue will spawn a new
render any time the input value is different from the previous one. So
if you pass an unmemoized value (like an inline object), it will never
stop spawning new renders.

The fix is to only defer during an urgent render. If we're already
inside a transition, retry, offscreen, or other non-urgen render, then
we can use the latest value.

* Temporarily disable "long nested update" warning

DevTools' timeline profiler warns if an update inside a layout effect
results in an expensive re-render. However, it misattributes renders
that are spawned from a sync render at lower priority. This affects the
new implementation of useDeferredValue but it would also apply to things
like Offscreen.

It's not obvious to me how to fix this given how DevTools models the
idea of a "nested update" so I'm disabling the warning for now to
unblock the bugfix for useDeferredValue.
2022-04-11 12:34:03 -04:00
Mengdi "Monday" Chen c89a15c716
[ReactDebugTools] wrap uncaught error from rendering user's component (#24216)
* [ReactDebugTools] wrap uncaught error from rendering user's component

* fix lint

* make error names more package specific

* update per review comments

* fix tests

* fix lint

* fix tests

* fix lint

* fix error name & nits

* try catch instead of mocking error

* fix test for older node.js version

* avoid false positive from try-catch in tests
2022-04-01 14:38:11 -04:00
Brian Vaughn 8b95ea2cba
Inline DevTools test snapshots and cleaned up tests (#24199) 2022-03-30 11:02:51 -04:00
Brian Vaughn eaa493e532
Profiler should only report stateful hooks that change between renders (#24189)
The Profiler has an advanced feature that shows why a component re-rendered. In the case of props and (class) state, it shows the names of props/state values that changed between renders. For hooks, DevTools tries to detect which ones may been related to the update by comparing prev/next internal hook structures.

My initial implementation tried to detect all changed hooks. In hindsight this is confusing, because only stateful hooks (e.g. useState, useReducer, and useSyncExternalStore) can schedule an update. (Other types of hooks can change between renders, but in a reactive way.) This PR changes the behavior to only report hooks that scheduled the update.
2022-03-29 11:11:31 -04:00
Brian Vaughn a6bdb882b7
Attach DevTools Tree keyboard events to the Tree container (not the document) (#24164)
We used to listen to at the document level for this event. That allowed us to listen to up/down arrow key events while another section
of DevTools (like the search input) was focused. This was a minor UX positive.

(We had to use ownerDocument rather than document for this, because the DevTools extension renders the Components and Profiler tabs into portals.)

This approach caused a problem though: it meant that a react-devtools-inline instance could steal (and prevent/block) keyboard events from other JavaScript on the page– which could even include other react-devtools-inline instances. This is a potential major UX negative.

Given the above trade offs, we now listen on the root of the Tree itself.
2022-03-25 12:41:13 -04:00
Brian Vaughn e62a8d7545
Store throws a specific Error type (UnsupportedBridgeOperationError) (#24147)
When this Error type is detected, DevTools shows a custom error overlay with upgrade/downgrade instructions.
2022-03-23 17:04:54 -04:00
Andrew Clark 2e0d86d221
Allow updating dehydrated root at lower priority without forcing client render (#24082)
* Pass children to hydration root constructor

I already made this change for the concurrent root API in #23309. This
does the same thing for the legacy API.

Doesn't change any behavior, but I will use this in the next steps.

* Add isRootDehydrated function

Currently this does nothing except read a boolean field, but I'm about
to change this logic.

Since this is accessed by React DOM, too, I put the function in a
separate module that can be deep imported. Previously, it was accessing
the FiberRoot directly. The reason it's a separate module is to break a
circular dependency between React DOM and the reconciler.

* Allow updates at lower pri without forcing client render

Currently, if a root is updated before the shell has finished hydrating
(for example, due to a top-level navigation), we immediately revert to
client rendering. This is rare because the root is expected is finish
quickly, but not exceedingly rare because the root may be suspended.

This adds support for updating the root without forcing a client render
as long as the update has lower priority than the initial hydration,
i.e. if the update is wrapped in startTransition.

To implement this, I had to do some refactoring. The main idea here is
to make it closer to how we implement hydration in Suspense boundaries:

- I moved isDehydrated from the shared FiberRoot object to the
HostRoot's state object.
- In the begin phase, I check if the root has received an by comparing
the new children to the initial children. If they are different, we
revert to client rendering, and set isDehydrated to false using a
derived state update (a la getDerivedStateFromProps).
- There are a few places where we used to set root.isDehydrated to false
as a way to force a client render. Instead, I set the ForceClientRender
flag on the root work-in-progress fiber.
- Whenever we fall back to client rendering, I log a recoverable error.

The overall code structure is almost identical to the corresponding
logic for Suspense components.

The reason this works is because if the update has lower priority than
the initial hydration, it won't be processed during the hydration
render, so the children will be the same.

We can go even further and allow updates at _higher_ priority (though
not sync) by implementing selective hydration at the root, like we do
for Suspense boundaries: interrupt the current render, attempt hydration
at slightly higher priority than the update, then continue rendering the
update. I haven't implemented this yet, but I've structured the code in
anticipation of adding this later.

* Wrap useMutableSource logic in feature flag
2022-03-20 16:18:51 -04:00
Luna Ruan 645ec5d6fc
fix inspecting an element in a nested renderer bug (#24116)
Fixes this issue, where inspecting components in nested renderers results in an error. The reason for this is because we have different fiberToIDMap instances for each renderer, and owners of a component could be in different renderers.

This fix moves the fiberToIDMap and idToArbitraryFiberMap out of the attach method so there's only one instance of each for all renderers.
2022-03-17 15:40:03 -04:00
Brian Vaughn 8fce116998
Update DevTools READMEs (#24105) 2022-03-16 11:37:10 -04:00
Brian Vaughn 63b86e1995
Disable unsupported Bridge protocol version dialog and add workaround for old protocol operations format (#24093)
Rationale: The only case where the unsupported dialog really matters is React Naive. That's the case where the frontend and backend versions are most likely to mismatch. In React Native, the backend is likely to send the bridge protocol version before sending operations– since the agent does this proactively during initialization.

I've tested the React Native starter app– after forcefully downgrading the backend version to 4.19.1 (see #23307 (comment)) and verified that this change "fixes" things. Not only does DevTools no longer throw an error that causes the UI to be hidden– it works (meaning that the Components tree can be inspected and interacted with).
2022-03-15 13:48:26 -04:00
Sebastian Silbermann 2bf7c02f0e
Don't hide console error|warn in inspectedElement-test (#24086) 2022-03-14 09:17:37 -04:00
Andrew Clark 061ac27bc9
Fix use of hydrateRoot in DevTools test (#24084)
I noticed while working on a different PR that this test was not
using hydrateRoot correctly. You're meant to pass the initial children
as the second argument.
2022-03-12 19:21:58 -05:00
Brian Vaughn 4a87fb5211
Better handle undefined Error stacks in DevTools error boundary (#24065) 2022-03-10 13:36:47 -05:00
Brian Vaughn 48a8574a68
Fixed edge case bug in Profiler (#24031) 2022-03-10 13:35:52 -05:00
salazarm d5f1b067c8
[ServerContext] Flight support for ServerContext (#23244)
* Flight side of server context

* 1 more test

* rm unused function

* flow+prettier

* flow again =)

* duplicate ReactServerContext across packages

* store default value when lazily initializing server context

* .

* better comment

* derp... missing import

* rm optional chaining

* missed feature flag

* React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ??

* add warning if non ServerContext passed into useServerContext

* pass context in as array of arrays

* make importServerContext nott pollute the global context state

* merge main

* remove useServerContext

* dont rely on object getters in ReactServerContext and disallow JSX

* add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry

* gate test case as experimental

* feedback

* remove unions

* Lint

* fix oopsies (tests/lint/mismatching arguments/signatures

* lint again

* replace-fork

* remove extraneous change

* rebase

* 1 more test

* rm unused function

* flow+prettier

* flow again =)

* duplicate ReactServerContext across packages

* store default value when lazily initializing server context

* .

* better comment

* derp... missing import

* rm optional chaining

* missed feature flag

* React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED ??

* add warning if non ServerContext passed into useServerContext

* pass context in as array of arrays

* make importServerContext nott pollute the global context state

* merge main

* remove useServerContext

* dont rely on object getters in ReactServerContext and disallow JSX

* add symbols to devtools + rename globalServerContextRegistry to just ContextRegistry

* gate test case as experimental

* feedback

* remove unions

* Lint

* fix oopsies (tests/lint/mismatching arguments/signatures

* lint again

* replace-fork

* remove extraneous change

* rebase

* reinline

* rebase

* add back changes lost due to rebase being hard

* emit chunk for provider

* remove case for React provider type

* update type for SomeChunk

* enable flag with experimental

* add missing types

* fix flow type

* missing type

* t: any

* revert extraneous type change

* better type

* better type

* feedback

* change import to type import

* test?

* test?

* remove react-dom

* remove react-native-renderer from react-server-native-relay/package.json

* gate change in FiberNewContext, getComponentNameFromType, use switch statement in FlightServer

* getComponentNameFromTpe: server context type gated and use displayName if available

* fallthrough

* lint....

* POP

* lint
2022-03-08 07:55:32 -05:00
Brian Vaughn 0e0b1a45fa
Show DevTools backend and frontend versions in UI (#23399)
This information can help with bug investigation for renderers (like React Native) that embed the DevTools backend into their source (separately from the DevTools frontend, which gets run by the user).

If the DevTools backend is too old to report a version, or if the version reported is the same as the frontend (as will be the case with the browser extension) then only a single version string will be shown, as before. If a different version is reported, then both will be shown separately.
2022-03-02 12:26:48 -05:00
Sebastian Markbåge 17806594cc
Move createRoot/hydrateRoot to react-dom/client (#23385)
* Move createRoot/hydrateRoot to /client

We want these APIs ideally to be imported separately from things you
might use in arbitrary components (like flushSync). Those other methods
are "isomorphic" to how the ReactDOM tree is rendered. Similar to hooks.

E.g. importing flushSync into a component that only uses it on the client
should ideally not also pull in the entry client implementation on the
server.

This also creates a nicer parity with /server where the roots are in a
separate entry point.

Unfortunately, I can't quite do this yet because we have some legacy APIs
that we plan on removing (like findDOMNode) and we also haven't implemented
flushSync using a flag like startTransition does yet.

Another problem is that we currently encourage these APIs to be aliased by
/profiling (or unstable_testing). In the future you don't have to alias
them because you can just change your roots to just import those APIs and
they'll still work with the isomorphic forms. Although we might also just
use export conditions for them.

For that all to work, I went with a different strategy for now where the
real API is in / but it comes with a warning if you use it. If you instead
import /client it disables the warning in a wrapper. That means that if you
alias / then import /client that will inturn import the alias and it'll
just work.

In a future breaking changes (likely when we switch to ESM) we can just
remove createRoot/hydrateRoot from / and move away from the aliasing
strategy.

* Update tests to import from react-dom/client

* Fix fixtures

* Update warnings

* Add test for the warning

* Update devtools

* Change order of react-dom, react-dom/client alias

I think the order matters here. The first one takes precedence.

* Require react-dom through client so it can be aliased

Co-authored-by: Andrew Clark <git@andrewclark.io>
2022-03-01 00:13:28 -05:00
Sebastian Markbåge 1ad8d81292
Remove object-assign polyfill (#23351)
* Remove object-assign polyfill

We really rely on a more modern environment where this is typically
polyfilled anyway and we don't officially support IE with more extensive
polyfilling anyway. So all environments should have the native version
by now.

* Use shared/assign instead of Object.assign in code

This is so that we have one cached local instance in the bundle.

Ideally we should have a compile do this for us but we already follow
this pattern with hasOwnProperty, isArray, Object.is etc.

* Transform Object.assign to now use shared/assign

We need this to use the shared instance when Object.spread is used.
2022-02-23 19:34:24 -05:00
Luna Ruan 08fce6208e
Gracefully handle empty "xstyle" prop values (Part 2) (#23279)
#23190 misses if entry is undefined or null. This fixes this issue.
2022-02-11 14:36:36 -05:00
Luna Ruan a6987bee73
add <TracingMarker> component boilerplate (#23275)
- Add Tracing Marker component type to React exports
- Add reconciler work tag
- Add devtools work tag
- Add boilerplate for the cache to render children

No functionality yet
2022-02-11 08:42:55 -08:00
Brian Vaughn fa816be7f0
DevTools: Timeline profiler refactor
Refactor DevTools to record Timeline data (in memory) while profiling. Updated the Profiler UI to import/export Timeline data along with legacy profiler data.

Relates to issue #22529
2022-01-28 13:09:28 -05:00
Brian Vaughn 3d1e7e7278
Suppress act() warnings in DevTools tests (#23192)
These warnings are not useful for DevTools tests– and sometimes may mask other, important warnings. This commit disables them.
2022-01-26 15:18:21 -05:00
Brian Vaughn 934f72221d
Gracefully handle empty "xstyle" prop values (#23190) 2022-01-26 13:54:44 -05:00
Brian Vaughn 13036bfbc8
DevTools should not crawl unmounted subtrees when profiling starts (#23162)
Previously we crawled all subtrees, even not-yet-mounted ones, to initialize context values. This was not only unecessary, but it also caused an error to be thrown. This commit adds a test and fixes that behavior.
2022-01-21 11:05:49 -05:00
Andrew Clark ca143e18d8
Prettier 2022-01-21 09:59:11 -05:00
Behnam Mohammadi 26baf6a174
styles: replace Array.isArray with module isArray (#23154) 2022-01-21 09:33:00 -05:00
Luna Ruan 7bee1379b7
Filter out deleted components that are added to the updaters list (#23156)
There was a bug that occurred when a destroy effect is called that causes an update. The update would be added to the updaters list even though the fiber that was calling the destroy effect was unmounted and no longer exists. This PR:

* Adds a patch to Devtools to filter out all in the update list that aren't in the fiberToIDMap (which contains all fibers currently on screen)
2022-01-20 13:29:43 -08:00
Brian Vaughn a637084320
DevTools: Add Jest snapshot serializer for number formatting (#23139)
Numbers in JavaScript can have precision issues due to how they are encoded. This shows up in snapshot tests sometimes with values like 0.0009999999999999992, which makes the tests hard to read and visually diff.

This PR adds a new snapshot serializers which clamps numbers at 3 decimal points (e.g. the above number 0.0009999999999999992 is serialized as 0.001). This new serializer does not impact non-numeric values, integers, and special numbers like NaN and Infinity.
2022-01-20 15:52:17 -05:00
Brian Vaughn d504824780
Enable scheduling profiler flag in react-dom/testing builds (#23142) 2022-01-19 11:20:42 -05:00
Brian Vaughn 51947a14bb
Refactored how React/DevTools log Timeline performance data (#23102)
Until now, DEV and PROFILING builds of React recorded Timeline profiling data using the User Timing API. This commit changes things so that React records this data by calling methods on the DevTools hook. (For now, DevTools still records that data using the User Timing API, to match previous behavior.)

This commit is large but most of it is just moving things around:

* New methods have been added to the DevTools hook (in "backend/profilingHooks") for recording the Timeline performance events.
* Reconciler's "ReactFiberDevToolsHook" has been updated to call these new methods (when they're present).
* User Timing method calls in "SchedulingProfiler" have been moved to DevTools "backend/profilingHooks" (to match previous behavior, for now).
* The old reconciler tests, "SchedulingProfiler-test" and "SchedulingProfilerLabels-test", have been moved into DevTools "TimelineProfiler-test" to ensure behavior didn't change unexpectedly.
* Two new methods have been added to the injected renderer interface: injectProfilingHooks() and getLaneLabelMap().

Relates to #22529.
2022-01-13 14:55:54 -05:00
Borja Paz Rodríguez 42c30e8b12
Correct typing errors detected in several files (#22965)
* Correct spelling errors in several files
* Correct typos in devtools-shared package files
2022-01-04 10:30:07 -05:00
BIKI DAS a8e9bbe0fe
Made the variable name more meaningful (#23017) 2021-12-22 15:58:06 -05:00
Brian Vaughn bcd24a6706
DevTools: Only show StrictMode badge on root elements (#23012)
* DevTools: Only show StrictMode badge on root elements

Showing an inline non-compliance badge for every element in the tree is noisy. This commit changes it so that we only show inline icons for root elements (although we continue to show an icon for inspected elements regardless).
2021-12-21 15:26:42 -05:00
Brian Vaughn a4ead704ba
Use ReactDOM Test Selector API in DevTools e2e tests (#22978)
Builds on top of the existing Playwright tests to plug in the test selector API: https://gist.github.com/bvaughn/d3c8b8842faf2ac2439bb11773a19cec

My goals in doing this are to...
1. Experiment with the new API to see what works and what doesn't.
2. Add some test selector attributes (and remove DOM-structure based selectors).
3. Focus the tests on DevTools itself (rather than the test app).

I also took this opportunity to add a few new test cases– like named hooks, editable props, component search, and profiling- just to play around more with the Playwright API.

Relates to issue #22646
2021-12-21 11:58:04 -05:00
Brian Vaughn 911f92a44d
DevTools: Support mulitple DevTools instances per page (#22949)
This is being done so that we can embed DevTools within the new React (beta) docs.

The primary changes here are to `react-devtools-inline/backend`:
* Add a new `createBridge` API
* Add an option to the `activate` method to support passing in the custom bridge object.

The `react-devtools-inline` README has been updated to include these new methods.

To verify these changes, this commit also updates the test shell to add a new entry-point for multiple DevTools.

This commit also replaces two direct calls to `window.postMessage()` with `bridge.send()` (and adds the related Flow types).
2021-12-14 12:16:16 -05:00
jstejada 5757919256
DevTools: Correctly log errors reported from the store (#22950) 2021-12-13 12:02:14 -05:00
jstejada a049aa0155
[DevTools] Log errors occurring or reported to the frontend (#22948) 2021-12-13 11:38:45 -05:00
Brian Vaughn 3b3daf5573
Advocate for StrictMode usage within Components tree (#22886)
Adds the concept of subtree modes to DevTools to bridge protocol as follows:
1. Add-root messages get two new attributes: one specifying whether the root is running in strict mode and another specifying whether the root (really the root's renderer) supports the concept of strict mode.
2. A new backend message type (TREE_OPERATION_SET_SUBTREE_MODE). This type specifies a subtree root (id) and a mode (bitmask). For now, the only mode this message deals with is strict mode.

The DevTools frontend has been updated as well to highlight non-StrictMode compliant components.

The changes to the bridge protocol require incrementing the bridge protocol version number, which will also require updating the version of react-devtools-core backend that is shipped with React Native.
2021-12-10 11:05:18 -05:00
Brian Vaughn ad607469c5
StyleX plug-in for resolving atomic styles to values for props.xstyle (#22808)
Adds the concept of "plugins" to the inspected element payload. Also adds the first plugin, one that resolves StyleX atomic style names to their values and displays them as a unified style object (rather than a nested array of objects and booleans).

Source file names are displayed first, in dim color, followed by an ordered set of resolved style values.

For builds with the new feature flag disabled, there is no observable change.

A next step to build on top of this could be to make the style values editable, but change the logic such that editing one directly added an inline style to the item (rather than modifying the stylex class– which may be shared between multiple other components).
2021-12-07 20:04:12 -05:00
Brian Vaughn 8b8817845a
Timeline search (#22799)
Refactor SearchInput component (used in Components tree) to be generic DevTools component with two uses: ComponentSearchInput and TimelineSearchInput.

Refactored Timeline Suspense to more closely match other, newer Suspense patterns (e.g. inspect component, named hooks) and colocated Susepnse code in timelineCache file.

Add search by component name functionality to the Timeline. For now, searching zooms in to the component measure and you can step through each time it rendered using the next/previous arrows.
2021-12-03 16:23:48 -05:00
jstejada a65ceef370
DevTools: Log version in internal logger (#22825) 2021-11-30 10:48:46 -05:00
Brian Vaughn 56efc65e58
DevTools should properly report re-renders due to (use)context changes (#22746)
Note that this only fixes things for newer versions of React (e.g. 18 alpha). Older versions will remain broken because there's not a good way to read the most recent context value for a location in the tree after render has completed. This is because React maintains a stack of context values during render, but by the time DevTools is called– render has finished and the stack is empty.
2021-11-11 14:22:22 -05:00
Brian Vaughn a44a7a2a3f
Filter empty commits (all Fibers bailed out) from Profiler (#22745) 2021-11-11 10:35:16 -05:00
Yash Joshi 2b77ab26ad
fix(devtools): accept json file in import fileinput (#22717) 2021-11-08 16:35:35 -05:00
Yash Joshi 2db6d6a5a7
fix(devtools): expose css vars to reach-ui portal components (#22716) 2021-11-08 15:17:22 -05:00
Sebastian Silbermann ee069065db
devtools: Display root type for root updates in "what caused this update?" (#22599) 2021-11-05 11:58:35 -04:00
Konstantin Popov 54f6ae9b1c
Fix small typos (#22701) 2021-11-04 19:49:06 -04:00
Brian Vaughn 13455d26d1
Cleaned up remaining "scheduling profiler" references in DevTools (#22696) 2021-11-04 11:40:45 -04:00
Brian Vaughn 1bf6deb865
Renamed packages/react-devtools-scheduling-profiler to packages/react-devtools-timeline (#22691) 2021-11-04 10:02:06 -04:00
Brian Vaughn 51c558aeb6
Rename (some) "scheduling profiler" references to "timeline" (#22690) 2021-11-03 15:10:29 -04:00
EzzAk 255221c869
[DevTools] Add open in editor for fb (#22649)
Co-authored-by: Brian Vaughn <bvaughn@fb.com>
2021-11-03 11:27:30 -04:00
Brian Vaughn 9fb3442250
Fix DevTools advanced tooltip display conditional check (#22669) 2021-11-02 11:02:45 -04:00
Andrew Clark 75f3ddebfa
Remove experimental useOpaqueIdentifier API (#22672)
useId is the updated version of this API.
2021-11-01 15:02:39 -07:00
Juan 26bc8ff9bf
Revert logic for checking for duplicate installations of DevTools (#22638)
* Revert "Only show DevTools warning about unrecognized build in Chrome (#22571)"

This reverts commit b72dc8e930.

* Revert "Show warning in UI when duplicate installations of DevTools extension are detected (#22563)"

This reverts commit 930c9e7eeb.

* Revert "Prevent errors/crashing when multiple installs of DevTools are present (#22517)"

This reverts commit 545d4c2de7.

* Remove all references to passing extensionId in postMessage

* Keep build changes

* lint
2021-10-27 16:34:44 -04:00
Joseph Savona fa9bea0c41
Initial implementation of cache cleanup (#22510)
This is an initial, partial implementation of a cleanup mechanism for the experimental Cache API. The idea is that consumers of the Cache API can register to be informed when a given Cache instance is no longer needed so that they can perform associated cleanup tasks to free resources stored in the cache. A canonical example would be cancelling pending network requests.

An overview of the high-level changes:

* Changes the `Cache` type from a Map of cache instances to be an object with the original Map of instances, a reference count (to count roughly "active references" to the cache instances - more below), and an AbortController.
* Adds a new public API, `unstable_getCacheSignal(): AbortSignal`, which is callable during render. It returns an AbortSignal tied to the lifetime of the cache - developers can listen for the 'abort' event on the signal, which React now triggers when a given cache instance is no longer referenced. 
  * Note that `AbortSignal` is a web standard that is supported by other platform APIs; for example a signal can be passed to `fetch()` to trigger cancellation of an HTTP request.
* Implements the above - triggering the 'abort' event - by handling passive mount/unmount for HostRoot and CacheComponent fiber nodes.

Cases handled:
* Aborted transitions: we clean up a new cache created for an aborted transition
* Suspense: we retain a fresh cache instance until a suspended tree resolves

For follow-ups:
* When a subsequent cache refresh is issued before a previous refresh completes, the refreshes are queued. Fresh cache instances for previous refreshes in the queue should be cleared, retaining only the most recent cache. I plan to address this in a follow-up PR.
* If a refresh is cancelled, the fresh cache should be cleaned up.
2021-10-21 14:11:42 -07:00
Brian Vaughn 4ba20579da
Scheduling Profiler: De-emphasize React internal frames (#22588)
This commit adds code to all React bundles to explicitly register the beginning and ending of the module. This is done by creating Error objects (which capture the file name, line number, and column number) and passing them explicitly to a DevTools hook (when present).

Next, as the Scheduling Profiler logs metadata to the User Timing API, it prints these module ranges along with other metadata (like Lane values and profiler version number).

Lastly, the Scheduling Profiler UI compares stack frames to these ranges when drawing the flame graph and dims or de-emphasizes frames that fall within an internal module.

The net effect of this is that user code (and 3rd party code) stands out clearly in the flame graph while React internal modules are dimmed.

Internal module ranges are completely optional. Older profiling samples, or ones recorded without the React DevTools extension installed, will simply not dim the internal frames.
2021-10-21 14:40:41 -04:00
Konstantin Popov f6abf4b400
Fix typos (#22494) 2021-10-20 23:22:41 -04:00
Andrew Clark 996da67b29
Replace global `jest` heuristic with `IS_REACT_ACT_ENVIRONMENT` (#22562)
* Remove `jest` global check in concurrent roots

In concurrent mode, instead of checking `jest`, we check the new
`IS_REACT_ACT_ENVIRONMENT` global. The default behavior is `false`.

Legacy mode behavior is unchanged.

React's own internal test suite use a custom version of `act` that works
by mocking the Scheduler — rather than the "real" act used publicly. So
we don't enable the flag in our repo.

* Warn if `act` is called in wrong environment

Adds a warning if `act` is called but `IS_REACT_ACT_ENVIRONMENT` is not
enabled. The goal is to prompt users to correctly configure their
testing environment, so that if they forget to use `act` in a different
test, we can detect and warn about.

It's expected that the environment flag will be configured by the
testing framework. For example, a Jest plugin. We will link to the
relevant documentation page, once it exists.

The warning only fires in concurrent mode. Legacy roots will keep the
existing behavior.
2021-10-18 08:59:18 -07:00
Juan 930c9e7eeb
Show warning in UI when duplicate installations of DevTools extension are detected (#22563) 2021-10-15 11:27:13 -04:00
Gabriel Trompiz a45533cc25
Allow to use the Profiler when no client is connected in standalone DevTools (#22551) 2021-10-14 08:31:45 -04:00
Brian Vaughn 8ee4ff8836
Surface backend errors during inspection in the frontend UI (#22546) 2021-10-13 10:35:21 -04:00
Juan afcb9cdc93
[DevTools] Update Fiber logic in backend renderer to match implementation in React (#22527)
* [DevTools] Update isMountedImpl to match implementation in React

* Also sync findCurrentFiberUsingSlowPathById
2021-10-08 16:19:54 -04:00
Juan 5fa4d79b00
[DevTools] Register logger for standalone DevTools (#22524) 2021-10-08 08:38:11 -04:00
Brian Vaughn cadf94df1f
Add new Jest --compact-console flag for DevTools tests (#22495) 2021-10-05 11:58:54 -04:00
BIKI DAS a4bc8ae4c1
Reopen #22481 Fixed modal closing issue (#22484)
Co-authored-by: Brian Vaughn <brian.david.vaughn@gmail.com>
2021-10-02 10:26:15 -04:00
Brian Vaughn 5f3b376c56
Show different error boundary UI for timeouts than normal errors (#22483) 2021-10-01 15:03:36 -04:00
Juan 2825a08dc0
[DevTools] Log basic usage events (#22478) 2021-09-30 17:19:07 -04:00
Juan f5d946da6b
[DevTools] Enable logger for internal build of DevTools extensions (#22476) 2021-09-30 14:13:13 -04:00
Juan 75b9869648
[DevTools] Extension reports logged events when feature flag is enabled (#22475) 2021-09-30 13:47:14 -04:00
Brian Vaughn 47177247f8
DevTools: Fixed potential cache miss when insepcting elements (#22472) 2021-09-30 12:48:53 -04:00
Brian Vaughn 9175f4d15e
Scheduling Profiler: Show Suspense resource .displayName (#22451) 2021-09-28 11:29:33 -04:00
Behnam Mohammadi 8131de13e2
prevent unused exec getCurrentValue after re-render (#22442) 2021-09-27 17:20:32 -04:00
Behnam Mohammadi 580e2f56d5
Add isArray in devTools utils (#22438) 2021-09-27 17:17:30 -04:00
Andrew Clark d3e0869324
Make root.unmount() synchronous (#22444)
* Move flushSync warning to React DOM

When you call in `flushSync` from an effect, React fires a warning. I've
moved the implementation of this warning out of the reconciler and into
React DOM.

`flushSync` is a renderer API, not an isomorphic API, because it has
behavior that was designed specifically for the constraints of React
DOM. The equivalent API in a different renderer may not be the same.
For example, React Native has a different threading model than the
browser, so it might not make sense to expose a `flushSync` API to the
JavaScript thread.

* Make root.unmount() synchronous

When you unmount a root, the internal state that React stores on the
DOM node is immediately cleared. So, we should also synchronously
delete the React tree. You should be able to create a new root using
the same container.
2021-09-27 14:04:39 -07:00
Brian Vaughn 2e41568313
DevTools encoding supports multibyte characters (e.g. "🟩") (#22424)
Changes our text encoding approach to properly support multibyte characters following this algorithm. Based on benchmarking, this new approach is roughly equivalent in terms of performance (sometimes slightly faster, sometimes slightly slower).

I also considered using TextEncoder/TextDecoder for this, but it was much slower (~85%).
2021-09-27 13:34:39 -04:00
Justin Grant c88fb49d37
Improve DEV errors if string coercion throws (Temporal.*, Symbol, etc.) (#22064)
* Revise ESLint rules for string coercion

Currently, react uses `'' + value` to coerce mixed values to strings.
This code will throw for Temporal objects or symbols.

To make string-coercion safer and to improve user-facing error messages,
This commit adds a new ESLint rule called `safe-string-coercion`.

This rule has two modes: a production mode and a non-production mode.
* If the `isProductionUserAppCode` option is true, then `'' + value`
  coercions are allowed (because they're faster, although they may
  throw) and `String(value)` coercions are disallowed. Exception:
  when building error messages or running DEV-only code in prod
  files, `String()` should be used because it won't throw.
* If the `isProductionUserAppCode` option is false, then `'' + value`
  coercions are disallowed (because they may throw, and in non-prod
  code it's not worth the risk) and `String(value)` are allowed.

Production mode is used for all files which will be bundled with
developers' userland apps. Non-prod mode is used for all other React
code: tests, DEV blocks, devtools extension, etc.

In production mode, in addiiton to flagging `String(value)` calls,
the rule will also flag `'' + value` or `value + ''` coercions that may
throw. The rule is smart enough to silence itself in the following
"will never throw" cases:
* When the coercion is wrapped in a `typeof` test that restricts to safe
  (non-symbol, non-object) types. Example:
    if (typeof value === 'string' || typeof value === 'number') {
      thisWontReport('' + value);
    }
* When what's being coerced is a unary function result, because unary
   functions never return an object or a symbol.
* When the coerced value is a commonly-used numeric identifier:
  `i`, `idx`, or `lineNumber`.
* When the statement immeidately before the coercion is a DEV-only
  call to a function from shared/CheckStringCoercion.js. This call is a
  no-op in production, but in DEV it will show a console error
  explaining the problem, then will throw right after a long explanatory
  code comment so that debugger users will have an idea what's going on.
  The check function call must be in the following format:
    if (__DEV__) {
      checkXxxxxStringCoercion(value);
    };

Manually disabling the rule is usually not necessary because almost all
prod use of the `'' + value` pattern falls into one of the categories
above. But in the rare cases where the rule isn't smart enough to detect
safe usage (e.g. when a coercion is inside a nested ternary operator),
manually disabling the rule will be needed.

The rule should also be manually disabled in prod error handling code
where `String(value)` should be used for coercions, because it'd be
bad to throw while building an error message or stack trace!

The prod and non-prod modes have differentiated error messages to
explain how to do a proper coercion in that mode.

If a production check call is needed but is missing or incorrect
(e.g. not in a DEV block or not immediately before the coercion), then
a context-sensitive error message will be reported so that developers
can figure out what's wrong and how to fix the problem.

Because string coercions are now handled by the `safe-string-coercion`
rule, the `no-primitive-constructor` rule no longer flags `String()`
usage. It still flags `new String(value)` because that usage is almost
always a bug.

* Add DEV-only string coercion check functions

This commit adds DEV-only functions to check whether coercing
values to strings using the `'' + value` pattern will throw. If it will
throw, these functions will:
1. Display a console error with a friendly error message describing
   the problem and the developer can fix it.
2. Perform the coercion, which will throw. Right before the line where
   the throwing happens, there's a long code comment that will help
   debugger users (or others looking at the exception call stack) figure
   out what happened and how to fix the problem.

One of these check functions should be called before all string coercion
of user-provided values, except when the the coercion is guaranteed not
to throw, e.g.
* if inside a typeof check like `if (typeof value === 'string')`
* if coercing the result of a unary function like `+value` or `value++`
* if coercing a variable named in a whitelist of numeric identifiers:
  `i`, `idx`, or `lineNumber`.

The new `safe-string-coercion` internal ESLint rule enforces that
these check functions are called when they are required.

Only use these check functions in production code that will be bundled
with user apps.  For non-prod code (and for production error-handling
code), use `String(value)` instead which may be a little slower but will
never throw.

* Add failing tests for string coercion

Added failing tests to verify:
* That input, select, and textarea elements with value and defaultValue
  set to Temporal-like objects which will throw when coerced to string
  using the `'' + value` pattern.
* That text elements will throw for Temporal-like objects
* That dangerouslySetInnerHTML will *not* throw for Temporal-like
  objects because this value is not cast to a string before passing to
  the DOM.
* That keys that are Temporal-like objects will throw

All tests above validate the friendly error messages thrown.

* Use `String(value)` for coercion in non-prod files

This commit switches non-production code from `'' + value` (which
throws for Temporal objects and symbols) to instead use `String(value)`
which won't throw for these or other future plus-phobic types.

"Non-produciton code" includes anything not bundled into user apps:
* Tests and test utilities. Note that I didn't change legacy React
  test fixtures because I assumed it was good for those files to
  act just like old React, including coercion behavior.
* Build scripts
* Dev tools package - In addition to switching to `String`, I also
  removed special-case code for coercing symbols which is now
  unnecessary.

* Add DEV-only string coercion checks to prod files

This commit adds DEV-only function calls to to check if string coercion
using `'' + value` will throw, which it will if the value is a Temporal
object or a symbol because those types can't be added with `+`.

If it will throw, then in DEV these checks will show a console error
to help the user undertsand what went wrong and how to fix the
problem. After emitting the console error, the check functions will
retry the coercion which will throw with a call stack that's easy (or
at least easier!) to troubleshoot because the exception happens right
after a long comment explaining the issue. So whether the user is in
a debugger, looking at the browser console, or viewing the in-browser
DEV call stack, it should be easy to understand and fix the problem.

In most cases, the safe-string-coercion ESLint rule is smart enough to
detect when a coercion is safe. But in rare cases (e.g. when a coercion
is inside a ternary) this rule will have to be manually disabled.

This commit also switches error-handling code to use `String(value)`
for coercion, because it's bad to crash when you're trying to build
an error message or a call stack!  Because `String()` is usually
disallowed by the `safe-string-coercion` ESLint rule in production
code, the rule must be disabled when `String()` is used.
2021-09-27 10:05:07 -07:00
Behnam Mohammadi c9d64e5f4c
add hasOwnProperty to devTools backend (#22437) 2021-09-27 08:56:56 -04:00
Brian Vaughn 1c73ceed5f
Scheduling Profiler marks should include thrown Errors (#22419) 2021-09-24 12:56:27 -04:00
Brian Vaughn b1a1cb1168
DevTools: Lazily parse indexed map sections (#22415)
Indexed maps divide nested source maps into sections, annotated with a line and column offset. Since these sections are JSON and can be quickly parsed, we can easily separate them without doing the heavier base64 and VLQ decoding process. This PR updates our sourcemap parsing code to defer parsing of an indexed map section until we actually need to retrieve mappings from it.
2021-09-24 11:09:42 -04:00
Brian Vaughn d174d063d1
DevTools: Hook names optimizations (#22403)
This commit dramatically improves the performance of the hook names feature by replacing the source-map-js integration with custom mapping code built on top of sourcemap-codec. Based on my own benchmarking, this makes parsing 3-4 times faster. (The bulk of these changes are in SourceMapConsumer.js.)

While implementing this code, I also uncovered a problem with the way we were caching source-map metadata that was causing us to potential parse the same source-map multiple times. (I addressed this in a separate commit for easier reviewing. The bulk of these changes are in parseSourceAndMetadata.js.)

Altogether these changes dramatically improve the performance of the hooks parsing code.

One additional thing we could look into if the source-map download still remains a large bottleneck would be to stream it and decode the mappings array while it streams in rather than in one synchronous chunk after the full source-map has been downloaded.
2021-09-22 20:17:57 -04:00
Luna Ruan 5b57bc6e31
[Draft] don't patch console during first render (#22308)
Previously, DevTools always overrode the native console to dim or supress StrictMode double logging. It also overrode console.log (in addition to console.error and console.warn). However, this changes the location shown by the browser console, which causes a bad developer experience. There is currently a TC39 proposal that would allow us to extend console without breaking developer experience, but in the meantime this PR changes the StrictMode console override behavior so that we only patch the console during the StrictMode double render so that, during the first render, the location points to developer code rather than our DevTools console code.
2021-09-21 15:00:11 -07:00
Konstantin Popov acf8ada4c0
Fix typo in types.js (react-devtools-shared) (#22299)
Fix typo:

becuase -> because
2021-09-20 15:09:59 -04:00
Brian Vaughn 7e8fb98e14
Enabled enableProfilerChangedHookIndices feature flag for all builds (#22365) 2021-09-20 13:10:50 -04:00
Sebastian Silbermann 3ee7a004e5
devtools: Display actual ReactDOM API name in root type (#22363) 2021-09-20 11:44:21 -04:00
Brian Vaughn f50ff357cf
DevTools: Fix memory leak via alternate Fiber pointer (#22346) 2021-09-17 12:53:07 -04:00
Brian Vaughn bc9bb87c2b
Clear performance marks after measuring (#22345) 2021-09-17 10:46:42 -04:00
Juan 1090ccd019
[DevTools] Enable hook names in standalone app (#22320) 2021-09-17 10:21:54 -04:00