Commit Graph
59 Commits
Author SHA1 Message Date
Sebastian "Sebbie" Silbermann c498bfce8b [devtools] Allow inspecting cause, name, message, stack of Errors in props (#33023) 2025-04-26 07:20:57 +02:00
Sebastian "Sebbie" SilbermannandRuslan Lesiutin 197d6a0403 [devtools] 1st class support of used Thenables (#32989)
Co-authored-by: Ruslan Lesiutin <rdlesyutin@gmail.com>
2025-04-24 13:46:31 +02:00
Ruslan Lesiutin d634548243 DevTools: merge element fields in TreeStateContext (#31956)
Stacked on https://github.com/facebook/react/pull/31892, see commit on
top.

For some reason, there were 2 fields different fields for essentially
same thing: `selectedElementID` and `inspectedElementID`. Basically, the
change is:
```
selectedElementID -> inspectedElementID
selectedElementIndex -> inspectedElementIndex
```

I have a theory that it was due to previously used async approach around
element inspection, and the whole `InspectedElementView` was wrapped in
`Suspense`.
2025-01-09 18:13:24 +00:00
Sebastian Markbåge a06cd9e1d1 [DevTools] Refactor Forcing Fallback / Error of Suspense / Error Boundaries (#30870)
First, this basically reverts
https://github.com/facebook/react/pull/30517/commits/1f3892ef8cc181218587ddc6accd994890c92ef5
to use a Map/Set to track what is forced to suspend/error again instead
of flags on the Instance. The difference is that now the key in the
Fiber itself instead of the ID. Critically this avoids the
fiberToFiberInstance map to look up whether or not a Fiber should be
forced to suspend when asked by the renderer.

This also allows us to force suspend/error on filtered instances. It's a
bit unclear what should happen when you try to Suspend or Error a child
but its parent boundary is filtered. It was also inconsistent between
Suspense and Error due to how they were implemented.

I think conceptually you're trying to simulate what would happen if that
Component errored or suspended so it would be misleading if we triggered
a different boundary than would happen in real life. So I think we
should trigger the nearest unfiltered Fiber, not the nearest Instance.
The consequence of this however is that if this instance was filtered,
there's no way to undo it without refreshing or removing the filter.
This is an edge case though since it's unusual you'd filter these in the
first place.

It used to be that Suspense walked the store in the frontend and Error
walked the Fibers in the backend. They also did this somewhat eagerly.
This simplifies and unifies the model by passing the id of what you
clicked in the frontend and then we walk the Fiber tree from there in
the backend to lazily find the boundary. However I also eagerly walk the
tree at first to find whether we have any Suspense or Error boundary
parents at all so we can hide the buttons if not.

This also implements it to work with VirtualInstances using #30865. I
find the nearest Fiber Instance downwards filtered or otherwise. Then
from its parent we find the nearest Error or Suspense boundary. That's
because VirtualInstance will always have their inner Fiber as an
Instance but they might not have their parent since it might be
filtered. Which would potentially cause us to skip over a filtered
parent Suspense boundary.
2024-09-05 15:48:17 -04:00
Sebastian Markbåge 36c04348d7 [DevTools] Make Functions Clickable to Jump to Definition (#30769)
Currently you can jump to definition of a function by right clicking
through the context menu. However, it's pretty difficult to discover.
This makes the functions clickable to jump to definition - like links.

This uses the same styling as we do for links (which are btw only
clickable if they're not editable). Including cursor: pointer.

I added a background on hover which follows the same pattern as the
owners list.

I also dropped the ƒ prefix when displaying functions. This is a cute
short cut and there's precedence in how Chrome prints functions in the
console *if* the function's toString would've had a function prefix like
if it was a function declaration or expression. It does not do this for
arrow functions or object methods.

Elsewhere in the JS ecosystem this isn't really used anywhere. It
invites more questions than it answers.

The parenthesis and curlies are enough. There's no ambiguity here since
strings have quotations. It looks better with just its object method
form. Keeping it simple seems best. To my eyes this flows better because
I'm used to looking at function syntax but not weird "f"s.

Before:

<img width="433" alt="Screenshot 2024-08-20 at 11 55 09 PM"
src="https://github.com/user-attachments/assets/9dd50da6-598f-4291-9e24-1cdc7200dc9e">


After:
<img width="388" alt="Screenshot 2024-08-20 at 11 46 01 PM"
src="https://github.com/user-attachments/assets/dd988e14-412e-4deb-8c8c-26a54be8331f">


After (Hover):
<img width="389" alt="Screenshot 2024-08-20 at 11 46 31 PM"
src="https://github.com/user-attachments/assets/6fb4ebed-5dc1-448a-8e4d-b6d4f3903329">
2024-08-22 12:35:49 -04:00
Sebastian Markbåge 13ddf1084b [DevTools] Find owners from the parent path that matches the Fiber or ReactComponentInfo (#30717)
This enables finding Server Components on the owner path. Server
Components aren't stateful so there's not actually one specific owner
that it necessarily matches. So it can't be a global look up. E.g. the
same Server Component can be rendered in two places or even nested
inside each other.

Therefore we need to find an appropriate instance using a heuristic. We
can do that by traversing the parent path since the owner is likely also
a parent. Not always but almost always.

To simplify things we can also do the same for Fibers. That brings us
one step closer to being able to get rid of the global
fiberToFiberInstance map since we can just use the shadow tree to find
this information.

This does mean that we can't find owners that aren't parents which is
usually ok. However, there is a test case that's interesting where you
have a React ART tree inside a DOM tree. In that case the owners
actually span multiple renderers and roots so the owner is not on the
parent stack. Usually this is fine since you'd just care about the
owners within React ART but ideally we'd support this. However, I think
that really the fix to this is that the React ART tree itself should
actually show up inside the DOM tree in DevTools and in the virtual
shadow tree because that's conceptually where it belongs. That would
then solve this particular issue. We'd just need some way to associate
the root with a DOM parent when it gets mounted.
2024-08-16 19:52:11 -04:00
Sebastian MarkbågeandRuslan Lesiutin 49496d4937 [DevTools] Support Server Components in Tree (#30684)
This adds VirtualInstances to the tree. Each Fiber has a list of its
parent Server Components in `_debugInfo`. The algorithm is that when we
enter a set of fibers, we actually traverse level 0 of all the
`_debugInfo` in each fiber. Then level 1 of each `_debugInfo` and so on.
It would be simpler if `_debugInfo` only contained Server Component
since then we could just look at the index in the array but it actually
contains other data as well which leads to multiple passes but we don't
expect it to have a lot of levels before hitting a reified fiber.
Finally when we hit the end a traverse the fiber itself.

This lets us match consecutive `ReactComponentInfo` that are all the
same at the same level. This creates a single VirtualInstance for each
sequence. This lets the same Server Component instance that's a parent
to multiple children appear as a single Instance instead of one per
Fiber.

Since a Server Component's result can be rendered in more than one place
there's not a 1:1 mapping though. If it is in different parents or if
the sequence is interrupted, then it gets split into two different
instances with the same `ReactComponentInfo` data.

The real interesting case is what happens during updates because this
algorithm means that a Fiber can become reparented during an update to
end up in a different VirtualInstance. The ideal would maybe be that the
frontend could deal with this reparenting but instead I basically just
unmount the previous instance (and its children) and mount a new
instance which leads to some interesting scenarios. This is inline with
the strategy I was intending to pursue anyway where instances are
reconciled against the previous children of the same parent instead of
the `fiberToFiberInstance` map - which would let us get rid of that map.
In that case the model is resilient to Fiber being in more than one
place at a time.

However this unmount/remount does mean that we can lose selection when
this happens. We could maybe do something like using the tracked path
like I did for component filters. Ideally it's a weird edge case though
because you'd typically not have it. The main case that it happens now
is for reorders of list of server components. In that case basically all
the children move between server components while the server components
themselves stay in place. We should really include the key in server
components so that we can reconcile them using the key to handle
reorders which would solve the common case anyway.

I convert the name to the `Env(Name)` pattern which allows the
Environment Name to be used as a badge.

<img width="1105" alt="Screenshot 2024-08-13 at 9 55 29 PM"
src="https://github.com/user-attachments/assets/323c20ba-b655-4ee8-84fa-8233f55d2999">

(Screenshot is with #30667. I haven't tried it with the alternative
fix.)

---------

Co-authored-by: Ruslan Lesiutin <rdlesyutin@gmail.com>
2024-08-14 11:16:51 -04:00
Sebastian Markbåge 25c584f567 [DevTools] Further Refactoring of Unmounts (#30658)
Stacked on #30625 and #30657.

This ensures that we only create instances during the commit
reconciliation and that we don't create unnecessary instances for things
that are filtered or not mounted. This ensures that we also can rely on
the reconciliation to do all the clean up. Now everything is created and
deleted as a pair in the same pass.

Previously we were including unfiltered components in the owner stack
which probably doesn't make sense since you're intending to filter them
everywhere presumably. However, it also means that those links were
broken since you can't link into owners that don't exist in the parent
tree.

The main complication is the component filters. It relied on not
unmounting the old instances. I had to update some tests that asserted
on ids that are now shifted.

For warnings/errors tracking I now restore them back into the pending
set when they unmount. Basically it puts them back into their
"pre-commit" state. That way when they remount they’re still there.

For restoring the current selection I use the tracked path mechanism
instead of relying on the id being unchanged. This is better anyway
because if you filter out the currently selected item it's better to
select the nearest match instead of just losing the selection.
2024-08-12 12:41:29 -04:00
Sebastian Markbåge 4ea12a11d1 [DevTools] Make Element Inspection Feel Snappy (#30555)
There's two problems. The biggest one is that it turns out that Chrome
is throttling looping timers that we're using both while polling and for
batching bridge traffic. This means that bridge traffic a lot of the
time just slows down to 1 second at a time. No wonder it feels sluggish.
The only solution is to not use timers for this.

Even when it doesn't like in Firefox the batching into 100ms still feels
too sluggish.

The fix I use is to batch using a microtask instead so we can still
batch multiple commands sent in a single event but we never artificially
slow down an interaction.

I don't think we've reevaluated this for a long time since this was in
the initial commit of DevTools to this repo. If it causes other issues
we can follow up on those.

We really shouldn't use timers for debouncing and such. In fact, React
itself recommends against it because we have a better technique with
scheduling in Concurrent Mode. The correct way to implement this in the
bridge is using a form of back-pressure where we don't keep sending
messages until we get a message back and only send the last one that
matters. E.g. when moving the cursor over a the elements tab we
shouldn't let the backend one-by-one move the DOM node to each one we
have ever passed. We should just move to the last one we're currently
hovering over. But this can't be done at the bridge layer since it
doesn't know if it's a last-one-wins or imperative operation where each
one needs to be sent. It needs to be done higher. I'm not currently
seeing any perf problems with this new approach but I'm curious on React
Native or some thing. RN might need the back-pressure approach. That can
be a follow up if we ever find a test case.

Finally, the other problem is that we use a Suspense boundary around the
Element Inspection. Suspense boundaries are for things that are expected
to take a long time to load. This shows a loading state immediately. To
avoid flashing when it ends up being fast, React throttles the reveal to
200ms. This means that we take a minimum of 200ms to show the props. The
way to show fast async data in React is using a Transition (either using
startTransition or useDeferredValue). This lets the old value remaining
in place while we're loading the next one.

We already implement this using `inspectedElementID` which is the async
one. It would be more idiomatic to implement this with useDeferredValue
rather than the reducer we have now but same principle. We were just
using the wrong ID in a few places so when it synchronously updated they
suspended. So I just made them use the inspectedElementID instead.

Then I can simply remove the Suspense boundary. Now the selection
updates in the tree view synchronously and the sidebar lags a frame or
two but it feels instant. It doesn't flash to white between which is
key.
2024-08-01 11:04:56 -04:00
Jan Kassens b565373afd lint: enable reportUnusedDisableDirectives and remove unused suppressions (#28721)
This enables linting against unused suppressions and removes the ones
that were unused.
2024-06-21 12:24:32 -04:00
Sebastian Markbåge 2774208039 Remove Warning: prefix and toString on console Arguments (#29839)
Basically make `console.error` and `console.warn` behave like normal -
when a component stack isn't appended. I need this because I need to be
able to print rich logs with the component stack option and to be able
to disable instrumentation completely in `console.createTask`
environments that don't need it.

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

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

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

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

The main motivations is:
a) we have a few duplicated tests, which this found an I deleted 
b) making sure we don't accidentally commit skipped tests
2024-06-10 14:31:37 -04:00
Sebastian Markbåge 84239da896 Move createElement/JSX Warnings into the Renderer (#29088)
This is necessary to simplify the component stack handling to make way
for owner stacks. It also solves some hacks that we used to have but
don't quite make sense. It also solves the problem where things like key
warnings get silenced in RSC because they get deduped. It also surfaces
areas where we were missing key warnings to begin with.

Almost every type of warning is issued from the renderer. React Elements
are really not anything special themselves. They're just lazily invoked
functions and its really the renderer that determines there semantics.

We have three types of warnings that previously fired in
JSX/createElement:

- Fragment props validation.
- Type validation.
- Key warning.

It's nice to be able to do some validation in the JSX/createElement
because it has a more specific stack frame at the callsite. However,
that's the case for every type of component and validation. That's the
whole point of enableOwnerStacks. It's also not sufficient to do it in
JSX/createElement so we also have validation in the renderers too. So
this validation is really just an eager validation but also happens
again later.

The problem with these is that we don't really know what types are valid
until we get to the renderer. Additionally, by placing it in the
isomorphic code it becomes harder to do deduping of warnings in a way
that makes sense for that renderer. It also means we can't reuse logic
for managing stacks etc.

Fragment props validation really should just be part of the renderer
like any other component type. This also matters once we add Fragment
refs and other fragment features. So I moved this into Fiber. However,
since some Fragments don't have Fibers, I do the validation in
ChildFiber instead of beginWork where it would normally happen.

For `type` validation we already do validation when rendering. By
leaving it to the renderer we don't have to hard code an extra list.
This list also varies by context. E.g. class components aren't allowed
in RSC but client references are but we don't have an isomorphic way to
identify client references because they're defined by the host config so
the current logic is flawed anyway. I kept the early validation for now
without the `enableOwnerStacks` since it does provide a nicer stack
frame but with that flag on it'll be handled with nice stacks anyway. I
normalized some of the errors to ensure tests pass.

For `key` validation it's the same principle. The mechanism for the
heuristic is still the same - if it passes statically through a parent
JSX/createElement call then it's considered validated. We already did
print the error later from the renderer so this also disables the early
log in the `enableOwnerStacks` flag.

I also added logging to Fizz so that key warnings can print in SSR logs.

Flight is a bit more complex. For elements that end up on the client we
just pass the `validated` flag along to the client and let the client
renderer print the error once rendered. For server components we log the
error from Flight with the server component as the owner on the stack
which will allow us to print the right stack for context. The factoring
of this is a little tricky because we only want to warn if it's in an
array parent but we want to log the error later to get the right debug
info.

Fiber/Fizz has a similar factoring problem that causes us to create a
fake Fiber for the owner which means the logs won't be associated with
the right place in DevTools.
2024-05-23 12:48:57 -04:00
Ricky dbfbfb3312 Update error messages (#28652)
## Overview

The error messages that say:

> ReactDOM.hydrate is no longer supported in React 18

Don't make sense in the React 19 release. Instead, they should say:

> ReactDOM.hydrate was removed in React 19.

For legacy mode, they should say:

> ReactDOM.hydrate has not been supported since React 18.
2024-03-26 17:25:53 -04:00
Jack Pope 38327309a4 Update isConcurrent RTR option usage (#28546)
Reverting some of https://github.com/facebook/react/pull/27804 which
renamed this option to stable. This PR just replaces internal usage to
make upcoming PRs cleaner.

Keeping isConcurrent unstable for the next major release in order to
enable a broader deprecation of RTR and be consistent with concurrent
rendering everywhere for next major.
(https://github.com/facebook/react/pull/28498)
- Next major will use concurrent root
- The old behavior (legacy root by default, concurrent root with
unstable option) will be preserved for React Native until new
architecture is fully shipped.
- Flag and legacy root usage can be removed after RN dependency is
unblocked without an additional breaking change
2024-03-18 11:35:16 -04:00
Ruslan Lesiutin 61bd00498d refactor[devtools]: lazily define source for fiber based on component stacks (#28351)
`_debugSource` was removed in
https://github.com/facebook/react/pull/28265.

This PR migrates DevTools to define `source` for Fiber based on
component stacks. This will be done lazily for inspected elements, once
user clicks on the element in the tree.

`DevToolsComponentStackFrame.js` was just copy-pasted from the
implementation in `ReactComponentStackFrame`.

Symbolication part is done in
https://github.com/facebook/react/pull/28471 and stacked on this commit.
2024-03-05 12:10:36 +00:00
Ricky 1940cb27b2 Update /link URLs to react.dev (#28477)
Depends on https://github.com/reactjs/react.dev/pull/6670 [merged]
2024-03-03 17:34:33 -05:00
Sebastian Markbåge 7a32d718b9 [Debug Tools] Introspect Promises in use() (#28297)
Alternative to #28295.

Instead of stashing all of the Usables eagerly, we can extract them by
replaying the render when we need them like we do with any other hook.
We already had an implementation of `use()` but it wasn't quite
complete.

These can also include further DebugInfo on them such as what Server
Component rendered the Promise or async debug info. This is nice just to
see which use() calls were made in the side-panel but it can also be
used to gather everything that might have suspended.

Together with https://github.com/facebook/react/pull/28286 we cover the
case when a Promise was used a child and if it was unwrapped with use().
Notably we don't cover a Promise that was thrown (although we do support
that in a Server Component which maybe we shouldn't). Throwing a Promise
isn't officially supported though and that use case should move to the
use() Hook.

The pattern of conditionally suspending based on cache also isn't really
supported with the use() pattern. You should always call use() if you
previously called use() with the same input. This also ensures that we
can track what might have suspended rather than what actually did.

One limitation of this strategy is that it's hard to find all the places
something might suspend in a tree without rerendering all the fibers
again. So we might need to still add something to the tree to indicate
which Fibers may have further debug info / thenables.
2024-02-12 17:54:28 -05:00
Ruslan Lesiutin bfdc12c191 chore: use versioned render in inspectedElement test (#28246) 2024-02-07 10:50:26 +00:00
Jack Pope b36ae8d7aa Add stable concurrent option to react-test-renderer (#27804)
## Summary

Concurrent rendering has been the default since React 18 release.
ReactTestRenderer requires passing `{unstable_isConcurrent: true}` to
match this behavior, which means by default tests written with RTR use a
different rendering method than the code they test.

Eventually, RTR should only use ConcurrentRoot. As a first step, let's
add a version of the concurrent option that isn't marked unstable. Next
we will follow up with removing the unstable option when it is safe to
merge.

## How did you test this change?

`yarn test
packages/react-test-renderer/src/__tests__/ReactTestRendererAsync-test.js`
2023-12-07 10:26:33 -05:00
Ruslan Lesiutin 6c7b41da3d feat[devtools]: display Forget badge for the relevant components (#27709)
Adds `Forget` badge to all relevant components.

Changes:
- If component is compiled with Forget and using a built-in
`useMemoCache` hook, it will have a `Forget` badge next to its display
name in:
  - components tree
  - inspected element view
  - owners list
- Such badges are indexable, so Forget components can be searched using
search bar.

Fixes:
- Displaying the badges for owners list inside the inspected component
view

Implementation:
- React DevTools backend is responsible for identifying if component is
compiled with Forget, based on `fiber.updateQueue.memoCache`. It will
wrap component's display name with `Forget(...)` prefix before passing
operations to the frontend. On the frontend side, we will parse the
display name and strip Forget prefix, marking the corresponding element
by setting `compiledWithForget` field. Almost the same logic is
currently used for HOC display names.
2023-11-23 18:37:21 +00:00
Ruslan Lesiutin 2eed132847 refactor[devtools/extension]: more stable element updates polling to avoid timed out errors (#27357)
Some context:
- When user selects an element in tree inspector, we display current
state of the component. In order to display really current state, we
start polling the backend to get available updates for the element.

Previously:
- Straight-forward sending an event to get element updates each second.
Potential race condition is not handled in any form.
- If user navigates from the page, timeout wouldn't be cleared and we
would potentially throw "Timed out ..." error.
- Bridge disconnection is not handled in any form, if it was shut down,
we could spam with "Timed out ..." errors.

With these changes:
- Requests are now chained, so there can be a single request at a time.
- Handling both navigation and shut down events.

This should reduce the number of "Timed out ..." errors that we see in
our logs for the extension. Other surfaces will also benefit from it,
but not to the full extent, as long as they utilize
"resumeElementPolling" and "pauseElementPolling" events.

Tested this on Chrome, running React DevTools on multiple tabs,
explicitly checked the case when service worker is in idle state and we
return back to the tab.
2023-09-12 15:05:39 +01:00
Ruslan Lesiutin 21021fb0f0 refactor[devtools]: copy to clipboard only on frontend side (#26604)
Fixes https://github.com/facebook/react/issues/26500

## Summary
- No more using `clipboard-js` from the backend side, now emitting
custom `saveToClipboard` event, also adding corresponding listener in
`store.js`
- Not migrating to `navigator.clipboard` api yet, there were some issues
with using it on Chrome, will add more details to
https://github.com/facebook/react/pull/26539

## How did you test this change?
- Tested on Chrome, Firefox, Edge
- Tested on standalone electron app: seems like context menu is not
expected to work there (cannot right-click on value, the menu is not
appearing), other logic (pressing on copy icon) was not changed
2023-04-12 16:12:03 +01: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
Andrew Clark 44d3807945 Move internalAct to internal-test-utils package (#26344)
This is not a public API. We only use it for our internal tests, the
ones in this repo. Let's move it to this private package. Practically
speaking this will also let us use async/await in the implementation.
2023-03-08 12:58:31 -05:00
Andrew Clark 702fc984e6 Codemod act -> await act (4/?) (#26338)
Similar to the rationale for `waitFor` (see #26285), we should always
await the result of an `act` call so that microtasks have a chance to
fire.

This only affects the internal `act` that we use in our repo, for now.
In the public `act` API, we don't yet require this; however, we
effectively will for any update that triggers suspense once `use` lands.
So we likely will start warning in an upcoming minor.
2023-03-08 11:36:05 -05:00
Ming Ye 71cace4d32 Migrate testRunner from jasmine2 to jest-circus (#26144)
## Summary

In jest v27, jest-circus as default test runner
(https://github.com/facebook/jest/pull/10686)

## How did you test this change?

ci green
2023-02-10 13:39:14 -05:00
Ming Ye 55542bc73d Update jest printBasicPrototype config (#26142) 2023-02-10 09:58:57 +01:00
Ming Ye 35698311de Update jest escapeString config (#26140)
## Summary

In jest v29, snapshotFormat default to escapeString:
false(https://github.com/facebook/jest/pull/13036)

## How did you test this change?

ci green
2023-02-10 00:08:37 +01: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
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
Vic Graf 5b59dd6400 Fix duplicate words tests (#25333)
* refactor: removed duplicated words in comments
* refactor: removed duplicate words in tests
2022-09-27 10:07:06 -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
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
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
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
Sebastian MarkbågeandAndrew Clark 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
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
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 47177247f8 DevTools: Fixed potential cache miss when insepcting elements (#22472) 2021-09-30 12:48:53 -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 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 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
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 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