mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
refactor: refactored devtools browser extension scripts to improve port management and service worker lifetime (#27215)
Fixes https://github.com/facebook/react/issues/27119, https://github.com/facebook/react/issues/27185. Fixed: - React DevTools now works as expected when user performs in-tab navigation, previously it was just stuck. https://github.com/facebook/react/assets/28902667/b11c5f84-7155-47a5-8b5a-7e90baca5347 - When user closes browser DevTools panel, we now do some cleanup to disconnect ports and emit shutdown event for bridge. This should fix the issue with registering duplicated fibers with the same id in Store. Changed: - We reconnect proxy port once in 25 seconds, in order to [keep service worker alive](https://developer.chrome.com/docs/extensions/whatsnew/#m110-sw-idle). - Instead of unregistering dynamically injected content scripts, wen now get list of already registered scripts and filter them out from scripts that we want to inject again, see dynamicallyInjectContentScripts.js. - Split `main.js` and `background.js` into multiple files. Tested on Chromium and Firefox browsers.
This commit is contained in:
+39
-33
@@ -2,9 +2,23 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
let backendDisconnected: boolean = false;
|
||||
let port = null;
|
||||
let backendInitialized: boolean = false;
|
||||
|
||||
connectPort();
|
||||
sayHelloToBackendManager();
|
||||
|
||||
// The backend waits to install the global hook until notified by the content script.
|
||||
// In the event of a page reload, the content script might be loaded before the backend manager is injected.
|
||||
// Because of this we need to poll the backend manager until it has been initialized.
|
||||
const intervalID = setInterval(() => {
|
||||
if (backendInitialized) {
|
||||
clearInterval(intervalID);
|
||||
} else {
|
||||
sayHelloToBackendManager();
|
||||
}
|
||||
}, 500);
|
||||
|
||||
function sayHelloToBackendManager() {
|
||||
window.postMessage(
|
||||
{
|
||||
@@ -16,6 +30,18 @@ function sayHelloToBackendManager() {
|
||||
}
|
||||
|
||||
function handleMessageFromDevtools(message) {
|
||||
if (message.source === 'react-devtools-service-worker' && message.stop) {
|
||||
window.removeEventListener('message', handleMessageFromPage);
|
||||
|
||||
// Calling disconnect here should not emit onDisconnect event inside this script
|
||||
// This port will not attempt to reconnect again
|
||||
// It will connect only once this content script will be injected again
|
||||
port?.disconnect();
|
||||
port = null;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
window.postMessage(
|
||||
{
|
||||
source: 'react-devtools-content-script',
|
||||
@@ -33,6 +59,7 @@ function handleMessageFromPage(event) {
|
||||
|
||||
port.postMessage(event.data.payload);
|
||||
}
|
||||
|
||||
// This is a message from the backend manager
|
||||
if (event.data.source === 'react-devtools-backend-manager') {
|
||||
chrome.runtime.sendMessage({
|
||||
@@ -43,42 +70,21 @@ function handleMessageFromPage(event) {
|
||||
}
|
||||
|
||||
function handleDisconnect() {
|
||||
backendDisconnected = true;
|
||||
|
||||
window.removeEventListener('message', handleMessageFromPage);
|
||||
port = null;
|
||||
|
||||
window.postMessage(
|
||||
{
|
||||
source: 'react-devtools-content-script',
|
||||
payload: {
|
||||
type: 'event',
|
||||
event: 'shutdown',
|
||||
},
|
||||
},
|
||||
'*',
|
||||
);
|
||||
connectPort();
|
||||
}
|
||||
|
||||
// proxy from main page to devtools (via the background page)
|
||||
const port = chrome.runtime.connect({
|
||||
name: 'content-script',
|
||||
});
|
||||
port.onMessage.addListener(handleMessageFromDevtools);
|
||||
port.onDisconnect.addListener(handleDisconnect);
|
||||
// Creates port from application page to the React DevTools' service worker
|
||||
// Which then connects it with extension port
|
||||
function connectPort() {
|
||||
port = chrome.runtime.connect({
|
||||
name: 'proxy',
|
||||
});
|
||||
|
||||
window.addEventListener('message', handleMessageFromPage);
|
||||
window.addEventListener('message', handleMessageFromPage);
|
||||
|
||||
sayHelloToBackendManager();
|
||||
|
||||
// The backend waits to install the global hook until notified by the content script.
|
||||
// In the event of a page reload, the content script might be loaded before the backend manager is injected.
|
||||
// Because of this we need to poll the backend manager until it has been initialized.
|
||||
if (!backendInitialized) {
|
||||
const intervalID = setInterval(() => {
|
||||
if (backendInitialized || backendDisconnected) {
|
||||
clearInterval(intervalID);
|
||||
} else {
|
||||
sayHelloToBackendManager();
|
||||
}
|
||||
}, 500);
|
||||
port.onMessage.addListener(handleMessageFromDevtools);
|
||||
port.onDisconnect.addListener(handleDisconnect);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user