Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor[devtools/extension]: migrate from using setInterval for polling if react is loaded #27323

Merged
merged 1 commit into from
Sep 1, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 28 additions & 21 deletions packages/react-devtools-extensions/src/main/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,23 @@ import registerEventsLogger from './registerEventsLogger';
import getProfilingFlags from './getProfilingFlags';
import './requestAnimationFramePolyfill';

function executeIfReactHasLoaded(callback) {
// Try polling for at least 5 seconds, in case if it takes too long to load react
const REACT_POLLING_TICK_COOLDOWN = 250;
const REACT_POLLING_ATTEMPTS_THRESHOLD = 20;

let reactPollingTimeoutId = null;
function clearReactPollingTimeout() {
clearTimeout(reactPollingTimeoutId);
reactPollingTimeoutId = null;
}

function executeIfReactHasLoaded(callback, attempt = 1) {
reactPollingTimeoutId = null;

if (attempt > REACT_POLLING_ATTEMPTS_THRESHOLD) {
return;
}

chrome.devtools.inspectedWindow.eval(
'window.__REACT_DEVTOOLS_GLOBAL_HOOK__ && window.__REACT_DEVTOOLS_GLOBAL_HOOK__.renderers.size > 0',
(pageHasReact, exceptionInfo) => {
Expand All @@ -53,6 +69,13 @@ function executeIfReactHasLoaded(callback) {

if (pageHasReact) {
callback();
} else {
reactPollingTimeoutId = setTimeout(
executeIfReactHasLoaded,
REACT_POLLING_TICK_COOLDOWN,
callback,
attempt + 1,
);
}
},
);
Expand Down Expand Up @@ -413,7 +436,7 @@ function createProfilerPanel() {

function performInTabNavigationCleanup() {
// Potentially, if react hasn't loaded yet and user performs in-tab navigation
clearReactPollingInterval();
clearReactPollingTimeout();

if (store !== null) {
// Store profiling data, so it can be used later
Expand Down Expand Up @@ -453,7 +476,7 @@ function performInTabNavigationCleanup() {

function performFullCleanup() {
// Potentially, if react hasn't loaded yet and user closed the browser DevTools
clearReactPollingInterval();
clearReactPollingTimeout();

if ((componentsPortalContainer || profilerPortalContainer) && root) {
// This should also emit bridge.shutdown, but only if this root was mounted
Expand Down Expand Up @@ -504,23 +527,14 @@ function mountReactDevTools() {
// TODO: display some disclaimer if user performs in-tab navigation to non-react application
// when React DevTools panels are already opened, currently we will display just blank white block
function mountReactDevToolsWhenReactHasLoaded() {
const checkIfReactHasLoaded = () => executeIfReactHasLoaded(onReactReady);

// Check to see if React has loaded in case React is added after page load
reactPollingIntervalId = setInterval(() => {
checkIfReactHasLoaded();
}, 500);

function onReactReady() {
clearReactPollingInterval();
clearReactPollingTimeout();
mountReactDevTools();
}

checkIfReactHasLoaded();
executeIfReactHasLoaded(onReactReady);
}

let reactPollingIntervalId = null;

let bridge = null;
let store = null;

Expand All @@ -543,8 +557,6 @@ chrome.devtools.network.onNavigated.addListener(syncSavedPreferences);

// Cleanup previous page state and remount everything
chrome.devtools.network.onNavigated.addListener(() => {
clearReactPollingInterval();

performInTabNavigationCleanup();
mountReactDevToolsWhenReactHasLoaded();
});
Expand All @@ -557,10 +569,5 @@ if (IS_FIREFOX) {
window.addEventListener('beforeunload', performFullCleanup);
}

function clearReactPollingInterval() {
clearInterval(reactPollingIntervalId);
reactPollingIntervalId = null;
}

syncSavedPreferences();
mountReactDevToolsWhenReactHasLoaded();