-
Notifications
You must be signed in to change notification settings - Fork 49.9k
[DevTools] browser extension: improve script injection logic #26492
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
Changes from 3 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,7 +5,7 @@ import {flushSync} from 'react-dom'; | |
| import {createRoot} from 'react-dom/client'; | ||
| import Bridge from 'react-devtools-shared/src/bridge'; | ||
| import Store from 'react-devtools-shared/src/devtools/store'; | ||
| import {getBrowserName, getBrowserTheme} from './utils'; | ||
| import {IS_CHROME, IS_EDGE, getBrowserTheme} from './utils'; | ||
| import {LOCAL_STORAGE_TRACE_UPDATES_ENABLED_KEY} from 'react-devtools-shared/src/constants'; | ||
| import {registerDevToolsEventLogger} from 'react-devtools-shared/src/registerDevToolsEventLogger'; | ||
| import { | ||
|
|
@@ -27,9 +27,6 @@ import {logEvent} from 'react-devtools-shared/src/Logger'; | |
| const LOCAL_STORAGE_SUPPORTS_PROFILING_KEY = | ||
| 'React::DevTools::supportsProfiling'; | ||
|
|
||
| const isChrome = getBrowserName() === 'Chrome'; | ||
| const isEdge = getBrowserName() === 'Edge'; | ||
|
|
||
| // rAF never fires on devtools_page (because it's in the background) | ||
| // https://bugs.chromium.org/p/chromium/issues/detail?id=1241986#c31 | ||
| // Since we render React elements here, we need to polyfill it with setTimeout | ||
|
|
@@ -176,10 +173,10 @@ function createPanelIfReactLoaded() { | |
|
|
||
| store = new Store(bridge, { | ||
| isProfiling, | ||
| supportsReloadAndProfile: isChrome || isEdge, | ||
| supportsReloadAndProfile: IS_CHROME || IS_EDGE, | ||
| supportsProfiling, | ||
| // At this time, the timeline can only parse Chrome performance profiles. | ||
| supportsTimeline: isChrome, | ||
| supportsTimeline: IS_CHROME, | ||
| supportsTraceUpdates: true, | ||
| }); | ||
| if (!isProfiling) { | ||
|
|
@@ -188,14 +185,26 @@ function createPanelIfReactLoaded() { | |
|
|
||
| // Initialize the backend only once the Store has been initialized. | ||
| // Otherwise the Store may miss important initial tree op codes. | ||
| chrome.devtools.inspectedWindow.eval( | ||
| `window.postMessage({ source: 'react-devtools-inject-backend' }, '*');`, | ||
| function (response, evalError) { | ||
| if (evalError) { | ||
| console.error(evalError); | ||
| } | ||
| }, | ||
| ); | ||
| if (IS_CHROME | IS_EDGE) { | ||
|
||
| chrome.runtime.sendMessage({ | ||
| source: 'react-devtools-main', | ||
| payload: { | ||
| type: 'react-devtools-inject-backend', | ||
| tabId, | ||
| }, | ||
| }); | ||
| } else { | ||
| // Firefox does not support executing script in MAIN wolrd from content script. | ||
mondaychen marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| // see prepareInjection.js | ||
| chrome.devtools.inspectedWindow.eval( | ||
| `window.postMessage({ source: 'react-devtools-inject-backend' }, '*');`, | ||
| function (response, evalError) { | ||
| if (evalError) { | ||
| console.error(evalError); | ||
| } | ||
| }, | ||
| ); | ||
| } | ||
|
|
||
| const viewAttributeSourceFunction = (id, path) => { | ||
| const rendererID = store.getRendererIDForElement(id); | ||
|
|
@@ -255,7 +264,7 @@ function createPanelIfReactLoaded() { | |
| // For some reason in Firefox, chrome.runtime.sendMessage() from a content script | ||
| // never reaches the chrome.runtime.onMessage event listener. | ||
| let fetchFileWithCaching = null; | ||
| if (isChrome) { | ||
| if (IS_CHROME) { | ||
| const fetchFromNetworkCache = (url, resolve, reject) => { | ||
| // Debug ID allows us to avoid re-logging (potentially long) URL strings below, | ||
| // while also still associating (potentially) interleaved logs with the original request. | ||
|
|
@@ -463,7 +472,7 @@ function createPanelIfReactLoaded() { | |
| let needsToSyncElementSelection = false; | ||
|
|
||
| chrome.devtools.panels.create( | ||
| isChrome || isEdge ? '⚛️ Components' : 'Components', | ||
| IS_CHROME || IS_EDGE ? '⚛️ Components' : 'Components', | ||
| '', | ||
| 'panel.html', | ||
| extensionPanel => { | ||
|
|
@@ -494,7 +503,7 @@ function createPanelIfReactLoaded() { | |
| ); | ||
|
|
||
| chrome.devtools.panels.create( | ||
| isChrome || isEdge ? '⚛️ Profiler' : 'Profiler', | ||
| IS_CHROME || IS_EDGE ? '⚛️ Profiler' : 'Profiler', | ||
| '', | ||
| 'panel.html', | ||
| extensionPanel => { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Should we put
react-devtools-inject-backendinto constant?I see its used in multiple places:
react/packages/react-devtools-extensions/src/main.js
Line 192 in 41b4714
react/packages/react-devtools-extensions/src/contentScripts/prepareInjection.js
Line 92 in 41b4714
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Many event names/types are used in this way. I'm not against extracting them into a shared constant file as a better engineering work, but let's use another PR to take care of them all together.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The big difference imo between using a constant and literals in that a constant will get allocated at the module level and would weight the sum of all the literals plus some small management extra.
Literals on the other hand are only allocated when used and referenced (they may even get GCed like in
case constant).