refactor[react-devtools]: initialize renderer interface early (#30946)

The current state is that `rendererInterface`, which contains all the
backend logic, like generating component stack or attaching errors to
fibers, or traversing the Fiber tree, ..., is only mounted after the
Frontend is created.

For browser extension, this means that we don't patch console or track
errors and warnings before Chrome DevTools is opened.

With these changes, `rendererInterface` is created right after
`renderer` is injected from React via global hook object (e. g.
`__REACT_DEVTOOLS_GLOBAL_HOOK__.inject(...)`.

Because of the current implementation, in case of multiple Reacts on the
page, all of them will patch the console independently. This will be
fixed in one of the next PRs, where I am moving console patching to the
global Hook.

This change of course makes `hook.js` script bigger, but I think it is a
reasonable trade-off for better DevX. We later can add more heuristics
to optimize the performance (if necessary) of `rendererInterface` for
cases when Frontend was connected late and Backend is attempting to
flush out too many recorded operations.

This essentially reverts https://github.com/facebook/react/pull/26563.
This commit is contained in:
Ruslan Lesiutin
2024-09-12 13:59:29 +01:00
committed by GitHub
parent d6cb4e7713
commit bb6b86ed59
10 changed files with 110 additions and 134 deletions
@@ -1,33 +0,0 @@
/**
* In order to support reload-and-profile functionality, the renderer needs to be injected before any other scripts.
* Since it is a complex file (with imports) we can't just toString() it like we do with the hook itself,
* So this entry point (one of the web_accessible_resources) provides a way to eagerly inject it.
* The hook will look for the presence of a global __REACT_DEVTOOLS_ATTACH__ and attach an injected renderer early.
* The normal case (not a reload-and-profile) will not make use of this entry point though.
*
* @flow
*/
import {attach} from 'react-devtools-shared/src/backend/fiber/renderer';
import {SESSION_STORAGE_RELOAD_AND_PROFILE_KEY} from 'react-devtools-shared/src/constants';
import {sessionStorageGetItem} from 'react-devtools-shared/src/storage';
if (
sessionStorageGetItem(SESSION_STORAGE_RELOAD_AND_PROFILE_KEY) === 'true' &&
!window.hasOwnProperty('__REACT_DEVTOOLS_ATTACH__')
) {
Object.defineProperty(
window,
'__REACT_DEVTOOLS_ATTACH__',
({
enumerable: false,
// This property needs to be configurable to allow third-party integrations
// to attach their own renderer. Note that using third-party integrations
// is not officially supported. Use at your own risk.
configurable: true,
get() {
return attach;
},
}: Object),
);
}