Commit Graph

139 Commits

Author SHA1 Message Date
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
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
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
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
BIKI DAS
a8e9bbe0fe Made the variable name more meaningful (#23017) 2021-12-22 15:58:06 -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
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
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
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
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
Brian Vaughn
8ee4ff8836 Surface backend errors during inspection in the frontend UI (#22546) 2021-10-13 10:35:21 -04:00
Brian Vaughn
cadf94df1f Add new Jest --compact-console flag for DevTools tests (#22495) 2021-10-05 11:58:54 -04:00
Brian Vaughn
47177247f8 DevTools: Fixed potential cache miss when insepcting elements (#22472) 2021-09-30 12:48:53 -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
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
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
Luna Ruan
597ecd6a0c [DevTools] Throw error in console without interfering with logs (#22175) 2021-08-30 14:37:49 -07:00
Luna Ruan
60a30cf32e Console Logging for StrictMode Double Rendering (#22030)
React currently suppress console logs in StrictMode during double rendering. However, this causes a lot of confusion. This PR moves the console suppression logic from React into React Devtools. Now by default, we no longer suppress console logs. Instead, we gray out the logs in console during double render. We also add a setting in React Devtools to allow developers to hide console logs during double render if they choose.
2021-08-25 15:35:38 -07:00
Brian Vaughn
edfe50510b DevTools: Replaced WeakMap with LRU for inspected element cache (#22160)
We use an LRU for this rather than a WeakMap because of how the "no-change" optimization works.

When the frontend polls the backend for an update on the element that's currently inspected, the backend will send a "no-change" message if the element hasn't updated (rendered) since the last time it was asked. In thid case, the frontend cache should reuse the previous (cached) value. Using a WeakMap keyed on Element generally works well for this, since Elements are mutable and stable in the Store. This doens't work properly though when component filters are changed, because this will cause the Store to dump all roots and re-initialize the tree (recreating the Element objects).

So instead we key on Element ID (which is stable in this case) and use an LRU for eviction.
2021-08-23 19:22:31 -04:00
Brian Vaughn
75a3e9fa40 DevTools: Reset cached indices in Store after elements reordered (#22147) 2021-08-20 12:53:28 -04:00
Sebastian Silbermann
b6ff9ad163 DevTools: update error indices when elements are added/removed (#22144) 2021-08-20 11:55:42 -04:00
Byron Luk
da627ded86 Devtools/function context change (#22047) 2021-08-10 14:16:54 -04:00
Shubham Pandey
6f3fcbd6fa Some remaining instances of master to main (#21982)
Co-authored-by: Shubham Pandey <shubham.pandey@mfine.co>
2021-07-30 08:56:55 -04:00
Brian Vaughn
6840c98c32 Remove named hooks feature flag (#21894) 2021-07-16 00:14:20 -04:00
Andrew Clark
a4ecd85e86 act: Batch updates, even in legacy roots (#21797)
In legacy roots, if an update originates outside of `batchedUpdates`,
check if it's inside an `act` scope; if so, treat it as if it were
batched. This is only necessary in legacy roots because in concurrent
roots, updates are batched by default.

With this change, the Test Utils and Test Renderer versions of `act` are
nothing more than aliases of the isomorphic API (still not exposed, but
will likely be the recommended API that replaces the others).
2021-07-12 17:15:20 -07:00
Andrew Clark
54e88ed12c Bugfix: Flush legacy sync passive effects at beginning of event (#21846)
* Re-land recent flushSync changes

Adds back #21776 and #21775, which were removed due to an internal
e2e test failure.

Will attempt to fix in subsequent commits.

* Failing test: Legacy mode sync passive effects

In concurrent roots, if a render is synchronous, we flush its passive
effects synchronously. In legacy roots, we don't do this because all
updates are synchronous — so we need to flush at the beginning of the
next event. This is how `discreteUpdates` worked.

* Flush legacy passive effects at beginning of event

Fixes test added in previous commit.
2021-07-10 11:15:11 -07:00
Brian Vaughn
9ccc25a0ea Reverting recent flushSync changes (#21816) 2021-07-07 15:07:55 -04:00
Andrew Clark
ed6c091fe9 Replace unbatchedUpdates with flushSync (#21776)
There's a weird quirk leftover from the old Stack (pre-Fiber)
implementation where the initial mount of a leagcy (ReactDOM.render)
root is flushed synchronously even inside `batchedUpdates`.

The original workaround for this was an internal method called
`unbatchedUpdates`. We've since added another API that works almost the
same way, `flushSync`.

The only difference is that `unbatchedUpdates` would not cause other
pending updates to flush too, only the newly mounted root. `flushSync`
flushes all pending sync work across all roots. This was to preserve
the exact behavior of the Stack implementation.

But since it's close enough, let's just use `flushSync`. It's unlikely
anyone's app accidentally relies on this subtle difference, and the
legacy API is deprecated in 18, anyway.
2021-07-01 15:14:07 -07:00
Brian Vaughn
c5cfa71948 DevTools: Show hook names based on variable usage (#21641)
Co-authored-by: Brian Vaughn <brian.david.vaughn@gmail.com>
Co-authored-by: Saphal Patro <saphal1998@gmail.com>
Co-authored-by: VibhorCodecianGupta <vibhordelgupta@gmail.com>
2021-07-01 14:39:18 -04:00
Brian Vaughn
d483463bc8 Updated scripts and config to replace "master" with "main" branch (#21768) 2021-06-29 14:26:24 -04:00
Brian Vaughn
73ffce1b6f DevTools: Update tests to fix warnings/errors (#21748)
Some new ones had slipped in (e.g. deprecated ReactDOM.render message from 18)
2021-06-24 22:42:44 -04:00
Andrew Clark
d7dce572c7 Remove internal act builds from public modules (#21721)
* Move internal version of act to shared module

No reason to have three different copies of this anymore.

I've left the the renderer-specific `act` entry points because legacy
mode tests need to also be wrapped in `batchedUpdates`. Next, I'll update
the tests to use `batchedUpdates` manually when needed.

* Migrates tests to use internal module directly

Instead of the `unstable_concurrentAct` exports. Now we can drop those
from the public builds.

I put it in the jest-react package since that's where we put our other
testing utilities (like `toFlushAndYield`). Not so much so it can be
consumed publicly (nobody uses that package except us), but so it works
with our build tests.

* Remove unused internal fields

These were used by the old act implementation. No longer needed.
2021-06-22 14:29:35 -07:00
Brian Vaughn
01be61c12f DevTools can inspect Proxies that return broken iterator functions (#21660) 2021-06-11 10:15:48 -04:00
Andrew Clark
aecb3b6d11 Deprecate ReactDOM.render and ReactDOM.hydrate (#21652)
* Use existing test warning filter for server tests

We have a warning filter for our internal tests to ignore warnings
that are too noisy or that we haven't removed from our test suite yet:
shouldIgnoreConsoleError.

Many of our server rendering tests don't use this filter, though,
because it has its own special of asserting warnings.

So I added the warning filter to the server tests, too.

* Deprecate ReactDOM.render and ReactDOM.hydrate

These are no longer supported in React 18. They are replaced by the
`createRoot` API.

The warning includes a link to documentation of the new API. Currently
it redirects to the corresponding working group post. Here's the PR to
set up the redirect: https://github.com/reactjs/reactjs.org/pull/3730

Many of our tests still use ReactDOM.render. We will need to gradually
migrate them over to createRoot.

In the meantime, I added the warnings to our internal warning filter.
2021-06-09 13:46:55 -07:00
Bao Pham
8b4201535c Devtools: add feature to trigger an error boundary (#21583)
Co-authored-by: Brian Vaughn <bvaughn@fb.com>
2021-06-03 11:21:44 -04:00
Brian Vaughn
6405efc368 Enabled Profiling feature flags for OSS release (#21565)
* Enabled Profiling feature flags for OSS release

`enableProfilerCommitHooks` and `enableProfilerNestedUpdatePhase`
2021-05-25 17:32:14 -04:00
Brian Vaughn
965fb8be6b DevTools: Support an element mounting before its owner (#21562) 2021-05-25 14:49:05 -04:00
Brian Vaughn
b8bbb6a13d Fix edge-case Fast Refresh bug that caused Fibers with warnings/errors to be untracked prematurely (#21536)
Refactor error/warning count tracking to avoid pre-allocating an ID for Fibers that aren't yet mounted. Instead, we store a temporary reference to the Fiber itself and later check to see if it successfully mounted before merging pending error/warning counts.

This avoids a problematic edge case where a force-remounted Fiber (from Fast Refresh) caused us to untrack a Fiber that was still mounted, resulting in a DevTools error if that Fiber was inspected in the Components tab.
2021-05-20 11:24:08 -04:00
Brian Vaughn
d6604ac031 Account for another DevTools + Fast Refresh edge case (#21523)
DevTools now 'untrack' Fibers (cleans up the ID-to-Fiber mapping) after a slight delay in order to support a Fast Refresh edge case:
1. Component type is updated and Fast Refresh schedules an update+remount.
2. flushPendingErrorsAndWarningsAfterDelay() runs, sees the old Fiber is no longer mounted (it's been disconnected by Fast Refresh), and calls untrackFiberID() to clear it from the Map.
3. React flushes pending passive effects before it runs the next render, which logs an error or warning, which causes a new ID to be generated for this Fiber.
4. DevTools now tries to unmount the old Component with the new ID.

The underlying problem here is the premature clearing of the Fiber ID, but DevTools has no way to detect that a given Fiber has been scheduled for Fast Refresh. (The '_debugNeedsRemount' flag won't necessarily be set.)

The best we can do is to delay untracking by a small amount, and give React time to process the Fast Refresh delay.
2021-05-18 22:44:29 -04:00
Brian Vaughn
b15bf2b2f1 DevTools bugfix for useState() with hasOwnProperty key (#21524) 2021-05-18 16:43:33 -04:00
Brian Vaughn
63927e0843 Fixed another Symbol concatenation issue with DevTools format() util (#21521) 2021-05-18 11:46:04 -04:00
Brian Vaughn
1e3383a411 DevTools: Reload all roots after Fast Refresh force remount (#21516)
Works around the corrupted Store state by detecting a broken Fast Refresh remount and forcefully dropping the root and re-mounting the entire tree. This prevents Fibers from getting duplicated in the Store (and in the Components tree). The benefit of this approach is that it doesn't rely on an update or change in behavior to Fast Refresh. (This workaround is pretty dirty, but since it's a DEV-only code path, it's probably okay.)

Note that this change doesn't fix all of the reported issues (see #21442 (comment)) but it does fix some of them.

This commit also slightly refactors the way DevTools assigns and manages unique IDs for Fibers in the backend by removing the indirection of a "primary Fiber" and instead mapping both the primary and alternate.

It also removes the previous cache-on-read behavior of getFiberID and splits the method into three separate functions for different use cases:
* getOrGenerateFiberID – Like the previous function, this method returns an ID or generates and caches a new one if the Fiber hasn't been seen before.
* getFiberIDUnsafe – This function returns an ID if one has already been generated or null if not. (It can be used to e.g. log a message about a Fiber without potentially causing it to leak.)
* getFiberIDThrows – This function returns an ID if one has already been generated or it throws. (It can be used to guarantee expected behavior rather than to silently cause a leak.)
2021-05-18 11:42:08 -04:00
Brian Vaughn
2bf4805e4b Update entry point exports (#21488)
The following APIs have been added to the `react` stable entry point:
* `SuspenseList`
* `startTransition`
* `unstable_createMutableSource`
* `unstable_useMutableSource`
* `useDeferredValue`
* `useTransition`

The following APIs have been added or removed from the `react-dom` stable entry point:
* `createRoot`
* `unstable_createPortal` (removed)

The following APIs have been added to the `react-is` stable entry point:
* `SuspenseList`
* `isSuspenseList`

The following feature flags have been changed from experimental to true:
* `enableLazyElements`
* `enableSelectiveHydration`
* `enableSuspenseServerRenderer`
2021-05-12 11:28:14 -04:00
Brian Vaughn
d1542de3a6 Unify React.memo and React.forwardRef display name logic (#21392)
Co-authored-by: iChenLei <2470828450@qq.com>
2021-05-04 11:40:16 -04:00
Brian Vaughn
22ab39be68 DevTools console patching should handle Symbols without erroring (#21368) 2021-04-27 16:36:20 -04:00