main
js 90 lines 2.8 KB
Raw
1 /** @flow */
2
3 import {createElement} from 'react';
4 import {createRoot} from 'react-dom/client';
5 import {
6 activate as activateBackend,
7 initialize as initializeBackend,
8 } from 'react-devtools-inline/backend';
9 import {initialize as initializeFrontend} from 'react-devtools-inline/frontend';
10 import {initDevTools} from 'react-devtools-shared/src/devtools';
11
12 // This is a pretty gross hack to make the runtime loaded named-hooks-code work.
13 // TODO (Webpack 5) Hoepfully we can remove this once we upgrade to Webpack 5.
14 // $FlowFixMe[cannot-resolve-name]
15 __webpack_public_path__ = '/dist/'; // eslint-disable-line no-undef
16
17 const iframe = document.getElementById('target') as any as HTMLIFrameElement;
18
19 const {contentDocument, contentWindow} = iframe;
20
21 // Helps with positioning Overlay UI.
22 contentWindow.__REACT_DEVTOOLS_TARGET_WINDOW__ = window;
23
24 initializeBackend(contentWindow);
25
26 // Initialize the front end and activate the backend early so that we are able
27 // to pass console settings in local storage to the backend before initial render
28 const DevTools = initializeFrontend(contentWindow);
29
30 // Activate the backend only once the DevTools frontend Store has been initialized.
31 // Otherwise the Store may miss important initial tree op codes.
32 activateBackend(contentWindow);
33
34 const container = document.getElementById('devtools') as any as HTMLElement;
35
36 let isTestAppMounted = true;
37
38 const mountButton = document.getElementById(
39 'mountButton',
40 ) as any as HTMLButtonElement;
41 mountButton.addEventListener('click', function () {
42 if (isTestAppMounted) {
43 if (typeof window.unmountTestApp === 'function') {
44 window.unmountTestApp();
45 mountButton.innerText = 'Mount test app';
46 isTestAppMounted = false;
47 }
48 } else {
49 if (typeof window.mountTestApp === 'function') {
50 window.mountTestApp();
51 mountButton.innerText = 'Unmount test app';
52 isTestAppMounted = true;
53 }
54 }
55 });
56
57 // TODO (Webpack 5) Hopefully we can remove this prop after the Webpack 5 migration.
58 function hookNamesModuleLoaderFunction() {
59 return import('react-devtools-inline/hookNames');
60 }
61
62 inject('dist/app-index.js', () => {
63 initDevTools({
64 connect(cb) {
65 const root = createRoot(container);
66 root.render(
67 createElement(DevTools, {
68 browserTheme: 'light',
69 enabledInspectedElementContextMenu: true,
70 hookNamesModuleLoaderFunction,
71 showTabBar: true,
72 warnIfLegacyBackendDetected: true,
73 warnIfUnsupportedVersionDetected: true,
74 }),
75 );
76 },
77
78 onReload(reloadFn) {
79 iframe.onload = reloadFn;
80 },
81 });
82 });
83
84 function inject(sourcePath: string, callback: () => void) {
85 const script = contentDocument.createElement('script');
86 script.onload = callback;
87 script.src = sourcePath;
88
89 (contentDocument.body as any as HTMLBodyElement).appendChild(script);
90 }