22
setBrowserSelectionFromReact,
23
setReactSelectionFromBrowser,
24
} from './elementSelection';
25
+import {startReactPolling} from './reactPolling';
26
import cloneStyleTags from './cloneStyleTags';
27
import injectBackendManager from './injectBackendManager';
28
import syncSavedPreferences from './syncSavedPreferences';
31
import debounce from './debounce';
32
import './requestAnimationFramePolyfill';
33
33
-// Try polling for at least 5 seconds, in case if it takes too long to load react
34
-const REACT_POLLING_TICK_COOLDOWN = 250;
35
-const REACT_POLLING_ATTEMPTS_THRESHOLD = 20;
36
-
37
-let reactPollingTimeoutId = null;
38
-export function clearReactPollingTimeout() {
39
- clearTimeout(reactPollingTimeoutId);
40
- reactPollingTimeoutId = null;
41
-}
42
-
43
-export function executeIfReactHasLoaded(callback, attempt = 1) {
44
- clearReactPollingTimeout();
45
-
46
- if (attempt > REACT_POLLING_ATTEMPTS_THRESHOLD) {
47
- return;
48
- }
49
-
50
- chrome.devtools.inspectedWindow.eval(
51
- 'window.__REACT_DEVTOOLS_GLOBAL_HOOK__ && window.__REACT_DEVTOOLS_GLOBAL_HOOK__.renderers.size > 0',
52
- (pageHasReact, exceptionInfo) => {
53
- if (exceptionInfo) {
54
- const {code, description, isError, isException, value} = exceptionInfo;
55
-
56
- if (isException) {
57
- console.error(
58
- `Received error while checking if react has loaded: ${value}`,
59
- );
60
- return;
61
- }
62
-
63
- if (isError) {
64
- console.error(
65
- `Received error with code ${code} while checking if react has loaded: ${description}`,
66
- );
67
- return;
68
- }
69
- }
70
-
71
- if (pageHasReact) {
72
- callback();
73
- } else {
74
- reactPollingTimeoutId = setTimeout(
75
- executeIfReactHasLoaded,
76
- REACT_POLLING_TICK_COOLDOWN,
77
- callback,
78
- attempt + 1,
79
- );
80
- }
81
- },
82
- );
83
-}
84
-
85
-let lastSubscribedBridgeListener = null;
86
-
34
function createBridge() {
35
bridge = new Bridge({
36
listen(fn) {
317
function createComponentsPanel() {
318
if (componentsPortalContainer) {
319
// Panel is created and user opened it at least once
320
+ ensureInitialHTMLIsCleared(componentsPortalContainer);
321
render('components');
322
323
return;
337
338
createdPanel.onShown.addListener(portal => {
339
componentsPortalContainer = portal.container;
392
- if (componentsPortalContainer != null) {
340
+ if (componentsPortalContainer != null && render) {
341
ensureInitialHTMLIsCleared(componentsPortalContainer);
342
343
render('components');
356
function createProfilerPanel() {
357
if (profilerPortalContainer) {
358
// Panel is created and user opened it at least once
359
+ ensureInitialHTMLIsCleared(profilerPortalContainer);
360
render('profiler');
361
362
return;
376
377
createdPanel.onShown.addListener(portal => {
378
profilerPortalContainer = portal.container;
430
- if (profilerPortalContainer != null) {
379
+ if (profilerPortalContainer != null && render) {
380
ensureInitialHTMLIsCleared(profilerPortalContainer);
381
382
render('profiler');
391
392
function performInTabNavigationCleanup() {
393
// Potentially, if react hasn't loaded yet and user performs in-tab navigation
445
- clearReactPollingTimeout();
394
+ clearReactPollingInstance();
395
396
if (store !== null) {
397
// Store profiling data, so it can be used later
428
429
function performFullCleanup() {
430
// Potentially, if react hasn't loaded yet and user closed the browser DevTools
482
- clearReactPollingTimeout();
431
+ clearReactPollingInstance();
432
433
if ((componentsPortalContainer || profilerPortalContainer) && root) {
434
// This should also emit bridge.shutdown, but only if this root was mounted
480
}
481
482
function mountReactDevTools() {
483
+ reactPollingInstance = null;
484
+
485
registerEventsLogger();
486
487
createBridgeAndStore();
492
createProfilerPanel();
493
}
494
544
-// TODO: display some disclaimer if user performs in-tab navigation to non-react application
545
-// when React DevTools panels are already opened, currently we will display just blank white block
546
-function mountReactDevToolsWhenReactHasLoaded() {
547
- function onReactReady() {
548
- clearReactPollingTimeout();
549
- mountReactDevTools();
495
+let reactPollingInstance = null;
496
+function clearReactPollingInstance() {
497
+ reactPollingInstance?.abort();
498
+ reactPollingInstance = null;
499
+}
500
+
501
+function showNoReactDisclaimer() {
502
+ if (componentsPortalContainer) {
503
+ componentsPortalContainer.innerHTML =
504
+ '<h1 class="no-react-disclaimer">Looks like this page doesn\'t have React, or it hasn\'t been loaded yet.</h1>';
505
+ delete componentsPortalContainer._hasInitialHTMLBeenCleared;
506
+ }
507
+
508
+ if (profilerPortalContainer) {
509
+ profilerPortalContainer.innerHTML =
510
+ '<h1 class="no-react-disclaimer">Looks like this page doesn\'t have React, or it hasn\'t been loaded yet.</h1>';
511
+ delete profilerPortalContainer._hasInitialHTMLBeenCleared;
512
}
513
+}
514
552
- executeIfReactHasLoaded(onReactReady, 1);
515
+function mountReactDevToolsWhenReactHasLoaded() {
516
+ reactPollingInstance = startReactPolling(
517
+ mountReactDevTools,
518
+ 5, // ~5 seconds
519
+ showNoReactDisclaimer,
520
+ );
521
}
522
523
let bridge = null;
524
+let lastSubscribedBridgeListener = null;
525
let store = null;
526
527
let profilingData = null;