@@ -5,8 +5,9 @@ import {createRoot} from 'react-dom/client';
5
5
import {
6
6
activate as activateBackend ,
7
7
initialize as initializeBackend ,
8
+ attach ,
8
9
} from 'react-devtools-inline/backend' ;
9
- import { initialize as initializeFrontend } from 'react-devtools-inline/frontend' ;
10
+ import { initialize as initializeFrontend , createBridge , createStore } from 'react-devtools-inline/frontend' ;
10
11
import { initDevTools } from 'react-devtools-shared/src/devtools' ;
11
12
12
13
// This is a pretty gross hack to make the runtime loaded named-hooks-code work.
@@ -16,20 +17,7 @@ __webpack_public_path__ = '/dist/'; // eslint-disable-line no-undef
16
17
17
18
const iframe = ( ( document . getElementById ( 'target' ) : any ) : HTMLIFrameElement ) ;
18
19
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 ) ;
20
+ let { contentDocument, contentWindow} = iframe ;
33
21
34
22
const container = ( ( document . getElementById ( 'devtools' ) : any ) : HTMLElement ) ;
35
23
@@ -59,27 +47,83 @@ function hookNamesModuleLoaderFunction() {
59
47
return import ( 'react-devtools-inline/hookNames' ) ;
60
48
}
61
49
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
- } ,
50
+ let store
51
+ let profilingData
52
+ let controller = new AbortController ( ) ;
53
+ const LOCAL_STORAGE_SUPPORTS_PROFILING_KEY = 'React::DevTools::supportsProfiling'
54
+ function render ( signal : AbortSignal ) {
55
+ ( { contentDocument, contentWindow} = iframe ) ;
56
+
57
+ const bridge = createBridge ( contentWindow )
58
+ bridge . addListener ( 'reloadAppForProfiling' , ( ) => {
59
+ localStorage . setItem ( LOCAL_STORAGE_SUPPORTS_PROFILING_KEY , 'true' )
60
+ contentWindow . sessionStorage . setItem ( 'React::DevTools::reloadAndProfile' , 'true' )
61
+ contentWindow . sessionStorage . setItem ( 'React::DevTools::recordChangeDescriptions' , 'true' )
62
+ contentWindow . location . reload ( ) ;
63
+ iframe . addEventListener ( 'load' , ( ) => {
64
+ contentWindow . __REACT_DEVTOOLS_ATTACH__ = attach ;
65
+ controller . abort ( ) ;
66
+ controller = new AbortController ( ) ;
67
+ render ( controller . signal ) ;
68
+ } , { once : true } ) ;
69
+ } )
70
+ let isProfiling = false
71
+ // reload and profile
72
+ {
73
+ if ( localStorage . getItem ( LOCAL_STORAGE_SUPPORTS_PROFILING_KEY ) === "true" ) {
74
+ isProfiling = true
75
+ if ( store ) profilingData = store . profilerStore . profilingData
76
+ localStorage . removeItem ( LOCAL_STORAGE_SUPPORTS_PROFILING_KEY )
77
+ }
78
+ }
79
+ store = createStore ( bridge , {
80
+ isProfiling,
81
+ supportsReloadAndProfile : true ,
82
+ supportsProfiling : true ,
83
+ supportsTimeline : true ,
84
+ supportsTraceUpdates : true ,
85
+ supportsNativeInspection : true ,
86
+ } )
87
+ if ( ! isProfiling && profilingData ) store . profilerStore . profilingData = profilingData
88
+
89
+ // Helps with positioning Overlay UI.
90
+ contentWindow . __REACT_DEVTOOLS_TARGET_WINDOW__ = window ;
91
+
92
+ initializeBackend ( contentWindow ) ;
93
+
94
+ // Initialize the front end and activate the backend early so that we are able
95
+ // to pass console settings in local storage to the backend before initial render
96
+ const DevTools = initializeFrontend ( contentWindow , { bridge, store} ) ;
97
+
98
+ // Activate the backend only once the DevTools frontend Store has been initialized.
99
+ // Otherwise the Store may miss important initial tree op codes.
100
+ activateBackend ( contentWindow ) ;
101
+
102
+ inject ( 'dist/app-index.js' , ( ) => {
103
+ initDevTools ( {
104
+ connect ( cb ) {
105
+ const root = createRoot ( container ) ;
106
+ root . render (
107
+ createElement ( DevTools , {
108
+ browserTheme : 'light' ,
109
+ enabledInspectedElementContextMenu : true ,
110
+ hookNamesModuleLoaderFunction,
111
+ showTabBar : true ,
112
+ warnIfLegacyBackendDetected : true ,
113
+ warnIfUnsupportedVersionDetected : true ,
114
+ } ) ,
115
+ ) ;
116
+ signal . addEventListener ( 'abort' , ( ) => root . unmount ( ) , { once : true } )
117
+ } ,
118
+
119
+ onReload ( reloadFn ) {
120
+ iframe . onload = reloadFn ;
121
+ } ,
122
+ } ) ;
81
123
} ) ;
82
- } ) ;
124
+
125
+ }
126
+ render ( controller . signal ) ;
83
127
84
128
function inject ( sourcePath : string , callback : ( ) = > void ) {
85
129
const script = contentDocument . createElement ( 'script' ) ;
0 commit comments